67#include <unordered_set>
71#define NANOFLANN_VERSION 0x190
74#if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
87#if defined(__GNUC__) || defined(__clang__)
88#define NANOFLANN_RESTRICT __restrict__
89#elif defined(_MSC_VER)
90#define NANOFLANN_RESTRICT __restrict
92#define NANOFLANN_RESTRICT
96#ifndef NANOFLANN_NODE_ALIGNMENT
97#define NANOFLANN_NODE_ALIGNMENT 16
109 return static_cast<T
>(3.14159265358979323846);
116template <
typename T,
typename =
int>
126template <
typename T,
typename =
int>
139template <
typename Container>
140inline typename std::enable_if<has_resize<Container>::value,
void>::type
resize(
141 Container& c,
const size_t nElements)
150template <
typename Container>
151inline typename std::enable_if<!has_resize<Container>::value,
void>::type
resize(
152 Container& c,
const size_t nElements)
154 if (nElements != c.size())
throw std::logic_error(
"Attempt to resize a fixed size container.");
160template <
typename Container,
typename T>
161inline typename std::enable_if<has_assign<Container>::value,
void>::type
assign(
162 Container& c,
const size_t nElements,
const T& value)
164 c.assign(nElements, value);
170template <
typename Container,
typename T>
171inline typename std::enable_if<!has_assign<Container>::value,
void>::type
assign(
172 Container& c,
const size_t nElements,
const T& value)
174 for (
size_t i = 0; i < nElements; i++) c[i] = value;
181 template <
typename PairType>
182 bool operator()(
const PairType& p1,
const PairType& p2)
const
184 return p1.second < p2.second;
196template <
typename IndexType =
size_t,
typename DistanceType =
double>
199 ResultItem() =
default;
200 ResultItem(
const IndexType index,
const DistanceType distance) :
first(index),
second(distance)
212template <
typename _DistanceType,
typename _IndexType =
size_t,
typename _CountType =
size_t>
216 using DistanceType = _DistanceType;
217 using IndexType = _IndexType;
218 using CountType = _CountType;
227 explicit KNNResultSet(CountType capacity_)
228 : indices(
nullptr), dists(
nullptr), capacity(capacity_), count(0)
232 void init(IndexType* indices_, DistanceType* dists_)
239 CountType size()
const noexcept {
return count; }
240 bool empty()
const noexcept {
return count == 0; }
241 bool full()
const noexcept {
return count == capacity; }
251 for (i = count; i > 0; --i)
255#ifdef NANOFLANN_FIRST_MATCH
256 if ((dists[i - 1] > dist) || ((dist == dists[i - 1]) && (indices[i - 1] > index)))
259 if (dists[i - 1] > dist)
264 dists[i] = dists[i - 1];
265 indices[i] = indices[i - 1];
276 if (count < capacity) count++;
286 return (count < capacity || !count) ? std::numeric_limits<DistanceType>::max()
297template <
typename _DistanceType,
typename _IndexType =
size_t,
typename _CountType =
size_t>
301 using DistanceType = _DistanceType;
302 using IndexType = _IndexType;
303 using CountType = _CountType;
310 DistanceType maximumSearchDistanceSquared;
313 explicit RKNNResultSet(CountType capacity_, DistanceType maximumSearchDistanceSquared_)
318 maximumSearchDistanceSquared(maximumSearchDistanceSquared_)
322 void init(IndexType* indices_, DistanceType* dists_)
327 if (capacity) dists[capacity - 1] = maximumSearchDistanceSquared;
330 CountType size()
const noexcept {
return count; }
331 bool empty()
const noexcept {
return count == 0; }
332 bool full()
const noexcept {
return count == capacity; }
342 for (i = count; i > 0; --i)
346#ifdef NANOFLANN_FIRST_MATCH
347 if ((dists[i - 1] > dist) || ((dist == dists[i - 1]) && (indices[i - 1] > index)))
350 if (dists[i - 1] > dist)
355 dists[i] = dists[i - 1];
356 indices[i] = indices[i - 1];
367 if (count < capacity) count++;
377 return (count < capacity || !count) ? maximumSearchDistanceSquared : dists[count - 1];
389template <
typename _DistanceType,
typename _IndexType =
size_t>
393 using DistanceType = _DistanceType;
394 using IndexType = _IndexType;
397 const DistanceType radius;
399 std::vector<ResultItem<IndexType, DistanceType>>& m_indices_dists;
401 explicit RadiusResultSet(
403 : radius(radius_), m_indices_dists(indices_dists)
408 void init() { clear(); }
409 void clear() { m_indices_dists.clear(); }
411 size_t size()
const noexcept {
return m_indices_dists.size(); }
412 bool empty()
const noexcept {
return m_indices_dists.empty(); }
413 bool full()
const noexcept {
return true; }
422 if (dist < radius) m_indices_dists.emplace_back(index, dist);
426 DistanceType worstDist() const noexcept {
return radius; }
434 if (m_indices_dists.empty())
435 throw std::runtime_error(
436 "Cannot invoke RadiusResultSet::worst_item() on "
437 "an empty list of results.");
439 std::max_element(m_indices_dists.begin(), m_indices_dists.end(),
IndexDist_Sorter());
443 void sort() { std::sort(m_indices_dists.begin(), m_indices_dists.end(),
IndexDist_Sorter()); }
451void save_value(std::ostream& stream,
const T& value)
453 stream.write(
reinterpret_cast<const char*
>(&value),
sizeof(T));
457void save_value(std::ostream& stream,
const std::vector<T>& value)
459 size_t size = value.size();
460 stream.write(
reinterpret_cast<const char*
>(&size),
sizeof(
size_t));
461 stream.write(
reinterpret_cast<const char*
>(value.data()),
sizeof(T) * size);
465void load_value(std::istream& stream, T& value)
467 stream.read(
reinterpret_cast<char*
>(&value),
sizeof(T));
471void load_value(std::istream& stream, std::vector<T>& value)
474 stream.read(
reinterpret_cast<char*
>(&size),
sizeof(
size_t));
476 stream.read(
reinterpret_cast<char*
>(value.data()),
sizeof(T) * size);
497template <
class T,
class DataSource,
typename _DistanceType = T,
typename IndexType =
size_t>
500 using ElementType = T;
501 using DistanceType = _DistanceType;
503 const DataSource& data_source;
505 L1_Adaptor(
const DataSource& _data_source) : data_source(_data_source) {}
507 inline DistanceType evalMetric(
508 const T* NANOFLANN_RESTRICT a,
const IndexType b_idx,
size_t size,
509 DistanceType worst_dist = -1)
const
511 DistanceType result = DistanceType();
512 const size_t multof4 = (size >> 2) << 2;
519 for (d = 0; d < multof4; d += 4)
521 const DistanceType diff0 =
522 std::abs(a[d + 0] - data_source.kdtree_get_pt(b_idx, d + 0));
523 const DistanceType diff1 =
524 std::abs(a[d + 1] - data_source.kdtree_get_pt(b_idx, d + 1));
525 const DistanceType diff2 =
526 std::abs(a[d + 2] - data_source.kdtree_get_pt(b_idx, d + 2));
527 const DistanceType diff3 =
528 std::abs(a[d + 3] - data_source.kdtree_get_pt(b_idx, d + 3));
530 result += (diff0 + diff1) + (diff2 + diff3);
536 for (d = 0; d < multof4; d += 4)
538 const DistanceType diff0 =
539 std::abs(a[d + 0] - data_source.kdtree_get_pt(b_idx, d + 0));
540 const DistanceType diff1 =
541 std::abs(a[d + 1] - data_source.kdtree_get_pt(b_idx, d + 1));
542 const DistanceType diff2 =
543 std::abs(a[d + 2] - data_source.kdtree_get_pt(b_idx, d + 2));
544 const DistanceType diff3 =
545 std::abs(a[d + 3] - data_source.kdtree_get_pt(b_idx, d + 3));
547 result += (diff0 + diff1) + (diff2 + diff3);
548 if (result > worst_dist)
556 switch (size - multof4)
559 result += std::abs(a[d + 2] - data_source.kdtree_get_pt(b_idx, d + 2));
561 result += std::abs(a[d + 1] - data_source.kdtree_get_pt(b_idx, d + 1));
563 result += std::abs(a[d + 0] - data_source.kdtree_get_pt(b_idx, d + 0));
570 template <
typename U,
typename V>
571 inline DistanceType accum_dist(
const U a,
const V b,
const size_t)
const
573 return std::abs(a - b);
587template <
class T,
class DataSource,
typename _DistanceType = T,
typename IndexType =
size_t>
590 using ElementType = T;
591 using DistanceType = _DistanceType;
593 const DataSource& data_source;
595 L2_Adaptor(
const DataSource& _data_source) : data_source(_data_source) {}
597 inline DistanceType evalMetric(
598 const T* NANOFLANN_RESTRICT a,
const IndexType b_idx,
size_t size,
599 DistanceType worst_dist = -1)
const
601 DistanceType result = DistanceType();
602 const size_t multof4 = (size >> 2) << 2;
609 for (d = 0; d < multof4; d += 4)
611 const DistanceType diff0 = a[d + 0] - data_source.kdtree_get_pt(b_idx, d + 0);
612 const DistanceType diff1 = a[d + 1] - data_source.kdtree_get_pt(b_idx, d + 1);
613 const DistanceType diff2 = a[d + 2] - data_source.kdtree_get_pt(b_idx, d + 2);
614 const DistanceType diff3 = a[d + 3] - data_source.kdtree_get_pt(b_idx, d + 3);
616 result += (diff0 * diff0 + diff1 * diff1) + (diff2 * diff2 + diff3 * diff3);
622 for (d = 0; d < multof4; d += 4)
624 const DistanceType diff0 = a[d + 0] - data_source.kdtree_get_pt(b_idx, d + 0);
625 const DistanceType diff1 = a[d + 1] - data_source.kdtree_get_pt(b_idx, d + 1);
626 const DistanceType diff2 = a[d + 2] - data_source.kdtree_get_pt(b_idx, d + 2);
627 const DistanceType diff3 = a[d + 3] - data_source.kdtree_get_pt(b_idx, d + 3);
629 result += (diff0 * diff0 + diff1 * diff1) + (diff2 * diff2 + diff3 * diff3);
630 if (result > worst_dist)
639 switch (size - multof4)
642 diff = a[d + 2] - data_source.kdtree_get_pt(b_idx, d + 2);
643 result += diff * diff;
645 diff = a[d + 1] - data_source.kdtree_get_pt(b_idx, d + 1);
646 result += diff * diff;
648 diff = a[d + 0] - data_source.kdtree_get_pt(b_idx, d + 0);
649 result += diff * diff;
656 template <
typename U,
typename V>
657 inline DistanceType accum_dist(
const U a,
const V b,
const size_t)
const
674template <
class T,
class DataSource,
typename _DistanceType = T,
typename IndexType =
size_t>
675struct L2_Simple_Adaptor
677 using ElementType = T;
678 using DistanceType = _DistanceType;
680 const DataSource& data_source;
682 L2_Simple_Adaptor(
const DataSource& _data_source) : data_source(_data_source) {}
684 inline DistanceType evalMetric(
const T* a,
const IndexType b_idx,
size_t size)
const
686 DistanceType result = DistanceType();
687 for (
size_t i = 0; i < size; ++i)
689 const DistanceType diff = a[i] - data_source.kdtree_get_pt(b_idx, i);
690 result += diff * diff;
695 template <
typename U,
typename V>
696 inline DistanceType accum_dist(
const U a,
const V b,
const size_t)
const
713template <
class T,
class DataSource,
typename _DistanceType = T,
typename IndexType =
size_t>
716 using ElementType = T;
717 using DistanceType = _DistanceType;
719 const DataSource& data_source;
721 SO2_Adaptor(
const DataSource& _data_source) : data_source(_data_source) {}
723 inline DistanceType evalMetric(
const T* a,
const IndexType b_idx,
size_t size)
const
725 return accum_dist(a[size - 1], data_source.kdtree_get_pt(b_idx, size - 1), size - 1);
730 template <
typename U,
typename V>
731 inline DistanceType
accum_dist(
const U a,
const V b,
const size_t)
const
733 DistanceType result = DistanceType();
738 else if (result < -PI)
754template <
class T,
class DataSource,
typename _DistanceType = T,
typename IndexType =
size_t>
757 using ElementType = T;
758 using DistanceType = _DistanceType;
762 SO3_Adaptor(
const DataSource& _data_source) : distance_L2_Simple(_data_source) {}
764 inline DistanceType evalMetric(
const T* a,
const IndexType b_idx,
size_t size)
const
766 return distance_L2_Simple.evalMetric(a, b_idx, size);
769 template <
typename U,
typename V>
770 inline DistanceType accum_dist(
const U a,
const V b,
const size_t idx)
const
772 return distance_L2_Simple.accum_dist(a, b, idx);
779 template <
class T,
class DataSource,
typename IndexType =
size_t>
789 template <
class T,
class DataSource,
typename IndexType =
size_t>
799 template <
class T,
class DataSource,
typename IndexType =
size_t>
808 template <
class T,
class DataSource,
typename IndexType =
size_t>
817 template <
class T,
class DataSource,
typename IndexType =
size_t>
829enum class KDTreeSingleIndexAdaptorFlags
832 SkipInitialBuildIndex = 1
835inline std::underlying_type<KDTreeSingleIndexAdaptorFlags>::type operator&(
836 KDTreeSingleIndexAdaptorFlags lhs, KDTreeSingleIndexAdaptorFlags rhs)
838 using underlying =
typename std::underlying_type<KDTreeSingleIndexAdaptorFlags>::type;
839 return static_cast<underlying
>(lhs) &
static_cast<underlying
>(rhs);
843struct KDTreeSingleIndexAdaptorParams
845 KDTreeSingleIndexAdaptorParams(
846 size_t _leaf_max_size = 10,
847 KDTreeSingleIndexAdaptorFlags _flags = KDTreeSingleIndexAdaptorFlags::None,
848 unsigned int _n_thread_build = 1)
849 : leaf_max_size(_leaf_max_size), flags(_flags), n_thread_build(_n_thread_build)
853 size_t leaf_max_size;
854 KDTreeSingleIndexAdaptorFlags flags;
855 unsigned int n_thread_build;
859struct SearchParameters
861 SearchParameters(
float eps_ = 0,
bool sorted_ =
true) :
eps(eps_),
sorted(sorted_) {}
888 static constexpr size_t WORDSIZE = 16;
889 static constexpr size_t BLOCKSIZE = 8192;
900 void* base_ =
nullptr;
901 void* loc_ =
nullptr;
913 Size wastedMemory = 0;
928 while (base_ !=
nullptr)
931 void* prev = *(
static_cast<void**
>(base_));
948 const Size size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1);
953 if (size > remaining_)
955 wastedMemory += remaining_;
958 const Size blocksize = size > BLOCKSIZE ? size + WORDSIZE : BLOCKSIZE + WORDSIZE;
964 throw std::bad_alloc();
968 static_cast<void**
>(m)[0] = base_;
971 remaining_ = blocksize - WORDSIZE;
972 loc_ =
static_cast<char*
>(m) + WORDSIZE;
975 loc_ =
static_cast<char*
>(loc_) + size;
990 template <
typename T>
993 T* mem =
static_cast<T*
>(this->
malloc(
sizeof(T) * count));
1005template <
int32_t DIM,
typename T>
1008 using type = std::array<T, DIM>;
1011template <
typename T>
1014 using type = std::vector<T>;
1034 class Derived,
typename Distance,
class DatasetAdaptor, int32_t DIM = -1,
1035 typename index_t = uint32_t>
1043 obj.pool_.free_all();
1044 obj.root_node_ =
nullptr;
1045 obj.size_at_index_build_ = 0;
1048 using ElementType =
typename Distance::ElementType;
1049 using DistanceType =
typename Distance::DistanceType;
1050 using IndexType = index_t;
1057 using Offset =
typename decltype(
vAcc_)::size_type;
1058 using Size =
typename decltype(
vAcc_)::size_type;
1059 using Dimension = int32_t;
1073 struct alignas(NANOFLANN_NODE_ALIGNMENT)
Node
1087 DistanceType divlow, divhigh;
1095 using NodePtr =
Node*;
1096 using NodeConstPtr =
const Node*;
1100 ElementType low, high;
1103 NodePtr root_node_ =
nullptr;
1105 Size leaf_max_size_ = 0;
1136 Size
size(
const Derived& obj)
const {
return obj.size_; }
1139 Size
veclen(
const Derived& obj)
const {
return DIM > 0 ? DIM : obj.dim_; }
1142 ElementType
dataset_get(
const Derived& obj, IndexType element, Dimension component)
const
1144 return obj.dataset_.kdtree_get_pt(element, component);
1153 return obj.pool_.usedMemory + obj.pool_.wastedMemory +
1154 obj.dataset_.kdtree_get_point_count() *
1162 const Derived& obj, Offset ind, Size count, Dimension element, ElementType& min_elem,
1163 ElementType& max_elem)
const
1166 max_elem = min_elem;
1167 for (Offset i = 1; i < count; ++i)
1170 if (val < min_elem) min_elem = val;
1171 if (val > max_elem) max_elem = val;
1186 assert(left < obj.dataset_.kdtree_get_point_count());
1188 NodePtr node = obj.pool_.template allocate<Node>();
1189 const auto dims = (DIM > 0 ? DIM : obj.dim_);
1192 if ((right - left) <=
static_cast<Offset
>(obj.leaf_max_size_))
1194 node->
child1 = node->child2 =
nullptr;
1199 for (Dimension i = 0; i < dims; ++i)
1201 bbox[i].low =
dataset_get(obj, obj.vAcc_[left], i);
1202 bbox[i].high =
dataset_get(obj, obj.vAcc_[left], i);
1204 for (Offset k = left + 1; k < right; ++k)
1206 for (Dimension i = 0; i < dims; ++i)
1208 const auto val =
dataset_get(obj, obj.vAcc_[k], i);
1209 if (bbox[i].low > val) bbox[i].low = val;
1210 if (bbox[i].high < val) bbox[i].high = val;
1219 DistanceType cutval;
1220 middleSplit_(obj, left, right - left, idx, cutfeat, cutval, bbox);
1226 left_bbox[cutfeat].high = cutval;
1231 right_bbox[cutfeat].low = cutval;
1232 node->child2 = this->
divideTree(obj, left + idx, right, right_bbox);
1234 node->
node_type.sub.divlow = left_bbox[cutfeat].high;
1235 node->
node_type.sub.divhigh = right_bbox[cutfeat].low;
1237 for (Dimension i = 0; i < dims; ++i)
1239 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
1240 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
1260 Derived& obj,
const Offset left,
const Offset right,
BoundingBox& bbox,
1261 std::atomic<unsigned int>& thread_count, std::mutex& mutex)
1263 std::unique_lock<std::mutex> lock(mutex);
1264 NodePtr node = obj.pool_.template allocate<Node>();
1267 const auto dims = (DIM > 0 ? DIM : obj.dim_);
1270 if ((right - left) <=
static_cast<Offset
>(obj.leaf_max_size_))
1272 node->
child1 = node->child2 =
nullptr;
1277 for (Dimension i = 0; i < dims; ++i)
1279 bbox[i].low =
dataset_get(obj, obj.vAcc_[left], i);
1280 bbox[i].high =
dataset_get(obj, obj.vAcc_[left], i);
1282 for (Offset k = left + 1; k < right; ++k)
1284 for (Dimension i = 0; i < dims; ++i)
1286 const auto val =
dataset_get(obj, obj.vAcc_[k], i);
1287 if (bbox[i].low > val) bbox[i].low = val;
1288 if (bbox[i].high < val) bbox[i].high = val;
1297 DistanceType cutval;
1298 middleSplit_(obj, left, right - left, idx, cutfeat, cutval, bbox);
1302 std::future<NodePtr> right_future;
1307 right_bbox[cutfeat].low = cutval;
1312 right_future = std::async(
1314 left + idx, right, std::ref(right_bbox), std::ref(thread_count),
1325 left_bbox[cutfeat].high = cutval;
1329 if (right_future.valid())
1333 node->child2 = right_future.get();
1341 obj, left + idx, right, right_bbox, thread_count, mutex);
1344 node->
node_type.sub.divlow = left_bbox[cutfeat].high;
1345 node->
node_type.sub.divhigh = right_bbox[cutfeat].low;
1347 for (Dimension i = 0; i < dims; ++i)
1349 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
1350 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
1358 const Derived& obj,
const Offset ind,
const Size count, Offset& index, Dimension& cutfeat,
1359 DistanceType& cutval,
const BoundingBox& bbox)
1361 const auto dims = (DIM > 0 ? DIM : obj.dim_);
1362 const auto EPS =
static_cast<DistanceType
>(0.00001);
1365 ElementType max_span = bbox[0].high - bbox[0].low;
1366 for (Dimension i = 1; i < dims; ++i)
1368 ElementType span = bbox[i].high - bbox[i].low;
1369 if (span > max_span) max_span = span;
1374 ElementType max_spread = -1;
1375 ElementType min_elem = 0, max_elem = 0;
1378 std::vector<Dimension> candidates;
1379 candidates.reserve(dims);
1380 for (Dimension i = 0; i < dims; ++i)
1382 if (bbox[i].high - bbox[i].low >= (1 - EPS) * max_span)
1384 candidates.push_back(i);
1389 for (Dimension dim : candidates)
1391 ElementType local_min = dataset_get(obj, vAcc_[ind], dim);
1392 ElementType local_max = local_min;
1395 constexpr size_t UNROLL = 4;
1397 for (; k + UNROLL <= count; k += UNROLL)
1399 ElementType v0 = dataset_get(obj, vAcc_[ind + k], dim);
1400 ElementType v1 = dataset_get(obj, vAcc_[ind + k + 1], dim);
1401 ElementType v2 = dataset_get(obj, vAcc_[ind + k + 2], dim);
1402 ElementType v3 = dataset_get(obj, vAcc_[ind + k + 3], dim);
1404 local_min = std::min({local_min, v0, v1, v2, v3});
1405 local_max = std::max({local_max, v0, v1, v2, v3});
1409 for (; k < count; ++k)
1411 ElementType val = dataset_get(obj, vAcc_[ind + k], dim);
1412 local_min = std::min(local_min, val);
1413 local_max = std::max(local_max, val);
1416 ElementType spread = local_max - local_min;
1417 if (spread > max_spread)
1420 max_spread = spread;
1421 min_elem = local_min;
1422 max_elem = local_max;
1427 DistanceType split_val = (bbox[cutfeat].low + bbox[cutfeat].high) / 2;
1428 if (split_val < min_elem) split_val = min_elem;
1429 if (split_val > max_elem) split_val = max_elem;
1435 planeSplit(obj, ind, count, cutfeat, cutval, lim1, lim2);
1437 index = (lim1 > count / 2) ? lim1 : (lim2 < count / 2) ? lim2 : count / 2;
1450 const Derived& obj,
const Offset ind,
const Size count,
const Dimension cutfeat,
1451 const DistanceType& cutval, Offset& lim1, Offset& lim2)
1456 Offset right = count - 1;
1458 while (mid <= right)
1464 std::swap(
vAcc_[ind + left],
vAcc_[ind + mid]);
1468 else if (val > cutval)
1470 std::swap(
vAcc_[ind + mid],
vAcc_[ind + right]);
1483 DistanceType computeInitialDistances(
1484 const Derived& obj,
const ElementType* vec, distance_vector_t& dists)
const
1487 DistanceType dist = DistanceType();
1489 for (Dimension i = 0; i < (DIM > 0 ? DIM : obj.dim_); ++i)
1491 if (vec[i] < obj.root_bbox_[i].low)
1493 dists[i] = obj.distance_.accum_dist(vec[i], obj.root_bbox_[i].low, i);
1496 if (vec[i] > obj.root_bbox_[i].high)
1498 dists[i] = obj.distance_.accum_dist(vec[i], obj.root_bbox_[i].high, i);
1505 static void save_tree(
const Derived& obj, std::ostream& stream,
const NodeConstPtr tree)
1507 save_value(stream, *tree);
1508 if (tree->child1 !=
nullptr)
1510 save_tree(obj, stream, tree->child1);
1512 if (tree->child2 !=
nullptr)
1514 save_tree(obj, stream, tree->child2);
1518 static void load_tree(Derived& obj, std::istream& stream, NodePtr& tree)
1520 tree = obj.pool_.template allocate<Node>();
1521 load_value(stream, *tree);
1522 if (tree->child1 !=
nullptr)
1524 load_tree(obj, stream, tree->child1);
1526 if (tree->child2 !=
nullptr)
1528 load_tree(obj, stream, tree->child2);
1537 void saveIndex(
const Derived& obj, std::ostream& stream)
const
1539 save_value(stream, obj.size_);
1540 save_value(stream, obj.dim_);
1541 save_value(stream, obj.root_bbox_);
1542 save_value(stream, obj.leaf_max_size_);
1543 save_value(stream, obj.vAcc_);
1544 if (obj.root_node_) save_tree(obj, stream, obj.root_node_);
1554 load_value(stream, obj.size_);
1555 load_value(stream, obj.dim_);
1556 load_value(stream, obj.root_bbox_);
1557 load_value(stream, obj.leaf_max_size_);
1558 load_value(stream, obj.vAcc_);
1559 load_tree(obj, stream, obj.root_node_);
1604template <
typename Distance,
class DatasetAdaptor, int32_t DIM = -1,
typename index_t = uint32_t>
1607 KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM, index_t>, Distance,
1608 DatasetAdaptor, DIM, index_t>
1624 DatasetAdaptor, DIM, index_t>;
1626 using Offset =
typename Base::Offset;
1627 using Size =
typename Base::Size;
1628 using Dimension =
typename Base::Dimension;
1630 using ElementType =
typename Base::ElementType;
1631 using DistanceType =
typename Base::DistanceType;
1632 using IndexType =
typename Base::IndexType;
1634 using Node =
typename Base::Node;
1635 using NodePtr = Node*;
1637 using Interval =
typename Base::Interval;
1667 template <
class... Args>
1669 const Dimension dimensionality,
const DatasetAdaptor& inputData,
1672 indexParams(params),
1673 distance_(inputData, std::forward<Args>(args)...)
1675 init(dimensionality, params);
1679 const Dimension dimensionality,
const DatasetAdaptor& inputData,
1681 : dataset_(inputData), indexParams(params), distance_(inputData)
1683 init(dimensionality, params);
1687 void init(
const Dimension dimensionality,
const KDTreeSingleIndexAdaptorParams& params)
1689 Base::size_ = dataset_.kdtree_get_point_count();
1690 Base::size_at_index_build_ = Base::size_;
1691 Base::dim_ = dimensionality;
1692 if (DIM > 0) Base::dim_ = DIM;
1693 Base::leaf_max_size_ = params.leaf_max_size;
1694 if (params.n_thread_build > 0)
1696 Base::n_thread_build_ = params.n_thread_build;
1700 Base::n_thread_build_ = std::max(std::thread::hardware_concurrency(), 1u);
1703 if (!(params.flags & KDTreeSingleIndexAdaptorFlags::SkipInitialBuildIndex))
1716 Base::size_ =
dataset_.kdtree_get_point_count();
1717 Base::size_at_index_build_ = Base::size_;
1720 Base::size_at_index_build_ = Base::size_;
1721 if (Base::size_ == 0)
return;
1722 computeBoundingBox(Base::root_bbox_);
1724 if (Base::n_thread_build_ == 1)
1726 Base::root_node_ = this->
divideTree(*
this, 0, Base::size_, Base::root_bbox_);
1730#ifndef NANOFLANN_NO_THREADS
1731 std::atomic<unsigned int> thread_count(0u);
1734 *
this, 0, Base::size_, Base::root_bbox_, thread_count, mutex);
1736 throw std::runtime_error(
"Multithreading is disabled");
1760 template <
typename RESULTSET>
1762 RESULTSET& result,
const ElementType* vec,
const SearchParameters& searchParams = {})
const
1765 if (this->size(*
this) == 0)
return false;
1766 if (!Base::root_node_)
1767 throw std::runtime_error(
1768 "[nanoflann] findNeighbors() called before building the "
1770 float epsError = 1 + searchParams.eps;
1773 distance_vector_t dists;
1775 auto zero =
static_cast<typename RESULTSET::DistanceType
>(0);
1776 assign(dists, (DIM > 0 ? DIM : Base::dim_), zero);
1777 DistanceType dist = this->computeInitialDistances(*
this, vec, dists);
1778 searchLevel(result, vec, Base::root_node_, dist, dists, epsError);
1780 if (searchParams.sorted) result.sort();
1782 return result.full();
1800 template <
typename RESULTSET>
1803 if (this->size(*
this) == 0)
return 0;
1804 if (!Base::root_node_)
1805 throw std::runtime_error(
1806 "[nanoflann] findWithinBox() called before building the "
1809 std::stack<NodePtr> stack;
1810 stack.push(Base::root_node_);
1812 while (!stack.empty())
1814 const NodePtr node = stack.top();
1820 for (Offset i = node->node_type.lr.left; i < node->node_type.lr.right; ++i)
1822 if (contains(bbox, Base::vAcc_[i]))
1824 if (!result.addPoint(0, Base::vAcc_[i]))
1828 return result.size();
1835 const int idx = node->node_type.sub.divfeat;
1836 const auto low_bound = node->node_type.sub.divlow;
1837 const auto high_bound = node->node_type.sub.divhigh;
1839 if (bbox[idx].low <= low_bound) stack.push(node->child1);
1840 if (bbox[idx].high >= high_bound) stack.push(node->child2);
1844 return result.size();
1863 const ElementType* query_point,
const Size num_closest, IndexType* out_indices,
1864 DistanceType* out_distances)
const
1867 resultSet.init(out_indices, out_distances);
1869 return resultSet.size();
1892 const ElementType* query_point,
const DistanceType& radius,
1897 const Size nFound = radiusSearchCustomCallback(query_point, resultSet, searchParams);
1906 template <
class SEARCH_CALLBACK>
1908 const ElementType* query_point, SEARCH_CALLBACK& resultSet,
1911 findNeighbors(resultSet, query_point, searchParams);
1912 return resultSet.size();
1932 const ElementType* query_point,
const Size num_closest, IndexType* out_indices,
1933 DistanceType* out_distances,
const DistanceType& radius)
const
1936 resultSet.init(out_indices, out_distances);
1938 return resultSet.size();
1949 Base::size_ =
dataset_.kdtree_get_point_count();
1950 if (Base::vAcc_.
size() != Base::size_) Base::vAcc_.resize(Base::size_);
1951 for (IndexType i = 0; i < static_cast<IndexType>(Base::size_); i++) Base::vAcc_[i] = i;
1954 void computeBoundingBox(BoundingBox& bbox)
1956 const auto dims = (DIM > 0 ? DIM : Base::dim_);
1958 if (dataset_.kdtree_get_bbox(bbox))
1964 const Size N = dataset_.kdtree_get_point_count();
1966 throw std::runtime_error(
1967 "[nanoflann] computeBoundingBox() called but "
1968 "no data points found.");
1969 for (Dimension i = 0; i < dims; ++i)
1971 bbox[i].low = bbox[i].high = this->dataset_get(*
this, Base::vAcc_[0], i);
1973 for (Offset k = 1; k < N; ++k)
1975 for (Dimension i = 0; i < dims; ++i)
1977 const auto val = this->dataset_get(*
this, Base::vAcc_[k], i);
1978 if (val < bbox[i].low) bbox[i].low = val;
1979 if (val > bbox[i].high) bbox[i].high = val;
1985 bool contains(
const BoundingBox& bbox, IndexType idx)
const
1987 const auto dims = (DIM > 0 ? DIM : Base::dim_);
1988 for (Dimension i = 0; i < dims; ++i)
1990 const auto point = this->dataset_.kdtree_get_pt(idx, i);
1991 if (point < bbox[i].low || point > bbox[i].high)
return false;
2002 template <
class RESULTSET>
2004 RESULTSET& result_set,
const ElementType* vec,
const NodePtr node, DistanceType mindist,
2010 for (Offset i = node->node_type.lr.left; i < node->node_type.lr.right; ++i)
2012 const IndexType accessor = Base::vAcc_[i];
2014 distance_.evalMetric(vec, accessor, (DIM > 0 ? DIM : Base::dim_));
2015 if (dist < result_set.worstDist())
2017 if (!result_set.addPoint(dist, Base::vAcc_[i]))
2029 Dimension idx = node->node_type.sub.divfeat;
2030 ElementType val = vec[idx];
2031 DistanceType diff1 = val - node->node_type.sub.divlow;
2032 DistanceType diff2 = val - node->node_type.sub.divhigh;
2036 DistanceType cut_dist;
2037 if ((diff1 + diff2) < 0)
2039 bestChild = node->child1;
2040 otherChild = node->child2;
2041 cut_dist = distance_.accum_dist(val, node->node_type.sub.divhigh, idx);
2045 bestChild = node->child2;
2046 otherChild = node->child1;
2047 cut_dist = distance_.accum_dist(val, node->node_type.sub.divlow, idx);
2051 if (!
searchLevel(result_set, vec, bestChild, mindist, dists, epsError))
2058 DistanceType dst = dists[idx];
2059 mindist = mindist + cut_dist - dst;
2060 dists[idx] = cut_dist;
2061 if (mindist * epsError <= result_set.worstDist())
2063 if (!
searchLevel(result_set, vec, otherChild, mindist, dists, epsError))
2080 void saveIndex(std::ostream& stream)
const { Base::saveIndex(*
this, stream); }
2087 void loadIndex(std::istream& stream) { Base::loadIndex(*
this, stream); }
2128template <
typename Distance,
class DatasetAdaptor, int32_t DIM = -1,
typename IndexType = uint32_t>
2131 KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM, IndexType>, Distance,
2132 DatasetAdaptor, DIM, IndexType>
2142 std::vector<int>& treeIndex_;
2148 Distance, DatasetAdaptor, DIM, IndexType>;
2150 using ElementType =
typename Base::ElementType;
2151 using DistanceType =
typename Base::DistanceType;
2153 using Offset =
typename Base::Offset;
2154 using Size =
typename Base::Size;
2155 using Dimension =
typename Base::Dimension;
2157 using Node =
typename Base::Node;
2158 using NodePtr = Node*;
2160 using Interval =
typename Base::Interval;
2185 const Dimension dimensionality,
const DatasetAdaptor& inputData,
2186 std::vector<int>& treeIndex,
2188 :
dataset_(inputData), index_params_(params), treeIndex_(treeIndex), distance_(inputData)
2191 Base::size_at_index_build_ = 0;
2192 for (
auto& v : Base::root_bbox_) v = {};
2193 Base::dim_ = dimensionality;
2194 if (DIM > 0) Base::dim_ = DIM;
2195 Base::leaf_max_size_ = params.leaf_max_size;
2196 if (params.n_thread_build > 0)
2198 Base::n_thread_build_ = params.n_thread_build;
2202 Base::n_thread_build_ = std::max(std::thread::hardware_concurrency(), 1u);
2213 std::swap(Base::vAcc_, tmp.Base::vAcc_);
2214 std::swap(Base::leaf_max_size_, tmp.Base::leaf_max_size_);
2215 std::swap(index_params_, tmp.index_params_);
2216 std::swap(treeIndex_, tmp.treeIndex_);
2217 std::swap(Base::size_, tmp.Base::size_);
2218 std::swap(Base::size_at_index_build_, tmp.Base::size_at_index_build_);
2219 std::swap(Base::root_node_, tmp.Base::root_node_);
2220 std::swap(Base::root_bbox_, tmp.Base::root_bbox_);
2221 std::swap(Base::pool_, tmp.Base::pool_);
2230 Base::size_ = Base::vAcc_.size();
2232 Base::size_at_index_build_ = Base::size_;
2233 if (Base::size_ == 0)
return;
2234 computeBoundingBox(Base::root_bbox_);
2236 if (Base::n_thread_build_ == 1)
2238 Base::root_node_ = this->
divideTree(*
this, 0, Base::size_, Base::root_bbox_);
2242#ifndef NANOFLANN_NO_THREADS
2243 std::atomic<unsigned int> thread_count(0u);
2246 *
this, 0, Base::size_, Base::root_bbox_, thread_count, mutex);
2248 throw std::runtime_error(
"Multithreading is disabled");
2276 template <
typename RESULTSET>
2278 RESULTSET& result,
const ElementType* vec,
const SearchParameters& searchParams = {})
const
2281 if (this->size(*
this) == 0)
return false;
2282 if (!Base::root_node_)
return false;
2283 float epsError = 1 + searchParams.eps;
2286 distance_vector_t dists;
2289 dists, (DIM > 0 ? DIM : Base::dim_),
2290 static_cast<typename distance_vector_t::value_type
>(0));
2291 DistanceType dist = this->computeInitialDistances(*
this, vec, dists);
2292 searchLevel(result, vec, Base::root_node_, dist, dists, epsError);
2294 if (searchParams.sorted) result.sort();
2296 return result.full();
2314 const ElementType* query_point,
const Size num_closest, IndexType* out_indices,
2315 DistanceType* out_distances,
const SearchParameters& searchParams = {})
const
2318 resultSet.init(out_indices, out_distances);
2319 findNeighbors(resultSet, query_point, searchParams);
2320 return resultSet.size();
2343 const ElementType* query_point,
const DistanceType& radius,
2348 const size_t nFound = radiusSearchCustomCallback(query_point, resultSet, searchParams);
2357 template <
class SEARCH_CALLBACK>
2359 const ElementType* query_point, SEARCH_CALLBACK& resultSet,
2362 findNeighbors(resultSet, query_point, searchParams);
2363 return resultSet.size();
2369 void computeBoundingBox(BoundingBox& bbox)
2371 const auto dims = (DIM > 0 ? DIM : Base::dim_);
2374 if (dataset_.kdtree_get_bbox(bbox))
2380 const Size N = Base::size_;
2382 throw std::runtime_error(
2383 "[nanoflann] computeBoundingBox() called but "
2384 "no data points found.");
2385 for (Dimension i = 0; i < dims; ++i)
2387 bbox[i].low = bbox[i].high = this->dataset_get(*
this, Base::vAcc_[0], i);
2389 for (Offset k = 1; k < N; ++k)
2391 for (Dimension i = 0; i < dims; ++i)
2393 const auto val = this->dataset_get(*
this, Base::vAcc_[k], i);
2394 if (val < bbox[i].low) bbox[i].low = val;
2395 if (val > bbox[i].high) bbox[i].high = val;
2405 template <
class RESULTSET>
2407 RESULTSET& result_set,
const ElementType* vec,
const NodePtr node, DistanceType mindist,
2413 for (Offset i = node->node_type.lr.left; i < node->node_type.lr.right; ++i)
2415 const IndexType index = Base::vAcc_[i];
2416 if (treeIndex_[index] == -1)
continue;
2417 DistanceType dist = distance_.evalMetric(vec, index, (DIM > 0 ? DIM : Base::dim_));
2418 if (dist < result_set.worstDist())
2420 if (!result_set.addPoint(
2421 static_cast<typename RESULTSET::DistanceType
>(dist),
2422 static_cast<typename RESULTSET::IndexType
>(Base::vAcc_[i])))
2434 Dimension idx = node->node_type.sub.divfeat;
2435 ElementType val = vec[idx];
2436 DistanceType diff1 = val - node->node_type.sub.divlow;
2437 DistanceType diff2 = val - node->node_type.sub.divhigh;
2441 DistanceType cut_dist;
2442 if ((diff1 + diff2) < 0)
2444 bestChild = node->child1;
2445 otherChild = node->child2;
2446 cut_dist = distance_.accum_dist(val, node->node_type.sub.divhigh, idx);
2450 bestChild = node->child2;
2451 otherChild = node->child1;
2452 cut_dist = distance_.accum_dist(val, node->node_type.sub.divlow, idx);
2456 searchLevel(result_set, vec, bestChild, mindist, dists, epsError);
2458 DistanceType dst = dists[idx];
2459 mindist = mindist + cut_dist - dst;
2460 dists[idx] = cut_dist;
2461 if (mindist * epsError <= result_set.worstDist())
2463 searchLevel(result_set, vec, otherChild, mindist, dists, epsError);
2498template <
typename Distance,
class DatasetAdaptor, int32_t DIM = -1,
typename IndexType = uint32_t>
2502 using ElementType =
typename Distance::ElementType;
2503 using DistanceType =
typename Distance::DistanceType;
2505 using Offset =
typename KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM>::Offset;
2506 using Size =
typename KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM>::Size;
2508 typename KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM>::Dimension;
2511 Size leaf_max_size_;
2523 std::unordered_set<int> removedPoints_;
2529 using index_container_t =
2531 std::vector<index_container_t> index_;
2540 int First0Bit(IndexType num)
2554 using my_kd_tree_t =
2555 KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM, IndexType>;
2556 std::vector<my_kd_tree_t> index(
2557 treeCount_, my_kd_tree_t(dim_ , dataset_, treeIndex_, index_params_));
2580 const int dimensionality,
const DatasetAdaptor& inputData,
2582 const size_t maximumPointCount = 1000000000U)
2583 :
dataset_(inputData), index_params_(params), distance_(inputData)
2585 treeCount_ =
static_cast<size_t>(std::log2(maximumPointCount)) + 1;
2587 dim_ = dimensionality;
2589 if (DIM > 0)
dim_ = DIM;
2590 leaf_max_size_ = params.leaf_max_size;
2592 const size_t num_initial_points =
dataset_.kdtree_get_point_count();
2593 if (num_initial_points > 0)
2606 const Size count = end - start + 1;
2609 for (IndexType idx = start; idx <= end; idx++)
2611 const int pos = First0Bit(pointCount_);
2612 maxIndex = std::max(pos, maxIndex);
2615 const auto it = removedPoints_.find(idx);
2616 if (it != removedPoints_.end())
2618 removedPoints_.erase(it);
2622 for (
int i = 0; i < pos; i++)
2624 for (
int j = 0; j < static_cast<int>(index_[i].vAcc_.size()); j++)
2626 index_[pos].vAcc_.push_back(index_[i].vAcc_[j]);
2629 index_[i].vAcc_.clear();
2631 index_[pos].vAcc_.push_back(idx);
2635 for (
int i = 0; i <= maxIndex; ++i)
2637 index_[i].freeIndex(index_[i]);
2638 if (!index_[i].vAcc_.empty()) index_[i].buildIndex();
2645 if (idx >= pointCount_)
return;
2646 removedPoints_.insert(idx);
2666 template <
typename RESULTSET>
2668 RESULTSET& result,
const ElementType* vec,
const SearchParameters& searchParams = {})
const
2670 for (
size_t i = 0; i < treeCount_; i++)
2672 index_[i].findNeighbors(result, &vec[0], searchParams);
2674 return result.full();
2704 class MatrixType, int32_t DIM = -1,
class Distance = nanoflann::metric_L2,
2705 bool row_major =
true>
2709 using num_t =
typename MatrixType::Scalar;
2710 using IndexType =
typename MatrixType::Index;
2711 using metric_t =
typename Distance::template traits<num_t, self_t, IndexType>::distance_t;
2714 metric_t, self_t, row_major ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime,
2721 using Size =
typename index_t::Size;
2722 using Dimension =
typename index_t::Dimension;
2726 const Dimension dimensionality,
const std::reference_wrapper<const MatrixType>& mat,
2727 const int leaf_max_size = 10,
const unsigned int n_thread_build = 1)
2728 : m_data_matrix(mat)
2730 const auto dims = row_major ? mat.get().cols() : mat.get().rows();
2731 if (
static_cast<Dimension
>(dims) != dimensionality)
2732 throw std::runtime_error(
2733 "Error: 'dimensionality' must match column count in data "
2735 if (DIM > 0 &&
static_cast<int32_t
>(dims) != DIM)
2736 throw std::runtime_error(
2737 "Data set dimensionality does not match the 'DIM' template "
2739 index_ =
new index_t(
2742 leaf_max_size, nanoflann::KDTreeSingleIndexAdaptorFlags::None, n_thread_build));
2751 const std::reference_wrapper<const MatrixType> m_data_matrix;
2762 const num_t* query_point,
const Size num_closest, IndexType* out_indices,
2763 num_t* out_distances)
const
2766 resultSet.init(out_indices, out_distances);
2767 index_->findNeighbors(resultSet, query_point);
2773 inline const self_t& derived() const noexcept {
return *
this; }
2774 inline self_t& derived() noexcept {
return *
this; }
2777 inline Size kdtree_get_point_count()
const
2780 return m_data_matrix.get().rows();
2782 return m_data_matrix.get().cols();
2786 inline num_t kdtree_get_pt(
const IndexType idx,
size_t dim)
const
2789 return m_data_matrix.get().coeff(idx, IndexType(dim));
2791 return m_data_matrix.get().coeff(IndexType(dim), idx);
2799 template <
class BBOX>
2800 inline bool kdtree_get_bbox(BBOX& )
const
2813#undef NANOFLANN_RESTRICT
Definition nanoflann.hpp:1037
void freeIndex(Derived &obj)
Definition nanoflann.hpp:1041
Size veclen(const Derived &obj) const
Definition nanoflann.hpp:1139
void computeMinMax(const Derived &obj, Offset ind, Size count, Dimension element, ElementType &min_elem, ElementType &max_elem) const
Definition nanoflann.hpp:1161
BoundingBox root_bbox_
Definition nanoflann.hpp:1124
void saveIndex(const Derived &obj, std::ostream &stream) const
Definition nanoflann.hpp:1537
Dimension dim_
Dimensionality of each data point.
Definition nanoflann.hpp:1113
typename array_or_vector< DIM, DistanceType >::type distance_vector_t
Definition nanoflann.hpp:1121
void planeSplit(const Derived &obj, const Offset ind, const Size count, const Dimension cutfeat, const DistanceType &cutval, Offset &lim1, Offset &lim2)
Definition nanoflann.hpp:1449
Size n_thread_build_
Number of thread for concurrent tree build.
Definition nanoflann.hpp:1108
NodePtr divideTree(Derived &obj, const Offset left, const Offset right, BoundingBox &bbox)
Definition nanoflann.hpp:1184
std::vector< IndexType > vAcc_
Definition nanoflann.hpp:1055
Size size(const Derived &obj) const
Definition nanoflann.hpp:1136
Size size_at_index_build_
Number of points in the dataset when the index was built.
Definition nanoflann.hpp:1112
NodePtr divideTreeConcurrent(Derived &obj, const Offset left, const Offset right, BoundingBox &bbox, std::atomic< unsigned int > &thread_count, std::mutex &mutex)
Definition nanoflann.hpp:1259
Size size_
Number of current points in the dataset.
Definition nanoflann.hpp:1110
Size usedMemory(const Derived &obj) const
Definition nanoflann.hpp:1151
void loadIndex(Derived &obj, std::istream &stream)
Definition nanoflann.hpp:1552
PooledAllocator pool_
Definition nanoflann.hpp:1133
ElementType dataset_get(const Derived &obj, IndexType element, Dimension component) const
Helper accessor to the dataset points:
Definition nanoflann.hpp:1142
typename array_or_vector< DIM, Interval >::type BoundingBox
Definition nanoflann.hpp:1117
Definition nanoflann.hpp:1609
bool searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindist, distance_vector_t &dists, const float epsError) const
Definition nanoflann.hpp:2003
void saveIndex(std::ostream &stream) const
Definition nanoflann.hpp:2080
Size findWithinBox(RESULTSET &result, const BoundingBox &bbox) const
Definition nanoflann.hpp:1801
Size radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< ResultItem< IndexType, DistanceType > > &IndicesDists, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1891
void init_vind()
Definition nanoflann.hpp:1946
void buildIndex()
Definition nanoflann.hpp:1714
const self_t & dataset_
Definition nanoflann.hpp:1616
KDTreeSingleIndexAdaptor(const KDTreeSingleIndexAdaptor< Distance, DatasetAdaptor, DIM, index_t > &)=delete
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1761
Size rknnSearch(const ElementType *query_point, const Size num_closest, IndexType *out_indices, DistanceType *out_distances, const DistanceType &radius) const
Definition nanoflann.hpp:1931
Size radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1907
typename Base::distance_vector_t distance_vector_t
Definition nanoflann.hpp:1645
void loadIndex(std::istream &stream)
Definition nanoflann.hpp:2087
typename Base::BoundingBox BoundingBox
Definition nanoflann.hpp:1641
KDTreeSingleIndexAdaptor(const Dimension dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams ¶ms, Args &&... args)
Definition nanoflann.hpp:1668
Size knnSearch(const ElementType *query_point, const Size num_closest, IndexType *out_indices, DistanceType *out_distances) const
Definition nanoflann.hpp:1862
Definition nanoflann.hpp:2133
Size radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< ResultItem< IndexType, DistanceType > > &IndicesDists, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2342
KDTreeSingleIndexDynamicAdaptor_(const Dimension dimensionality, const DatasetAdaptor &inputData, std::vector< int > &treeIndex, const KDTreeSingleIndexAdaptorParams ¶ms=KDTreeSingleIndexAdaptorParams())
Definition nanoflann.hpp:2184
typename Base::BoundingBox BoundingBox
Definition nanoflann.hpp:2163
const DatasetAdaptor & dataset_
Definition nanoflann.hpp:2138
Size radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2358
KDTreeSingleIndexDynamicAdaptor_(const KDTreeSingleIndexDynamicAdaptor_ &rhs)=default
void buildIndex()
Definition nanoflann.hpp:2228
void saveIndex(std::ostream &stream)
Definition nanoflann.hpp:2474
typename Base::distance_vector_t distance_vector_t
Definition nanoflann.hpp:2167
void loadIndex(std::istream &stream)
Definition nanoflann.hpp:2481
Size knnSearch(const ElementType *query_point, const Size num_closest, IndexType *out_indices, DistanceType *out_distances, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2313
void searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindist, distance_vector_t &dists, const float epsError) const
Definition nanoflann.hpp:2406
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2277
KDTreeSingleIndexDynamicAdaptor_ operator=(const KDTreeSingleIndexDynamicAdaptor_ &rhs)
Definition nanoflann.hpp:2210
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2667
const DatasetAdaptor & dataset_
The source of our data.
Definition nanoflann.hpp:2518
void removePoint(size_t idx)
Definition nanoflann.hpp:2643
void addPoints(IndexType start, IndexType end)
Definition nanoflann.hpp:2604
KDTreeSingleIndexDynamicAdaptor(const int dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams ¶ms=KDTreeSingleIndexAdaptorParams(), const size_t maximumPointCount=1000000000U)
Definition nanoflann.hpp:2579
std::vector< int > treeIndex_
Definition nanoflann.hpp:2522
const std::vector< index_container_t > & getAllIndices() const
Definition nanoflann.hpp:2536
Dimension dim_
Dimensionality of each data point.
Definition nanoflann.hpp:2527
KDTreeSingleIndexDynamicAdaptor(const KDTreeSingleIndexDynamicAdaptor< Distance, DatasetAdaptor, DIM, IndexType > &)=delete
Definition nanoflann.hpp:214
bool addPoint(DistanceType dist, IndexType index)
Definition nanoflann.hpp:248
DistanceType worstDist() const noexcept
Returns the worst distance among found solutions if the search result is full, or the maximum possibl...
Definition nanoflann.hpp:284
Definition nanoflann.hpp:887
~PooledAllocator()
Definition nanoflann.hpp:923
void free_all()
Definition nanoflann.hpp:926
void * malloc(const size_t req_size)
Definition nanoflann.hpp:942
T * allocate(const size_t count=1)
Definition nanoflann.hpp:991
PooledAllocator()
Definition nanoflann.hpp:918
Definition nanoflann.hpp:299
bool addPoint(DistanceType dist, IndexType index)
Definition nanoflann.hpp:339
DistanceType worstDist() const noexcept
Returns the worst distance among found solutions if the search result is full, or the maximum possibl...
Definition nanoflann.hpp:375
Definition nanoflann.hpp:391
ResultItem< IndexType, DistanceType > worst_item() const
Definition nanoflann.hpp:432
bool addPoint(DistanceType dist, IndexType index)
Definition nanoflann.hpp:420
std::enable_if< has_assign< Container >::value, void >::type assign(Container &c, const size_t nElements, const T &value)
Definition nanoflann.hpp:161
std::enable_if< has_resize< Container >::value, void >::type resize(Container &c, const size_t nElements)
Definition nanoflann.hpp:140
constexpr T pi_const()
Definition nanoflann.hpp:107
Definition nanoflann.hpp:179
bool operator()(const PairType &p1, const PairType &p2) const
Definition nanoflann.hpp:182
Definition nanoflann.hpp:1099
Definition nanoflann.hpp:1074
Offset right
Indices of points in leaf node.
Definition nanoflann.hpp:1081
Dimension divfeat
Dimension used for subdivision. The values used for subdivision.
Definition nanoflann.hpp:1085
Node * child1
Definition nanoflann.hpp:1092
union nanoflann::KDTreeBaseClass::Node::@327270127162340211203002370327206303122355110302 node_type
void query(const num_t *query_point, const Size num_closest, IndexType *out_indices, num_t *out_distances) const
Definition nanoflann.hpp:2761
KDTreeEigenMatrixAdaptor(const self_t &)=delete
typename index_t::Offset Offset
Definition nanoflann.hpp:2720
KDTreeEigenMatrixAdaptor(const Dimension dimensionality, const std::reference_wrapper< const MatrixType > &mat, const int leaf_max_size=10, const unsigned int n_thread_build=1)
Constructor: takes a const ref to the matrix object with the data points.
Definition nanoflann.hpp:2725
Definition nanoflann.hpp:844
Definition nanoflann.hpp:499
Definition nanoflann.hpp:589
Definition nanoflann.hpp:676
Definition nanoflann.hpp:484
Definition nanoflann.hpp:198
DistanceType second
Distance from sample to query point.
Definition nanoflann.hpp:205
IndexType first
Index of the sample in the dataset.
Definition nanoflann.hpp:204
Definition nanoflann.hpp:715
DistanceType accum_dist(const U a, const V b, const size_t) const
Definition nanoflann.hpp:731
Definition nanoflann.hpp:756
Definition nanoflann.hpp:860
bool sorted
only for radius search, require neighbours sorted by distance (default: true)
Definition nanoflann.hpp:864
float eps
search for eps-approximate neighbours (default: 0)
Definition nanoflann.hpp:863
Definition nanoflann.hpp:1007
Definition nanoflann.hpp:128
Definition nanoflann.hpp:118
Definition nanoflann.hpp:781
Definition nanoflann.hpp:778
Definition nanoflann.hpp:791
Definition nanoflann.hpp:801
Definition nanoflann.hpp:798
Definition nanoflann.hpp:788
Definition nanoflann.hpp:810
Definition nanoflann.hpp:807
Definition nanoflann.hpp:819
Definition nanoflann.hpp:816