24#ifndef DYNAMIC_RTREE_H
25#define DYNAMIC_RTREE_H
62template <
class DATATYPE,
class ELEMTYPE =
int,
int NUMDIMS = 2,
int TMAXNODES = 16>
89 aOther.m_root =
nullptr;
101 aOther.m_root =
nullptr;
115 void Insert(
const ELEMTYPE aMin[NUMDIMS],
const ELEMTYPE aMax[NUMDIMS],
116 const DATATYPE& aData )
126 uint32_t reinsertedLevels = 0;
128 insertImpl( aMin, aMax, aData, reinsertedLevels );
137 bool Remove(
const ELEMTYPE aMin[NUMDIMS],
const ELEMTYPE aMax[NUMDIMS],
138 const DATATYPE& aData )
144 std::vector<NODE*> reinsertList;
155 ELEMTYPE fullMin[NUMDIMS];
156 ELEMTYPE fullMax[NUMDIMS];
158 for(
int d = 0; d < NUMDIMS; ++d )
160 fullMin[d] = std::numeric_limits<ELEMTYPE>::lowest();
161 fullMax[d] = std::numeric_limits<ELEMTYPE>::max();
164 reinsertList.clear();
185 template <
class VISITOR>
186 int Search(
const ELEMTYPE aMin[NUMDIMS],
const ELEMTYPE aMax[NUMDIMS],
187 VISITOR& aVisitor )
const
234 if( aEntries.empty() )
240 ELEMTYPE globalMin[NUMDIMS], globalMax[NUMDIMS];
242 for(
int d = 0; d < NUMDIMS; ++d )
244 globalMin[d] = std::numeric_limits<ELEMTYPE>::max();
245 globalMax[d] = std::numeric_limits<ELEMTYPE>::lowest();
248 for(
const auto& entry : aEntries )
250 for(
int d = 0; d < NUMDIMS; ++d )
252 if( entry.min[d] < globalMin[d] )
253 globalMin[d] = entry.min[d];
255 if( entry.max[d] > globalMax[d] )
256 globalMax[d] = entry.max[d];
261 double range[NUMDIMS];
263 for(
int d = 0; d < NUMDIMS; ++d )
265 range[d] =
static_cast<double>( globalMax[d] ) - globalMin[d];
267 if( range[d] <= 0.0 )
271 std::sort( aEntries.begin(), aEntries.end(),
272 [&](
const BULK_ENTRY& a,
const BULK_ENTRY& b )
274 uint32_t coordsA[NUMDIMS], coordsB[NUMDIMS];
276 for( int d = 0; d < NUMDIMS; ++d )
278 double centerA = ( static_cast<double>( a.min[d] ) + a.max[d] ) / 2.0;
279 double centerB = ( static_cast<double>( b.min[d] ) + b.max[d] ) / 2.0;
281 coordsA[d] = static_cast<uint32_t>(
282 ( ( centerA - globalMin[d] ) / range[d] )
283 * static_cast<double>( UINT32_MAX ) );
284 coordsB[d] = static_cast<uint32_t>(
285 ( ( centerB - globalMin[d] ) / range[d] )
286 * static_cast<double>( UINT32_MAX ) );
294 std::vector<NODE*> currentLevel;
295 size_t n = aEntries.size();
298 for(
size_t i = 0; i < n; i +=
MAXNODES )
302 int cnt =
static_cast<int>( std::min<size_t>(
MAXNODES, n - i ) );
304 for(
int j = 0; j < cnt; ++j )
306 const auto& entry = aEntries[i + j];
307 leaf->SetChildBounds( j, entry.min, entry.max );
308 leaf->SetInsertBounds( j, entry.min, entry.max );
309 leaf->data[j] = entry.data;
313 currentLevel.push_back( leaf );
319 while( currentLevel.size() > 1 )
321 size_t levelSize = currentLevel.size();
322 std::vector<NODE*> nextLevel;
325 for(
size_t i = 0; i < levelSize; i +=
MAXNODES )
328 internal->level = level;
329 int cnt =
static_cast<int>( std::min<size_t>(
MAXNODES, levelSize - i ) );
331 for(
int j = 0; j < cnt; ++j )
333 NODE* child = currentLevel[i + j];
334 ELEMTYPE childMin[NUMDIMS], childMax[NUMDIMS];
335 child->ComputeEnclosingBounds( childMin, childMax );
336 internal->SetChildBounds( j, childMin, childMax );
337 internal->children[j] = child;
340 internal->count = cnt;
341 nextLevel.push_back( internal );
344 currentLevel = std::move( nextLevel );
378 if( aRoot && aRoot->
count > 0 )
380 m_stack.push_back( { aRoot, 0 } );
405 return !( *
this == aOther );
421 if(
top.node->IsLeaf() )
423 if(
top.childIdx <
top.node->count )
435 if(
top.childIdx <
top.node->count )
437 NODE* child =
top.node->children[
top.childIdx];
439 m_stack.push_back( { child, 0 } );
457 Iterator
end()
const {
return Iterator(); }
475 const ELEMTYPE aMax[NUMDIMS] )
477 for(
int d = 0; d < NUMDIMS; ++d )
483 if( aRoot && aRoot->
count > 0 )
485 m_stack.push_back( { aRoot, 0 } );
509 return !( *
this == aOther );
525 if(
top.node->IsLeaf() )
527 while(
top.childIdx <
top.node->count )
544 bool descended =
false;
546 while(
top.childIdx <
top.node->count )
550 NODE* child =
top.node->children[
top.childIdx];
552 m_stack.push_back( { child, 0 } );
583 const ELEMTYPE aMax[NUMDIMS] ) :
586 for(
int d = 0; d < NUMDIMS; ++d )
609 const ELEMTYPE aMax[NUMDIMS] )
const
611 return SearchRange(
m_root, aMin, aMax );
622 std::vector<std::pair<int64_t, DATATYPE>>& aResults )
const
629 using QueueEntry = std::pair<int64_t, std::pair<NODE*, int>>;
631 auto cmp = [](
const QueueEntry& a,
const QueueEntry& b )
633 return a.first > b.first;
635 std::priority_queue<QueueEntry, std::vector<QueueEntry>,
decltype( cmp )> pq( cmp );
638 for(
int i = 0; i <
m_root->count; ++i )
641 pq.push( { dist, {
m_root, i } } );
644 while( !pq.empty() &&
static_cast<int>( aResults.size() ) < aK )
646 auto [dist, entry] = pq.top();
648 NODE* node = entry.first;
649 int slot = entry.second;
653 aResults.push_back( { dist, node->
data[slot] } );
659 for(
int i = 0; i < child->
count; ++i )
661 int64_t childDist =
minDistSq( child, i, aPoint );
662 pq.push( { childDist, { child, i } } );
697 for(
int i = 0; i < aNode->
count; ++i )
707 void insertImpl(
const ELEMTYPE aMin[NUMDIMS],
const ELEMTYPE aMax[NUMDIMS],
708 const DATATYPE& aData, uint32_t& aReinsertedLevels )
711 std::vector<NODE*>
path;
717 int slot = leaf->
count;
720 leaf->
data[slot] = aData;
738 const ELEMTYPE aMax[NUMDIMS], std::vector<NODE*>& aPath )
745 aPath.push_back( node );
747 if( node->
level == 1 )
751 int64_t bestOverlapInc = std::numeric_limits<int64_t>::max();
752 int64_t bestAreaInc = std::numeric_limits<int64_t>::max();
753 int64_t bestArea = std::numeric_limits<int64_t>::max();
755 for(
int i = 0; i < node->
count; ++i )
759 int64_t overlapInc = overlapAfter - overlapBefore;
763 if( overlapInc < bestOverlapInc
764 || ( overlapInc == bestOverlapInc && areaInc < bestAreaInc )
765 || ( overlapInc == bestOverlapInc && areaInc == bestAreaInc
766 && area < bestArea ) )
769 bestOverlapInc = overlapInc;
770 bestAreaInc = areaInc;
781 int64_t bestAreaInc = std::numeric_limits<int64_t>::max();
782 int64_t bestArea = std::numeric_limits<int64_t>::max();
784 for(
int i = 0; i < node->
count; ++i )
789 if( areaInc < bestAreaInc
790 || ( areaInc == bestAreaInc && area < bestArea ) )
793 bestAreaInc = areaInc;
809 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
810 std::vector<NODE*>& aPath, uint32_t& aReinsertedLevels )
812 int level = aNode->
level;
818 splitNode( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
822 const uint32_t levelMask = 1U << level;
824 if( !( aReinsertedLevels & levelMask ) )
826 aReinsertedLevels |= levelMask;
827 forcedReinsert( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
831 splitNode( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
842 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
843 std::vector<NODE*>& aPath, uint32_t& aReinsertedLevels )
848 ELEMTYPE min[NUMDIMS];
849 ELEMTYPE max[NUMDIMS];
850 ELEMTYPE insertMin[NUMDIMS];
851 ELEMTYPE insertMax[NUMDIMS];
857 int totalEntries = aNode->
count + 1;
858 std::vector<ENTRY> entries( totalEntries );
861 ELEMTYPE nodeMin[NUMDIMS];
862 ELEMTYPE nodeMax[NUMDIMS];
867 for(
int d = 0; d < NUMDIMS; ++d )
868 center[d] = (
static_cast<double>( nodeMin[d] ) + nodeMax[d] ) / 2.0;
871 for(
int i = 0; i < aNode->
count; ++i )
877 aNode->
GetInsertBounds( i, entries[i].insertMin, entries[i].insertMax );
878 entries[i].data = aNode->
data[i];
879 entries[i].child =
nullptr;
883 entries[i].child = aNode->
children[i];
889 for(
int d = 0; d < NUMDIMS; ++d )
891 double entryCenter = (
static_cast<double>( entries[i].min[d] )
892 + entries[i].max[d] ) / 2.0;
893 double diff = entryCenter -
center[d];
894 distSq +=
static_cast<int64_t
>( diff * diff );
897 entries[i].distSq = distSq;
901 ENTRY& newEntry = entries[aNode->
count];
903 for(
int d = 0; d < NUMDIMS; ++d )
905 newEntry.min[d] = aMin[d];
906 newEntry.max[d] = aMax[d];
907 newEntry.insertMin[d] = aMin[d];
908 newEntry.insertMax[d] = aMax[d];
911 newEntry.data = aData;
912 newEntry.child =
nullptr;
916 for(
int d = 0; d < NUMDIMS; ++d )
918 double entryCenter = (
static_cast<double>( aMin[d] ) + aMax[d] ) / 2.0;
919 double diff = entryCenter -
center[d];
920 distSq +=
static_cast<int64_t
>( diff * diff );
923 newEntry.distSq = distSq;
926 std::sort( entries.begin(), entries.end(),
927 [](
const ENTRY& a,
const ENTRY& b )
929 return a.distSq > b.distSq;
935 if( reinsertCount <= 0 )
938 splitNode( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
945 for(
int i = reinsertCount; i < totalEntries; ++i )
947 int slot = aNode->
count;
952 aNode->
SetInsertBounds( slot, entries[i].insertMin, entries[i].insertMax );
953 aNode->
data[slot] = entries[i].data;
957 aNode->
children[slot] = entries[i].child;
966 for(
int i = 0; i < reinsertCount; ++i )
970 insertImpl( entries[i].insertMin, entries[i].insertMax,
971 entries[i].data, aReinsertedLevels );
975 reinsertNode( entries[i].child, entries[i].min, entries[i].max,
976 aNode->
level - 1, aReinsertedLevels );
985 const ELEMTYPE aMax[NUMDIMS],
int aLevel,
986 uint32_t& aReinsertedLevels )
989 std::vector<NODE*>
path;
994 int slot = target->
count;
1010 const ELEMTYPE aMax[NUMDIMS],
int aTargetLevel,
1011 std::vector<NODE*>& aPath )
1016 while( node->
level > aTargetLevel )
1018 aPath.push_back( node );
1021 int64_t bestAreaInc = std::numeric_limits<int64_t>::max();
1022 int64_t bestArea = std::numeric_limits<int64_t>::max();
1024 for(
int i = 0; i < node->
count; ++i )
1029 if( areaInc < bestAreaInc
1030 || ( areaInc == bestAreaInc && area < bestArea ) )
1033 bestAreaInc = areaInc;
1053 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
1054 std::vector<NODE*>& aPath, uint32_t& aReinsertedLevels )
1057 int totalEntries = aNode->
count + 1;
1058 std::vector<SPLIT_ENTRY> entries( totalEntries );
1060 for(
int i = 0; i < aNode->
count; ++i )
1066 aNode->
GetInsertBounds( i, entries[i].insertMin, entries[i].insertMax );
1067 entries[i].data = aNode->
data[i];
1068 entries[i].child =
nullptr;
1072 entries[i].child = aNode->
children[i];
1077 for(
int d = 0; d < NUMDIMS; ++d )
1079 entries[aNode->
count].min[d] = aMin[d];
1080 entries[aNode->
count].max[d] = aMax[d];
1081 entries[aNode->
count].insertMin[d] = aMin[d];
1082 entries[aNode->
count].insertMax[d] = aMax[d];
1085 entries[aNode->
count].data = aData;
1086 entries[aNode->
count].child =
nullptr;
1090 int64_t bestPerimeterSum = std::numeric_limits<int64_t>::max();
1092 for(
int axis = 0; axis < NUMDIMS; ++axis )
1094 int64_t perimeterSum = 0;
1097 std::sort( entries.begin(), entries.end(),
1098 [axis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1100 return a.min[axis] < b.min[axis]
1101 || ( a.min[axis] == b.min[axis]
1102 && a.max[axis] < b.max[axis] );
1108 std::sort( entries.begin(), entries.end(),
1109 [axis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1111 return a.max[axis] < b.max[axis]
1112 || ( a.max[axis] == b.max[axis]
1113 && a.min[axis] < b.min[axis] );
1118 if( perimeterSum < bestPerimeterSum )
1120 bestPerimeterSum = perimeterSum;
1127 std::sort( entries.begin(), entries.end(),
1128 [bestAxis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1130 return a.min[bestAxis] < b.min[bestAxis]
1131 || ( a.min[bestAxis] == b.min[bestAxis]
1132 && a.max[bestAxis] < b.max[bestAxis] );
1138 std::vector<SPLIT_ENTRY> entriesByMax = entries;
1140 std::sort( entriesByMax.begin(), entriesByMax.end(),
1141 [bestAxis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1143 return a.max[bestAxis] < b.max[bestAxis]
1144 || ( a.max[bestAxis] == b.max[bestAxis]
1145 && a.min[bestAxis] < b.min[bestAxis] );
1152 if( overlapMax < overlapMin )
1154 entries = std::move( entriesByMax );
1155 bestSplit = bestSplitMax;
1165 for(
int i = 0; i < bestSplit; ++i )
1167 int slot = aNode->
count;
1172 aNode->
SetInsertBounds( slot, entries[i].insertMin, entries[i].insertMax );
1173 aNode->
data[slot] = entries[i].data;
1177 aNode->
children[slot] = entries[i].child;
1183 for(
int i = bestSplit; i < totalEntries; ++i )
1185 int slot = sibling->
count;
1191 entries[i].insertMax );
1192 sibling->
data[slot] = entries[i].data;
1196 sibling->
children[slot] = entries[i].child;
1203 ELEMTYPE sibMin[NUMDIMS], sibMax[NUMDIMS];
1212 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1224 NODE* parent = aPath.back();
1229 if( childSlot >= 0 )
1231 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1239 int slot = parent->
count;
1259 const ELEMTYPE aMax[NUMDIMS],
NODE* aChild,
1260 std::vector<NODE*>& aPath,
1261 uint32_t& aReinsertedLevels )
1263 int totalEntries = aNode->
count + 1;
1264 std::vector<SPLIT_ENTRY> entries( totalEntries );
1266 for(
int i = 0; i < aNode->
count; ++i )
1269 entries[i].child = aNode->
children[i];
1272 for(
int d = 0; d < NUMDIMS; ++d )
1274 entries[aNode->
count].min[d] = aMin[d];
1275 entries[aNode->
count].max[d] = aMax[d];
1278 entries[aNode->
count].child = aChild;
1282 int64_t bestPerimeterSum = std::numeric_limits<int64_t>::max();
1284 for(
int axis = 0; axis < NUMDIMS; ++axis )
1286 std::sort( entries.begin(), entries.end(),
1287 [axis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1289 return a.min[axis] < b.min[axis];
1294 if( perimSum < bestPerimeterSum )
1296 bestPerimeterSum = perimSum;
1302 std::sort( entries.begin(), entries.end(),
1303 [bestAxis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1305 return a.min[bestAxis] < b.min[bestAxis];
1316 for(
int i = 0; i < bestSplit; ++i )
1318 int slot = aNode->
count;
1320 aNode->
children[slot] = entries[i].child;
1324 for(
int i = bestSplit; i < totalEntries; ++i )
1326 int slot = sibling->
count;
1328 sibling->
children[slot] = entries[i].child;
1332 ELEMTYPE sibMin[NUMDIMS], sibMax[NUMDIMS];
1340 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1352 NODE* parent = aPath.back();
1355 if( childSlot >= 0 )
1357 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1364 int slot = parent->
count;
1375 aReinsertedLevels );
1383 template <
class ENTRY_VEC>
1392 for(
int grp = 0; grp < 2; ++grp )
1394 int start = ( grp == 0 ) ? 0 : k;
1395 int end = ( grp == 0 ) ? k : aTotalEntries;
1397 int64_t perimeter = 0;
1399 for(
int d = 0; d < NUMDIMS; ++d )
1401 ELEMTYPE mn = std::numeric_limits<ELEMTYPE>::max();
1402 ELEMTYPE mx = std::numeric_limits<ELEMTYPE>::lowest();
1404 for(
int i = start; i <
end; ++i )
1406 if( aEntries[i].min[d] < mn )
1407 mn = aEntries[i].min[d];
1409 if( aEntries[i].max[d] > mx )
1410 mx = aEntries[i].max[d];
1413 perimeter +=
static_cast<int64_t
>( mx ) - mn;
1416 sum += 2 * perimeter;
1426 template <
class ENTRY_VEC>
1430 int64_t bestOverlap = std::numeric_limits<int64_t>::max();
1431 int64_t bestAreaSum = std::numeric_limits<int64_t>::max();
1438 int64_t areaSum = 0;
1440 for(
int grp = 0; grp < 2; ++grp )
1442 int start = ( grp == 0 ) ? 0 : k;
1443 int end = ( grp == 0 ) ? k : aTotalEntries;
1446 for(
int d = 0; d < NUMDIMS; ++d )
1448 ELEMTYPE mn = std::numeric_limits<ELEMTYPE>::max();
1449 ELEMTYPE mx = std::numeric_limits<ELEMTYPE>::lowest();
1451 for(
int i = start; i <
end; ++i )
1453 if( aEntries[i].min[d] < mn )
1454 mn = aEntries[i].min[d];
1456 if( aEntries[i].max[d] > mx )
1457 mx = aEntries[i].max[d];
1460 area *=
static_cast<int64_t
>( mx ) - mn;
1466 if( overlap < bestOverlap
1467 || ( overlap == bestOverlap && areaSum < bestAreaSum ) )
1470 bestOverlap = overlap;
1471 bestAreaSum = areaSum;
1481 template <
class ENTRY_VEC>
1483 int aTotalEntries )
const
1485 ELEMTYPE g1Min[NUMDIMS], g1Max[NUMDIMS];
1486 ELEMTYPE g2Min[NUMDIMS], g2Max[NUMDIMS];
1488 for(
int d = 0; d < NUMDIMS; ++d )
1490 g1Min[d] = g2Min[d] = std::numeric_limits<ELEMTYPE>::max();
1491 g1Max[d] = g2Max[d] = std::numeric_limits<ELEMTYPE>::lowest();
1494 for(
int i = 0; i < aSplitIdx; ++i )
1496 for(
int d = 0; d < NUMDIMS; ++d )
1498 if( aEntries[i].min[d] < g1Min[d] )
1499 g1Min[d] = aEntries[i].min[d];
1501 if( aEntries[i].max[d] > g1Max[d] )
1502 g1Max[d] = aEntries[i].max[d];
1506 for(
int i = aSplitIdx; i < aTotalEntries; ++i )
1508 for(
int d = 0; d < NUMDIMS; ++d )
1510 if( aEntries[i].min[d] < g2Min[d] )
1511 g2Min[d] = aEntries[i].min[d];
1513 if( aEntries[i].max[d] > g2Max[d] )
1514 g2Max[d] = aEntries[i].max[d];
1519 int64_t overlap = 1;
1521 for(
int d = 0; d < NUMDIMS; ++d )
1523 ELEMTYPE lo = std::max( g1Min[d], g2Min[d] );
1524 ELEMTYPE hi = std::min( g1Max[d], g2Max[d] );
1529 overlap *=
static_cast<int64_t
>( hi ) - lo;
1541 ELEMTYPE iMin[NUMDIMS], iMax[NUMDIMS];
1544 for(
int j = 0; j < aNode->
count; ++j )
1559 const ELEMTYPE aMax[NUMDIMS] )
const
1561 ELEMTYPE enlargedMin[NUMDIMS], enlargedMax[NUMDIMS];
1564 for(
int d = 0; d < NUMDIMS; ++d )
1566 if( aMin[d] < enlargedMin[d] )
1567 enlargedMin[d] = aMin[d];
1569 if( aMax[d] > enlargedMax[d] )
1570 enlargedMax[d] = aMax[d];
1575 for(
int j = 0; j < aNode->
count; ++j )
1595 NODE* childToUpdate = aBottomChild;
1597 for(
int i =
static_cast<int>( aPath.size() ) - 1; i >= 0; --i )
1599 NODE* parent = aPath[i];
1607 ELEMTYPE childMin[NUMDIMS], childMax[NUMDIMS];
1613 childToUpdate = parent;
1619 for(
int i = 0; i < aParent->
count; ++i )
1621 if( aParent->
children[i] == aChild )
1632 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
1633 std::vector<NODE*>& aReinsertList )
1637 for(
int i = 0; i < aNode->
count; ++i )
1639 if( aNode->
data[i] == aData
1651 for(
int i = 0; i < aNode->
count; ++i )
1658 if(
removeImpl( child, aMin, aMax, aData, aReinsertList ) )
1661 if( child->
count > 0 )
1663 ELEMTYPE childMin[NUMDIMS], childMax[NUMDIMS];
1670 aReinsertList.push_back( child );
1692 for(
NODE* orphan : aReinsertList )
1694 if( orphan->IsLeaf() )
1696 for(
int i = 0; i < orphan->count; ++i )
1698 ELEMTYPE mn[NUMDIMS], mx[NUMDIMS];
1699 orphan->GetInsertBounds( i, mn, mx );
1701 uint32_t reinsertedLevels = 0;
1702 insertImpl( mn, mx, orphan->data[i], reinsertedLevels );
1707 for(
int i = 0; i < orphan->count; ++i )
1709 ELEMTYPE mn[NUMDIMS], mx[NUMDIMS];
1710 orphan->GetChildBounds( i, mn, mx );
1712 uint32_t reinsertedLevels = 0;
1713 reinsertNode( orphan->children[i], mn, mx, orphan->level - 1,
1744 template <
class VISITOR>
1746 const ELEMTYPE aMax[NUMDIMS], VISITOR& aVisitor,
int& aFound )
const
1754 int i = std::countr_zero( mask );
1758 if( !aVisitor( aNode->
data[i] ) )
1766 int i = std::countr_zero( mask );
1780 int64_t
minDistSq(
NODE* aNode,
int aSlot,
const ELEMTYPE aPoint[NUMDIMS] )
const
1784 for(
int d = 0; d < NUMDIMS; ++d )
1786 ELEMTYPE lo = aNode->
bounds[d * 2][aSlot];
1787 ELEMTYPE hi = aNode->
bounds[d * 2 + 1][aSlot];
1789 if( aPoint[d] < lo )
1791 int64_t diff =
static_cast<int64_t
>( lo ) - aPoint[d];
1792 dist += diff * diff;
1794 else if( aPoint[d] > hi )
1796 int64_t diff =
static_cast<int64_t
>( aPoint[d] ) - hi;
1797 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
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 int aMin[NUMDIMS], const int aMax[NUMDIMS], std::vector< NODE * > &aPath)
SLAB_ALLOCATOR< NODE > m_allocator
void adjustPath(const std::vector< NODE * > &aPath, NODE *aBottomChild=nullptr)
DYNAMIC_RTREE & operator=(DYNAMIC_RTREE &&aOther) noexcept
void removeAllNodes(NODE *aNode)
int64_t computeOverlap(NODE *aNode, int aIdx) const
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
int64_t computeSplitOverlap(const ENTRY_VEC &aEntries, int aSplitIdx, int aTotalEntries) const
DYNAMIC_RTREE(const DYNAMIC_RTREE &)=delete
void splitNodeInternal(NODE *aNode, const int aMin[NUMDIMS], const int aMax[NUMDIMS], NODE *aChild, std::vector< NODE * > &aPath, uint32_t &aReinsertedLevels)
static constexpr int MAXNODES
void reinsertNode(NODE *aChild, const int aMin[NUMDIMS], const int aMax[NUMDIMS], int aLevel, uint32_t &aReinsertedLevels)
int findChildSlot(NODE *aParent, NODE *aChild) const
static constexpr int MINNODES
DYNAMIC_RTREE & operator=(const DYNAMIC_RTREE &)=delete
void splitNode(NODE *aNode, const int aMin[NUMDIMS], const int aMax[NUMDIMS], const SCH_ITEM *&aData, std::vector< NODE * > &aPath, uint32_t &aReinsertedLevels)
DYNAMIC_RTREE(DYNAMIC_RTREE &&aOther) noexcept
void overflowTreatment(NODE *aNode, const int aMin[NUMDIMS], const int aMax[NUMDIMS], const SCH_ITEM *&aData, std::vector< NODE * > &aPath, uint32_t &aReinsertedLevels)
RTREE_NODE< SCH_ITEM *, int, NUMDIMS, 16 > NODE
int64_t minDistSq(NODE *aNode, int aSlot, const int aPoint[NUMDIMS]) const
int64_t computeOverlapEnlarged(NODE *aNode, int aIdx, const int aMin[NUMDIMS], const int aMax[NUMDIMS]) const
void forcedReinsert(NODE *aNode, const int aMin[NUMDIMS], const int aMax[NUMDIMS], const SCH_ITEM *&aData, std::vector< NODE * > &aPath, uint32_t &aReinsertedLevels)
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 int aMin[NUMDIMS], const int aMax[NUMDIMS], int aTargetLevel, std::vector< NODE * > &aPath)
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)