GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
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 * 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 */
28struct dist {
29 int id; /* branch id */
30 RectReal distance; /* distance to node center */
31};
32
33/* Initialize one branch cell in an internal node. */
34static 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. */
42static 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. */
50static 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
57static 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 */
62void 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. */
74struct 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++) {
88 n->branch[i].rect.boundary = RTreeAllocBoundary(t);
89 RTreeInitBranch[NODETYPE(level, t->fd)](&(n->branch[i]), t);
90 }
91
92 return n;
93}
94
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 */
109void 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 */
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 */
135void 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 */
176static 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);
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;
209 }
210 else if (overlap == bestoverlap) {
211 /* resolve ties */
212 if (increase < bestIncr) {
213 best = i;
214 bestArea = area;
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 */
235int 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;
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;
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. */
269void 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 */
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 */
317static 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 */
329static 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 */
344static 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 */
399static 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 */
435static 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);
441 p->b.rect.boundary = RTreeAllocBoundary(t);
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 */
450static 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 */
467static 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;
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 */
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 */
602void RTreeTabIn(int depth)
603{
604 int i;
605
606 for (i = 0; i < depth; i++)
607 putchar('\t');
608}
609
610static 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. */
617void 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
void RTreeDestroyNode(struct RTree_Node *n, int nodes)
Definition node.c:290
void RTreeTabIn(int depth)
Definition node.c:602
struct RTree_Node * RTreeAllocNode(struct RTree *t, int level)
Definition node.c:74
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
void RTreeFreeBoundary(struct RTree_Rect *r)
Delete the boundary of a rectangle.
Definition rect.c:98
RectReal * RTreeAllocBoundary(struct RTree *t)
Allocate the boundary array of a rectangle for a given tree.
Definition rect.c:81
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_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
Definition rtree.h:123