1 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
2 *
3 * XASTIR, Amateur Station Tracking and Information Reporting
4 * Copyright (C) 1999,2000 Frank Giannandrea
5 * Copyright (C) 2000-2019 The Xastir Group
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * Look at the README for more information on the program.
22 */
23 /****************************************************************************
24 * MODULE: R-Tree library
25 *
26 * AUTHOR(S): Antonin Guttman - original code
27 * Melinda Green (melinda@superliminal.com) - major clean-up
28 * and implementation of bounding spheres
29 *
30 * PURPOSE: Multidimensional index
31 *
32 */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include "assert.h"
37 #include "index.h"
38 #include "card.h"
39
40
41 // Make a new index, empty. Consists of a single node.
42 //
Xastir_RTreeNewIndex(void)43 struct Node * Xastir_RTreeNewIndex(void)
44 {
45 struct Node *x;
46 x = Xastir_RTreeNewNode();
47 x->level = 0; /* leaf */
48 return x;
49 }
50
51
52
53 // Search in an index tree or subtree for all data retangles that
54 // overlap the argument rectangle.
55 // Return the number of qualifying data rects.
56 //
Xastir_RTreeSearch(struct Node * N,struct Rect * R,SearchHitCallback shcb,void * cbarg)57 int Xastir_RTreeSearch(struct Node *N, struct Rect *R, SearchHitCallback shcb, void* cbarg)
58 {
59 struct Node *n = N;
60 struct Rect *r = R; // NOTE: Suspected bug was R sent in as Node* and cast to Rect* here. Fix not yet tested.
61 int hitCount = 0;
62 int i;
63
64 assert(n);
65 assert(n->level >= 0);
66 assert(r);
67
68 if (n->level > 0) /* this is an internal node in the tree */
69 {
70 for (i=0; i<Xastir_NODECARD; i++)
71 if (n->branch[i].child &&
72 Xastir_RTreeOverlap(r,&n->branch[i].rect))
73 {
74 hitCount += Xastir_RTreeSearch(n->branch[i].child, R, shcb, cbarg);
75 }
76 }
77 else /* this is a leaf node */
78 {
79 for (i=0; i<Xastir_LEAFCARD; i++)
80 if (n->branch[i].child &&
81 Xastir_RTreeOverlap(r,&n->branch[i].rect))
82 {
83 hitCount++;
84 if(shcb) // call the user-provided callback
85 if( ! shcb(n->branch[i].child, cbarg))
86 {
87 return hitCount; // callback wants to terminate search early
88 }
89 }
90 }
91 return hitCount;
92 }
93
94
95
96 // Inserts a new data rectangle into the index structure.
97 // 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 //
Xastir_RTreeInsertRect2(struct Rect * r,void * tid,struct Node * n,struct Node ** new_node,int level)104 static int Xastir_RTreeInsertRect2(struct Rect *r,
105 void *tid, struct Node *n, struct Node **new_node, int level)
106 {
107 /*
108 register struct Rect *r = R;
109 register int tid = Tid;
110 register struct Node *n = N, **new_node = New_node;
111 register int level = Level;
112 */
113
114 int i;
115 struct Branch b;
116 struct Node *n2;
117
118 assert(r && n && new_node);
119 assert(level >= 0 && level <= n->level);
120
121 // Still above level for insertion, go down tree recursively
122 //
123 if (n->level > level)
124 {
125 i = Xastir_RTreePickBranch(r, n);
126 if (!Xastir_RTreeInsertRect2(r, tid, n->branch[i].child, &n2, level))
127 {
128 // child was not split
129 //
130 n->branch[i].rect =
131 Xastir_RTreeCombineRect(r,&(n->branch[i].rect));
132 return 0;
133 }
134 else // child was split
135 {
136 n->branch[i].rect = Xastir_RTreeNodeCover(n->branch[i].child);
137 b.child = n2;
138 b.rect = Xastir_RTreeNodeCover(n2);
139 return Xastir_RTreeAddBranch(&b, n, new_node);
140 }
141 }
142
143 // Have reached level for insertion. Add rect, split if necessary
144 //
145 else if (n->level == level)
146 {
147 b.rect = *r;
148 b.child = (struct Node *) tid;
149 /* child field of leaves contains tid of data record */
150 return Xastir_RTreeAddBranch(&b, n, new_node);
151 }
152 else
153 {
154 /* Not supposed to happen */
155 assert (FALSE);
156 return 0;
157 }
158 }
159
160
161
162 // Insert a data rectangle into an index structure.
163 // Xastir_RTreeInsertRect provides for splitting the root;
164 // returns 1 if root was split, 0 if it was not.
165 // The level argument specifies the number of steps up from the leaf
166 // level to insert; e.g. a data rectangle goes in at level = 0.
167 // Xastir_RTreeInsertRect2 does the recursion.
168 //
Xastir_RTreeInsertRect(struct Rect * R,void * Tid,struct Node ** Root,int Level)169 int Xastir_RTreeInsertRect(struct Rect *R, void *Tid, struct Node **Root, int Level)
170 {
171 struct Rect *r = R;
172 void *tid = Tid;
173 struct Node **root = Root;
174 int level = Level;
175 int i;
176 struct Node *newroot;
177 struct Node *newnode;
178 struct Branch b;
179 int result;
180
181 assert(r && root);
182 assert(level >= 0 && level <= (*root)->level);
183 for (i=0; i<NUMDIMS; i++)
184 {
185 assert(r->boundary[i] <= r->boundary[NUMDIMS+i]);
186 }
187
188 if (Xastir_RTreeInsertRect2(r, tid, *root, &newnode, level)) /* root split */
189 {
190 newroot = Xastir_RTreeNewNode(); /* grow a new root, & tree taller */
191 newroot->level = (*root)->level + 1;
192 b.rect = Xastir_RTreeNodeCover(*root);
193 b.child = *root;
194 Xastir_RTreeAddBranch(&b, newroot, NULL);
195 b.rect = Xastir_RTreeNodeCover(newnode);
196 b.child = newnode;
197 Xastir_RTreeAddBranch(&b, newroot, NULL);
198 *root = newroot;
199 result = 1;
200 }
201 else
202 {
203 result = 0;
204 }
205
206 return result;
207 }
208
209
210
211
212 // Allocate space for a node in the list used in DeletRect to
213 // store Nodes that are too empty.
214 //
Xastir_RTreeNewListNode(void)215 static struct ListNode * Xastir_RTreeNewListNode(void)
216 {
217 return (struct ListNode *) malloc(sizeof(struct ListNode));
218 //return new ListNode;
219 }
220
221
Xastir_RTreeFreeListNode(struct ListNode * p)222 static void Xastir_RTreeFreeListNode(struct ListNode *p)
223 {
224 free(p);
225 //delete(p);
226 }
227
228
229
230 // Add a node to the reinsertion list. All its branches will later
231 // be reinserted into the index structure.
232 //
Xastir_RTreeReInsert(struct Node * n,struct ListNode ** ee)233 static void Xastir_RTreeReInsert(struct Node *n, struct ListNode **ee)
234 {
235 struct ListNode *l;
236
237 l = Xastir_RTreeNewListNode();
238 l->node = n;
239 l->next = *ee;
240 *ee = l;
241 }
242
243
244 // Delete a rectangle from non-root part of an index structure.
245 // Called by Xastir_RTreeDeleteRect. Descends tree recursively,
246 // merges branches on the way back up.
247 // Returns 1 if record not found, 0 if success.
248 //
249 static int
Xastir_RTreeDeleteRect2(struct Rect * R,void * Tid,struct Node * N,struct ListNode ** Ee)250 Xastir_RTreeDeleteRect2(struct Rect *R, void *Tid, struct Node *N, struct ListNode **Ee)
251 {
252 struct Rect *r = R;
253 void *tid = Tid;
254 struct Node *n = N;
255 struct ListNode **ee = Ee;
256 int i;
257
258 assert(r && n && ee);
259 assert(tid != NULL);
260 assert(n->level >= 0);
261
262 if (n->level > 0) // not a leaf node
263 {
264 for (i = 0; i < Xastir_NODECARD; i++)
265 {
266 if (n->branch[i].child && Xastir_RTreeOverlap(r, &(n->branch[i].rect)))
267 {
268 if (!Xastir_RTreeDeleteRect2(r, tid, n->branch[i].child, ee))
269 {
270 if (n->branch[i].child->count >= MinNodeFill)
271 n->branch[i].rect = Xastir_RTreeNodeCover(
272 n->branch[i].child);
273 else
274 {
275 // not enough entries in child,
276 // eliminate child node
277 //
278 Xastir_RTreeReInsert(n->branch[i].child, ee);
279 Xastir_RTreeDisconnectBranch(n, i);
280 }
281 return 0;
282 }
283 }
284 }
285 return 1;
286 }
287 else // a leaf node
288 {
289 for (i = 0; i < Xastir_LEAFCARD; i++)
290 {
291 if (n->branch[i].child &&
292 n->branch[i].child == (struct Node *) tid)
293 {
294 Xastir_RTreeDisconnectBranch(n, i);
295 return 0;
296 }
297 }
298 return 1;
299 }
300 }
301
302
303
304 // Delete a data rectangle from an index structure.
305 // Pass in a pointer to a Rect, the tid of the record, ptr to ptr to root node.
306 // Returns 1 if record not found, 0 if success.
307 // Xastir_RTreeDeleteRect provides for eliminating the root.
308 //
Xastir_RTreeDeleteRect(struct Rect * R,void * Tid,struct Node ** Nn)309 int Xastir_RTreeDeleteRect(struct Rect *R, void *Tid, struct Node**Nn)
310 {
311 struct Rect *r = R;
312 void *tid = Tid;
313 struct Node **nn = Nn;
314 int i;
315 struct Node *tmp_nptr=NULL; // Original superliminal.com
316 // source did not initialize.
317 // Code analysis says shouldn't
318 // matter, but let's initialize
319 // to shut up GCC
320 struct ListNode *reInsertList = NULL;
321 struct ListNode *e;
322
323 assert(r && nn);
324 assert(*nn);
325 assert(tid != NULL);
326
327 if (!Xastir_RTreeDeleteRect2(r, tid, *nn, &reInsertList))
328 {
329 /* found and deleted a data item */
330
331 /* reinsert any branches from eliminated nodes */
332 while (reInsertList)
333 {
334 tmp_nptr = reInsertList->node;
335 for (i = 0; i < MAXKIDS(tmp_nptr); i++)
336 {
337 if (tmp_nptr->branch[i].child)
338 {
339 Xastir_RTreeInsertRect(
340 &(tmp_nptr->branch[i].rect),
341 tmp_nptr->branch[i].child,
342 nn,
343 tmp_nptr->level);
344 }
345 }
346 e = reInsertList;
347 reInsertList = reInsertList->next;
348 Xastir_RTreeFreeNode(e->node);
349 Xastir_RTreeFreeListNode(e);
350 }
351
352 /* check for redundant root (not leaf, 1 child) and eliminate
353 */
354 if ((*nn)->count == 1 && (*nn)->level > 0)
355 {
356 for (i = 0; i < Xastir_NODECARD; i++)
357 {
358 tmp_nptr = (*nn)->branch[i].child;
359 if(tmp_nptr)
360 {
361 break;
362 }
363 }
364 assert(tmp_nptr);
365 Xastir_RTreeFreeNode(*nn);
366 *nn = tmp_nptr;
367 }
368 return 0;
369 }
370 else
371 {
372 return 1;
373 }
374 }
375