PGE Engine
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Macros Pages
RTree.h
1 #ifndef RTREE_H
2 #define RTREE_H
3 
4 // NOTE This file compiles under MSVC 6 SP5 and MSVC .Net 2003 it may not work on other compilers without modification.
5 
6 // NOTE These next few lines may be win32 specific, you may need to modify them to compile on other platform
7 #include <stdio.h>
8 #include <math.h>
9 #include <assert.h>
10 #include <stdlib.h>
11 
12 #include <algorithm>
13 
14 #define ASSERT assert // RTree uses ASSERT( condition )
15 #ifndef Min
16  #define Min std::min
17 #endif //Min
18 #ifndef Max
19  #define Max std::max
20 #endif //Max
21 
22 //
23 // RTree.h
24 //
25 
26 #define RTREE_TEMPLATE template<class DATATYPE, class ELEMTYPE, int NUMDIMS, class ELEMTYPEREAL, int TMAXNODES, int TMINNODES>
27 #define RTREE_QUAL RTree<DATATYPE, ELEMTYPE, NUMDIMS, ELEMTYPEREAL, TMAXNODES, TMINNODES>
28 
29 #define RTREE_DONT_USE_MEMPOOLS // This version does not contain a fixed memory allocator, fill in lines with EXAMPLE to implement one.
30 #define RTREE_USE_SPHERICAL_VOLUME // Better split classification, may be slower on some systems
31 
32 // Fwd decl
33 class RTFileStream; // File I/O helper class, look below for implementation and notes.
34 
35 
52 template<class DATATYPE, class ELEMTYPE, int NUMDIMS,
53  class ELEMTYPEREAL = ELEMTYPE, int TMAXNODES = 8, int TMINNODES = TMAXNODES / 2>
54 class RTree
55 {
56 protected:
57 
58  struct Node; // Fwd decl. Used by other internal structs and iterator
59 
60 public:
61 
62  // These constant must be declared after Branch and before Node struct
63  // Stuck up here for MSVC 6 compiler. NSVC .NET 2003 is much happier.
64  enum
65  {
66  MAXNODES = TMAXNODES,
67  MINNODES = TMINNODES,
68  };
69 
70  typedef bool (*t_resultCallback)(DATATYPE, void*);
71 
72 public:
73 
74  RTree();
75  virtual ~RTree();
76 
81  void Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId);
82 
87  void Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId);
88 
96  int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], t_resultCallback a_resultCallback, void* a_context);
97 
99  void RemoveAll();
100 
102  int Count();
103 
105  bool Load(const char* a_fileName);
107  bool Load(RTFileStream& a_stream);
108 
109 
111  bool Save(const char* a_fileName);
113  bool Save(RTFileStream& a_stream);
114 
116  class Iterator
117  {
118  private:
119 
120  enum { MAX_STACK = 32 }; // Max stack size. Allows almost n^32 where n is number of branches in node
121 
122  struct StackElement
123  {
124  Node* m_node;
125  int m_branchIndex;
126  };
127 
128  public:
129 
130  Iterator() { Init(); }
131 
132  ~Iterator() { }
133 
135  bool IsNull() { return (m_tos <= 0); }
136 
138  bool IsNotNull() { return (m_tos > 0); }
139 
141  DATATYPE& operator*()
142  {
143  ASSERT(IsNotNull());
144  StackElement& curTos = m_stack[m_tos - 1];
145  return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
146  }
147 
149  const DATATYPE& operator*() const
150  {
151  ASSERT(IsNotNull());
152  StackElement& curTos = m_stack[m_tos - 1];
153  return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
154  }
155 
157  bool operator++() { return FindNextData(); }
158 
160  void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
161  {
162  ASSERT(IsNotNull());
163  StackElement& curTos = m_stack[m_tos - 1];
164  Branch& curBranch = curTos.m_node->m_branch[curTos.m_branchIndex];
165 
166  for(int index = 0; index < NUMDIMS; ++index)
167  {
168  a_min[index] = curBranch.m_rect.m_min[index];
169  a_max[index] = curBranch.m_rect.m_max[index];
170  }
171  }
172 
173  private:
174 
176  void Init() { m_tos = 0; }
177 
179  bool FindNextData()
180  {
181  for(;;)
182  {
183  if(m_tos <= 0)
184  {
185  return false;
186  }
187  StackElement curTos = Pop(); // Copy stack top cause it may change as we use it
188 
189  if(curTos.m_node->IsLeaf())
190  {
191  // Keep walking through data while we can
192  if(curTos.m_branchIndex+1 < curTos.m_node->m_count)
193  {
194  // There is more data, just point to the next one
195  Push(curTos.m_node, curTos.m_branchIndex + 1);
196  return true;
197  }
198  // No more data, so it will fall back to previous level
199  }
200  else
201  {
202  if(curTos.m_branchIndex+1 < curTos.m_node->m_count)
203  {
204  // Push sibling on for future tree walk
205  // This is the 'fall back' node when we finish with the current level
206  Push(curTos.m_node, curTos.m_branchIndex + 1);
207  }
208  // Since cur node is not a leaf, push first of next level to get deeper into the tree
209  Node* nextLevelnode = curTos.m_node->m_branch[curTos.m_branchIndex].m_child;
210  Push(nextLevelnode, 0);
211 
212  // If we pushed on a new leaf, exit as the data is ready at TOS
213  if(nextLevelnode->IsLeaf())
214  {
215  return true;
216  }
217  }
218  }
219  }
220 
222  void Push(Node* a_node, int a_branchIndex)
223  {
224  m_stack[m_tos].m_node = a_node;
225  m_stack[m_tos].m_branchIndex = a_branchIndex;
226  ++m_tos;
227  ASSERT(m_tos <= MAX_STACK);
228  }
229 
231  StackElement& Pop()
232  {
233  ASSERT(m_tos > 0);
234  --m_tos;
235  return m_stack[m_tos];
236  }
237 
238  StackElement m_stack[MAX_STACK];
239  int m_tos;
240 
241  friend class RTree; // Allow hiding of non-public functions while allowing manipulation by logical owner
242  };
243 
245  void GetFirst(Iterator& a_it)
246  {
247  a_it.Init();
248  Node* first = m_root;
249  while(first)
250  {
251  if(first->IsInternalNode() && first->m_count > 1)
252  {
253  a_it.Push(first, 1); // Descend sibling branch later
254  }
255  else if(first->IsLeaf())
256  {
257  if(first->m_count)
258  {
259  a_it.Push(first, 0);
260  }
261  break;
262  }
263  first = first->m_branch[0].m_child;
264  }
265  }
266 
268  void GetNext(Iterator& a_it) { ++a_it; }
269 
271  bool IsNull(Iterator& a_it) { return a_it.IsNull(); }
272 
274  DATATYPE& GetAt(Iterator& a_it) { return *a_it; }
275 
276 protected:
277 
279  struct Rect
280  {
281  ELEMTYPE m_min[NUMDIMS];
282  ELEMTYPE m_max[NUMDIMS];
283  };
284 
288  struct Branch
289  {
292  DATATYPE m_data;
293  };
294 
296  struct Node
297  {
298  bool IsInternalNode() { return (m_level > 0); } // Not a leaf, but a internal node
299  bool IsLeaf() { return (m_level == 0); } // A leaf, contains data
300 
301  int m_count;
302  int m_level;
304  };
305 
307  struct ListNode
308  {
311  };
312 
315  {
316  enum { NOT_TAKEN = -1 }; // indicates that position
317 
318  int m_partition[MAXNODES+1];
319  int m_total;
320  int m_minFill;
321  int m_count[2];
322  Rect m_cover[2];
323  ELEMTYPEREAL m_area[2];
324 
325  Branch m_branchBuf[MAXNODES+1];
326  int m_branchCount;
327  Rect m_coverSplit;
328  ELEMTYPEREAL m_coverSplitArea;
329  };
330 
331  Node* AllocNode();
332  void FreeNode(Node* a_node);
333  void InitNode(Node* a_node);
334  void InitRect(Rect* a_rect);
335  bool InsertRectRec(const Branch& a_branch, Node* a_node, Node** a_newNode, int a_level);
336  bool InsertRect(const Branch& a_branch, Node** a_root, int a_level);
337  Rect NodeCover(Node* a_node);
338  bool AddBranch(const Branch* a_branch, Node* a_node, Node** a_newNode);
339  void DisconnectBranch(Node* a_node, int a_index);
340  int PickBranch(const Rect* a_rect, Node* a_node);
341  Rect CombineRect(const Rect* a_rectA, const Rect* a_rectB);
342  void SplitNode(Node* a_node, const Branch* a_branch, Node** a_newNode);
343  ELEMTYPEREAL RectSphericalVolume(Rect* a_rect);
344  ELEMTYPEREAL RectVolume(Rect* a_rect);
345  ELEMTYPEREAL CalcRectVolume(Rect* a_rect);
346  void GetBranches(Node* a_node, const Branch* a_branch, PartitionVars* a_parVars);
347  void ChoosePartition(PartitionVars* a_parVars, int a_minFill);
348  void LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars);
349  void InitParVars(PartitionVars* a_parVars, int a_maxRects, int a_minFill);
350  void PickSeeds(PartitionVars* a_parVars);
351  void Classify(int a_index, int a_group, PartitionVars* a_parVars);
352  bool RemoveRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root);
353  bool RemoveRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node, ListNode** a_listNode);
354  ListNode* AllocListNode();
355  void FreeListNode(ListNode* a_listNode);
356  bool Overlap(Rect* a_rectA, Rect* a_rectB);
357  void ReInsert(Node* a_node, ListNode** a_listNode);
358  bool Search(Node* a_node, Rect* a_rect, int& a_foundCount, t_resultCallback a_resultCallback, void* a_context);
359  void RemoveAllRec(Node* a_node);
360  void Reset();
361  void CountRec(Node* a_node, int& a_count);
362 
363  bool SaveRec(Node* a_node, RTFileStream& a_stream);
364  bool LoadRec(Node* a_node, RTFileStream& a_stream);
365 
366  Node* m_root;
367  ELEMTYPEREAL m_unitSphereVolume;
368 };
369 
370 
371 // Because there is not stream support, this is a quick and dirty file I/O helper.
372 // Users will likely replace its usage with a Stream implementation from their favorite API.
374 {
375  FILE* m_file;
376 
377 public:
378 
379 
380  RTFileStream()
381  {
382  m_file = NULL;
383  }
384 
385  ~RTFileStream()
386  {
387  Close();
388  }
389 
390  bool OpenRead(const char* a_fileName)
391  {
392  m_file = fopen(a_fileName, "rb");
393  if(!m_file)
394  {
395  return false;
396  }
397  return true;
398  }
399 
400  bool OpenWrite(const char* a_fileName)
401  {
402  m_file = fopen(a_fileName, "wb");
403  if(!m_file)
404  {
405  return false;
406  }
407  return true;
408  }
409 
410  void Close()
411  {
412  if(m_file)
413  {
414  fclose(m_file);
415  m_file = NULL;
416  }
417  }
418 
419  template< typename TYPE >
420  size_t Write(const TYPE& a_value)
421  {
422  ASSERT(m_file);
423  return fwrite((void*)&a_value, sizeof(a_value), 1, m_file);
424  }
425 
426  template< typename TYPE >
427  size_t WriteArray(const TYPE* a_array, int a_count)
428  {
429  ASSERT(m_file);
430  return fwrite((void*)a_array, sizeof(TYPE) * a_count, 1, m_file);
431  }
432 
433  template< typename TYPE >
434  size_t Read(TYPE& a_value)
435  {
436  ASSERT(m_file);
437  return fread((void*)&a_value, sizeof(a_value), 1, m_file);
438  }
439 
440  template< typename TYPE >
441  size_t ReadArray(TYPE* a_array, int a_count)
442  {
443  ASSERT(m_file);
444  return fread((void*)a_array, sizeof(TYPE) * a_count, 1, m_file);
445  }
446 };
447 
448 
449 RTREE_TEMPLATE
450 RTREE_QUAL::RTree()
451 {
452  ASSERT(MAXNODES > MINNODES);
453  ASSERT(MINNODES > 0);
454 
455  // Precomputed volumes of the unit spheres for the first few dimensions
456  const float UNIT_SPHERE_VOLUMES[] = {
457  0.000000f, 2.000000f, 3.141593f, // Dimension 0,1,2
458  4.188790f, 4.934802f, 5.263789f, // Dimension 3,4,5
459  5.167713f, 4.724766f, 4.058712f, // Dimension 6,7,8
460  3.298509f, 2.550164f, 1.884104f, // Dimension 9,10,11
461  1.335263f, 0.910629f, 0.599265f, // Dimension 12,13,14
462  0.381443f, 0.235331f, 0.140981f, // Dimension 15,16,17
463  0.082146f, 0.046622f, 0.025807f, // Dimension 18,19,20
464  };
465 
466  m_root = AllocNode();
467  m_root->m_level = 0;
468  m_unitSphereVolume = (ELEMTYPEREAL)UNIT_SPHERE_VOLUMES[NUMDIMS];
469 }
470 
471 
472 RTREE_TEMPLATE
473 RTREE_QUAL::~RTree()
474 {
475  Reset(); // Free, or reset node memory
476 }
477 
478 
479 RTREE_TEMPLATE
480 void RTREE_QUAL::Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
481 {
482 #ifdef _DEBUG
483  for(int index=0; index<NUMDIMS; ++index)
484  {
485  ASSERT(a_min[index] <= a_max[index]);
486  }
487 #endif //_DEBUG
488 
489  Branch branch;
490  branch.m_data = a_dataId;
491  branch.m_child = NULL;
492 
493  for(int axis=0; axis<NUMDIMS; ++axis)
494  {
495  branch.m_rect.m_min[axis] = a_min[axis];
496  branch.m_rect.m_max[axis] = a_max[axis];
497  }
498 
499  InsertRect(branch, &m_root, 0);
500 }
501 
502 
503 RTREE_TEMPLATE
504 void RTREE_QUAL::Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
505 {
506 #ifdef _DEBUG
507  for(int index=0; index<NUMDIMS; ++index)
508  {
509  ASSERT(a_min[index] <= a_max[index]);
510  }
511 #endif //_DEBUG
512 
513  Rect rect;
514 
515  for(int axis=0; axis<NUMDIMS; ++axis)
516  {
517  rect.m_min[axis] = a_min[axis];
518  rect.m_max[axis] = a_max[axis];
519  }
520 
521  RemoveRect(&rect, a_dataId, &m_root);
522 }
523 
524 
525 RTREE_TEMPLATE
526 int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], t_resultCallback a_resultCallback, void* a_context)
527 {
528 #ifdef _DEBUG
529  for(int index=0; index<NUMDIMS; ++index)
530  {
531  ASSERT(a_min[index] <= a_max[index]);
532  }
533 #endif //_DEBUG
534 
535  Rect rect;
536 
537  for(int axis=0; axis<NUMDIMS; ++axis)
538  {
539  rect.m_min[axis] = a_min[axis];
540  rect.m_max[axis] = a_max[axis];
541  }
542 
543  // NOTE: May want to return search result another way, perhaps returning the number of found elements here.
544 
545  int foundCount = 0;
546  Search(m_root, &rect, foundCount, a_resultCallback, a_context);
547 
548  return foundCount;
549 }
550 
551 
552 RTREE_TEMPLATE
553 int RTREE_QUAL::Count()
554 {
555  int count = 0;
556  CountRec(m_root, count);
557 
558  return count;
559 }
560 
561 
562 
563 RTREE_TEMPLATE
564 void RTREE_QUAL::CountRec(Node* a_node, int& a_count)
565 {
566  if(a_node->IsInternalNode()) // not a leaf node
567  {
568  for(int index = 0; index < a_node->m_count; ++index)
569  {
570  CountRec(a_node->m_branch[index].m_child, a_count);
571  }
572  }
573  else // A leaf node
574  {
575  a_count += a_node->m_count;
576  }
577 }
578 
579 
580 RTREE_TEMPLATE
581 bool RTREE_QUAL::Load(const char* a_fileName)
582 {
583  RemoveAll(); // Clear existing tree
584 
585  RTFileStream stream;
586  if(!stream.OpenRead(a_fileName))
587  {
588  return false;
589  }
590 
591  bool result = Load(stream);
592 
593  stream.Close();
594 
595  return result;
596 }
597 
598 
599 
600 RTREE_TEMPLATE
601 bool RTREE_QUAL::Load(RTFileStream& a_stream)
602 {
603  // Write some kind of header
604  int _dataFileId = ('R'<<0)|('T'<<8)|('R'<<16)|('E'<<24);
605  int _dataSize = sizeof(DATATYPE);
606  int _dataNumDims = NUMDIMS;
607  int _dataElemSize = sizeof(ELEMTYPE);
608  int _dataElemRealSize = sizeof(ELEMTYPEREAL);
609  int _dataMaxNodes = TMAXNODES;
610  int _dataMinNodes = TMINNODES;
611 
612  int dataFileId = 0;
613  int dataSize = 0;
614  int dataNumDims = 0;
615  int dataElemSize = 0;
616  int dataElemRealSize = 0;
617  int dataMaxNodes = 0;
618  int dataMinNodes = 0;
619 
620  a_stream.Read(dataFileId);
621  a_stream.Read(dataSize);
622  a_stream.Read(dataNumDims);
623  a_stream.Read(dataElemSize);
624  a_stream.Read(dataElemRealSize);
625  a_stream.Read(dataMaxNodes);
626  a_stream.Read(dataMinNodes);
627 
628  bool result = false;
629 
630  // Test if header was valid and compatible
631  if( (dataFileId == _dataFileId)
632  && (dataSize == _dataSize)
633  && (dataNumDims == _dataNumDims)
634  && (dataElemSize == _dataElemSize)
635  && (dataElemRealSize == _dataElemRealSize)
636  && (dataMaxNodes == _dataMaxNodes)
637  && (dataMinNodes == _dataMinNodes)
638  )
639  {
640  // Recursively load tree
641  result = LoadRec(m_root, a_stream);
642  }
643 
644  return result;
645 }
646 
647 
648 RTREE_TEMPLATE
649 bool RTREE_QUAL::LoadRec(Node* a_node, RTFileStream& a_stream)
650 {
651  a_stream.Read(a_node->m_level);
652  a_stream.Read(a_node->m_count);
653 
654  if(a_node->IsInternalNode()) // not a leaf node
655  {
656  for(int index = 0; index < a_node->m_count; ++index)
657  {
658  Branch* curBranch = &a_node->m_branch[index];
659 
660  a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
661  a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
662 
663  curBranch->m_child = AllocNode();
664  LoadRec(curBranch->m_child, a_stream);
665  }
666  }
667  else // A leaf node
668  {
669  for(int index = 0; index < a_node->m_count; ++index)
670  {
671  Branch* curBranch = &a_node->m_branch[index];
672 
673  a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
674  a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
675 
676  a_stream.Read(curBranch->m_data);
677  }
678  }
679 
680  return true; // Should do more error checking on I/O operations
681 }
682 
683 
684 RTREE_TEMPLATE
685 bool RTREE_QUAL::Save(const char* a_fileName)
686 {
687  RTFileStream stream;
688  if(!stream.OpenWrite(a_fileName))
689  {
690  return false;
691  }
692 
693  bool result = Save(stream);
694 
695  stream.Close();
696 
697  return result;
698 }
699 
700 
701 RTREE_TEMPLATE
702 bool RTREE_QUAL::Save(RTFileStream& a_stream)
703 {
704  // Write some kind of header
705  int dataFileId = ('R'<<0)|('T'<<8)|('R'<<16)|('E'<<24);
706  int dataSize = sizeof(DATATYPE);
707  int dataNumDims = NUMDIMS;
708  int dataElemSize = sizeof(ELEMTYPE);
709  int dataElemRealSize = sizeof(ELEMTYPEREAL);
710  int dataMaxNodes = TMAXNODES;
711  int dataMinNodes = TMINNODES;
712 
713  a_stream.Write(dataFileId);
714  a_stream.Write(dataSize);
715  a_stream.Write(dataNumDims);
716  a_stream.Write(dataElemSize);
717  a_stream.Write(dataElemRealSize);
718  a_stream.Write(dataMaxNodes);
719  a_stream.Write(dataMinNodes);
720 
721  // Recursively save tree
722  bool result = SaveRec(m_root, a_stream);
723 
724  return result;
725 }
726 
727 
728 RTREE_TEMPLATE
729 bool RTREE_QUAL::SaveRec(Node* a_node, RTFileStream& a_stream)
730 {
731  a_stream.Write(a_node->m_level);
732  a_stream.Write(a_node->m_count);
733 
734  if(a_node->IsInternalNode()) // not a leaf node
735  {
736  for(int index = 0; index < a_node->m_count; ++index)
737  {
738  Branch* curBranch = &a_node->m_branch[index];
739 
740  a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
741  a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
742 
743  SaveRec(curBranch->m_child, a_stream);
744  }
745  }
746  else // A leaf node
747  {
748  for(int index = 0; index < a_node->m_count; ++index)
749  {
750  Branch* curBranch = &a_node->m_branch[index];
751 
752  a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
753  a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
754 
755  a_stream.Write(curBranch->m_data);
756  }
757  }
758 
759  return true; // Should do more error checking on I/O operations
760 }
761 
762 
763 RTREE_TEMPLATE
764 void RTREE_QUAL::RemoveAll()
765 {
766  // Delete all existing nodes
767  Reset();
768 
769  m_root = AllocNode();
770  m_root->m_level = 0;
771 }
772 
773 
774 RTREE_TEMPLATE
775 void RTREE_QUAL::Reset()
776 {
777 #ifdef RTREE_DONT_USE_MEMPOOLS
778  // Delete all existing nodes
779  RemoveAllRec(m_root);
780 #else // RTREE_DONT_USE_MEMPOOLS
781  // Just reset memory pools. We are not using complex types
782  // EXAMPLE
783 #endif // RTREE_DONT_USE_MEMPOOLS
784 }
785 
786 
787 RTREE_TEMPLATE
788 void RTREE_QUAL::RemoveAllRec(Node* a_node)
789 {
790  ASSERT(a_node);
791  ASSERT(a_node->m_level >= 0);
792 
793  if(a_node->IsInternalNode()) // This is an internal node in the tree
794  {
795  for(int index=0; index < a_node->m_count; ++index)
796  {
797  RemoveAllRec(a_node->m_branch[index].m_child);
798  }
799  }
800  FreeNode(a_node);
801 }
802 
803 
804 RTREE_TEMPLATE
805 typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode()
806 {
807  Node* newNode;
808 #ifdef RTREE_DONT_USE_MEMPOOLS
809  newNode = new Node;
810 #else // RTREE_DONT_USE_MEMPOOLS
811  // EXAMPLE
812 #endif // RTREE_DONT_USE_MEMPOOLS
813  InitNode(newNode);
814  return newNode;
815 }
816 
817 
818 RTREE_TEMPLATE
819 void RTREE_QUAL::FreeNode(Node* a_node)
820 {
821  ASSERT(a_node);
822 
823 #ifdef RTREE_DONT_USE_MEMPOOLS
824  delete a_node;
825 #else // RTREE_DONT_USE_MEMPOOLS
826  // EXAMPLE
827 #endif // RTREE_DONT_USE_MEMPOOLS
828 }
829 
830 
831 // Allocate space for a node in the list used in DeletRect to
832 // store Nodes that are too empty.
833 RTREE_TEMPLATE
834 typename RTREE_QUAL::ListNode* RTREE_QUAL::AllocListNode()
835 {
836 #ifdef RTREE_DONT_USE_MEMPOOLS
837  return new ListNode;
838 #else // RTREE_DONT_USE_MEMPOOLS
839  // EXAMPLE
840 #endif // RTREE_DONT_USE_MEMPOOLS
841 }
842 
843 
844 RTREE_TEMPLATE
845 void RTREE_QUAL::FreeListNode(ListNode* a_listNode)
846 {
847 #ifdef RTREE_DONT_USE_MEMPOOLS
848  delete a_listNode;
849 #else // RTREE_DONT_USE_MEMPOOLS
850  // EXAMPLE
851 #endif // RTREE_DONT_USE_MEMPOOLS
852 }
853 
854 
855 RTREE_TEMPLATE
856 void RTREE_QUAL::InitNode(Node* a_node)
857 {
858  a_node->m_count = 0;
859  a_node->m_level = -1;
860 }
861 
862 
863 RTREE_TEMPLATE
864 void RTREE_QUAL::InitRect(Rect* a_rect)
865 {
866  for(int index = 0; index < NUMDIMS; ++index)
867  {
868  a_rect->m_min[index] = (ELEMTYPE)0;
869  a_rect->m_max[index] = (ELEMTYPE)0;
870  }
871 }
872 
873 
874 // Inserts a new data rectangle into the index structure.
875 // Recursively descends tree, propagates splits back up.
876 // Returns 0 if node was not split. Old node updated.
877 // If node was split, returns 1 and sets the pointer pointed to by
878 // new_node to point to the new node. Old node updated to become one of two.
879 // The level argument specifies the number of steps up from the leaf
880 // level to insert; e.g. a data rectangle goes in at level = 0.
881 RTREE_TEMPLATE
882 bool RTREE_QUAL::InsertRectRec(const Branch& a_branch, Node* a_node, Node** a_newNode, int a_level)
883 {
884  ASSERT(a_node && a_newNode);
885  ASSERT(a_level >= 0 && a_level <= a_node->m_level);
886 
887  // recurse until we reach the correct level for the new record. data records
888  // will always be called with a_level == 0 (leaf)
889  if(a_node->m_level > a_level)
890  {
891  // Still above level for insertion, go down tree recursively
892  Node* otherNode;
893 
894  // find the optimal branch for this record
895  int index = PickBranch(&a_branch.m_rect, a_node);
896 
897  // recursively insert this record into the picked branch
898  bool childWasSplit = InsertRectRec(a_branch, a_node->m_branch[index].m_child, &otherNode, a_level);
899 
900  if (!childWasSplit)
901  {
902  // Child was not split. Merge the bounding box of the new record with the
903  // existing bounding box
904  a_node->m_branch[index].m_rect = CombineRect(&a_branch.m_rect, &(a_node->m_branch[index].m_rect));
905  return false;
906  }
907  else
908  {
909  // Child was split. The old branches are now re-partitioned to two nodes
910  // so we have to re-calculate the bounding boxes of each node
911  a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
912  Branch branch;
913  branch.m_child = otherNode;
914  branch.m_rect = NodeCover(otherNode);
915 
916  // The old node is already a child of a_node. Now add the newly-created
917  // node to a_node as well. a_node might be split because of that.
918  return AddBranch(&branch, a_node, a_newNode);
919  }
920  }
921  else if(a_node->m_level == a_level)
922  {
923  // We have reached level for insertion. Add rect, split if necessary
924  return AddBranch(&a_branch, a_node, a_newNode);
925  }
926  else
927  {
928  // Should never occur
929  ASSERT(0);
930  return false;
931  }
932 }
933 
934 
935 // Insert a data rectangle into an index structure.
936 // InsertRect provides for splitting the root;
937 // returns 1 if root was split, 0 if it was not.
938 // The level argument specifies the number of steps up from the leaf
939 // level to insert; e.g. a data rectangle goes in at level = 0.
940 // InsertRect2 does the recursion.
941 //
942 RTREE_TEMPLATE
943 bool RTREE_QUAL::InsertRect(const Branch& a_branch, Node** a_root, int a_level)
944 {
945  ASSERT(a_root);
946  ASSERT(a_level >= 0 && a_level <= (*a_root)->m_level);
947 #ifdef _DEBUG
948  for(int index=0; index < NUMDIMS; ++index)
949  {
950  ASSERT(a_branch.m_rect.m_min[index] <= a_branch.m_rect.m_max[index]);
951  }
952 #endif //_DEBUG
953 
954  Node* newNode;
955 
956  if(InsertRectRec(a_branch, *a_root, &newNode, a_level)) // Root split
957  {
958  // Grow tree taller and new root
959  Node* newRoot = AllocNode();
960  newRoot->m_level = (*a_root)->m_level + 1;
961 
962  Branch branch;
963 
964  // add old root node as a child of the new root
965  branch.m_rect = NodeCover(*a_root);
966  branch.m_child = *a_root;
967  AddBranch(&branch, newRoot, NULL);
968 
969  // add the split node as a child of the new root
970  branch.m_rect = NodeCover(newNode);
971  branch.m_child = newNode;
972  AddBranch(&branch, newRoot, NULL);
973 
974  // set the new root as the root node
975  *a_root = newRoot;
976 
977  return true;
978  }
979 
980  return false;
981 }
982 
983 
984 // Find the smallest rectangle that includes all rectangles in branches of a node.
985 RTREE_TEMPLATE
986 typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(Node* a_node)
987 {
988  ASSERT(a_node);
989 
990  Rect rect = a_node->m_branch[0].m_rect;
991  for(int index = 1; index < a_node->m_count; ++index)
992  {
993  rect = CombineRect(&rect, &(a_node->m_branch[index].m_rect));
994  }
995 
996  return rect;
997 }
998 
999 
1000 // Add a branch to a node. Split the node if necessary.
1001 // Returns 0 if node not split. Old node updated.
1002 // Returns 1 if node split, sets *new_node to address of new node.
1003 // Old node updated, becomes one of two.
1004 RTREE_TEMPLATE
1005 bool RTREE_QUAL::AddBranch(const Branch* a_branch, Node* a_node, Node** a_newNode)
1006 {
1007  ASSERT(a_branch);
1008  ASSERT(a_node);
1009 
1010  if(a_node->m_count < MAXNODES) // Split won't be necessary
1011  {
1012  a_node->m_branch[a_node->m_count] = *a_branch;
1013  ++a_node->m_count;
1014 
1015  return false;
1016  }
1017  else
1018  {
1019  ASSERT(a_newNode);
1020 
1021  SplitNode(a_node, a_branch, a_newNode);
1022  return true;
1023  }
1024 }
1025 
1026 
1027 // Disconnect a dependent node.
1028 // Caller must return (or stop using iteration index) after this as count has changed
1029 RTREE_TEMPLATE
1030 void RTREE_QUAL::DisconnectBranch(Node* a_node, int a_index)
1031 {
1032  ASSERT(a_node && (a_index >= 0) && (a_index < MAXNODES));
1033  ASSERT(a_node->m_count > 0);
1034 
1035  // Remove element by swapping with the last element to prevent gaps in array
1036  a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1];
1037 
1038  --a_node->m_count;
1039 }
1040 
1041 
1042 // Pick a branch. Pick the one that will need the smallest increase
1043 // in area to accomodate the new rectangle. This will result in the
1044 // least total area for the covering rectangles in the current node.
1045 // In case of a tie, pick the one which was smaller before, to get
1046 // the best resolution when searching.
1047 RTREE_TEMPLATE
1048 int RTREE_QUAL::PickBranch(const Rect* a_rect, Node* a_node)
1049 {
1050  ASSERT(a_rect && a_node);
1051 
1052  bool firstTime = true;
1053  ELEMTYPEREAL increase;
1054  ELEMTYPEREAL bestIncr = (ELEMTYPEREAL)-1;
1055  ELEMTYPEREAL area;
1056  ELEMTYPEREAL bestArea;
1057  int best=0;
1058  Rect tempRect;
1059 
1060  for(int index=0; index < a_node->m_count; ++index)
1061  {
1062  Rect* curRect = &a_node->m_branch[index].m_rect;
1063  area = CalcRectVolume(curRect);
1064  tempRect = CombineRect(a_rect, curRect);
1065  increase = CalcRectVolume(&tempRect) - area;
1066  if((increase < bestIncr) || firstTime)
1067  {
1068  best = index;
1069  bestArea = area;
1070  bestIncr = increase;
1071  firstTime = false;
1072  }
1073  else if((increase == bestIncr) && (area < bestArea))
1074  {
1075  best = index;
1076  bestArea = area;
1077  bestIncr = increase;
1078  }
1079  }
1080  return best;
1081 }
1082 
1083 
1084 // Combine two rectangles into larger one containing both
1085 RTREE_TEMPLATE
1086 typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect(const Rect* a_rectA, const Rect* a_rectB)
1087 {
1088  ASSERT(a_rectA && a_rectB);
1089 
1090  Rect newRect;
1091 
1092  for(int index = 0; index < NUMDIMS; ++index)
1093  {
1094  newRect.m_min[index] = Min(a_rectA->m_min[index], a_rectB->m_min[index]);
1095  newRect.m_max[index] = Max(a_rectA->m_max[index], a_rectB->m_max[index]);
1096  }
1097 
1098  return newRect;
1099 }
1100 
1101 
1102 
1103 // Split a node.
1104 // Divides the nodes branches and the extra one between two nodes.
1105 // Old node is one of the new ones, and one really new one is created.
1106 // Tries more than one method for choosing a partition, uses best result.
1107 RTREE_TEMPLATE
1108 void RTREE_QUAL::SplitNode(Node* a_node, const Branch* a_branch, Node** a_newNode)
1109 {
1110  ASSERT(a_node);
1111  ASSERT(a_branch);
1112 
1113  // Could just use local here, but member or external is faster since it is reused
1114  PartitionVars localVars;
1115  PartitionVars* parVars = &localVars;
1116 
1117  // Load all the branches into a buffer, initialize old node
1118  GetBranches(a_node, a_branch, parVars);
1119 
1120  // Find partition
1121  ChoosePartition(parVars, MINNODES);
1122 
1123  // Create a new node to hold (about) half of the branches
1124  *a_newNode = AllocNode();
1125  (*a_newNode)->m_level = a_node->m_level;
1126 
1127  // Put branches from buffer into 2 nodes according to the chosen partition
1128  a_node->m_count = 0;
1129  LoadNodes(a_node, *a_newNode, parVars);
1130 
1131  ASSERT((a_node->m_count + (*a_newNode)->m_count) == parVars->m_total);
1132 }
1133 
1134 
1135 // Calculate the n-dimensional volume of a rectangle
1136 RTREE_TEMPLATE
1137 ELEMTYPEREAL RTREE_QUAL::RectVolume(Rect* a_rect)
1138 {
1139  ASSERT(a_rect);
1140 
1141  ELEMTYPEREAL volume = (ELEMTYPEREAL)1;
1142 
1143  for(int index=0; index<NUMDIMS; ++index)
1144  {
1145  volume *= a_rect->m_max[index] - a_rect->m_min[index];
1146  }
1147 
1148  ASSERT(volume >= (ELEMTYPEREAL)0);
1149 
1150  return volume;
1151 }
1152 
1153 
1154 // The exact volume of the bounding sphere for the given Rect
1155 RTREE_TEMPLATE
1156 ELEMTYPEREAL RTREE_QUAL::RectSphericalVolume(Rect* a_rect)
1157 {
1158  ASSERT(a_rect);
1159 
1160  ELEMTYPEREAL sumOfSquares = (ELEMTYPEREAL)0;
1161  ELEMTYPEREAL radius;
1162 
1163  for(int index=0; index < NUMDIMS; ++index)
1164  {
1165  ELEMTYPEREAL halfExtent = ((ELEMTYPEREAL)a_rect->m_max[index] - (ELEMTYPEREAL)a_rect->m_min[index]) * 0.5f;
1166  sumOfSquares += halfExtent * halfExtent;
1167  }
1168 
1169  radius = (ELEMTYPEREAL)sqrt(sumOfSquares);
1170 
1171  // Pow maybe slow, so test for common dims like 2,3 and just use x*x, x*x*x.
1172  if(NUMDIMS == 3)
1173  {
1174  return (radius * radius * radius * m_unitSphereVolume);
1175  }
1176  else if(NUMDIMS == 2)
1177  {
1178  return (radius * radius * m_unitSphereVolume);
1179  }
1180  else
1181  {
1182  return (ELEMTYPEREAL)(pow(radius, NUMDIMS) * m_unitSphereVolume);
1183  }
1184 }
1185 
1186 
1187 // Use one of the methods to calculate retangle volume
1188 RTREE_TEMPLATE
1189 ELEMTYPEREAL RTREE_QUAL::CalcRectVolume(Rect* a_rect)
1190 {
1191 #ifdef RTREE_USE_SPHERICAL_VOLUME
1192  return RectSphericalVolume(a_rect); // Slower but helps certain merge cases
1193 #else // RTREE_USE_SPHERICAL_VOLUME
1194  return RectVolume(a_rect); // Faster but can cause poor merges
1195 #endif // RTREE_USE_SPHERICAL_VOLUME
1196 }
1197 
1198 
1199 // Load branch buffer with branches from full node plus the extra branch.
1200 RTREE_TEMPLATE
1201 void RTREE_QUAL::GetBranches(Node* a_node, const Branch* a_branch, PartitionVars* a_parVars)
1202 {
1203  ASSERT(a_node);
1204  ASSERT(a_branch);
1205 
1206  ASSERT(a_node->m_count == MAXNODES);
1207 
1208  // Load the branch buffer
1209  for(int index=0; index < MAXNODES; ++index)
1210  {
1211  a_parVars->m_branchBuf[index] = a_node->m_branch[index];
1212  }
1213  a_parVars->m_branchBuf[MAXNODES] = *a_branch;
1214  a_parVars->m_branchCount = MAXNODES + 1;
1215 
1216  // Calculate rect containing all in the set
1217  a_parVars->m_coverSplit = a_parVars->m_branchBuf[0].m_rect;
1218  for(int index=1; index < MAXNODES+1; ++index)
1219  {
1220  a_parVars->m_coverSplit = CombineRect(&a_parVars->m_coverSplit, &a_parVars->m_branchBuf[index].m_rect);
1221  }
1222  a_parVars->m_coverSplitArea = CalcRectVolume(&a_parVars->m_coverSplit);
1223 }
1224 
1225 
1226 // Method #0 for choosing a partition:
1227 // As the seeds for the two groups, pick the two rects that would waste the
1228 // most area if covered by a single rectangle, i.e. evidently the worst pair
1229 // to have in the same group.
1230 // Of the remaining, one at a time is chosen to be put in one of the two groups.
1231 // The one chosen is the one with the greatest difference in area expansion
1232 // depending on which group - the rect most strongly attracted to one group
1233 // and repelled from the other.
1234 // If one group gets too full (more would force other group to violate min
1235 // fill requirement) then other group gets the rest.
1236 // These last are the ones that can go in either group most easily.
1237 RTREE_TEMPLATE
1238 void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars, int a_minFill)
1239 {
1240  ASSERT(a_parVars);
1241 
1242  ELEMTYPEREAL biggestDiff;
1243  int group, chosen=0, betterGroup=0;
1244 
1245  InitParVars(a_parVars, a_parVars->m_branchCount, a_minFill);
1246  PickSeeds(a_parVars);
1247 
1248  while (((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
1249  && (a_parVars->m_count[0] < (a_parVars->m_total - a_parVars->m_minFill))
1250  && (a_parVars->m_count[1] < (a_parVars->m_total - a_parVars->m_minFill)))
1251  {
1252  biggestDiff = (ELEMTYPEREAL) -1;
1253  for(int index=0; index<a_parVars->m_total; ++index)
1254  {
1255  if(PartitionVars::NOT_TAKEN == a_parVars->m_partition[index])
1256  {
1257  Rect* curRect = &a_parVars->m_branchBuf[index].m_rect;
1258  Rect rect0 = CombineRect(curRect, &a_parVars->m_cover[0]);
1259  Rect rect1 = CombineRect(curRect, &a_parVars->m_cover[1]);
1260  ELEMTYPEREAL growth0 = CalcRectVolume(&rect0) - a_parVars->m_area[0];
1261  ELEMTYPEREAL growth1 = CalcRectVolume(&rect1) - a_parVars->m_area[1];
1262  ELEMTYPEREAL diff = growth1 - growth0;
1263  if(diff >= 0)
1264  {
1265  group = 0;
1266  }
1267  else
1268  {
1269  group = 1;
1270  diff = -diff;
1271  }
1272 
1273  if(diff > biggestDiff)
1274  {
1275  biggestDiff = diff;
1276  chosen = index;
1277  betterGroup = group;
1278  }
1279  else if((diff == biggestDiff) && (a_parVars->m_count[group] < a_parVars->m_count[betterGroup]))
1280  {
1281  chosen = index;
1282  betterGroup = group;
1283  }
1284  }
1285  }
1286  Classify(chosen, betterGroup, a_parVars);
1287  }
1288 
1289  // If one group too full, put remaining rects in the other
1290  if((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
1291  {
1292  if(a_parVars->m_count[0] >= a_parVars->m_total - a_parVars->m_minFill)
1293  {
1294  group = 1;
1295  }
1296  else
1297  {
1298  group = 0;
1299  }
1300  for(int index=0; index<a_parVars->m_total; ++index)
1301  {
1302  if(PartitionVars::NOT_TAKEN == a_parVars->m_partition[index])
1303  {
1304  Classify(index, group, a_parVars);
1305  }
1306  }
1307  }
1308 
1309  ASSERT((a_parVars->m_count[0] + a_parVars->m_count[1]) == a_parVars->m_total);
1310  ASSERT((a_parVars->m_count[0] >= a_parVars->m_minFill) &&
1311  (a_parVars->m_count[1] >= a_parVars->m_minFill));
1312 }
1313 
1314 
1315 // Copy branches from the buffer into two nodes according to the partition.
1316 RTREE_TEMPLATE
1317 void RTREE_QUAL::LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars)
1318 {
1319  ASSERT(a_nodeA);
1320  ASSERT(a_nodeB);
1321  ASSERT(a_parVars);
1322 
1323  for(int index=0; index < a_parVars->m_total; ++index)
1324  {
1325  ASSERT(a_parVars->m_partition[index] == 0 || a_parVars->m_partition[index] == 1);
1326 
1327  int targetNodeIndex = a_parVars->m_partition[index];
1328  Node* targetNodes[] = {a_nodeA, a_nodeB};
1329 
1330  // It is assured that AddBranch here will not cause a node split.
1331  bool nodeWasSplit = AddBranch(&a_parVars->m_branchBuf[index], targetNodes[targetNodeIndex], NULL);
1332  ASSERT(!nodeWasSplit);
1333  }
1334 }
1335 
1336 
1337 // Initialize a PartitionVars structure.
1338 RTREE_TEMPLATE
1339 void RTREE_QUAL::InitParVars(PartitionVars* a_parVars, int a_maxRects, int a_minFill)
1340 {
1341  ASSERT(a_parVars);
1342 
1343  a_parVars->m_count[0] = a_parVars->m_count[1] = 0;
1344  a_parVars->m_area[0] = a_parVars->m_area[1] = (ELEMTYPEREAL)0;
1345  a_parVars->m_total = a_maxRects;
1346  a_parVars->m_minFill = a_minFill;
1347  for(int index=0; index < a_maxRects; ++index)
1348  {
1349  a_parVars->m_partition[index] = PartitionVars::NOT_TAKEN;
1350  }
1351 }
1352 
1353 
1354 RTREE_TEMPLATE
1355 void RTREE_QUAL::PickSeeds(PartitionVars* a_parVars)
1356 {
1357  int seed0=0, seed1=0;
1358  ELEMTYPEREAL worst, waste;
1359  ELEMTYPEREAL area[MAXNODES+1];
1360 
1361  for(int index=0; index<a_parVars->m_total; ++index)
1362  {
1363  area[index] = CalcRectVolume(&a_parVars->m_branchBuf[index].m_rect);
1364  }
1365 
1366  worst = -a_parVars->m_coverSplitArea - 1;
1367  for(int indexA=0; indexA < a_parVars->m_total-1; ++indexA)
1368  {
1369  for(int indexB = indexA+1; indexB < a_parVars->m_total; ++indexB)
1370  {
1371  Rect oneRect = CombineRect(&a_parVars->m_branchBuf[indexA].m_rect, &a_parVars->m_branchBuf[indexB].m_rect);
1372  waste = CalcRectVolume(&oneRect) - area[indexA] - area[indexB];
1373  if(waste > worst)
1374  {
1375  worst = waste;
1376  seed0 = indexA;
1377  seed1 = indexB;
1378  }
1379  }
1380  }
1381 
1382  Classify(seed0, 0, a_parVars);
1383  Classify(seed1, 1, a_parVars);
1384 }
1385 
1386 
1387 // Put a branch in one of the groups.
1388 RTREE_TEMPLATE
1389 void RTREE_QUAL::Classify(int a_index, int a_group, PartitionVars* a_parVars)
1390 {
1391  ASSERT(a_parVars);
1392  ASSERT(PartitionVars::NOT_TAKEN == a_parVars->m_partition[a_index]);
1393 
1394  a_parVars->m_partition[a_index] = a_group;
1395 
1396  // Calculate combined rect
1397  if (a_parVars->m_count[a_group] == 0)
1398  {
1399  a_parVars->m_cover[a_group] = a_parVars->m_branchBuf[a_index].m_rect;
1400  }
1401  else
1402  {
1403  a_parVars->m_cover[a_group] = CombineRect(&a_parVars->m_branchBuf[a_index].m_rect, &a_parVars->m_cover[a_group]);
1404  }
1405 
1406  // Calculate volume of combined rect
1407  a_parVars->m_area[a_group] = CalcRectVolume(&a_parVars->m_cover[a_group]);
1408 
1409  ++a_parVars->m_count[a_group];
1410 }
1411 
1412 
1413 // Delete a data rectangle from an index structure.
1414 // Pass in a pointer to a Rect, the tid of the record, ptr to ptr to root node.
1415 // Returns 1 if record not found, 0 if success.
1416 // RemoveRect provides for eliminating the root.
1417 RTREE_TEMPLATE
1418 bool RTREE_QUAL::RemoveRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root)
1419 {
1420  ASSERT(a_rect && a_root);
1421  ASSERT(*a_root);
1422 
1423  ListNode* reInsertList = NULL;
1424 
1425  if(!RemoveRectRec(a_rect, a_id, *a_root, &reInsertList))
1426  {
1427  // Found and deleted a data item
1428  // Reinsert any branches from eliminated nodes
1429  while(reInsertList)
1430  {
1431  Node* tempNode = reInsertList->m_node;
1432 
1433  for(int index = 0; index < tempNode->m_count; ++index)
1434  {
1435  // TODO go over this code. should I use (tempNode->m_level - 1)?
1436  InsertRect(tempNode->m_branch[index],
1437  a_root,
1438  tempNode->m_level);
1439  }
1440 
1441  ListNode* remLNode = reInsertList;
1442  reInsertList = reInsertList->m_next;
1443 
1444  FreeNode(remLNode->m_node);
1445  FreeListNode(remLNode);
1446  }
1447 
1448  // Check for redundant root (not leaf, 1 child) and eliminate TODO replace
1449  // if with while? In case there is a whole branch of redundant roots...
1450  if((*a_root)->m_count == 1 && (*a_root)->IsInternalNode())
1451  {
1452  Node* tempNode = (*a_root)->m_branch[0].m_child;
1453 
1454  ASSERT(tempNode);
1455  FreeNode(*a_root);
1456  *a_root = tempNode;
1457  }
1458  return false;
1459  }
1460  else
1461  {
1462  return true;
1463  }
1464 }
1465 
1466 
1467 // Delete a rectangle from non-root part of an index structure.
1468 // Called by RemoveRect. Descends tree recursively,
1469 // merges branches on the way back up.
1470 // Returns 1 if record not found, 0 if success.
1471 RTREE_TEMPLATE
1472 bool RTREE_QUAL::RemoveRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node, ListNode** a_listNode)
1473 {
1474  ASSERT(a_rect && a_node && a_listNode);
1475  ASSERT(a_node->m_level >= 0);
1476 
1477  if(a_node->IsInternalNode()) // not a leaf node
1478  {
1479  for(int index = 0; index < a_node->m_count; ++index)
1480  {
1481  if(Overlap(a_rect, &(a_node->m_branch[index].m_rect)))
1482  {
1483  if(!RemoveRectRec(a_rect, a_id, a_node->m_branch[index].m_child, a_listNode))
1484  {
1485  if(a_node->m_branch[index].m_child->m_count >= MINNODES)
1486  {
1487  // child removed, just resize parent rect
1488  a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
1489  }
1490  else
1491  {
1492  // child removed, not enough entries in node, eliminate node
1493  ReInsert(a_node->m_branch[index].m_child, a_listNode);
1494  DisconnectBranch(a_node, index); // Must return after this call as count has changed
1495  }
1496  return false;
1497  }
1498  }
1499  }
1500  return true;
1501  }
1502  else // A leaf node
1503  {
1504  for(int index = 0; index < a_node->m_count; ++index)
1505  {
1506  if(a_node->m_branch[index].m_data == a_id)
1507  {
1508  DisconnectBranch(a_node, index); // Must return after this call as count has changed
1509  return false;
1510  }
1511  }
1512  return true;
1513  }
1514 }
1515 
1516 
1517 // Decide whether two rectangles overlap.
1518 RTREE_TEMPLATE
1519 bool RTREE_QUAL::Overlap(Rect* a_rectA, Rect* a_rectB)
1520 {
1521  ASSERT(a_rectA && a_rectB);
1522 
1523  for(int index=0; index < NUMDIMS; ++index)
1524  {
1525  if (a_rectA->m_min[index] > a_rectB->m_max[index] ||
1526  a_rectB->m_min[index] > a_rectA->m_max[index])
1527  {
1528  return false;
1529  }
1530  }
1531  return true;
1532 }
1533 
1534 
1535 // Add a node to the reinsertion list. All its branches will later
1536 // be reinserted into the index structure.
1537 RTREE_TEMPLATE
1538 void RTREE_QUAL::ReInsert(Node* a_node, ListNode** a_listNode)
1539 {
1540  ListNode* newListNode;
1541 
1542  newListNode = AllocListNode();
1543  newListNode->m_node = a_node;
1544  newListNode->m_next = *a_listNode;
1545  *a_listNode = newListNode;
1546 }
1547 
1548 
1549 // Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
1550 RTREE_TEMPLATE
1551 bool RTREE_QUAL::Search(Node* a_node, Rect* a_rect, int& a_foundCount, t_resultCallback a_resultCallback, void* a_context)
1552 {
1553  ASSERT(a_node);
1554  ASSERT(a_node->m_level >= 0);
1555  ASSERT(a_rect);
1556 
1557  if(a_node->IsInternalNode())
1558  {
1559  // This is an internal node in the tree
1560  for(int index=0; index < a_node->m_count; ++index)
1561  {
1562  if(Overlap(a_rect, &a_node->m_branch[index].m_rect))
1563  {
1564  if(!Search(a_node->m_branch[index].m_child, a_rect, a_foundCount, a_resultCallback, a_context))
1565  {
1566  // The callback indicated to stop searching
1567  return false;
1568  }
1569  }
1570  }
1571  }
1572  else
1573  {
1574  // This is a leaf node
1575  for(int index=0; index < a_node->m_count; ++index)
1576  {
1577  if(Overlap(a_rect, &a_node->m_branch[index].m_rect))
1578  {
1579  DATATYPE& id = a_node->m_branch[index].m_data;
1580  ++a_foundCount;
1581 
1582  // NOTE: There are different ways to return results. Here's where to modify
1583  if(a_resultCallback)
1584  {
1585  if(!a_resultCallback(id, a_context))
1586  {
1587  return false; // Don't continue searching
1588  }
1589  }
1590  }
1591  }
1592  }
1593 
1594  return true; // Continue searching
1595 }
1596 
1597 
1598 #undef RTREE_TEMPLATE
1599 #undef RTREE_QUAL
1600 
1601 #endif //RTREE_H
1602 
Variables for finding a split partition.
Definition: RTree.h:314
int m_level
Leaf is zero, others positive.
Definition: RTree.h:302
int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], t_resultCallback a_resultCallback, void *a_context)
Branch m_branch[MAXNODES]
Branch.
Definition: RTree.h:303
ELEMTYPE m_min[NUMDIMS]
Min dimensions of bounding box.
Definition: RTree.h:281
DATATYPE & GetAt(Iterator &a_it)
Get object at iterator position.
Definition: RTree.h:274
int Count()
Count the data elements in this container. This is slow as no internal counter is maintained...
ELEMTYPEREAL m_unitSphereVolume
Unit sphere constant for required number of dimensions.
Definition: RTree.h:367
Definition: RTree.h:288
Node * m_root
Root of tree.
Definition: RTree.h:366
Definition: RTree.h:373
void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
Get the bounds for this node.
Definition: RTree.h:160
bool operator++()
Find the next data element.
Definition: RTree.h:157
void GetFirst(Iterator &a_it)
Get 'first' for iteration.
Definition: RTree.h:245
void GetNext(Iterator &a_it)
Get Next for iteration.
Definition: RTree.h:268
bool IsNull(Iterator &a_it)
Is iterator NULL, or at end?
Definition: RTree.h:271
A link list of nodes for reinsertion after a delete operation.
Definition: RTree.h:307
void Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)
Rect m_rect
Bounds.
Definition: RTree.h:290
Node * m_node
Node.
Definition: RTree.h:310
const DATATYPE & operator*() const
Access the current data element. Caller must be sure iterator is not NULL first.
Definition: RTree.h:149
Max elements in node.
Definition: RTree.h:66
void RemoveAll()
Remove all entries from tree.
Definition: RTree.h:54
DATATYPE & operator*()
Access the current data element. Caller must be sure iterator is not NULL first.
Definition: RTree.h:141
DATATYPE m_data
Data Id.
Definition: RTree.h:292
Definition: Test.cpp:14
int m_count
Count.
Definition: RTree.h:301
ListNode * m_next
Next in list.
Definition: RTree.h:309
ELEMTYPE m_max[NUMDIMS]
Max dimensions of bounding box.
Definition: RTree.h:282
bool Save(const char *a_fileName)
Save tree contents to file.
Node * m_child
Child node.
Definition: RTree.h:291
Node for each branch level.
Definition: RTree.h:296
bool Load(const char *a_fileName)
Load tree contents from file.
Iterator is not remove safe.
Definition: RTree.h:116
bool IsNull()
Is iterator invalid.
Definition: RTree.h:135
bool IsNotNull()
Is iterator pointing to valid data.
Definition: RTree.h:138
Minimal bounding rectangle (n-dimensional)
Definition: RTree.h:279
Min elements in node.
Definition: RTree.h:67
void Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)