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