VR-Forces Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
RTree.h
Go to the documentation of this file.
1 #pragma once
2 
4 
6 #include <stdio.h>
7 #include <math.h>
8 #include <assert.h>
9 #include <stdlib.h>
10 
11 #include <algorithm>
12 #include <functional>
13 #include <vector>
14 
15 namespace makVrf
16 {
17 
18 #define ASSERT assert
19 //#ifndef Min
20 //#endif //Min
22 //#ifndef Max
24 //#endif //Max
25 
29 
30 #define RTREE_TEMPLATE template<class DATATYPE, class ELEMTYPE, int NUMDIMS, class ELEMTYPEREAL, int TMAXNODES, int TMINNODES>
31 #define RTREE_QUAL RTree<DATATYPE, ELEMTYPE, NUMDIMS, ELEMTYPEREAL, TMAXNODES, TMINNODES>
32 
33 #define RTREE_DONT_USE_MEMPOOLS
34 #define RTREE_USE_SPHERICAL_VOLUME
35 
36 class RTFileStream;
38 
39 
56 template<class DATATYPE, class ELEMTYPE, int NUMDIMS,
57  class ELEMTYPEREAL = ELEMTYPE, int TMAXNODES = 8, int TMINNODES = TMAXNODES / 2>
58 class RTree
59 {
60  static_assert(std::numeric_limits<ELEMTYPEREAL>::is_iec559, "'ELEMTYPEREAL' accepts floating-point types only");
61 
62 protected:
63 
64  struct Node;
65 
66 public:
67 
70  enum
71  {
72  MAXNODES = TMAXNODES,
73  MINNODES = TMINNODES,
74  };
75 
76 public:
77 
78  RTree();
79  RTree(const RTree& other);
80  virtual ~RTree();
81 
86  void Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId);
87 
92  void Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId);
93 
101  int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], std::function<bool (const DATATYPE&)> callback) const;
102 
104  void RemoveAll();
105 
107  int Count();
108 
110  bool Load(const char* a_fileName);
112  bool Load(RTFileStream& a_stream);
113 
114 
116  bool Save(const char* a_fileName);
118  bool Save(RTFileStream& a_stream);
119 
121  class Iterator
122  {
123  private:
124 
125  enum { MAX_STACK = 32 };
126 
128  {
131  };
132 
133  public:
134 
135  Iterator() { Init(); }
136 
137  ~Iterator() { }
138 
140  bool IsNull() { return (m_tos <= 0); }
141 
143  bool IsNotNull() { return (m_tos > 0); }
144 
146  DATATYPE& operator*()
147  {
148  ASSERT(IsNotNull());
149  StackElement& curTos = m_stack[m_tos - 1];
150  return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
151  }
152 
154  const DATATYPE& operator*() const
155  {
156  ASSERT(IsNotNull());
157  StackElement& curTos = m_stack[m_tos - 1];
158  return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
159  }
160 
162  bool operator++() { return FindNextData(); }
163 
165  void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
166  {
167  ASSERT(IsNotNull());
168  StackElement& curTos = m_stack[m_tos - 1];
169  Branch& curBranch = curTos.m_node->m_branch[curTos.m_branchIndex];
170 
171  for(int index = 0; index < NUMDIMS; ++index)
172  {
173  a_min[index] = curBranch.m_rect.m_min[index];
174  a_max[index] = curBranch.m_rect.m_max[index];
175  }
176  }
177 
178  private:
179 
181  void Init() { m_tos = 0; }
182 
185  {
186  for(;;)
187  {
188  if(m_tos <= 0)
189  {
190  return false;
191  }
192  StackElement curTos = Pop();
193 
194  if(curTos.m_node->IsLeaf())
195  {
197  if(curTos.m_branchIndex+1 < curTos.m_node->m_count)
198  {
200  Push(curTos.m_node, curTos.m_branchIndex + 1);
201  return true;
202  }
204  }
205  else
206  {
207  if(curTos.m_branchIndex+1 < curTos.m_node->m_count)
208  {
211  Push(curTos.m_node, curTos.m_branchIndex + 1);
212  }
214  Node* nextLevelnode = curTos.m_node->m_branch[curTos.m_branchIndex].m_child;
215  Push(nextLevelnode, 0);
216 
218  if(nextLevelnode->IsLeaf())
219  {
220  return true;
221  }
222  }
223  }
224  }
225 
227  void Push(Node* a_node, int a_branchIndex)
228  {
229  m_stack[m_tos].m_node = a_node;
230  m_stack[m_tos].m_branchIndex = a_branchIndex;
231  ++m_tos;
232  ASSERT(m_tos <= MAX_STACK);
233  }
234 
237  {
238  ASSERT(m_tos > 0);
239  --m_tos;
240  return m_stack[m_tos];
241  }
242 
244  int m_tos;
245 
246  friend class RTree;
247  };
248 
250  void GetFirst(Iterator& a_it)
251  {
252  a_it.Init();
253  Node* first = m_root;
254  while(first)
255  {
256  if(first->IsInternalNode() && first->m_count > 1)
257  {
258  a_it.Push(first, 1);
259  }
260  else if(first->IsLeaf())
261  {
262  if(first->m_count)
263  {
264  a_it.Push(first, 0);
265  }
266  break;
267  }
268  first = first->m_branch[0].m_child;
269  }
270  }
271 
273  void GetNext(Iterator& a_it) { ++a_it; }
274 
276  bool IsNull(Iterator& a_it) { return a_it.IsNull(); }
277 
279  DATATYPE& GetAt(Iterator& a_it) { return *a_it; }
280 
281 protected:
282 
284  struct Rect
285  {
286  ELEMTYPE m_min[NUMDIMS];
287  ELEMTYPE m_max[NUMDIMS];
288  };
289 
293  struct Branch
294  {
297  DATATYPE m_data;
298  };
299 
301  struct Node
302  {
303  bool IsInternalNode() { return (m_level > 0); }
304  bool IsLeaf() { return (m_level == 0); }
305 
306  int m_count;
307  int m_level;
309  };
310 
312  struct ListNode
313  {
316  };
317 
320  {
321  enum { NOT_TAKEN = -1 };
322 
324  int m_total;
326  int m_count[2];
328  ELEMTYPEREAL m_area[2];
329 
333  ELEMTYPEREAL m_coverSplitArea;
334  };
335 
336  Node* AllocNode();
337  void FreeNode(Node* a_node);
338  void InitNode(Node* a_node);
339  void InitRect(Rect* a_rect);
340  bool InsertRectRec(const Branch& a_branch, Node* a_node, Node** a_newNode, int a_level);
341  bool InsertRect(const Branch& a_branch, Node** a_root, int a_level);
342  Rect NodeCover(Node* a_node);
343  bool AddBranch(const Branch* a_branch, Node* a_node, Node** a_newNode);
344  void DisconnectBranch(Node* a_node, int a_index);
345  int PickBranch(const Rect* a_rect, Node* a_node);
346  Rect CombineRect(const Rect* a_rectA, const Rect* a_rectB);
347  void SplitNode(Node* a_node, const Branch* a_branch, Node** a_newNode);
348  ELEMTYPEREAL RectSphericalVolume(Rect* a_rect);
349  ELEMTYPEREAL RectVolume(Rect* a_rect);
350  ELEMTYPEREAL CalcRectVolume(Rect* a_rect);
351  void GetBranches(Node* a_node, const Branch* a_branch, PartitionVars* a_parVars);
352  void ChoosePartition(PartitionVars* a_parVars, int a_minFill);
353  void LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars);
354  void InitParVars(PartitionVars* a_parVars, int a_maxRects, int a_minFill);
355  void PickSeeds(PartitionVars* a_parVars);
356  void Classify(int a_index, int a_group, PartitionVars* a_parVars);
357  bool RemoveRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root);
358  bool RemoveRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node, ListNode** a_listNode);
360  void FreeListNode(ListNode* a_listNode);
361  bool Overlap(Rect* a_rectA, Rect* a_rectB) const;
362  void ReInsert(Node* a_node, ListNode** a_listNode);
363  bool Search(Node* a_node, Rect* a_rect, int& a_foundCount, std::function<bool (const DATATYPE&)> callback) const;
364  void RemoveAllRec(Node* a_node);
365  void Reset();
366  void CountRec(Node* a_node, int& a_count);
367 
368  bool SaveRec(Node* a_node, RTFileStream& a_stream);
369  bool LoadRec(Node* a_node, RTFileStream& a_stream);
370  void CopyRec(Node* current, Node* other);
371 
372  Node* m_root;
373  ELEMTYPEREAL m_unitSphereVolume;
374 
375 public:
377  std::vector<Rect> ListTree() const;
378 };
379 
380 
384 {
385  FILE* m_file;
386 
387 public:
388 
389 
391  {
392  m_file = NULL;
393  }
394 
396  {
397  Close();
398  }
399 
400  bool Open(const char* a_fileName, const char* mode)
401  {
402 #if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)
403  return fopen_s(&m_file, a_fileName, mode) == 0;
404 #else
405  m_file = fopen(a_fileName, mode);
406  return m_file != nullptr;
407 #endif
408  }
409 
410  bool OpenRead(const char* a_fileName)
411  {
412  return this->Open(a_fileName, "rb");
413  }
414 
415  bool OpenWrite(const char* a_fileName)
416  {
417  return this->Open(a_fileName, "wb");
418  }
419 
420  void Close()
421  {
422  if(m_file)
423  {
424  fclose(m_file);
425  m_file = NULL;
426  }
427  }
428 
429  template< typename TYPE >
430  size_t Write(const TYPE& a_value)
431  {
432  ASSERT(m_file);
433  return fwrite((void*)&a_value, sizeof(a_value), 1, m_file);
434  }
435 
436  template< typename TYPE >
437  size_t WriteArray(const TYPE* a_array, int a_count)
438  {
439  ASSERT(m_file);
440  return fwrite((void*)a_array, sizeof(TYPE) * a_count, 1, m_file);
441  }
442 
443  template< typename TYPE >
444  size_t Read(TYPE& a_value)
445  {
446  ASSERT(m_file);
447  return fread((void*)&a_value, sizeof(a_value), 1, m_file);
448  }
449 
450  template< typename TYPE >
451  size_t ReadArray(TYPE* a_array, int a_count)
452  {
453  ASSERT(m_file);
454  return fread((void*)a_array, sizeof(TYPE) * a_count, 1, m_file);
455  }
456 };
457 
458 
460 RTREE_QUAL::RTree()
461 {
462  ASSERT(MAXNODES > MINNODES);
463  ASSERT(MINNODES > 0);
464 
466  const float UNIT_SPHERE_VOLUMES[] = {
467  0.000000f, 2.000000f, 3.141593f,
468  4.188790f, 4.934802f, 5.263789f,
469  5.167713f, 4.724766f, 4.058712f,
470  3.298509f, 2.550164f, 1.884104f,
471  1.335263f, 0.910629f, 0.599265f,
472  0.381443f, 0.235331f, 0.140981f,
473  0.082146f, 0.046622f, 0.025807f,
474  };
475 
476  m_root = AllocNode();
477  m_root->m_level = 0;
478  m_unitSphereVolume = (ELEMTYPEREAL)UNIT_SPHERE_VOLUMES[NUMDIMS];
479 }
480 
481 
483 RTREE_QUAL::RTree(const RTree& other) : RTree()
484 {
485  CopyRec(m_root, other.m_root);
486 }
487 
488 
490 RTREE_QUAL::~RTree()
491 {
492  Reset();
493 }
494 
495 
497 void RTREE_QUAL::Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
498 {
499 #ifdef _DEBUG
500  for(int index=0; index<NUMDIMS; ++index)
501  {
502  ASSERT(a_min[index] <= a_max[index]);
503  }
504 #endif //_DEBUG
505 
506  Branch branch;
507  branch.m_data = a_dataId;
508  branch.m_child = NULL;
509 
510  for(int axis=0; axis<NUMDIMS; ++axis)
511  {
512  branch.m_rect.m_min[axis] = a_min[axis];
513  branch.m_rect.m_max[axis] = a_max[axis];
514  }
515 
516  InsertRect(branch, &m_root, 0);
517 }
518 
519 
521 void RTREE_QUAL::Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
522 {
523 #ifdef _DEBUG
524  for(int index=0; index<NUMDIMS; ++index)
525  {
526  ASSERT(a_min[index] <= a_max[index]);
527  }
528 #endif //_DEBUG
529 
530  Rect rect;
531 
532  for(int axis=0; axis<NUMDIMS; ++axis)
533  {
534  rect.m_min[axis] = a_min[axis];
535  rect.m_max[axis] = a_max[axis];
536  }
537 
538  RemoveRect(&rect, a_dataId, &m_root);
539 }
540 
541 
543 int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], std::function<bool (const DATATYPE&)> callback) const
544 {
545 #ifdef _DEBUG
546  for(int index=0; index<NUMDIMS; ++index)
547  {
548  ASSERT(a_min[index] <= a_max[index]);
549  }
550 #endif //_DEBUG
551 
552  Rect rect;
553 
554  for(int axis=0; axis<NUMDIMS; ++axis)
555  {
556  rect.m_min[axis] = a_min[axis];
557  rect.m_max[axis] = a_max[axis];
558  }
559 
561 
562  int foundCount = 0;
563  Search(m_root, &rect, foundCount, callback);
564 
565  return foundCount;
566 }
567 
568 
570 int RTREE_QUAL::Count()
571 {
572  int count = 0;
573  CountRec(m_root, count);
574 
575  return count;
576 }
577 
578 
579 
581 void RTREE_QUAL::CountRec(Node* a_node, int& a_count)
582 {
583  if(a_node->IsInternalNode())
584  {
585  for(int index = 0; index < a_node->m_count; ++index)
586  {
587  CountRec(a_node->m_branch[index].m_child, a_count);
588  }
589  }
590  else
591  {
592  a_count += a_node->m_count;
593  }
594 }
595 
596 
598 bool RTREE_QUAL::Load(const char* a_fileName)
599 {
600  RemoveAll();
601 
602  RTFileStream stream;
603  if(!stream.OpenRead(a_fileName))
604  {
605  return false;
606  }
607 
608  bool result = Load(stream);
609 
610  stream.Close();
611 
612  return result;
613 }
614 
615 
616 
618 bool RTREE_QUAL::Load(RTFileStream& a_stream)
619 {
621  int _dataFileId = ('R'<<0)|('T'<<8)|('R'<<16)|('E'<<24);
622  int _dataSize = sizeof(DATATYPE);
623  int _dataNumDims = NUMDIMS;
624  int _dataElemSize = sizeof(ELEMTYPE);
625  int _dataElemRealSize = sizeof(ELEMTYPEREAL);
626  int _dataMaxNodes = TMAXNODES;
627  int _dataMinNodes = TMINNODES;
628 
629  int dataFileId = 0;
630  int dataSize = 0;
631  int dataNumDims = 0;
632  int dataElemSize = 0;
633  int dataElemRealSize = 0;
634  int dataMaxNodes = 0;
635  int dataMinNodes = 0;
636 
637  a_stream.Read(dataFileId);
638  a_stream.Read(dataSize);
639  a_stream.Read(dataNumDims);
640  a_stream.Read(dataElemSize);
641  a_stream.Read(dataElemRealSize);
642  a_stream.Read(dataMaxNodes);
643  a_stream.Read(dataMinNodes);
644 
645  bool result = false;
646 
648  if( (dataFileId == _dataFileId)
649  && (dataSize == _dataSize)
650  && (dataNumDims == _dataNumDims)
651  && (dataElemSize == _dataElemSize)
652  && (dataElemRealSize == _dataElemRealSize)
653  && (dataMaxNodes == _dataMaxNodes)
654  && (dataMinNodes == _dataMinNodes)
655  )
656  {
658  result = LoadRec(m_root, a_stream);
659  }
660 
661  return result;
662 }
663 
664 
666 bool RTREE_QUAL::LoadRec(Node* a_node, RTFileStream& a_stream)
667 {
668  a_stream.Read(a_node->m_level);
669  a_stream.Read(a_node->m_count);
670 
671  if(a_node->IsInternalNode())
672  {
673  for(int index = 0; index < a_node->m_count; ++index)
674  {
675  Branch* curBranch = &a_node->m_branch[index];
676 
677  a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
678  a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
679 
680  curBranch->m_child = AllocNode();
681  LoadRec(curBranch->m_child, a_stream);
682  }
683  }
684  else
685  {
686  for(int index = 0; index < a_node->m_count; ++index)
687  {
688  Branch* curBranch = &a_node->m_branch[index];
689 
690  a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
691  a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
692 
693  a_stream.Read(curBranch->m_data);
694  }
695  }
696 
697  return true;
698 }
699 
700 
702 void RTREE_QUAL::CopyRec(Node* current, Node* other)
703 {
704  current->m_level = other->m_level;
705  current->m_count = other->m_count;
706 
707  if(current->IsInternalNode())
708  {
709  for(int index = 0; index < current->m_count; ++index)
710  {
711  Branch* currentBranch = &current->m_branch[index];
712  Branch* otherBranch = &other->m_branch[index];
713 
714  std::copy(otherBranch->m_rect.m_min,
715  otherBranch->m_rect.m_min + NUMDIMS,
716  currentBranch->m_rect.m_min);
717 
718  std::copy(otherBranch->m_rect.m_max,
719  otherBranch->m_rect.m_max + NUMDIMS,
720  currentBranch->m_rect.m_max);
721 
722  currentBranch->m_child = AllocNode();
723  CopyRec(currentBranch->m_child, otherBranch->m_child);
724  }
725  }
726  else
727  {
728  for(int index = 0; index < current->m_count; ++index)
729  {
730  Branch* currentBranch = &current->m_branch[index];
731  Branch* otherBranch = &other->m_branch[index];
732 
733  std::copy(otherBranch->m_rect.m_min,
734  otherBranch->m_rect.m_min + NUMDIMS,
735  currentBranch->m_rect.m_min);
736 
737  std::copy(otherBranch->m_rect.m_max,
738  otherBranch->m_rect.m_max + NUMDIMS,
739  currentBranch->m_rect.m_max);
740 
741  currentBranch->m_data = otherBranch->m_data;
742  }
743  }
744 }
745 
746 
748 bool RTREE_QUAL::Save(const char* a_fileName)
749 {
750  RTFileStream stream;
751  if(!stream.OpenWrite(a_fileName))
752  {
753  return false;
754  }
755 
756  bool result = Save(stream);
757 
758  stream.Close();
759 
760  return result;
761 }
762 
763 
765 bool RTREE_QUAL::Save(RTFileStream& a_stream)
766 {
768  int dataFileId = ('R'<<0)|('T'<<8)|('R'<<16)|('E'<<24);
769  int dataSize = sizeof(DATATYPE);
770  int dataNumDims = NUMDIMS;
771  int dataElemSize = sizeof(ELEMTYPE);
772  int dataElemRealSize = sizeof(ELEMTYPEREAL);
773  int dataMaxNodes = TMAXNODES;
774  int dataMinNodes = TMINNODES;
775 
776  a_stream.Write(dataFileId);
777  a_stream.Write(dataSize);
778  a_stream.Write(dataNumDims);
779  a_stream.Write(dataElemSize);
780  a_stream.Write(dataElemRealSize);
781  a_stream.Write(dataMaxNodes);
782  a_stream.Write(dataMinNodes);
783 
785  bool result = SaveRec(m_root, a_stream);
786 
787  return result;
788 }
789 
790 
792 bool RTREE_QUAL::SaveRec(Node* a_node, RTFileStream& a_stream)
793 {
794  a_stream.Write(a_node->m_level);
795  a_stream.Write(a_node->m_count);
796 
797  if(a_node->IsInternalNode())
798  {
799  for(int index = 0; index < a_node->m_count; ++index)
800  {
801  Branch* curBranch = &a_node->m_branch[index];
802 
803  a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
804  a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
805 
806  SaveRec(curBranch->m_child, a_stream);
807  }
808  }
809  else
810  {
811  for(int index = 0; index < a_node->m_count; ++index)
812  {
813  Branch* curBranch = &a_node->m_branch[index];
814 
815  a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
816  a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
817 
818  a_stream.Write(curBranch->m_data);
819  }
820  }
821 
822  return true;
823 }
824 
825 
827 void RTREE_QUAL::RemoveAll()
828 {
830  Reset();
831 
832  m_root = AllocNode();
833  m_root->m_level = 0;
834 }
835 
836 
838 void RTREE_QUAL::Reset()
839 {
840 #ifdef RTREE_DONT_USE_MEMPOOLS
841  RemoveAllRec(m_root);
843 #else
844 #endif
847 }
848 
849 
851 void RTREE_QUAL::RemoveAllRec(Node* a_node)
852 {
853  ASSERT(a_node);
854  ASSERT(a_node->m_level >= 0);
855 
856  if(a_node->IsInternalNode())
857  {
858  for(int index=0; index < a_node->m_count; ++index)
859  {
860  RemoveAllRec(a_node->m_branch[index].m_child);
861  }
862  }
863  FreeNode(a_node);
864 }
865 
866 
868 typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode()
869 {
870  Node* newNode;
871 #ifdef RTREE_DONT_USE_MEMPOOLS
872  newNode = new Node;
873 #else
874 #endif
876  InitNode(newNode);
877  return newNode;
878 }
879 
880 
882 void RTREE_QUAL::FreeNode(Node* a_node)
883 {
884  ASSERT(a_node);
885 
886 #ifdef RTREE_DONT_USE_MEMPOOLS
887  delete a_node;
888 #else
889 #endif
891 }
892 
893 
897 typename RTREE_QUAL::ListNode* RTREE_QUAL::AllocListNode()
898 {
899 #ifdef RTREE_DONT_USE_MEMPOOLS
900  return new ListNode;
901 #else
902 #endif
904 }
905 
906 
908 void RTREE_QUAL::FreeListNode(ListNode* a_listNode)
909 {
910 #ifdef RTREE_DONT_USE_MEMPOOLS
911  delete a_listNode;
912 #else
913 #endif
915 }
916 
917 
919 void RTREE_QUAL::InitNode(Node* a_node)
920 {
921  a_node->m_count = 0;
922  a_node->m_level = -1;
923 }
924 
925 
927 void RTREE_QUAL::InitRect(Rect* a_rect)
928 {
929  for(int index = 0; index < NUMDIMS; ++index)
930  {
931  a_rect->m_min[index] = (ELEMTYPE)0;
932  a_rect->m_max[index] = (ELEMTYPE)0;
933  }
934 }
935 
936 
945 bool RTREE_QUAL::InsertRectRec(const Branch& a_branch, Node* a_node, Node** a_newNode, int a_level)
946 {
947  ASSERT(a_node && a_newNode);
948  ASSERT(a_level >= 0 && a_level <= a_node->m_level);
949 
952  if(a_node->m_level > a_level)
953  {
955  Node* otherNode;
956 
958  int index = PickBranch(&a_branch.m_rect, a_node);
959 
961  bool childWasSplit = InsertRectRec(a_branch, a_node->m_branch[index].m_child, &otherNode, a_level);
962 
963  if (!childWasSplit)
964  {
967  a_node->m_branch[index].m_rect = CombineRect(&a_branch.m_rect, &(a_node->m_branch[index].m_rect));
968  return false;
969  }
970  else
971  {
974  a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
975  Branch branch;
976  branch.m_child = otherNode;
977  branch.m_rect = NodeCover(otherNode);
978 
981  return AddBranch(&branch, a_node, a_newNode);
982  }
983  }
984  else if(a_node->m_level == a_level)
985  {
987  return AddBranch(&a_branch, a_node, a_newNode);
988  }
989  else
990  {
992  ASSERT(0);
993  return false;
994  }
995 }
996 
997 
1006 bool RTREE_QUAL::InsertRect(const Branch& a_branch, Node** a_root, int a_level)
1007 {
1008  ASSERT(a_root);
1009  ASSERT(a_level >= 0 && a_level <= (*a_root)->m_level);
1010 #ifdef _DEBUG
1011  for(int index=0; index < NUMDIMS; ++index)
1012  {
1013  ASSERT(a_branch.m_rect.m_min[index] <= a_branch.m_rect.m_max[index]);
1014  }
1015 #endif //_DEBUG
1016 
1017  Node* newNode;
1018 
1019  if(InsertRectRec(a_branch, *a_root, &newNode, a_level))
1020  {
1022  Node* newRoot = AllocNode();
1023  newRoot->m_level = (*a_root)->m_level + 1;
1024 
1025  Branch branch;
1026 
1028  branch.m_rect = NodeCover(*a_root);
1029  branch.m_child = *a_root;
1030  AddBranch(&branch, newRoot, NULL);
1031 
1033  branch.m_rect = NodeCover(newNode);
1034  branch.m_child = newNode;
1035  AddBranch(&branch, newRoot, NULL);
1036 
1038  *a_root = newRoot;
1039 
1040  return true;
1041  }
1042 
1043  return false;
1044 }
1045 
1046 
1049 typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(Node* a_node)
1050 {
1051  ASSERT(a_node);
1052 
1053  Rect rect = a_node->m_branch[0].m_rect;
1054  for(int index = 1; index < a_node->m_count; ++index)
1055  {
1056  rect = CombineRect(&rect, &(a_node->m_branch[index].m_rect));
1057  }
1058 
1059  return rect;
1060 }
1061 
1062 
1068 bool RTREE_QUAL::AddBranch(const Branch* a_branch, Node* a_node, Node** a_newNode)
1069 {
1070  ASSERT(a_branch);
1071  ASSERT(a_node);
1072 
1073  if(a_node->m_count < MAXNODES)
1074  {
1075  a_node->m_branch[a_node->m_count] = *a_branch;
1076  ++a_node->m_count;
1077 
1078  return false;
1079  }
1080  else
1081  {
1082  ASSERT(a_newNode);
1083 
1084  SplitNode(a_node, a_branch, a_newNode);
1085  return true;
1086  }
1087 }
1088 
1089 
1093 void RTREE_QUAL::DisconnectBranch(Node* a_node, int a_index)
1094 {
1095  ASSERT(a_node && (a_index >= 0) && (a_index < MAXNODES));
1096  ASSERT(a_node->m_count > 0);
1097 
1099  a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1];
1100 
1101  --a_node->m_count;
1102 }
1103 
1104 
1111 int RTREE_QUAL::PickBranch(const Rect* a_rect, Node* a_node)
1112 {
1113  ASSERT(a_rect && a_node);
1114 
1115  bool firstTime = true;
1116  ELEMTYPEREAL increase;
1117  ELEMTYPEREAL bestIncr = (ELEMTYPEREAL)-1;
1118  ELEMTYPEREAL area;
1119  ELEMTYPEREAL bestArea = (ELEMTYPEREAL)0;
1120  int best = 0;
1121  Rect tempRect;
1122 
1123  for(int index=0; index < a_node->m_count; ++index)
1124  {
1125  Rect* curRect = &a_node->m_branch[index].m_rect;
1126  area = CalcRectVolume(curRect);
1127  tempRect = CombineRect(a_rect, curRect);
1128  increase = CalcRectVolume(&tempRect) - area;
1129  if((increase < bestIncr) || firstTime)
1130  {
1131  best = index;
1132  bestArea = area;
1133  bestIncr = increase;
1134  firstTime = false;
1135  }
1136  else if((increase == bestIncr) && (area < bestArea))
1137  {
1138  best = index;
1139  bestArea = area;
1140  bestIncr = increase;
1141  }
1142  }
1143  return best;
1144 }
1145 
1146 
1149 typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect(const Rect* a_rectA, const Rect* a_rectB)
1150 {
1151  ASSERT(a_rectA && a_rectB);
1152 
1153  Rect newRect;
1154 
1155  for(int index = 0; index < NUMDIMS; ++index)
1156  {
1157  //newRect.m_min[index] = Min(a_rectA->m_min[index], a_rectB->m_min[index]);
1158  newRect.m_min[index] = std::min(a_rectA->m_min[index], a_rectB->m_min[index]);
1159  //newRect.m_max[index] = Max(a_rectA->m_max[index], a_rectB->m_max[index]);
1160  newRect.m_max[index] = std::max(a_rectA->m_max[index], a_rectB->m_max[index]);
1161  }
1162 
1163  return newRect;
1164 }
1165 
1166 
1167 
1173 void RTREE_QUAL::SplitNode(Node* a_node, const Branch* a_branch, Node** a_newNode)
1174 {
1175  ASSERT(a_node);
1176  ASSERT(a_branch);
1177 
1179  PartitionVars localVars;
1180  PartitionVars* parVars = &localVars;
1181 
1183  GetBranches(a_node, a_branch, parVars);
1184 
1186  ChoosePartition(parVars, MINNODES);
1187 
1189  *a_newNode = AllocNode();
1190  (*a_newNode)->m_level = a_node->m_level;
1191 
1193  a_node->m_count = 0;
1194  LoadNodes(a_node, *a_newNode, parVars);
1195 
1196  ASSERT((a_node->m_count + (*a_newNode)->m_count) == parVars->m_total);
1197 }
1198 
1199 
1202 ELEMTYPEREAL RTREE_QUAL::RectVolume(Rect* a_rect)
1203 {
1204  ASSERT(a_rect);
1205 
1206  ELEMTYPEREAL volume = (ELEMTYPEREAL)1;
1207 
1208  for(int index=0; index<NUMDIMS; ++index)
1209  {
1210  volume *= a_rect->m_max[index] - a_rect->m_min[index];
1211  }
1212 
1213  ASSERT(volume >= (ELEMTYPEREAL)0);
1214 
1215  return volume;
1216 }
1217 
1218 
1221 ELEMTYPEREAL RTREE_QUAL::RectSphericalVolume(Rect* a_rect)
1222 {
1223  ASSERT(a_rect);
1224 
1225  ELEMTYPEREAL sumOfSquares = (ELEMTYPEREAL)0;
1226  ELEMTYPEREAL radius;
1227 
1228  for(int index=0; index < NUMDIMS; ++index)
1229  {
1230  ELEMTYPEREAL halfExtent = ((ELEMTYPEREAL)a_rect->m_max[index] - (ELEMTYPEREAL)a_rect->m_min[index]) * (ELEMTYPEREAL)0.5;
1231  sumOfSquares += halfExtent * halfExtent;
1232  }
1233 
1234  radius = (ELEMTYPEREAL)sqrt(sumOfSquares);
1235 
1237  if(NUMDIMS == 3)
1238  {
1239  return (radius * radius * radius * m_unitSphereVolume);
1240  }
1241  else if(NUMDIMS == 2)
1242  {
1243  return (radius * radius * m_unitSphereVolume);
1244  }
1245  else
1246  {
1247  return (ELEMTYPEREAL)(pow(radius, NUMDIMS) * m_unitSphereVolume);
1248  }
1249 }
1250 
1251 
1254 ELEMTYPEREAL RTREE_QUAL::CalcRectVolume(Rect* a_rect)
1255 {
1256 #ifdef RTREE_USE_SPHERICAL_VOLUME
1257  return RectSphericalVolume(a_rect);
1258 #else
1259  return RectVolume(a_rect);
1260 #endif
1261 }
1262 
1263 
1266 void RTREE_QUAL::GetBranches(Node* a_node, const Branch* a_branch, PartitionVars* a_parVars)
1267 {
1268  ASSERT(a_node);
1269  ASSERT(a_branch);
1270 
1271  ASSERT(a_node->m_count == MAXNODES);
1272 
1274  for(int index=0; index < MAXNODES; ++index)
1275  {
1276  a_parVars->m_branchBuf[index] = a_node->m_branch[index];
1277  }
1278  a_parVars->m_branchBuf[MAXNODES] = *a_branch;
1279  a_parVars->m_branchCount = MAXNODES + 1;
1280 
1282  a_parVars->m_coverSplit = a_parVars->m_branchBuf[0].m_rect;
1283  for(int index=1; index < MAXNODES+1; ++index)
1284  {
1285  a_parVars->m_coverSplit = CombineRect(&a_parVars->m_coverSplit, &a_parVars->m_branchBuf[index].m_rect);
1286  }
1287  a_parVars->m_coverSplitArea = CalcRectVolume(&a_parVars->m_coverSplit);
1288 }
1289 
1290 
1303 void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars, int a_minFill)
1304 {
1305  ASSERT(a_parVars);
1306 
1307  ELEMTYPEREAL biggestDiff;
1308  int group, chosen = 0, betterGroup = 0;
1309 
1310  InitParVars(a_parVars, a_parVars->m_branchCount, a_minFill);
1311  PickSeeds(a_parVars);
1312 
1313  while (((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
1314  && (a_parVars->m_count[0] < (a_parVars->m_total - a_parVars->m_minFill))
1315  && (a_parVars->m_count[1] < (a_parVars->m_total - a_parVars->m_minFill)))
1316  {
1317  biggestDiff = (ELEMTYPEREAL) -1;
1318  for(int index=0; index<a_parVars->m_total; ++index)
1319  {
1320  if(PartitionVars::NOT_TAKEN == a_parVars->m_partition[index])
1321  {
1322  Rect* curRect = &a_parVars->m_branchBuf[index].m_rect;
1323  Rect rect0 = CombineRect(curRect, &a_parVars->m_cover[0]);
1324  Rect rect1 = CombineRect(curRect, &a_parVars->m_cover[1]);
1325  ELEMTYPEREAL growth0 = CalcRectVolume(&rect0) - a_parVars->m_area[0];
1326  ELEMTYPEREAL growth1 = CalcRectVolume(&rect1) - a_parVars->m_area[1];
1327  ELEMTYPEREAL diff = growth1 - growth0;
1328  if(diff >= 0)
1329  {
1330  group = 0;
1331  }
1332  else
1333  {
1334  group = 1;
1335  diff = -diff;
1336  }
1337 
1338  if(diff > biggestDiff)
1339  {
1340  biggestDiff = diff;
1341  chosen = index;
1342  betterGroup = group;
1343  }
1344  else if((diff == biggestDiff) && (a_parVars->m_count[group] < a_parVars->m_count[betterGroup]))
1345  {
1346  chosen = index;
1347  betterGroup = group;
1348  }
1349  }
1350  }
1351  Classify(chosen, betterGroup, a_parVars);
1352  }
1353 
1355  if((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
1356  {
1357  if(a_parVars->m_count[0] >= a_parVars->m_total - a_parVars->m_minFill)
1358  {
1359  group = 1;
1360  }
1361  else
1362  {
1363  group = 0;
1364  }
1365  for(int index=0; index<a_parVars->m_total; ++index)
1366  {
1367  if(PartitionVars::NOT_TAKEN == a_parVars->m_partition[index])
1368  {
1369  Classify(index, group, a_parVars);
1370  }
1371  }
1372  }
1373 
1374  ASSERT((a_parVars->m_count[0] + a_parVars->m_count[1]) == a_parVars->m_total);
1375  ASSERT((a_parVars->m_count[0] >= a_parVars->m_minFill) &&
1376  (a_parVars->m_count[1] >= a_parVars->m_minFill));
1377 }
1378 
1379 
1382 void RTREE_QUAL::LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars)
1383 {
1384  ASSERT(a_nodeA);
1385  ASSERT(a_nodeB);
1386  ASSERT(a_parVars);
1387 
1388  for(int index=0; index < a_parVars->m_total; ++index)
1389  {
1390  ASSERT(a_parVars->m_partition[index] == 0 || a_parVars->m_partition[index] == 1);
1391 
1392  int targetNodeIndex = a_parVars->m_partition[index];
1393  Node* targetNodes[] = {a_nodeA, a_nodeB};
1394 
1396  AddBranch(&a_parVars->m_branchBuf[index], targetNodes[targetNodeIndex], NULL);
1397  }
1398 }
1399 
1400 
1403 void RTREE_QUAL::InitParVars(PartitionVars* a_parVars, int a_maxRects, int a_minFill)
1404 {
1405  ASSERT(a_parVars);
1406 
1407  a_parVars->m_count[0] = a_parVars->m_count[1] = 0;
1408  a_parVars->m_area[0] = a_parVars->m_area[1] = (ELEMTYPEREAL)0;
1409  a_parVars->m_total = a_maxRects;
1410  a_parVars->m_minFill = a_minFill;
1411  for(int index=0; index < a_maxRects; ++index)
1412  {
1413  a_parVars->m_partition[index] = PartitionVars::NOT_TAKEN;
1414  }
1415 }
1416 
1417 
1419 void RTREE_QUAL::PickSeeds(PartitionVars* a_parVars)
1420 {
1421  int seed0 = 0, seed1 = 0;
1422  ELEMTYPEREAL worst, waste;
1423  ELEMTYPEREAL area[MAXNODES+1];
1424 
1425  for(int index=0; index<a_parVars->m_total; ++index)
1426  {
1427  area[index] = CalcRectVolume(&a_parVars->m_branchBuf[index].m_rect);
1428  }
1429 
1430  worst = -a_parVars->m_coverSplitArea - 1;
1431  for(int indexA=0; indexA < a_parVars->m_total-1; ++indexA)
1432  {
1433  for(int indexB = indexA+1; indexB < a_parVars->m_total; ++indexB)
1434  {
1435  Rect oneRect = CombineRect(&a_parVars->m_branchBuf[indexA].m_rect, &a_parVars->m_branchBuf[indexB].m_rect);
1436  waste = CalcRectVolume(&oneRect) - area[indexA] - area[indexB];
1437  if(waste > worst)
1438  {
1439  worst = waste;
1440  seed0 = indexA;
1441  seed1 = indexB;
1442  }
1443  }
1444  }
1445 
1446  Classify(seed0, 0, a_parVars);
1447  Classify(seed1, 1, a_parVars);
1448 }
1449 
1450 
1453 void RTREE_QUAL::Classify(int a_index, int a_group, PartitionVars* a_parVars)
1454 {
1455  ASSERT(a_parVars);
1456  ASSERT(PartitionVars::NOT_TAKEN == a_parVars->m_partition[a_index]);
1457 
1458  a_parVars->m_partition[a_index] = a_group;
1459 
1461  if (a_parVars->m_count[a_group] == 0)
1462  {
1463  a_parVars->m_cover[a_group] = a_parVars->m_branchBuf[a_index].m_rect;
1464  }
1465  else
1466  {
1467  a_parVars->m_cover[a_group] = CombineRect(&a_parVars->m_branchBuf[a_index].m_rect, &a_parVars->m_cover[a_group]);
1468  }
1469 
1471  a_parVars->m_area[a_group] = CalcRectVolume(&a_parVars->m_cover[a_group]);
1472 
1473  ++a_parVars->m_count[a_group];
1474 }
1475 
1476 
1482 bool RTREE_QUAL::RemoveRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root)
1483 {
1484  ASSERT(a_rect && a_root);
1485  ASSERT(*a_root);
1486 
1487  ListNode* reInsertList = NULL;
1488 
1489  if(!RemoveRectRec(a_rect, a_id, *a_root, &reInsertList))
1490  {
1493  while(reInsertList)
1494  {
1495  Node* tempNode = reInsertList->m_node;
1496 
1497  for(int index = 0; index < tempNode->m_count; ++index)
1498  {
1500  InsertRect(tempNode->m_branch[index],
1501  a_root,
1502  tempNode->m_level);
1503  }
1504 
1505  ListNode* remLNode = reInsertList;
1506  reInsertList = reInsertList->m_next;
1507 
1508  FreeNode(remLNode->m_node);
1509  FreeListNode(remLNode);
1510  }
1511 
1514  if((*a_root)->m_count == 1 && (*a_root)->IsInternalNode())
1515  {
1516  Node* tempNode = (*a_root)->m_branch[0].m_child;
1517 
1518  ASSERT(tempNode);
1519  FreeNode(*a_root);
1520  *a_root = tempNode;
1521  }
1522  return false;
1523  }
1524  else
1525  {
1526  return true;
1527  }
1528 }
1529 
1530 
1536 bool RTREE_QUAL::RemoveRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node, ListNode** a_listNode)
1537 {
1538  ASSERT(a_rect && a_node && a_listNode);
1539  ASSERT(a_node->m_level >= 0);
1540 
1541  if(a_node->IsInternalNode())
1542  {
1543  for(int index = 0; index < a_node->m_count; ++index)
1544  {
1545  if(Overlap(a_rect, &(a_node->m_branch[index].m_rect)))
1546  {
1547  if(!RemoveRectRec(a_rect, a_id, a_node->m_branch[index].m_child, a_listNode))
1548  {
1549  if(a_node->m_branch[index].m_child->m_count >= MINNODES)
1550  {
1552  a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
1553  }
1554  else
1555  {
1557  ReInsert(a_node->m_branch[index].m_child, a_listNode);
1558  DisconnectBranch(a_node, index);
1559  }
1560  return false;
1561  }
1562  }
1563  }
1564  return true;
1565  }
1566  else
1567  {
1568  for(int index = 0; index < a_node->m_count; ++index)
1569  {
1570  if(a_node->m_branch[index].m_data == a_id)
1571  {
1572  DisconnectBranch(a_node, index);
1573  return false;
1574  }
1575  }
1576  return true;
1577  }
1578 }
1579 
1580 
1583 bool RTREE_QUAL::Overlap(Rect* a_rectA, Rect* a_rectB) const
1584 {
1585  ASSERT(a_rectA && a_rectB);
1586 
1587  for(int index=0; index < NUMDIMS; ++index)
1588  {
1589  if (a_rectA->m_min[index] > a_rectB->m_max[index] ||
1590  a_rectB->m_min[index] > a_rectA->m_max[index])
1591  {
1592  return false;
1593  }
1594  }
1595  return true;
1596 }
1597 
1598 
1602 void RTREE_QUAL::ReInsert(Node* a_node, ListNode** a_listNode)
1603 {
1604  ListNode* newListNode;
1605 
1606  newListNode = AllocListNode();
1607  newListNode->m_node = a_node;
1608  newListNode->m_next = *a_listNode;
1609  *a_listNode = newListNode;
1610 }
1611 
1612 
1615 bool RTREE_QUAL::Search(Node* a_node, Rect* a_rect, int& a_foundCount, std::function<bool (const DATATYPE&)> callback) const
1616 {
1617  ASSERT(a_node);
1618  ASSERT(a_node->m_level >= 0);
1619  ASSERT(a_rect);
1620 
1621  if(a_node->IsInternalNode())
1622  {
1624  for(int index=0; index < a_node->m_count; ++index)
1625  {
1626  if(Overlap(a_rect, &a_node->m_branch[index].m_rect))
1627  {
1628  if(!Search(a_node->m_branch[index].m_child, a_rect, a_foundCount, callback))
1629  {
1631  return false;
1632  }
1633  }
1634  }
1635  }
1636  else
1637  {
1639  for(int index=0; index < a_node->m_count; ++index)
1640  {
1641  if(Overlap(a_rect, &a_node->m_branch[index].m_rect))
1642  {
1643  DATATYPE& id = a_node->m_branch[index].m_data;
1644  ++a_foundCount;
1645 
1646  if(callback && !callback(id))
1647  {
1648  return false;
1649  }
1650  }
1651  }
1652  }
1653 
1654  return true;
1655 }
1656 
1657 
1659 std::vector<typename RTREE_QUAL::Rect> RTREE_QUAL::ListTree() const
1660 {
1661  ASSERT(m_root);
1662  ASSERT(m_root->m_level >= 0);
1663 
1664  std::vector<Rect> treeList;
1665 
1666  std::vector<Node*> toVisit;
1667  toVisit.push_back(m_root);
1668 
1669  while (!toVisit.empty()) {
1670  Node* a_node = toVisit.back();
1671  toVisit.pop_back();
1672  if(a_node->IsInternalNode())
1673  {
1675  for(int index=0; index < a_node->m_count; ++index)
1676  {
1677  treeList.push_back(a_node->m_branch[index].m_rect);
1678  toVisit.push_back(a_node->m_branch[index].m_child);
1679  }
1680  }
1681  else
1682  {
1684  for(int index=0; index < a_node->m_count; ++index)
1685  {
1686  treeList.push_back(a_node->m_branch[index].m_rect);
1687  }
1688  }
1689  }
1690 
1691  return treeList;
1692 }
1693 
1694 
1695 #undef RTREE_TEMPLATE
1696 #undef RTREE_QUAL
1697 
1698 }
1699 
1700 
int Count()
! Count the data elements in this container. This is slow as no internal counter is maintained...
bool IsLeaf()
Not a leaf, but a internal node.
Definition: RTree.h:304
DATATYPE & GetAt(Iterator &a_it)
! Get object at iterator position
Definition: RTree.h:279
void LoadNodes(Node *a_nodeA, Node *a_nodeB, PartitionVars *a_parVars)
const DATATYPE & operator*() const
! Access the current data element. Caller must be sure iterator is not NULL first.
Definition: RTree.h:154
Node * m_node
Node.
Definition: RTree.h:315
int PickBranch(const Rect *a_rect, Node *a_node)
Min elements in node.
Definition: RTree.h:73
Definition: RTree.h:125
void GetFirst(Iterator &a_it)
! Get &#39;first&#39; for iteration
Definition: RTree.h:250
void RemoveAll()
! Remove all entries from tree
int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], std::function< bool(const DATATYPE &)> callback) const
! Find all within search rectangle !
RTFileStream()
Definition: RTree.h:390
void Close()
Definition: RTree.h:420
size_t WriteArray(const TYPE *a_array, int a_count)
Definition: RTree.h:437
ELEMTYPE m_max[NUMDIMS]
Max dimensions of bounding box.
Definition: RTree.h:287
int m_partition[MAXNODES+1]
indicates that position
Definition: RTree.h:323
size_t ReadArray(TYPE *a_array, int a_count)
Definition: RTree.h:451
bool IsInternalNode()
Definition: RTree.h:303
void GetNext(Iterator &a_it)
! Get Next for iteration
Definition: RTree.h:273
int m_count
A leaf, contains data.
Definition: RTree.h:306
Max elements in node.
Definition: RTree.h:72
Node * m_root
Root of tree.
Definition: RTree.h:372
ELEMTYPE m_min[NUMDIMS]
Min dimensions of bounding box.
Definition: RTree.h:286
FILE * m_file
Definition: RTree.h:385
void Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)
! Remove entry !
bool OpenWrite(const char *a_fileName)
Definition: RTree.h:415
int m_total
Definition: RTree.h:324
void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
! Get the bounds for this node
Definition: RTree.h:165
bool SaveRec(Node *a_node, RTFileStream &a_stream)
bool FindNextData()
! Find the next data element in the tree (For internal use only)
Definition: RTree.h:184
void Classify(int a_index, int a_group, PartitionVars *a_parVars)
void Push(Node *a_node, int a_branchIndex)
! Push node and branch onto iteration stack (For internal use only)
Definition: RTree.h:227
int m_tos
Top Of Stack index.
Definition: RTree.h:244
void CopyRec(Node *current, Node *other)
Node * m_node
Definition: RTree.h:129
Max stack size. Allows almost n^32 where n is number of branches in node.
Definition: RTree.h:127
void FreeNode(Node *a_node)
void ChoosePartition(PartitionVars *a_parVars, int a_minFill)
ELEMTYPEREAL CalcRectVolume(Rect *a_rect)
Rect NodeCover(Node *a_node)
bool Load(const char *a_fileName)
! Load tree contents from file
bool Save(const char *a_fileName)
! Save tree contents to file
void Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)
! Insert entry !
ELEMTYPEREAL RectSphericalVolume(Rect *a_rect)
ELEMTYPEREAL m_area[2]
Definition: RTree.h:328
bool Open(const char *a_fileName, const char *mode)
Definition: RTree.h:400
#define ASSERT
Definition: RTree.h:18
bool IsNull()
! Is iterator invalid
Definition: RTree.h:140
int m_count[2]
Definition: RTree.h:326
void DisconnectBranch(Node *a_node, int a_index)
Iterator()
Definition: RTree.h:135
size_t Read(TYPE &a_value)
Definition: RTree.h:444
void CountRec(Node *a_node, int &a_count)
bool OpenRead(const char *a_fileName)
Definition: RTree.h:410
! Variables for finding a split partition
Definition: RTree.h:319
bool Overlap(Rect *a_rectA, Rect *a_rectB) const
File I/O helper class, look below for implementation and notes.
Definition: RTree.h:58
! Minimal bounding rectangle (n-dimensional)
Definition: RTree.h:284
bool AddBranch(const Branch *a_branch, Node *a_node, Node **a_newNode)
Rect CombineRect(const Rect *a_rectA, const Rect *a_rectB)
int m_branchIndex
Definition: RTree.h:130
void ReInsert(Node *a_node, ListNode **a_listNode)
DATATYPE & operator*()
! Access the current data element. Caller must be sure iterator is not NULL first.
Definition: RTree.h:146
ListNode * m_next
Next in list.
Definition: RTree.h:314
Rect m_cover[2]
Definition: RTree.h:327
! May be data or may be another subtree ! The parents level determines this. ! If the parents level i...
Definition: RTree.h:293
Rect m_coverSplit
Definition: RTree.h:332
voidpf stream
Definition: ioapi.h:39
ELEMTYPEREAL RectVolume(Rect *a_rect)
void GetBranches(Node *a_node, const Branch *a_branch, PartitionVars *a_parVars)
bool RemoveRect(Rect *a_rect, const DATATYPE &a_id, Node **a_root)
int m_level
Leaf is zero, others positive.
Definition: RTree.h:307
bool IsNull(Iterator &a_it)
! Is iterator NULL, or at end?
Definition: RTree.h:276
void Init()
! Reset iterator
Definition: RTree.h:181
void InitParVars(PartitionVars *a_parVars, int a_maxRects, int a_minFill)
void SplitNode(Node *a_node, const Branch *a_branch, Node **a_newNode)
ListNode * AllocListNode()
std::vector< Rect > ListTree() const
return all the AABBs that form the RTree
const char int mode
Definition: ioapi.h:38
bool InsertRectRec(const Branch &a_branch, Node *a_node, Node **a_newNode, int a_level)
Rect m_rect
Bounds.
Definition: RTree.h:295
Node * m_child
Child node.
Definition: RTree.h:296
#define RTREE_TEMPLATE
#define Min std::min
Definition: RTree.h:30
! Node for each branch level
Definition: RTree.h:301
void RemoveAllRec(Node *a_node)
Branch m_branch[MAXNODES]
Branch.
Definition: RTree.h:308
StackElement & Pop()
! Pop element off iteration stack (For internal use only)
Definition: RTree.h:236
virtual ~RTree()
! A link list of nodes for reinsertion after a delete operation
Definition: RTree.h:312
void InitNode(Node *a_node)
~Iterator()
Definition: RTree.h:137
ELEMTYPEREAL m_coverSplitArea
Definition: RTree.h:333
Branch m_branchBuf[MAXNODES+1]
Definition: RTree.h:330
bool IsNotNull()
! Is iterator pointing to valid data
Definition: RTree.h:143
Node * AllocNode()
bool operator++()
! Find the next data element
Definition: RTree.h:162
void FreeListNode(ListNode *a_listNode)
int m_minFill
Definition: RTree.h:325
DATATYPE m_data
Data Id.
Definition: RTree.h:297
size_t Write(const TYPE &a_value)
Definition: RTree.h:430
~RTFileStream()
Definition: RTree.h:395
void PickSeeds(PartitionVars *a_parVars)
void InitRect(Rect *a_rect)
! Iterator is not remove safe.
Definition: RTree.h:121
bool InsertRect(const Branch &a_branch, Node **a_root, int a_level)
int m_branchCount
Definition: RTree.h:331
StackElement m_stack[MAX_STACK]
Stack as we are doing iteration instead of recursion.
Definition: RTree.h:243
bool LoadRec(Node *a_node, RTFileStream &a_stream)
Because there is not stream support, this is a quick and dirty file I/O helper. Users will likely rep...
Definition: RTree.h:383
bool RemoveRectRec(Rect *a_rect, const DATATYPE &a_id, Node *a_node, ListNode **a_listNode)
ELEMTYPEREAL m_unitSphereVolume
Unit sphere constant for required number of dimensions.
Definition: RTree.h:373

Document ID: Generated on Thu Oct 23 22:29:17 EDT 2025 from SVN revision 280951
Copyright © 2005-2024 MAK Technologies. All Rights Reserved (www.mak.com)