14 #define ASSERT assert // RTree uses ASSERT( condition )
26 #define RTREE_TEMPLATE template<class DATATYPE, class ELEMTYPE, int NUMDIMS, class ELEMTYPEREAL, int TMAXNODES, int TMINNODES>
27 #define RTREE_QUAL RTree<DATATYPE, ELEMTYPE, NUMDIMS, ELEMTYPEREAL, TMAXNODES, TMINNODES>
29 #define RTREE_DONT_USE_MEMPOOLS // This version does not contain a fixed memory allocator, fill in lines with EXAMPLE to implement one.
30 #define RTREE_USE_SPHERICAL_VOLUME // Better split classification, may be slower on some systems
52 template<
class DATATYPE,
class ELEMTYPE,
int NUMDIMS,
53 class ELEMTYPEREAL = ELEMTYPE,
int TMAXNODES = 8,
int TMINNODES = TMAXNODES / 2>
70 typedef bool (*t_resultCallback)(DATATYPE,
void*);
81 void Insert(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId);
87 void Remove(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId);
96 int Search(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS], t_resultCallback a_resultCallback,
void* a_context);
105 bool Load(
const char* a_fileName);
111 bool Save(
const char* a_fileName);
120 enum { MAX_STACK = 32 };
144 StackElement& curTos = m_stack[m_tos - 1];
145 return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
152 StackElement& curTos = m_stack[m_tos - 1];
153 return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
160 void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
163 StackElement& curTos = m_stack[m_tos - 1];
164 Branch& curBranch = curTos.m_node->m_branch[curTos.m_branchIndex];
166 for(
int index = 0; index < NUMDIMS; ++index)
176 void Init() { m_tos = 0; }
187 StackElement curTos = Pop();
189 if(curTos.m_node->IsLeaf())
192 if(curTos.m_branchIndex+1 < curTos.m_node->m_count)
195 Push(curTos.m_node, curTos.m_branchIndex + 1);
202 if(curTos.m_branchIndex+1 < curTos.m_node->m_count)
206 Push(curTos.m_node, curTos.m_branchIndex + 1);
209 Node* nextLevelnode = curTos.m_node->m_branch[curTos.m_branchIndex].m_child;
210 Push(nextLevelnode, 0);
213 if(nextLevelnode->IsLeaf())
222 void Push(Node* a_node,
int a_branchIndex)
224 m_stack[m_tos].m_node = a_node;
225 m_stack[m_tos].m_branchIndex = a_branchIndex;
227 ASSERT(m_tos <= MAX_STACK);
235 return m_stack[m_tos];
238 StackElement m_stack[MAX_STACK];
251 if(first->IsInternalNode() && first->m_count > 1)
255 else if(first->IsLeaf())
271 bool IsNull(Iterator& a_it) {
return a_it.IsNull(); }
274 DATATYPE&
GetAt(Iterator& a_it) {
return *a_it; }
298 bool IsInternalNode() {
return (
m_level > 0); }
299 bool IsLeaf() {
return (
m_level == 0); }
316 enum { NOT_TAKEN = -1 };
323 ELEMTYPEREAL m_area[2];
328 ELEMTYPEREAL m_coverSplitArea;
332 void FreeNode(
Node* a_node);
333 void InitNode(
Node* a_node);
334 void InitRect(
Rect* a_rect);
335 bool InsertRectRec(
const Branch& a_branch,
Node* a_node,
Node** a_newNode,
int a_level);
336 bool InsertRect(
const Branch& a_branch,
Node** a_root,
int a_level);
338 bool AddBranch(
const Branch* a_branch,
Node* a_node,
Node** a_newNode);
339 void DisconnectBranch(
Node* a_node,
int a_index);
340 int PickBranch(
const Rect* a_rect,
Node* a_node);
341 Rect CombineRect(
const Rect* a_rectA,
const Rect* a_rectB);
342 void SplitNode(
Node* a_node,
const Branch* a_branch,
Node** a_newNode);
343 ELEMTYPEREAL RectSphericalVolume(
Rect* a_rect);
344 ELEMTYPEREAL RectVolume(
Rect* a_rect);
345 ELEMTYPEREAL CalcRectVolume(
Rect* a_rect);
347 void ChoosePartition(
PartitionVars* a_parVars,
int a_minFill);
349 void InitParVars(
PartitionVars* a_parVars,
int a_maxRects,
int a_minFill);
351 void Classify(
int a_index,
int a_group,
PartitionVars* a_parVars);
352 bool RemoveRect(
Rect* a_rect,
const DATATYPE& a_id,
Node** a_root);
353 bool RemoveRectRec(
Rect* a_rect,
const DATATYPE& a_id,
Node* a_node,
ListNode** a_listNode);
355 void FreeListNode(
ListNode* a_listNode);
356 bool Overlap(
Rect* a_rectA,
Rect* a_rectB);
358 bool Search(
Node* a_node,
Rect* a_rect,
int& a_foundCount, t_resultCallback a_resultCallback,
void* a_context);
359 void RemoveAllRec(
Node* a_node);
361 void CountRec(
Node* a_node,
int& a_count);
390 bool OpenRead(
const char* a_fileName)
392 m_file = fopen(a_fileName,
"rb");
400 bool OpenWrite(
const char* a_fileName)
402 m_file = fopen(a_fileName,
"wb");
419 template<
typename TYPE >
420 size_t Write(
const TYPE& a_value)
423 return fwrite((
void*)&a_value,
sizeof(a_value), 1, m_file);
426 template<
typename TYPE >
427 size_t WriteArray(
const TYPE* a_array,
int a_count)
430 return fwrite((
void*)a_array,
sizeof(TYPE) * a_count, 1, m_file);
433 template<
typename TYPE >
434 size_t Read(TYPE& a_value)
437 return fread((
void*)&a_value,
sizeof(a_value), 1, m_file);
440 template<
typename TYPE >
441 size_t ReadArray(TYPE* a_array,
int a_count)
444 return fread((
void*)a_array,
sizeof(TYPE) * a_count, 1, m_file);
452 ASSERT(MAXNODES > MINNODES);
453 ASSERT(MINNODES > 0);
456 const float UNIT_SPHERE_VOLUMES[] = {
457 0.000000f, 2.000000f, 3.141593f,
458 4.188790f, 4.934802f, 5.263789f,
459 5.167713f, 4.724766f, 4.058712f,
460 3.298509f, 2.550164f, 1.884104f,
461 1.335263f, 0.910629f, 0.599265f,
462 0.381443f, 0.235331f, 0.140981f,
463 0.082146f, 0.046622f, 0.025807f,
466 m_root = AllocNode();
468 m_unitSphereVolume = (ELEMTYPEREAL)UNIT_SPHERE_VOLUMES[NUMDIMS];
480 void RTREE_QUAL::Insert(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId)
483 for(
int index=0; index<NUMDIMS; ++index)
485 ASSERT(a_min[index] <= a_max[index]);
490 branch.m_data = a_dataId;
491 branch.m_child = NULL;
493 for(
int axis=0; axis<NUMDIMS; ++axis)
495 branch.m_rect.m_min[axis] = a_min[axis];
496 branch.m_rect.m_max[axis] = a_max[axis];
499 InsertRect(branch, &m_root, 0);
504 void RTREE_QUAL::Remove(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId)
507 for(
int index=0; index<NUMDIMS; ++index)
509 ASSERT(a_min[index] <= a_max[index]);
515 for(
int axis=0; axis<NUMDIMS; ++axis)
517 rect.m_min[axis] = a_min[axis];
518 rect.m_max[axis] = a_max[axis];
521 RemoveRect(&rect, a_dataId, &m_root);
526 int RTREE_QUAL::Search(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS], t_resultCallback a_resultCallback,
void* a_context)
529 for(
int index=0; index<NUMDIMS; ++index)
531 ASSERT(a_min[index] <= a_max[index]);
537 for(
int axis=0; axis<NUMDIMS; ++axis)
539 rect.m_min[axis] = a_min[axis];
540 rect.m_max[axis] = a_max[axis];
546 Search(m_root, &rect, foundCount, a_resultCallback, a_context);
553 int RTREE_QUAL::Count()
556 CountRec(m_root, count);
564 void RTREE_QUAL::CountRec(Node* a_node,
int& a_count)
566 if(a_node->IsInternalNode())
568 for(
int index = 0; index < a_node->m_count; ++index)
570 CountRec(a_node->m_branch[index].m_child, a_count);
575 a_count += a_node->m_count;
581 bool RTREE_QUAL::Load(
const char* a_fileName)
586 if(!stream.OpenRead(a_fileName))
591 bool result = Load(stream);
604 int _dataFileId = (
'R'<<0)|(
'T'<<8)|(
'R'<<16)|(
'E'<<24);
605 int _dataSize =
sizeof(DATATYPE);
606 int _dataNumDims = NUMDIMS;
607 int _dataElemSize =
sizeof(ELEMTYPE);
608 int _dataElemRealSize =
sizeof(ELEMTYPEREAL);
609 int _dataMaxNodes = TMAXNODES;
610 int _dataMinNodes = TMINNODES;
615 int dataElemSize = 0;
616 int dataElemRealSize = 0;
617 int dataMaxNodes = 0;
618 int dataMinNodes = 0;
620 a_stream.Read(dataFileId);
621 a_stream.Read(dataSize);
622 a_stream.Read(dataNumDims);
623 a_stream.Read(dataElemSize);
624 a_stream.Read(dataElemRealSize);
625 a_stream.Read(dataMaxNodes);
626 a_stream.Read(dataMinNodes);
631 if( (dataFileId == _dataFileId)
632 && (dataSize == _dataSize)
633 && (dataNumDims == _dataNumDims)
634 && (dataElemSize == _dataElemSize)
635 && (dataElemRealSize == _dataElemRealSize)
636 && (dataMaxNodes == _dataMaxNodes)
637 && (dataMinNodes == _dataMinNodes)
641 result = LoadRec(m_root, a_stream);
649 bool RTREE_QUAL::LoadRec(Node* a_node,
RTFileStream& a_stream)
651 a_stream.Read(a_node->m_level);
652 a_stream.Read(a_node->m_count);
654 if(a_node->IsInternalNode())
656 for(
int index = 0; index < a_node->m_count; ++index)
658 Branch* curBranch = &a_node->m_branch[index];
660 a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
661 a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
663 curBranch->m_child = AllocNode();
664 LoadRec(curBranch->m_child, a_stream);
669 for(
int index = 0; index < a_node->m_count; ++index)
671 Branch* curBranch = &a_node->m_branch[index];
673 a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
674 a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
676 a_stream.Read(curBranch->m_data);
685 bool RTREE_QUAL::Save(
const char* a_fileName)
688 if(!stream.OpenWrite(a_fileName))
693 bool result = Save(stream);
705 int dataFileId = (
'R'<<0)|(
'T'<<8)|(
'R'<<16)|(
'E'<<24);
706 int dataSize =
sizeof(DATATYPE);
707 int dataNumDims = NUMDIMS;
708 int dataElemSize =
sizeof(ELEMTYPE);
709 int dataElemRealSize =
sizeof(ELEMTYPEREAL);
710 int dataMaxNodes = TMAXNODES;
711 int dataMinNodes = TMINNODES;
713 a_stream.Write(dataFileId);
714 a_stream.Write(dataSize);
715 a_stream.Write(dataNumDims);
716 a_stream.Write(dataElemSize);
717 a_stream.Write(dataElemRealSize);
718 a_stream.Write(dataMaxNodes);
719 a_stream.Write(dataMinNodes);
722 bool result = SaveRec(m_root, a_stream);
729 bool RTREE_QUAL::SaveRec(Node* a_node,
RTFileStream& a_stream)
731 a_stream.Write(a_node->m_level);
732 a_stream.Write(a_node->m_count);
734 if(a_node->IsInternalNode())
736 for(
int index = 0; index < a_node->m_count; ++index)
738 Branch* curBranch = &a_node->m_branch[index];
740 a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
741 a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
743 SaveRec(curBranch->m_child, a_stream);
748 for(
int index = 0; index < a_node->m_count; ++index)
750 Branch* curBranch = &a_node->m_branch[index];
752 a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
753 a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
755 a_stream.Write(curBranch->m_data);
764 void RTREE_QUAL::RemoveAll()
769 m_root = AllocNode();
775 void RTREE_QUAL::Reset()
777 #ifdef RTREE_DONT_USE_MEMPOOLS
779 RemoveAllRec(m_root);
780 #else // RTREE_DONT_USE_MEMPOOLS
783 #endif // RTREE_DONT_USE_MEMPOOLS
788 void RTREE_QUAL::RemoveAllRec(Node* a_node)
791 ASSERT(a_node->m_level >= 0);
793 if(a_node->IsInternalNode())
795 for(
int index=0; index < a_node->m_count; ++index)
797 RemoveAllRec(a_node->m_branch[index].m_child);
805 typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode()
808 #ifdef RTREE_DONT_USE_MEMPOOLS
810 #else // RTREE_DONT_USE_MEMPOOLS
812 #endif // RTREE_DONT_USE_MEMPOOLS
819 void RTREE_QUAL::FreeNode(Node* a_node)
823 #ifdef RTREE_DONT_USE_MEMPOOLS
825 #else // RTREE_DONT_USE_MEMPOOLS
827 #endif // RTREE_DONT_USE_MEMPOOLS
834 typename RTREE_QUAL::ListNode* RTREE_QUAL::AllocListNode()
836 #ifdef RTREE_DONT_USE_MEMPOOLS
838 #else // RTREE_DONT_USE_MEMPOOLS
840 #endif // RTREE_DONT_USE_MEMPOOLS
845 void RTREE_QUAL::FreeListNode(ListNode* a_listNode)
847 #ifdef RTREE_DONT_USE_MEMPOOLS
849 #else // RTREE_DONT_USE_MEMPOOLS
851 #endif // RTREE_DONT_USE_MEMPOOLS
856 void RTREE_QUAL::InitNode(Node* a_node)
859 a_node->m_level = -1;
864 void RTREE_QUAL::InitRect(
Rect* a_rect)
866 for(
int index = 0; index < NUMDIMS; ++index)
868 a_rect->m_min[index] = (ELEMTYPE)0;
869 a_rect->m_max[index] = (ELEMTYPE)0;
882 bool RTREE_QUAL::InsertRectRec(
const Branch& a_branch, Node* a_node, Node** a_newNode,
int a_level)
884 ASSERT(a_node && a_newNode);
885 ASSERT(a_level >= 0 && a_level <= a_node->m_level);
889 if(a_node->m_level > a_level)
895 int index = PickBranch(&a_branch.m_rect, a_node);
898 bool childWasSplit = InsertRectRec(a_branch, a_node->m_branch[index].m_child, &otherNode, a_level);
904 a_node->m_branch[index].m_rect = CombineRect(&a_branch.m_rect, &(a_node->m_branch[index].m_rect));
911 a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
913 branch.m_child = otherNode;
914 branch.m_rect = NodeCover(otherNode);
918 return AddBranch(&branch, a_node, a_newNode);
921 else if(a_node->m_level == a_level)
924 return AddBranch(&a_branch, a_node, a_newNode);
943 bool RTREE_QUAL::InsertRect(
const Branch& a_branch, Node** a_root,
int a_level)
946 ASSERT(a_level >= 0 && a_level <= (*a_root)->m_level);
948 for(
int index=0; index < NUMDIMS; ++index)
950 ASSERT(a_branch.m_rect.m_min[index] <= a_branch.m_rect.m_max[index]);
956 if(InsertRectRec(a_branch, *a_root, &newNode, a_level))
959 Node* newRoot = AllocNode();
960 newRoot->m_level = (*a_root)->m_level + 1;
965 branch.m_rect = NodeCover(*a_root);
966 branch.m_child = *a_root;
967 AddBranch(&branch, newRoot, NULL);
970 branch.m_rect = NodeCover(newNode);
971 branch.m_child = newNode;
972 AddBranch(&branch, newRoot, NULL);
986 typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(Node* a_node)
990 Rect rect = a_node->m_branch[0].m_rect;
991 for(
int index = 1; index < a_node->m_count; ++index)
993 rect = CombineRect(&rect, &(a_node->m_branch[index].m_rect));
1005 bool RTREE_QUAL::AddBranch(
const Branch* a_branch, Node* a_node, Node** a_newNode)
1010 if(a_node->m_count < MAXNODES)
1012 a_node->m_branch[a_node->m_count] = *a_branch;
1021 SplitNode(a_node, a_branch, a_newNode);
1030 void RTREE_QUAL::DisconnectBranch(Node* a_node,
int a_index)
1032 ASSERT(a_node && (a_index >= 0) && (a_index < MAXNODES));
1033 ASSERT(a_node->m_count > 0);
1036 a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1];
1048 int RTREE_QUAL::PickBranch(
const Rect* a_rect, Node* a_node)
1050 ASSERT(a_rect && a_node);
1052 bool firstTime =
true;
1053 ELEMTYPEREAL increase;
1054 ELEMTYPEREAL bestIncr = (ELEMTYPEREAL)-1;
1056 ELEMTYPEREAL bestArea;
1060 for(
int index=0; index < a_node->m_count; ++index)
1062 Rect* curRect = &a_node->m_branch[index].m_rect;
1063 area = CalcRectVolume(curRect);
1064 tempRect = CombineRect(a_rect, curRect);
1065 increase = CalcRectVolume(&tempRect) - area;
1066 if((increase < bestIncr) || firstTime)
1070 bestIncr = increase;
1073 else if((increase == bestIncr) && (area < bestArea))
1077 bestIncr = increase;
1086 typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect(
const Rect* a_rectA,
const Rect* a_rectB)
1088 ASSERT(a_rectA && a_rectB);
1092 for(
int index = 0; index < NUMDIMS; ++index)
1094 newRect.m_min[index] = Min(a_rectA->m_min[index], a_rectB->m_min[index]);
1095 newRect.m_max[index] = Max(a_rectA->m_max[index], a_rectB->m_max[index]);
1108 void RTREE_QUAL::SplitNode(Node* a_node,
const Branch* a_branch, Node** a_newNode)
1114 PartitionVars localVars;
1115 PartitionVars* parVars = &localVars;
1118 GetBranches(a_node, a_branch, parVars);
1121 ChoosePartition(parVars, MINNODES);
1124 *a_newNode = AllocNode();
1125 (*a_newNode)->m_level = a_node->m_level;
1128 a_node->m_count = 0;
1129 LoadNodes(a_node, *a_newNode, parVars);
1131 ASSERT((a_node->m_count + (*a_newNode)->m_count) == parVars->m_total);
1137 ELEMTYPEREAL RTREE_QUAL::RectVolume(
Rect* a_rect)
1141 ELEMTYPEREAL volume = (ELEMTYPEREAL)1;
1143 for(
int index=0; index<NUMDIMS; ++index)
1145 volume *= a_rect->m_max[index] - a_rect->m_min[index];
1148 ASSERT(volume >= (ELEMTYPEREAL)0);
1156 ELEMTYPEREAL RTREE_QUAL::RectSphericalVolume(
Rect* a_rect)
1160 ELEMTYPEREAL sumOfSquares = (ELEMTYPEREAL)0;
1161 ELEMTYPEREAL radius;
1163 for(
int index=0; index < NUMDIMS; ++index)
1165 ELEMTYPEREAL halfExtent = ((ELEMTYPEREAL)a_rect->m_max[index] - (ELEMTYPEREAL)a_rect->m_min[index]) * 0.5f;
1166 sumOfSquares += halfExtent * halfExtent;
1169 radius = (ELEMTYPEREAL)sqrt(sumOfSquares);
1174 return (radius * radius * radius * m_unitSphereVolume);
1176 else if(NUMDIMS == 2)
1178 return (radius * radius * m_unitSphereVolume);
1182 return (ELEMTYPEREAL)(pow(radius, NUMDIMS) * m_unitSphereVolume);
1189 ELEMTYPEREAL RTREE_QUAL::CalcRectVolume(
Rect* a_rect)
1191 #ifdef RTREE_USE_SPHERICAL_VOLUME
1192 return RectSphericalVolume(a_rect);
1193 #else // RTREE_USE_SPHERICAL_VOLUME
1194 return RectVolume(a_rect);
1195 #endif // RTREE_USE_SPHERICAL_VOLUME
1201 void RTREE_QUAL::GetBranches(Node* a_node,
const Branch* a_branch, PartitionVars* a_parVars)
1206 ASSERT(a_node->m_count == MAXNODES);
1209 for(
int index=0; index < MAXNODES; ++index)
1211 a_parVars->m_branchBuf[index] = a_node->m_branch[index];
1213 a_parVars->m_branchBuf[MAXNODES] = *a_branch;
1214 a_parVars->m_branchCount = MAXNODES + 1;
1217 a_parVars->m_coverSplit = a_parVars->m_branchBuf[0].m_rect;
1218 for(
int index=1; index < MAXNODES+1; ++index)
1220 a_parVars->m_coverSplit = CombineRect(&a_parVars->m_coverSplit, &a_parVars->m_branchBuf[index].m_rect);
1222 a_parVars->m_coverSplitArea = CalcRectVolume(&a_parVars->m_coverSplit);
1238 void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars,
int a_minFill)
1242 ELEMTYPEREAL biggestDiff;
1243 int group, chosen=0, betterGroup=0;
1245 InitParVars(a_parVars, a_parVars->m_branchCount, a_minFill);
1246 PickSeeds(a_parVars);
1248 while (((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
1249 && (a_parVars->m_count[0] < (a_parVars->m_total - a_parVars->m_minFill))
1250 && (a_parVars->m_count[1] < (a_parVars->m_total - a_parVars->m_minFill)))
1252 biggestDiff = (ELEMTYPEREAL) -1;
1253 for(
int index=0; index<a_parVars->m_total; ++index)
1255 if(PartitionVars::NOT_TAKEN == a_parVars->m_partition[index])
1257 Rect* curRect = &a_parVars->m_branchBuf[index].m_rect;
1258 Rect rect0 = CombineRect(curRect, &a_parVars->m_cover[0]);
1259 Rect rect1 = CombineRect(curRect, &a_parVars->m_cover[1]);
1260 ELEMTYPEREAL growth0 = CalcRectVolume(&rect0) - a_parVars->m_area[0];
1261 ELEMTYPEREAL growth1 = CalcRectVolume(&rect1) - a_parVars->m_area[1];
1262 ELEMTYPEREAL diff = growth1 - growth0;
1273 if(diff > biggestDiff)
1277 betterGroup = group;
1279 else if((diff == biggestDiff) && (a_parVars->m_count[group] < a_parVars->m_count[betterGroup]))
1282 betterGroup = group;
1286 Classify(chosen, betterGroup, a_parVars);
1290 if((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
1292 if(a_parVars->m_count[0] >= a_parVars->m_total - a_parVars->m_minFill)
1300 for(
int index=0; index<a_parVars->m_total; ++index)
1302 if(PartitionVars::NOT_TAKEN == a_parVars->m_partition[index])
1304 Classify(index, group, a_parVars);
1309 ASSERT((a_parVars->m_count[0] + a_parVars->m_count[1]) == a_parVars->m_total);
1310 ASSERT((a_parVars->m_count[0] >= a_parVars->m_minFill) &&
1311 (a_parVars->m_count[1] >= a_parVars->m_minFill));
1317 void RTREE_QUAL::LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars)
1323 for(
int index=0; index < a_parVars->m_total; ++index)
1325 ASSERT(a_parVars->m_partition[index] == 0 || a_parVars->m_partition[index] == 1);
1327 int targetNodeIndex = a_parVars->m_partition[index];
1328 Node* targetNodes[] = {a_nodeA, a_nodeB};
1331 bool nodeWasSplit = AddBranch(&a_parVars->m_branchBuf[index], targetNodes[targetNodeIndex], NULL);
1332 ASSERT(!nodeWasSplit);
1339 void RTREE_QUAL::InitParVars(PartitionVars* a_parVars,
int a_maxRects,
int a_minFill)
1343 a_parVars->m_count[0] = a_parVars->m_count[1] = 0;
1344 a_parVars->m_area[0] = a_parVars->m_area[1] = (ELEMTYPEREAL)0;
1345 a_parVars->m_total = a_maxRects;
1346 a_parVars->m_minFill = a_minFill;
1347 for(
int index=0; index < a_maxRects; ++index)
1349 a_parVars->m_partition[index] = PartitionVars::NOT_TAKEN;
1355 void RTREE_QUAL::PickSeeds(PartitionVars* a_parVars)
1357 int seed0=0, seed1=0;
1358 ELEMTYPEREAL worst, waste;
1359 ELEMTYPEREAL area[MAXNODES+1];
1361 for(
int index=0; index<a_parVars->m_total; ++index)
1363 area[index] = CalcRectVolume(&a_parVars->m_branchBuf[index].m_rect);
1366 worst = -a_parVars->m_coverSplitArea - 1;
1367 for(
int indexA=0; indexA < a_parVars->m_total-1; ++indexA)
1369 for(
int indexB = indexA+1; indexB < a_parVars->m_total; ++indexB)
1371 Rect oneRect = CombineRect(&a_parVars->m_branchBuf[indexA].m_rect, &a_parVars->m_branchBuf[indexB].m_rect);
1372 waste = CalcRectVolume(&oneRect) - area[indexA] - area[indexB];
1382 Classify(seed0, 0, a_parVars);
1383 Classify(seed1, 1, a_parVars);
1389 void RTREE_QUAL::Classify(
int a_index,
int a_group, PartitionVars* a_parVars)
1392 ASSERT(PartitionVars::NOT_TAKEN == a_parVars->m_partition[a_index]);
1394 a_parVars->m_partition[a_index] = a_group;
1397 if (a_parVars->m_count[a_group] == 0)
1399 a_parVars->m_cover[a_group] = a_parVars->m_branchBuf[a_index].m_rect;
1403 a_parVars->m_cover[a_group] = CombineRect(&a_parVars->m_branchBuf[a_index].m_rect, &a_parVars->m_cover[a_group]);
1407 a_parVars->m_area[a_group] = CalcRectVolume(&a_parVars->m_cover[a_group]);
1409 ++a_parVars->m_count[a_group];
1418 bool RTREE_QUAL::RemoveRect(
Rect* a_rect,
const DATATYPE& a_id, Node** a_root)
1420 ASSERT(a_rect && a_root);
1423 ListNode* reInsertList = NULL;
1425 if(!RemoveRectRec(a_rect, a_id, *a_root, &reInsertList))
1431 Node* tempNode = reInsertList->m_node;
1433 for(
int index = 0; index < tempNode->m_count; ++index)
1436 InsertRect(tempNode->m_branch[index],
1441 ListNode* remLNode = reInsertList;
1442 reInsertList = reInsertList->m_next;
1444 FreeNode(remLNode->m_node);
1445 FreeListNode(remLNode);
1450 if((*a_root)->m_count == 1 && (*a_root)->IsInternalNode())
1452 Node* tempNode = (*a_root)->m_branch[0].m_child;
1472 bool RTREE_QUAL::RemoveRectRec(
Rect* a_rect,
const DATATYPE& a_id, Node* a_node, ListNode** a_listNode)
1474 ASSERT(a_rect && a_node && a_listNode);
1475 ASSERT(a_node->m_level >= 0);
1477 if(a_node->IsInternalNode())
1479 for(
int index = 0; index < a_node->m_count; ++index)
1481 if(Overlap(a_rect, &(a_node->m_branch[index].m_rect)))
1483 if(!RemoveRectRec(a_rect, a_id, a_node->m_branch[index].m_child, a_listNode))
1485 if(a_node->m_branch[index].m_child->m_count >= MINNODES)
1488 a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
1493 ReInsert(a_node->m_branch[index].m_child, a_listNode);
1494 DisconnectBranch(a_node, index);
1504 for(
int index = 0; index < a_node->m_count; ++index)
1506 if(a_node->m_branch[index].m_data == a_id)
1508 DisconnectBranch(a_node, index);
1519 bool RTREE_QUAL::Overlap(
Rect* a_rectA,
Rect* a_rectB)
1521 ASSERT(a_rectA && a_rectB);
1523 for(
int index=0; index < NUMDIMS; ++index)
1525 if (a_rectA->m_min[index] > a_rectB->m_max[index] ||
1526 a_rectB->m_min[index] > a_rectA->m_max[index])
1538 void RTREE_QUAL::ReInsert(Node* a_node, ListNode** a_listNode)
1540 ListNode* newListNode;
1542 newListNode = AllocListNode();
1543 newListNode->m_node = a_node;
1544 newListNode->m_next = *a_listNode;
1545 *a_listNode = newListNode;
1551 bool RTREE_QUAL::Search(Node* a_node,
Rect* a_rect,
int& a_foundCount, t_resultCallback a_resultCallback,
void* a_context)
1554 ASSERT(a_node->m_level >= 0);
1557 if(a_node->IsInternalNode())
1560 for(
int index=0; index < a_node->m_count; ++index)
1562 if(Overlap(a_rect, &a_node->m_branch[index].m_rect))
1564 if(!Search(a_node->m_branch[index].m_child, a_rect, a_foundCount, a_resultCallback, a_context))
1575 for(
int index=0; index < a_node->m_count; ++index)
1577 if(Overlap(a_rect, &a_node->m_branch[index].m_rect))
1579 DATATYPE&
id = a_node->m_branch[index].m_data;
1583 if(a_resultCallback)
1585 if(!a_resultCallback(
id, a_context))
1598 #undef RTREE_TEMPLATE
Variables for finding a split partition.
Definition: RTree.h:314
int m_level
Leaf is zero, others positive.
Definition: RTree.h:302
int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], t_resultCallback a_resultCallback, void *a_context)
Branch m_branch[MAXNODES]
Branch.
Definition: RTree.h:303
ELEMTYPE m_min[NUMDIMS]
Min dimensions of bounding box.
Definition: RTree.h:281
DATATYPE & GetAt(Iterator &a_it)
Get object at iterator position.
Definition: RTree.h:274
int Count()
Count the data elements in this container. This is slow as no internal counter is maintained...
ELEMTYPEREAL m_unitSphereVolume
Unit sphere constant for required number of dimensions.
Definition: RTree.h:367
Node * m_root
Root of tree.
Definition: RTree.h:366
void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
Get the bounds for this node.
Definition: RTree.h:160
bool operator++()
Find the next data element.
Definition: RTree.h:157
void GetFirst(Iterator &a_it)
Get 'first' for iteration.
Definition: RTree.h:245
void GetNext(Iterator &a_it)
Get Next for iteration.
Definition: RTree.h:268
bool IsNull(Iterator &a_it)
Is iterator NULL, or at end?
Definition: RTree.h:271
A link list of nodes for reinsertion after a delete operation.
Definition: RTree.h:307
void Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)
Rect m_rect
Bounds.
Definition: RTree.h:290
Node * m_node
Node.
Definition: RTree.h:310
const DATATYPE & operator*() const
Access the current data element. Caller must be sure iterator is not NULL first.
Definition: RTree.h:149
Max elements in node.
Definition: RTree.h:66
void RemoveAll()
Remove all entries from tree.
DATATYPE & operator*()
Access the current data element. Caller must be sure iterator is not NULL first.
Definition: RTree.h:141
DATATYPE m_data
Data Id.
Definition: RTree.h:292
int m_count
Count.
Definition: RTree.h:301
ListNode * m_next
Next in list.
Definition: RTree.h:309
ELEMTYPE m_max[NUMDIMS]
Max dimensions of bounding box.
Definition: RTree.h:282
bool Save(const char *a_fileName)
Save tree contents to file.
Node * m_child
Child node.
Definition: RTree.h:291
Node for each branch level.
Definition: RTree.h:296
bool Load(const char *a_fileName)
Load tree contents from file.
Iterator is not remove safe.
Definition: RTree.h:116
bool IsNull()
Is iterator invalid.
Definition: RTree.h:135
bool IsNotNull()
Is iterator pointing to valid data.
Definition: RTree.h:138
Minimal bounding rectangle (n-dimensional)
Definition: RTree.h:279
Min elements in node.
Definition: RTree.h:67
void Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)