2
/****************************************************************************
3
* MODULE: R-Tree library
5
* AUTHOR(S): Antonin Guttman - original code
6
* Daniel Green (green@superliminal.com) - major clean-up
7
* and implementation of bounding spheres
9
* PURPOSE: Multidimensional index
11
* COPYRIGHT: (C) 2001 by the GRASS Development Team
13
* This program is free software under the GNU General Public
14
* License (>=v2). Read the file COPYING that comes with GRASS
16
*****************************************************************************/
2
\file lib/vector/rtree/index.c
4
\brief R-Tree library - Multidimensional index
6
Higher level functions for managing R*-Trees.
8
(C) 2010-2012 by the GRASS Development Team
10
This program is free software under the
11
GNU General Public License (>=v2).
12
Read the file COPYING that comes with GRASS
15
\author Antonin Guttman - original code
16
\author Daniel Green (green@superliminal.com) - major clean-up
17
and implementation of bounding spheres
18
\author Markus Metz - file-based and memory-based R*-tree
21
/* Read these articles first before attempting to modify the code
24
* Guttman, A. (1984). "R-Trees: A Dynamic Index Structure for Spatial
25
* Searching". Proceedings of the 1984 ACM SIGMOD international
26
* conference on Management of data - SIGMOD '84. pp. 47.
27
* DOI:10.1145/602259.602266
31
* Beckmann, N.; Kriegel, H. P.; Schneider, R.; Seeger, B. (1990).
32
* "The R*-tree: an efficient and robust access method for points and
33
* rectangles". Proceedings of the 1990 ACM SIGMOD international
34
* conference on Management of data - SIGMOD '90. pp. 322.
35
* DOI:10.1145/93597.98741
19
39
#include <stdlib.h>
40
#include <sys/types.h>
43
#include <grass/gis.h>
24
/* Make a new index, empty. Consists of a single node. */
25
struct Node *RTreeNewIndex(void)
30
x->level = 0; /* leaf */
35
* Search in an index tree or subtree for all data retangles that
36
* overlap the argument rectangle.
37
* Return the number of qualifying data rects.
39
int RTreeSearch(struct Node *N, struct Rect *R, SearchHitCallback shcb,
42
register struct Node *n = N;
43
register struct Rect *r = R; /* NOTE: Suspected bug was R sent in as Node* and cast to Rect* here. */
45
/* Fix not yet tested. */
46
register int hitCount = 0;
50
assert(n->level >= 0);
53
if (n->level > 0) { /* this is an internal node in the tree */
54
for (i = 0; i < NODECARD; i++)
55
if (n->branch[i].child && RTreeOverlap(r, &n->branch[i].rect)) {
56
hitCount += RTreeSearch(n->branch[i].child, r, shcb, cbarg);
59
else { /* this is a leaf node */
61
for (i = 0; i < LEAFCARD; i++)
62
if (n->branch[i].child && RTreeOverlap(r, &n->branch[i].rect)) {
64
if (shcb) /* call the user-provided callback */
65
if (!shcb((int)n->branch[i].child, cbarg))
66
return hitCount; /* callback wants to terminate search early */
73
* Inserts a new data rectangle into the index structure.
74
* Recursively descends tree, propagates splits back up.
75
* Returns 0 if node was not split. Old node updated.
76
* If node was split, returns 1 and sets the pointer pointed to by
77
* new_node to point to the new node. Old node updated to become one of two.
78
* The level argument specifies the number of steps up from the leaf
79
* level to insert; e.g. a data rectangle goes in at level = 0.
81
static int RTreeInsertRect2(struct Rect *r,
82
struct Node *child, struct Node *n, struct Node **new_node,
86
register struct Rect *r = R;
87
register int tid = Tid;
88
register struct Node *n = N, **new_node = New_node;
89
register int level = Level;
96
assert(r && n && new_node);
97
assert(level >= 0 && level <= n->level);
99
/* Still above level for insertion, go down tree recursively */
100
if (n->level > level) {
101
i = RTreePickBranch(r, n);
102
if (!RTreeInsertRect2(r, child, n->branch[i].child, &n2, level)) {
103
/* child was not split */
104
n->branch[i].rect = RTreeCombineRect(r, &(n->branch[i].rect));
107
else { /* child was split */
109
n->branch[i].rect = RTreeNodeCover(n->branch[i].child);
111
b.rect = RTreeNodeCover(n2);
112
return RTreeAddBranch(&b, n, new_node);
116
/* Have reached level for insertion. Add rect, split if necessary */
117
else if (n->level == level) {
120
/* child field of leaves contains tid of data record */
121
return RTreeAddBranch(&b, n, new_node);
124
/* Not supposed to happen */
131
* Insert a data rectangle into an index structure.
132
* RTreeInsertRect provides for splitting the root;
133
* returns 1 if root was split, 0 if it was not.
134
* The level argument specifies the number of steps up from the leaf
135
* level to insert; e.g. a data rectangle goes in at level = 0.
136
* RTreeInsertRect2 does the recursion.
138
int RTreeInsertRect(struct Rect *R, int Tid, struct Node **Root, int Level)
141
return RTreeInsertRect1(R, (struct Node *) Tid, Root, Level);
144
int RTreeInsertRect1(struct Rect *R, struct Node *Child, struct Node **Root, int Level)
146
register struct Rect *r = R;
147
register struct Node *child = Child;
148
register struct Node **root = Root;
149
register int level = Level;
151
register struct Node *newroot;
152
struct Node *newnode;
157
assert(level >= 0 && level <= (*root)->level);
158
for (i = 0; i < NUMDIMS; i++) {
159
assert(r->boundary[i] <= r->boundary[NUMDIMS + i]);
162
if (RTreeInsertRect2(r, child, *root, &newnode, level)) { /* root split */
163
newroot = RTreeNewNode(); /* grow a new root, & tree taller */
164
newroot->level = (*root)->level + 1;
165
b.rect = RTreeNodeCover(*root);
167
RTreeAddBranch(&b, newroot, NULL);
168
b.rect = RTreeNodeCover(newnode);
170
RTreeAddBranch(&b, newroot, NULL);
47
\brief Create new empty R*-Tree
49
This method creates a new RTree, either in memory (fd < 0) or in file.
50
If the file descriptor is positive, the corresponding file must have
51
been opened for reading and writing.
52
This method must also be called if an existing tree previously saved
53
to file is going to be accessed.
55
\param fd file descriptor to hold data, negative toggles memory mode
56
\param rootpos offset in file to root node (past any header info)
57
\param ndims number of dimensions for the new tree: min 2, max 20
59
\return pointer to new RTree structure
61
struct RTree *RTreeCreateTree(int fd, off_t rootpos, int ndims)
63
struct RTree *new_rtree;
67
new_rtree = (struct RTree *)malloc(sizeof(struct RTree));
70
new_rtree->rootpos = rootpos;
71
new_rtree->ndims = ndims;
72
new_rtree->nsides = 2 * ndims;
73
/* hack to keep compatibility */
75
new_rtree->ndims_alloc = 3;
181
* Allocate space for a node in the list used in DeletRect to
77
new_rtree->ndims_alloc = ndims;
79
new_rtree->nsides_alloc = 2 * new_rtree->ndims_alloc;
81
/* init free node positions */
82
new_rtree->free_nodes.avail = 0;
83
new_rtree->free_nodes.alloc = 0;
84
new_rtree->free_nodes.pos = NULL;
86
new_rtree->rectsize = new_rtree->nsides_alloc * sizeof(RectReal);
87
new_rtree->nodesize = sizeof(struct RTree_Node) -
88
MAXCARD * sizeof(RectReal *) +
89
MAXCARD * new_rtree->rectsize;
91
new_rtree->branchsize = sizeof(struct RTree_Branch) -
92
sizeof(RectReal *) + new_rtree->rectsize;
94
/* create empty root node */
95
n = RTreeAllocNode(new_rtree, 0);
96
new_rtree->rootlevel = n->level = 0; /* leaf */
98
/* use overflow by default */
99
new_rtree->overflow = 1;
101
if (fd > -1) { /* file based */
102
/* nodecard and leafcard can be adjusted, must NOT be larger than MAXCARD */
103
new_rtree->nodecard = MAXCARD;
104
new_rtree->leafcard = MAXCARD;
106
/* initialize node buffer */
107
new_rtree->nb = calloc(MAXLEVEL, sizeof(struct NodeBuffer *));
108
new_rtree->nb[0] = calloc(MAXLEVEL * NODE_BUFFER_SIZE, sizeof(struct NodeBuffer));
109
for (i = 1; i < MAXLEVEL; i++) {
110
new_rtree->nb[i] = new_rtree->nb[i - 1] + NODE_BUFFER_SIZE;
113
new_rtree->used = malloc(MAXLEVEL * sizeof(int *));
114
new_rtree->used[0] = malloc(MAXLEVEL * NODE_BUFFER_SIZE * sizeof(int));
115
for (i = 0; i < MAXLEVEL; i++) {
117
new_rtree->used[i] = new_rtree->used[i - 1] + NODE_BUFFER_SIZE;
118
for (j = 0; j < NODE_BUFFER_SIZE; j++) {
119
new_rtree->nb[i][j].dirty = 0;
120
new_rtree->nb[i][j].pos = -1;
122
new_rtree->used[i][j] = j;
124
new_rtree->nb[i][j].n.branch = malloc(MAXCARD * sizeof(struct RTree_Branch));
126
/* alloc memory for rectangles */
127
for (k = 0; k < MAXCARD; k++) {
128
new_rtree->nb[i][j].n.branch[k].rect.boundary = RTreeAllocBoundary(new_rtree);
133
/* write empty root node */
134
lseek(new_rtree->fd, rootpos, SEEK_SET);
135
RTreeWriteNode(n, new_rtree);
137
new_rtree->root = NULL;
139
new_rtree->insert_rect = RTreeInsertRectF;
140
new_rtree->delete_rect = RTreeDeleteRectF;
141
new_rtree->search_rect = RTreeSearchF;
142
new_rtree->valid_child = RTreeValidChildF;
144
else { /* memory based */
145
new_rtree->nodecard = MAXCARD;
146
new_rtree->leafcard = MAXCARD;
148
new_rtree->insert_rect = RTreeInsertRectM;
149
new_rtree->delete_rect = RTreeDeleteRectM;
150
new_rtree->search_rect = RTreeSearchM;
151
new_rtree->valid_child = RTreeValidChildM;
156
/* minimum number of remaining children for RTreeDeleteRect */
157
/* NOTE: min fill can be changed if needed, must be < nodecard and leafcard. */
158
new_rtree->min_node_fill = (new_rtree->nodecard - 2) / 2;
159
new_rtree->min_leaf_fill = (new_rtree->leafcard - 2) / 2;
161
/* balance criteria for node splitting */
162
new_rtree->minfill_node_split = (new_rtree->nodecard - 1) / 2;
163
new_rtree->minfill_leaf_split = (new_rtree->leafcard - 1) / 2;
165
new_rtree->n_nodes = 1;
166
new_rtree->n_leafs = 0;
168
/* initialize temp variables */
169
new_rtree->ns = malloc(MAXLEVEL * sizeof(struct nstack));
171
new_rtree->p.cover[0].boundary = RTreeAllocBoundary(new_rtree);
172
new_rtree->p.cover[1].boundary = RTreeAllocBoundary(new_rtree);
174
new_rtree->tmpb1.rect.boundary = RTreeAllocBoundary(new_rtree);
175
new_rtree->tmpb2.rect.boundary = RTreeAllocBoundary(new_rtree);
176
new_rtree->c.rect.boundary = RTreeAllocBoundary(new_rtree);
178
new_rtree->BranchBuf = malloc((MAXCARD + 1) * sizeof(struct RTree_Branch));
179
for (i = 0; i <= MAXCARD; i++) {
180
new_rtree->BranchBuf[i].rect.boundary = RTreeAllocBoundary(new_rtree);
182
new_rtree->rect_0.boundary = RTreeAllocBoundary(new_rtree);
183
new_rtree->rect_1.boundary = RTreeAllocBoundary(new_rtree);
184
new_rtree->upperrect.boundary = RTreeAllocBoundary(new_rtree);
185
new_rtree->orect.boundary = RTreeAllocBoundary(new_rtree);
186
new_rtree->center_n = (RectReal *)malloc(new_rtree->ndims_alloc * sizeof(RectReal));
192
\brief Enable/disable R*-tree forced reinsertion (overflow)
194
For dynamic R*-trees with runtime insertion and deletion,
195
forced reinsertion results in a more compact tree, searches are a bit
196
faster. For static R*-trees (no insertion/deletion after creation)
197
forced reinsertion can be disabled at the cost of slower searches.
199
\param t pointer to RTree structure
200
\param overflow binary flag
204
void RTreeSetOverflow(struct RTree *t, char overflow)
206
t->overflow = overflow != 0;
210
\brief Destroy an R*-Tree
212
This method releases all memory allocated to a RTree. It deletes all
213
rectangles and all memory allocated for internal support data.
214
Note that for a file-based RTree, the file is not deleted and not
215
closed. The file can thus be used to permanently store an RTree.
217
\param t pointer to RTree structure
222
void RTreeDestroyTree(struct RTree *t)
231
for (i = 0; i < MAXLEVEL; i++) {
232
for (j = 0; j < NODE_BUFFER_SIZE; j++) {
233
for (k = 0; k < MAXCARD; k++) {
234
RTreeFreeBoundary(&t->nb[i][j].n.branch[k].rect);
236
free(t->nb[i][j].n.branch);
240
if (t->free_nodes.alloc)
241
free(t->free_nodes.pos);
248
RTreeDestroyNode(t->root, t->root->level ? t->nodecard : t->leafcard);
250
/* free temp variables */
253
RTreeFreeBoundary(&(t->p.cover[0]));
254
RTreeFreeBoundary(&(t->p.cover[1]));
256
RTreeFreeBoundary(&(t->tmpb1.rect));
257
RTreeFreeBoundary(&(t->tmpb2.rect));
258
RTreeFreeBoundary(&(t->c.rect));
259
for (i = 0; i <= MAXCARD; i++) {
260
RTreeFreeBoundary(&(t->BranchBuf[i].rect));
263
RTreeFreeBoundary(&(t->rect_0));
264
RTreeFreeBoundary(&(t->rect_1));
265
RTreeFreeBoundary(&(t->upperrect));
266
RTreeFreeBoundary(&(t->orect));
275
\brief Search an R*-Tree
277
Search in an RTree for all data retangles that overlap or touch the
279
Return the number of qualifying data rectangles.
280
The search stops if the SearchHitCallBack function returns 0 (zero)
281
or if there are no more qualifying data rectangles.
283
\param t pointer to RTree structure
284
\param r pointer to rectangle to use for searching
285
\param shcb Search Hit CallBack function
286
\param cbarg custom pointer used as argument for the shcb fn
288
\return number of qualifying data rectangles
292
* add option to select operator to select rectangles ?
294
* possible alternatives:
295
* - select all rectangles that are fully contained in r
296
* - select all rectangles that fully contain r
298
int RTreeSearch(struct RTree *t, struct RTree_Rect *r,
299
SearchHitCallback *shcb, void *cbarg)
303
return t->search_rect(t, r, shcb, cbarg);
307
\brief Insert an item into a R*-Tree
309
\param r pointer to rectangle to use for searching
310
\param tid data id stored with rectangle, must be > 0
311
\param t pointer to RTree structure
313
\return number of qualifying data rectangles
315
int RTreeInsertRect(struct RTree_Rect *r, int tid, struct RTree *t)
317
union RTree_Child newchild;
319
assert(r && t && tid > 0);
324
return t->insert_rect(r, newchild, 0, t);
328
\brief Delete an item from a R*-Tree
330
This method deletes an item from the RTree. The rectangle passed to
331
this method does not need to be the exact rectangle, the only
332
requirement is that this rectangle overlaps with the rectangle to
333
be deleted. The rectangle to be deleted is identified by its id.
335
\param r pointer to rectangle to use for searching
336
\param tid id of the data to be deleted, must be > 0
337
\param t pointer to RTree structure
340
\return 1 if data item not found
342
int RTreeDeleteRect(struct RTree_Rect *r, int tid, struct RTree *t)
344
union RTree_Child child;
346
assert(r && t && tid > 0);
350
return t->delete_rect(r, child, t);
354
/***********************************
355
* internally used functions *
356
***********************************/
360
* Allocate space for a node in the list used in DeleteRect to
182
361
* store Nodes that are too empty.
184
static struct ListNode *RTreeNewListNode(void)
363
struct RTree_ListNode *RTreeNewListNode(void)
186
return (struct ListNode *)malloc(sizeof(struct ListNode));
187
/* return new ListNode; */
365
return (struct RTree_ListNode *)malloc(sizeof(struct RTree_ListNode));
190
static void RTreeFreeListNode(struct ListNode *p)
368
void RTreeFreeListNode(struct RTree_ListNode *p)
197
374
* Add a node to the reinsertion list. All its branches will later
198
375
* be reinserted into the index structure.
200
static void RTreeReInsert(struct Node *n, struct ListNode **ee)
377
void RTreeReInsertNode(struct RTree_Node *n, struct RTree_ListNode **ee)
202
register struct ListNode *l;
379
struct RTree_ListNode *l = RTreeNewListNode();
204
l = RTreeNewListNode();
211
* Delete a rectangle from non-root part of an index structure.
212
* Called by RTreeDeleteRect. Descends tree recursively,
213
* merges branches on the way back up.
214
* Returns 1 if record not found, 0 if success.
217
RTreeDeleteRect2(struct Rect *R, struct Node *Child, struct Node *N,
218
struct ListNode **Ee)
220
register struct Rect *r = R;
221
register struct Node *child = Child;
222
register struct Node *n = N;
223
register struct ListNode **ee = Ee;
226
assert(r && n && ee);
228
assert(n->level >= 0);
230
if (n->level > 0) { /* not a leaf node */
231
for (i = 0; i < NODECARD; i++) {
232
if (n->branch[i].child && RTreeOverlap(r, &(n->branch[i].rect))) {
233
if (!RTreeDeleteRect2(r, child, n->branch[i].child, ee)) {
234
if (n->branch[i].child->count >= MinNodeFill) {
236
RTreeNodeCover(n->branch[i].child);
239
/* not enough entries in child, eliminate child node */
240
RTreeReInsert(n->branch[i].child, ee);
241
RTreeDisconnectBranch(n, i);
249
else { /* a leaf node */
251
for (i = 0; i < LEAFCARD; i++) {
252
if (n->branch[i].child &&
253
n->branch[i].child == child) {
254
RTreeDisconnectBranch(n, i);
263
* Delete a data rectangle from an index structure.
264
* Pass in a pointer to a Rect, the tid of the record, ptr to ptr to root node.
265
* Returns 1 if record not found, 0 if success.
266
* RTreeDeleteRect provides for eliminating the root.
268
int RTreeDeleteRect(struct Rect *R, int Tid, struct Node **Nn)
270
/* wrapper not really needed, but restricts compile warnings to rtree lib */
271
/* this way it's easier to fix if necessary? */
272
return RTreeDeleteRect1(R, (struct Node *) Tid, Nn);
275
int RTreeDeleteRect1(struct Rect *R, struct Node *Child, struct Node **Nn)
277
register struct Rect *r = R;
278
register struct Node *child = Child;
279
register struct Node **nn = Nn;
281
struct Node *tmp_nptr = NULL;
282
struct ListNode *reInsertList = NULL;
283
register struct ListNode *e;
289
if (!RTreeDeleteRect2(r, child, *nn, &reInsertList)) {
290
/* found and deleted a data item */
292
/* reinsert any branches from eliminated nodes */
293
while (reInsertList) {
294
tmp_nptr = reInsertList->node;
295
for (i = 0; i < MAXKIDS(tmp_nptr); i++) {
296
if (tmp_nptr->branch[i].child) {
297
RTreeInsertRect1(&(tmp_nptr->branch[i].rect),
298
tmp_nptr->branch[i].child,
299
nn, tmp_nptr->level);
303
reInsertList = reInsertList->next;
304
RTreeFreeNode(e->node);
305
RTreeFreeListNode(e);
308
/* check for redundant root (not leaf, 1 child) and eliminate */
309
if ((*nn)->count == 1 && (*nn)->level > 0) {
310
for (i = 0; i < NODECARD; i++) {
311
tmp_nptr = (*nn)->branch[i].child;
387
* Free ListBranch, used by R*-type forced reinsertion
389
void RTreeFreeListBranch(struct RTree_ListBranch *p)
391
RTreeFreeBoundary(&(p->b.rect));