Skip to content

Commit f1efcd1

Browse files
committed
Refactoring neighbors impl
1 parent 2d9c0f6 commit f1efcd1

1 file changed

Lines changed: 41 additions & 40 deletions

File tree

flatbush.h

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,7 +1392,7 @@ class Flatbush {
13921392
std::vector<size_t> searchImpl(const Box<ArrayType>& iBounds,
13931393
const FilterCb& iFilterFn) const noexcept;
13941394

1395-
template <bool IsWideIndex>
1395+
template <bool IsWideIndex, bool UseHeap>
13961396
std::vector<size_t> neighborsImpl(const Point<ArrayType>& iPoint,
13971397
size_t iMaxResults,
13981398
double iMaxDistSquared,
@@ -1816,13 +1816,11 @@ std::vector<size_t> Flatbush<ArrayType>::search(const Box<ArrayType>& iBounds,
18161816
}
18171817

18181818
template <typename ArrayType>
1819-
template <bool IsWideIndex>
1819+
template <bool IsWideIndex, bool UseHeap>
18201820
std::vector<size_t> Flatbush<ArrayType>::neighborsImpl(const Point<ArrayType>& iPoint,
18211821
size_t iMaxResults,
18221822
double iMaxDistSquared,
18231823
const FilterCb& iFilterFn) const noexcept {
1824-
static constexpr auto kMergeThreshold = 64UL;
1825-
const auto wUseHeap = iMaxResults > kMergeThreshold;
18261824
const auto wNumItems = numItems();
18271825
const auto wNodeSize = nodeSize();
18281826
auto wNodeIndex = mBoxes.size() - 1UL;
@@ -1834,55 +1832,47 @@ std::vector<size_t> Flatbush<ArrayType>::neighborsImpl(const Point<ArrayType>& i
18341832
while (true) {
18351833
// find the end index of the node
18361834
const auto wEnd = std::min(wNodeIndex + wNodeSize, upperBound(wNodeIndex));
1835+
const auto wIsInternalNode = wNodeIndex >= wNumItems;
1836+
const auto wQueueSize = wQueue.size();
18371837

1838-
if (wUseHeap) {
1839-
// Heap strategy: push_heap after each insert, pop from front
1840-
for (auto wPosition = wNodeIndex; wPosition < wEnd; ++wPosition) {
1841-
const auto wDistSquared = detail::computeDistanceSquared(iPoint, mBoxes[wPosition]);
1842-
if (wDistSquared > iMaxDistSquared) {
1843-
continue;
1844-
}
1845-
const auto wIndex = getIndex<IsWideIndex>(wPosition);
1846-
const auto wIsInternalNode = wNodeIndex >= wNumItems;
1847-
if (wIsInternalNode || !iFilterFn || iFilterFn(wIndex, mBoxes[wPosition])) {
1848-
wQueue.emplace_back((wIndex << 1U) + !wIsInternalNode, wDistSquared);
1849-
std::push_heap(wQueue.begin(), wQueue.end());
1850-
}
1838+
for (auto wPosition = wNodeIndex; wPosition < wEnd; ++wPosition) {
1839+
const auto wDistSquared = detail::computeDistanceSquared(iPoint, mBoxes[wPosition]);
1840+
1841+
if (wDistSquared > iMaxDistSquared) {
1842+
continue;
1843+
}
1844+
1845+
const auto wIndex = getIndex<IsWideIndex>(wPosition);
1846+
1847+
if (wIsInternalNode || !iFilterFn || iFilterFn(wIndex, mBoxes[wPosition])) {
1848+
wQueue.emplace_back((wIndex << 1U) + !wIsInternalNode, wDistSquared);
1849+
if (UseHeap) std::push_heap(wQueue.begin(), wQueue.end());
18511850
}
1851+
}
18521852

1853+
if (UseHeap) { // Heap strategy: push_heap after each insert, pop from front
18531854
while (!wQueue.empty() && (wQueue.front().mId & 1U)) {
18541855
wResults.push_back(wQueue.front().mId >> 1U);
18551856
std::pop_heap(wQueue.begin(), wQueue.end());
18561857
wQueue.pop_back();
1858+
18571859
if (wResults.size() >= iMaxResults) {
18581860
return wResults;
18591861
}
18601862
}
1861-
} else {
1862-
// Sorted-vector strategy: batch insert, sort+merge, pop from back
1863-
const auto wOldSize = wQueue.size();
1864-
1865-
for (auto wPosition = wNodeIndex; wPosition < wEnd; ++wPosition) {
1866-
const auto wDistSquared = detail::computeDistanceSquared(iPoint, mBoxes[wPosition]);
1867-
if (wDistSquared > iMaxDistSquared) {
1868-
continue;
1869-
}
1870-
const auto wIndex = getIndex<IsWideIndex>(wPosition);
1871-
const auto wIsInternalNode = wNodeIndex >= wNumItems;
1872-
if (wIsInternalNode || !iFilterFn || iFilterFn(wIndex, mBoxes[wPosition])) {
1873-
wQueue.emplace_back((wIndex << 1U) + !wIsInternalNode, wDistSquared);
1874-
}
1875-
}
18761863

1877-
if (wQueue.size() > wOldSize) {
1878-
const auto wMid = wQueue.begin() + static_cast<ptrdiff_t>(wOldSize);
1879-
std::sort(wMid, wQueue.end(), std::less<IndexDistance>());
1880-
std::inplace_merge(wQueue.begin(), wMid, wQueue.end(), std::less<IndexDistance>());
1864+
std::pop_heap(wQueue.begin(), wQueue.end());
1865+
} else { // Sorted-vector strategy: batch insert, sort+merge, pop from back
1866+
if (wQueue.size() > wQueueSize) {
1867+
const auto wMid = wQueue.begin() + static_cast<ptrdiff_t>(wQueueSize);
1868+
std::sort(wMid, wQueue.end());
1869+
std::inplace_merge(wQueue.begin(), wMid, wQueue.end());
18811870
}
18821871

18831872
while (!wQueue.empty() && (wQueue.back().mId & 1U)) {
18841873
wResults.push_back(wQueue.back().mId >> 1U);
18851874
wQueue.pop_back();
1875+
18861876
if (wResults.size() >= iMaxResults) {
18871877
return wResults;
18881878
}
@@ -1893,8 +1883,7 @@ std::vector<size_t> Flatbush<ArrayType>::neighborsImpl(const Point<ArrayType>& i
18931883
break;
18941884
}
18951885

1896-
if (wUseHeap) std::pop_heap(wQueue.begin(), wQueue.end());
1897-
wNodeIndex = wQueue.back().mId >> 3U;
1886+
wNodeIndex = wQueue.back().mId >> 3U; // undo indexing + for binary compatibility with JS
18981887
wQueue.pop_back();
18991888

19001889
#ifdef __GNUC__
@@ -1912,17 +1901,29 @@ std::vector<size_t> Flatbush<ArrayType>::neighbors(const Point<ArrayType>& iPoin
19121901
size_t iMaxResults,
19131902
double iMaxDistance,
19141903
const FilterCb& iFilterFn) const noexcept {
1904+
static constexpr auto kMergeThreshold = 64UL;
1905+
static constexpr auto kWideIndex = true;
1906+
static constexpr auto kUseHeap = true;
19151907
const auto wMaxDistSquared = iMaxDistance * iMaxDistance;
1908+
const auto wNeedHeap = iMaxResults > kMergeThreshold;
19161909

19171910
if (!canDoNeighbors(iPoint, iMaxResults, iMaxDistance, wMaxDistSquared)) {
19181911
return {};
19191912
}
19201913

19211914
if (mIsWideIndex) {
1922-
return neighborsImpl<true>(iPoint, iMaxResults, wMaxDistSquared, iFilterFn);
1915+
if (wNeedHeap) {
1916+
return neighborsImpl<kWideIndex, kUseHeap>(iPoint, iMaxResults, wMaxDistSquared, iFilterFn);
1917+
}
1918+
1919+
return neighborsImpl<kWideIndex, !kUseHeap>(iPoint, iMaxResults, wMaxDistSquared, iFilterFn);
1920+
}
1921+
1922+
if (wNeedHeap) {
1923+
return neighborsImpl<!kWideIndex, kUseHeap>(iPoint, iMaxResults, wMaxDistSquared, iFilterFn);
19231924
}
19241925

1925-
return neighborsImpl<false>(iPoint, iMaxResults, wMaxDistSquared, iFilterFn);
1926+
return neighborsImpl<!kWideIndex, !kUseHeap>(iPoint, iMaxResults, wMaxDistSquared, iFilterFn);
19261927
}
19271928
} // namespace flatbush
19281929

0 commit comments

Comments
 (0)