61#include <unordered_set>
65#define NANOFLANN_VERSION 0x180
68#if !defined(NOMINMAX) && \
69 (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
90 return static_cast<T
>(3.14159265358979323846);
97template <
typename T,
typename =
int>
108template <
typename T,
typename =
int>
122template <
typename Container>
123inline typename std::enable_if<has_resize<Container>::value,
void>::type
resize(
124 Container& c,
const size_t nElements)
133template <
typename Container>
134inline typename std::enable_if<!has_resize<Container>::value,
void>::type
135 resize(Container& c,
const size_t nElements)
137 if (nElements != c.size())
138 throw std::logic_error(
"Try to change the size of a std::array.");
144template <
typename Container,
typename T>
145inline typename std::enable_if<has_assign<Container>::value,
void>::type
assign(
146 Container& c,
const size_t nElements,
const T& value)
148 c.assign(nElements, value);
154template <
typename Container,
typename T>
155inline typename std::enable_if<!has_assign<Container>::value,
void>::type
156 assign(Container& c,
const size_t nElements,
const T& value)
158 for (
size_t i = 0; i < nElements; i++) c[i] = value;
165 template <
typename PairType>
166 bool operator()(
const PairType& p1,
const PairType& p2)
const
168 return p1.second < p2.second;
180template <
typename IndexType =
size_t,
typename DistanceType =
double>
184 ResultItem(
const IndexType index,
const DistanceType distance)
198 typename _DistanceType,
typename _IndexType = size_t,
199 typename _CountType =
size_t>
203 using DistanceType = _DistanceType;
204 using IndexType = _IndexType;
205 using CountType = _CountType;
215 : indices(
nullptr), dists(
nullptr), capacity(capacity_), count(0)
219 void init(IndexType* indices_, DistanceType* dists_)
226 CountType size()
const {
return count; }
227 bool empty()
const {
return count == 0; }
228 bool full()
const {
return count == capacity; }
238 for (i = count; i > 0; --i)
242#ifdef NANOFLANN_FIRST_MATCH
243 if ((dists[i - 1] > dist) ||
244 ((dist == dists[i - 1]) && (indices[i - 1] > index)))
247 if (dists[i - 1] > dist)
252 dists[i] = dists[i - 1];
253 indices[i] = indices[i - 1];
264 if (count < capacity) count++;
274 return (count < capacity || !count)
275 ? std::numeric_limits<DistanceType>::max()
287 typename _DistanceType,
typename _IndexType = size_t,
288 typename _CountType =
size_t>
292 using DistanceType = _DistanceType;
293 using IndexType = _IndexType;
294 using CountType = _CountType;
301 DistanceType maximumSearchDistanceSquared;
305 CountType capacity_, DistanceType maximumSearchDistanceSquared_)
310 maximumSearchDistanceSquared(maximumSearchDistanceSquared_)
314 void init(IndexType* indices_, DistanceType* dists_)
319 if (capacity) dists[capacity - 1] = maximumSearchDistanceSquared;
322 CountType size()
const {
return count; }
323 bool empty()
const {
return count == 0; }
324 bool full()
const {
return count == capacity; }
334 for (i = count; i > 0; --i)
338#ifdef NANOFLANN_FIRST_MATCH
339 if ((dists[i - 1] > dist) ||
340 ((dist == dists[i - 1]) && (indices[i - 1] > index)))
343 if (dists[i - 1] > dist)
348 dists[i] = dists[i - 1];
349 indices[i] = indices[i - 1];
360 if (count < capacity) count++;
370 return (count < capacity || !count) ? maximumSearchDistanceSquared
383template <
typename _DistanceType,
typename _IndexType =
size_t>
387 using DistanceType = _DistanceType;
388 using IndexType = _IndexType;
391 const DistanceType radius;
393 std::vector<ResultItem<IndexType, DistanceType>>& m_indices_dists;
396 DistanceType radius_,
398 : radius(radius_), m_indices_dists(indices_dists)
403 void init() { clear(); }
404 void clear() { m_indices_dists.clear(); }
406 size_t size()
const {
return m_indices_dists.size(); }
407 size_t empty()
const {
return m_indices_dists.empty(); }
409 bool full()
const {
return true; }
418 if (dist < radius) m_indices_dists.emplace_back(index, dist);
422 DistanceType worstDist()
const {
return radius; }
430 if (m_indices_dists.empty())
431 throw std::runtime_error(
432 "Cannot invoke RadiusResultSet::worst_item() on "
433 "an empty list of results.");
434 auto it = std::max_element(
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);
498 class T,
class DataSource,
typename _DistanceType = T,
499 typename IndexType =
size_t>
502 using ElementType = T;
503 using DistanceType = _DistanceType;
505 const DataSource& data_source;
507 L1_Adaptor(
const DataSource& _data_source) : data_source(_data_source) {}
509 DistanceType evalMetric(
510 const T* a,
const IndexType b_idx,
size_t size,
511 DistanceType worst_dist = -1)
const
513 DistanceType result = DistanceType();
514 const T* last = a + size;
515 const T* lastgroup = last - 3;
519 while (a < lastgroup)
521 const DistanceType diff0 =
522 std::abs(a[0] - data_source.kdtree_get_pt(b_idx, d++));
523 const DistanceType diff1 =
524 std::abs(a[1] - data_source.kdtree_get_pt(b_idx, d++));
525 const DistanceType diff2 =
526 std::abs(a[2] - data_source.kdtree_get_pt(b_idx, d++));
527 const DistanceType diff3 =
528 std::abs(a[3] - data_source.kdtree_get_pt(b_idx, d++));
529 result += diff0 + diff1 + diff2 + diff3;
531 if ((worst_dist > 0) && (result > worst_dist)) {
return result; }
537 result += std::abs(*a++ - data_source.kdtree_get_pt(b_idx, d++));
542 template <
typename U,
typename V>
543 DistanceType accum_dist(
const U a,
const V b,
const size_t)
const
545 return std::abs(a - b);
560 class T,
class DataSource,
typename _DistanceType = T,
561 typename IndexType =
size_t>
564 using ElementType = T;
565 using DistanceType = _DistanceType;
567 const DataSource& data_source;
569 L2_Adaptor(
const DataSource& _data_source) : data_source(_data_source) {}
571 DistanceType evalMetric(
572 const T* a,
const IndexType b_idx,
size_t size,
573 DistanceType worst_dist = -1)
const
575 DistanceType result = DistanceType();
576 const T* last = a + size;
577 const T* lastgroup = last - 3;
581 while (a < lastgroup)
583 const DistanceType diff0 =
584 a[0] - data_source.kdtree_get_pt(b_idx, d++);
585 const DistanceType diff1 =
586 a[1] - data_source.kdtree_get_pt(b_idx, d++);
587 const DistanceType diff2 =
588 a[2] - data_source.kdtree_get_pt(b_idx, d++);
589 const DistanceType diff3 =
590 a[3] - data_source.kdtree_get_pt(b_idx, d++);
592 diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
594 if ((worst_dist > 0) && (result > worst_dist)) {
return result; }
600 const DistanceType diff0 =
601 *a++ - data_source.kdtree_get_pt(b_idx, d++);
602 result += diff0 * diff0;
607 template <
typename U,
typename V>
608 DistanceType accum_dist(
const U a,
const V b,
const size_t)
const
610 return (a - b) * (a - b);
625 class T,
class DataSource,
typename _DistanceType = T,
626 typename IndexType =
size_t>
629 using ElementType = T;
630 using DistanceType = _DistanceType;
632 const DataSource& data_source;
635 : data_source(_data_source)
639 DistanceType evalMetric(
640 const T* a,
const IndexType b_idx,
size_t size)
const
642 DistanceType result = DistanceType();
643 for (
size_t i = 0; i < size; ++i)
645 const DistanceType diff =
646 a[i] - data_source.kdtree_get_pt(b_idx, i);
647 result += diff * diff;
652 template <
typename U,
typename V>
653 DistanceType accum_dist(
const U a,
const V b,
const size_t)
const
655 return (a - b) * (a - b);
670 class T,
class DataSource,
typename _DistanceType = T,
671 typename IndexType =
size_t>
674 using ElementType = T;
675 using DistanceType = _DistanceType;
677 const DataSource& data_source;
679 SO2_Adaptor(
const DataSource& _data_source) : data_source(_data_source) {}
681 DistanceType evalMetric(
682 const T* a,
const IndexType b_idx,
size_t size)
const
685 a[size - 1], data_source.kdtree_get_pt(b_idx, size - 1), size - 1);
690 template <
typename U,
typename V>
691 DistanceType
accum_dist(
const U a,
const V b,
const size_t)
const
693 DistanceType result = DistanceType();
694 DistanceType PI = pi_const<DistanceType>();
698 else if (result < -PI)
715 class T,
class DataSource,
typename _DistanceType = T,
716 typename IndexType =
size_t>
719 using ElementType = T;
720 using DistanceType = _DistanceType;
726 : distance_L2_Simple(_data_source)
730 DistanceType evalMetric(
731 const T* a,
const IndexType b_idx,
size_t size)
const
733 return distance_L2_Simple.evalMetric(a, b_idx, size);
736 template <
typename U,
typename V>
737 DistanceType accum_dist(
const U a,
const V b,
const size_t idx)
const
739 return distance_L2_Simple.accum_dist(a, b, idx);
746 template <
class T,
class DataSource,
typename IndexType =
size_t>
756 template <
class T,
class DataSource,
typename IndexType =
size_t>
766 template <
class T,
class DataSource,
typename IndexType =
size_t>
775 template <
class T,
class DataSource,
typename IndexType =
size_t>
784 template <
class T,
class DataSource,
typename IndexType =
size_t>
796enum class KDTreeSingleIndexAdaptorFlags
799 SkipInitialBuildIndex = 1
802inline std::underlying_type<KDTreeSingleIndexAdaptorFlags>::type operator&(
803 KDTreeSingleIndexAdaptorFlags lhs, KDTreeSingleIndexAdaptorFlags rhs)
806 typename std::underlying_type<KDTreeSingleIndexAdaptorFlags>::type;
807 return static_cast<underlying
>(lhs) &
static_cast<underlying
>(rhs);
814 size_t _leaf_max_size = 10,
815 KDTreeSingleIndexAdaptorFlags _flags =
816 KDTreeSingleIndexAdaptorFlags::None,
817 unsigned int _n_thread_build = 1)
818 : leaf_max_size(_leaf_max_size),
820 n_thread_build(_n_thread_build)
824 size_t leaf_max_size;
825 KDTreeSingleIndexAdaptorFlags flags;
826 unsigned int n_thread_build;
833 : eps(eps_), sorted(sorted_)
862 static constexpr size_t WORDSIZE = 16;
863 static constexpr size_t BLOCKSIZE = 8192;
874 void* base_ =
nullptr;
875 void* loc_ =
nullptr;
887 Size wastedMemory = 0;
902 while (base_ !=
nullptr)
905 void* prev = *(
static_cast<void**
>(base_));
922 const Size size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1);
927 if (size > remaining_)
929 wastedMemory += remaining_;
932 const Size blocksize =
933 size > BLOCKSIZE ? size + WORDSIZE : BLOCKSIZE + WORDSIZE;
936 void* m = ::malloc(blocksize);
937 if (!m) {
throw std::bad_alloc(); }
940 static_cast<void**
>(m)[0] = base_;
943 remaining_ = blocksize - WORDSIZE;
944 loc_ =
static_cast<char*
>(m) + WORDSIZE;
947 loc_ =
static_cast<char*
>(loc_) + size;
962 template <
typename T>
965 T* mem =
static_cast<T*
>(this->malloc(
sizeof(T) * count));
977template <
int32_t DIM,
typename T>
980 using type = std::array<T, DIM>;
986 using type = std::vector<T>;
1006 class Derived,
typename Distance,
class DatasetAdaptor, int32_t DIM = -1,
1007 typename index_t = uint32_t>
1015 obj.pool_.free_all();
1016 obj.root_node_ =
nullptr;
1017 obj.size_at_index_build_ = 0;
1020 using ElementType =
typename Distance::ElementType;
1021 using DistanceType =
typename Distance::DistanceType;
1022 using IndexType = index_t;
1029 using Offset =
typename decltype(vAcc_)::size_type;
1030 using Size =
typename decltype(vAcc_)::size_type;
1031 using Dimension = int32_t;
1055 Node *child1 =
nullptr, *child2 =
nullptr;
1063 ElementType low, high;
1068 Size leaf_max_size_ = 0;
1071 Size n_thread_build_ = 1;
1075 Size size_at_index_build_ = 0;
1099 Size
size(
const Derived& obj)
const {
return obj.size_; }
1102 Size
veclen(
const Derived& obj)
const {
return DIM > 0 ? DIM : obj.dim_; }
1106 const Derived& obj, IndexType element, Dimension component)
const
1108 return obj.dataset_.kdtree_get_pt(element, component);
1117 return obj.pool_.usedMemory + obj.pool_.wastedMemory +
1118 obj.dataset_.kdtree_get_point_count() *
1126 const Derived& obj, Offset ind, Size count, Dimension element,
1127 ElementType& min_elem, ElementType& max_elem)
const
1129 min_elem = dataset_get(obj, vAcc_[ind], element);
1130 max_elem = min_elem;
1131 for (Offset i = 1; i < count; ++i)
1133 ElementType val = dataset_get(obj, vAcc_[ind + i], element);
1134 if (val < min_elem) min_elem = val;
1135 if (val > max_elem) max_elem = val;
1149 Derived& obj,
const Offset left,
const Offset right,
BoundingBox& bbox)
1151 assert(left < obj.dataset_.kdtree_get_point_count());
1153 NodePtr node = obj.pool_.template allocate<Node>();
1154 const auto dims = (DIM > 0 ? DIM : obj.dim_);
1157 if ((right - left) <=
static_cast<Offset
>(obj.leaf_max_size_))
1159 node->
child1 = node->child2 =
nullptr;
1164 for (Dimension i = 0; i < dims; ++i)
1166 bbox[i].low = dataset_get(obj, obj.vAcc_[left], i);
1167 bbox[i].high = dataset_get(obj, obj.vAcc_[left], i);
1169 for (Offset k = left + 1; k < right; ++k)
1171 for (Dimension i = 0; i < dims; ++i)
1173 const auto val = dataset_get(obj, obj.vAcc_[k], i);
1174 if (bbox[i].low > val) bbox[i].low = val;
1175 if (bbox[i].high < val) bbox[i].high = val;
1184 DistanceType cutval;
1185 middleSplit_(obj, left, right - left, idx, cutfeat, cutval, bbox);
1191 left_bbox[cutfeat].high = cutval;
1192 node->
child1 = this->divideTree(obj, left, left + idx, left_bbox);
1196 right_bbox[cutfeat].low = cutval;
1197 node->child2 = this->divideTree(obj, left + idx, right, right_bbox);
1199 node->
node_type.sub.divlow = left_bbox[cutfeat].high;
1200 node->
node_type.sub.divhigh = right_bbox[cutfeat].low;
1202 for (Dimension i = 0; i < dims; ++i)
1204 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
1205 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
1225 Derived& obj,
const Offset left,
const Offset right,
BoundingBox& bbox,
1226 std::atomic<unsigned int>& thread_count, std::mutex& mutex)
1228 std::unique_lock<std::mutex> lock(mutex);
1229 NodePtr node = obj.pool_.template allocate<Node>();
1232 const auto dims = (DIM > 0 ? DIM : obj.dim_);
1235 if ((right - left) <=
static_cast<Offset
>(obj.leaf_max_size_))
1237 node->
child1 = node->child2 =
nullptr;
1242 for (Dimension i = 0; i < dims; ++i)
1244 bbox[i].low = dataset_get(obj, obj.vAcc_[left], i);
1245 bbox[i].high = dataset_get(obj, obj.vAcc_[left], i);
1247 for (Offset k = left + 1; k < right; ++k)
1249 for (Dimension i = 0; i < dims; ++i)
1251 const auto val = dataset_get(obj, obj.vAcc_[k], i);
1252 if (bbox[i].low > val) bbox[i].low = val;
1253 if (bbox[i].high < val) bbox[i].high = val;
1262 DistanceType cutval;
1263 middleSplit_(obj, left, right - left, idx, cutfeat, cutval, bbox);
1267 std::future<NodePtr> right_future;
1272 right_bbox[cutfeat].low = cutval;
1273 if (++thread_count < n_thread_build_)
1277 right_future = std::async(
1278 std::launch::async, &KDTreeBaseClass::divideTreeConcurrent,
1279 this, std::ref(obj), left + idx, right,
1280 std::ref(right_bbox), std::ref(thread_count),
1283 else { --thread_count; }
1288 left_bbox[cutfeat].high = cutval;
1289 node->
child1 = this->divideTreeConcurrent(
1290 obj, left, left + idx, left_bbox, thread_count, mutex);
1292 if (right_future.valid())
1296 node->child2 = right_future.get();
1303 node->child2 = this->divideTreeConcurrent(
1304 obj, left + idx, right, right_bbox, thread_count, mutex);
1307 node->
node_type.sub.divlow = left_bbox[cutfeat].high;
1308 node->
node_type.sub.divhigh = right_bbox[cutfeat].low;
1310 for (Dimension i = 0; i < dims; ++i)
1312 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
1313 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
1321 const Derived& obj,
const Offset ind,
const Size count, Offset& index,
1322 Dimension& cutfeat, DistanceType& cutval,
const BoundingBox& bbox)
1324 const auto dims = (DIM > 0 ? DIM : obj.dim_);
1325 const auto EPS =
static_cast<DistanceType
>(0.00001);
1326 ElementType max_span = bbox[0].high - bbox[0].low;
1327 for (Dimension i = 1; i < dims; ++i)
1329 ElementType span = bbox[i].high - bbox[i].low;
1330 if (span > max_span) { max_span = span; }
1332 ElementType max_spread = -1;
1334 ElementType min_elem = 0, max_elem = 0;
1335 for (Dimension i = 0; i < dims; ++i)
1337 ElementType span = bbox[i].high - bbox[i].low;
1338 if (span >= (1 - EPS) * max_span)
1340 ElementType min_elem_, max_elem_;
1341 computeMinMax(obj, ind, count, i, min_elem_, max_elem_);
1342 ElementType spread = max_elem_ - min_elem_;
1343 if (spread > max_spread)
1346 max_spread = spread;
1347 min_elem = min_elem_;
1348 max_elem = max_elem_;
1353 DistanceType split_val = (bbox[cutfeat].low + bbox[cutfeat].high) / 2;
1355 if (split_val < min_elem)
1357 else if (split_val > max_elem)
1363 planeSplit(obj, ind, count, cutfeat, cutval, lim1, lim2);
1365 if (lim1 > count / 2)
1367 else if (lim2 < count / 2)
1383 const Derived& obj,
const Offset ind,
const Size count,
1384 const Dimension cutfeat,
const DistanceType& cutval, Offset& lim1,
1391 Offset right = count - 1;
1394 while (left <= right &&
1395 dataset_get(obj, vAcc_[ind + left], cutfeat) < cutval)
1397 while (right && left <= right &&
1398 dataset_get(obj, vAcc_[ind + right], cutfeat) >= cutval)
1400 if (left > right || !right)
1402 std::swap(vAcc_[ind + left], vAcc_[ind + right]);
1414 while (left <= right &&
1415 dataset_get(obj, vAcc_[ind + left], cutfeat) <= cutval)
1417 while (right && left <= right &&
1418 dataset_get(obj, vAcc_[ind + right], cutfeat) > cutval)
1420 if (left > right || !right)
1422 std::swap(vAcc_[ind + left], vAcc_[ind + right]);
1429 DistanceType computeInitialDistances(
1430 const Derived& obj,
const ElementType* vec,
1431 distance_vector_t& dists)
const
1434 DistanceType dist = DistanceType();
1436 for (Dimension i = 0; i < (DIM > 0 ? DIM : obj.dim_); ++i)
1438 if (vec[i] < obj.root_bbox_[i].low)
1441 obj.distance_.accum_dist(vec[i], obj.root_bbox_[i].low, i);
1444 if (vec[i] > obj.root_bbox_[i].high)
1447 obj.distance_.accum_dist(vec[i], obj.root_bbox_[i].high, i);
1454 static void save_tree(
1455 const Derived& obj, std::ostream& stream,
const NodeConstPtr tree)
1457 save_value(stream, *tree);
1458 if (tree->child1 !=
nullptr) { save_tree(obj, stream, tree->child1); }
1459 if (tree->child2 !=
nullptr) { save_tree(obj, stream, tree->child2); }
1462 static void load_tree(Derived& obj, std::istream& stream, NodePtr& tree)
1464 tree = obj.pool_.template allocate<Node>();
1465 load_value(stream, *tree);
1466 if (tree->child1 !=
nullptr) { load_tree(obj, stream, tree->child1); }
1467 if (tree->child2 !=
nullptr) { load_tree(obj, stream, tree->child2); }
1475 void saveIndex(
const Derived& obj, std::ostream& stream)
const
1477 save_value(stream, obj.size_);
1478 save_value(stream, obj.dim_);
1479 save_value(stream, obj.root_bbox_);
1480 save_value(stream, obj.leaf_max_size_);
1481 save_value(stream, obj.vAcc_);
1482 if (obj.root_node_) save_tree(obj, stream, obj.root_node_);
1492 load_value(stream, obj.size_);
1493 load_value(stream, obj.dim_);
1494 load_value(stream, obj.root_bbox_);
1495 load_value(stream, obj.leaf_max_size_);
1496 load_value(stream, obj.vAcc_);
1497 load_tree(obj, stream, obj.root_node_);
1543 typename Distance,
class DatasetAdaptor, int32_t DIM = -1,
1544 typename index_t = uint32_t>
1547 KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM, index_t>,
1548 Distance, DatasetAdaptor, DIM, index_t>
1554 Distance, DatasetAdaptor, DIM, index_t>&) =
delete;
1565 Distance, DatasetAdaptor, DIM, index_t>,
1566 Distance, DatasetAdaptor, DIM, index_t>;
1568 using Offset =
typename Base::Offset;
1569 using Size =
typename Base::Size;
1570 using Dimension =
typename Base::Dimension;
1572 using ElementType =
typename Base::ElementType;
1573 using DistanceType =
typename Base::DistanceType;
1574 using IndexType =
typename Base::IndexType;
1576 using Node =
typename Base::Node;
1577 using NodePtr = Node*;
1579 using Interval =
typename Base::Interval;
1609 template <
class... Args>
1611 const Dimension dimensionality,
const DatasetAdaptor& inputData,
1613 : dataset_(inputData),
1614 indexParams(params),
1615 distance_(inputData, std::forward<Args>(args)...)
1617 init(dimensionality, params);
1621 const Dimension dimensionality,
const DatasetAdaptor& inputData,
1623 : dataset_(inputData), indexParams(params), distance_(inputData)
1625 init(dimensionality, params);
1630 const Dimension dimensionality,
1631 const KDTreeSingleIndexAdaptorParams& params)
1633 Base::size_ = dataset_.kdtree_get_point_count();
1634 Base::size_at_index_build_ = Base::size_;
1635 Base::dim_ = dimensionality;
1636 if (DIM > 0) Base::dim_ = DIM;
1637 Base::leaf_max_size_ = params.leaf_max_size;
1638 if (params.n_thread_build > 0)
1640 Base::n_thread_build_ = params.n_thread_build;
1644 Base::n_thread_build_ =
1645 std::max(std::thread::hardware_concurrency(), 1u);
1648 if (!(params.flags &
1649 KDTreeSingleIndexAdaptorFlags::SkipInitialBuildIndex))
1662 Base::size_ = dataset_.kdtree_get_point_count();
1663 Base::size_at_index_build_ = Base::size_;
1665 this->freeIndex(*
this);
1666 Base::size_at_index_build_ = Base::size_;
1667 if (Base::size_ == 0)
return;
1668 computeBoundingBox(Base::root_bbox_);
1670 if (Base::n_thread_build_ == 1)
1673 this->divideTree(*
this, 0, Base::size_, Base::root_bbox_);
1677#ifndef NANOFLANN_NO_THREADS
1678 std::atomic<unsigned int> thread_count(0u);
1680 Base::root_node_ = this->divideTreeConcurrent(
1681 *
this, 0, Base::size_, Base::root_bbox_, thread_count, mutex);
1683 throw std::runtime_error(
"Multithreading is disabled");
1707 template <
typename RESULTSET>
1709 RESULTSET& result,
const ElementType* vec,
1713 if (this->size(*
this) == 0)
return false;
1714 if (!Base::root_node_)
1715 throw std::runtime_error(
1716 "[nanoflann] findNeighbors() called before building the "
1718 float epsError = 1 + searchParams.eps;
1721 distance_vector_t dists;
1723 auto zero =
static_cast<typename RESULTSET::DistanceType
>(0);
1724 assign(dists, (DIM > 0 ? DIM : Base::dim_), zero);
1725 DistanceType dist = this->computeInitialDistances(*
this, vec, dists);
1726 searchLevel(result, vec, Base::root_node_, dist, dists, epsError);
1728 if (searchParams.sorted) result.sort();
1730 return result.full();
1748 template <
typename RESULTSET>
1751 if (this->size(*
this) == 0)
return 0;
1752 if (!Base::root_node_)
1753 throw std::runtime_error(
1754 "[nanoflann] findWithinBox() called before building the "
1757 std::stack<NodePtr> stack;
1758 stack.push(Base::root_node_);
1760 while (!stack.empty())
1762 const NodePtr node = stack.top();
1768 for (Offset i = node->node_type.lr.left;
1769 i < node->node_type.lr.right; ++i)
1771 if (contains(bbox, Base::vAcc_[i]))
1773 if (!result.addPoint(0, Base::vAcc_[i]))
1777 return result.size();
1784 const int idx = node->node_type.sub.divfeat;
1785 const auto low_bound = node->node_type.sub.divlow;
1786 const auto high_bound = node->node_type.sub.divhigh;
1788 if (bbox[idx].low <= low_bound) stack.push(node->child1);
1789 if (bbox[idx].high >= high_bound) stack.push(node->child2);
1793 return result.size();
1812 const ElementType* query_point,
const Size num_closest,
1813 IndexType* out_indices, DistanceType* out_distances)
const
1816 resultSet.init(out_indices, out_distances);
1817 findNeighbors(resultSet, query_point);
1818 return resultSet.size();
1841 const ElementType* query_point,
const DistanceType& radius,
1846 radius, IndicesDists);
1848 radiusSearchCustomCallback(query_point, resultSet, searchParams);
1857 template <
class SEARCH_CALLBACK>
1859 const ElementType* query_point, SEARCH_CALLBACK& resultSet,
1862 findNeighbors(resultSet, query_point, searchParams);
1863 return resultSet.size();
1883 const ElementType* query_point,
const Size num_closest,
1884 IndexType* out_indices, DistanceType* out_distances,
1885 const DistanceType& radius)
const
1888 num_closest, radius);
1889 resultSet.init(out_indices, out_distances);
1890 findNeighbors(resultSet, query_point);
1891 return resultSet.size();
1902 Base::size_ = dataset_.kdtree_get_point_count();
1903 if (Base::vAcc_.size() != Base::size_) Base::vAcc_.resize(Base::size_);
1904 for (IndexType i = 0; i < static_cast<IndexType>(Base::size_); i++)
1908 void computeBoundingBox(BoundingBox& bbox)
1910 const auto dims = (DIM > 0 ? DIM : Base::dim_);
1912 if (dataset_.kdtree_get_bbox(bbox))
1918 const Size N = dataset_.kdtree_get_point_count();
1920 throw std::runtime_error(
1921 "[nanoflann] computeBoundingBox() called but "
1922 "no data points found.");
1923 for (Dimension i = 0; i < dims; ++i)
1925 bbox[i].low = bbox[i].high =
1926 this->dataset_get(*
this, Base::vAcc_[0], i);
1928 for (Offset k = 1; k < N; ++k)
1930 for (Dimension i = 0; i < dims; ++i)
1933 this->dataset_get(*
this, Base::vAcc_[k], i);
1934 if (val < bbox[i].low) bbox[i].low = val;
1935 if (val > bbox[i].high) bbox[i].high = val;
1941 bool contains(
const BoundingBox& bbox, IndexType idx)
const
1943 const auto dims = (DIM > 0 ? DIM : Base::dim_);
1944 for (Dimension i = 0; i < dims; ++i)
1946 const auto point = this->dataset_.kdtree_get_pt(idx, i);
1947 if (point < bbox[i].low || point > bbox[i].high)
return false;
1958 template <
class RESULTSET>
1960 RESULTSET& result_set,
const ElementType* vec,
const NodePtr node,
1962 const float epsError)
const
1967 for (Offset i = node->node_type.lr.left;
1968 i < node->node_type.lr.right; ++i)
1970 const IndexType accessor = Base::vAcc_[i];
1971 DistanceType dist = distance_.evalMetric(
1972 vec, accessor, (DIM > 0 ? DIM : Base::dim_));
1973 if (dist < result_set.worstDist())
1975 if (!result_set.addPoint(dist, Base::vAcc_[i]))
1987 Dimension idx = node->node_type.sub.divfeat;
1988 ElementType val = vec[idx];
1989 DistanceType diff1 = val - node->node_type.sub.divlow;
1990 DistanceType diff2 = val - node->node_type.sub.divhigh;
1994 DistanceType cut_dist;
1995 if ((diff1 + diff2) < 0)
1997 bestChild = node->child1;
1998 otherChild = node->child2;
2000 distance_.accum_dist(val, node->node_type.sub.divhigh, idx);
2004 bestChild = node->child2;
2005 otherChild = node->child1;
2007 distance_.accum_dist(val, node->node_type.sub.divlow, idx);
2011 if (!searchLevel(result_set, vec, bestChild, mindist, dists, epsError))
2018 DistanceType dst = dists[idx];
2019 mindist = mindist + cut_dist - dst;
2020 dists[idx] = cut_dist;
2021 if (mindist * epsError <= result_set.worstDist())
2024 result_set, vec, otherChild, mindist, dists, epsError))
2043 Base::saveIndex(*
this, stream);
2051 void loadIndex(std::istream& stream) { Base::loadIndex(*
this, stream); }
2093 typename Distance,
class DatasetAdaptor, int32_t DIM = -1,
2094 typename IndexType = uint32_t>
2097 KDTreeSingleIndexDynamicAdaptor_<
2098 Distance, DatasetAdaptor, DIM, IndexType>,
2099 Distance, DatasetAdaptor, DIM, IndexType>
2109 std::vector<int>& treeIndex_;
2115 Distance, DatasetAdaptor, DIM, IndexType>,
2116 Distance, DatasetAdaptor, DIM, IndexType>;
2118 using ElementType =
typename Base::ElementType;
2119 using DistanceType =
typename Base::DistanceType;
2121 using Offset =
typename Base::Offset;
2122 using Size =
typename Base::Size;
2123 using Dimension =
typename Base::Dimension;
2125 using Node =
typename Base::Node;
2126 using NodePtr = Node*;
2128 using Interval =
typename Base::Interval;
2153 const Dimension dimensionality,
const DatasetAdaptor& inputData,
2154 std::vector<int>& treeIndex,
2157 : dataset_(inputData),
2158 index_params_(params),
2159 treeIndex_(treeIndex),
2160 distance_(inputData)
2163 Base::size_at_index_build_ = 0;
2164 for (
auto& v : Base::root_bbox_) v = {};
2165 Base::dim_ = dimensionality;
2166 if (DIM > 0) Base::dim_ = DIM;
2167 Base::leaf_max_size_ = params.leaf_max_size;
2168 if (params.n_thread_build > 0)
2170 Base::n_thread_build_ = params.n_thread_build;
2174 Base::n_thread_build_ =
2175 std::max(std::thread::hardware_concurrency(), 1u);
2188 std::swap(Base::vAcc_, tmp.Base::vAcc_);
2189 std::swap(Base::leaf_max_size_, tmp.Base::leaf_max_size_);
2190 std::swap(index_params_, tmp.index_params_);
2191 std::swap(treeIndex_, tmp.treeIndex_);
2192 std::swap(Base::size_, tmp.Base::size_);
2193 std::swap(Base::size_at_index_build_, tmp.Base::size_at_index_build_);
2194 std::swap(Base::root_node_, tmp.Base::root_node_);
2195 std::swap(Base::root_bbox_, tmp.Base::root_bbox_);
2196 std::swap(Base::pool_, tmp.Base::pool_);
2205 Base::size_ = Base::vAcc_.size();
2206 this->freeIndex(*
this);
2207 Base::size_at_index_build_ = Base::size_;
2208 if (Base::size_ == 0)
return;
2209 computeBoundingBox(Base::root_bbox_);
2211 if (Base::n_thread_build_ == 1)
2214 this->divideTree(*
this, 0, Base::size_, Base::root_bbox_);
2218#ifndef NANOFLANN_NO_THREADS
2219 std::atomic<unsigned int> thread_count(0u);
2221 Base::root_node_ = this->divideTreeConcurrent(
2222 *
this, 0, Base::size_, Base::root_bbox_, thread_count, mutex);
2224 throw std::runtime_error(
"Multithreading is disabled");
2252 template <
typename RESULTSET>
2254 RESULTSET& result,
const ElementType* vec,
2258 if (this->size(*
this) == 0)
return false;
2259 if (!Base::root_node_)
return false;
2260 float epsError = 1 + searchParams.eps;
2263 distance_vector_t dists;
2266 dists, (DIM > 0 ? DIM : Base::dim_),
2267 static_cast<typename distance_vector_t::value_type>(0));
2268 DistanceType dist = this->computeInitialDistances(*
this, vec, dists);
2269 searchLevel(result, vec, Base::root_node_, dist, dists, epsError);
2270 return result.full();
2288 const ElementType* query_point,
const Size num_closest,
2289 IndexType* out_indices, DistanceType* out_distances,
2293 resultSet.init(out_indices, out_distances);
2294 findNeighbors(resultSet, query_point, searchParams);
2295 return resultSet.size();
2318 const ElementType* query_point,
const DistanceType& radius,
2323 radius, IndicesDists);
2324 const size_t nFound =
2325 radiusSearchCustomCallback(query_point, resultSet, searchParams);
2334 template <
class SEARCH_CALLBACK>
2336 const ElementType* query_point, SEARCH_CALLBACK& resultSet,
2339 findNeighbors(resultSet, query_point, searchParams);
2340 return resultSet.size();
2346 void computeBoundingBox(BoundingBox& bbox)
2348 const auto dims = (DIM > 0 ? DIM : Base::dim_);
2351 if (dataset_.kdtree_get_bbox(bbox))
2357 const Size N = Base::size_;
2359 throw std::runtime_error(
2360 "[nanoflann] computeBoundingBox() called but "
2361 "no data points found.");
2362 for (Dimension i = 0; i < dims; ++i)
2364 bbox[i].low = bbox[i].high =
2365 this->dataset_get(*
this, Base::vAcc_[0], i);
2367 for (Offset k = 1; k < N; ++k)
2369 for (Dimension i = 0; i < dims; ++i)
2372 this->dataset_get(*
this, Base::vAcc_[k], i);
2373 if (val < bbox[i].low) bbox[i].low = val;
2374 if (val > bbox[i].high) bbox[i].high = val;
2384 template <
class RESULTSET>
2386 RESULTSET& result_set,
const ElementType* vec,
const NodePtr node,
2388 const float epsError)
const
2393 for (Offset i = node->node_type.lr.left;
2394 i < node->node_type.lr.right; ++i)
2396 const IndexType index = Base::vAcc_[i];
2397 if (treeIndex_[index] == -1)
continue;
2398 DistanceType dist = distance_.evalMetric(
2399 vec, index, (DIM > 0 ? DIM : Base::dim_));
2400 if (dist < result_set.worstDist())
2402 if (!result_set.addPoint(
2403 static_cast<typename RESULTSET::DistanceType
>(dist),
2404 static_cast<typename RESULTSET::IndexType
>(
2417 Dimension idx = node->node_type.sub.divfeat;
2418 ElementType val = vec[idx];
2419 DistanceType diff1 = val - node->node_type.sub.divlow;
2420 DistanceType diff2 = val - node->node_type.sub.divhigh;
2424 DistanceType cut_dist;
2425 if ((diff1 + diff2) < 0)
2427 bestChild = node->child1;
2428 otherChild = node->child2;
2430 distance_.accum_dist(val, node->node_type.sub.divhigh, idx);
2434 bestChild = node->child2;
2435 otherChild = node->child1;
2437 distance_.accum_dist(val, node->node_type.sub.divlow, idx);
2441 searchLevel(result_set, vec, bestChild, mindist, dists, epsError);
2443 DistanceType dst = dists[idx];
2444 mindist = mindist + cut_dist - dst;
2445 dists[idx] = cut_dist;
2446 if (mindist * epsError <= result_set.worstDist())
2448 searchLevel(result_set, vec, otherChild, mindist, dists, epsError);
2484 typename Distance,
class DatasetAdaptor, int32_t DIM = -1,
2485 typename IndexType = uint32_t>
2489 using ElementType =
typename Distance::ElementType;
2490 using DistanceType =
typename Distance::DistanceType;
2493 Distance, DatasetAdaptor, DIM>::Offset;
2495 Distance, DatasetAdaptor, DIM>::Size;
2497 Distance, DatasetAdaptor, DIM>::Dimension;
2500 Size leaf_max_size_;
2512 std::unordered_set<int> removedPoints_;
2519 Distance, DatasetAdaptor, DIM, IndexType>;
2520 std::vector<index_container_t> index_;
2532 int First0Bit(IndexType num)
2546 using my_kd_tree_t = KDTreeSingleIndexDynamicAdaptor_<
2547 Distance, DatasetAdaptor, DIM, IndexType>;
2548 std::vector<my_kd_tree_t> index(
2550 my_kd_tree_t(dim_ , dataset_, treeIndex_, index_params_));
2573 const int dimensionality,
const DatasetAdaptor& inputData,
2576 const size_t maximumPointCount = 1000000000U)
2577 : dataset_(inputData), index_params_(params), distance_(inputData)
2579 treeCount_ =
static_cast<size_t>(std::log2(maximumPointCount)) + 1;
2581 dim_ = dimensionality;
2583 if (DIM > 0) dim_ = DIM;
2584 leaf_max_size_ = params.leaf_max_size;
2586 const size_t num_initial_points = dataset_.kdtree_get_point_count();
2587 if (num_initial_points > 0) { addPoints(0, num_initial_points - 1); }
2593 Distance, DatasetAdaptor, DIM, IndexType>&) =
delete;
2598 const Size count = end - start + 1;
2600 treeIndex_.resize(treeIndex_.size() + count);
2601 for (IndexType idx = start; idx <= end; idx++)
2603 const int pos = First0Bit(pointCount_);
2604 maxIndex = std::max(pos, maxIndex);
2605 treeIndex_[pointCount_] = pos;
2607 const auto it = removedPoints_.find(idx);
2608 if (it != removedPoints_.end())
2610 removedPoints_.erase(it);
2611 treeIndex_[idx] = pos;
2614 for (
int i = 0; i < pos; i++)
2616 for (
int j = 0; j < static_cast<int>(index_[i].vAcc_.size());
2619 index_[pos].vAcc_.push_back(index_[i].vAcc_[j]);
2620 if (treeIndex_[index_[i].vAcc_[j]] != -1)
2621 treeIndex_[index_[i].vAcc_[j]] = pos;
2623 index_[i].vAcc_.clear();
2625 index_[pos].vAcc_.push_back(idx);
2629 for (
int i = 0; i <= maxIndex; ++i)
2631 index_[i].freeIndex(index_[i]);
2632 if (!index_[i].vAcc_.empty()) index_[i].buildIndex();
2639 if (idx >= pointCount_)
return;
2640 removedPoints_.insert(idx);
2641 treeIndex_[idx] = -1;
2660 template <
typename RESULTSET>
2662 RESULTSET& result,
const ElementType* vec,
2665 for (
size_t i = 0; i < treeCount_; i++)
2667 index_[i].findNeighbors(result, &vec[0], searchParams);
2669 return result.full();
2700 bool row_major =
true>
2705 using num_t =
typename MatrixType::Scalar;
2706 using IndexType =
typename MatrixType::Index;
2707 using metric_t =
typename Distance::template traits<
2708 num_t,
self_t, IndexType>::distance_t;
2712 row_major ? MatrixType::ColsAtCompileTime
2713 : MatrixType::RowsAtCompileTime,
2720 using Size =
typename index_t::Size;
2721 using Dimension =
typename index_t::Dimension;
2725 const Dimension dimensionality,
2726 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 "
2742 leaf_max_size, nanoflann::KDTreeSingleIndexAdaptorFlags::None,
2752 const std::reference_wrapper<const MatrixType> m_data_matrix;
2763 const num_t* query_point,
const Size num_closest,
2764 IndexType* out_indices, num_t* out_distances)
const
2767 resultSet.init(out_indices, out_distances);
2774 const self_t& derived()
const {
return *
this; }
2775 self_t& derived() {
return *
this; }
2778 Size kdtree_get_point_count()
const
2781 return m_data_matrix.get().rows();
2783 return m_data_matrix.get().cols();
2787 num_t kdtree_get_pt(
const IndexType idx,
size_t dim)
const
2790 return m_data_matrix.get().coeff(idx, IndexType(dim));
2792 return m_data_matrix.get().coeff(IndexType(dim), idx);
2800 template <
class BBOX>
2801 bool kdtree_get_bbox(BBOX& )
const
// end of grouping
Definition nanoflann.hpp:1009
void freeIndex(Derived &obj)
Definition nanoflann.hpp:1013
Size veclen(const Derived &obj) const
Definition nanoflann.hpp:1102
void computeMinMax(const Derived &obj, Offset ind, Size count, Dimension element, ElementType &min_elem, ElementType &max_elem) const
Definition nanoflann.hpp:1125
BoundingBox root_bbox_
Definition nanoflann.hpp:1087
void saveIndex(const Derived &obj, std::ostream &stream) const
Definition nanoflann.hpp:1475
typename array_or_vector< DIM, DistanceType >::type distance_vector_t
Definition nanoflann.hpp:1084
void planeSplit(const Derived &obj, const Offset ind, const Size count, const Dimension cutfeat, const DistanceType &cutval, Offset &lim1, Offset &lim2)
Definition nanoflann.hpp:1382
NodePtr divideTree(Derived &obj, const Offset left, const Offset right, BoundingBox &bbox)
Definition nanoflann.hpp:1148
std::vector< IndexType > vAcc_
Definition nanoflann.hpp:1027
Size size(const Derived &obj) const
Definition nanoflann.hpp:1099
NodePtr divideTreeConcurrent(Derived &obj, const Offset left, const Offset right, BoundingBox &bbox, std::atomic< unsigned int > &thread_count, std::mutex &mutex)
Definition nanoflann.hpp:1224
Size usedMemory(const Derived &obj) const
Definition nanoflann.hpp:1115
void loadIndex(Derived &obj, std::istream &stream)
Definition nanoflann.hpp:1490
PooledAllocator pool_
Definition nanoflann.hpp:1096
ElementType dataset_get(const Derived &obj, IndexType element, Dimension component) const
Helper accessor to the dataset points:
Definition nanoflann.hpp:1105
typename array_or_vector< DIM, Interval >::type BoundingBox
Definition nanoflann.hpp:1080
Definition nanoflann.hpp:1549
bool searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindist, distance_vector_t &dists, const float epsError) const
Definition nanoflann.hpp:1959
void saveIndex(std::ostream &stream) const
Definition nanoflann.hpp:2041
Size findWithinBox(RESULTSET &result, const BoundingBox &bbox) const
Definition nanoflann.hpp:1749
Size radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< ResultItem< IndexType, DistanceType > > &IndicesDists, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1840
void init_vind()
Definition nanoflann.hpp:1899
void buildIndex()
Definition nanoflann.hpp:1660
const DatasetAdaptor & dataset_
Definition nanoflann.hpp:1557
KDTreeSingleIndexAdaptor(const KDTreeSingleIndexAdaptor< Distance, DatasetAdaptor, DIM, index_t > &)=delete
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1708
Size rknnSearch(const ElementType *query_point, const Size num_closest, IndexType *out_indices, DistanceType *out_distances, const DistanceType &radius) const
Definition nanoflann.hpp:1882
Size radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1858
typename Base::distance_vector_t distance_vector_t
Definition nanoflann.hpp:1587
void loadIndex(std::istream &stream)
Definition nanoflann.hpp:2051
typename Base::BoundingBox BoundingBox
Definition nanoflann.hpp:1583
KDTreeSingleIndexAdaptor(const Dimension dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams ¶ms, Args &&... args)
Definition nanoflann.hpp:1610
Size knnSearch(const ElementType *query_point, const Size num_closest, IndexType *out_indices, DistanceType *out_distances) const
Definition nanoflann.hpp:1811
Definition nanoflann.hpp:2100
Size radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< ResultItem< IndexType, DistanceType > > &IndicesDists, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2317
KDTreeSingleIndexDynamicAdaptor_(const Dimension dimensionality, const DatasetAdaptor &inputData, std::vector< int > &treeIndex, const KDTreeSingleIndexAdaptorParams ¶ms=KDTreeSingleIndexAdaptorParams())
Definition nanoflann.hpp:2152
typename Base::BoundingBox BoundingBox
Definition nanoflann.hpp:2131
const DatasetAdaptor & dataset_
The source of our data.
Definition nanoflann.hpp:2105
Size radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2335
KDTreeSingleIndexDynamicAdaptor_(const KDTreeSingleIndexDynamicAdaptor_ &rhs)=default
void buildIndex()
Definition nanoflann.hpp:2203
void saveIndex(std::ostream &stream)
Definition nanoflann.hpp:2459
typename Base::distance_vector_t distance_vector_t
Definition nanoflann.hpp:2135
void loadIndex(std::istream &stream)
Definition nanoflann.hpp:2466
Size knnSearch(const ElementType *query_point, const Size num_closest, IndexType *out_indices, DistanceType *out_distances, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2287
void searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindist, distance_vector_t &dists, const float epsError) const
Definition nanoflann.hpp:2385
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2253
KDTreeSingleIndexDynamicAdaptor_ operator=(const KDTreeSingleIndexDynamicAdaptor_ &rhs)
Definition nanoflann.hpp:2184
Definition nanoflann.hpp:2487
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2661
const DatasetAdaptor & dataset_
The source of our data.
Definition nanoflann.hpp:2507
void removePoint(size_t idx)
Definition nanoflann.hpp:2637
void addPoints(IndexType start, IndexType end)
Definition nanoflann.hpp:2596
KDTreeSingleIndexDynamicAdaptor(const int dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams ¶ms=KDTreeSingleIndexAdaptorParams(), const size_t maximumPointCount=1000000000U)
Definition nanoflann.hpp:2572
std::vector< int > treeIndex_
Definition nanoflann.hpp:2511
const std::vector< index_container_t > & getAllIndices() const
Definition nanoflann.hpp:2525
Dimension dim_
Dimensionality of each data point.
Definition nanoflann.hpp:2516
KDTreeSingleIndexDynamicAdaptor(const KDTreeSingleIndexDynamicAdaptor< Distance, DatasetAdaptor, DIM, IndexType > &)=delete
Definition nanoflann.hpp:201
bool addPoint(DistanceType dist, IndexType index)
Definition nanoflann.hpp:235
DistanceType worstDist() const
Definition nanoflann.hpp:272
Definition nanoflann.hpp:861
~PooledAllocator()
Definition nanoflann.hpp:897
void free_all()
Definition nanoflann.hpp:900
void * malloc(const size_t req_size)
Definition nanoflann.hpp:916
T * allocate(const size_t count=1)
Definition nanoflann.hpp:963
PooledAllocator()
Definition nanoflann.hpp:892
Definition nanoflann.hpp:290
bool addPoint(DistanceType dist, IndexType index)
Definition nanoflann.hpp:331
DistanceType worstDist() const
Definition nanoflann.hpp:368
Definition nanoflann.hpp:385
ResultItem< IndexType, DistanceType > worst_item() const
Definition nanoflann.hpp:428
bool addPoint(DistanceType dist, IndexType index)
Definition nanoflann.hpp:416
std::enable_if< has_assign< Container >::value, void >::type assign(Container &c, const size_t nElements, const T &value)
Definition nanoflann.hpp:145
T pi_const()
Definition nanoflann.hpp:88
std::enable_if< has_resize< Container >::value, void >::type resize(Container &c, const size_t nElements)
Definition nanoflann.hpp:123
Definition nanoflann.hpp:163
bool operator()(const PairType &p1, const PairType &p2) const
Definition nanoflann.hpp:166
Definition nanoflann.hpp:1062
Definition nanoflann.hpp:1037
DistanceType divlow
The values used for subdivision.
Definition nanoflann.hpp:1050
Offset right
Indices of points in leaf node.
Definition nanoflann.hpp:1044
union nanoflann::KDTreeBaseClass::Node::@0 node_type
Dimension divfeat
Definition nanoflann.hpp:1048
Node * child1
Definition nanoflann.hpp:1055
Definition nanoflann.hpp:2702
void query(const num_t *query_point, const Size num_closest, IndexType *out_indices, num_t *out_distances) const
Definition nanoflann.hpp:2762
KDTreeEigenMatrixAdaptor(const self_t &)=delete
typename index_t::Offset Offset
Definition nanoflann.hpp:2719
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:2724
Definition nanoflann.hpp:812
Definition nanoflann.hpp:501
Definition nanoflann.hpp:563
Definition nanoflann.hpp:628
Definition nanoflann.hpp:484
Definition nanoflann.hpp:182
DistanceType second
Distance from sample to query point.
Definition nanoflann.hpp:190
IndexType first
Index of the sample in the dataset.
Definition nanoflann.hpp:189
Definition nanoflann.hpp:673
DistanceType accum_dist(const U a, const V b, const size_t) const
Definition nanoflann.hpp:691
Definition nanoflann.hpp:718
Definition nanoflann.hpp:831
bool sorted
distance (default: true)
Definition nanoflann.hpp:838
float eps
search for eps-approximate neighbours (default: 0)
Definition nanoflann.hpp:837
Definition nanoflann.hpp:979
Definition nanoflann.hpp:110
Definition nanoflann.hpp:99
Definition nanoflann.hpp:748
Definition nanoflann.hpp:745
Definition nanoflann.hpp:758
Definition nanoflann.hpp:768
Definition nanoflann.hpp:765
Definition nanoflann.hpp:755
Definition nanoflann.hpp:777
Definition nanoflann.hpp:774
Definition nanoflann.hpp:786
Definition nanoflann.hpp:783