GRASS 8 Programmer's Manual 8.6.0dev(2026)-8843f13794
Loading...
Searching...
No Matches
node.c
Go to the documentation of this file.
1/****************************************************************************
2 * MODULE: R-Tree library
3 *
4 * AUTHOR(S): Antonin Guttman - original code
5 * Daniel Green (green@superliminal.com) - major clean-up
6 * and implementation of bounding spheres
7 * Markus Metz - file-based and memory-based R*-tree
8 *
9 * PURPOSE: Multidimensional index
10 *
11 * SPDX-FileCopyrightText: 2010 GRASS Development Team
12 * SPDX-License-Identifier: GPL-2.0-or-later
13 *****************************************************************************/
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <assert.h>
19#include <grass/gis.h>
20#include "index.h"
21#include "split.h"
22#include "card.h"
23
24/* rectangle distances for forced removal */
25struct dist {
26 int id; /* branch id */
27 RectReal distance; /* distance to node center */
28};
29
30/* Initialize one branch cell in an internal node. */
31static void RTreeInitNodeBranchM(struct RTree_Branch *b, struct RTree *t)
32{
33 RTreeInitRect(&(b->rect), t);
34 memset(&(b->child), 0, sizeof(union RTree_Child));
35 b->child.ptr = NULL;
36}
37
38/* Initialize one branch cell in an internal node. */
39static void RTreeInitNodeBranchF(struct RTree_Branch *b, struct RTree *t)
40{
41 RTreeInitRect(&(b->rect), t);
42 memset(&(b->child), 0, sizeof(union RTree_Child));
43 b->child.pos = -1;
44}
45
46/* Initialize one branch cell in a leaf node. */
47static void RTreeInitLeafBranch(struct RTree_Branch *b, struct RTree *t)
48{
49 RTreeInitRect(&(b->rect), t);
50 memset(&(b->child), 0, sizeof(union RTree_Child));
51 b->child.id = 0;
52}
53
54static void (*RTreeInitBranch[3])(struct RTree_Branch *b, struct RTree *t) = {
55 RTreeInitLeafBranch, RTreeInitNodeBranchM, RTreeInitNodeBranchF};
56
57/* Initialize a Node structure. */
58/* type = 1: leaf, type = 2: internal, memory, type = 3: internal, file */
59void RTreeInitNode(struct RTree *t, struct RTree_Node *n, int type)
60{
61 int i;
62
63 n->count = 0;
64 n->level = -1;
65
66 for (i = 0; i < MAXCARD; i++)
67 RTreeInitBranch[type](&(n->branch[i]), t);
68}
69
70/* Make a new node and initialize to have all branch cells empty. */
71struct RTree_Node *RTreeAllocNode(struct RTree *t, int level)
72{
73 int i;
74 struct RTree_Node *n;
75
76 n = (struct RTree_Node *)malloc(sizeof(struct RTree_Node));
77 assert(n);
78
79 n->count = 0;
80 n->level = level;
81
82 n->branch = malloc(MAXCARD * sizeof(struct RTree_Branch));
83
84 for (i = 0; i < MAXCARD; i++) {
85 n->branch[i].rect.boundary = RTreeAllocBoundary(t);
86 RTreeInitBranch[NODETYPE(level, t->fd)](&(n->branch[i]), t);
87 }
88
89 return n;
90}
91
93{
94 int i;
95
96 assert(n);
97
98 for (i = 0; i < MAXCARD; i++)
99 RTreeFreeBoundary(&(n->branch[i].rect));
100
101 free(n->branch);
102 free(n);
103}
104
105/* copy node 2 to node 1 */
106void RTreeCopyNode(struct RTree_Node *n1, struct RTree_Node *n2,
107 struct RTree *t)
108{
109 int i;
110
111 assert(n1 && n2);
112
113 n1->count = n2->count;
114 n1->level = n2->level;
115 for (i = 0; i < MAXCARD; i++) {
116 RTreeCopyBranch(&(n1->branch[i]), &(n2->branch[i]), t);
117 }
118}
119
120/* copy branch 2 to branch 1 */
122 struct RTree *t)
123{
124 b1->child = b2->child;
125 RTreeCopyRect(&(b1->rect), &(b2->rect), t);
126}
127
128/*
129 * Find the smallest rectangle that includes all rectangles in
130 * branches of a node.
131 */
132void RTreeNodeCover(struct RTree_Node *n, struct RTree_Rect *r, struct RTree *t)
133{
134 int i, first_time = 1;
135
136 if ((n)->level > 0) { /* internal node */
137 for (i = 0; i < t->nodecard; i++) {
138 if (t->valid_child(&(n->branch[i].child))) {
139 if (first_time) {
140 RTreeCopyRect(r, &(n->branch[i].rect), t);
141 first_time = 0;
142 }
143 else
144 RTreeExpandRect(r, &(n->branch[i].rect), t);
145 }
146 }
147 }
148 else { /* leaf */
149 for (i = 0; i < t->leafcard; i++) {
150 if (n->branch[i].child.id) {
151 if (first_time) {
152 RTreeCopyRect(r, &(n->branch[i].rect), t);
153 first_time = 0;
154 }
155 else
156 RTreeExpandRect(r, &(n->branch[i].rect), t);
157 }
158 }
159 }
160}
161
162/*
163 * Idea from R*-tree, modified: not overlap size but overlap number
164 *
165 * Pick a branch from leaf nodes (current node has level 1). Pick the
166 * one that will result in the smallest number of overlapping siblings.
167 * This will result in the least ambiguous node covering the new
168 * rectangle, improving search speed.
169 * In case of a tie, pick the one which needs the smallest increase in
170 * area to accommodate the new rectangle, then the smallest area before,
171 * to get the best resolution when searching.
172 */
173static int RTreePickLeafBranch(struct RTree_Rect *r, struct RTree_Node *n,
174 struct RTree *t)
175{
176 struct RTree_Rect *rr;
177 int i, j;
178 RectReal increase, bestIncr = -1, area, bestArea = 0;
179 int best = 0, bestoverlap;
180 int overlap;
181
182 bestoverlap = t->nodecard + 1;
183
184 /* get the branch that will overlap with the smallest number of
185 * sibling branches when including the new rectangle */
186 for (i = 0; i < t->nodecard; i++) {
187 if (t->valid_child(&(n->branch[i].child))) {
188 rr = &n->branch[i].rect;
189 RTreeCombineRect(r, rr, &(t->orect), t);
191 increase = RTreeRectSphericalVolume(&(t->orect), t) - area;
192
193 overlap = 0;
194 for (j = 0; j < t->leafcard; j++) {
195 if (j != i) {
196 rr = &n->branch[j].rect;
197 overlap += RTreeOverlap(&(t->orect), rr, t);
198 }
199 }
200
201 if (overlap < bestoverlap) {
202 best = i;
203 bestoverlap = overlap;
204 bestArea = area;
206 }
207 else if (overlap == bestoverlap) {
208 /* resolve ties */
209 if (increase < bestIncr) {
210 best = i;
211 bestArea = area;
213 }
214 else if (increase == bestIncr && area < bestArea) {
215 best = i;
216 bestArea = area;
217 }
218 }
219 }
220 }
221
222 return best;
223}
224
225/*
226 * Pick a branch. Pick the one that will need the smallest increase
227 * in area to accommodate the new rectangle. This will result in the
228 * least total area for the covering rectangles in the current node.
229 * In case of a tie, pick the one which was smaller before, to get
230 * the best resolution when searching.
231 */
232int RTreePickBranch(struct RTree_Rect *r, struct RTree_Node *n, struct RTree *t)
233{
234 struct RTree_Rect *rr;
235 int i, first_time = 1;
236 RectReal increase, bestIncr = (RectReal)-1, area, bestArea = 0;
237 int best = 0;
238
239 assert((n)->level > 0); /* must not be called on leaf node */
240
241 if ((n)->level == 1)
242 return RTreePickLeafBranch(r, n, t);
243
244 for (i = 0; i < t->nodecard; i++) {
245 if (t->valid_child(&(n->branch[i].child))) {
246 rr = &n->branch[i].rect;
248 RTreeCombineRect(r, rr, &(t->orect), t);
249 increase = RTreeRectSphericalVolume(&(t->orect), t) - area;
250 if (increase < bestIncr || first_time) {
251 best = i;
252 bestArea = area;
254 first_time = 0;
255 }
256 else if (increase == bestIncr && area < bestArea) {
257 best = i;
258 bestArea = area;
259 }
260 }
261 }
262 return best;
263}
264
265/* Disconnect a dependent node. */
266void RTreeDisconnectBranch(struct RTree_Node *n, int i, struct RTree *t)
267{
268 if ((n)->level > 0) {
269 assert(n && i >= 0 && i < t->nodecard);
270 assert(t->valid_child(&(n->branch[i].child)));
271 if (t->fd < 0)
272 RTreeInitNodeBranchM(&(n->branch[i]), t);
273 else
274 RTreeInitNodeBranchF(&(n->branch[i]), t);
275 }
276 else {
277 assert(n && i >= 0 && i < t->leafcard);
278 assert(n->branch[i].child.id);
279 RTreeInitLeafBranch(&(n->branch[i]), t);
280 }
281
282 n->count--;
283}
284
285/* Destroy (free) node recursively. */
286/* NOTE: only needed for memory based index */
288{
289 int i;
290
291 if (n->level > 0) { /* it is not leaf -> destroy children */
292 for (i = 0; i < nodes; i++) {
293 if (n->branch[i].child.ptr) {
294 RTreeDestroyNode(n->branch[i].child.ptr, nodes);
295 }
296 }
297 }
298
299 /* Free this node */
300 RTreeFreeNode(n);
301
302 return;
303}
304
305/****************************************************************
306 * *
307 * R*-tree: force remove FORCECARD branches for reinsertion *
308 * *
309 ****************************************************************/
310
311/*
312 * swap dist structs
313 */
314static void RTreeSwapDist(struct dist *a, struct dist *b)
315{
316 struct dist c;
317
318 c = *a;
319 *a = *b;
320 *b = c;
321}
322
323/*
324 * check if dist is sorted ascending to distance
325 */
326static int RTreeDistIsSorted(struct dist *d, int first, int last)
327{
328 int i;
329
330 for (i = first; i < last; i++) {
331 if (d[i].distance > d[i + 1].distance)
332 return 0;
333 }
334
335 return 1;
336}
337
338/*
339 * partition dist for quicksort on distance
340 */
341static int RTreePartitionDist(struct dist *d, int first, int last)
342{
343 int pivot, mid = ((first + last) >> 1);
344 int larger, smaller;
345
346 if (last - first == 1) { /* only two items in list */
347 if (d[first].distance > d[last].distance) {
348 RTreeSwapDist(&(d[first]), &(d[last]));
349 }
350 return last;
351 }
352
353 /* Larger of two */
354 larger = pivot = mid;
355 smaller = first;
356 if (d[first].distance > d[mid].distance) {
357 larger = pivot = first;
358 smaller = mid;
359 }
360
361 if (d[larger].distance > d[last].distance) {
362 /* larger is largest, get the larger of smaller and last */
363 pivot = last;
364 if (d[smaller].distance > d[last].distance) {
365 pivot = smaller;
366 }
367 }
368
369 if (pivot != last) {
370 RTreeSwapDist(&(d[pivot]), &(d[last]));
371 }
372
373 pivot = first;
374
375 while (first < last) {
376 if (d[first].distance <= d[last].distance) {
377 if (pivot != first) {
378 RTreeSwapDist(&(d[pivot]), &(d[first]));
379 }
380 pivot++;
381 }
382 ++first;
383 }
384
385 if (pivot != last) {
386 RTreeSwapDist(&(d[pivot]), &(d[last]));
387 }
388
389 return pivot;
390}
391
392/*
393 * quicksort dist struct ascending by distance
394 * n is last valid index
395 */
396static void RTreeQuicksortDist(struct dist *d, int n)
397{
398 int pivot, first, last;
399 int s_first[MAXCARD + 1], s_last[MAXCARD + 1], stacksize;
400
401 s_first[0] = 0;
402 s_last[0] = n;
403
404 stacksize = 1;
405
406 /* use stack */
407 while (stacksize) {
408 stacksize--;
409 first = s_first[stacksize];
410 last = s_last[stacksize];
411 if (first < last) {
412 if (!RTreeDistIsSorted(d, first, last)) {
413
414 pivot = RTreePartitionDist(d, first, last);
415
416 s_first[stacksize] = first;
417 s_last[stacksize] = pivot - 1;
418 stacksize++;
419
420 s_first[stacksize] = pivot + 1;
421 s_last[stacksize] = last;
422 stacksize++;
423 }
424 }
425 }
426}
427
428/*
429 * Allocate space for a branch in the list used in InsertRect to
430 * store branches of nodes that are too full.
431 */
432static struct RTree_ListBranch *RTreeNewListBranch(struct RTree *t)
433{
434 struct RTree_ListBranch *p =
435 (struct RTree_ListBranch *)malloc(sizeof(struct RTree_ListBranch));
436
437 assert(p);
438 p->b.rect.boundary = RTreeAllocBoundary(t);
439
440 return p;
441}
442
443/*
444 * Add a branch to the reinsertion list. It will later
445 * be reinserted into the index structure.
446 */
447static void RTreeReInsertBranch(struct RTree_Branch b, int level,
448 struct RTree_ListBranch **ee, struct RTree *t)
449{
450 register struct RTree_ListBranch *l;
451
452 l = RTreeNewListBranch(t);
453 RTreeCopyBranch(&(l->b), &b, t);
454 l->level = level;
455 l->next = *ee;
456 *ee = l;
457}
458
459/*
460 * Remove branches from a node. Select the 2 branches whose rectangle
461 * center is farthest away from node cover center.
462 * Old node updated.
463 */
464static void RTreeRemoveBranches(struct RTree_Node *n, struct RTree_Branch *b,
465 struct RTree_ListBranch **ee,
466 struct RTree_Rect *cover, struct RTree *t)
467{
468 int i, j, maxkids, type;
470 struct dist rdist[MAXCARD + 1];
471
472 struct RTree_Rect *new_cover = &(t->orect);
473 RectReal *center_n = t->center_n;
474
475 assert(cover);
476
477 maxkids = MAXKIDS((n)->level, t);
478 type = NODETYPE((n)->level, t->fd);
479
480 assert(n->count == maxkids); /* must be full */
481
482 RTreeCombineRect(cover, &(b->rect), new_cover, t);
483
484 /* center coords of node cover */
485 for (j = 0; j < t->ndims; j++) {
486 center_n[j] =
487 (new_cover->boundary[j + t->ndims_alloc] + new_cover->boundary[j]) /
488 2;
489 }
490
491 /* compute distances of child rectangle centers to node cover center */
492 for (i = 0; i < maxkids; i++) {
493 RTreeCopyBranch(&(t->BranchBuf[i]), &(n->branch[i]), t);
494 rdist[i].distance = 0;
495 rdist[i].id = i;
496 for (j = 0; j < t->ndims; j++) {
497 center_r = (t->BranchBuf[i].rect.boundary[j + t->ndims_alloc] +
498 t->BranchBuf[i].rect.boundary[j]) /
499 2;
500 delta = center_n[j] - center_r;
501 rdist[i].distance += delta * delta;
502 }
503
504 RTreeInitBranch[type](&(n->branch[i]), t);
505 }
506
507 /* new branch */
508 RTreeCopyBranch(&(t->BranchBuf[maxkids]), b, t);
509 rdist[maxkids].distance = 0;
510 for (j = 0; j < t->ndims; j++) {
511 center_r =
512 (b->rect.boundary[j + t->ndims_alloc] + b->rect.boundary[j]) / 2;
513 delta = center_n[j] - center_r;
514 rdist[maxkids].distance += delta * delta;
515 }
516 rdist[maxkids].id = maxkids;
517
518 /* quicksort dist */
519 RTreeQuicksortDist(rdist, maxkids);
520
521 /* put largest three in branch list, farthest from center first */
522 for (i = 0; i < FORCECARD; i++) {
523 RTreeReInsertBranch(t->BranchBuf[rdist[maxkids - i].id], n->level, ee,
524 t);
525 }
526 /* put remaining in node, closest to center first */
527 for (i = 0; i < maxkids - FORCECARD + 1; i++) {
528 RTreeCopyBranch(&(n->branch[i]), &(t->BranchBuf[rdist[i].id]), t);
529 }
530 n->count = maxkids - FORCECARD + 1;
531}
532
533/*
534 * Add a branch to a node. Split the node if necessary.
535 * Returns 0 if node not split. Old node updated.
536 * Returns 1 if node split, sets *new_node to address of new node.
537 * Old node updated, becomes one of two.
538 * Returns 2 if branches were removed for forced reinsertion
539 */
541 struct RTree_Node **newnode, struct RTree_ListBranch **ee,
542 struct RTree_Rect *cover, char *overflow, struct RTree *t)
543{
544 int i, maxkids;
545
546 maxkids = MAXKIDS((n)->level, t);
547
548 if (n->count < maxkids) { /* split won't be necessary */
549 if ((n)->level > 0) { /* internal node */
550 for (i = 0; i < maxkids; i++) { /* find empty branch */
551 if (!t->valid_child(&(n->branch[i].child))) {
552 /* copy branch */
553 n->branch[i].child = b->child;
554 RTreeCopyRect(&(n->branch[i].rect), &(b->rect), t);
555 n->count++;
556 break;
557 }
558 }
559 return 0;
560 }
561 else if ((n)->level == 0) { /* leaf */
562 for (i = 0; i < maxkids; i++) { /* find empty branch */
563 if (n->branch[i].child.id == 0) {
564 /* copy branch */
565 n->branch[i].child = b->child;
566 RTreeCopyRect(&(n->branch[i].rect), &(b->rect), t);
567 n->count++;
568 break;
569 }
570 }
571 return 0;
572 }
573 }
574 else {
575 if (n->level < t->rootlevel && overflow[n->level]) {
576 /* R*-tree forced reinsert */
577 RTreeRemoveBranches(n, b, ee, cover, t);
578 overflow[n->level] = 0;
579 return 2;
580 }
581 else {
582 if (t->fd > -1)
583 RTreeInitNode(t, *newnode, NODETYPE(n->level, t->fd));
584 else
585 *newnode = RTreeAllocNode(t, (n)->level);
586 RTreeSplitNode(n, b, *newnode, t);
587 return 1;
588 }
589 }
590
591 /* should not be reached */
592 assert(0);
593 return -1;
594}
595
596/*
597 * for debugging only: print items to stdout
598 */
599void RTreeTabIn(int depth)
600{
601 int i;
602
603 for (i = 0; i < depth; i++)
604 putchar('\t');
605}
606
607static void RTreePrintBranch(struct RTree_Branch *b, int depth, struct RTree *t)
608{
609 RTreePrintRect(&(b->rect), depth, t);
610 RTreePrintNode(b->child.ptr, depth, t);
611}
612
613/* Print out the data in a node. */
614void RTreePrintNode(struct RTree_Node *n, int depth, struct RTree *t)
615{
616 int i, maxkids;
617
618 RTreeTabIn(depth);
619
620 maxkids = (n->level > 0 ? t->nodecard : t->leafcard);
621
622 fprintf(stdout, "node");
623 if (n->level == 0)
624 fprintf(stdout, " LEAF");
625 else if (n->level > 0)
626 fprintf(stdout, " NONLEAF");
627 else
628 fprintf(stdout, " TYPE=?");
629 fprintf(stdout, " level=%d count=%d", n->level, n->count);
630
631 for (i = 0; i < maxkids; i++) {
632 if (n->level == 0) {
633 RTreeTabIn(depth);
634 RTreePrintRect(&(n->branch[i].rect), depth, t);
635 fprintf(stdout, "\t%d: data id = %d\n", i, n->branch[i].child.id);
636 }
637 else {
638 RTreeTabIn(depth);
639 fprintf(stdout, "branch %d\n", i);
640 RTreePrintBranch(&(n->branch[i]), depth + 1, t);
641 }
642 }
643}
#define MAXKIDS(level, t)
Definition card.h:24
#define NULL
Definition ccmath.h:32
RectReal RTreeRectSphericalVolume(struct RTree_Rect *, struct RTree *)
Definition rect.c:429
#define NODETYPE(l, fd)
Definition index.h:28
void RTreeSplitNode(struct RTree_Node *, struct RTree_Branch *, struct RTree_Node *, struct RTree *)
Definition split.c:610
void RTreeCombineRect(struct RTree_Rect *, struct RTree_Rect *, struct RTree_Rect *, struct RTree *)
Definition rect.c:497
int RTreeExpandRect(struct RTree_Rect *, struct RTree_Rect *, struct RTree *)
Definition rect.c:533
void RTreeInitRect(struct RTree_Rect *, struct RTree *)
Initialize a rectangle to have all 0 coordinates.
Definition rect.c:106
#define RTreeCopyRect(r1, r2, t)
Definition index.h:97
#define FORCECARD
Definition index.h:26
#define assert(condition)
Definition lz4.c:291
void RTreePrintNode(struct RTree_Node *n, int depth, struct RTree *t)
Definition node.c:614
void RTreeCopyNode(struct RTree_Node *n1, struct RTree_Node *n2, struct RTree *t)
Definition node.c:106
void RTreeCopyBranch(struct RTree_Branch *b1, struct RTree_Branch *b2, struct RTree *t)
Definition node.c:121
void RTreeFreeNode(struct RTree_Node *n)
Definition node.c:92
void RTreeDisconnectBranch(struct RTree_Node *n, int i, struct RTree *t)
Definition node.c:266
void RTreeNodeCover(struct RTree_Node *n, struct RTree_Rect *r, struct RTree *t)
Definition node.c:132
void RTreeDestroyNode(struct RTree_Node *n, int nodes)
Definition node.c:287
void RTreeTabIn(int depth)
Definition node.c:599
struct RTree_Node * RTreeAllocNode(struct RTree *t, int level)
Definition node.c:71
int RTreeAddBranch(struct RTree_Branch *b, struct RTree_Node *n, struct RTree_Node **newnode, struct RTree_ListBranch **ee, struct RTree_Rect *cover, char *overflow, struct RTree *t)
Definition node.c:540
int RTreePickBranch(struct RTree_Rect *r, struct RTree_Node *n, struct RTree *t)
Definition node.c:232
void RTreeInitNode(struct RTree *t, struct RTree_Node *n, int type)
Definition node.c:59
double b
Definition r_raster.c:37
double l
Definition r_raster.c:37
double t
Definition r_raster.c:37
double r
Definition r_raster.c:37
void RTreeFreeBoundary(struct RTree_Rect *r)
Delete the boundary of a rectangle.
Definition rect.c:95
RectReal * RTreeAllocBoundary(struct RTree *t)
Allocate the boundary array of a rectangle for a given tree.
Definition rect.c:78
int RTreeOverlap(struct RTree_Rect *r, struct RTree_Rect *s, struct RTree *t)
Definition rect.c:587
void RTreePrintRect(struct RTree_Rect *R, int depth, struct RTree *t)
Definition rect.c:301
#define MAXCARD
Definition rtree.h:41
double RectReal
Definition rtree.h:23
void * malloc(unsigned)
void free(void *)
struct RTree_Branch b
Definition index.h:42
int count
Definition rtree.h:71
int level
Definition rtree.h:72
struct RTree_Branch * branch
Definition rtree.h:73
Definition rtree.h:120