Krotos Modules 3
Loading...
Searching...
No Matches
nanoflann.hpp
Go to the documentation of this file.
1/***********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
5 * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
6 * Copyright 2011-2022 Jose Luis Blanco (joseluisblancoc@gmail.com).
7 * All rights reserved.
8 *
9 * THE BSD LICENSE
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *************************************************************************/
32
45#pragma once
46
47#include <algorithm>
48#include <array>
49#include <cassert>
50#include <cmath> // for abs()
51#include <cstdlib> // for abs()
52#include <functional> // std::reference_wrapper
53#include <istream>
54#include <limits> // std::numeric_limits
55#include <ostream>
56#include <stdexcept>
57#include <unordered_set>
58#include <vector>
59
61#define NANOFLANN_VERSION 0x150
62
63// Avoid conflicting declaration of min/max macros in Windows headers
64#if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
65#define NOMINMAX
66#ifdef max
67#undef max
68#undef min
69#endif
70#endif
71// Avoid conflicts with X11 headers
72#ifdef None
73#undef None
74#endif
75
76namespace nanoflann
77{
82template <typename T> T pi_const() { return static_cast<T>(3.14159265358979323846); }
83
88template <typename T, typename = int> struct has_resize : std::false_type
89{
90};
91
92template <typename T> struct has_resize<T, decltype((void)std::declval<T>().resize(1), 0)> : std::true_type
93{
94};
95
96template <typename T, typename = int> struct has_assign : std::false_type
97{
98};
99
100template <typename T> struct has_assign<T, decltype((void)std::declval<T>().assign(1, 0), 0)> : std::true_type
101{
102};
103
107template <typename Container>
108inline typename std::enable_if<has_resize<Container>::value, void>::type resize(Container& c, const size_t nElements)
109{
110 c.resize(nElements);
111}
112
117template <typename Container>
118inline typename std::enable_if<!has_resize<Container>::value, void>::type resize(Container& c, const size_t nElements)
119{
120 if (nElements != c.size())
121 throw std::logic_error("Try to change the size of a std::array.");
122}
123
127template <typename Container, typename T>
128inline typename std::enable_if<has_assign<Container>::value, void>::type assign(Container& c, const size_t nElements,
129 const T& value)
130{
131 c.assign(nElements, value);
132}
133
137template <typename Container, typename T>
138inline typename std::enable_if<!has_assign<Container>::value, void>::type assign(Container& c, const size_t nElements,
139 const T& value)
140{
141 for (size_t i = 0; i < nElements; i++)
142 c[i] = value;
143}
144
147template <typename _DistanceType, typename _IndexType = size_t, typename _CountType = size_t> class KNNResultSet
148{
149 public:
150 using DistanceType = _DistanceType;
151 using IndexType = _IndexType;
152 using CountType = _CountType;
153
154 private:
159
160 public:
161 explicit KNNResultSet(CountType capacity_) : indices(nullptr), dists(nullptr), capacity(capacity_), count(0) {}
162
163 void init(IndexType* indices_, DistanceType* dists_)
164 {
165 indices = indices_;
166 dists = dists_;
167 count = 0;
168 if (capacity)
169 dists[capacity - 1] = (std::numeric_limits<DistanceType>::max)();
170 }
171
172 CountType size() const { return count; }
173
174 bool full() const { return count == capacity; }
175
182 {
183 CountType i;
184 for (i = count; i > 0; --i)
185 {
188#ifdef NANOFLANN_FIRST_MATCH
189 if ((dists[i - 1] > dist) || ((dist == dists[i - 1]) && (indices[i - 1] > index)))
190 {
191#else
192 if (dists[i - 1] > dist)
193 {
194#endif
195 if (i < capacity)
196 {
197 dists[i] = dists[i - 1];
198 indices[i] = indices[i - 1];
199 }
200 }
201 else
202 break;
203 }
204 if (i < capacity)
205 {
206 dists[i] = dist;
207 indices[i] = index;
208 }
209 if (count < capacity)
210 count++;
211
212 // tell caller that the search shall continue
213 return true;
214 }
215
216 DistanceType worstDist() const { return dists[capacity - 1]; }
217};
218
221{
223 template <typename PairType> bool operator()(const PairType& p1, const PairType& p2) const
224 {
225 return p1.second < p2.second;
226 }
227};
228
237template <typename IndexType = size_t, typename DistanceType = double> struct ResultItem
238{
239 ResultItem() = default;
240 ResultItem(const IndexType index, const DistanceType distance) : first(index), second(distance) {}
241
242 IndexType first;
243 DistanceType second;
244};
245
249template <typename _DistanceType, typename _IndexType = size_t> class RadiusResultSet
250{
251 public:
252 using DistanceType = _DistanceType;
253 using IndexType = _IndexType;
254
255 public:
257
258 std::vector<ResultItem<IndexType, DistanceType>>& m_indices_dists;
259
260 explicit RadiusResultSet(DistanceType radius_, std::vector<ResultItem<IndexType, DistanceType>>& indices_dists)
261 : radius(radius_), m_indices_dists(indices_dists)
262 {
263 init();
264 }
265
266 void init() { clear(); }
267 void clear() { m_indices_dists.clear(); }
268
269 size_t size() const { return m_indices_dists.size(); }
270 size_t empty() const { return m_indices_dists.empty(); }
271
272 bool full() const { return true; }
273
280 {
281 if (dist < radius)
282 m_indices_dists.emplace_back(index, dist);
283 return true;
284 }
285
286 DistanceType worstDist() const { return radius; }
287
293 {
294 if (m_indices_dists.empty())
295 throw std::runtime_error("Cannot invoke RadiusResultSet::worst_item() on "
296 "an empty list of results.");
297 auto it = std::max_element(m_indices_dists.begin(), m_indices_dists.end(), IndexDist_Sorter());
298 return *it;
299 }
300};
301
306template <typename T> void save_value(std::ostream& stream, const T& value)
307{
308 stream.write(reinterpret_cast<const char*>(&value), sizeof(T));
309}
310
311template <typename T> void save_value(std::ostream& stream, const std::vector<T>& value)
312{
313 size_t size = value.size();
314 stream.write(reinterpret_cast<const char*>(&size), sizeof(size_t));
315 stream.write(reinterpret_cast<const char*>(value.data()), sizeof(T) * size);
316}
317
318template <typename T> void load_value(std::istream& stream, T& value)
319{
320 stream.read(reinterpret_cast<char*>(&value), sizeof(T));
321}
322
323template <typename T> void load_value(std::istream& stream, std::vector<T>& value)
324{
325 size_t size;
326 stream.read(reinterpret_cast<char*>(&size), sizeof(size_t));
327 value.resize(size);
328 stream.read(reinterpret_cast<char*>(value.data()), sizeof(T) * size);
329}
335struct Metric
336{
337};
338
349template <class T, class DataSource, typename _DistanceType = T, typename IndexType = uint32_t> struct L1_Adaptor
350{
351 using ElementType = T;
352 using DistanceType = _DistanceType;
353
354 const DataSource& data_source;
355
356 L1_Adaptor(const DataSource& _data_source) : data_source(_data_source) {}
357
358 DistanceType evalMetric(const T* a, const IndexType b_idx, size_t size, DistanceType worst_dist = -1) const
359 {
360 DistanceType result = DistanceType();
361 const T* last = a + size;
362 const T* lastgroup = last - 3;
363 size_t d = 0;
364
365 /* Process 4 items with each loop for efficiency. */
366 while (a < lastgroup)
367 {
368 const DistanceType diff0 = std::abs(a[0] - data_source.kdtree_get_pt(b_idx, d++));
369 const DistanceType diff1 = std::abs(a[1] - data_source.kdtree_get_pt(b_idx, d++));
370 const DistanceType diff2 = std::abs(a[2] - data_source.kdtree_get_pt(b_idx, d++));
371 const DistanceType diff3 = std::abs(a[3] - data_source.kdtree_get_pt(b_idx, d++));
372 result += diff0 + diff1 + diff2 + diff3;
373 a += 4;
374 if ((worst_dist > 0) && (result > worst_dist))
375 {
376 return result;
377 }
378 }
379 /* Process last 0-3 components. Not needed for standard vector lengths.
380 */
381 while (a < last)
382 {
383 result += std::abs(*a++ - data_source.kdtree_get_pt(b_idx, d++));
384 }
385 return result;
386 }
387
388 template <typename U, typename V> DistanceType accum_dist(const U a, const V b, const size_t) const
389 {
390 return std::abs(a - b);
391 }
392};
393
404template <class T, class DataSource, typename _DistanceType = T, typename IndexType = uint32_t> struct L2_Adaptor
405{
406 using ElementType = T;
407 using DistanceType = _DistanceType;
408
409 const DataSource& data_source;
410
411 L2_Adaptor(const DataSource& _data_source) : data_source(_data_source) {}
412
413 DistanceType evalMetric(const T* a, const IndexType b_idx, size_t size, DistanceType worst_dist = -1) const
414 {
415 DistanceType result = DistanceType();
416 const T* last = a + size;
417 const T* lastgroup = last - 3;
418 size_t d = 0;
419
420 /* Process 4 items with each loop for efficiency. */
421 while (a < lastgroup)
422 {
423 const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx, d++);
424 const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx, d++);
425 const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx, d++);
426 const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx, d++);
427 result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
428 a += 4;
429 if ((worst_dist > 0) && (result > worst_dist))
430 {
431 return result;
432 }
433 }
434 /* Process last 0-3 components. Not needed for standard vector lengths.
435 */
436 while (a < last)
437 {
438 const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx, d++);
439 result += diff0 * diff0;
440 }
441 return result;
442 }
443
444 template <typename U, typename V> DistanceType accum_dist(const U a, const V b, const size_t) const
445 {
446 return (a - b) * (a - b);
447 }
448};
449
460template <class T, class DataSource, typename _DistanceType = T, typename IndexType = uint32_t> struct L2_Simple_Adaptor
461{
462 using ElementType = T;
463 using DistanceType = _DistanceType;
464
465 const DataSource& data_source;
466
467 L2_Simple_Adaptor(const DataSource& _data_source) : data_source(_data_source) {}
468
469 DistanceType evalMetric(const T* a, const IndexType b_idx, size_t size) const
470 {
471 DistanceType result = DistanceType();
472 for (size_t i = 0; i < size; ++i)
473 {
474 const DistanceType diff = a[i] - data_source.kdtree_get_pt(b_idx, i);
475 result += diff * diff;
476 }
477 return result;
478 }
479
480 template <typename U, typename V> DistanceType accum_dist(const U a, const V b, const size_t) const
481 {
482 return (a - b) * (a - b);
483 }
484};
485
496template <class T, class DataSource, typename _DistanceType = T, typename IndexType = uint32_t> struct SO2_Adaptor
497{
498 using ElementType = T;
499 using DistanceType = _DistanceType;
500
501 const DataSource& data_source;
502
503 SO2_Adaptor(const DataSource& _data_source) : data_source(_data_source) {}
504
505 DistanceType evalMetric(const T* a, const IndexType b_idx, size_t size) const
506 {
507 return accum_dist(a[size - 1], data_source.kdtree_get_pt(b_idx, size - 1), size - 1);
508 }
509
512 template <typename U, typename V> DistanceType accum_dist(const U a, const V b, const size_t) const
513 {
514 DistanceType result = DistanceType();
515 DistanceType PI = pi_const<DistanceType>();
516 result = b - a;
517 if (result > PI)
518 result -= 2 * PI;
519 else if (result < -PI)
520 result += 2 * PI;
521 return result;
522 }
523};
524
535template <class T, class DataSource, typename _DistanceType = T, typename IndexType = uint32_t> struct SO3_Adaptor
536{
537 using ElementType = T;
538 using DistanceType = _DistanceType;
539
541
542 SO3_Adaptor(const DataSource& _data_source) : distance_L2_Simple(_data_source) {}
543
544 DistanceType evalMetric(const T* a, const IndexType b_idx, size_t size) const
545 {
546 return distance_L2_Simple.evalMetric(a, b_idx, size);
547 }
548
549 template <typename U, typename V> DistanceType accum_dist(const U a, const V b, const size_t idx) const
550 {
551 return distance_L2_Simple.accum_dist(a, b, idx);
552 }
553};
554
556struct metric_L1 : public Metric
557{
558 template <class T, class DataSource, typename IndexType = uint32_t> struct traits
559 {
561 };
562};
565struct metric_L2 : public Metric
566{
567 template <class T, class DataSource, typename IndexType = uint32_t> struct traits
568 {
570 };
571};
575{
576 template <class T, class DataSource, typename IndexType = uint32_t> struct traits
577 {
579 };
580};
582struct metric_SO2 : public Metric
583{
584 template <class T, class DataSource, typename IndexType = uint32_t> struct traits
585 {
587 };
588};
590struct metric_SO3 : public Metric
591{
592 template <class T, class DataSource, typename IndexType = uint32_t> struct traits
593 {
595 };
596};
597
604{
605 None = 0,
607};
608
609inline std::underlying_type<KDTreeSingleIndexAdaptorFlags>::type operator&(KDTreeSingleIndexAdaptorFlags lhs,
611{
612 using underlying = typename std::underlying_type<KDTreeSingleIndexAdaptorFlags>::type;
613 return static_cast<underlying>(lhs) & static_cast<underlying>(rhs);
614}
615
618{
619 KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size = 10,
620 KDTreeSingleIndexAdaptorFlags _flags = KDTreeSingleIndexAdaptorFlags::None)
621 : leaf_max_size(_leaf_max_size), flags(_flags)
622 {
623 }
624
627};
628
631{
632 SearchParameters(float eps_ = 0, bool sorted_ = true) : eps(eps_), sorted(sorted_) {}
633
634 float eps;
635 bool sorted;
637};
658{
659 static constexpr size_t WORDSIZE = 16;
660 static constexpr size_t BLOCKSIZE = 8192;
661
662 /* We maintain memory alignment to word boundaries by requiring that all
663 allocations be in multiples of the machine wordsize. */
664 /* Size of machine word in bytes. Must be power of 2. */
665 /* Minimum number of bytes requested at a time from the system. Must be
666 * multiple of WORDSIZE. */
667
668 using Offset = uint32_t;
669 using Size = uint32_t;
670 using Dimension = int32_t;
671
672 Size remaining_ = 0;
673 void* base_ = nullptr;
674 void* loc_ = nullptr;
675
677 {
678 remaining_ = 0;
679 base_ = nullptr;
680 usedMemory = 0;
681 wastedMemory = 0;
682 }
683
684 public:
685 Size usedMemory = 0;
686 Size wastedMemory = 0;
687
691 PooledAllocator() { internal_init(); }
692
696 ~PooledAllocator() { free_all(); }
697
699 void free_all()
700 {
701 while (base_ != nullptr)
702 {
703 // Get pointer to prev block
704 void* prev = *(static_cast<void**>(base_));
705 ::free(base_);
706 base_ = prev;
707 }
708 internal_init();
709 }
710
715 void* malloc(const size_t req_size)
716 {
717 /* Round size up to a multiple of wordsize. The following expression
718 only works for WORDSIZE that is a power of 2, by masking last bits
719 of incremented size to zero.
720 */
721 const Size size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1);
722
723 /* Check whether a new block must be allocated. Note that the first
724 word of a block is reserved for a pointer to the previous block.
725 */
726 if (size > remaining_)
727 {
728 wastedMemory += remaining_;
729
730 /* Allocate new storage. */
731 const Size blocksize = (size + sizeof(void*) + (WORDSIZE - 1) > BLOCKSIZE)
732 ? size + sizeof(void*) + (WORDSIZE - 1)
733 : BLOCKSIZE;
734
735 // use the standard C malloc to allocate memory
736 void* m = ::malloc(blocksize);
737 if (!m)
738 {
739 fprintf(stderr, "Failed to allocate memory.\n");
740 throw std::bad_alloc();
741 }
742
743 /* Fill first word of new block with pointer to previous block. */
744 static_cast<void**>(m)[0] = base_;
745 base_ = m;
746
747 Size shift = 0;
748 // int size_t = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) &
749 // (WORDSIZE-1))) & (WORDSIZE-1);
750
751 remaining_ = blocksize - sizeof(void*) - shift;
752 loc_ = (static_cast<char*>(m) + sizeof(void*) + shift);
753 }
754 void* rloc = loc_;
755 loc_ = static_cast<char*>(loc_) + size;
756 remaining_ -= size;
757
758 usedMemory += size;
759
760 return rloc;
761 }
762
770 template <typename T> T* allocate(const size_t count = 1)
771 {
772 T* mem = static_cast<T*>(this->malloc(sizeof(T) * count));
773 return mem;
774 }
775};
784template <int32_t DIM, typename T> struct array_or_vector
785{
786 using type = std::array<T, DIM>;
787};
789template <typename T> struct array_or_vector<-1, T>
790{
791 using type = std::vector<T>;
792};
793
810template <class Derived, typename Distance, class DatasetAdaptor, int32_t DIM = -1, typename IndexType = uint32_t>
812{
813 public:
816 void freeIndex(Derived& obj)
817 {
818 obj.pool_.free_all();
819 obj.root_node_ = nullptr;
820 obj.size_at_index_build_ = 0;
821 }
822
823 using ElementType = typename Distance::ElementType;
824 using DistanceType = typename Distance::DistanceType;
825
829 std::vector<IndexType> vAcc_;
830
831 using Offset = typename decltype(vAcc_)::size_type;
832 using Size = typename decltype(vAcc_)::size_type;
833 using Dimension = int32_t;
834
835 /*---------------------------
836 * Internal Data Structures
837 * --------------------------*/
838 struct Node
839 {
842 union {
843 struct leaf
844 {
845 Offset left, right;
846 } lr;
847 struct nonleaf
848 {
852 } sub;
853 } node_type;
854
856 Node *child1 = nullptr, *child2 = nullptr;
857 };
858
859 using NodePtr = Node*;
860 using NodeConstPtr = const Node*;
861
862 struct Interval
863 {
865 };
866
867 NodePtr root_node_ = nullptr;
868
869 Size leaf_max_size_ = 0;
870
872 Size size_ = 0;
874 Size size_at_index_build_ = 0;
875 Dimension dim_ = 0;
876
880
884
887
896
898 Size size(const Derived& obj) const { return obj.size_; }
899
901 Size veclen(const Derived& obj) { return DIM > 0 ? DIM : obj.dim; }
902
904 ElementType dataset_get(const Derived& obj, IndexType element, Dimension component) const
905 {
906 return obj.dataset_.kdtree_get_pt(element, component);
907 }
908
913 Size usedMemory(Derived& obj)
914 {
915 return obj.pool_.usedMemory + obj.pool_.wastedMemory +
916 obj.dataset_.kdtree_get_point_count() * sizeof(IndexType); // pool memory and vind array memory
917 }
918
919 void computeMinMax(const Derived& obj, Offset ind, Size count, Dimension element, ElementType& min_elem,
920 ElementType& max_elem)
921 {
922 min_elem = dataset_get(obj, vAcc_[ind], element);
923 max_elem = min_elem;
924 for (Offset i = 1; i < count; ++i)
925 {
926 ElementType val = dataset_get(obj, vAcc_[ind + i], element);
927 if (val < min_elem)
928 min_elem = val;
929 if (val > max_elem)
930 max_elem = val;
931 }
932 }
933
941 NodePtr divideTree(Derived& obj, const Offset left, const Offset right, BoundingBox& bbox)
942 {
943 NodePtr node = obj.pool_.template allocate<Node>(); // allocate memory
944 const auto dims = (DIM > 0 ? DIM : obj.dim_);
945
946 /* If too few exemplars remain, then make this a leaf node. */
947 if ((right - left) <= static_cast<Offset>(obj.leaf_max_size_))
948 {
949 node->child1 = node->child2 = nullptr; /* Mark as leaf node. */
950 node->node_type.lr.left = left;
951 node->node_type.lr.right = right;
952
953 // compute bounding-box of leaf points
954 for (Dimension i = 0; i < dims; ++i)
955 {
956 bbox[i].low = dataset_get(obj, obj.vAcc_[left], i);
957 bbox[i].high = dataset_get(obj, obj.vAcc_[left], i);
958 }
959 for (Offset k = left + 1; k < right; ++k)
960 {
961 for (Dimension i = 0; i < dims; ++i)
962 {
963 const auto val = dataset_get(obj, obj.vAcc_[k], i);
964 if (bbox[i].low > val)
965 bbox[i].low = val;
966 if (bbox[i].high < val)
967 bbox[i].high = val;
968 }
969 }
970 }
971 else
972 {
973 Offset idx;
974 Dimension cutfeat;
975 DistanceType cutval;
976 middleSplit_(obj, left, right - left, idx, cutfeat, cutval, bbox);
977
978 node->node_type.sub.divfeat = cutfeat;
979
980 BoundingBox left_bbox(bbox);
981 left_bbox[cutfeat].high = cutval;
982 node->child1 = this->divideTree(obj, left, left + idx, left_bbox);
983
984 BoundingBox right_bbox(bbox);
985 right_bbox[cutfeat].low = cutval;
986 node->child2 = this->divideTree(obj, left + idx, right, right_bbox);
987
988 node->node_type.sub.divlow = left_bbox[cutfeat].high;
989 node->node_type.sub.divhigh = right_bbox[cutfeat].low;
990
991 for (Dimension i = 0; i < dims; ++i)
992 {
993 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
994 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
995 }
996 }
997
998 return node;
999 }
1000
1001 void middleSplit_(const Derived& obj, const Offset ind, const Size count, Offset& index, Dimension& cutfeat,
1002 DistanceType& cutval, const BoundingBox& bbox)
1003 {
1004 const auto dims = (DIM > 0 ? DIM : obj.dim_);
1005 const auto EPS = static_cast<DistanceType>(0.00001);
1006 ElementType max_span = bbox[0].high - bbox[0].low;
1007 for (Dimension i = 1; i < dims; ++i)
1008 {
1009 ElementType span = bbox[i].high - bbox[i].low;
1010 if (span > max_span)
1011 {
1012 max_span = span;
1013 }
1014 }
1015 ElementType max_spread = -1;
1016 cutfeat = 0;
1017 for (Dimension i = 0; i < dims; ++i)
1018 {
1019 ElementType span = bbox[i].high - bbox[i].low;
1020 if (span > (1 - EPS) * max_span)
1021 {
1022 ElementType min_elem, max_elem;
1023 computeMinMax(obj, ind, count, i, min_elem, max_elem);
1024 ElementType spread = max_elem - min_elem;
1025 if (spread > max_spread)
1026 {
1027 cutfeat = i;
1028 max_spread = spread;
1029 }
1030 }
1031 }
1032 // split in the middle
1033 DistanceType split_val = (bbox[cutfeat].low + bbox[cutfeat].high) / 2;
1034 ElementType min_elem, max_elem;
1035 computeMinMax(obj, ind, count, cutfeat, min_elem, max_elem);
1036
1037 if (split_val < min_elem)
1038 cutval = min_elem;
1039 else if (split_val > max_elem)
1040 cutval = max_elem;
1041 else
1042 cutval = split_val;
1043
1044 Offset lim1, lim2;
1045 planeSplit(obj, ind, count, cutfeat, cutval, lim1, lim2);
1046
1047 if (lim1 > count / 2)
1048 index = lim1;
1049 else if (lim2 < count / 2)
1050 index = lim2;
1051 else
1052 index = count / 2;
1053 }
1054
1064 void planeSplit(const Derived& obj, const Offset ind, const Size count, const Dimension cutfeat,
1065 const DistanceType& cutval, Offset& lim1, Offset& lim2)
1066 {
1067 /* Move vector indices for left subtree to front of list. */
1068 Offset left = 0;
1069 Offset right = count - 1;
1070 for (;;)
1071 {
1072 while (left <= right && dataset_get(obj, vAcc_[ind + left], cutfeat) < cutval)
1073 ++left;
1074 while (right && left <= right && dataset_get(obj, vAcc_[ind + right], cutfeat) >= cutval)
1075 --right;
1076 if (left > right || !right)
1077 break; // "!right" was added to support unsigned Index types
1078 std::swap(vAcc_[ind + left], vAcc_[ind + right]);
1079 ++left;
1080 --right;
1081 }
1082 /* If either list is empty, it means that all remaining features
1083 * are identical. Split in the middle to maintain a balanced tree.
1084 */
1085 lim1 = left;
1086 right = count - 1;
1087 for (;;)
1088 {
1089 while (left <= right && dataset_get(obj, vAcc_[ind + left], cutfeat) <= cutval)
1090 ++left;
1091 while (right && left <= right && dataset_get(obj, vAcc_[ind + right], cutfeat) > cutval)
1092 --right;
1093 if (left > right || !right)
1094 break; // "!right" was added to support unsigned Index types
1095 std::swap(vAcc_[ind + left], vAcc_[ind + right]);
1096 ++left;
1097 --right;
1098 }
1099 lim2 = left;
1100 }
1101
1102 DistanceType computeInitialDistances(const Derived& obj, const ElementType* vec, distance_vector_t& dists) const
1103 {
1104 assert(vec);
1105 DistanceType dist = DistanceType();
1106
1107 for (Dimension i = 0; i < (DIM > 0 ? DIM : obj.dim_); ++i)
1108 {
1109 if (vec[i] < obj.root_bbox_[i].low)
1110 {
1111 dists[i] = obj.distance_.accum_dist(vec[i], obj.root_bbox_[i].low, i);
1112 dist += dists[i];
1113 }
1114 if (vec[i] > obj.root_bbox_[i].high)
1115 {
1116 dists[i] = obj.distance_.accum_dist(vec[i], obj.root_bbox_[i].high, i);
1117 dist += dists[i];
1118 }
1119 }
1120 return dist;
1121 }
1122
1123 static void save_tree(const Derived& obj, std::ostream& stream, const NodeConstPtr tree)
1124 {
1125 save_value(stream, *tree);
1126 if (tree->child1 != nullptr)
1127 {
1128 save_tree(obj, stream, tree->child1);
1129 }
1130 if (tree->child2 != nullptr)
1131 {
1132 save_tree(obj, stream, tree->child2);
1133 }
1134 }
1135
1136 static void load_tree(Derived& obj, std::istream& stream, NodePtr& tree)
1137 {
1138 tree = obj.pool_.template allocate<Node>();
1139 load_value(stream, *tree);
1140 if (tree->child1 != nullptr)
1141 {
1142 load_tree(obj, stream, tree->child1);
1143 }
1144 if (tree->child2 != nullptr)
1145 {
1146 load_tree(obj, stream, tree->child2);
1147 }
1148 }
1149
1155 void saveIndex(const Derived& obj, std::ostream& stream) const
1156 {
1157 save_value(stream, obj.size_);
1158 save_value(stream, obj.dim_);
1159 save_value(stream, obj.root_bbox_);
1160 save_value(stream, obj.leaf_max_size_);
1161 save_value(stream, obj.vAcc_);
1162 save_tree(obj, stream, obj.root_node_);
1163 }
1164
1170 void loadIndex(Derived& obj, std::istream& stream)
1171 {
1172 load_value(stream, obj.size_);
1173 load_value(stream, obj.dim_);
1174 load_value(stream, obj.root_bbox_);
1175 load_value(stream, obj.leaf_max_size_);
1176 load_value(stream, obj.vAcc_);
1177 load_tree(obj, stream, obj.root_node_);
1178 }
1179};
1180
1222template <typename Distance, class DatasetAdaptor, int32_t DIM = -1, typename IndexType = uint32_t>
1224 : public KDTreeBaseClass<KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM, IndexType>, Distance,
1225 DatasetAdaptor, DIM, IndexType>
1226{
1227 public:
1230 delete;
1231
1233 const DatasetAdaptor& dataset_;
1234
1236
1237 Distance distance_;
1238
1241 DIM, IndexType>;
1242
1243 using Offset = typename Base::Offset;
1244 using Size = typename Base::Size;
1245 using Dimension = typename Base::Dimension;
1246
1247 using ElementType = typename Base::ElementType;
1248 using DistanceType = typename Base::DistanceType;
1249
1250 using Node = typename Base::Node;
1251 using NodePtr = Node*;
1252
1253 using Interval = typename Base::Interval;
1254
1257 using BoundingBox = typename Base::BoundingBox;
1258
1261 using distance_vector_t = typename Base::distance_vector_t;
1262
1283 template <class... Args>
1284 explicit KDTreeSingleIndexAdaptor(const Dimension dimensionality, const DatasetAdaptor& inputData,
1285 const KDTreeSingleIndexAdaptorParams& params, Args&&... args)
1286 : dataset_(inputData), indexParams(params), distance_(inputData, std::forward<Args>(args)...)
1287 {
1288 init(dimensionality, params);
1289 }
1290
1291 explicit KDTreeSingleIndexAdaptor(const Dimension dimensionality, const DatasetAdaptor& inputData,
1292 const KDTreeSingleIndexAdaptorParams& params = {})
1293 : dataset_(inputData), indexParams(params), distance_(inputData)
1294 {
1295 init(dimensionality, params);
1296 }
1297
1298 private:
1299 void init(const Dimension dimensionality, const KDTreeSingleIndexAdaptorParams& params)
1300 {
1301 Base::size_ = dataset_.kdtree_get_point_count();
1302 Base::size_at_index_build_ = Base::size_;
1303 Base::dim_ = dimensionality;
1304 if (DIM > 0)
1305 Base::dim_ = DIM;
1306 Base::leaf_max_size_ = params.leaf_max_size;
1307
1308 if (!(params.flags & KDTreeSingleIndexAdaptorFlags::SkipInitialBuildIndex))
1309 {
1310 // Build KD-tree:
1311 buildIndex();
1312 }
1313 }
1314
1315 public:
1320 {
1321 Base::size_ = dataset_.kdtree_get_point_count();
1322 Base::size_at_index_build_ = Base::size_;
1323 init_vind();
1324 this->freeIndex(*this);
1325 Base::size_at_index_build_ = Base::size_;
1326 if (Base::size_ == 0)
1327 return;
1328 computeBoundingBox(Base::root_bbox_);
1329 // construct the tree
1330 Base::root_node_ = this->divideTree(*this, 0, Base::size_, Base::root_bbox_);
1331 }
1332
1352 template <typename RESULTSET>
1353 bool findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParameters& searchParams = {}) const
1354 {
1355 assert(vec);
1356 if (this->size(*this) == 0)
1357 return false;
1358 if (!Base::root_node_)
1359 throw std::runtime_error("[nanoflann] findNeighbors() called before building the "
1360 "index.");
1361 float epsError = 1 + searchParams.eps;
1362
1363 // fixed or variable-sized container (depending on DIM)
1364 distance_vector_t dists;
1365 // Fill it with zeros.
1366 auto zero = static_cast<decltype(result.worstDist())>(0);
1367 assign(dists, (DIM > 0 ? DIM : Base::dim_), zero);
1368 DistanceType dist = this->computeInitialDistances(*this, vec, dists);
1369 searchLevel(result, vec, Base::root_node_, dist, dists, epsError);
1370 return result.full();
1371 }
1372
1388 Size knnSearch(const ElementType* query_point, const Size num_closest, IndexType* out_indices,
1389 DistanceType* out_distances) const
1390 {
1392 resultSet.init(out_indices, out_distances);
1393 findNeighbors(resultSet, query_point);
1394 return resultSet.size();
1395 }
1396
1416 Size radiusSearch(const ElementType* query_point, const DistanceType& radius,
1417 std::vector<ResultItem<IndexType, DistanceType>>& IndicesDists,
1418 const SearchParameters& searchParams = {}) const
1419 {
1420 RadiusResultSet<DistanceType, IndexType> resultSet(radius, IndicesDists);
1421 const Size nFound = radiusSearchCustomCallback(query_point, resultSet, searchParams);
1422 if (searchParams.sorted)
1423 std::sort(IndicesDists.begin(), IndicesDists.end(), IndexDist_Sorter());
1424 return nFound;
1425 }
1426
1432 template <class SEARCH_CALLBACK>
1433 Size radiusSearchCustomCallback(const ElementType* query_point, SEARCH_CALLBACK& resultSet,
1434 const SearchParameters& searchParams = {}) const
1435 {
1436 findNeighbors(resultSet, query_point, searchParams);
1437 return resultSet.size();
1438 }
1439
1442 public:
1446 {
1447 // Create a permutable array of indices to the input vectors.
1448 Base::size_ = dataset_.kdtree_get_point_count();
1449 if (Base::vAcc_.size() != Base::size_)
1450 Base::vAcc_.resize(Base::size_);
1451 for (Size i = 0; i < Base::size_; i++)
1452 Base::vAcc_[i] = i;
1453 }
1454
1456 {
1457 const auto dims = (DIM > 0 ? DIM : Base::dim_);
1458 resize(bbox, dims);
1459 if (dataset_.kdtree_get_bbox(bbox))
1460 {
1461 // Done! It was implemented in derived class
1462 }
1463 else
1464 {
1465 const Size N = dataset_.kdtree_get_point_count();
1466 if (!N)
1467 throw std::runtime_error("[nanoflann] computeBoundingBox() called but "
1468 "no data points found.");
1469 for (Dimension i = 0; i < dims; ++i)
1470 {
1471 bbox[i].low = bbox[i].high = this->dataset_get(*this, Base::vAcc_[0], i);
1472 }
1473 for (Offset k = 1; k < N; ++k)
1474 {
1475 for (Dimension i = 0; i < dims; ++i)
1476 {
1477 const auto val = this->dataset_get(*this, Base::vAcc_[k], i);
1478 if (val < bbox[i].low)
1479 bbox[i].low = val;
1480 if (val > bbox[i].high)
1481 bbox[i].high = val;
1482 }
1483 }
1484 }
1485 }
1486
1493 template <class RESULTSET>
1494 bool searchLevel(RESULTSET& result_set, const ElementType* vec, const NodePtr node, DistanceType mindist,
1495 distance_vector_t& dists, const float epsError) const
1496 {
1497 /* If this is a leaf node, then do check and return. */
1498 if ((node->child1 == nullptr) && (node->child2 == nullptr))
1499 {
1500 DistanceType worst_dist = result_set.worstDist();
1501 for (Offset i = node->node_type.lr.left; i < node->node_type.lr.right; ++i)
1502 {
1503 const IndexType accessor = Base::vAcc_[i]; // reorder... : i;
1504 DistanceType dist = distance_.evalMetric(vec, accessor, (DIM > 0 ? DIM : Base::dim_));
1505 if (dist < worst_dist)
1506 {
1507 if (!result_set.addPoint(dist, Base::vAcc_[i]))
1508 {
1509 // the resultset doesn't want to receive any more
1510 // points, we're done searching!
1511 return false;
1512 }
1513 }
1514 }
1515 return true;
1516 }
1517
1518 /* Which child branch should be taken first? */
1519 Dimension idx = node->node_type.sub.divfeat;
1520 ElementType val = vec[idx];
1521 DistanceType diff1 = val - node->node_type.sub.divlow;
1522 DistanceType diff2 = val - node->node_type.sub.divhigh;
1523
1524 NodePtr bestChild;
1525 NodePtr otherChild;
1526 DistanceType cut_dist;
1527 if ((diff1 + diff2) < 0)
1528 {
1529 bestChild = node->child1;
1530 otherChild = node->child2;
1531 cut_dist = distance_.accum_dist(val, node->node_type.sub.divhigh, idx);
1532 }
1533 else
1534 {
1535 bestChild = node->child2;
1536 otherChild = node->child1;
1537 cut_dist = distance_.accum_dist(val, node->node_type.sub.divlow, idx);
1538 }
1539
1540 /* Call recursively to search next level down. */
1541 if (!searchLevel(result_set, vec, bestChild, mindist, dists, epsError))
1542 {
1543 // the resultset doesn't want to receive any more points, we're done
1544 // searching!
1545 return false;
1546 }
1547
1548 DistanceType dst = dists[idx];
1549 mindist = mindist + cut_dist - dst;
1550 dists[idx] = cut_dist;
1551 if (mindist * epsError <= result_set.worstDist())
1552 {
1553 if (!searchLevel(result_set, vec, otherChild, mindist, dists, epsError))
1554 {
1555 // the resultset doesn't want to receive any more points, we're
1556 // done searching!
1557 return false;
1558 }
1559 }
1560 dists[idx] = dst;
1561 return true;
1562 }
1563
1564 public:
1570 void saveIndex(std::ostream& stream) const { Base::saveIndex(*this, stream); }
1571
1577 void loadIndex(std::istream& stream) { Base::loadIndex(*this, stream); }
1578
1579}; // class KDTree
1580
1618template <typename Distance, class DatasetAdaptor, int32_t DIM = -1, typename IndexType = uint32_t>
1620 : public KDTreeBaseClass<KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM, IndexType>, Distance,
1621 DatasetAdaptor, DIM, IndexType>
1622{
1623 public:
1627 const DatasetAdaptor& dataset_;
1628
1630
1631 std::vector<int>& treeIndex_;
1632
1633 Distance distance_;
1634
1637 DatasetAdaptor, DIM, IndexType>;
1638
1639 using ElementType = typename Base::ElementType;
1640 using DistanceType = typename Base::DistanceType;
1641
1642 using Offset = typename Base::Offset;
1643 using Size = typename Base::Size;
1644 using Dimension = typename Base::Dimension;
1645
1646 using Node = typename Base::Node;
1647 using NodePtr = Node*;
1648
1649 using Interval = typename Base::Interval;
1652 using BoundingBox = typename Base::BoundingBox;
1653
1656 using distance_vector_t = typename Base::distance_vector_t;
1657
1673 KDTreeSingleIndexDynamicAdaptor_(const Dimension dimensionality, const DatasetAdaptor& inputData,
1674 std::vector<int>& treeIndex,
1676 : dataset_(inputData), index_params_(params), treeIndex_(treeIndex), distance_(inputData)
1677 {
1678 Base::size_ = 0;
1679 Base::size_at_index_build_ = 0;
1680 for (auto& v : Base::root_bbox_)
1681 v = {};
1682 Base::dim_ = dimensionality;
1683 if (DIM > 0)
1684 Base::dim_ = DIM;
1685 Base::leaf_max_size_ = params.leaf_max_size;
1686 }
1687
1690
1693 {
1695 std::swap(Base::vAcc_, tmp.Base::vAcc_);
1696 std::swap(Base::leaf_max_size_, tmp.Base::leaf_max_size_);
1697 std::swap(index_params_, tmp.index_params_);
1698 std::swap(treeIndex_, tmp.treeIndex_);
1699 std::swap(Base::size_, tmp.Base::size_);
1700 std::swap(Base::size_at_index_build_, tmp.Base::size_at_index_build_);
1701 std::swap(Base::root_node_, tmp.Base::root_node_);
1702 std::swap(Base::root_bbox_, tmp.Base::root_bbox_);
1703 std::swap(Base::pool_, tmp.Base::pool_);
1704 return *this;
1705 }
1706
1711 {
1712 Base::size_ = Base::vAcc_.size();
1713 this->freeIndex(*this);
1714 Base::size_at_index_build_ = Base::size_;
1715 if (Base::size_ == 0)
1716 return;
1717 computeBoundingBox(Base::root_bbox_);
1718 // construct the tree
1719 Base::root_node_ = this->divideTree(*this, 0, Base::size_, Base::root_bbox_);
1720 }
1721
1745 template <typename RESULTSET>
1746 bool findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParameters& searchParams = {}) const
1747 {
1748 assert(vec);
1749 if (this->size(*this) == 0)
1750 return false;
1751 if (!Base::root_node_)
1752 return false;
1753 float epsError = 1 + searchParams.eps;
1754
1755 // fixed or variable-sized container (depending on DIM)
1756 distance_vector_t dists;
1757 // Fill it with zeros.
1758 assign(dists, (DIM > 0 ? DIM : Base::dim_), static_cast<typename distance_vector_t::value_type>(0));
1759 DistanceType dist = this->computeInitialDistances(*this, vec, dists);
1760 searchLevel(result, vec, Base::root_node_, dist, dists, epsError);
1761 return result.full();
1762 }
1763
1778 Size knnSearch(const ElementType* query_point, const Size num_closest, IndexType* out_indices,
1779 DistanceType* out_distances) const
1780 {
1782 resultSet.init(out_indices, out_distances);
1783 findNeighbors(resultSet, query_point);
1784 return resultSet.size();
1785 }
1786
1806 Size radiusSearch(const ElementType* query_point, const DistanceType& radius,
1807 std::vector<ResultItem<IndexType, DistanceType>>& IndicesDists,
1808 const SearchParameters& searchParams = {}) const
1809 {
1810 RadiusResultSet<DistanceType, IndexType> resultSet(radius, IndicesDists);
1811 const size_t nFound = radiusSearchCustomCallback(query_point, resultSet, searchParams);
1812 if (searchParams.sorted)
1813 std::sort(IndicesDists.begin(), IndicesDists.end(), IndexDist_Sorter());
1814 return nFound;
1815 }
1816
1822 template <class SEARCH_CALLBACK>
1823 Size radiusSearchCustomCallback(const ElementType* query_point, SEARCH_CALLBACK& resultSet,
1824 const SearchParameters& searchParams = {}) const
1825 {
1826 findNeighbors(resultSet, query_point, searchParams);
1827 return resultSet.size();
1828 }
1829
1832 public:
1834 {
1835 const auto dims = (DIM > 0 ? DIM : Base::dim_);
1836 resize(bbox, dims);
1837
1838 if (dataset_.kdtree_get_bbox(bbox))
1839 {
1840 // Done! It was implemented in derived class
1841 }
1842 else
1843 {
1844 const Size N = Base::size_;
1845 if (!N)
1846 throw std::runtime_error("[nanoflann] computeBoundingBox() called but "
1847 "no data points found.");
1848 for (Dimension i = 0; i < dims; ++i)
1849 {
1850 bbox[i].low = bbox[i].high = this->dataset_get(*this, Base::vAcc_[0], i);
1851 }
1852 for (Offset k = 1; k < N; ++k)
1853 {
1854 for (Dimension i = 0; i < dims; ++i)
1855 {
1856 const auto val = this->dataset_get(*this, Base::vAcc_[k], i);
1857 if (val < bbox[i].low)
1858 bbox[i].low = val;
1859 if (val > bbox[i].high)
1860 bbox[i].high = val;
1861 }
1862 }
1863 }
1864 }
1865
1870 template <class RESULTSET>
1871 void searchLevel(RESULTSET& result_set, const ElementType* vec, const NodePtr node, DistanceType mindist,
1872 distance_vector_t& dists, const float epsError) const
1873 {
1874 /* If this is a leaf node, then do check and return. */
1875 if ((node->child1 == nullptr) && (node->child2 == nullptr))
1876 {
1877 DistanceType worst_dist = result_set.worstDist();
1878 for (Offset i = node->node_type.lr.left; i < node->node_type.lr.right; ++i)
1879 {
1880 const IndexType index = Base::vAcc_[i]; // reorder... : i;
1881 if (treeIndex_[index] == -1)
1882 continue;
1883 DistanceType dist = distance_.evalMetric(vec, index, (DIM > 0 ? DIM : Base::dim_));
1884 if (dist < worst_dist)
1885 {
1886 if (!result_set.addPoint(static_cast<typename RESULTSET::DistanceType>(dist),
1887 static_cast<typename RESULTSET::IndexType>(Base::vAcc_[i])))
1888 {
1889 // the resultset doesn't want to receive any more
1890 // points, we're done searching!
1891 return; // false;
1892 }
1893 }
1894 }
1895 return;
1896 }
1897
1898 /* Which child branch should be taken first? */
1899 Dimension idx = node->node_type.sub.divfeat;
1900 ElementType val = vec[idx];
1901 DistanceType diff1 = val - node->node_type.sub.divlow;
1902 DistanceType diff2 = val - node->node_type.sub.divhigh;
1903
1904 NodePtr bestChild;
1905 NodePtr otherChild;
1906 DistanceType cut_dist;
1907 if ((diff1 + diff2) < 0)
1908 {
1909 bestChild = node->child1;
1910 otherChild = node->child2;
1911 cut_dist = distance_.accum_dist(val, node->node_type.sub.divhigh, idx);
1912 }
1913 else
1914 {
1915 bestChild = node->child2;
1916 otherChild = node->child1;
1917 cut_dist = distance_.accum_dist(val, node->node_type.sub.divlow, idx);
1918 }
1919
1920 /* Call recursively to search next level down. */
1921 searchLevel(result_set, vec, bestChild, mindist, dists, epsError);
1922
1923 DistanceType dst = dists[idx];
1924 mindist = mindist + cut_dist - dst;
1925 dists[idx] = cut_dist;
1926 if (mindist * epsError <= result_set.worstDist())
1927 {
1928 searchLevel(result_set, vec, otherChild, mindist, dists, epsError);
1929 }
1930 dists[idx] = dst;
1931 }
1932
1933 public:
1939 void saveIndex(std::ostream& stream) { saveIndex(*this, stream); }
1940
1946 void loadIndex(std::istream& stream) { loadIndex(*this, stream); }
1947};
1948
1963template <typename Distance, class DatasetAdaptor, int32_t DIM = -1, typename IndexType = uint32_t>
1965{
1966 public:
1967 using ElementType = typename Distance::ElementType;
1968 using DistanceType = typename Distance::DistanceType;
1969
1973
1974 protected:
1978
1982 const DatasetAdaptor& dataset_;
1983
1986 std::vector<int> treeIndex_;
1987 std::unordered_set<int> removedPoints_;
1988
1990
1992
1994 std::vector<index_container_t> index_;
1995
1996 public:
1999 const std::vector<index_container_t>& getAllIndices() const { return index_; }
2000
2001 private:
2003 int First0Bit(IndexType num)
2004 {
2005 int pos = 0;
2006 while (num & 1)
2007 {
2008 num = num >> 1;
2009 pos++;
2010 }
2011 return pos;
2012 }
2013
2015 void init()
2016 {
2018 std::vector<my_kd_tree_t> index(treeCount_, my_kd_tree_t(dim_ /*dim*/, dataset_, treeIndex_, index_params_));
2019 index_ = index;
2020 }
2021
2022 public:
2023 Distance distance_;
2024
2041 const int dimensionality, const DatasetAdaptor& inputData,
2043 const size_t maximumPointCount = 1000000000U)
2044 : dataset_(inputData), index_params_(params), distance_(inputData)
2045 {
2046 treeCount_ = static_cast<size_t>(std::log2(maximumPointCount)) + 1;
2047 pointCount_ = 0U;
2048 dim_ = dimensionality;
2049 treeIndex_.clear();
2050 if (DIM > 0)
2051 dim_ = DIM;
2052 leaf_max_size_ = params.leaf_max_size;
2053 init();
2054 const size_t num_initial_points = dataset_.kdtree_get_point_count();
2055 if (num_initial_points > 0)
2056 {
2057 addPoints(0, num_initial_points - 1);
2058 }
2059 }
2060
2064
2066 void addPoints(IndexType start, IndexType end)
2067 {
2068 const Size count = end - start + 1;
2069 int maxIndex = 0;
2070 treeIndex_.resize(treeIndex_.size() + count);
2071 for (IndexType idx = start; idx <= end; idx++)
2072 {
2073 const int pos = First0Bit(pointCount_);
2074 maxIndex = std::max(pos, maxIndex);
2075 treeIndex_[pointCount_] = pos;
2076
2077 const auto it = removedPoints_.find(idx);
2078 if (it != removedPoints_.end())
2079 {
2080 removedPoints_.erase(it);
2081 treeIndex_[idx] = pos;
2082 }
2083
2084 for (int i = 0; i < pos; i++)
2085 {
2086 for (int j = 0; j < static_cast<int>(index_[i].vAcc_.size()); j++)
2087 {
2088 index_[pos].vAcc_.push_back(index_[i].vAcc_[j]);
2089 if (treeIndex_[index_[i].vAcc_[j]] != -1)
2090 treeIndex_[index_[i].vAcc_[j]] = pos;
2091 }
2092 index_[i].vAcc_.clear();
2093 }
2094 index_[pos].vAcc_.push_back(idx);
2095 pointCount_++;
2096 }
2097
2098 for (int i = 0; i <= maxIndex; ++i)
2099 {
2100 index_[i].freeIndex(index_[i]);
2101 if (!index_[i].vAcc_.empty())
2102 index_[i].buildIndex();
2103 }
2104 }
2105
2107 void removePoint(size_t idx)
2108 {
2109 if (idx >= pointCount_)
2110 return;
2111 removedPoints_.insert(idx);
2112 treeIndex_[idx] = -1;
2113 }
2114
2131 template <typename RESULTSET>
2132 bool findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParameters& searchParams = {}) const
2133 {
2134 for (size_t i = 0; i < treeCount_; i++)
2135 {
2136 index_[i].findNeighbors(result, &vec[0], searchParams);
2137 }
2138 return result.full();
2139 }
2140};
2141
2167template <class MatrixType, int32_t DIM = -1, class Distance = nanoflann::metric_L2, bool row_major = true>
2169{
2171 using num_t = typename MatrixType::Scalar;
2172 using IndexType = typename MatrixType::Index;
2173 using metric_t = typename Distance::template traits<num_t, self_t, IndexType>::distance_t;
2174
2176 metric_t, self_t, row_major ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime, IndexType>;
2177
2180
2181 using Offset = typename index_t::Offset;
2182 using Size = typename index_t::Size;
2184
2186 explicit KDTreeEigenMatrixAdaptor(const Dimension dimensionality,
2187 const std::reference_wrapper<const MatrixType>& mat, const int leaf_max_size = 10)
2188 : m_data_matrix(mat)
2189 {
2190 const auto dims = row_major ? mat.get().cols() : mat.get().rows();
2191 if (static_cast<Dimension>(dims) != dimensionality)
2192 throw std::runtime_error("Error: 'dimensionality' must match column count in data "
2193 "matrix");
2194 if (DIM > 0 && static_cast<int32_t>(dims) != DIM)
2195 throw std::runtime_error("Data set dimensionality does not match the 'DIM' template "
2196 "argument");
2197 index_ = new index_t(dims, *this /* adaptor */, nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size));
2198 }
2199
2200 public:
2203
2204 ~KDTreeEigenMatrixAdaptor() { delete index_; }
2205
2206 const std::reference_wrapper<const MatrixType> m_data_matrix;
2207
2216 void query(const num_t* query_point, const Size num_closest, IndexType* out_indices, num_t* out_distances) const
2217 {
2218 nanoflann::KNNResultSet<num_t, IndexType> resultSet(num_closest);
2219 resultSet.init(out_indices, out_distances);
2220 index_->findNeighbors(resultSet, query_point);
2221 }
2222
2226 const self_t& derived() const { return *this; }
2227 self_t& derived() { return *this; }
2228
2229 // Must return the number of data points
2231 {
2232 if (row_major)
2233 return m_data_matrix.get().rows();
2234 else
2235 return m_data_matrix.get().cols();
2236 }
2237
2238 // Returns the dim'th component of the idx'th point in the class:
2239 num_t kdtree_get_pt(const IndexType idx, size_t dim) const
2240 {
2241 if (row_major)
2242 return m_data_matrix.get().coeff(idx, IndexType(dim));
2243 else
2244 return m_data_matrix.get().coeff(IndexType(dim), idx);
2245 }
2246
2247 // Optional bounding-box computation: return false to default to a standard
2248 // bbox computation loop.
2249 // Return true if the BBOX was already computed by the class and returned
2250 // in "bb" so it can be avoided to redo it again. Look at bb.size() to
2251 // find out the expected dimensionality (e.g. 2 or 3 for point clouds)
2252 template <class BBOX> bool kdtree_get_bbox(BBOX& /*bb*/) const { return false; }
2253
2256}; // end of KDTreeEigenMatrixAdaptor
2259 // end of grouping
2260} // namespace nanoflann
Definition nanoflann.hpp:812
Size usedMemory(Derived &obj)
Definition nanoflann.hpp:913
DistanceType computeInitialDistances(const Derived &obj, const ElementType *vec, distance_vector_t &dists) const
Definition nanoflann.hpp:1102
void planeSplit(const Derived &obj, const Offset ind, const Size count, const Dimension cutfeat, const DistanceType &cutval, Offset &lim1, Offset &lim2)
Definition nanoflann.hpp:1064
typename array_or_vector< DIM, DistanceType >::type distance_vector_t
Definition nanoflann.hpp:883
std::vector< IndexType > vAcc_
Definition nanoflann.hpp:829
void computeMinMax(const Derived &obj, Offset ind, Size count, Dimension element, ElementType &min_elem, ElementType &max_elem)
Definition nanoflann.hpp:919
static void load_tree(Derived &obj, std::istream &stream, NodePtr &tree)
Definition nanoflann.hpp:1136
Size size(const Derived &obj) const
Definition nanoflann.hpp:898
void freeIndex(Derived &obj)
Definition nanoflann.hpp:816
void loadIndex(Derived &obj, std::istream &stream)
Definition nanoflann.hpp:1170
typename array_or_vector< DIM, Interval >::type BoundingBox
Definition nanoflann.hpp:879
BoundingBox root_bbox_
Definition nanoflann.hpp:886
typename decltype(vAcc_)::size_type Size
Definition nanoflann.hpp:832
void saveIndex(const Derived &obj, std::ostream &stream) const
Definition nanoflann.hpp:1155
void middleSplit_(const Derived &obj, const Offset ind, const Size count, Offset &index, Dimension &cutfeat, DistanceType &cutval, const BoundingBox &bbox)
Definition nanoflann.hpp:1001
typename Distance::ElementType ElementType
Definition nanoflann.hpp:823
PooledAllocator pool_
Definition nanoflann.hpp:895
NodePtr divideTree(Derived &obj, const Offset left, const Offset right, BoundingBox &bbox)
Definition nanoflann.hpp:941
typename Distance::DistanceType DistanceType
Definition nanoflann.hpp:824
ElementType dataset_get(const Derived &obj, IndexType element, Dimension component) const
Helper accessor to the dataset points:
Definition nanoflann.hpp:904
Size veclen(const Derived &obj)
Definition nanoflann.hpp:901
static void save_tree(const Derived &obj, std::ostream &stream, const NodeConstPtr tree)
Definition nanoflann.hpp:1123
int32_t Dimension
Definition nanoflann.hpp:833
typename decltype(vAcc_)::size_type Offset
Definition nanoflann.hpp:831
Definition nanoflann.hpp:1226
const KDTreeSingleIndexAdaptorParams indexParams
Definition nanoflann.hpp:1235
Size radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1433
KDTreeSingleIndexAdaptor(const KDTreeSingleIndexAdaptor< Distance, DatasetAdaptor, DIM, IndexType > &)=delete
KDTreeSingleIndexAdaptor(const Dimension dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams &params, Args &&... args)
Definition nanoflann.hpp:1284
Distance distance_
Definition nanoflann.hpp:1237
typename Base::Size Size
Definition nanoflann.hpp:1244
typename Base::ElementType ElementType
Definition nanoflann.hpp:1247
typename nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexAdaptor< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType > Base
Definition nanoflann.hpp:1239
Size radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< ResultItem< IndexType, DistanceType > > &IndicesDists, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1416
typename Base::distance_vector_t distance_vector_t
Definition nanoflann.hpp:1261
void loadIndex(std::istream &stream)
Definition nanoflann.hpp:1577
typename Base::Node Node
Definition nanoflann.hpp:1250
typename Base::BoundingBox BoundingBox
Definition nanoflann.hpp:1257
typename Base::DistanceType DistanceType
Definition nanoflann.hpp:1248
KDTreeSingleIndexAdaptor(const Dimension dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams &params={})
Definition nanoflann.hpp:1291
typename Base::Interval Interval
Definition nanoflann.hpp:1253
Size knnSearch(const ElementType *query_point, const Size num_closest, IndexType *out_indices, DistanceType *out_distances) const
Definition nanoflann.hpp:1388
typename Base::Dimension Dimension
Definition nanoflann.hpp:1245
void init(const Dimension dimensionality, const KDTreeSingleIndexAdaptorParams &params)
Definition nanoflann.hpp:1299
void init_vind()
Definition nanoflann.hpp:1445
const DatasetAdaptor & dataset_
Definition nanoflann.hpp:1233
void saveIndex(std::ostream &stream) const
Definition nanoflann.hpp:1570
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1353
Node * NodePtr
Definition nanoflann.hpp:1251
typename Base::Offset Offset
Definition nanoflann.hpp:1243
void buildIndex()
Definition nanoflann.hpp:1319
bool searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindist, distance_vector_t &dists, const float epsError) const
Definition nanoflann.hpp:1494
void computeBoundingBox(BoundingBox &bbox)
Definition nanoflann.hpp:1455
Definition nanoflann.hpp:1622
Size radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< ResultItem< IndexType, DistanceType > > &IndicesDists, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1806
KDTreeSingleIndexDynamicAdaptor_(const Dimension dimensionality, const DatasetAdaptor &inputData, std::vector< int > &treeIndex, const KDTreeSingleIndexAdaptorParams &params=KDTreeSingleIndexAdaptorParams())
Definition nanoflann.hpp:1673
std::vector< int > & treeIndex_
Definition nanoflann.hpp:1631
typename Base::Dimension Dimension
Definition nanoflann.hpp:1644
typename Base::BoundingBox BoundingBox
Definition nanoflann.hpp:1652
const DatasetAdaptor & dataset_
The source of our data.
Definition nanoflann.hpp:1627
Size radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1823
typename Base::DistanceType DistanceType
Definition nanoflann.hpp:1640
KDTreeSingleIndexAdaptorParams index_params_
Definition nanoflann.hpp:1629
KDTreeSingleIndexDynamicAdaptor_(const KDTreeSingleIndexDynamicAdaptor_ &rhs)=default
typename Base::Offset Offset
Definition nanoflann.hpp:1642
void buildIndex()
Definition nanoflann.hpp:1710
typename Base::ElementType ElementType
Definition nanoflann.hpp:1639
void saveIndex(std::ostream &stream)
Definition nanoflann.hpp:1939
void computeBoundingBox(BoundingBox &bbox)
Definition nanoflann.hpp:1833
typename Base::Node Node
Definition nanoflann.hpp:1646
typename Base::Size Size
Definition nanoflann.hpp:1643
Node * NodePtr
Definition nanoflann.hpp:1647
typename Base::distance_vector_t distance_vector_t
Definition nanoflann.hpp:1656
void loadIndex(std::istream &stream)
Definition nanoflann.hpp:1946
typename Base::Interval Interval
Definition nanoflann.hpp:1649
typename nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType > Base
Definition nanoflann.hpp:1635
Size knnSearch(const ElementType *query_point, const Size num_closest, IndexType *out_indices, DistanceType *out_distances) const
Definition nanoflann.hpp:1778
void searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindist, distance_vector_t &dists, const float epsError) const
Definition nanoflann.hpp:1871
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1746
Distance distance_
Definition nanoflann.hpp:1633
KDTreeSingleIndexDynamicAdaptor_ operator=(const KDTreeSingleIndexDynamicAdaptor_ &rhs)
Definition nanoflann.hpp:1692
Definition nanoflann.hpp:1965
typename KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM >::Dimension Dimension
Definition nanoflann.hpp:1972
void init()
Definition nanoflann.hpp:2015
int First0Bit(IndexType num)
Definition nanoflann.hpp:2003
typename Distance::ElementType ElementType
Definition nanoflann.hpp:1967
Size treeCount_
Definition nanoflann.hpp:1976
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2132
typename Distance::DistanceType DistanceType
Definition nanoflann.hpp:1968
Size leaf_max_size_
Definition nanoflann.hpp:1975
Distance distance_
Definition nanoflann.hpp:2023
const DatasetAdaptor & dataset_
The source of our data.
Definition nanoflann.hpp:1982
void removePoint(size_t idx)
Definition nanoflann.hpp:2107
std::unordered_set< int > removedPoints_
Definition nanoflann.hpp:1987
Size pointCount_
Definition nanoflann.hpp:1977
typename KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM >::Offset Offset
Definition nanoflann.hpp:1970
void addPoints(IndexType start, IndexType end)
Definition nanoflann.hpp:2066
std::vector< index_container_t > index_
Definition nanoflann.hpp:1994
KDTreeSingleIndexDynamicAdaptor(const int dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams &params=KDTreeSingleIndexAdaptorParams(), const size_t maximumPointCount=1000000000U)
Definition nanoflann.hpp:2040
std::vector< int > treeIndex_
Definition nanoflann.hpp:1986
const std::vector< index_container_t > & getAllIndices() const
Definition nanoflann.hpp:1999
KDTreeSingleIndexAdaptorParams index_params_
Definition nanoflann.hpp:1989
Dimension dim_
Dimensionality of each data point.
Definition nanoflann.hpp:1991
KDTreeSingleIndexDynamicAdaptor(const KDTreeSingleIndexDynamicAdaptor< Distance, DatasetAdaptor, DIM, IndexType > &)=delete
typename KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM >::Size Size
Definition nanoflann.hpp:1971
Definition nanoflann.hpp:148
_CountType CountType
Definition nanoflann.hpp:152
CountType capacity
Definition nanoflann.hpp:157
void init(IndexType *indices_, DistanceType *dists_)
Definition nanoflann.hpp:163
_DistanceType DistanceType
Definition nanoflann.hpp:150
bool addPoint(DistanceType dist, IndexType index)
Definition nanoflann.hpp:181
CountType size() const
Definition nanoflann.hpp:172
DistanceType * dists
Definition nanoflann.hpp:156
KNNResultSet(CountType capacity_)
Definition nanoflann.hpp:161
_IndexType IndexType
Definition nanoflann.hpp:151
DistanceType worstDist() const
Definition nanoflann.hpp:216
IndexType * indices
Definition nanoflann.hpp:155
bool full() const
Definition nanoflann.hpp:174
CountType count
Definition nanoflann.hpp:158
Definition nanoflann.hpp:658
~PooledAllocator()
Definition nanoflann.hpp:696
void free_all()
Definition nanoflann.hpp:699
void internal_init()
Definition nanoflann.hpp:676
uint32_t Offset
Definition nanoflann.hpp:668
void * malloc(const size_t req_size)
Definition nanoflann.hpp:715
int32_t Dimension
Definition nanoflann.hpp:670
T * allocate(const size_t count=1)
Definition nanoflann.hpp:770
uint32_t Size
Definition nanoflann.hpp:669
PooledAllocator()
Definition nanoflann.hpp:691
Definition nanoflann.hpp:250
void init()
Definition nanoflann.hpp:266
const DistanceType radius
Definition nanoflann.hpp:256
RadiusResultSet(DistanceType radius_, std::vector< ResultItem< IndexType, DistanceType > > &indices_dists)
Definition nanoflann.hpp:260
size_t empty() const
Definition nanoflann.hpp:270
DistanceType worstDist() const
Definition nanoflann.hpp:286
ResultItem< IndexType, DistanceType > worst_item() const
Definition nanoflann.hpp:292
_DistanceType DistanceType
Definition nanoflann.hpp:252
bool full() const
Definition nanoflann.hpp:272
size_t size() const
Definition nanoflann.hpp:269
std::vector< ResultItem< IndexType, DistanceType > > & m_indices_dists
Definition nanoflann.hpp:258
void clear()
Definition nanoflann.hpp:267
_IndexType IndexType
Definition nanoflann.hpp:253
bool addPoint(DistanceType dist, IndexType index)
Definition nanoflann.hpp:279
void load_value(std::istream &stream, T &value)
Definition nanoflann.hpp:318
void save_value(std::ostream &stream, const T &value)
Definition nanoflann.hpp:306
std::enable_if< has_assign< Container >::value, void >::type assign(Container &c, const size_t nElements, const T &value)
Definition nanoflann.hpp:128
T pi_const()
Definition nanoflann.hpp:82
std::enable_if< has_resize< Container >::value, void >::type resize(Container &c, const size_t nElements)
Definition nanoflann.hpp:108
std::underlying_type< KDTreeSingleIndexAdaptorFlags >::type operator&(KDTreeSingleIndexAdaptorFlags lhs, KDTreeSingleIndexAdaptorFlags rhs)
Definition nanoflann.hpp:609
KDTreeSingleIndexAdaptorFlags
Definition nanoflann.hpp:604
Definition nanoflann.hpp:77
Definition nanoflann.hpp:221
bool operator()(const PairType &p1, const PairType &p2) const
Definition nanoflann.hpp:223
Definition nanoflann.hpp:863
ElementType high
Definition nanoflann.hpp:864
Definition nanoflann.hpp:839
DistanceType divhigh
Definition nanoflann.hpp:851
Offset left
Definition nanoflann.hpp:845
struct nanoflann::KDTreeBaseClass::Node::@0::nonleaf sub
Node * child1
Definition nanoflann.hpp:856
Dimension divfeat
Definition nanoflann.hpp:849
Node * child2
Definition nanoflann.hpp:856
struct nanoflann::KDTreeBaseClass::Node::@0::leaf lr
union nanoflann::KDTreeBaseClass::Node::@0 node_type
Definition nanoflann.hpp:2169
void query(const num_t *query_point, const Size num_closest, IndexType *out_indices, num_t *out_distances) const
Definition nanoflann.hpp:2216
typename MatrixType::Scalar num_t
Definition nanoflann.hpp:2171
num_t kdtree_get_pt(const IndexType idx, size_t dim) const
Definition nanoflann.hpp:2239
Size kdtree_get_point_count() const
Definition nanoflann.hpp:2230
KDTreeEigenMatrixAdaptor(const Dimension dimensionality, const std::reference_wrapper< const MatrixType > &mat, const int leaf_max_size=10)
Constructor: takes a const ref to the matrix object with the data points.
Definition nanoflann.hpp:2186
typename index_t::Size Size
Definition nanoflann.hpp:2182
bool kdtree_get_bbox(BBOX &) const
Definition nanoflann.hpp:2252
const std::reference_wrapper< const MatrixType > m_data_matrix
Definition nanoflann.hpp:2206
KDTreeEigenMatrixAdaptor(const self_t &)=delete
const self_t & derived() const
Definition nanoflann.hpp:2226
index_t * index_
Definition nanoflann.hpp:2178
typename Distance::template traits< num_t, self_t, IndexType >::distance_t metric_t
Definition nanoflann.hpp:2173
self_t & derived()
Definition nanoflann.hpp:2227
typename MatrixType::Index IndexType
Definition nanoflann.hpp:2172
typename index_t::Dimension Dimension
Definition nanoflann.hpp:2183
typename index_t::Offset Offset
Definition nanoflann.hpp:2181
~KDTreeEigenMatrixAdaptor()
Definition nanoflann.hpp:2204
Definition nanoflann.hpp:618
KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size=10, KDTreeSingleIndexAdaptorFlags _flags=KDTreeSingleIndexAdaptorFlags::None)
Definition nanoflann.hpp:619
size_t leaf_max_size
Definition nanoflann.hpp:625
KDTreeSingleIndexAdaptorFlags flags
Definition nanoflann.hpp:626
Definition nanoflann.hpp:350
T ElementType
Definition nanoflann.hpp:351
DistanceType evalMetric(const T *a, const IndexType b_idx, size_t size, DistanceType worst_dist=-1) const
Definition nanoflann.hpp:358
const DataSource & data_source
Definition nanoflann.hpp:354
DistanceType accum_dist(const U a, const V b, const size_t) const
Definition nanoflann.hpp:388
_DistanceType DistanceType
Definition nanoflann.hpp:352
L1_Adaptor(const DataSource &_data_source)
Definition nanoflann.hpp:356
Definition nanoflann.hpp:405
_DistanceType DistanceType
Definition nanoflann.hpp:407
DistanceType accum_dist(const U a, const V b, const size_t) const
Definition nanoflann.hpp:444
DistanceType evalMetric(const T *a, const IndexType b_idx, size_t size, DistanceType worst_dist=-1) const
Definition nanoflann.hpp:413
T ElementType
Definition nanoflann.hpp:406
L2_Adaptor(const DataSource &_data_source)
Definition nanoflann.hpp:411
const DataSource & data_source
Definition nanoflann.hpp:409
Definition nanoflann.hpp:461
const DataSource & data_source
Definition nanoflann.hpp:465
DistanceType evalMetric(const T *a, const IndexType b_idx, size_t size) const
Definition nanoflann.hpp:469
DistanceType accum_dist(const U a, const V b, const size_t) const
Definition nanoflann.hpp:480
L2_Simple_Adaptor(const DataSource &_data_source)
Definition nanoflann.hpp:467
_DistanceType DistanceType
Definition nanoflann.hpp:463
T ElementType
Definition nanoflann.hpp:462
Definition nanoflann.hpp:336
Definition nanoflann.hpp:238
DistanceType second
Distance from sample to query point.
Definition nanoflann.hpp:243
ResultItem(const IndexType index, const DistanceType distance)
Definition nanoflann.hpp:240
IndexType first
Index of the sample in the dataset.
Definition nanoflann.hpp:242
Definition nanoflann.hpp:497
const DataSource & data_source
Definition nanoflann.hpp:501
_DistanceType DistanceType
Definition nanoflann.hpp:499
T ElementType
Definition nanoflann.hpp:498
DistanceType evalMetric(const T *a, const IndexType b_idx, size_t size) const
Definition nanoflann.hpp:505
SO2_Adaptor(const DataSource &_data_source)
Definition nanoflann.hpp:503
DistanceType accum_dist(const U a, const V b, const size_t) const
Definition nanoflann.hpp:512
Definition nanoflann.hpp:536
_DistanceType DistanceType
Definition nanoflann.hpp:538
L2_Simple_Adaptor< T, DataSource, DistanceType, IndexType > distance_L2_Simple
Definition nanoflann.hpp:540
T ElementType
Definition nanoflann.hpp:537
DistanceType evalMetric(const T *a, const IndexType b_idx, size_t size) const
Definition nanoflann.hpp:544
SO3_Adaptor(const DataSource &_data_source)
Definition nanoflann.hpp:542
DistanceType accum_dist(const U a, const V b, const size_t idx) const
Definition nanoflann.hpp:549
Definition nanoflann.hpp:631
SearchParameters(float eps_=0, bool sorted_=true)
Definition nanoflann.hpp:632
bool sorted
Definition nanoflann.hpp:635
float eps
search for eps-approximate neighbours (default: 0)
Definition nanoflann.hpp:634
std::vector< T > type
Definition nanoflann.hpp:791
Definition nanoflann.hpp:785
std::array< T, DIM > type
Definition nanoflann.hpp:786
Definition nanoflann.hpp:97
Definition nanoflann.hpp:89
Definition nanoflann.hpp:559
Definition nanoflann.hpp:557
Definition nanoflann.hpp:568
Definition nanoflann.hpp:577
Definition nanoflann.hpp:575
Definition nanoflann.hpp:566
Definition nanoflann.hpp:585
Definition nanoflann.hpp:583
Definition nanoflann.hpp:593
Definition nanoflann.hpp:591