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