20#define RTREE_TEMPLATE template<class DATATYPE, class ELEMTYPE, int NUMDIMS, class ELEMTYPEREAL, int TMAXNODES, int TMINNODES>
21#define RTREE_QUAL RTree<DATATYPE, ELEMTYPE, NUMDIMS, ELEMTYPEREAL, TMAXNODES, TMINNODES>
23#define RTREE_DONT_USE_MEMPOOLS
24#define RTREE_USE_SPHERICAL_VOLUME
46template<
class DATATYPE,
class ELEMTYPE,
int NUMDIMS,
47 class ELEMTYPEREAL = ELEMTYPE,
int TMAXNODES = 8,
int TMINNODES = TMAXNODES / 2>
50 static_assert(std::numeric_limits<ELEMTYPEREAL>::is_iec559,
"'ELEMTYPEREAL' accepts floating-point types only");
76 void Insert(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId);
82 void Remove(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId);
90 template<
typename Func>
91 int Search(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS], Func&& callback)
const;
100 bool Load(
const char* a_fileName);
106 bool Save(
const char* a_fileName);
115 enum { MAX_STACK = 32 };
139 StackElement& curTos = m_stack[m_tos - 1];
140 return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
147 StackElement& curTos = m_stack[m_tos - 1];
148 return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
155 void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
158 StackElement& curTos = m_stack[m_tos - 1];
159 Branch& curBranch = curTos.m_node->m_branch[curTos.m_branchIndex];
161 for (
int index = 0; index < NUMDIMS; ++index)
171 void Init() { m_tos = 0; }
182 StackElement curTos = Pop();
184 if (curTos.m_node->IsLeaf())
187 if (curTos.m_branchIndex + 1 < curTos.m_node->m_count)
190 Push(curTos.m_node, curTos.m_branchIndex + 1);
197 if (curTos.m_branchIndex + 1 < curTos.m_node->m_count)
201 Push(curTos.m_node, curTos.m_branchIndex + 1);
204 Node* nextLevelnode = curTos.m_node->m_branch[curTos.m_branchIndex].m_child;
205 Push(nextLevelnode, 0);
208 if (nextLevelnode->IsLeaf())
217 void Push(Node* a_node,
int a_branchIndex)
219 m_stack[m_tos].m_node = a_node;
220 m_stack[m_tos].m_branchIndex = a_branchIndex;
222 assert(m_tos <= MAX_STACK);
230 return m_stack[m_tos];
233 StackElement m_stack[MAX_STACK];
354 template<
typename Func>
355 bool Search(
Node* a_node,
Rect* a_rect,
int& a_foundCount, Func&& callback)
const;
389 bool Open(
const char* a_fileName,
const char* mode)
391#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)
392 return fopen_s(&m_file, a_fileName, mode) == 0;
394 m_file = fopen(a_fileName, mode);
395 return m_file !=
nullptr;
401 return this->
Open(a_fileName,
"rb");
406 return this->
Open(a_fileName,
"wb");
418 template<
typename TYPE >
422 return fwrite((
void*)&a_value,
sizeof(a_value), 1, m_file);
425 template<
typename TYPE >
429 return fwrite((
void*)a_array,
sizeof(TYPE) * a_count, 1, m_file);
432 template<
typename TYPE >
436 return fread((
void*)&a_value,
sizeof(a_value), 1, m_file);
439 template<
typename TYPE >
443 return fread((
void*)a_array,
sizeof(TYPE) * a_count, 1, m_file);
451 assert(MAXNODES > MINNODES);
452 assert(MINNODES > 0);
455 const float UNIT_SPHERE_VOLUMES[] = {
456 0.000000f, 2.000000f, 3.141593f,
457 4.188790f, 4.934802f, 5.263789f,
458 5.167713f, 4.724766f, 4.058712f,
459 3.298509f, 2.550164f, 1.884104f,
460 1.335263f, 0.910629f, 0.599265f,
461 0.381443f, 0.235331f, 0.140981f,
462 0.082146f, 0.046622f, 0.025807f,
465 m_root = AllocNode();
467 m_unitSphereVolume = (ELEMTYPEREAL)UNIT_SPHERE_VOLUMES[NUMDIMS];
486void RTREE_QUAL::Insert(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId)
489 for (
int index = 0; index < NUMDIMS; ++index)
491 assert(a_min[index] <= a_max[index]);
499 for (
int axis = 0; axis < NUMDIMS; ++axis)
505 InsertRect(branch, &m_root, 0);
510void RTREE_QUAL::Remove(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS],
const DATATYPE& a_dataId)
513 for (
int index = 0; index < NUMDIMS; ++index)
515 assert(a_min[index] <= a_max[index]);
521 for (
int axis = 0; axis < NUMDIMS; ++axis)
523 rect.
m_min[axis] = a_min[axis];
524 rect.
m_max[axis] = a_max[axis];
527 RemoveRect(&rect, a_dataId, &m_root);
532template<
typename Func>
533int RTREE_QUAL::Search(
const ELEMTYPE a_min[NUMDIMS],
const ELEMTYPE a_max[NUMDIMS], Func&& callback)
const
536 for (
int index = 0; index < NUMDIMS; ++index)
538 assert(a_min[index] <= a_max[index]);
544 for (
int axis = 0; axis < NUMDIMS; ++axis)
546 rect.
m_min[axis] = a_min[axis];
547 rect.
m_max[axis] = a_max[axis];
553 Search(m_root, &rect, foundCount, std::forward<Func>(callback));
560int RTREE_QUAL::Count()
563 CountRec(m_root, count);
571void RTREE_QUAL::CountRec(
Node* a_node,
int& a_count)
575 for (
int index = 0; index < a_node->
m_count; ++index)
588bool RTREE_QUAL::Load(
const char* a_fileName)
598 bool result = Load(stream);
611 int _dataFileId = (
'R' << 0) | (
'T' << 8) | (
'R' << 16) | (
'E' << 24);
612 int _dataSize =
sizeof(DATATYPE);
613 int _dataNumDims = NUMDIMS;
614 int _dataElemSize =
sizeof(ELEMTYPE);
615 int _dataElemRealSize =
sizeof(ELEMTYPEREAL);
616 int _dataMaxNodes = TMAXNODES;
617 int _dataMinNodes = TMINNODES;
622 int dataElemSize = 0;
623 int dataElemRealSize = 0;
624 int dataMaxNodes = 0;
625 int dataMinNodes = 0;
627 a_stream.
Read(dataFileId);
628 a_stream.
Read(dataSize);
629 a_stream.
Read(dataNumDims);
630 a_stream.
Read(dataElemSize);
631 a_stream.
Read(dataElemRealSize);
632 a_stream.
Read(dataMaxNodes);
633 a_stream.
Read(dataMinNodes);
638 if ((dataFileId == _dataFileId)
639 && (dataSize == _dataSize)
640 && (dataNumDims == _dataNumDims)
641 && (dataElemSize == _dataElemSize)
642 && (dataElemRealSize == _dataElemRealSize)
643 && (dataMaxNodes == _dataMaxNodes)
644 && (dataMinNodes == _dataMinNodes)
648 result = LoadRec(m_root, a_stream);
663 for (
int index = 0; index < a_node->
m_count; ++index)
670 curBranch->
m_child = AllocNode();
671 LoadRec(curBranch->
m_child, a_stream);
676 for (
int index = 0; index < a_node->
m_count; ++index)
692void RTREE_QUAL::CopyRec(
Node* current,
Node* other)
699 for (
int index = 0; index < current->
m_count; ++index)
712 currentBranch->
m_child = AllocNode();
718 for (
int index = 0; index < current->
m_count; ++index)
738bool RTREE_QUAL::Save(
const char* a_fileName)
746 bool result = Save(stream);
758 int dataFileId = (
'R' << 0) | (
'T' << 8) | (
'R' << 16) | (
'E' << 24);
759 int dataSize =
sizeof(DATATYPE);
760 int dataNumDims = NUMDIMS;
761 int dataElemSize =
sizeof(ELEMTYPE);
762 int dataElemRealSize =
sizeof(ELEMTYPEREAL);
763 int dataMaxNodes = TMAXNODES;
764 int dataMinNodes = TMINNODES;
766 a_stream.
Write(dataFileId);
767 a_stream.
Write(dataSize);
768 a_stream.
Write(dataNumDims);
769 a_stream.
Write(dataElemSize);
770 a_stream.
Write(dataElemRealSize);
771 a_stream.
Write(dataMaxNodes);
772 a_stream.
Write(dataMinNodes);
775 bool result = SaveRec(m_root, a_stream);
789 for (
int index = 0; index < a_node->
m_count; ++index)
796 SaveRec(curBranch->
m_child, a_stream);
801 for (
int index = 0; index < a_node->
m_count; ++index)
817void RTREE_QUAL::RemoveAll()
822 m_root = AllocNode();
828void RTREE_QUAL::Reset()
830#ifdef RTREE_DONT_USE_MEMPOOLS
832 RemoveAllRec(m_root);
841void RTREE_QUAL::RemoveAllRec(
Node* a_node)
848 for (
int index = 0; index < a_node->
m_count; ++index)
858typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode()
861#ifdef RTREE_DONT_USE_MEMPOOLS
872void RTREE_QUAL::FreeNode(
Node* a_node)
876#ifdef RTREE_DONT_USE_MEMPOOLS
887typename RTREE_QUAL::ListNode* RTREE_QUAL::AllocListNode()
889#ifdef RTREE_DONT_USE_MEMPOOLS
900#ifdef RTREE_DONT_USE_MEMPOOLS
909void RTREE_QUAL::InitNode(
Node* a_node)
917void RTREE_QUAL::InitRect(
Rect* a_rect)
919 for (
int index = 0; index < NUMDIMS; ++index)
921 a_rect->
m_min[index] = (ELEMTYPE)0;
922 a_rect->
m_max[index] = (ELEMTYPE)0;
935bool RTREE_QUAL::InsertRectRec(
const Branch& a_branch,
Node* a_node,
Node** a_newNode,
int a_level)
937 assert(a_node && a_newNode);
938 assert(a_level >= 0 && a_level <= a_node->m_level);
948 int index = PickBranch(&a_branch.
m_rect, a_node);
951 bool childWasSplit = InsertRectRec(a_branch, a_node->
m_branch[index].
m_child, &otherNode, a_level);
967 branch.
m_rect = NodeCover(otherNode);
971 return AddBranch(&branch, a_node, a_newNode);
974 else if (a_node->
m_level == a_level)
977 return AddBranch(&a_branch, a_node, a_newNode);
996bool RTREE_QUAL::InsertRect(
const Branch& a_branch,
Node** a_root,
int a_level)
999 assert(a_level >= 0 && a_level <= (*a_root)->m_level);
1001 for (
int index = 0; index < NUMDIMS; ++index)
1009 if (InsertRectRec(a_branch, *a_root, &newNode, a_level))
1012 Node* newRoot = AllocNode();
1013 newRoot->
m_level = (*a_root)->m_level + 1;
1018 branch.
m_rect = NodeCover(*a_root);
1020 AddBranch(&branch, newRoot,
NULL);
1023 branch.
m_rect = NodeCover(newNode);
1025 AddBranch(&branch, newRoot,
NULL);
1039typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(
Node* a_node)
1044 for (
int index = 1; index < a_node->
m_count; ++index)
1063 if (a_node->
m_count < MAXNODES)
1074 SplitNode(a_node, a_branch, a_newNode);
1083void RTREE_QUAL::DisconnectBranch(
Node* a_node,
int a_index)
1085 assert(a_node && (a_index >= 0) && (a_index < MAXNODES));
1101int RTREE_QUAL::PickBranch(
const Rect* a_rect,
Node* a_node)
1103 assert(a_rect && a_node);
1105 bool firstTime =
true;
1106 ELEMTYPEREAL increase;
1107 ELEMTYPEREAL bestIncr = (ELEMTYPEREAL)-1;
1109 ELEMTYPEREAL bestArea = 0;
1113 for (
int index = 0; index < a_node->
m_count; ++index)
1116 area = CalcRectVolume(curRect);
1117 tempRect = CombineRect(a_rect, curRect);
1118 increase = CalcRectVolume(&tempRect) - area;
1119 if ((increase < bestIncr) || firstTime)
1123 bestIncr = increase;
1126 else if ((increase == bestIncr) && (area < bestArea))
1130 bestIncr = increase;
1139typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect(
const Rect* a_rectA,
const Rect* a_rectB)
1141 assert(a_rectA && a_rectB);
1145 for (
int index = 0; index < NUMDIMS; ++index)
1147 newRect.
m_min[index] = std::min(a_rectA->
m_min[index], a_rectB->
m_min[index]);
1148 newRect.
m_max[index] = std::max(a_rectA->
m_max[index], a_rectB->
m_max[index]);
1171 GetBranches(a_node, a_branch, parVars);
1174 ChoosePartition(parVars, MINNODES);
1177 *a_newNode = AllocNode();
1178 (*a_newNode)->m_level = a_node->
m_level;
1182 LoadNodes(a_node, *a_newNode, parVars);
1184 assert((a_node->
m_count + (*a_newNode)->m_count) == parVars->
m_total);
1190ELEMTYPEREAL RTREE_QUAL::RectVolume(
Rect* a_rect)
1194 ELEMTYPEREAL volume = (ELEMTYPEREAL)1;
1196 for (
int index = 0; index < NUMDIMS; ++index)
1198 volume *= a_rect->
m_max[index] - a_rect->
m_min[index];
1201 assert(volume >= (ELEMTYPEREAL)0);
1209ELEMTYPEREAL RTREE_QUAL::RectSphericalVolume(
Rect* a_rect)
1213 ELEMTYPEREAL sumOfSquares = (ELEMTYPEREAL)0;
1214 ELEMTYPEREAL radius;
1216 for (
int index = 0; index < NUMDIMS; ++index)
1218 ELEMTYPEREAL halfExtent = ((ELEMTYPEREAL)a_rect->
m_max[index] - (ELEMTYPEREAL)a_rect->
m_min[index]) * (ELEMTYPEREAL)0.5;
1219 sumOfSquares += halfExtent * halfExtent;
1222 radius = (ELEMTYPEREAL)sqrt(sumOfSquares);
1227 return (radius * radius * radius * m_unitSphereVolume);
1229 else if (NUMDIMS == 2)
1231 return (radius * radius * m_unitSphereVolume);
1235 return (ELEMTYPEREAL)(pow(radius, NUMDIMS) * m_unitSphereVolume);
1242ELEMTYPEREAL RTREE_QUAL::CalcRectVolume(
Rect* a_rect)
1244#ifdef RTREE_USE_SPHERICAL_VOLUME
1245 return RectSphericalVolume(a_rect);
1247 return RectVolume(a_rect);
1259 assert(a_node->
m_count == MAXNODES);
1262 for (
int index = 0; index < MAXNODES; ++index)
1271 for (
int index = 1; index < MAXNODES + 1; ++index)
1295 ELEMTYPEREAL biggestDiff;
1296 int group, chosen = 0, betterGroup = 0;
1298 InitParVars(a_parVars, a_parVars->
m_branchCount, a_minFill);
1299 PickSeeds(a_parVars);
1305 biggestDiff = (ELEMTYPEREAL)-1;
1306 for (
int index = 0; index < a_parVars->
m_total; ++index)
1308 if (PartitionVars::NOT_TAKEN == a_parVars->
m_partition[index])
1311 Rect rect0 = CombineRect(curRect, &a_parVars->
m_cover[0]);
1312 Rect rect1 = CombineRect(curRect, &a_parVars->
m_cover[1]);
1313 ELEMTYPEREAL growth0 = CalcRectVolume(&rect0) - a_parVars->
m_area[0];
1314 ELEMTYPEREAL growth1 = CalcRectVolume(&rect1) - a_parVars->
m_area[1];
1315 ELEMTYPEREAL diff = growth1 - growth0;
1326 if (diff > biggestDiff)
1330 betterGroup = group;
1332 else if ((diff == biggestDiff) && (a_parVars->
m_count[group] < a_parVars->
m_count[betterGroup]))
1335 betterGroup = group;
1339 Classify(chosen, betterGroup, a_parVars);
1353 for (
int index = 0; index < a_parVars->
m_total; ++index)
1355 if (PartitionVars::NOT_TAKEN == a_parVars->
m_partition[index])
1357 Classify(index, group, a_parVars);
1376 for (
int index = 0; index < a_parVars->
m_total; ++index)
1380 int targetNodeIndex = a_parVars->
m_partition[index];
1381 Node* targetNodes[] = { a_nodeA, a_nodeB };
1384 bool nodeWasSplit = AddBranch(&a_parVars->
m_branchBuf[index], targetNodes[targetNodeIndex],
NULL);
1385 assert(!nodeWasSplit);
1392void RTREE_QUAL::InitParVars(
PartitionVars* a_parVars,
int a_maxRects,
int a_minFill)
1397 a_parVars->
m_area[0] = a_parVars->
m_area[1] = (ELEMTYPEREAL)0;
1398 a_parVars->
m_total = a_maxRects;
1400 for (
int index = 0; index < a_maxRects; ++index)
1402 a_parVars->
m_partition[index] = PartitionVars::NOT_TAKEN;
1410 int seed0 = 0, seed1 = 0;
1411 ELEMTYPEREAL worst, waste;
1412 ELEMTYPEREAL area[MAXNODES + 1];
1414 for (
int index = 0; index < a_parVars->
m_total; ++index)
1420 for (
int indexA = 0; indexA < a_parVars->
m_total - 1; ++indexA)
1422 for (
int indexB = indexA + 1; indexB < a_parVars->
m_total; ++indexB)
1425 waste = CalcRectVolume(&oneRect) - area[indexA] - area[indexB];
1435 Classify(seed0, 0, a_parVars);
1436 Classify(seed1, 1, a_parVars);
1445 assert(PartitionVars::NOT_TAKEN == a_parVars->
m_partition[a_index]);
1450 if (a_parVars->
m_count[a_group] == 0)
1460 a_parVars->
m_area[a_group] = CalcRectVolume(&a_parVars->
m_cover[a_group]);
1462 ++a_parVars->
m_count[a_group];
1471bool RTREE_QUAL::RemoveRect(
Rect* a_rect,
const DATATYPE& a_id,
Node** a_root)
1473 assert(a_rect && a_root);
1478 if (!RemoveRectRec(a_rect, a_id, *a_root, &reInsertList))
1482 while (reInsertList)
1486 for (
int index = 0; index < tempNode->
m_count; ++index)
1489 InsertRect(tempNode->
m_branch[index],
1495 reInsertList = reInsertList->
m_next;
1497 FreeNode(remLNode->
m_node);
1498 FreeListNode(remLNode);
1503 if ((*a_root)->m_count == 1 && (*a_root)->IsInternalNode())
1525bool RTREE_QUAL::RemoveRectRec(
Rect* a_rect,
const DATATYPE& a_id,
Node* a_node,
ListNode** a_listNode)
1527 assert(a_rect && a_node && a_listNode);
1532 for (
int index = 0; index < a_node->
m_count; ++index)
1536 if (!RemoveRectRec(a_rect, a_id, a_node->
m_branch[index].
m_child, a_listNode))
1547 DisconnectBranch(a_node, index);
1557 for (
int index = 0; index < a_node->
m_count; ++index)
1561 DisconnectBranch(a_node, index);
1572bool RTREE_QUAL::Overlap(
Rect* a_rectA,
Rect* a_rectB)
const
1574 assert(a_rectA && a_rectB);
1576 for (
int index = 0; index < NUMDIMS; ++index)
1578 if (a_rectA->
m_min[index] > a_rectB->
m_max[index] ||
1579 a_rectB->
m_min[index] > a_rectA->
m_max[index])
1595 newListNode = AllocListNode();
1596 newListNode->
m_node = a_node;
1597 newListNode->
m_next = *a_listNode;
1598 *a_listNode = newListNode;
1604template<
typename Func>
1605bool RTREE_QUAL::Search(
Node* a_node,
Rect* a_rect,
int& a_foundCount, Func&& callback)
const
1614 for (
int index = 0; index < a_node->
m_count; ++index)
1618 if (!Search(a_node->
m_branch[index].
m_child, a_rect, a_foundCount, std::forward<Func>(callback)))
1629 for (
int index = 0; index < a_node->
m_count; ++index)
1648#undef RTREE_TEMPLATE
size_t Read(TYPE &a_value)
size_t Write(const TYPE &a_value)
bool Open(const char *a_fileName, const char *mode)
size_t WriteArray(const TYPE *a_array, int a_count)
bool OpenWrite(const char *a_fileName)
bool OpenRead(const char *a_fileName)
size_t ReadArray(TYPE *a_array, int a_count)
Iterator is not remove safe.
bool IsNull()
Is iterator invalid.
void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
Get the bounds for this node.
const DATATYPE & operator*() const
Access the current data element. Caller must be sure iterator is not NULL first.
bool IsNotNull()
Is iterator pointing to valid data.
DATATYPE & operator*()
Access the current data element. Caller must be sure iterator is not NULL first.
bool operator++()
Find the next data element.
Implementation of RTree, a multidimensional bounding rectangle tree.
@ MINNODES
Min elements in node.
@ MAXNODES
Max elements in node.
bool InsertRect(const Branch &a_branch, Node **a_root, int a_level)
void FreeListNode(ListNode *a_listNode)
bool AddBranch(const Branch *a_branch, Node *a_node, Node **a_newNode)
int PickBranch(const Rect *a_rect, Node *a_node)
void Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)
Remove entry.
void CountRec(Node *a_node, int &a_count)
ELEMTYPEREAL CalcRectVolume(Rect *a_rect)
void ChoosePartition(PartitionVars *a_parVars, int a_minFill)
void RemoveAll()
Remove all entries from tree.
void GetBranches(Node *a_node, const Branch *a_branch, PartitionVars *a_parVars)
void GetNext(Iterator &a_it)
Get Next for iteration.
Node * m_root
Root of tree.
void RemoveAllRec(Node *a_node)
bool RemoveRectRec(Rect *a_rect, const DATATYPE &a_id, Node *a_node, ListNode **a_listNode)
bool SaveRec(Node *a_node, RTFileStream &a_stream)
void ReInsert(Node *a_node, ListNode **a_listNode)
void Classify(int a_index, int a_group, PartitionVars *a_parVars)
Rect NodeCover(Node *a_node)
bool RemoveRect(Rect *a_rect, const DATATYPE &a_id, Node **a_root)
bool Save(const char *a_fileName)
Save tree contents to file.
void FreeNode(Node *a_node)
ELEMTYPEREAL RectSphericalVolume(Rect *a_rect)
int Count()
Count the data elements in this container. This is slow as no internal counter is maintained.
void LoadNodes(Node *a_nodeA, Node *a_nodeB, PartitionVars *a_parVars)
bool IsNull(Iterator &a_it)
Is iterator NULL, or at end?
DATATYPE & GetAt(Iterator &a_it)
Get object at iterator position.
ListNode * AllocListNode()
void Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)
Insert entry.
int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], Func &&callback) const
Find all within search rectangle.
Rect CombineRect(const Rect *a_rectA, const Rect *a_rectB)
void InitRect(Rect *a_rect)
void InitNode(Node *a_node)
void CopyRec(Node *current, Node *other)
bool LoadRec(Node *a_node, RTFileStream &a_stream)
void InitParVars(PartitionVars *a_parVars, int a_maxRects, int a_minFill)
bool Overlap(Rect *a_rectA, Rect *a_rectB) const
void GetFirst(Iterator &a_it)
Get 'first' for iteration.
bool Load(const char *a_fileName)
Load tree contents from file.
void DisconnectBranch(Node *a_node, int a_index)
void SplitNode(Node *a_node, const Branch *a_branch, Node **a_newNode)
ELEMTYPEREAL m_unitSphereVolume
Unit sphere constant for required number of dimensions.
void PickSeeds(PartitionVars *a_parVars)
bool InsertRectRec(const Branch &a_branch, Node *a_node, Node **a_newNode, int a_level)
ELEMTYPEREAL RectVolume(Rect *a_rect)
May be data or may be another subtree The parents level determines this.
Node * m_child
Child node.
A link list of nodes for reinsertion after a delete operation.
ListNode * m_next
Next in list.
Node for each branch level.
int m_level
Leaf is zero, others positive.
Branch m_branch[MAXNODES]
Branch.
Variables for finding a split partition.
int m_partition[MAXNODES+1]
Branch m_branchBuf[MAXNODES+1]
ELEMTYPEREAL m_coverSplitArea
Minimal bounding rectangle (n-dimensional)
ELEMTYPE m_min[NUMDIMS]
Min dimensions of bounding box.
ELEMTYPE m_max[NUMDIMS]
Max dimensions of bounding box.