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