20#ifndef DYNAMIC_RTREE_H
21#define DYNAMIC_RTREE_H
58template <
class DATATYPE,
class ELEMTYPE =
int,
int NUMDIMS = 2,
int TMAXNODES = 16>
85 aOther.m_root =
nullptr;
97 aOther.m_root =
nullptr;
111 void Insert(
const ELEMTYPE aMin[NUMDIMS],
const ELEMTYPE aMax[NUMDIMS],
112 const DATATYPE& aData )
122 uint32_t reinsertedLevels = 0;
124 insertImpl( aMin, aMax, aData, reinsertedLevels );
133 bool Remove(
const ELEMTYPE aMin[NUMDIMS],
const ELEMTYPE aMax[NUMDIMS],
134 const DATATYPE& aData )
140 std::vector<NODE*> reinsertList;
151 ELEMTYPE fullMin[NUMDIMS];
152 ELEMTYPE fullMax[NUMDIMS];
154 for(
int d = 0; d < NUMDIMS; ++d )
156 fullMin[d] = std::numeric_limits<ELEMTYPE>::lowest();
157 fullMax[d] = std::numeric_limits<ELEMTYPE>::max();
160 reinsertList.clear();
181 template <
class VISITOR>
182 int Search(
const ELEMTYPE aMin[NUMDIMS],
const ELEMTYPE aMax[NUMDIMS],
183 VISITOR& aVisitor )
const
226 if( aEntries.empty() )
235 ELEMTYPE globalMin[NUMDIMS], globalMax[NUMDIMS];
237 for(
int d = 0; d < NUMDIMS; ++d )
239 globalMin[d] = std::numeric_limits<ELEMTYPE>::max();
240 globalMax[d] = std::numeric_limits<ELEMTYPE>::lowest();
243 for(
const auto& entry : aEntries )
245 for(
int d = 0; d < NUMDIMS; ++d )
247 if( entry.min[d] < globalMin[d] )
248 globalMin[d] = entry.min[d];
250 if( entry.max[d] > globalMax[d] )
251 globalMax[d] = entry.max[d];
256 double range[NUMDIMS];
258 for(
int d = 0; d < NUMDIMS; ++d )
260 range[d] =
static_cast<double>( globalMax[d] ) - globalMin[d];
262 if( range[d] <= 0.0 )
268 size_t n = aEntries.size();
269 std::vector<std::pair<uint64_t, size_t>> order( n );
271 for(
size_t i = 0; i < n; ++i )
273 const BULK_ENTRY& entry = aEntries[i];
274 uint32_t coords[NUMDIMS];
276 for(
int d = 0; d < NUMDIMS; ++d )
278 double center = (
static_cast<double>( entry.min[d] ) + entry.max[d] ) / 2.0;
280 coords[d] =
static_cast<uint32_t
>( ( (
center - globalMin[d] ) / range[d] )
281 *
static_cast<double>( UINT32_MAX ) );
287 std::sort( order.begin(), order.end() );
296 std::vector<NODE*> currentLevel;
299 for(
size_t i = 0; i < n; i +=
MAXNODES )
303 int cnt =
static_cast<int>( std::min<size_t>(
MAXNODES, n - i ) );
305 for(
int j = 0; j < cnt; ++j )
307 const auto& entry = aEntries[order[i + j].second];
310 leaf->
data[j] = entry.data;
314 currentLevel.push_back( leaf );
320 while( currentLevel.size() > 1 )
322 size_t levelSize = currentLevel.size();
323 std::vector<NODE*> nextLevel;
326 for(
size_t i = 0; i < levelSize; i +=
MAXNODES )
329 internal->
level = level;
330 int cnt =
static_cast<int>( std::min<size_t>(
MAXNODES, levelSize - i ) );
332 for(
int j = 0; j < cnt; ++j )
334 NODE* child = currentLevel[i + j];
335 ELEMTYPE childMin[NUMDIMS], childMax[NUMDIMS];
341 internal->
count = cnt;
342 nextLevel.push_back( internal );
345 currentLevel = std::move( nextLevel );
379 if( aRoot && aRoot->
count > 0 )
381 m_stack.push_back( { aRoot, 0 } );
406 return !( *
this == aOther );
422 if(
top.node->IsLeaf() )
424 if(
top.childIdx <
top.node->count )
436 if(
top.childIdx <
top.node->count )
438 NODE* child =
top.node->children[
top.childIdx];
440 m_stack.push_back( { child, 0 } );
458 Iterator
end()
const {
return Iterator(); }
476 const ELEMTYPE aMax[NUMDIMS] )
478 for(
int d = 0; d < NUMDIMS; ++d )
484 if( aRoot && aRoot->
count > 0 )
486 m_stack.push_back( { aRoot, 0 } );
510 return !( *
this == aOther );
526 if(
top.node->IsLeaf() )
528 while(
top.childIdx <
top.node->count )
545 bool descended =
false;
547 while(
top.childIdx <
top.node->count )
551 NODE* child =
top.node->children[
top.childIdx];
553 m_stack.push_back( { child, 0 } );
584 const ELEMTYPE aMax[NUMDIMS] ) :
587 for(
int d = 0; d < NUMDIMS; ++d )
610 const ELEMTYPE aMax[NUMDIMS] )
const
612 return SearchRange(
m_root, aMin, aMax );
623 std::vector<std::pair<int64_t, DATATYPE>>& aResults )
const
630 using QueueEntry = std::pair<int64_t, std::pair<NODE*, int>>;
632 auto cmp = [](
const QueueEntry& a,
const QueueEntry& b )
634 return a.first > b.first;
636 std::priority_queue<QueueEntry, std::vector<QueueEntry>,
decltype( cmp )> pq( cmp );
639 for(
int i = 0; i <
m_root->count; ++i )
642 pq.push( { dist, {
m_root, i } } );
645 while( !pq.empty() &&
static_cast<int>( aResults.size() ) < aK )
647 auto [dist, entry] = pq.top();
649 NODE* node = entry.first;
650 int slot = entry.second;
654 aResults.push_back( { dist, node->
data[slot] } );
660 for(
int i = 0; i < child->
count; ++i )
662 int64_t childDist =
minDistSq( child, i, aPoint );
663 pq.push( { childDist, { child, i } } );
698 for(
int i = 0; i < aNode->
count; ++i )
708 void insertImpl(
const ELEMTYPE aMin[NUMDIMS],
const ELEMTYPE aMax[NUMDIMS],
709 const DATATYPE& aData, uint32_t& aReinsertedLevels )
712 std::vector<NODE*>
path;
718 int slot = leaf->
count;
721 leaf->
data[slot] = aData;
739 const ELEMTYPE aMax[NUMDIMS], std::vector<NODE*>& aPath )
746 aPath.push_back( node );
748 if( node->
level == 1 )
752 int64_t bestOverlapInc = std::numeric_limits<int64_t>::max();
753 int64_t bestAreaInc = std::numeric_limits<int64_t>::max();
754 int64_t bestArea = std::numeric_limits<int64_t>::max();
756 for(
int i = 0; i < node->
count; ++i )
760 int64_t overlapInc = overlapAfter - overlapBefore;
764 if( overlapInc < bestOverlapInc
765 || ( overlapInc == bestOverlapInc && areaInc < bestAreaInc )
766 || ( overlapInc == bestOverlapInc && areaInc == bestAreaInc
767 && area < bestArea ) )
770 bestOverlapInc = overlapInc;
771 bestAreaInc = areaInc;
782 int64_t bestAreaInc = std::numeric_limits<int64_t>::max();
783 int64_t bestArea = std::numeric_limits<int64_t>::max();
785 for(
int i = 0; i < node->
count; ++i )
790 if( areaInc < bestAreaInc
791 || ( areaInc == bestAreaInc && area < bestArea ) )
794 bestAreaInc = areaInc;
810 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
811 std::vector<NODE*>& aPath, uint32_t& aReinsertedLevels )
813 int level = aNode->
level;
819 splitNode( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
823 const uint32_t levelMask = 1U << level;
825 if( !( aReinsertedLevels & levelMask ) )
827 aReinsertedLevels |= levelMask;
828 forcedReinsert( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
832 splitNode( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
843 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
844 std::vector<NODE*>& aPath, uint32_t& aReinsertedLevels )
849 ELEMTYPE min[NUMDIMS];
850 ELEMTYPE max[NUMDIMS];
851 ELEMTYPE insertMin[NUMDIMS];
852 ELEMTYPE insertMax[NUMDIMS];
858 int totalEntries = aNode->
count + 1;
859 std::vector<ENTRY> entries( totalEntries );
862 ELEMTYPE nodeMin[NUMDIMS];
863 ELEMTYPE nodeMax[NUMDIMS];
868 for(
int d = 0; d < NUMDIMS; ++d )
869 center[d] = (
static_cast<double>( nodeMin[d] ) + nodeMax[d] ) / 2.0;
872 for(
int i = 0; i < aNode->
count; ++i )
878 aNode->
GetInsertBounds( i, entries[i].insertMin, entries[i].insertMax );
879 entries[i].data = aNode->
data[i];
880 entries[i].child =
nullptr;
884 entries[i].child = aNode->
children[i];
890 for(
int d = 0; d < NUMDIMS; ++d )
892 double entryCenter = (
static_cast<double>( entries[i].min[d] )
893 + entries[i].max[d] ) / 2.0;
894 double diff = entryCenter -
center[d];
895 distSq +=
static_cast<int64_t
>( diff * diff );
898 entries[i].distSq = distSq;
902 ENTRY& newEntry = entries[aNode->
count];
904 for(
int d = 0; d < NUMDIMS; ++d )
906 newEntry.min[d] = aMin[d];
907 newEntry.max[d] = aMax[d];
908 newEntry.insertMin[d] = aMin[d];
909 newEntry.insertMax[d] = aMax[d];
912 newEntry.data = aData;
913 newEntry.child =
nullptr;
917 for(
int d = 0; d < NUMDIMS; ++d )
919 double entryCenter = (
static_cast<double>( aMin[d] ) + aMax[d] ) / 2.0;
920 double diff = entryCenter -
center[d];
921 distSq +=
static_cast<int64_t
>( diff * diff );
924 newEntry.distSq = distSq;
927 std::sort( entries.begin(), entries.end(),
928 [](
const ENTRY& a,
const ENTRY& b )
930 return a.distSq > b.distSq;
936 if( reinsertCount <= 0 )
939 splitNode( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
946 for(
int i = reinsertCount; i < totalEntries; ++i )
948 int slot = aNode->
count;
953 aNode->
SetInsertBounds( slot, entries[i].insertMin, entries[i].insertMax );
954 aNode->
data[slot] = entries[i].data;
958 aNode->
children[slot] = entries[i].child;
967 for(
int i = 0; i < reinsertCount; ++i )
971 insertImpl( entries[i].insertMin, entries[i].insertMax,
972 entries[i].data, aReinsertedLevels );
976 reinsertNode( entries[i].child, entries[i].min, entries[i].max,
977 aNode->
level - 1, aReinsertedLevels );
986 const ELEMTYPE aMax[NUMDIMS],
int aLevel,
987 uint32_t& aReinsertedLevels )
990 std::vector<NODE*>
path;
995 int slot = target->
count;
1011 const ELEMTYPE aMax[NUMDIMS],
int aTargetLevel,
1012 std::vector<NODE*>& aPath )
1017 while( node->
level > aTargetLevel )
1019 aPath.push_back( node );
1022 int64_t bestAreaInc = std::numeric_limits<int64_t>::max();
1023 int64_t bestArea = std::numeric_limits<int64_t>::max();
1025 for(
int i = 0; i < node->
count; ++i )
1030 if( areaInc < bestAreaInc
1031 || ( areaInc == bestAreaInc && area < bestArea ) )
1034 bestAreaInc = areaInc;
1054 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
1055 std::vector<NODE*>& aPath, uint32_t& aReinsertedLevels )
1058 int totalEntries = aNode->
count + 1;
1059 std::vector<SPLIT_ENTRY> entries( totalEntries );
1061 for(
int i = 0; i < aNode->
count; ++i )
1067 aNode->
GetInsertBounds( i, entries[i].insertMin, entries[i].insertMax );
1068 entries[i].data = aNode->
data[i];
1069 entries[i].child =
nullptr;
1073 entries[i].child = aNode->
children[i];
1078 for(
int d = 0; d < NUMDIMS; ++d )
1080 entries[aNode->
count].min[d] = aMin[d];
1081 entries[aNode->
count].max[d] = aMax[d];
1082 entries[aNode->
count].insertMin[d] = aMin[d];
1083 entries[aNode->
count].insertMax[d] = aMax[d];
1086 entries[aNode->
count].data = aData;
1087 entries[aNode->
count].child =
nullptr;
1091 int64_t bestPerimeterSum = std::numeric_limits<int64_t>::max();
1093 for(
int axis = 0; axis < NUMDIMS; ++axis )
1095 int64_t perimeterSum = 0;
1098 std::sort( entries.begin(), entries.end(),
1099 [axis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1101 return a.min[axis] < b.min[axis]
1102 || ( a.min[axis] == b.min[axis]
1103 && a.max[axis] < b.max[axis] );
1109 std::sort( entries.begin(), entries.end(),
1110 [axis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1112 return a.max[axis] < b.max[axis]
1113 || ( a.max[axis] == b.max[axis]
1114 && a.min[axis] < b.min[axis] );
1119 if( perimeterSum < bestPerimeterSum )
1121 bestPerimeterSum = perimeterSum;
1128 std::sort( entries.begin(), entries.end(),
1129 [bestAxis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1131 return a.min[bestAxis] < b.min[bestAxis]
1132 || ( a.min[bestAxis] == b.min[bestAxis]
1133 && a.max[bestAxis] < b.max[bestAxis] );
1139 std::vector<SPLIT_ENTRY> entriesByMax = entries;
1141 std::sort( entriesByMax.begin(), entriesByMax.end(),
1142 [bestAxis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1144 return a.max[bestAxis] < b.max[bestAxis]
1145 || ( a.max[bestAxis] == b.max[bestAxis]
1146 && a.min[bestAxis] < b.min[bestAxis] );
1153 if( overlapMax < overlapMin )
1155 entries = std::move( entriesByMax );
1156 bestSplit = bestSplitMax;
1166 for(
int i = 0; i < bestSplit; ++i )
1168 int slot = aNode->
count;
1173 aNode->
SetInsertBounds( slot, entries[i].insertMin, entries[i].insertMax );
1174 aNode->
data[slot] = entries[i].data;
1178 aNode->
children[slot] = entries[i].child;
1184 for(
int i = bestSplit; i < totalEntries; ++i )
1186 int slot = sibling->
count;
1192 entries[i].insertMax );
1193 sibling->
data[slot] = entries[i].data;
1197 sibling->
children[slot] = entries[i].child;
1204 ELEMTYPE sibMin[NUMDIMS], sibMax[NUMDIMS];
1213 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1225 NODE* parent = aPath.back();
1230 if( childSlot >= 0 )
1232 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1240 int slot = parent->
count;
1260 const ELEMTYPE aMax[NUMDIMS],
NODE* aChild,
1261 std::vector<NODE*>& aPath,
1262 uint32_t& aReinsertedLevels )
1264 int totalEntries = aNode->
count + 1;
1265 std::vector<SPLIT_ENTRY> entries( totalEntries );
1267 for(
int i = 0; i < aNode->
count; ++i )
1270 entries[i].child = aNode->
children[i];
1273 for(
int d = 0; d < NUMDIMS; ++d )
1275 entries[aNode->
count].min[d] = aMin[d];
1276 entries[aNode->
count].max[d] = aMax[d];
1279 entries[aNode->
count].child = aChild;
1283 int64_t bestPerimeterSum = std::numeric_limits<int64_t>::max();
1285 for(
int axis = 0; axis < NUMDIMS; ++axis )
1287 std::sort( entries.begin(), entries.end(),
1288 [axis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1290 return a.min[axis] < b.min[axis];
1295 if( perimSum < bestPerimeterSum )
1297 bestPerimeterSum = perimSum;
1303 std::sort( entries.begin(), entries.end(),
1304 [bestAxis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1306 return a.min[bestAxis] < b.min[bestAxis];
1317 for(
int i = 0; i < bestSplit; ++i )
1319 int slot = aNode->
count;
1321 aNode->
children[slot] = entries[i].child;
1325 for(
int i = bestSplit; i < totalEntries; ++i )
1327 int slot = sibling->
count;
1329 sibling->
children[slot] = entries[i].child;
1333 ELEMTYPE sibMin[NUMDIMS], sibMax[NUMDIMS];
1341 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1353 NODE* parent = aPath.back();
1356 if( childSlot >= 0 )
1358 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1365 int slot = parent->
count;
1376 aReinsertedLevels );
1384 template <
class ENTRY_VEC>
1393 for(
int grp = 0; grp < 2; ++grp )
1395 int start = ( grp == 0 ) ? 0 : k;
1396 int end = ( grp == 0 ) ? k : aTotalEntries;
1398 int64_t perimeter = 0;
1400 for(
int d = 0; d < NUMDIMS; ++d )
1402 ELEMTYPE mn = std::numeric_limits<ELEMTYPE>::max();
1403 ELEMTYPE mx = std::numeric_limits<ELEMTYPE>::lowest();
1405 for(
int i = start; i <
end; ++i )
1407 if( aEntries[i].min[d] < mn )
1408 mn = aEntries[i].min[d];
1410 if( aEntries[i].max[d] > mx )
1411 mx = aEntries[i].max[d];
1414 perimeter +=
static_cast<int64_t
>( mx ) - mn;
1417 sum += 2 * perimeter;
1427 template <
class ENTRY_VEC>
1431 int64_t bestOverlap = std::numeric_limits<int64_t>::max();
1432 int64_t bestAreaSum = std::numeric_limits<int64_t>::max();
1439 int64_t areaSum = 0;
1441 for(
int grp = 0; grp < 2; ++grp )
1443 int start = ( grp == 0 ) ? 0 : k;
1444 int end = ( grp == 0 ) ? k : aTotalEntries;
1447 for(
int d = 0; d < NUMDIMS; ++d )
1449 ELEMTYPE mn = std::numeric_limits<ELEMTYPE>::max();
1450 ELEMTYPE mx = std::numeric_limits<ELEMTYPE>::lowest();
1452 for(
int i = start; i <
end; ++i )
1454 if( aEntries[i].min[d] < mn )
1455 mn = aEntries[i].min[d];
1457 if( aEntries[i].max[d] > mx )
1458 mx = aEntries[i].max[d];
1461 area *=
static_cast<int64_t
>( mx ) - mn;
1467 if( overlap < bestOverlap
1468 || ( overlap == bestOverlap && areaSum < bestAreaSum ) )
1471 bestOverlap = overlap;
1472 bestAreaSum = areaSum;
1482 template <
class ENTRY_VEC>
1484 int aTotalEntries )
const
1486 ELEMTYPE g1Min[NUMDIMS], g1Max[NUMDIMS];
1487 ELEMTYPE g2Min[NUMDIMS], g2Max[NUMDIMS];
1489 for(
int d = 0; d < NUMDIMS; ++d )
1491 g1Min[d] = g2Min[d] = std::numeric_limits<ELEMTYPE>::max();
1492 g1Max[d] = g2Max[d] = std::numeric_limits<ELEMTYPE>::lowest();
1495 for(
int i = 0; i < aSplitIdx; ++i )
1497 for(
int d = 0; d < NUMDIMS; ++d )
1499 if( aEntries[i].min[d] < g1Min[d] )
1500 g1Min[d] = aEntries[i].min[d];
1502 if( aEntries[i].max[d] > g1Max[d] )
1503 g1Max[d] = aEntries[i].max[d];
1507 for(
int i = aSplitIdx; i < aTotalEntries; ++i )
1509 for(
int d = 0; d < NUMDIMS; ++d )
1511 if( aEntries[i].min[d] < g2Min[d] )
1512 g2Min[d] = aEntries[i].min[d];
1514 if( aEntries[i].max[d] > g2Max[d] )
1515 g2Max[d] = aEntries[i].max[d];
1520 int64_t overlap = 1;
1522 for(
int d = 0; d < NUMDIMS; ++d )
1524 ELEMTYPE lo = std::max( g1Min[d], g2Min[d] );
1525 ELEMTYPE hi = std::min( g1Max[d], g2Max[d] );
1530 overlap *=
static_cast<int64_t
>( hi ) - lo;
1542 ELEMTYPE iMin[NUMDIMS], iMax[NUMDIMS];
1545 for(
int j = 0; j < aNode->
count; ++j )
1560 const ELEMTYPE aMax[NUMDIMS] )
const
1562 ELEMTYPE enlargedMin[NUMDIMS], enlargedMax[NUMDIMS];
1565 for(
int d = 0; d < NUMDIMS; ++d )
1567 if( aMin[d] < enlargedMin[d] )
1568 enlargedMin[d] = aMin[d];
1570 if( aMax[d] > enlargedMax[d] )
1571 enlargedMax[d] = aMax[d];
1576 for(
int j = 0; j < aNode->
count; ++j )
1596 NODE* childToUpdate = aBottomChild;
1598 for(
int i =
static_cast<int>( aPath.size() ) - 1; i >= 0; --i )
1600 NODE* parent = aPath[i];
1608 ELEMTYPE childMin[NUMDIMS], childMax[NUMDIMS];
1614 childToUpdate = parent;
1620 for(
int i = 0; i < aParent->
count; ++i )
1622 if( aParent->
children[i] == aChild )
1633 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
1634 std::vector<NODE*>& aReinsertList )
1638 for(
int i = 0; i < aNode->
count; ++i )
1640 if( aNode->
data[i] == aData
1652 for(
int i = 0; i < aNode->
count; ++i )
1659 if(
removeImpl( child, aMin, aMax, aData, aReinsertList ) )
1662 if( child->
count > 0 )
1664 ELEMTYPE childMin[NUMDIMS], childMax[NUMDIMS];
1671 aReinsertList.push_back( child );
1693 for(
NODE* orphan : aReinsertList )
1695 if( orphan->IsLeaf() )
1697 for(
int i = 0; i < orphan->count; ++i )
1699 ELEMTYPE mn[NUMDIMS], mx[NUMDIMS];
1700 orphan->GetInsertBounds( i, mn, mx );
1702 uint32_t reinsertedLevels = 0;
1703 insertImpl( mn, mx, orphan->data[i], reinsertedLevels );
1708 for(
int i = 0; i < orphan->count; ++i )
1710 ELEMTYPE mn[NUMDIMS], mx[NUMDIMS];
1711 orphan->GetChildBounds( i, mn, mx );
1713 uint32_t reinsertedLevels = 0;
1714 reinsertNode( orphan->children[i], mn, mx, orphan->level - 1,
1745 template <
class VISITOR>
1747 const ELEMTYPE aMax[NUMDIMS], VISITOR& aVisitor,
int& aFound )
const
1755 int i = std::countr_zero( mask );
1759 if( !aVisitor( aNode->
data[i] ) )
1767 int i = std::countr_zero( mask );
1781 int64_t
minDistSq(
NODE* aNode,
int aSlot,
const ELEMTYPE aPoint[NUMDIMS] )
const
1785 for(
int d = 0; d < NUMDIMS; ++d )
1787 ELEMTYPE lo = aNode->
bounds[d * 2][aSlot];
1788 ELEMTYPE hi = aNode->
bounds[d * 2 + 1][aSlot];
1790 if( aPoint[d] < lo )
1792 int64_t diff =
static_cast<int64_t
>( lo ) - aPoint[d];
1793 dist += diff * diff;
1795 else if( aPoint[d] > hi )
1797 int64_t diff =
static_cast<int64_t
>( aPoint[d] ) - hi;
1798 dist += diff * diff;
const DATATYPE * operator->() const
std::forward_iterator_tag iterator_category
const DATATYPE & reference
bool operator!=(const Iterator &aOther) const
bool operator==(const Iterator &aOther) const
ptrdiff_t difference_type
std::vector< STACK_ENTRY > m_stack
const DATATYPE & operator*() const
Lazy iterator that traverses only nodes overlapping a query rectangle.
SearchIterator & operator++()
std::vector< STACK_ENTRY > m_stack
SearchIterator(NODE *aRoot, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS])
std::input_iterator_tag iterator_category
bool operator!=(const SearchIterator &aOther) const
const DATATYPE & operator*() const
ptrdiff_t difference_type
const DATATYPE & reference
bool operator==(const SearchIterator &aOther) const
SearchIterator begin() const
SearchRange(NODE *aRoot, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS])
SearchIterator end() const
int64_t computeSplitPerimeters(const ENTRY_VEC &aEntries, int aTotalEntries) const
Compute sum of perimeters for all valid split distributions.
void NearestNeighbors(const ELEMTYPE aPoint[NUMDIMS], int aK, std::vector< std::pair< int64_t, DATATYPE > > &aResults) const
Nearest-neighbor search using Hjaltason & Samet's algorithm.
static constexpr int REINSERT_COUNT
void reinsertOrphans(std::vector< NODE * > &aReinsertList)
Reinsert all entries from orphaned underflowing nodes.
bool removeImpl(NODE *aNode, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], const DATATYPE &aData, std::vector< NODE * > &aReinsertList)
Remove an item from the tree, collecting underflowing nodes for reinsertion.
bool searchImpl(NODE *aNode, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], VISITOR &aVisitor, int &aFound) const
Recursive search.
int Search(const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], VISITOR &aVisitor) const
Search for items whose bounding boxes overlap the query rectangle.
NODE * chooseSubtree(NODE *aNode, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], std::vector< NODE * > &aPath)
R*-tree ChooseSubtree.
SLAB_ALLOCATOR< NODE > m_allocator
void adjustPath(const std::vector< NODE * > &aPath, NODE *aBottomChild=nullptr)
Adjust bounding boxes for all nodes in the path (root to leaf).
DYNAMIC_RTREE & operator=(DYNAMIC_RTREE &&aOther) noexcept
void removeAllNodes(NODE *aNode)
int64_t computeOverlap(NODE *aNode, int aIdx) const
Compute total overlap of child i with all other children in the node.
size_t MemoryUsage() const
Return approximate memory usage in bytes.
bool Remove(const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], const DATATYPE &aData)
Remove an item using its stored insertion bounding box.
void Insert(const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], const DATATYPE &aData)
Insert an item with the given bounding box.
int findBestSplitIndex(const ENTRY_VEC &aEntries, int aTotalEntries) const
Find the split index that minimizes overlap between the two groups.
int64_t computeSplitOverlap(const ENTRY_VEC &aEntries, int aSplitIdx, int aTotalEntries) const
Compute the overlap area between two split groups.
DYNAMIC_RTREE(const DYNAMIC_RTREE &)=delete
void splitNodeInternal(NODE *aNode, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], NODE *aChild, std::vector< NODE * > &aPath, uint32_t &aReinsertedLevels)
Split an internal node to insert a new child.
static constexpr int MAXNODES
void reinsertNode(NODE *aChild, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], int aLevel, uint32_t &aReinsertedLevels)
Reinsert an internal node's child at its correct level.
int findChildSlot(NODE *aParent, NODE *aChild) const
static constexpr int MINNODES
DYNAMIC_RTREE & operator=(const DYNAMIC_RTREE &)=delete
void splitNode(NODE *aNode, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], const DATATYPE &aData, std::vector< NODE * > &aPath, uint32_t &aReinsertedLevels)
R*-tree split.
DYNAMIC_RTREE(DYNAMIC_RTREE &&aOther) noexcept
void overflowTreatment(NODE *aNode, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], const DATATYPE &aData, std::vector< NODE * > &aPath, uint32_t &aReinsertedLevels)
Handle overflow: forced reinsert or split.
RTREE_NODE< SCH_ITEM *, int, NUMDIMS, 16 > NODE
int64_t minDistSq(NODE *aNode, int aSlot, const ELEMTYPE aPoint[NUMDIMS]) const
Compute minimum squared distance from a point to a child's bounding box.
int64_t computeOverlapEnlarged(NODE *aNode, int aIdx, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS]) const
Compute total overlap of child i (enlarged to include query box) with other children.
void forcedReinsert(NODE *aNode, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], const DATATYPE &aData, std::vector< NODE * > &aPath, uint32_t &aReinsertedLevels)
R*-tree forced reinsert.
void insertImpl(const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], const DATATYPE &aData, uint32_t &aReinsertedLevels)
Core insertion with forced reinsert tracking.
void freeNode(NODE *aNode)
SearchRange Overlapping(const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS]) const
Return a lazy range of items overlapping the query rectangle.
void BulkLoad(std::vector< BULK_ENTRY > &aEntries)
Build the tree from a batch of entries using Hilbert-curve packed bulk loading.
NODE * chooseSubtreeAtLevel(NODE *aNode, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], int aTargetLevel, std::vector< NODE * > &aPath)
ChooseSubtree targeting a specific level.
void condenseRoot()
If the root has only one child, replace it with that child.
void RemoveAll()
Remove all items from the tree.
Pool allocator for R-tree nodes.
uint64_t HilbertND2D(int aOrder, const uint32_t aCoords[NUMDIMS])
Compute Hilbert index for N-dimensional coordinates.
Entry type for bulk loading.
ELEMTYPE insertMin[NUMDIMS]
ELEMTYPE insertMax[NUMDIMS]
R-tree node with Structure-of-Arrays bounding box layout.
static constexpr int MINNODES
int64_t ChildOverlapArea(int i, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS]) const
Compute the overlap area between child slot i and the given box.
ELEMTYPE bounds[NUMDIMS *2][MAXNODES]
int64_t ChildEnlargement(int i, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS]) const
Compute how much child slot i's area would increase if it were enlarged to include the given bounding...
int64_t ChildArea(int i) const
Compute the area (or volume for 3D) of child slot i's bounding box.
void GetChildBounds(int i, ELEMTYPE aMin[NUMDIMS], ELEMTYPE aMax[NUMDIMS]) const
Get the bounding box for child slot i.
RTREE_NODE * children[MAXNODES]
uint32_t ChildOverlapMask(const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS]) const
Bitmask of children whose bounding boxes overlap the query rectangle.
bool ChildOverlaps(int i, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS]) const
Test whether child slot i's bounding box overlaps with the given query box.
void SetChildBounds(int i, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS])
Set the bounding box for child slot i.
void SetInsertBounds(int i, const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS])
Store the insertion bounding box for leaf entry i.
void GetInsertBounds(int i, ELEMTYPE aMin[NUMDIMS], ELEMTYPE aMax[NUMDIMS]) const
Get the stored insertion bounding box for leaf entry i.
void ComputeEnclosingBounds(ELEMTYPE aMin[NUMDIMS], ELEMTYPE aMax[NUMDIMS]) const
Compute the bounding box that encloses all children in this node.
void RemoveChild(int i)
Remove child at slot i by swapping with last entry.
KIBIS top(path, &reporter)