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
230 if( aEntries.empty() )
236 ELEMTYPE globalMin[NUMDIMS], globalMax[NUMDIMS];
238 for(
int d = 0; d < NUMDIMS; ++d )
240 globalMin[d] = std::numeric_limits<ELEMTYPE>::max();
241 globalMax[d] = std::numeric_limits<ELEMTYPE>::lowest();
244 for(
const auto& entry : aEntries )
246 for(
int d = 0; d < NUMDIMS; ++d )
248 if( entry.min[d] < globalMin[d] )
249 globalMin[d] = entry.min[d];
251 if( entry.max[d] > globalMax[d] )
252 globalMax[d] = entry.max[d];
257 double range[NUMDIMS];
259 for(
int d = 0; d < NUMDIMS; ++d )
261 range[d] =
static_cast<double>( globalMax[d] ) - globalMin[d];
263 if( range[d] <= 0.0 )
267 std::sort( aEntries.begin(), aEntries.end(),
268 [&](
const BULK_ENTRY& a,
const BULK_ENTRY& b )
270 uint32_t coordsA[NUMDIMS], coordsB[NUMDIMS];
272 for( int d = 0; d < NUMDIMS; ++d )
274 double centerA = ( static_cast<double>( a.min[d] ) + a.max[d] ) / 2.0;
275 double centerB = ( static_cast<double>( b.min[d] ) + b.max[d] ) / 2.0;
277 coordsA[d] = static_cast<uint32_t>(
278 ( ( centerA - globalMin[d] ) / range[d] )
279 * static_cast<double>( UINT32_MAX ) );
280 coordsB[d] = static_cast<uint32_t>(
281 ( ( centerB - globalMin[d] ) / range[d] )
282 * static_cast<double>( UINT32_MAX ) );
290 std::vector<NODE*> currentLevel;
291 size_t n = aEntries.size();
294 for(
size_t i = 0; i < n; i +=
MAXNODES )
298 int cnt =
static_cast<int>( std::min<size_t>(
MAXNODES, n - i ) );
300 for(
int j = 0; j < cnt; ++j )
302 const auto& entry = aEntries[i + j];
303 leaf->SetChildBounds( j, entry.min, entry.max );
304 leaf->SetInsertBounds( j, entry.min, entry.max );
305 leaf->data[j] = entry.data;
309 currentLevel.push_back( leaf );
315 while( currentLevel.size() > 1 )
317 size_t levelSize = currentLevel.size();
318 std::vector<NODE*> nextLevel;
321 for(
size_t i = 0; i < levelSize; i +=
MAXNODES )
324 internal->level = level;
325 int cnt =
static_cast<int>( std::min<size_t>(
MAXNODES, levelSize - i ) );
327 for(
int j = 0; j < cnt; ++j )
329 NODE* child = currentLevel[i + j];
330 ELEMTYPE childMin[NUMDIMS], childMax[NUMDIMS];
331 child->ComputeEnclosingBounds( childMin, childMax );
332 internal->SetChildBounds( j, childMin, childMax );
333 internal->children[j] = child;
336 internal->count = cnt;
337 nextLevel.push_back( internal );
340 currentLevel = std::move( nextLevel );
374 if( aRoot && aRoot->
count > 0 )
376 m_stack.push_back( { aRoot, 0 } );
401 return !( *
this == aOther );
417 if(
top.node->IsLeaf() )
419 if(
top.childIdx <
top.node->count )
431 if(
top.childIdx <
top.node->count )
433 NODE* child =
top.node->children[
top.childIdx];
435 m_stack.push_back( { child, 0 } );
453 Iterator
end()
const {
return Iterator(); }
471 const ELEMTYPE aMax[NUMDIMS] )
473 for(
int d = 0; d < NUMDIMS; ++d )
479 if( aRoot && aRoot->
count > 0 )
481 m_stack.push_back( { aRoot, 0 } );
505 return !( *
this == aOther );
521 if(
top.node->IsLeaf() )
523 while(
top.childIdx <
top.node->count )
540 bool descended =
false;
542 while(
top.childIdx <
top.node->count )
546 NODE* child =
top.node->children[
top.childIdx];
548 m_stack.push_back( { child, 0 } );
579 const ELEMTYPE aMax[NUMDIMS] ) :
582 for(
int d = 0; d < NUMDIMS; ++d )
605 const ELEMTYPE aMax[NUMDIMS] )
const
607 return SearchRange(
m_root, aMin, aMax );
618 std::vector<std::pair<int64_t, DATATYPE>>& aResults )
const
625 using QueueEntry = std::pair<int64_t, std::pair<NODE*, int>>;
627 auto cmp = [](
const QueueEntry& a,
const QueueEntry& b )
629 return a.first > b.first;
631 std::priority_queue<QueueEntry, std::vector<QueueEntry>,
decltype( cmp )> pq( cmp );
634 for(
int i = 0; i <
m_root->count; ++i )
637 pq.push( { dist, {
m_root, i } } );
640 while( !pq.empty() &&
static_cast<int>( aResults.size() ) < aK )
642 auto [dist, entry] = pq.top();
644 NODE* node = entry.first;
645 int slot = entry.second;
649 aResults.push_back( { dist, node->
data[slot] } );
655 for(
int i = 0; i < child->
count; ++i )
657 int64_t childDist =
minDistSq( child, i, aPoint );
658 pq.push( { childDist, { child, i } } );
693 for(
int i = 0; i < aNode->
count; ++i )
703 void insertImpl(
const ELEMTYPE aMin[NUMDIMS],
const ELEMTYPE aMax[NUMDIMS],
704 const DATATYPE& aData, uint32_t& aReinsertedLevels )
707 std::vector<NODE*>
path;
713 int slot = leaf->
count;
716 leaf->
data[slot] = aData;
734 const ELEMTYPE aMax[NUMDIMS], std::vector<NODE*>& aPath )
741 aPath.push_back( node );
743 if( node->
level == 1 )
747 int64_t bestOverlapInc = std::numeric_limits<int64_t>::max();
748 int64_t bestAreaInc = std::numeric_limits<int64_t>::max();
749 int64_t bestArea = std::numeric_limits<int64_t>::max();
751 for(
int i = 0; i < node->
count; ++i )
755 int64_t overlapInc = overlapAfter - overlapBefore;
759 if( overlapInc < bestOverlapInc
760 || ( overlapInc == bestOverlapInc && areaInc < bestAreaInc )
761 || ( overlapInc == bestOverlapInc && areaInc == bestAreaInc
762 && area < bestArea ) )
765 bestOverlapInc = overlapInc;
766 bestAreaInc = areaInc;
777 int64_t bestAreaInc = std::numeric_limits<int64_t>::max();
778 int64_t bestArea = std::numeric_limits<int64_t>::max();
780 for(
int i = 0; i < node->
count; ++i )
785 if( areaInc < bestAreaInc
786 || ( areaInc == bestAreaInc && area < bestArea ) )
789 bestAreaInc = areaInc;
805 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
806 std::vector<NODE*>& aPath, uint32_t& aReinsertedLevels )
808 int level = aNode->
level;
814 splitNode( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
818 const uint32_t levelMask = 1U << level;
820 if( !( aReinsertedLevels & levelMask ) )
822 aReinsertedLevels |= levelMask;
823 forcedReinsert( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
827 splitNode( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
838 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
839 std::vector<NODE*>& aPath, uint32_t& aReinsertedLevels )
844 ELEMTYPE min[NUMDIMS];
845 ELEMTYPE max[NUMDIMS];
846 ELEMTYPE insertMin[NUMDIMS];
847 ELEMTYPE insertMax[NUMDIMS];
853 int totalEntries = aNode->
count + 1;
854 std::vector<ENTRY> entries( totalEntries );
857 ELEMTYPE nodeMin[NUMDIMS];
858 ELEMTYPE nodeMax[NUMDIMS];
863 for(
int d = 0; d < NUMDIMS; ++d )
864 center[d] = (
static_cast<double>( nodeMin[d] ) + nodeMax[d] ) / 2.0;
867 for(
int i = 0; i < aNode->
count; ++i )
873 aNode->
GetInsertBounds( i, entries[i].insertMin, entries[i].insertMax );
874 entries[i].data = aNode->
data[i];
875 entries[i].child =
nullptr;
879 entries[i].child = aNode->
children[i];
885 for(
int d = 0; d < NUMDIMS; ++d )
887 double entryCenter = (
static_cast<double>( entries[i].min[d] )
888 + entries[i].max[d] ) / 2.0;
889 double diff = entryCenter -
center[d];
890 distSq +=
static_cast<int64_t
>( diff * diff );
893 entries[i].distSq = distSq;
897 ENTRY& newEntry = entries[aNode->
count];
899 for(
int d = 0; d < NUMDIMS; ++d )
901 newEntry.min[d] = aMin[d];
902 newEntry.max[d] = aMax[d];
903 newEntry.insertMin[d] = aMin[d];
904 newEntry.insertMax[d] = aMax[d];
907 newEntry.data = aData;
908 newEntry.child =
nullptr;
912 for(
int d = 0; d < NUMDIMS; ++d )
914 double entryCenter = (
static_cast<double>( aMin[d] ) + aMax[d] ) / 2.0;
915 double diff = entryCenter -
center[d];
916 distSq +=
static_cast<int64_t
>( diff * diff );
919 newEntry.distSq = distSq;
922 std::sort( entries.begin(), entries.end(),
923 [](
const ENTRY& a,
const ENTRY& b )
925 return a.distSq > b.distSq;
931 if( reinsertCount <= 0 )
934 splitNode( aNode, aMin, aMax, aData, aPath, aReinsertedLevels );
941 for(
int i = reinsertCount; i < totalEntries; ++i )
943 int slot = aNode->
count;
948 aNode->
SetInsertBounds( slot, entries[i].insertMin, entries[i].insertMax );
949 aNode->
data[slot] = entries[i].data;
953 aNode->
children[slot] = entries[i].child;
962 for(
int i = 0; i < reinsertCount; ++i )
966 insertImpl( entries[i].insertMin, entries[i].insertMax,
967 entries[i].data, aReinsertedLevels );
971 reinsertNode( entries[i].child, entries[i].min, entries[i].max,
972 aNode->
level - 1, aReinsertedLevels );
981 const ELEMTYPE aMax[NUMDIMS],
int aLevel,
982 uint32_t& aReinsertedLevels )
985 std::vector<NODE*>
path;
990 int slot = target->
count;
1006 const ELEMTYPE aMax[NUMDIMS],
int aTargetLevel,
1007 std::vector<NODE*>& aPath )
1012 while( node->
level > aTargetLevel )
1014 aPath.push_back( node );
1017 int64_t bestAreaInc = std::numeric_limits<int64_t>::max();
1018 int64_t bestArea = std::numeric_limits<int64_t>::max();
1020 for(
int i = 0; i < node->
count; ++i )
1025 if( areaInc < bestAreaInc
1026 || ( areaInc == bestAreaInc && area < bestArea ) )
1029 bestAreaInc = areaInc;
1049 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
1050 std::vector<NODE*>& aPath, uint32_t& aReinsertedLevels )
1053 int totalEntries = aNode->
count + 1;
1054 std::vector<SPLIT_ENTRY> entries( totalEntries );
1056 for(
int i = 0; i < aNode->
count; ++i )
1062 aNode->
GetInsertBounds( i, entries[i].insertMin, entries[i].insertMax );
1063 entries[i].data = aNode->
data[i];
1064 entries[i].child =
nullptr;
1068 entries[i].child = aNode->
children[i];
1073 for(
int d = 0; d < NUMDIMS; ++d )
1075 entries[aNode->
count].min[d] = aMin[d];
1076 entries[aNode->
count].max[d] = aMax[d];
1077 entries[aNode->
count].insertMin[d] = aMin[d];
1078 entries[aNode->
count].insertMax[d] = aMax[d];
1081 entries[aNode->
count].data = aData;
1082 entries[aNode->
count].child =
nullptr;
1086 int64_t bestPerimeterSum = std::numeric_limits<int64_t>::max();
1088 for(
int axis = 0; axis < NUMDIMS; ++axis )
1090 int64_t perimeterSum = 0;
1093 std::sort( entries.begin(), entries.end(),
1094 [axis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1096 return a.min[axis] < b.min[axis]
1097 || ( a.min[axis] == b.min[axis]
1098 && a.max[axis] < b.max[axis] );
1104 std::sort( entries.begin(), entries.end(),
1105 [axis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1107 return a.max[axis] < b.max[axis]
1108 || ( a.max[axis] == b.max[axis]
1109 && a.min[axis] < b.min[axis] );
1114 if( perimeterSum < bestPerimeterSum )
1116 bestPerimeterSum = perimeterSum;
1123 std::sort( entries.begin(), entries.end(),
1124 [bestAxis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1126 return a.min[bestAxis] < b.min[bestAxis]
1127 || ( a.min[bestAxis] == b.min[bestAxis]
1128 && a.max[bestAxis] < b.max[bestAxis] );
1134 std::vector<SPLIT_ENTRY> entriesByMax = entries;
1136 std::sort( entriesByMax.begin(), entriesByMax.end(),
1137 [bestAxis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1139 return a.max[bestAxis] < b.max[bestAxis]
1140 || ( a.max[bestAxis] == b.max[bestAxis]
1141 && a.min[bestAxis] < b.min[bestAxis] );
1148 if( overlapMax < overlapMin )
1150 entries = std::move( entriesByMax );
1151 bestSplit = bestSplitMax;
1161 for(
int i = 0; i < bestSplit; ++i )
1163 int slot = aNode->
count;
1168 aNode->
SetInsertBounds( slot, entries[i].insertMin, entries[i].insertMax );
1169 aNode->
data[slot] = entries[i].data;
1173 aNode->
children[slot] = entries[i].child;
1179 for(
int i = bestSplit; i < totalEntries; ++i )
1181 int slot = sibling->
count;
1187 entries[i].insertMax );
1188 sibling->
data[slot] = entries[i].data;
1192 sibling->
children[slot] = entries[i].child;
1199 ELEMTYPE sibMin[NUMDIMS], sibMax[NUMDIMS];
1208 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1220 NODE* parent = aPath.back();
1225 if( childSlot >= 0 )
1227 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1235 int slot = parent->
count;
1255 const ELEMTYPE aMax[NUMDIMS],
NODE* aChild,
1256 std::vector<NODE*>& aPath,
1257 uint32_t& aReinsertedLevels )
1259 int totalEntries = aNode->
count + 1;
1260 std::vector<SPLIT_ENTRY> entries( totalEntries );
1262 for(
int i = 0; i < aNode->
count; ++i )
1265 entries[i].child = aNode->
children[i];
1268 for(
int d = 0; d < NUMDIMS; ++d )
1270 entries[aNode->
count].min[d] = aMin[d];
1271 entries[aNode->
count].max[d] = aMax[d];
1274 entries[aNode->
count].child = aChild;
1278 int64_t bestPerimeterSum = std::numeric_limits<int64_t>::max();
1280 for(
int axis = 0; axis < NUMDIMS; ++axis )
1282 std::sort( entries.begin(), entries.end(),
1283 [axis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1285 return a.min[axis] < b.min[axis];
1290 if( perimSum < bestPerimeterSum )
1292 bestPerimeterSum = perimSum;
1298 std::sort( entries.begin(), entries.end(),
1299 [bestAxis](
const SPLIT_ENTRY& a,
const SPLIT_ENTRY& b )
1301 return a.min[bestAxis] < b.min[bestAxis];
1312 for(
int i = 0; i < bestSplit; ++i )
1314 int slot = aNode->
count;
1316 aNode->
children[slot] = entries[i].child;
1320 for(
int i = bestSplit; i < totalEntries; ++i )
1322 int slot = sibling->
count;
1324 sibling->
children[slot] = entries[i].child;
1328 ELEMTYPE sibMin[NUMDIMS], sibMax[NUMDIMS];
1336 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1348 NODE* parent = aPath.back();
1351 if( childSlot >= 0 )
1353 ELEMTYPE nodeMin[NUMDIMS], nodeMax[NUMDIMS];
1360 int slot = parent->
count;
1371 aReinsertedLevels );
1379 template <
class ENTRY_VEC>
1388 for(
int grp = 0; grp < 2; ++grp )
1390 int start = ( grp == 0 ) ? 0 : k;
1391 int end = ( grp == 0 ) ? k : aTotalEntries;
1393 int64_t perimeter = 0;
1395 for(
int d = 0; d < NUMDIMS; ++d )
1397 ELEMTYPE mn = std::numeric_limits<ELEMTYPE>::max();
1398 ELEMTYPE mx = std::numeric_limits<ELEMTYPE>::lowest();
1400 for(
int i = start; i <
end; ++i )
1402 if( aEntries[i].min[d] < mn )
1403 mn = aEntries[i].min[d];
1405 if( aEntries[i].max[d] > mx )
1406 mx = aEntries[i].max[d];
1409 perimeter +=
static_cast<int64_t
>( mx ) - mn;
1412 sum += 2 * perimeter;
1422 template <
class ENTRY_VEC>
1426 int64_t bestOverlap = std::numeric_limits<int64_t>::max();
1427 int64_t bestAreaSum = std::numeric_limits<int64_t>::max();
1434 int64_t areaSum = 0;
1436 for(
int grp = 0; grp < 2; ++grp )
1438 int start = ( grp == 0 ) ? 0 : k;
1439 int end = ( grp == 0 ) ? k : aTotalEntries;
1442 for(
int d = 0; d < NUMDIMS; ++d )
1444 ELEMTYPE mn = std::numeric_limits<ELEMTYPE>::max();
1445 ELEMTYPE mx = std::numeric_limits<ELEMTYPE>::lowest();
1447 for(
int i = start; i <
end; ++i )
1449 if( aEntries[i].min[d] < mn )
1450 mn = aEntries[i].min[d];
1452 if( aEntries[i].max[d] > mx )
1453 mx = aEntries[i].max[d];
1456 area *=
static_cast<int64_t
>( mx ) - mn;
1462 if( overlap < bestOverlap
1463 || ( overlap == bestOverlap && areaSum < bestAreaSum ) )
1466 bestOverlap = overlap;
1467 bestAreaSum = areaSum;
1477 template <
class ENTRY_VEC>
1479 int aTotalEntries )
const
1481 ELEMTYPE g1Min[NUMDIMS], g1Max[NUMDIMS];
1482 ELEMTYPE g2Min[NUMDIMS], g2Max[NUMDIMS];
1484 for(
int d = 0; d < NUMDIMS; ++d )
1486 g1Min[d] = g2Min[d] = std::numeric_limits<ELEMTYPE>::max();
1487 g1Max[d] = g2Max[d] = std::numeric_limits<ELEMTYPE>::lowest();
1490 for(
int i = 0; i < aSplitIdx; ++i )
1492 for(
int d = 0; d < NUMDIMS; ++d )
1494 if( aEntries[i].min[d] < g1Min[d] )
1495 g1Min[d] = aEntries[i].min[d];
1497 if( aEntries[i].max[d] > g1Max[d] )
1498 g1Max[d] = aEntries[i].max[d];
1502 for(
int i = aSplitIdx; i < aTotalEntries; ++i )
1504 for(
int d = 0; d < NUMDIMS; ++d )
1506 if( aEntries[i].min[d] < g2Min[d] )
1507 g2Min[d] = aEntries[i].min[d];
1509 if( aEntries[i].max[d] > g2Max[d] )
1510 g2Max[d] = aEntries[i].max[d];
1515 int64_t overlap = 1;
1517 for(
int d = 0; d < NUMDIMS; ++d )
1519 ELEMTYPE lo = std::max( g1Min[d], g2Min[d] );
1520 ELEMTYPE hi = std::min( g1Max[d], g2Max[d] );
1525 overlap *=
static_cast<int64_t
>( hi ) - lo;
1537 ELEMTYPE iMin[NUMDIMS], iMax[NUMDIMS];
1540 for(
int j = 0; j < aNode->
count; ++j )
1555 const ELEMTYPE aMax[NUMDIMS] )
const
1557 ELEMTYPE enlargedMin[NUMDIMS], enlargedMax[NUMDIMS];
1560 for(
int d = 0; d < NUMDIMS; ++d )
1562 if( aMin[d] < enlargedMin[d] )
1563 enlargedMin[d] = aMin[d];
1565 if( aMax[d] > enlargedMax[d] )
1566 enlargedMax[d] = aMax[d];
1571 for(
int j = 0; j < aNode->
count; ++j )
1591 NODE* childToUpdate = aBottomChild;
1593 for(
int i =
static_cast<int>( aPath.size() ) - 1; i >= 0; --i )
1595 NODE* parent = aPath[i];
1603 ELEMTYPE childMin[NUMDIMS], childMax[NUMDIMS];
1609 childToUpdate = parent;
1615 for(
int i = 0; i < aParent->
count; ++i )
1617 if( aParent->
children[i] == aChild )
1628 const ELEMTYPE aMax[NUMDIMS],
const DATATYPE& aData,
1629 std::vector<NODE*>& aReinsertList )
1633 for(
int i = 0; i < aNode->
count; ++i )
1635 if( aNode->
data[i] == aData
1647 for(
int i = 0; i < aNode->
count; ++i )
1654 if(
removeImpl( child, aMin, aMax, aData, aReinsertList ) )
1657 if( child->
count > 0 )
1659 ELEMTYPE childMin[NUMDIMS], childMax[NUMDIMS];
1666 aReinsertList.push_back( child );
1688 for(
NODE* orphan : aReinsertList )
1690 if( orphan->IsLeaf() )
1692 for(
int i = 0; i < orphan->count; ++i )
1694 ELEMTYPE mn[NUMDIMS], mx[NUMDIMS];
1695 orphan->GetInsertBounds( i, mn, mx );
1697 uint32_t reinsertedLevels = 0;
1698 insertImpl( mn, mx, orphan->data[i], reinsertedLevels );
1703 for(
int i = 0; i < orphan->count; ++i )
1705 ELEMTYPE mn[NUMDIMS], mx[NUMDIMS];
1706 orphan->GetChildBounds( i, mn, mx );
1708 uint32_t reinsertedLevels = 0;
1709 reinsertNode( orphan->children[i], mn, mx, orphan->level - 1,
1740 template <
class VISITOR>
1742 const ELEMTYPE aMax[NUMDIMS], VISITOR& aVisitor,
int& aFound )
const
1750 int i = std::countr_zero( mask );
1754 if( !aVisitor( aNode->
data[i] ) )
1762 int i = std::countr_zero( mask );
1776 int64_t
minDistSq(
NODE* aNode,
int aSlot,
const ELEMTYPE aPoint[NUMDIMS] )
const
1780 for(
int d = 0; d < NUMDIMS; ++d )
1782 ELEMTYPE lo = aNode->
bounds[d * 2][aSlot];
1783 ELEMTYPE hi = aNode->
bounds[d * 2 + 1][aSlot];
1785 if( aPoint[d] < lo )
1787 int64_t diff =
static_cast<int64_t
>( lo ) - aPoint[d];
1788 dist += diff * diff;
1790 else if( aPoint[d] > hi )
1792 int64_t diff =
static_cast<int64_t
>( aPoint[d] ) - hi;
1793 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)