GRASS 8 Programmer's Manual 8.6.0dev(2026)-c83afef6d3
Loading...
Searching...
No Matches
indexm.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 <stdlib.h>
16#include <assert.h>
17#include <grass/gis.h>
18#include "index.h"
19
21{
22 return (child->ptr != NULL);
23}
24
25/*
26 * Search in an index tree for all data rectangles that
27 * overlap the argument rectangle.
28 * Return the number of qualifying data rects.
29 */
31 void *cbarg)
32{
33 struct RTree_Node *n;
34 int hitCount = 0, notfound;
35 int i;
36 int top = 0;
37 struct nstack *s = t->ns;
38
39 /* stack size of t->rootlevel + 1 is enough because of depth first search */
40 /* only one node per level on stack at any given time */
41
42 /* add root node position to stack */
43 s[top].sn = t->root;
44 s[top].branch_id = i = 0;
45 n = s[top].sn;
46
47 while (top >= 0) {
48 n = s[top].sn;
49 if (s[top].sn->level > 0) { /* this is an internal node in the tree */
50 notfound = 1;
51 for (i = s[top].branch_id; i < t->nodecard; i++) {
52 if (s[top].sn->branch[i].child.ptr &&
53 RTreeOverlap(r, &(s[top].sn->branch[i].rect), t)) {
54 s[top++].branch_id = i + 1;
55 /* add next node to stack */
56 s[top].sn = n->branch[i].child.ptr;
57 s[top].branch_id = 0;
58 notfound = 0;
59 break;
60 }
61 }
62 if (notfound) {
63 /* nothing else found, go back up */
64 s[top].branch_id = t->nodecard;
65 top--;
66 }
67 }
68 else { /* this is a leaf node */
69 for (i = 0; i < t->leafcard; i++) {
70 if (s[top].sn->branch[i].child.id &&
71 RTreeOverlap(r, &(s[top].sn->branch[i].rect), t)) {
72 hitCount++;
73 if (shcb) { /* call the user-provided callback */
74 if (!shcb(s[top].sn->branch[i].child.id,
75 &s[top].sn->branch[i].rect, cbarg)) {
76 /* callback wants to terminate search early */
77 return hitCount;
78 }
79 }
80 }
81 }
82 top--;
83 }
84 }
85
86 return hitCount;
87}
88
89/*
90 * Inserts a new data rectangle into the index structure.
91 * Non-recursively descends tree.
92 * Returns 0 if node was not split and nothing was removed.
93 * Returns 1 if root node was split. Old node updated to become one of two.
94 * Returns 2 if branches need to be reinserted.
95 * The level argument specifies the number of steps up from the leaf
96 * level to insert; e.g. a data rectangle goes in at level = 0.
97 */
98static int RTreeInsertRect2M(struct RTree_Rect *r, union RTree_Child child,
99 int level, struct RTree_Node **newnode,
100 struct RTree *t, struct RTree_ListBranch **ee,
101 char *overflow)
102{
103 int i;
104 struct RTree_Node *n, *n2;
105 struct RTree_Rect *cover;
106 int top = 0, down = 0;
107 int result;
108 struct RTree_Branch *b = &(t->tmpb2);
109 struct nstack *s = t->ns;
110
111 /* add root node to stack */
112 s[top].sn = t->root;
113
114 /* go down to level of insertion */
115 while (s[top].sn->level > level) {
116 n = s[top].sn;
117 i = RTreePickBranch(r, n, t);
118 s[top++].branch_id = i;
119 /* add next node to stack */
120 s[top].sn = n->branch[i].child.ptr;
121 }
122
123 /* Have reached level for insertion. Remove p rectangles or split */
124 RTreeCopyRect(&(b->rect), r, t);
125 /* child field of leaves contains tid of data record */
126 b->child = child;
127 /* add branch, may split node or remove branches */
128 cover = NULL;
129 if (top)
130 cover = &(s[top - 1].sn->branch[s[top - 1].branch_id].rect);
131 result = RTreeAddBranch(b, s[top].sn, &n2, ee, cover, overflow, t);
132 /* update node count */
133 if (result == 1) {
134 t->n_nodes++;
135 }
136
137 /* go back up */
138 while (top) {
139 down = top--;
140 i = s[top].branch_id;
141 if (result == 0) { /* branch was added */
142 RTreeExpandRect(&(s[top].sn->branch[i].rect), r, t);
143 }
144 else if (result == 2) { /* branches were removed */
145 /* get node cover of previous node */
146 RTreeNodeCover(s[down].sn, &(s[top].sn->branch[i].rect), t);
147 }
148 else if (result == 1) { /* node was split */
149 /* get node cover of previous node */
150 RTreeNodeCover(s[down].sn, &(s[top].sn->branch[i].rect), t);
151 /* add new branch for new node previously added by RTreeAddBranch()
152 */
153 b->child.ptr = n2;
154 RTreeNodeCover(b->child.ptr, &(b->rect), t);
155
156 /* add branch, may split node or remove branches */
157 cover = NULL;
158 if (top)
159 cover = &(s[top - 1].sn->branch[s[top - 1].branch_id].rect);
160 result = RTreeAddBranch(b, s[top].sn, &n2, ee, cover, overflow, t);
161
162 /* update node count */
163 if (result == 1) {
164 t->n_nodes++;
165 }
166 }
167 }
168
169 *newnode = n2;
170
171 return result;
172}
173
174/*
175 * Insert a data rectangle into an index structure.
176 * RTreeInsertRect provides for splitting the root;
177 * returns 1 if root was split, 0 if it was not.
178 * The level argument specifies the number of steps up from the leaf
179 * level to insert; e.g. a data rectangle goes in at level = 0.
180 * RTreeInsertRect2 does the actual insertion.
181 */
182int RTreeInsertRectM(struct RTree_Rect *r, union RTree_Child child, int level,
183 struct RTree *t)
184{
185 struct RTree_Node *newnode, *newroot;
187 struct RTree_ListBranch *e;
188 int result;
189 char overflow[MAXLEVEL];
190 struct RTree_Branch *b = &(t->tmpb1);
191
192 /* R*-tree forced reinsertion: for each level only once */
193 memset(overflow, t->overflow, MAXLEVEL);
194
195 result = RTreeInsertRect2M(r, child, level, &newnode, t, &reInsertList,
196 overflow);
197
198 if (result == 1) { /* root split */
199 /* grow a new root, & tree taller */
200 t->rootlevel++;
201 newroot = RTreeAllocNode(t, t->rootlevel);
202 newroot->level = t->rootlevel;
203 /* branch for old root */
204 RTreeNodeCover(t->root, &(b->rect), t);
205 b->child.ptr = t->root;
207 /* branch for new node created by RTreeInsertRect2() */
208 RTreeNodeCover(newnode, &(b->rect), t);
209 b->child.ptr = newnode;
211 /* set new root node */
212 t->root = newroot;
213 t->n_nodes++;
214
215 return result;
216 }
217
218 if (result == 2) { /* branches were removed */
219 while (reInsertList) {
220 /* get next branch in list */
222 level = reInsertList->level;
223 e = reInsertList;
226 /* reinsert branches */
227 result = RTreeInsertRect2M(&(b->rect), b->child, level, &newnode, t,
228 &reInsertList, overflow);
229
230 if (result == 1) { /* root split */
231 /* grow a new root, & tree taller */
232 t->rootlevel++;
233 newroot = RTreeAllocNode(t, t->rootlevel);
234 newroot->level = t->rootlevel;
235 /* branch for old root */
236 RTreeNodeCover(t->root, &(b->rect), t);
237 b->child.ptr = t->root;
239 /* branch for new node created by RTreeInsertRect2() */
240 RTreeNodeCover(newnode, &(b->rect), t);
241 b->child.ptr = newnode;
243 /* set new root node */
244 t->root = newroot;
245 t->n_nodes++;
246 }
247 }
248 }
249
250 return result;
251}
252
253/*
254 * Delete a rectangle from non-root part of an index structure.
255 * Called by RTreeDeleteRect. Descends tree non-recursively,
256 * merges branches on the way back up.
257 * Returns 1 if record not found, 0 if success.
258 */
259static int RTreeDeleteRect2M(struct RTree_Rect *r, union RTree_Child child,
260 struct RTree *t, struct RTree_ListNode **ee)
261{
262 int i, notfound = 1;
263 struct RTree_Node *n;
264 int top = 0, down = 0;
265 int minfill;
266 struct nstack *s = t->ns;
267
268 assert(ee);
269
270 /* add root node position to stack */
271 s[top].sn = t->root;
272 s[top].branch_id = 0;
273 n = s[top].sn;
274
275 while (notfound && top >= 0) {
276 /* go down to level 0, remember path */
277 if (s[top].sn->level > 0) {
278 n = s[top].sn;
279 for (i = s[top].branch_id; i < t->nodecard; i++) {
280 if (n->branch[i].child.ptr &&
281 RTreeOverlap(r, &(n->branch[i].rect), t)) {
282 s[top++].branch_id = i + 1;
283 /* add next node to stack */
284 s[top].sn = n->branch[i].child.ptr;
285 s[top].branch_id = 0;
286
287 notfound = 0;
288 break;
289 }
290 }
291 if (notfound) {
292 /* nothing else found, go back up */
293 s[top].branch_id = t->nodecard;
294 top--;
295 }
296 else /* found a way down but not yet the item */
297 notfound = 1;
298 }
299 else {
300 for (i = 0; i < t->leafcard; i++) {
301 if (s[top].sn->branch[i].child.id &&
302 s[top].sn->branch[i].child.id ==
303 child.id) { /* found item */
304 RTreeDisconnectBranch(s[top].sn, i, t);
305 t->n_leafs--;
306 notfound = 0;
307 break;
308 }
309 }
310 if (notfound) /* continue searching */
311 top--;
312 }
313 }
314
315 if (notfound) {
316 return notfound;
317 }
318
319 /* go back up */
320 while (top) {
321 down = top;
322 top--;
323 i = s[top].branch_id - 1;
324 assert(s[down].sn->level == s[top].sn->level - 1);
325
326 minfill = (s[down].sn->level ? t->min_node_fill : t->min_leaf_fill);
327 if (s[down].sn->count >= minfill) {
328 /* just update node cover */
329 RTreeNodeCover(s[down].sn, &(s[top].sn->branch[i].rect), t);
330 }
331 else {
332 /* not enough entries in child, eliminate child node */
333 RTreeReInsertNode(s[top].sn->branch[i].child.ptr, ee);
334 RTreeDisconnectBranch(s[top].sn, i, t);
335 }
336 }
337
338 return notfound;
339}
340
341/*
342 * should be called by RTreeDeleteRect() only
343 *
344 * Delete a data rectangle from an index structure.
345 * Pass in a pointer to a Rect, the tid of the record, ptr RTree.
346 * Returns 1 if record not found, 0 if success.
347 * RTreeDeleteRect1 provides for eliminating the root.
348 */
349int RTreeDeleteRectM(struct RTree_Rect *r, union RTree_Child child,
350 struct RTree *t)
351{
352 int i;
353 struct RTree_Node *n;
355 struct RTree_ListNode *e;
356
357 if (!RTreeDeleteRect2M(r, child, t, &reInsertList)) {
358 /* found and deleted a data item */
359
360 /* reinsert any branches from eliminated nodes */
361 while (reInsertList) {
362 t->n_nodes--;
363 n = reInsertList->node;
364 if (n->level > 0) { /* reinsert node branches */
365 for (i = 0; i < t->nodecard; i++) {
366 if (n->branch[i].child.ptr) {
367 RTreeInsertRectM(&(n->branch[i].rect),
368 n->branch[i].child, n->level, t);
369 }
370 }
371 }
372 else { /* reinsert leaf branches */
373 for (i = 0; i < t->leafcard; i++) {
374 if (n->branch[i].child.id) {
375 RTreeInsertRectM(&(n->branch[i].rect),
376 n->branch[i].child, n->level, t);
377 }
378 }
379 }
380 e = reInsertList;
384 }
385
386 /* check for redundant root (not leaf, 1 child) and eliminate */
387 n = t->root;
388
389 if (n->count == 1 && n->level > 0) {
390 for (i = 0; i < t->nodecard; i++) {
391 if (n->branch[i].child.ptr)
392 break;
393 }
394 t->root = n->branch[i].child.ptr;
395 RTreeFreeNode(n);
396 t->rootlevel--;
397 }
398 return 0;
399 }
400
401 return 1;
402}
#define NULL
Definition ccmath.h:32
int RTreeAddBranch(struct RTree_Branch *, struct RTree_Node *, struct RTree_Node **, struct RTree_ListBranch **, struct RTree_Rect *, char *, struct RTree *)
Definition node.c:540
void RTreeDisconnectBranch(struct RTree_Node *, int, struct RTree *)
Definition node.c:266
void RTreeNodeCover(struct RTree_Node *, struct RTree_Rect *, struct RTree *)
Definition node.c:132
void RTreeCopyBranch(struct RTree_Branch *, struct RTree_Branch *, struct RTree *)
Definition node.c:121
int RTreePickBranch(struct RTree_Rect *, struct RTree_Node *, struct RTree *)
Definition node.c:232
int RTreeExpandRect(struct RTree_Rect *, struct RTree_Rect *, struct RTree *)
Definition rect.c:533
#define RTreeCopyRect(r1, r2, t)
Definition index.h:97
int RTreeDeleteRectM(struct RTree_Rect *r, union RTree_Child child, struct RTree *t)
Definition indexm.c:349
int RTreeSearchM(struct RTree *t, struct RTree_Rect *r, SearchHitCallback *shcb, void *cbarg)
Definition indexm.c:30
int RTreeValidChildM(union RTree_Child *child)
Definition indexm.c:20
int RTreeInsertRectM(struct RTree_Rect *r, union RTree_Child child, int level, struct RTree *t)
Definition indexm.c:182
#define assert(condition)
Definition lz4.c:291
void RTreeFreeNode(struct RTree_Node *n)
Definition node.c:92
struct RTree_Node * RTreeAllocNode(struct RTree *t, int level)
Definition node.c:71
double b
Definition r_raster.c:37
double t
Definition r_raster.c:37
double r
Definition r_raster.c:37
int RTreeOverlap(struct RTree_Rect *r, struct RTree_Rect *s, struct RTree *t)
Definition rect.c:587
int SearchHitCallback(int id, const struct RTree_Rect *rect, void *arg)
Definition rtree.h:83
union RTree_Child child
Definition rtree.h:66
struct RTree_Node * node
Definition index.h:32
int count
Definition rtree.h:71
int level
Definition rtree.h:72
struct RTree_Branch * branch
Definition rtree.h:73
Definition rtree.h:120
Definition rtree.h:97
struct RTree_Node * sn
Definition rtree.h:98
int branch_id
Definition rtree.h:99
struct RTree_Node * ptr
Definition rtree.h:59
int id
Definition rtree.h:58
void RTreeFreeListNode(struct RTree_ListNode *p)
void RTreeReInsertNode(struct RTree_Node *n, struct RTree_ListNode **ee)
void RTreeFreeListBranch(struct RTree_ListBranch *p)
#define MAXLEVEL
Maximum verbosity level.
Definition verbose.c:28