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>
33 #define RTREE_DONT_USE_MEMPOOLS
34 #define RTREE_USE_SPHERICAL_VOLUME
56 template<
class DATATYPE,
class ELEMTYPE,
int NUMDIMS,
57 class ELEMTYPEREAL = ELEMTYPE,
int TMAXNODES = 8,
int TMINNODES = TMAXNODES / 2>
60 static_assert(std::numeric_limits<ELEMTYPEREAL>::is_iec559,
"'ELEMTYPEREAL' accepts floating-point types only");
86 void Insert(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId);
92 void Remove(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId);
101 int Search(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS], std::function<
bool (
const DATATYPE&)> callback)
const;
110 bool Load(
const char* a_fileName);
116 bool Save(
const char* a_fileName);
165 void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
171 for(
int index = 0; index < NUMDIMS; ++index)
215 Push(nextLevelnode, 0);
218 if(nextLevelnode->
IsLeaf())
256 if(first->IsInternalNode() && first->m_count > 1)
260 else if(first->IsLeaf())
276 bool IsNull(Iterator& a_it) {
return a_it.IsNull(); }
279 DATATYPE&
GetAt(Iterator& a_it) {
return *a_it; }
363 bool Search(
Node* a_node,
Rect* a_rect,
int& a_foundCount, std::function<
bool (
const DATATYPE&)> callback)
const;
400 bool Open(
const char* a_fileName,
const char*
mode)
402 #if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)
403 return fopen_s(&
m_file, a_fileName, mode) == 0;
405 m_file = fopen(a_fileName, mode);
412 return this->
Open(a_fileName,
"rb");
417 return this->
Open(a_fileName,
"wb");
429 template<
typename TYPE >
433 return fwrite((
void*)&a_value,
sizeof(a_value), 1,
m_file);
436 template<
typename TYPE >
440 return fwrite((
void*)a_array,
sizeof(TYPE) * a_count, 1,
m_file);
443 template<
typename TYPE >
447 return fread((
void*)&a_value,
sizeof(a_value), 1,
m_file);
450 template<
typename TYPE >
454 return fread((
void*)a_array,
sizeof(TYPE) * a_count, 1,
m_file);
462 ASSERT(MAXNODES > MINNODES);
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,
476 m_root = AllocNode();
478 m_unitSphereVolume = (ELEMTYPEREAL)UNIT_SPHERE_VOLUMES[NUMDIMS];
483 RTREE_QUAL::RTree(
const RTree& other) : RTree()
485 CopyRec(m_root, other.m_root);
497 void RTREE_QUAL::Insert(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId)
500 for(
int index=0; index<NUMDIMS; ++index)
502 ASSERT(a_min[index] <= a_max[index]);
507 branch.m_data = a_dataId;
508 branch.m_child = NULL;
510 for(
int axis=0; axis<NUMDIMS; ++axis)
512 branch.m_rect.m_min[axis] = a_min[axis];
513 branch.m_rect.m_max[axis] = a_max[axis];
516 InsertRect(branch, &m_root, 0);
521 void RTREE_QUAL::Remove(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId)
524 for(
int index=0; index<NUMDIMS; ++index)
526 ASSERT(a_min[index] <= a_max[index]);
532 for(
int axis=0; axis<NUMDIMS; ++axis)
534 rect.m_min[axis] = a_min[axis];
535 rect.m_max[axis] = a_max[axis];
538 RemoveRect(&rect, a_dataId, &m_root);
543 int RTREE_QUAL::Search(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS], std::function<
bool (
const DATATYPE&)> callback)
const
546 for(
int index=0; index<NUMDIMS; ++index)
548 ASSERT(a_min[index] <= a_max[index]);
554 for(
int axis=0; axis<NUMDIMS; ++axis)
556 rect.m_min[axis] = a_min[axis];
557 rect.m_max[axis] = a_max[axis];
563 Search(m_root, &rect, foundCount, callback);
570 int RTREE_QUAL::Count()
573 CountRec(m_root, count);
581 void RTREE_QUAL::CountRec(Node* a_node,
int& a_count)
583 if(a_node->IsInternalNode())
585 for(
int index = 0; index < a_node->m_count; ++index)
587 CountRec(a_node->m_branch[index].m_child, a_count);
592 a_count += a_node->m_count;
598 bool RTREE_QUAL::Load(
const char* a_fileName)
603 if(!stream.OpenRead(a_fileName))
608 bool result = Load(stream);
618 bool RTREE_QUAL::Load(RTFileStream& a_stream)
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;
632 int dataElemSize = 0;
633 int dataElemRealSize = 0;
634 int dataMaxNodes = 0;
635 int dataMinNodes = 0;
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);
648 if( (dataFileId == _dataFileId)
649 && (dataSize == _dataSize)
650 && (dataNumDims == _dataNumDims)
651 && (dataElemSize == _dataElemSize)
652 && (dataElemRealSize == _dataElemRealSize)
653 && (dataMaxNodes == _dataMaxNodes)
654 && (dataMinNodes == _dataMinNodes)
658 result = LoadRec(m_root, a_stream);
666 bool RTREE_QUAL::LoadRec(Node* a_node, RTFileStream& a_stream)
668 a_stream.Read(a_node->m_level);
669 a_stream.Read(a_node->m_count);
671 if(a_node->IsInternalNode())
673 for(
int index = 0; index < a_node->m_count; ++index)
675 Branch* curBranch = &a_node->m_branch[index];
677 a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
678 a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
680 curBranch->m_child = AllocNode();
681 LoadRec(curBranch->m_child, a_stream);
686 for(
int index = 0; index < a_node->m_count; ++index)
688 Branch* curBranch = &a_node->m_branch[index];
690 a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
691 a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
693 a_stream.Read(curBranch->m_data);
702 void RTREE_QUAL::CopyRec(Node* current, Node* other)
704 current->m_level = other->m_level;
705 current->m_count = other->m_count;
707 if(current->IsInternalNode())
709 for(
int index = 0; index < current->m_count; ++index)
711 Branch* currentBranch = ¤t->m_branch[index];
712 Branch* otherBranch = &other->m_branch[index];
714 std::copy(otherBranch->m_rect.m_min,
715 otherBranch->m_rect.m_min + NUMDIMS,
716 currentBranch->m_rect.m_min);
718 std::copy(otherBranch->m_rect.m_max,
719 otherBranch->m_rect.m_max + NUMDIMS,
720 currentBranch->m_rect.m_max);
722 currentBranch->m_child = AllocNode();
723 CopyRec(currentBranch->m_child, otherBranch->m_child);
728 for(
int index = 0; index < current->m_count; ++index)
730 Branch* currentBranch = ¤t->m_branch[index];
731 Branch* otherBranch = &other->m_branch[index];
733 std::copy(otherBranch->m_rect.m_min,
734 otherBranch->m_rect.m_min + NUMDIMS,
735 currentBranch->m_rect.m_min);
737 std::copy(otherBranch->m_rect.m_max,
738 otherBranch->m_rect.m_max + NUMDIMS,
739 currentBranch->m_rect.m_max);
741 currentBranch->m_data = otherBranch->m_data;
748 bool RTREE_QUAL::Save(
const char* a_fileName)
751 if(!stream.OpenWrite(a_fileName))
756 bool result = Save(stream);
765 bool RTREE_QUAL::Save(RTFileStream& a_stream)
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;
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);
785 bool result = SaveRec(m_root, a_stream);
792 bool RTREE_QUAL::SaveRec(Node* a_node, RTFileStream& a_stream)
794 a_stream.Write(a_node->m_level);
795 a_stream.Write(a_node->m_count);
797 if(a_node->IsInternalNode())
799 for(
int index = 0; index < a_node->m_count; ++index)
801 Branch* curBranch = &a_node->m_branch[index];
803 a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
804 a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
806 SaveRec(curBranch->m_child, a_stream);
811 for(
int index = 0; index < a_node->m_count; ++index)
813 Branch* curBranch = &a_node->m_branch[index];
815 a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
816 a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
818 a_stream.Write(curBranch->m_data);
827 void RTREE_QUAL::RemoveAll()
832 m_root = AllocNode();
838 void RTREE_QUAL::Reset()
840 #ifdef RTREE_DONT_USE_MEMPOOLS
841 RemoveAllRec(m_root);
851 void RTREE_QUAL::RemoveAllRec(Node* a_node)
854 ASSERT(a_node->m_level >= 0);
856 if(a_node->IsInternalNode())
858 for(
int index=0; index < a_node->m_count; ++index)
860 RemoveAllRec(a_node->m_branch[index].m_child);
868 typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode()
871 #ifdef RTREE_DONT_USE_MEMPOOLS
882 void RTREE_QUAL::FreeNode(Node* a_node)
886 #ifdef RTREE_DONT_USE_MEMPOOLS
897 typename RTREE_QUAL::ListNode* RTREE_QUAL::AllocListNode()
899 #ifdef RTREE_DONT_USE_MEMPOOLS
908 void RTREE_QUAL::FreeListNode(ListNode* a_listNode)
910 #ifdef RTREE_DONT_USE_MEMPOOLS
919 void RTREE_QUAL::InitNode(Node* a_node)
922 a_node->m_level = -1;
927 void RTREE_QUAL::InitRect(Rect* a_rect)
929 for(
int index = 0; index < NUMDIMS; ++index)
931 a_rect->m_min[index] = (ELEMTYPE)0;
932 a_rect->m_max[index] = (ELEMTYPE)0;
945 bool RTREE_QUAL::InsertRectRec(
const Branch& a_branch, Node* a_node, Node** a_newNode,
int a_level)
947 ASSERT(a_node && a_newNode);
948 ASSERT(a_level >= 0 && a_level <= a_node->m_level);
952 if(a_node->m_level > a_level)
958 int index = PickBranch(&a_branch.m_rect, a_node);
961 bool childWasSplit = InsertRectRec(a_branch, a_node->m_branch[index].m_child, &otherNode, a_level);
967 a_node->m_branch[index].m_rect = CombineRect(&a_branch.m_rect, &(a_node->m_branch[index].m_rect));
974 a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
976 branch.m_child = otherNode;
977 branch.m_rect = NodeCover(otherNode);
981 return AddBranch(&branch, a_node, a_newNode);
984 else if(a_node->m_level == a_level)
987 return AddBranch(&a_branch, a_node, a_newNode);
1006 bool RTREE_QUAL::InsertRect(
const Branch& a_branch, Node** a_root,
int a_level)
1009 ASSERT(a_level >= 0 && a_level <= (*a_root)->m_level);
1011 for(
int index=0; index < NUMDIMS; ++index)
1013 ASSERT(a_branch.m_rect.m_min[index] <= a_branch.m_rect.m_max[index]);
1019 if(InsertRectRec(a_branch, *a_root, &newNode, a_level))
1022 Node* newRoot = AllocNode();
1023 newRoot->m_level = (*a_root)->m_level + 1;
1028 branch.m_rect = NodeCover(*a_root);
1029 branch.m_child = *a_root;
1030 AddBranch(&branch, newRoot, NULL);
1033 branch.m_rect = NodeCover(newNode);
1034 branch.m_child = newNode;
1035 AddBranch(&branch, newRoot, NULL);
1049 typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(Node* a_node)
1053 Rect rect = a_node->m_branch[0].m_rect;
1054 for(
int index = 1; index < a_node->m_count; ++index)
1056 rect = CombineRect(&rect, &(a_node->m_branch[index].m_rect));
1068 bool RTREE_QUAL::AddBranch(
const Branch* a_branch, Node* a_node, Node** a_newNode)
1073 if(a_node->m_count < MAXNODES)
1075 a_node->m_branch[a_node->m_count] = *a_branch;
1084 SplitNode(a_node, a_branch, a_newNode);
1093 void RTREE_QUAL::DisconnectBranch(Node* a_node,
int a_index)
1095 ASSERT(a_node && (a_index >= 0) && (a_index < MAXNODES));
1096 ASSERT(a_node->m_count > 0);
1099 a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1];
1111 int RTREE_QUAL::PickBranch(
const Rect* a_rect, Node* a_node)
1113 ASSERT(a_rect && a_node);
1115 bool firstTime =
true;
1116 ELEMTYPEREAL increase;
1117 ELEMTYPEREAL bestIncr = (ELEMTYPEREAL)-1;
1119 ELEMTYPEREAL bestArea = (ELEMTYPEREAL)0;
1123 for(
int index=0; index < a_node->m_count; ++index)
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)
1133 bestIncr = increase;
1136 else if((increase == bestIncr) && (area < bestArea))
1140 bestIncr = increase;
1149 typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect(
const Rect* a_rectA,
const Rect* a_rectB)
1151 ASSERT(a_rectA && a_rectB);
1155 for(
int index = 0; index < NUMDIMS; ++index)
1158 newRect.m_min[index] = std::min(a_rectA->m_min[index], a_rectB->m_min[index]);
1160 newRect.m_max[index] = std::max(a_rectA->m_max[index], a_rectB->m_max[index]);
1173 void RTREE_QUAL::SplitNode(Node* a_node,
const Branch* a_branch, Node** a_newNode)
1179 PartitionVars localVars;
1180 PartitionVars* parVars = &localVars;
1183 GetBranches(a_node, a_branch, parVars);
1186 ChoosePartition(parVars, MINNODES);
1189 *a_newNode = AllocNode();
1190 (*a_newNode)->m_level = a_node->m_level;
1193 a_node->m_count = 0;
1194 LoadNodes(a_node, *a_newNode, parVars);
1196 ASSERT((a_node->m_count + (*a_newNode)->m_count) == parVars->m_total);
1202 ELEMTYPEREAL RTREE_QUAL::RectVolume(Rect* a_rect)
1206 ELEMTYPEREAL volume = (ELEMTYPEREAL)1;
1208 for(
int index=0; index<NUMDIMS; ++index)
1210 volume *= a_rect->m_max[index] - a_rect->m_min[index];
1213 ASSERT(volume >= (ELEMTYPEREAL)0);
1221 ELEMTYPEREAL RTREE_QUAL::RectSphericalVolume(Rect* a_rect)
1225 ELEMTYPEREAL sumOfSquares = (ELEMTYPEREAL)0;
1226 ELEMTYPEREAL radius;
1228 for(
int index=0; index < NUMDIMS; ++index)
1230 ELEMTYPEREAL halfExtent = ((ELEMTYPEREAL)a_rect->m_max[index] - (ELEMTYPEREAL)a_rect->m_min[index]) * (ELEMTYPEREAL)0.5;
1231 sumOfSquares += halfExtent * halfExtent;
1234 radius = (ELEMTYPEREAL)sqrt(sumOfSquares);
1239 return (radius * radius * radius * m_unitSphereVolume);
1241 else if(NUMDIMS == 2)
1243 return (radius * radius * m_unitSphereVolume);
1247 return (ELEMTYPEREAL)(pow(radius, NUMDIMS) * m_unitSphereVolume);
1254 ELEMTYPEREAL RTREE_QUAL::CalcRectVolume(Rect* a_rect)
1256 #ifdef RTREE_USE_SPHERICAL_VOLUME
1257 return RectSphericalVolume(a_rect);
1259 return RectVolume(a_rect);
1266 void RTREE_QUAL::GetBranches(Node* a_node,
const Branch* a_branch, PartitionVars* a_parVars)
1271 ASSERT(a_node->m_count == MAXNODES);
1274 for(
int index=0; index < MAXNODES; ++index)
1276 a_parVars->m_branchBuf[index] = a_node->m_branch[index];
1278 a_parVars->m_branchBuf[MAXNODES] = *a_branch;
1279 a_parVars->m_branchCount = MAXNODES + 1;
1282 a_parVars->m_coverSplit = a_parVars->m_branchBuf[0].m_rect;
1283 for(
int index=1; index < MAXNODES+1; ++index)
1285 a_parVars->m_coverSplit = CombineRect(&a_parVars->m_coverSplit, &a_parVars->m_branchBuf[index].m_rect);
1287 a_parVars->m_coverSplitArea = CalcRectVolume(&a_parVars->m_coverSplit);
1303 void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars,
int a_minFill)
1307 ELEMTYPEREAL biggestDiff;
1308 int group, chosen = 0, betterGroup = 0;
1310 InitParVars(a_parVars, a_parVars->m_branchCount, a_minFill);
1311 PickSeeds(a_parVars);
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)))
1317 biggestDiff = (ELEMTYPEREAL) -1;
1318 for(
int index=0; index<a_parVars->m_total; ++index)
1320 if(PartitionVars::NOT_TAKEN == a_parVars->m_partition[index])
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;
1338 if(diff > biggestDiff)
1342 betterGroup = group;
1344 else if((diff == biggestDiff) && (a_parVars->m_count[group] < a_parVars->m_count[betterGroup]))
1347 betterGroup = group;
1351 Classify(chosen, betterGroup, a_parVars);
1355 if((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
1357 if(a_parVars->m_count[0] >= a_parVars->m_total - a_parVars->m_minFill)
1365 for(
int index=0; index<a_parVars->m_total; ++index)
1367 if(PartitionVars::NOT_TAKEN == a_parVars->m_partition[index])
1369 Classify(index, group, a_parVars);
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));
1382 void RTREE_QUAL::LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars)
1388 for(
int index=0; index < a_parVars->m_total; ++index)
1390 ASSERT(a_parVars->m_partition[index] == 0 || a_parVars->m_partition[index] == 1);
1392 int targetNodeIndex = a_parVars->m_partition[index];
1393 Node* targetNodes[] = {a_nodeA, a_nodeB};
1396 AddBranch(&a_parVars->m_branchBuf[index], targetNodes[targetNodeIndex], NULL);
1403 void RTREE_QUAL::InitParVars(PartitionVars* a_parVars,
int a_maxRects,
int a_minFill)
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)
1413 a_parVars->m_partition[index] = PartitionVars::NOT_TAKEN;
1419 void RTREE_QUAL::PickSeeds(PartitionVars* a_parVars)
1421 int seed0 = 0, seed1 = 0;
1422 ELEMTYPEREAL worst, waste;
1423 ELEMTYPEREAL area[MAXNODES+1];
1425 for(
int index=0; index<a_parVars->m_total; ++index)
1427 area[index] = CalcRectVolume(&a_parVars->m_branchBuf[index].m_rect);
1430 worst = -a_parVars->m_coverSplitArea - 1;
1431 for(
int indexA=0; indexA < a_parVars->m_total-1; ++indexA)
1433 for(
int indexB = indexA+1; indexB < a_parVars->m_total; ++indexB)
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];
1446 Classify(seed0, 0, a_parVars);
1447 Classify(seed1, 1, a_parVars);
1453 void RTREE_QUAL::Classify(
int a_index,
int a_group, PartitionVars* a_parVars)
1456 ASSERT(PartitionVars::NOT_TAKEN == a_parVars->m_partition[a_index]);
1458 a_parVars->m_partition[a_index] = a_group;
1461 if (a_parVars->m_count[a_group] == 0)
1463 a_parVars->m_cover[a_group] = a_parVars->m_branchBuf[a_index].m_rect;
1467 a_parVars->m_cover[a_group] = CombineRect(&a_parVars->m_branchBuf[a_index].m_rect, &a_parVars->m_cover[a_group]);
1471 a_parVars->m_area[a_group] = CalcRectVolume(&a_parVars->m_cover[a_group]);
1473 ++a_parVars->m_count[a_group];
1482 bool RTREE_QUAL::RemoveRect(Rect* a_rect,
const DATATYPE& a_id, Node** a_root)
1484 ASSERT(a_rect && a_root);
1487 ListNode* reInsertList = NULL;
1489 if(!RemoveRectRec(a_rect, a_id, *a_root, &reInsertList))
1495 Node* tempNode = reInsertList->m_node;
1497 for(
int index = 0; index < tempNode->m_count; ++index)
1500 InsertRect(tempNode->m_branch[index],
1505 ListNode* remLNode = reInsertList;
1506 reInsertList = reInsertList->m_next;
1508 FreeNode(remLNode->m_node);
1509 FreeListNode(remLNode);
1514 if((*a_root)->m_count == 1 && (*a_root)->IsInternalNode())
1516 Node* tempNode = (*a_root)->m_branch[0].m_child;
1536 bool RTREE_QUAL::RemoveRectRec(Rect* a_rect,
const DATATYPE& a_id, Node* a_node, ListNode** a_listNode)
1538 ASSERT(a_rect && a_node && a_listNode);
1539 ASSERT(a_node->m_level >= 0);
1541 if(a_node->IsInternalNode())
1543 for(
int index = 0; index < a_node->m_count; ++index)
1545 if(Overlap(a_rect, &(a_node->m_branch[index].m_rect)))
1547 if(!RemoveRectRec(a_rect, a_id, a_node->m_branch[index].m_child, a_listNode))
1549 if(a_node->m_branch[index].m_child->m_count >= MINNODES)
1552 a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
1557 ReInsert(a_node->m_branch[index].m_child, a_listNode);
1558 DisconnectBranch(a_node, index);
1568 for(
int index = 0; index < a_node->m_count; ++index)
1570 if(a_node->m_branch[index].m_data == a_id)
1572 DisconnectBranch(a_node, index);
1583 bool RTREE_QUAL::Overlap(Rect* a_rectA, Rect* a_rectB)
const
1585 ASSERT(a_rectA && a_rectB);
1587 for(
int index=0; index < NUMDIMS; ++index)
1589 if (a_rectA->m_min[index] > a_rectB->m_max[index] ||
1590 a_rectB->m_min[index] > a_rectA->m_max[index])
1602 void RTREE_QUAL::ReInsert(Node* a_node, ListNode** a_listNode)
1604 ListNode* newListNode;
1606 newListNode = AllocListNode();
1607 newListNode->m_node = a_node;
1608 newListNode->m_next = *a_listNode;
1609 *a_listNode = newListNode;
1615 bool RTREE_QUAL::Search(Node* a_node, Rect* a_rect,
int& a_foundCount, std::function<
bool (
const DATATYPE&)> callback)
const
1618 ASSERT(a_node->m_level >= 0);
1621 if(a_node->IsInternalNode())
1624 for(
int index=0; index < a_node->m_count; ++index)
1626 if(Overlap(a_rect, &a_node->m_branch[index].m_rect))
1628 if(!Search(a_node->m_branch[index].m_child, a_rect, a_foundCount, callback))
1639 for(
int index=0; index < a_node->m_count; ++index)
1641 if(Overlap(a_rect, &a_node->m_branch[index].m_rect))
1643 DATATYPE&
id = a_node->m_branch[index].m_data;
1646 if(callback && !callback(
id))
1659 std::vector<typename RTREE_QUAL::Rect> RTREE_QUAL::ListTree()
const
1662 ASSERT(m_root->m_level >= 0);
1664 std::vector<Rect> treeList;
1666 std::vector<Node*> toVisit;
1667 toVisit.push_back(m_root);
1669 while (!toVisit.empty()) {
1670 Node* a_node = toVisit.back();
1672 if(a_node->IsInternalNode())
1675 for(
int index=0; index < a_node->m_count; ++index)
1677 treeList.push_back(a_node->m_branch[index].m_rect);
1678 toVisit.push_back(a_node->m_branch[index].m_child);
1684 for(
int index=0; index < a_node->m_count; ++index)
1686 treeList.push_back(a_node->m_branch[index].m_rect);
1695 #undef RTREE_TEMPLATE
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
void GetFirst(Iterator &a_it)
! Get 'first' 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
! 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
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