GRASS 8 Programmer's Manual 8.6.0dev(2026)-c83afef6d3
Loading...
Searching...
No Matches
indexf.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: 2001 GRASS Development Team
12 * SPDX-License-Identifier: GPL-2.0-or-later
13 *****************************************************************************/
14
15#include <stdlib.h>
16#include <stdio.h>
17#include <string.h>
18#include <sys/types.h>
19#include <assert.h>
20#include <grass/gis.h>
21#include "index.h"
22
24{
25 return (child->pos > -1);
26}
27
28/*
29 * Search in an index tree for all data rectangles that
30 * overlap the argument rectangle.
31 * Return the number of qualifying data rects.
32 */
34 void *cbarg)
35{
36 struct RTree_Node *n;
37 int hitCount = 0, notfound, currlevel;
38 int i;
39 int top = 0;
40 struct nstack *s = t->ns;
41
42 /* stack size of t->rootlevel + 1 is enough because of depth first search */
43 /* only one node per level on stack at any given time */
44
45 /* add root node position to stack */
46 currlevel = t->rootlevel;
47 s[top].pos = t->rootpos;
48 s[top].sn = RTreeGetNode(s[top].pos, currlevel, t);
49 s[top].branch_id = i = 0;
50
51 while (top >= 0) {
52 n = s[top].sn;
53 if (s[top].sn->level > 0) { /* this is an internal node in the tree */
54 notfound = 1;
55 currlevel = s[top].sn->level - 1;
56 for (i = s[top].branch_id; i < t->nodecard; i++) {
57 if (s[top].sn->branch[i].child.pos > -1 &&
58 RTreeOverlap(r, &(s[top].sn->branch[i].rect), t)) {
59 s[top++].branch_id = i + 1;
60 /* add next node to stack */
61 s[top].pos = n->branch[i].child.pos;
62 s[top].sn = RTreeGetNode(s[top].pos, currlevel, t);
63 s[top].branch_id = 0;
64 notfound = 0;
65 break;
66 }
67 }
68 if (notfound) {
69 /* nothing else found, go back up */
70 s[top].branch_id = t->nodecard;
71 top--;
72 }
73 }
74 else { /* this is a leaf node */
75 for (i = 0; i < t->leafcard; i++) {
76 if (s[top].sn->branch[i].child.id &&
77 RTreeOverlap(r, &(s[top].sn->branch[i].rect), t)) {
78 hitCount++;
79 if (shcb) { /* call the user-provided callback */
80 if (!shcb(s[top].sn->branch[i].child.id,
81 &(s[top].sn->branch[i].rect), cbarg)) {
82 /* callback wants to terminate search early */
83 return hitCount;
84 }
85 }
86 }
87 }
88 top--;
89 }
90 }
91
92 return hitCount;
93}
94
95/*
96 * Inserts a new data rectangle into the index structure.
97 * Non-recursively descends tree, propagates splits back up.
98 * Returns 0 if node was not split. Old node updated.
99 * If node was split, returns 1 and sets the pointer pointed to by
100 * new_node to point to the new node. Old node updated to become one of two.
101 * The level argument specifies the number of steps up from the leaf
102 * level to insert; e.g. a data rectangle goes in at level = 0.
103 */
104static int RTreeInsertRect2F(struct RTree_Rect *r, union RTree_Child child,
105 int level, struct RTree_Node *newnode,
106 off_t *newnode_pos, struct RTree *t,
107 struct RTree_ListBranch **ee, char *overflow)
108{
109 int i, currlevel;
110 struct RTree_Node *n, *n2;
111 struct RTree_Rect *cover;
112 int top = 0, down = 0;
113 int result;
114 struct RTree_Branch *b = &(t->tmpb2);
115 struct nstack *s = t->ns;
116
117 struct RTree_Rect *nr = &(t->orect);
118
119 n2 = newnode;
120
121 /* add root node position to stack */
122 currlevel = t->rootlevel;
123 s[top].pos = t->rootpos;
124 s[top].sn = RTreeGetNode(s[top].pos, currlevel, t);
125
126 /* go down to level of insertion */
127 while (s[top].sn->level > level) {
128 n = s[top].sn;
129 currlevel = s[top].sn->level - 1;
130 i = RTreePickBranch(r, n, t);
131 s[top++].branch_id = i;
132 /* add next node to stack */
133 s[top].pos = n->branch[i].child.pos;
134 s[top].sn = RTreeGetNode(s[top].pos, currlevel, t);
135 }
136
137 /* Have reached level for insertion. Add rect, split if necessary */
138 RTreeCopyRect(&(b->rect), r, t);
139 /* child field of leaves contains tid of data record */
140 b->child = child;
141 /* add branch, may split node or remove branches */
142 cover = NULL;
143 if (top)
144 cover = &(s[top - 1].sn->branch[s[top - 1].branch_id].rect);
145 result = RTreeAddBranch(b, s[top].sn, &n2, ee, cover, overflow, t);
146 /* update node */
147 RTreeNodeChanged(s[top].sn, s[top].pos, t);
148 /* write out new node if node was split */
149 if (result == 1) {
151 RTreeWriteNode(n2, t);
152 t->n_nodes++;
153 }
154
155 /* go back up */
156 while (top) {
157 down = top--;
158 i = s[top].branch_id;
159 if (result == 0) { /* branch was added */
160 if (RTreeExpandRect(&(s[top].sn->branch[i].rect), r, t)) {
161 RTreeNodeChanged(s[top].sn, s[top].pos, t);
162 }
163 }
164 else if (result == 2) { /* branches were removed */
165 /* get node cover of previous node */
166 RTreeNodeCover(s[down].sn, nr, t);
167 /* rewrite rect */
168 if (!RTreeCompareRect(nr, &(s[top].sn->branch[i].rect), t)) {
169 RTreeCopyRect(&(s[top].sn->branch[i].rect), nr, t);
170 RTreeNodeChanged(s[top].sn, s[top].pos, t);
171 }
172 }
173 else if (result == 1) { /* node was split */
174 /* get node cover of previous node */
175 RTreeNodeCover(s[down].sn, &(s[top].sn->branch[i].rect), t);
176 /* add new branch for new node previously added by RTreeAddBranch()
177 */
178 b->child.pos = *newnode_pos;
179 RTreeNodeCover(n2, &(b->rect), t);
180
181 /* add branch, may split node or remove branches */
182 cover = NULL;
183 if (top)
184 cover = &(s[top - 1].sn->branch[s[top - 1].branch_id].rect);
185 result = RTreeAddBranch(b, s[top].sn, &n2, ee, cover, overflow, t);
186
187 /* update node */
188 RTreeNodeChanged(s[top].sn, s[top].pos, t);
189
190 /* write out new node if node was split */
191 if (result == 1) {
193 RTreeWriteNode(n2, t);
194 t->n_nodes++;
195 }
196 }
197 }
198
199 return result;
200}
201
202/*
203 * Insert a data rectangle into an index structure.
204 * RTreeInsertRect provides for splitting the root;
205 * returns 1 if root was split, 0 if it was not.
206 * The level argument specifies the number of steps up from the leaf
207 * level to insert; e.g. a data rectangle goes in at level = 0.
208 * RTreeInsertRect2 does the actual insertion.
209 */
210int RTreeInsertRectF(struct RTree_Rect *r, union RTree_Child child, int level,
211 struct RTree *t)
212{
214 struct RTree_ListBranch *e;
215 int result;
216 char overflow[MAXLEVEL];
217 struct RTree_Branch *b = &(t->tmpb1);
218 off_t newnode_pos = -1;
219
220 struct RTree_Node *oldroot;
221 static struct RTree_Node *newroot = NULL, *newnode = NULL;
222
223 if (!newroot) {
226 }
227
228 /* R*-tree forced reinsertion: for each level only once */
229 memset(overflow, t->overflow, MAXLEVEL);
230
231 result = RTreeInsertRect2F(r, child, level, newnode, &newnode_pos, t,
232 &reInsertList, overflow);
233
234 if (result == 1) { /* root split */
235 oldroot = RTreeGetNode(t->rootpos, t->rootlevel, t);
236 /* grow a new root, & tree taller */
237 t->rootlevel++;
238 RTreeInitNode(t, newroot, NODETYPE(t->rootlevel, t->fd));
239 newroot->level = t->rootlevel;
240 /* branch for old root */
241 RTreeNodeCover(oldroot, &(b->rect), t);
242 b->child.pos = t->rootpos;
244 /* branch for new node created by RTreeInsertRect2() */
245 RTreeNodeCover(newnode, &(b->rect), t);
246 b->child.pos = newnode_pos; /* offset to new node as returned by
247 RTreeInsertRect2F() */
249 /* write new root node */
250 t->rootpos = RTreeGetNodePos(t);
252 t->n_nodes++;
253
254 return result;
255 }
256
257 if (result == 2) { /* branches were removed */
258 while (reInsertList) {
259 /* get next branch in list */
261 level = reInsertList->level;
262 e = reInsertList;
265 /* reinsert branches */
266 result =
267 RTreeInsertRect2F(&(b->rect), b->child, level, newnode,
268 &newnode_pos, t, &reInsertList, overflow);
269
270 if (result == 1) { /* root split */
271 oldroot = RTreeGetNode(t->rootpos, t->rootlevel, t);
272 /* grow a new root, & tree taller */
273 t->rootlevel++;
274 RTreeInitNode(t, newroot, NODETYPE(t->rootlevel, t->fd));
275 newroot->level = t->rootlevel;
276 /* branch for old root */
277 RTreeNodeCover(oldroot, &(b->rect), t);
278 b->child.pos = t->rootpos;
280 /* branch for new node created by RTreeInsertRect2() */
281 RTreeNodeCover(newnode, &(b->rect), t);
282 b->child.pos = newnode_pos;
284 /* write new root node */
285 t->rootpos = RTreeGetNodePos(t);
287 t->n_nodes++;
288 }
289 }
290 }
291
292 return result;
293}
294
295/*
296 * Delete a rectangle from non-root part of an index structure.
297 * Called by RTreeDeleteRect. Descends tree non-recursively,
298 * merges branches on the way back up.
299 * Returns 1 if record not found, 0 if success.
300 */
301static int RTreeDeleteRect2F(struct RTree_Rect *r, union RTree_Child child,
302 struct RTree *t, struct RTree_ListNode **ee)
303{
304 int i, notfound = 1, currlevel;
305 struct RTree_Node *n;
306 int top = 0, down = 0;
307 int minfill;
308 struct nstack *s = t->ns;
309
310 struct RTree_Rect *nr = &(t->orect);
311
312 /* add root node position to stack */
313 currlevel = t->rootlevel;
314 s[top].pos = t->rootpos;
315 s[top].sn = RTreeGetNode(s[top].pos, currlevel, t);
316 s[top].branch_id = 0;
317
318 while (notfound && top >= 0) {
319 /* go down to level 0, remember path */
320 if (s[top].sn->level > 0) {
321 n = s[top].sn;
322 currlevel = s[top].sn->level - 1;
323 for (i = s[top].branch_id; i < t->nodecard; i++) {
324 if (n->branch[i].child.pos > -1 &&
325 RTreeOverlap(r, &(n->branch[i].rect), t)) {
326 s[top++].branch_id = i + 1;
327 /* add next node to stack */
328 s[top].pos = n->branch[i].child.pos;
329 s[top].sn = RTreeGetNode(s[top].pos, currlevel, t);
330 s[top].branch_id = 0;
331
332 notfound = 0;
333 break;
334 }
335 }
336 if (notfound) {
337 /* nothing else found, go back up */
338 s[top].branch_id = t->nodecard;
339 top--;
340 }
341 else /* found a way down but not yet the item */
342 notfound = 1;
343 }
344 else {
345 for (i = 0; i < t->leafcard; i++) {
346 if (s[top].sn->branch[i].child.id &&
347 s[top].sn->branch[i].child.id ==
348 child.id) { /* found item */
349 RTreeDisconnectBranch(s[top].sn, i, t);
350 RTreeNodeChanged(s[top].sn, s[top].pos, t);
351 t->n_leafs--;
352 notfound = 0;
353 break;
354 }
355 }
356 if (notfound) /* continue searching */
357 top--;
358 }
359 }
360
361 if (notfound) {
362 return notfound;
363 }
364
365 /* go back up */
366 while (top) {
367 down = top;
368 top--;
369 i = s[top].branch_id - 1;
370
371 minfill = (s[down].sn->level ? t->min_node_fill : t->min_leaf_fill);
372 if (s[down].sn->count >= minfill) {
373 /* just update node cover */
374 RTreeNodeCover(s[down].sn, nr, t);
375 /* rewrite rect */
376 if (!RTreeCompareRect(nr, &(s[top].sn->branch[i].rect), t)) {
377 RTreeCopyRect(&(s[top].sn->branch[i].rect), nr, t);
378 RTreeNodeChanged(s[top].sn, s[top].pos, t);
379 }
380 }
381 else {
382 /* not enough entries in child, eliminate child node */
383 n = RTreeAllocNode(t, s[down].sn->level);
384 /* copy node */
385 RTreeCopyNode(n, s[down].sn, t);
386 RTreeAddNodePos(s[down].pos, s[down].sn->level, t);
388 RTreeDisconnectBranch(s[top].sn, i, t);
389
390 RTreeNodeChanged(s[top].sn, s[top].pos, t);
391 }
392 }
393
394 return notfound;
395}
396
397/*
398 * should be called by RTreeDeleteRect() only
399 *
400 * Delete a data rectangle from an index structure.
401 * Pass in a pointer to a Rect, the tid of the record, ptr RTree.
402 * Returns 1 if record not found, 0 if success.
403 * RTreeDeleteRect1 provides for eliminating the root.
404 */
405int RTreeDeleteRectF(struct RTree_Rect *r, union RTree_Child child,
406 struct RTree *t)
407{
408 int i;
409 struct RTree_Node *n;
410 struct RTree_ListNode *e, *reInsertList = NULL;
411
412 if (!RTreeDeleteRect2F(r, child, t, &reInsertList)) {
413 /* found and deleted a data item */
414
415 /* reinsert any branches from eliminated nodes */
416 while (reInsertList) {
417 t->n_nodes--;
418 n = reInsertList->node;
419 if (n->level > 0) { /* reinsert node branches */
420 for (i = 0; i < t->nodecard; i++) {
421 if (n->branch[i].child.pos > -1) {
422 RTreeInsertRectF(&(n->branch[i].rect),
423 n->branch[i].child, n->level, t);
424 }
425 }
426 }
427 else { /* reinsert leaf branches */
428 for (i = 0; i < t->leafcard; i++) {
429 if (n->branch[i].child.id) {
430 RTreeInsertRectF(&(n->branch[i].rect),
431 n->branch[i].child, n->level, t);
432 }
433 }
434 }
435 e = reInsertList;
439 }
440
441 /* check for redundant root (not leaf, 1 child) and eliminate */
442 n = RTreeGetNode(t->rootpos, t->rootlevel, t);
443
444 if (n->count == 1 && n->level > 0) {
445 for (i = 0; i < t->nodecard; i++) {
446 if (n->branch[i].child.pos > -1)
447 break;
448 }
449 RTreeAddNodePos(t->rootpos, t->rootlevel, t);
450 t->rootpos = n->branch[i].child.pos;
451 t->rootlevel--;
452 t->n_nodes--;
453 }
454
455 return 0;
456 }
457
458 return 1;
459}
#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 RTreeAddNodePos(off_t, int, struct RTree *)
Definition io.c:31
struct RTree_Node * RTreeGetNode(off_t, int, struct RTree *)
Definition io.c:115
#define NODETYPE(l, fd)
Definition index.h:28
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
void RTreeNodeChanged(struct RTree_Node *, off_t, struct RTree *)
Definition io.c:209
int RTreeExpandRect(struct RTree_Rect *, struct RTree_Rect *, struct RTree *)
Definition rect.c:533
#define RTreeCopyRect(r1, r2, t)
Definition index.h:97
int RTreeCompareRect(struct RTree_Rect *, struct RTree_Rect *, struct RTree *)
Definition rect.c:567
int RTreeSearchF(struct RTree *t, struct RTree_Rect *r, SearchHitCallback *shcb, void *cbarg)
Definition indexf.c:33
int RTreeValidChildF(union RTree_Child *child)
Definition indexf.c:23
int RTreeDeleteRectF(struct RTree_Rect *r, union RTree_Child child, struct RTree *t)
Definition indexf.c:405
int RTreeInsertRectF(struct RTree_Rect *r, union RTree_Child child, int level, struct RTree *t)
Definition indexf.c:210
off_t RTreeGetNodePos(struct RTree *t)
Definition io.c:71
size_t RTreeWriteNode(struct RTree_Node *n, struct RTree *t)
Definition io.c:174
void RTreeCopyNode(struct RTree_Node *n1, struct RTree_Node *n2, struct RTree *t)
Definition node.c:106
void RTreeFreeNode(struct RTree_Node *n)
Definition node.c:92
struct RTree_Node * RTreeAllocNode(struct RTree *t, int level)
Definition node.c:71
void RTreeInitNode(struct RTree *t, struct RTree_Node *n, int type)
Definition node.c:59
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
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
off_t pos
Definition rtree.h:100
struct RTree_Node * sn
Definition rtree.h:98
int branch_id
Definition rtree.h:99
off_t pos
Definition rtree.h:60
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