uvgVPCCenc 1.0.0
uvgVPCCenc is an open-source real-time V-PCC encoder library written in C++ from scratch.
Loading...
Searching...
No Matches
nanoflann.hpp
Go to the documentation of this file.
1// This header merges noneflann.hpp, KDTreeVectorOfVectorsAdaptor.h and the related utils.h. //
2
3/***********************************************************************
4 * Software License Agreement (BSD License)
5 *
6 * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
7 * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
8 * Copyright 2011-2023 Jose Luis Blanco (joseluisblancoc@gmail.com).
9 * All rights reserved.
10 *
11 * THE BSD LICENSE
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *************************************************************************/
34
47#pragma once
48#pragma GCC diagnostic ignored "-Wunused-parameter"
49#include <algorithm>
50#include <array>
51#include <atomic>
52#include <cassert>
53#include <cmath> // for abs()
54#include <cstdlib> // for abs()
55#include <functional> // std::reference_wrapper
56#include <future>
57#include <istream>
58#include <limits> // std::numeric_limits
59#include <ostream>
60#include <stdexcept>
61#include <unordered_set>
62#include <vector>
63
65#define NANOFLANN_VERSION 0x151
66
67// Avoid conflicting declaration of min/max macros in Windows headers
68#if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
69#define NOMINMAX
70#ifdef max
71#undef max
72#undef min
73#endif
74#endif
75// Avoid conflicts with X11 headers
76#ifdef None
77#undef None
78#endif
79
80// nanoflann.hpp //
81
82namespace nanoflann {
87template <typename T>
89 return static_cast<T>(3.14159265358979323846);
90}
91
96template <typename T, typename = int>
97struct has_resize : std::false_type {};
98
99template <typename T>
100struct has_resize<T, decltype((void)std::declval<T>().resize(1), 0)> : std::true_type {};
101
102template <typename T, typename = int>
103struct has_assign : std::false_type {};
104
105template <typename T>
106struct has_assign<T, decltype((void)std::declval<T>().assign(1, 0), 0)> : std::true_type {};
107
111template <typename Container>
112inline typename std::enable_if<has_resize<Container>::value, void>::type resize(Container& c, const size_t nElements) {
113 c.resize(nElements);
114}
115
120template <typename Container>
121inline typename std::enable_if<!has_resize<Container>::value, void>::type resize(Container& c, const size_t nElements) {
122 if (nElements != c.size()) throw std::logic_error("Try to change the size of a std::array.");
123}
124
128template <typename Container, typename T>
129inline typename std::enable_if<has_assign<Container>::value, void>::type assign(Container& c, const size_t nElements, const T& value) {
130 c.assign(nElements, value);
131}
132
136template <typename Container, typename T>
137inline typename std::enable_if<!has_assign<Container>::value, void>::type assign(Container& c, const size_t nElements, const T& value) {
138 for (size_t i = 0; i < nElements; i++) c[i] = value;
139}
140
145template <typename _DistanceType, typename _IndexType = size_t, typename _CountType = size_t>
147 public:
148 using DistanceType = _DistanceType;
149 using IndexType = _IndexType;
150 using CountType = _CountType;
151
152 private:
153 IndexType* indices;
154 DistanceType* dists;
155 CountType capacity;
156 CountType count;
157
158 public:
159 explicit KNNResultSet(CountType capacity_) : indices(nullptr), dists(nullptr), capacity(capacity_), count(0) {}
160
161 void init(IndexType* indices_, DistanceType* dists_) {
162 indices = indices_;
163 dists = dists_;
164 count = 0;
165 if (capacity) dists[capacity - 1] = (std::numeric_limits<DistanceType>::max)();
166 }
167
168 CountType size() const { return count; }
169 bool empty() const { return count == 0; }
170 bool full() const { return count == capacity; }
171
177 bool addPoint(DistanceType dist, IndexType index) {
178 CountType i;
179 for (i = count; i > 0; --i) {
182#ifdef NANOFLANN_FIRST_MATCH
183 if ((dists[i - 1] > dist) || ((dist == dists[i - 1]) && (indices[i - 1] > index))) {
184#else
185 if (dists[i - 1] > dist) {
186#endif
187 if (i < capacity) {
188 dists[i] = dists[i - 1];
189 indices[i] = indices[i - 1];
190 }
191 } else
192 break;
193 }
194 if (i < capacity) {
195 dists[i] = dist;
196 indices[i] = index;
197 }
198 if (count < capacity) count++;
199
200 // tell caller that the search shall continue
201 return true;
202 }
203
204 DistanceType worstDist() const { return dists[capacity - 1]; }
205};
206
208template <typename _DistanceType, typename _IndexType = size_t, typename _CountType = size_t>
210 public:
211 using DistanceType = _DistanceType;
212 using IndexType = _IndexType;
213 using CountType = _CountType;
214
215 private:
216 IndexType* indices;
217 DistanceType* dists;
218 CountType capacity;
219 CountType count;
220 DistanceType maximumSearchDistanceSquared;
221
222 public:
223 explicit RKNNResultSet(CountType capacity_, DistanceType maximumSearchDistanceSquared_)
224 : indices(nullptr), dists(nullptr), capacity(capacity_), count(0), maximumSearchDistanceSquared(maximumSearchDistanceSquared_) {}
225
226 void init(IndexType* indices_, DistanceType* dists_) {
227 indices = indices_;
228 dists = dists_;
229 count = 0;
230 if (capacity) dists[capacity - 1] = maximumSearchDistanceSquared;
231 }
232
233 CountType size() const { return count; }
234 bool empty() const { return count == 0; }
235 bool full() const { return count == capacity; }
236
242 bool addPoint(DistanceType dist, IndexType index) {
243 CountType i;
244 for (i = count; i > 0; --i) {
247#ifdef NANOFLANN_FIRST_MATCH
248 if ((dists[i - 1] > dist) || ((dist == dists[i - 1]) && (indices[i - 1] > index))) {
249#else
250 if (dists[i - 1] > dist) {
251#endif
252 if (i < capacity) {
253 dists[i] = dists[i - 1];
254 indices[i] = indices[i - 1];
255 }
256 } else
257 break;
258 }
259 if (i < capacity) {
260 dists[i] = dist;
261 indices[i] = index;
262 }
263 if (count < capacity) count++;
264
265 // tell caller that the search shall continue
266 return true;
267 }
268
269 DistanceType worstDist() const { return dists[capacity - 1]; }
270};
271
275 template <typename PairType>
276 bool operator()(const PairType& p1, const PairType& p2) const {
277 return p1.second < p2.second;
278 }
279};
280
289template <typename IndexType = size_t, typename DistanceType = double>
291 ResultItem() = default;
292 ResultItem(const IndexType index, const DistanceType distance) : first(index), second(distance) {}
293
294 IndexType first;
295 DistanceType second;
296};
297
301template <typename _DistanceType, typename _IndexType = size_t>
303 public:
304 using DistanceType = _DistanceType;
305 using IndexType = _IndexType;
306
307 public:
309
310 std::vector<ResultItem<IndexType, DistanceType>>& m_indices_dists;
311
312 explicit RadiusResultSet(DistanceType radius_, std::vector<ResultItem<IndexType, DistanceType>>& indices_dists)
313 : radius(radius_), m_indices_dists(indices_dists) {
314 init();
315 }
316
317 void init() { clear(); }
318 void clear() { m_indices_dists.clear(); }
319
320 size_t size() const { return m_indices_dists.size(); }
321 size_t empty() const { return m_indices_dists.empty(); }
322
323 bool full() const { return true; }
324
330 bool addPoint(DistanceType dist, IndexType index) {
331 if (dist < radius) m_indices_dists.emplace_back(index, dist);
332 return true;
333 }
334
335 DistanceType worstDist() const { return radius; }
336
342 if (m_indices_dists.empty())
343 throw std::runtime_error(
344 "Cannot invoke RadiusResultSet::worst_item() on "
345 "an empty list of results.");
346 auto it = std::max_element(m_indices_dists.begin(), m_indices_dists.end(), IndexDist_Sorter());
347 return *it;
348 }
349};
350
355template <typename T>
356void save_value(std::ostream& stream, const T& value) {
357 stream.write(reinterpret_cast<const char*>(&value), sizeof(T));
358}
359
360template <typename T>
361void save_value(std::ostream& stream, const std::vector<T>& value) {
362 size_t size = value.size();
363 stream.write(reinterpret_cast<const char*>(&size), sizeof(size_t));
364 stream.write(reinterpret_cast<const char*>(value.data()), sizeof(T) * size);
365}
366
367template <typename T>
368void load_value(std::istream& stream, T& value) {
369 stream.read(reinterpret_cast<char*>(&value), sizeof(T));
370}
371
372template <typename T>
373void load_value(std::istream& stream, std::vector<T>& value) {
374 size_t size;
375 stream.read(reinterpret_cast<char*>(&size), sizeof(size_t));
376 value.resize(size);
377 stream.read(reinterpret_cast<char*>(value.data()), sizeof(T) * size);
378}
384struct Metric {};
385
396template <class T, class DataSource, typename _DistanceType = T, typename IndexType = uint32_t>
398 using ElementType = T;
399 using DistanceType = _DistanceType;
400
401 const DataSource& data_source;
402
403 L1_Adaptor(const DataSource& _data_source) : data_source(_data_source) {}
404
405 DistanceType evalMetric(const T* a, const IndexType b_idx, size_t size, DistanceType worst_dist = -1) const {
406 DistanceType result = DistanceType();
407 const T* last = a + size;
408 const T* lastgroup = last - 3;
409 size_t d = 0;
410
411 /* Process 4 items with each loop for efficiency. */
412 while (a < lastgroup) {
413 const DistanceType diff0 = std::abs(a[0] - data_source.kdtree_get_pt(b_idx, d++));
414 const DistanceType diff1 = std::abs(a[1] - data_source.kdtree_get_pt(b_idx, d++));
415 const DistanceType diff2 = std::abs(a[2] - data_source.kdtree_get_pt(b_idx, d++));
416 const DistanceType diff3 = std::abs(a[3] - data_source.kdtree_get_pt(b_idx, d++));
417 result += diff0 + diff1 + diff2 + diff3;
418 a += 4;
419 if ((worst_dist > 0) && (result > worst_dist)) {
420 return result;
421 }
422 }
423 /* Process last 0-3 components. Not needed for standard vector lengths.
424 */
425 while (a < last) {
426 result += std::abs(*a++ - data_source.kdtree_get_pt(b_idx, d++));
427 }
428 return result;
429 }
430
431 template <typename U, typename V>
432 DistanceType accum_dist(const U a, const V b, const size_t) const {
433 return std::abs(a - b);
434 }
435};
436
447template <class T, class DataSource, typename _DistanceType = T, typename IndexType = uint32_t>
449 using ElementType = T;
450 using DistanceType = _DistanceType;
451
452 const DataSource& data_source;
453
454 L2_Adaptor(const DataSource& _data_source) : data_source(_data_source) {}
455
456 DistanceType evalMetric(const T* a, const IndexType b_idx, size_t size, DistanceType worst_dist = -1) const {
457 DistanceType result = DistanceType();
458 const T* last = a + size;
459 const T* lastgroup = last - 3;
460 size_t d = 0;
461
462 /* Process 4 items with each loop for efficiency. */
463 while (a < lastgroup) {
464 const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx, d++);
465 const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx, d++);
466 const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx, d++);
467 const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx, d++);
468 result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
469 a += 4;
470 if ((worst_dist > 0) && (result > worst_dist)) {
471 return result;
472 }
473 }
474 /* Process last 0-3 components. Not needed for standard vector lengths.
475 */
476 while (a < last) {
477 const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx, d++);
478 result += diff0 * diff0;
479 }
480 return result;
481 }
482
483 template <typename U, typename V>
484 DistanceType accum_dist(const U a, const V b, const size_t) const {
485 return (a - b) * (a - b);
486 }
487};
488
499template <class T, class DataSource, typename _DistanceType = T, typename IndexType = uint32_t>
501 using ElementType = T;
502 using DistanceType = _DistanceType;
503
504 const DataSource& data_source;
505
506 L2_Simple_Adaptor(const DataSource& _data_source) : data_source(_data_source) {}
507
508 DistanceType evalMetric(const T* a, const IndexType b_idx, size_t size) const {
509 DistanceType result = DistanceType();
510 for (size_t i = 0; i < size; ++i) {
511 const DistanceType diff = a[i] - data_source.kdtree_get_pt(b_idx, i);
512 result += diff * diff;
513 }
514 return result;
515 }
516
517 template <typename U, typename V>
518 DistanceType accum_dist(const U a, const V b, const size_t) const {
519 return (a - b) * (a - b);
520 }
521};
522
533template <class T, class DataSource, typename _DistanceType = T, typename IndexType = uint32_t>
535 using ElementType = T;
536 using DistanceType = _DistanceType;
537
538 const DataSource& data_source;
539
540 SO2_Adaptor(const DataSource& _data_source) : data_source(_data_source) {}
541
542 DistanceType evalMetric(const T* a, const IndexType b_idx, size_t size) const {
543 return accum_dist(a[size - 1], data_source.kdtree_get_pt(b_idx, size - 1), size - 1);
544 }
545
548 template <typename U, typename V>
549 DistanceType accum_dist(const U a, const V b, const size_t) const {
550 DistanceType result = DistanceType();
551 DistanceType PI = pi_const<DistanceType>();
552 result = b - a;
553 if (result > PI)
554 result -= 2 * PI;
555 else if (result < -PI)
556 result += 2 * PI;
557 return result;
558 }
559};
560
571template <class T, class DataSource, typename _DistanceType = T, typename IndexType = uint32_t>
573 using ElementType = T;
574 using DistanceType = _DistanceType;
575
577
578 SO3_Adaptor(const DataSource& _data_source) : distance_L2_Simple(_data_source) {}
579
580 DistanceType evalMetric(const T* a, const IndexType b_idx, size_t size) const {
581 return distance_L2_Simple.evalMetric(a, b_idx, size);
582 }
583
584 template <typename U, typename V>
585 DistanceType accum_dist(const U a, const V b, const size_t idx) const {
586 return distance_L2_Simple.accum_dist(a, b, idx);
587 }
588};
589
591struct metric_L1 : public Metric {
592 template <class T, class DataSource, typename IndexType = uint32_t>
596};
599struct metric_L2 : public Metric {
600 template <class T, class DataSource, typename IndexType = uint32_t>
604};
607struct metric_L2_Simple : public Metric {
608 template <class T, class DataSource, typename IndexType = uint32_t>
612};
614struct metric_SO2 : public Metric {
615 template <class T, class DataSource, typename IndexType = uint32_t>
619};
621struct metric_SO3 : public Metric {
622 template <class T, class DataSource, typename IndexType = uint32_t>
626};
627
634
635inline std::underlying_type<KDTreeSingleIndexAdaptorFlags>::type operator&(KDTreeSingleIndexAdaptorFlags lhs,
637 using underlying = typename std::underlying_type<KDTreeSingleIndexAdaptorFlags>::type;
638 return static_cast<underlying>(lhs) & static_cast<underlying>(rhs);
639}
640
643 KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size = 10,
644 KDTreeSingleIndexAdaptorFlags _flags = KDTreeSingleIndexAdaptorFlags::None,
645 unsigned int _n_thread_build = 1)
646 : leaf_max_size(_leaf_max_size), flags(_flags), n_thread_build(_n_thread_build) {}
647
650 unsigned int n_thread_build;
651};
652
655 SearchParameters(float eps_ = 0, bool sorted_ = true) : eps(eps_), sorted(sorted_) {}
656
657 float eps;
658 bool sorted;
660};
681 static constexpr size_t WORDSIZE = 16;
682 static constexpr size_t BLOCKSIZE = 8192;
683
684 /* We maintain memory alignment to word boundaries by requiring that all
685 allocations be in multiples of the machine wordsize. */
686 /* Size of machine word in bytes. Must be power of 2. */
687 /* Minimum number of bytes requested at a time from the system. Must be
688 * multiple of WORDSIZE. */
689
690 using Offset = uint32_t;
691 using Size = uint32_t;
692 using Dimension = int32_t;
693
694 Size remaining_ = 0;
695 void* base_ = nullptr;
696 void* loc_ = nullptr;
697
698 void internal_init() {
699 remaining_ = 0;
700 base_ = nullptr;
701 usedMemory = 0;
702 wastedMemory = 0;
703 }
704
705 public:
706 Size usedMemory = 0;
707 Size wastedMemory = 0;
708
712 PooledAllocator() { internal_init(); }
713
717 ~PooledAllocator() { free_all(); }
718
720 void free_all() {
721 while (base_ != nullptr) {
722 // Get pointer to prev block
723 void* prev = *(static_cast<void**>(base_));
724 ::free(base_);
725 base_ = prev;
726 }
727 internal_init();
728 }
729
734 void* malloc(const size_t req_size) {
735 /* Round size up to a multiple of wordsize. The following expression
736 only works for WORDSIZE that is a power of 2, by masking last bits
737 of incremented size to zero.
738 */
739 const Size size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1);
740
741 /* Check whether a new block must be allocated. Note that the first
742 word of a block is reserved for a pointer to the previous block.
743 */
744 if (size > remaining_) {
745 wastedMemory += remaining_;
746
747 /* Allocate new storage. */
748 const Size blocksize = (size + sizeof(void*) + (WORDSIZE - 1) > BLOCKSIZE) ? size + sizeof(void*) + (WORDSIZE - 1) : BLOCKSIZE;
749
750 // use the standard C malloc to allocate memory
751 void* m = ::malloc(blocksize);
752 if (!m) {
753 fprintf(stderr, "Failed to allocate memory.\n");
754 throw std::bad_alloc();
755 }
756
757 /* Fill first word of new block with pointer to previous block. */
758 static_cast<void**>(m)[0] = base_;
759 base_ = m;
760
761 Size shift = 0;
762 // int size_t = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) &
763 // (WORDSIZE-1))) & (WORDSIZE-1);
764
765 remaining_ = blocksize - sizeof(void*) - shift;
766 loc_ = (static_cast<char*>(m) + sizeof(void*) + shift);
767 }
768 void* rloc = loc_;
769 loc_ = static_cast<char*>(loc_) + size;
770 remaining_ -= size;
771
772 usedMemory += size;
773
774 return rloc;
775 }
776
784 template <typename T>
785 T* allocate(const size_t count = 1) {
786 T* mem = static_cast<T*>(this->malloc(sizeof(T) * count));
787 return mem;
788 }
789};
798template <int32_t DIM, typename T>
800 using type = std::array<T, DIM>;
801};
803template <typename T>
804struct array_or_vector<-1, T> {
805 using type = std::vector<T>;
806};
807
824template <class Derived, typename Distance, class DatasetAdaptor, int32_t DIM = -1, typename IndexType = uint32_t>
826 public:
829 void freeIndex(Derived& obj) {
830 obj.pool_.free_all();
831 obj.root_node_ = nullptr;
832 obj.size_at_index_build_ = 0;
833 }
834
835 using ElementType = typename Distance::ElementType;
836 using DistanceType = typename Distance::DistanceType;
837
841 std::vector<IndexType> vAcc_;
842
843 using Offset = typename decltype(vAcc_)::size_type;
844 using Size = typename decltype(vAcc_)::size_type;
845 using Dimension = int32_t;
846
847 /*---------------------------
848 * Internal Data Structures
849 * --------------------------*/
850 struct Node {
853 union {
854 struct leaf {
855 Offset left, right;
856 } lr;
857 struct nonleaf {
861 } sub;
862 } node_type;
863
865 Node *child1 = nullptr, *child2 = nullptr;
866 };
867
868 using NodePtr = Node*;
869 using NodeConstPtr = const Node*;
870
871 struct Interval {
873 };
874
875 NodePtr root_node_ = nullptr;
876
877 Size leaf_max_size_ = 0;
878
880 Size n_thread_build_ = 1;
882 Size size_ = 0;
884 Size size_at_index_build_ = 0;
885 Dimension dim_ = 0;
886
890
894
897
906
908 Size size(const Derived& obj) const { return obj.size_; }
909
911 Size veclen(const Derived& obj) { return DIM > 0 ? DIM : obj.dim; }
912
914 ElementType dataset_get(const Derived& obj, IndexType element, Dimension component) const {
915 return obj.dataset_.kdtree_get_pt(element, component);
916 }
917
922 Size usedMemory(Derived& obj) {
923 return obj.pool_.usedMemory + obj.pool_.wastedMemory +
924 obj.dataset_.kdtree_get_point_count() * sizeof(IndexType); // pool memory and vind array memory
925 }
926
927 void computeMinMax(const Derived& obj, Offset ind, Size count, Dimension element, ElementType& min_elem, ElementType& max_elem) {
928 min_elem = dataset_get(obj, vAcc_[ind], element);
929 max_elem = min_elem;
930 for (Offset i = 1; i < count; ++i) {
931 ElementType val = dataset_get(obj, vAcc_[ind + i], element);
932 if (val < min_elem) min_elem = val;
933 if (val > max_elem) max_elem = val;
934 }
935 }
936
944 NodePtr divideTree(Derived& obj, const Offset left, const Offset right, BoundingBox& bbox) {
945 NodePtr node = obj.pool_.template allocate<Node>(); // allocate memory
946 const auto dims = (DIM > 0 ? DIM : obj.dim_);
947
948 /* If too few exemplars remain, then make this a leaf node. */
949 if ((right - left) <= static_cast<Offset>(obj.leaf_max_size_)) {
950 node->child1 = node->child2 = nullptr; /* Mark as leaf node. */
951 node->node_type.lr.left = left;
952 node->node_type.lr.right = right;
953
954 // compute bounding-box of leaf points
955 for (Dimension i = 0; i < dims; ++i) {
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 for (Dimension i = 0; i < dims; ++i) {
961 const auto val = dataset_get(obj, obj.vAcc_[k], i);
962 if (bbox[i].low > val) bbox[i].low = val;
963 if (bbox[i].high < val) bbox[i].high = val;
964 }
965 }
966 } else {
967 Offset idx;
968 Dimension cutfeat;
969 DistanceType cutval;
970 middleSplit_(obj, left, right - left, idx, cutfeat, cutval, bbox);
971
972 node->node_type.sub.divfeat = cutfeat;
973
974 BoundingBox left_bbox(bbox);
975 left_bbox[cutfeat].high = cutval;
976 node->child1 = this->divideTree(obj, left, left + idx, left_bbox);
977
978 BoundingBox right_bbox(bbox);
979 right_bbox[cutfeat].low = cutval;
980 node->child2 = this->divideTree(obj, left + idx, right, right_bbox);
981
982 node->node_type.sub.divlow = left_bbox[cutfeat].high;
983 node->node_type.sub.divhigh = right_bbox[cutfeat].low;
984
985 for (Dimension i = 0; i < dims; ++i) {
986 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
987 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
988 }
989 }
990
991 return node;
992 }
993
1004 NodePtr divideTreeConcurrent(Derived& obj, const Offset left, const Offset right, BoundingBox& bbox,
1005 std::atomic<unsigned int>& thread_count, std::mutex& mutex) {
1006 std::unique_lock<std::mutex> lock(mutex);
1007 NodePtr node = obj.pool_.template allocate<Node>(); // allocate memory
1008 lock.unlock();
1009
1010 const auto dims = (DIM > 0 ? DIM : obj.dim_);
1011
1012 /* If too few exemplars remain, then make this a leaf node. */
1013 if ((right - left) <= static_cast<Offset>(obj.leaf_max_size_)) {
1014 node->child1 = node->child2 = nullptr; /* Mark as leaf node. */
1015 node->node_type.lr.left = left;
1016 node->node_type.lr.right = right;
1017
1018 // compute bounding-box of leaf points
1019 for (Dimension i = 0; i < dims; ++i) {
1020 bbox[i].low = dataset_get(obj, obj.vAcc_[left], i);
1021 bbox[i].high = dataset_get(obj, obj.vAcc_[left], i);
1022 }
1023 for (Offset k = left + 1; k < right; ++k) {
1024 for (Dimension i = 0; i < dims; ++i) {
1025 const auto val = dataset_get(obj, obj.vAcc_[k], i);
1026 if (bbox[i].low > val) bbox[i].low = val;
1027 if (bbox[i].high < val) bbox[i].high = val;
1028 }
1029 }
1030 } else {
1031 Offset idx;
1032 Dimension cutfeat;
1033 DistanceType cutval;
1034 middleSplit_(obj, left, right - left, idx, cutfeat, cutval, bbox);
1035
1036 node->node_type.sub.divfeat = cutfeat;
1037
1038 std::future<NodePtr> left_future, right_future;
1039
1040 BoundingBox left_bbox(bbox);
1041 left_bbox[cutfeat].high = cutval;
1042 if (++thread_count < n_thread_build_) {
1043 left_future = std::async(std::launch::async, &KDTreeBaseClass::divideTreeConcurrent, this, std::ref(obj), left, left + idx,
1044 std::ref(left_bbox), std::ref(thread_count), std::ref(mutex));
1045 } else {
1046 --thread_count;
1047 node->child1 = this->divideTreeConcurrent(obj, left, left + idx, left_bbox, thread_count, mutex);
1048 }
1049
1050 BoundingBox right_bbox(bbox);
1051 right_bbox[cutfeat].low = cutval;
1052 if (++thread_count < n_thread_build_) {
1053 right_future = std::async(std::launch::async, &KDTreeBaseClass::divideTreeConcurrent, this, std::ref(obj), left + idx, right,
1054 std::ref(right_bbox), std::ref(thread_count), std::ref(mutex));
1055 } else {
1056 --thread_count;
1057 node->child2 = this->divideTreeConcurrent(obj, left + idx, right, right_bbox, thread_count, mutex);
1058 }
1059
1060 if (left_future.valid()) {
1061 node->child1 = left_future.get();
1062 --thread_count;
1063 }
1064 if (right_future.valid()) {
1065 node->child2 = right_future.get();
1066 --thread_count;
1067 }
1068
1069 node->node_type.sub.divlow = left_bbox[cutfeat].high;
1070 node->node_type.sub.divhigh = right_bbox[cutfeat].low;
1071
1072 for (Dimension i = 0; i < dims; ++i) {
1073 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
1074 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
1075 }
1076 }
1077
1078 return node;
1079 }
1080
1081 void middleSplit_(const Derived& obj, const Offset ind, const Size count, Offset& index, Dimension& cutfeat, DistanceType& cutval,
1082 const BoundingBox& bbox) {
1083 const auto dims = (DIM > 0 ? DIM : obj.dim_);
1084 const auto EPS = static_cast<DistanceType>(0.00001);
1085 ElementType max_span = bbox[0].high - bbox[0].low;
1086 for (Dimension i = 1; i < dims; ++i) {
1087 ElementType span = bbox[i].high - bbox[i].low;
1088 if (span > max_span) {
1089 max_span = span;
1090 }
1091 }
1092 ElementType max_spread = -1;
1093 cutfeat = 0;
1094 ElementType min_elem = 0, max_elem = 0;
1095 for (Dimension i = 0; i < dims; ++i) {
1096 ElementType span = bbox[i].high - bbox[i].low;
1097 if (span > (1 - EPS) * max_span) {
1098 ElementType min_elem_, max_elem_;
1099 computeMinMax(obj, ind, count, i, min_elem_, max_elem_);
1100 ElementType spread = max_elem_ - min_elem_;
1101 if (spread > max_spread) {
1102 cutfeat = i;
1103 max_spread = spread;
1104 min_elem = min_elem_;
1105 max_elem = max_elem_;
1106 }
1107 }
1108 }
1109 // split in the middle
1110 DistanceType split_val = (bbox[cutfeat].low + bbox[cutfeat].high) / 2;
1111
1112 if (split_val < min_elem)
1113 cutval = min_elem;
1114 else if (split_val > max_elem)
1115 cutval = max_elem;
1116 else
1117 cutval = split_val;
1118
1119 Offset lim1, lim2;
1120 planeSplit(obj, ind, count, cutfeat, cutval, lim1, lim2);
1121
1122 if (lim1 > count / 2)
1123 index = lim1;
1124 else if (lim2 < count / 2)
1125 index = lim2;
1126 else
1127 index = count / 2;
1128 }
1129
1139 void planeSplit(const Derived& obj, const Offset ind, const Size count, const Dimension cutfeat, const DistanceType& cutval, Offset& lim1,
1140 Offset& lim2) {
1141 /* Move vector indices for left subtree to front of list. */
1142 Offset left = 0;
1143 Offset right = count - 1;
1144 for (;;) {
1145 while (left <= right && dataset_get(obj, vAcc_[ind + left], cutfeat) < cutval) ++left;
1146 while (right && left <= right && dataset_get(obj, vAcc_[ind + right], cutfeat) >= cutval) --right;
1147 if (left > right || !right) break; // "!right" was added to support unsigned Index types
1148 std::swap(vAcc_[ind + left], vAcc_[ind + right]);
1149 ++left;
1150 --right;
1151 }
1152 /* If either list is empty, it means that all remaining features
1153 * are identical. Split in the middle to maintain a balanced tree.
1154 */
1155 lim1 = left;
1156 right = count - 1;
1157 for (;;) {
1158 while (left <= right && dataset_get(obj, vAcc_[ind + left], cutfeat) <= cutval) ++left;
1159 while (right && left <= right && dataset_get(obj, vAcc_[ind + right], cutfeat) > cutval) --right;
1160 if (left > right || !right) break; // "!right" was added to support unsigned Index types
1161 std::swap(vAcc_[ind + left], vAcc_[ind + right]);
1162 ++left;
1163 --right;
1164 }
1165 lim2 = left;
1166 }
1167
1168 DistanceType computeInitialDistances(const Derived& obj, const ElementType* vec, distance_vector_t& dists) const {
1169 assert(vec);
1170 DistanceType dist = DistanceType();
1171
1172 for (Dimension i = 0; i < (DIM > 0 ? DIM : obj.dim_); ++i) {
1173 if (vec[i] < obj.root_bbox_[i].low) {
1174 dists[i] = obj.distance_.accum_dist(vec[i], obj.root_bbox_[i].low, i);
1175 dist += dists[i];
1176 }
1177 if (vec[i] > obj.root_bbox_[i].high) {
1178 dists[i] = obj.distance_.accum_dist(vec[i], obj.root_bbox_[i].high, i);
1179 dist += dists[i];
1180 }
1181 }
1182 return dist;
1183 }
1184
1185 static void save_tree(const Derived& obj, std::ostream& stream, const NodeConstPtr tree) {
1186 save_value(stream, *tree);
1187 if (tree->child1 != nullptr) {
1188 save_tree(obj, stream, tree->child1);
1189 }
1190 if (tree->child2 != nullptr) {
1191 save_tree(obj, stream, tree->child2);
1192 }
1193 }
1194
1195 static void load_tree(Derived& obj, std::istream& stream, NodePtr& tree) {
1196 tree = obj.pool_.template allocate<Node>();
1197 load_value(stream, *tree);
1198 if (tree->child1 != nullptr) {
1199 load_tree(obj, stream, tree->child1);
1200 }
1201 if (tree->child2 != nullptr) {
1202 load_tree(obj, stream, tree->child2);
1203 }
1204 }
1205
1211 void saveIndex(const Derived& obj, std::ostream& stream) const {
1212 save_value(stream, obj.size_);
1213 save_value(stream, obj.dim_);
1214 save_value(stream, obj.root_bbox_);
1215 save_value(stream, obj.leaf_max_size_);
1216 save_value(stream, obj.vAcc_);
1217 if (obj.root_node_) save_tree(obj, stream, obj.root_node_);
1218 }
1219
1225 void loadIndex(Derived& obj, std::istream& stream) {
1226 load_value(stream, obj.size_);
1227 load_value(stream, obj.dim_);
1228 load_value(stream, obj.root_bbox_);
1229 load_value(stream, obj.leaf_max_size_);
1230 load_value(stream, obj.vAcc_);
1231 load_tree(obj, stream, obj.root_node_);
1232 }
1233};
1234
1276template <typename Distance, class DatasetAdaptor, int32_t DIM = -1, typename IndexType = uint32_t>
1278 : public KDTreeBaseClass<KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM, IndexType>, Distance, DatasetAdaptor, DIM, IndexType> {
1279 public:
1282
1284 const DatasetAdaptor& dataset_;
1285
1287
1288 Distance distance_;
1289
1291 DatasetAdaptor, DIM, IndexType>;
1292
1293 using Offset = typename Base::Offset;
1294 using Size = typename Base::Size;
1295 using Dimension = typename Base::Dimension;
1296
1297 using ElementType = typename Base::ElementType;
1298 using DistanceType = typename Base::DistanceType;
1299
1300 using Node = typename Base::Node;
1301 using NodePtr = Node*;
1302
1303 using Interval = typename Base::Interval;
1304
1307 using BoundingBox = typename Base::BoundingBox;
1308
1311 using distance_vector_t = typename Base::distance_vector_t;
1312
1333 template <class... Args>
1334 explicit KDTreeSingleIndexAdaptor(const Dimension dimensionality, const DatasetAdaptor& inputData,
1335 const KDTreeSingleIndexAdaptorParams& params, Args&&... args)
1336 : dataset_(inputData), indexParams(params), distance_(inputData, std::forward<Args>(args)...) {
1337 init(dimensionality, params);
1338 }
1339
1340 explicit KDTreeSingleIndexAdaptor(const Dimension dimensionality, const DatasetAdaptor& inputData,
1341 const KDTreeSingleIndexAdaptorParams& params = {})
1342 : dataset_(inputData), indexParams(params), distance_(inputData) {
1343 init(dimensionality, params);
1344 }
1345
1346 private:
1347 void init(const Dimension dimensionality, const KDTreeSingleIndexAdaptorParams& params) {
1348 Base::size_ = dataset_.kdtree_get_point_count();
1349 Base::size_at_index_build_ = Base::size_;
1350 Base::dim_ = dimensionality;
1351 if (DIM > 0) Base::dim_ = DIM;
1352 Base::leaf_max_size_ = params.leaf_max_size;
1353 if (params.n_thread_build > 0) {
1354 Base::n_thread_build_ = params.n_thread_build;
1355 } else {
1356 Base::n_thread_build_ = std::max(std::thread::hardware_concurrency(), 1u);
1357 }
1358
1359 if (!(params.flags & KDTreeSingleIndexAdaptorFlags::SkipInitialBuildIndex)) {
1360 // Build KD-tree:
1361 buildIndex();
1362 }
1363 }
1364
1365 public:
1369 void buildIndex() {
1370 Base::size_ = dataset_.kdtree_get_point_count();
1371 Base::size_at_index_build_ = Base::size_;
1372 init_vind();
1373 this->freeIndex(*this);
1374 Base::size_at_index_build_ = Base::size_;
1375 if (Base::size_ == 0) return;
1376 computeBoundingBox(Base::root_bbox_);
1377 // construct the tree
1378 if (Base::n_thread_build_ == 1) {
1379 Base::root_node_ = this->divideTree(*this, 0, Base::size_, Base::root_bbox_);
1380 } else {
1381 std::atomic<unsigned int> thread_count(0u);
1382 std::mutex mutex;
1383 Base::root_node_ = this->divideTreeConcurrent(*this, 0, Base::size_, Base::root_bbox_, thread_count, mutex);
1384 }
1385 }
1386
1406 template <typename RESULTSET>
1407 bool findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParameters& searchParams = {}) const {
1408 assert(vec);
1409 if (this->size(*this) == 0) return false;
1410 if (!Base::root_node_)
1411 throw std::runtime_error(
1412 "[nanoflann] findNeighbors() called before building the "
1413 "index.");
1414 float epsError = 1 + searchParams.eps;
1415
1416 // fixed or variable-sized container (depending on DIM)
1417 distance_vector_t dists;
1418 // Fill it with zeros.
1419 auto zero = static_cast<decltype(result.worstDist())>(0);
1420 assign(dists, (DIM > 0 ? DIM : Base::dim_), zero);
1421 DistanceType dist = this->computeInitialDistances(*this, vec, dists);
1422 searchLevel(result, vec, Base::root_node_, dist, dists, epsError);
1423 return result.full();
1424 }
1425
1441 Size knnSearch(const ElementType* query_point, const Size num_closest, IndexType* out_indices, DistanceType* out_distances) const {
1443 resultSet.init(out_indices, out_distances);
1444 findNeighbors(resultSet, query_point);
1445 return resultSet.size();
1446 }
1447
1467 Size radiusSearch(const ElementType* query_point, const DistanceType& radius,
1468 std::vector<ResultItem<IndexType, DistanceType>>& IndicesDists, const SearchParameters& searchParams = {}) const {
1469 RadiusResultSet<DistanceType, IndexType> resultSet(radius, IndicesDists);
1470 const Size nFound = radiusSearchCustomCallback(query_point, resultSet, searchParams);
1471 if (searchParams.sorted) std::sort(IndicesDists.begin(), IndicesDists.end(), IndexDist_Sorter());
1472 return nFound;
1473 }
1474
1480 template <class SEARCH_CALLBACK>
1481 Size radiusSearchCustomCallback(const ElementType* query_point, SEARCH_CALLBACK& resultSet,
1482 const SearchParameters& searchParams = {}) const {
1483 findNeighbors(resultSet, query_point, searchParams);
1484 return resultSet.size();
1485 }
1486
1503 Size rknnSearch(const ElementType* query_point, const Size num_closest, IndexType* out_indices, DistanceType* out_distances,
1504 const DistanceType& radius) const {
1505 nanoflann::RKNNResultSet<DistanceType, IndexType> resultSet(num_closest, radius);
1506 resultSet.init(out_indices, out_distances);
1507 findNeighbors(resultSet, query_point);
1508 return resultSet.size();
1509 }
1510
1513 public:
1516 void init_vind() {
1517 // Create a permutable array of indices to the input vectors.
1518 Base::size_ = dataset_.kdtree_get_point_count();
1519 if (Base::vAcc_.size() != Base::size_) Base::vAcc_.resize(Base::size_);
1520 for (Size i = 0; i < Base::size_; i++) Base::vAcc_[i] = i;
1521 }
1522
1524 const auto dims = (DIM > 0 ? DIM : Base::dim_);
1525 resize(bbox, dims);
1526 if (dataset_.kdtree_get_bbox(bbox)) {
1527 // Done! It was implemented in derived class
1528 } else {
1529 const Size N = dataset_.kdtree_get_point_count();
1530 if (!N)
1531 throw std::runtime_error(
1532 "[nanoflann] computeBoundingBox() called but "
1533 "no data points found.");
1534 for (Dimension i = 0; i < dims; ++i) {
1535 bbox[i].low = bbox[i].high = this->dataset_get(*this, Base::vAcc_[0], i);
1536 }
1537 for (Offset k = 1; k < N; ++k) {
1538 for (Dimension i = 0; i < dims; ++i) {
1539 const auto val = this->dataset_get(*this, Base::vAcc_[k], i);
1540 if (val < bbox[i].low) bbox[i].low = val;
1541 if (val > bbox[i].high) bbox[i].high = val;
1542 }
1543 }
1544 }
1545 }
1546
1553 template <class RESULTSET>
1554 bool searchLevel(RESULTSET& result_set, const ElementType* vec, const NodePtr node, DistanceType mindist, distance_vector_t& dists,
1555 const float epsError) const {
1556 /* If this is a leaf node, then do check and return. */
1557 if ((node->child1 == nullptr) && (node->child2 == nullptr)) {
1558 DistanceType worst_dist = result_set.worstDist();
1559 for (Offset i = node->node_type.lr.left; i < node->node_type.lr.right; ++i) {
1560 const IndexType accessor = Base::vAcc_[i]; // reorder... : i;
1561 DistanceType dist = distance_.evalMetric(vec, accessor, (DIM > 0 ? DIM : Base::dim_));
1562 if (dist < worst_dist) {
1563 if (!result_set.addPoint(dist, Base::vAcc_[i])) {
1564 // the resultset doesn't want to receive any more
1565 // points, we're done searching!
1566 return false;
1567 }
1568 }
1569 }
1570 return true;
1571 }
1572
1573 /* Which child branch should be taken first? */
1574 Dimension idx = node->node_type.sub.divfeat;
1575 ElementType val = vec[idx];
1576 DistanceType diff1 = val - node->node_type.sub.divlow;
1577 DistanceType diff2 = val - node->node_type.sub.divhigh;
1578
1579 NodePtr bestChild;
1580 NodePtr otherChild;
1581 DistanceType cut_dist;
1582 if ((diff1 + diff2) < 0) {
1583 bestChild = node->child1;
1584 otherChild = node->child2;
1585 cut_dist = distance_.accum_dist(val, node->node_type.sub.divhigh, idx);
1586 } else {
1587 bestChild = node->child2;
1588 otherChild = node->child1;
1589 cut_dist = distance_.accum_dist(val, node->node_type.sub.divlow, idx);
1590 }
1591
1592 /* Call recursively to search next level down. */
1593 if (!searchLevel(result_set, vec, bestChild, mindist, dists, epsError)) {
1594 // the resultset doesn't want to receive any more points, we're done
1595 // searching!
1596 return false;
1597 }
1598
1599 DistanceType dst = dists[idx];
1600 mindist = mindist + cut_dist - dst;
1601 dists[idx] = cut_dist;
1602 if (mindist * epsError <= result_set.worstDist()) {
1603 if (!searchLevel(result_set, vec, otherChild, mindist, dists, epsError)) {
1604 // the resultset doesn't want to receive any more points, we're
1605 // done searching!
1606 return false;
1607 }
1608 }
1609 dists[idx] = dst;
1610 return true;
1611 }
1612
1613 public:
1619 void saveIndex(std::ostream& stream) const { Base::saveIndex(*this, stream); }
1620
1626 void loadIndex(std::istream& stream) { Base::loadIndex(*this, stream); }
1627
1628}; // class KDTree
1629
1667template <typename Distance, class DatasetAdaptor, int32_t DIM = -1, typename IndexType = uint32_t>
1668class KDTreeSingleIndexDynamicAdaptor_ : public KDTreeBaseClass<KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM, IndexType>,
1669 Distance, DatasetAdaptor, DIM, IndexType> {
1670 public:
1674 const DatasetAdaptor& dataset_;
1675
1677
1678 std::vector<int>& treeIndex_;
1679
1680 Distance distance_;
1681
1683 Distance, DatasetAdaptor, DIM, IndexType>;
1684
1685 using ElementType = typename Base::ElementType;
1686 using DistanceType = typename Base::DistanceType;
1687
1688 using Offset = typename Base::Offset;
1689 using Size = typename Base::Size;
1690 using Dimension = typename Base::Dimension;
1691
1692 using Node = typename Base::Node;
1693 using NodePtr = Node*;
1694
1695 using Interval = typename Base::Interval;
1698 using BoundingBox = typename Base::BoundingBox;
1699
1702 using distance_vector_t = typename Base::distance_vector_t;
1703
1719 KDTreeSingleIndexDynamicAdaptor_(const Dimension dimensionality, const DatasetAdaptor& inputData, std::vector<int>& treeIndex,
1721 : dataset_(inputData), index_params_(params), treeIndex_(treeIndex), distance_(inputData) {
1722 Base::size_ = 0;
1723 Base::size_at_index_build_ = 0;
1724 for (auto& v : Base::root_bbox_) v = {};
1725 Base::dim_ = dimensionality;
1726 if (DIM > 0) Base::dim_ = DIM;
1727 Base::leaf_max_size_ = params.leaf_max_size;
1728 if (params.n_thread_build > 0) {
1729 Base::n_thread_build_ = params.n_thread_build;
1730 } else {
1731 Base::n_thread_build_ = std::max(std::thread::hardware_concurrency(), 1u);
1732 }
1733 }
1734
1737
1741 std::swap(Base::vAcc_, tmp.Base::vAcc_);
1742 std::swap(Base::leaf_max_size_, tmp.Base::leaf_max_size_);
1743 std::swap(index_params_, tmp.index_params_);
1744 std::swap(treeIndex_, tmp.treeIndex_);
1745 std::swap(Base::size_, tmp.Base::size_);
1746 std::swap(Base::size_at_index_build_, tmp.Base::size_at_index_build_);
1747 std::swap(Base::root_node_, tmp.Base::root_node_);
1748 std::swap(Base::root_bbox_, tmp.Base::root_bbox_);
1749 std::swap(Base::pool_, tmp.Base::pool_);
1750 return *this;
1751 }
1752
1756 void buildIndex() {
1757 Base::size_ = Base::vAcc_.size();
1758 this->freeIndex(*this);
1759 Base::size_at_index_build_ = Base::size_;
1760 if (Base::size_ == 0) return;
1761 computeBoundingBox(Base::root_bbox_);
1762 // construct the tree
1763 if (Base::n_thread_build_ == 1) {
1764 Base::root_node_ = this->divideTree(*this, 0, Base::size_, Base::root_bbox_);
1765 } else {
1766 std::atomic<unsigned int> thread_count(0u);
1767 std::mutex mutex;
1768 Base::root_node_ = this->divideTreeConcurrent(*this, 0, Base::size_, Base::root_bbox_, thread_count, mutex);
1769 }
1770 }
1771
1795 template <typename RESULTSET>
1796 bool findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParameters& searchParams = {}) const {
1797 assert(vec);
1798 if (this->size(*this) == 0) return false;
1799 if (!Base::root_node_) return false;
1800 float epsError = 1 + searchParams.eps;
1801
1802 // fixed or variable-sized container (depending on DIM)
1803 distance_vector_t dists;
1804 // Fill it with zeros.
1805 assign(dists, (DIM > 0 ? DIM : Base::dim_), static_cast<typename distance_vector_t::value_type>(0));
1806 DistanceType dist = this->computeInitialDistances(*this, vec, dists);
1807 searchLevel(result, vec, Base::root_node_, dist, dists, epsError);
1808 return result.full();
1809 }
1810
1825 Size knnSearch(const ElementType* query_point, const Size num_closest, IndexType* out_indices, DistanceType* out_distances,
1826 const SearchParameters& searchParams = {}) const {
1828 resultSet.init(out_indices, out_distances);
1829 findNeighbors(resultSet, query_point, searchParams);
1830 return resultSet.size();
1831 }
1832
1852 Size radiusSearch(const ElementType* query_point, const DistanceType& radius,
1853 std::vector<ResultItem<IndexType, DistanceType>>& IndicesDists, const SearchParameters& searchParams = {}) const {
1854 RadiusResultSet<DistanceType, IndexType> resultSet(radius, IndicesDists);
1855 const size_t nFound = radiusSearchCustomCallback(query_point, resultSet, searchParams);
1856 if (searchParams.sorted) std::sort(IndicesDists.begin(), IndicesDists.end(), IndexDist_Sorter());
1857 return nFound;
1858 }
1859
1865 template <class SEARCH_CALLBACK>
1866 Size radiusSearchCustomCallback(const ElementType* query_point, SEARCH_CALLBACK& resultSet,
1867 const SearchParameters& searchParams = {}) const {
1868 findNeighbors(resultSet, query_point, searchParams);
1869 return resultSet.size();
1870 }
1871
1874 public:
1876 const auto dims = (DIM > 0 ? DIM : Base::dim_);
1877 resize(bbox, dims);
1878
1879 if (dataset_.kdtree_get_bbox(bbox)) {
1880 // Done! It was implemented in derived class
1881 } else {
1882 const Size N = Base::size_;
1883 if (!N)
1884 throw std::runtime_error(
1885 "[nanoflann] computeBoundingBox() called but "
1886 "no data points found.");
1887 for (Dimension i = 0; i < dims; ++i) {
1888 bbox[i].low = bbox[i].high = this->dataset_get(*this, Base::vAcc_[0], i);
1889 }
1890 for (Offset k = 1; k < N; ++k) {
1891 for (Dimension i = 0; i < dims; ++i) {
1892 const auto val = this->dataset_get(*this, Base::vAcc_[k], i);
1893 if (val < bbox[i].low) bbox[i].low = val;
1894 if (val > bbox[i].high) bbox[i].high = val;
1895 }
1896 }
1897 }
1898 }
1899
1904 template <class RESULTSET>
1905 void searchLevel(RESULTSET& result_set, const ElementType* vec, const NodePtr node, DistanceType mindist, distance_vector_t& dists,
1906 const float epsError) const {
1907 /* If this is a leaf node, then do check and return. */
1908 if ((node->child1 == nullptr) && (node->child2 == nullptr)) {
1909 DistanceType worst_dist = result_set.worstDist();
1910 for (Offset i = node->node_type.lr.left; i < node->node_type.lr.right; ++i) {
1911 const IndexType index = Base::vAcc_[i]; // reorder... : i;
1912 if (treeIndex_[index] == -1) continue;
1913 DistanceType dist = distance_.evalMetric(vec, index, (DIM > 0 ? DIM : Base::dim_));
1914 if (dist < worst_dist) {
1915 if (!result_set.addPoint(static_cast<typename RESULTSET::DistanceType>(dist),
1916 static_cast<typename RESULTSET::IndexType>(Base::vAcc_[i]))) {
1917 // the resultset doesn't want to receive any more
1918 // points, we're done searching!
1919 return; // false;
1920 }
1921 }
1922 }
1923 return;
1924 }
1925
1926 /* Which child branch should be taken first? */
1927 Dimension idx = node->node_type.sub.divfeat;
1928 ElementType val = vec[idx];
1929 DistanceType diff1 = val - node->node_type.sub.divlow;
1930 DistanceType diff2 = val - node->node_type.sub.divhigh;
1931
1932 NodePtr bestChild;
1933 NodePtr otherChild;
1934 DistanceType cut_dist;
1935 if ((diff1 + diff2) < 0) {
1936 bestChild = node->child1;
1937 otherChild = node->child2;
1938 cut_dist = distance_.accum_dist(val, node->node_type.sub.divhigh, idx);
1939 } else {
1940 bestChild = node->child2;
1941 otherChild = node->child1;
1942 cut_dist = distance_.accum_dist(val, node->node_type.sub.divlow, idx);
1943 }
1944
1945 /* Call recursively to search next level down. */
1946 searchLevel(result_set, vec, bestChild, mindist, dists, epsError);
1947
1948 DistanceType dst = dists[idx];
1949 mindist = mindist + cut_dist - dst;
1950 dists[idx] = cut_dist;
1951 if (mindist * epsError <= result_set.worstDist()) {
1952 searchLevel(result_set, vec, otherChild, mindist, dists, epsError);
1953 }
1954 dists[idx] = dst;
1955 }
1956
1957 public:
1963 void saveIndex(std::ostream& stream) { saveIndex(*this, stream); }
1964
1970 void loadIndex(std::istream& stream) { loadIndex(*this, stream); }
1971};
1972
1987template <typename Distance, class DatasetAdaptor, int32_t DIM = -1, typename IndexType = uint32_t>
1989 public:
1990 using ElementType = typename Distance::ElementType;
1991 using DistanceType = typename Distance::DistanceType;
1992
1996
1997 protected:
2001
2005 const DatasetAdaptor& dataset_;
2006
2009 std::vector<int> treeIndex_;
2010 std::unordered_set<int> removedPoints_;
2011
2013
2015
2017 std::vector<index_container_t> index_;
2018
2019 public:
2022 const std::vector<index_container_t>& getAllIndices() const { return index_; }
2023
2024 private:
2026 int First0Bit(IndexType num) {
2027 int pos = 0;
2028 while (num & 1) {
2029 num = num >> 1;
2030 pos++;
2031 }
2032 return pos;
2033 }
2034
2036 void init() {
2037 using my_kd_tree_t = KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM, IndexType>;
2038 std::vector<my_kd_tree_t> index(treeCount_, my_kd_tree_t(dim_ /*dim*/, dataset_, treeIndex_, index_params_));
2039 index_ = index;
2040 }
2041
2042 public:
2043 Distance distance_;
2044
2060 explicit KDTreeSingleIndexDynamicAdaptor(const int dimensionality, const DatasetAdaptor& inputData,
2062 const size_t maximumPointCount = 1000000000U)
2063 : dataset_(inputData), index_params_(params), distance_(inputData) {
2064 treeCount_ = static_cast<size_t>(std::log2(maximumPointCount)) + 1;
2065 pointCount_ = 0U;
2066 dim_ = dimensionality;
2067 treeIndex_.clear();
2068 if (DIM > 0) dim_ = DIM;
2069 leaf_max_size_ = params.leaf_max_size;
2070 init();
2071 const size_t num_initial_points = dataset_.kdtree_get_point_count();
2072 if (num_initial_points > 0) {
2073 addPoints(0, num_initial_points - 1);
2074 }
2075 }
2076
2079
2081 void addPoints(IndexType start, IndexType end) {
2082 const Size count = end - start + 1;
2083 int maxIndex = 0;
2084 treeIndex_.resize(treeIndex_.size() + count);
2085 for (IndexType idx = start; idx <= end; idx++) {
2086 const int pos = First0Bit(pointCount_);
2087 maxIndex = std::max(pos, maxIndex);
2088 treeIndex_[pointCount_] = pos;
2089
2090 const auto it = removedPoints_.find(idx);
2091 if (it != removedPoints_.end()) {
2092 removedPoints_.erase(it);
2093 treeIndex_[idx] = pos;
2094 }
2095
2096 for (int i = 0; i < pos; i++) {
2097 for (int j = 0; j < static_cast<int>(index_[i].vAcc_.size()); j++) {
2098 index_[pos].vAcc_.push_back(index_[i].vAcc_[j]);
2099 if (treeIndex_[index_[i].vAcc_[j]] != -1) treeIndex_[index_[i].vAcc_[j]] = pos;
2100 }
2101 index_[i].vAcc_.clear();
2102 }
2103 index_[pos].vAcc_.push_back(idx);
2104 pointCount_++;
2105 }
2106
2107 for (int i = 0; i <= maxIndex; ++i) {
2108 index_[i].freeIndex(index_[i]);
2109 if (!index_[i].vAcc_.empty()) index_[i].buildIndex();
2110 }
2111 }
2112
2114 void removePoint(size_t idx) {
2115 if (idx >= pointCount_) return;
2116 removedPoints_.insert(idx);
2117 treeIndex_[idx] = -1;
2118 }
2119
2136 template <typename RESULTSET>
2137 bool findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParameters& searchParams = {}) const {
2138 for (size_t i = 0; i < treeCount_; i++) {
2139 index_[i].findNeighbors(result, &vec[0], searchParams);
2140 }
2141 return result.full();
2142 }
2143};
2144
2170template <class MatrixType, int32_t DIM = -1, class Distance = nanoflann::metric_L2, bool row_major = true>
2173 using num_t = typename MatrixType::Scalar;
2174 using IndexType = typename MatrixType::Index;
2175 using metric_t = typename Distance::template traits<num_t, self_t, IndexType>::distance_t;
2176
2177 using index_t =
2179
2182
2183 using Offset = typename index_t::Offset;
2184 using Size = typename index_t::Size;
2186
2188 explicit KDTreeEigenMatrixAdaptor(const Dimension dimensionality, const std::reference_wrapper<const MatrixType>& mat,
2189 const int leaf_max_size = 10)
2190 : m_data_matrix(mat) {
2191 const auto dims = row_major ? mat.get().cols() : mat.get().rows();
2192 if (static_cast<Dimension>(dims) != dimensionality)
2193 throw std::runtime_error(
2194 "Error: 'dimensionality' must match column count in data "
2195 "matrix");
2196 if (DIM > 0 && static_cast<int32_t>(dims) != DIM)
2197 throw std::runtime_error(
2198 "Data set dimensionality does not match the 'DIM' template "
2199 "argument");
2200 index_ = new index_t(dims, *this /* adaptor */, nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size));
2201 }
2202
2203 public:
2206
2207 ~KDTreeEigenMatrixAdaptor() { delete index_; }
2208
2209 const std::reference_wrapper<const MatrixType> m_data_matrix;
2210
2219 void query(const num_t* query_point, const Size num_closest, IndexType* out_indices, num_t* out_distances) const {
2220 nanoflann::KNNResultSet<num_t, IndexType> resultSet(num_closest);
2221 resultSet.init(out_indices, out_distances);
2222 index_->findNeighbors(resultSet, query_point);
2223 }
2224
2228 const self_t& derived() const { return *this; }
2229 self_t& derived() { return *this; }
2230
2231 // Must return the number of data points
2233 if (row_major)
2234 return m_data_matrix.get().rows();
2235 else
2236 return m_data_matrix.get().cols();
2237 }
2238
2239 // Returns the dim'th component of the idx'th point in the class:
2240 num_t kdtree_get_pt(const IndexType idx, size_t dim) const {
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>
2253 bool kdtree_get_bbox(BBOX& /*bb*/) const {
2254 return false;
2255 }
2256
2259}; // end of KDTreeEigenMatrixAdaptor
// end of grouping
2263} // namespace nanoflann
2264
2265// KDTreeVectorOfVectorsAdaptor.h //
2266
2267/***********************************************************************
2268 * Software License Agreement (BSD License)
2269 *
2270 * Copyright 2011-16 Jose Luis Blanco (joseluisblancoc@gmail.com).
2271 * All rights reserved.
2272 *
2273 * Redistribution and use in source and binary forms, with or without
2274 * modification, are permitted provided that the following conditions
2275 * are met:
2276 *
2277 * 1. Redistributions of source code must retain the above copyright
2278 * notice, this list of conditions and the following disclaimer.
2279 * 2. Redistributions in binary form must reproduce the above copyright
2280 * notice, this list of conditions and the following disclaimer in the
2281 * documentation and/or other materials provided with the distribution.
2282 *
2283 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2284 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2285 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2286 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2287 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2288 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2289 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2290 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2291 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2292 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2293 *************************************************************************/
2294
2295// ===== This example shows how to use nanoflann with these types of containers:
2296// using my_vector_of_vectors_t = std::vector<std::vector<double> > ;
2297//
2298// The next one requires #include <Eigen/Dense>
2299// using my_vector_of_vectors_t = std::vector<Eigen::VectorXd> ;
2300// =============================================================================
2301
2313template <class VectorOfVectorsType, typename num_t = double, int DIM = -1, class Distance = nanoflann::metric_L2,
2314 typename IndexType = size_t>
2317 using metric_t = typename Distance::template traits<num_t, self_t>::distance_t;
2319
2322 index_t* index = nullptr;
2323
2326 KDTreeVectorOfVectorsAdaptor(const size_t /* dimensionality */, const VectorOfVectorsType& mat, const int leaf_max_size = 10,
2327 const unsigned int n_thread_build = 1)
2328 : m_data(mat) {
2329 assert(mat.size() != 0 && mat[0].size() != 0);
2330 const size_t dims = mat[0].size();
2331 if (DIM > 0 && static_cast<int>(dims) != DIM)
2332 throw std::runtime_error(
2333 "Data set dimensionality does not match the 'DIM' template "
2334 "argument");
2335 index = new index_t(
2336 static_cast<int>(dims), *this /* adaptor */,
2338 }
2339
2341
2342 const VectorOfVectorsType& m_data;
2343
2349 inline void query(const num_t* query_point, const size_t num_closest, IndexType* out_indices, num_t* out_distances_sq) const {
2350 nanoflann::KNNResultSet<num_t, IndexType> resultSet(num_closest);
2351 resultSet.init(out_indices, out_distances_sq);
2352 index->findNeighbors(resultSet, query_point);
2353 }
2354
2358 const self_t& derived() const { return *this; }
2359 self_t& derived() { return *this; }
2360
2361 // Must return the number of data points
2362 inline size_t kdtree_get_point_count() const { return m_data.size(); }
2363
2364 // Returns the dim'th component of the idx'th point in the class:
2365 inline num_t kdtree_get_pt(const size_t idx, const size_t dim) const { return m_data[idx][dim]; }
2366
2367 // Optional bounding-box computation: return false to default to a standard
2368 // bbox computation loop.
2369 // Return true if the BBOX was already computed by the class and returned
2370 // in "bb" so it can be avoided to redo it again. Look at bb.size() to
2371 // find out the expected dimensionality (e.g. 2 or 3 for point clouds)
2372 template <class BBOX>
2373 bool kdtree_get_bbox(BBOX& /*bb*/) const {
2374 return false;
2375 }
2376
2379}; // end of KDTreeVectorOfVectorsAdaptor
2380
2381// utils.h of nanoflann //
2382
2383template <typename T>
2385 struct Point {
2386 T x, y, z;
2387 };
2388
2389 using coord_t = T;
2390
2391 std::vector<Point> pts;
2392
2393 // Must return the number of data points
2394 inline size_t kdtree_get_point_count() const { return pts.size(); }
2395
2396 // Returns the dim'th component of the idx'th point in the class:
2397 // Since this is inlined and the "dim" argument is typically an immediate
2398 // value, the
2399 // "if/else's" are actually solved at compile time.
2400 inline T kdtree_get_pt(const size_t idx, const size_t dim) const {
2401 if (dim == 0)
2402 return pts[idx].x;
2403 else if (dim == 1)
2404 return pts[idx].y;
2405 else
2406 return pts[idx].z;
2407 }
2408
2409 // Optional bounding-box computation: return false to default to a standard
2410 // bbox computation loop.
2411 // Return true if the BBOX was already computed by the class and returned
2412 // in "bb" so it can be avoided to redo it again. Look at bb.size() to
2413 // find out the expected dimensionality (e.g. 2 or 3 for point clouds)
2414 template <class BBOX>
2415 bool kdtree_get_bbox(BBOX& /* bb */) const {
2416 return false;
2417 }
2418};
2419
2420template <typename T>
2421void generateRandomPointCloudRanges(PointCloud<T>& pc, const size_t N, const T max_range_x, const T max_range_y, const T max_range_z) {
2422 // Generating Random Point Cloud
2423 pc.pts.resize(N);
2424 for (size_t i = 0; i < N; i++) {
2425 pc.pts[i].x = max_range_x * (rand() % 1000) / T(1000);
2426 pc.pts[i].y = max_range_y * (rand() % 1000) / T(1000);
2427 pc.pts[i].z = max_range_z * (rand() % 1000) / T(1000);
2428 }
2429}
2430
2431template <typename T>
2432void generateRandomPointCloud(PointCloud<T>& pc, const size_t N, const T max_range = 10) {
2433 generateRandomPointCloudRanges(pc, N, max_range, max_range, max_range);
2434}
2435
2436// This is an exampleof a custom data set class
2437template <typename T>
2439 struct Point {
2440 T w, x, y, z;
2441 };
2442
2443 std::vector<Point> pts;
2444
2445 // Must return the number of data points
2446 inline size_t kdtree_get_point_count() const { return pts.size(); }
2447
2448 // Returns the dim'th component of the idx'th point in the class:
2449 // Since this is inlined and the "dim" argument is typically an immediate
2450 // value, the
2451 // "if/else's" are actually solved at compile time.
2452 inline T kdtree_get_pt(const size_t idx, const size_t dim) const {
2453 if (dim == 0)
2454 return pts[idx].w;
2455 else if (dim == 1)
2456 return pts[idx].x;
2457 else if (dim == 2)
2458 return pts[idx].y;
2459 else
2460 return pts[idx].z;
2461 }
2462
2463 // Optional bounding-box computation: return false to default to a standard
2464 // bbox computation loop.
2465 // Return true if the BBOX was already computed by the class and returned
2466 // in "bb" so it can be avoided to redo it again. Look at bb.size() to
2467 // find out the expected dimensionality (e.g. 2 or 3 for point clouds)
2468 template <class BBOX>
2469 bool kdtree_get_bbox(BBOX& /* bb */) const {
2470 return false;
2471 }
2472};
2473
2474template <typename T>
2476 // Generating Random Quaternions
2477 point.pts.resize(N);
2478 T theta, X, Y, Z, sinAng, cosAng, mag;
2479 for (size_t i = 0; i < N; i++) {
2480 theta = static_cast<T>(nanoflann::pi_const<double>() * (((double)rand()) / RAND_MAX));
2481 // Generate random value in [-1, 1]
2482 X = static_cast<T>(2 * (((double)rand()) / RAND_MAX) - 1);
2483 Y = static_cast<T>(2 * (((double)rand()) / RAND_MAX) - 1);
2484 Z = static_cast<T>(2 * (((double)rand()) / RAND_MAX) - 1);
2485 mag = sqrt(X * X + Y * Y + Z * Z);
2486 X /= mag;
2487 Y /= mag;
2488 Z /= mag;
2489 cosAng = cos(theta / 2);
2490 sinAng = sin(theta / 2);
2491 point.pts[i].w = cosAng;
2492 point.pts[i].x = X * sinAng;
2493 point.pts[i].y = Y * sinAng;
2494 point.pts[i].z = Z * sinAng;
2495 }
2496}
2497
2498// This is an exampleof a custom data set class
2499template <typename T>
2501 struct Point {
2503 };
2504
2505 std::vector<Point> pts;
2506
2507 // Must return the number of data points
2508 inline size_t kdtree_get_point_count() const { return pts.size(); }
2509
2510 // Returns the dim'th component of the idx'th point in the class:
2511 // Since this is inlined and the "dim" argument is typically an immediate
2512 // value, the
2513 // "if/else's" are actually solved at compile time.
2514 inline T kdtree_get_pt(const size_t idx, const size_t dim = 0) const { return pts[idx].theta; }
2515
2516 // Optional bounding-box computation: return false to default to a standard
2517 // bbox computation loop.
2518 // Return true if the BBOX was already computed by the class and returned
2519 // in "bb" so it can be avoided to redo it again. Look at bb.size() to
2520 // find out the expected dimensionality (e.g. 2 or 3 for point clouds)
2521 template <class BBOX>
2522 bool kdtree_get_bbox(BBOX& /* bb */) const {
2523 return false;
2524 }
2525};
2526
2527template <typename T>
2529 // Generating Random Orientations
2530 point.pts.resize(N);
2531 for (size_t i = 0; i < N; i++) {
2532 point.pts[i].theta =
2533 static_cast<T>((2 * nanoflann::pi_const<double>() * (((double)rand()) / RAND_MAX)) - nanoflann::pi_const<double>());
2534 }
2535}
2536
2537inline void dump_mem_usage() {
2538 FILE* f = fopen("/proc/self/statm", "rt");
2539 if (!f) return;
2540 char str[300];
2541 size_t n = fread(str, 1, 200, f);
2542 str[n] = 0;
2543 printf("MEM: %s\n", str);
2544 fclose(f);
2545}
Definition nanoflann.hpp:825
Size usedMemory(Derived &obj)
Definition nanoflann.hpp:922
DistanceType computeInitialDistances(const Derived &obj, const ElementType *vec, distance_vector_t &dists) const
Definition nanoflann.hpp:1168
NodePtr divideTreeConcurrent(Derived &obj, const Offset left, const Offset right, BoundingBox &bbox, std::atomic< unsigned int > &thread_count, std::mutex &mutex)
Definition nanoflann.hpp:1004
void planeSplit(const Derived &obj, const Offset ind, const Size count, const Dimension cutfeat, const DistanceType &cutval, Offset &lim1, Offset &lim2)
Definition nanoflann.hpp:1139
typename array_or_vector< DIM, DistanceType >::type distance_vector_t
Definition nanoflann.hpp:893
std::vector< IndexType > vAcc_
Definition nanoflann.hpp:841
void computeMinMax(const Derived &obj, Offset ind, Size count, Dimension element, ElementType &min_elem, ElementType &max_elem)
Definition nanoflann.hpp:927
static void load_tree(Derived &obj, std::istream &stream, NodePtr &tree)
Definition nanoflann.hpp:1195
Size size(const Derived &obj) const
Definition nanoflann.hpp:908
void freeIndex(Derived &obj)
Definition nanoflann.hpp:829
void loadIndex(Derived &obj, std::istream &stream)
Definition nanoflann.hpp:1225
typename array_or_vector< DIM, Interval >::type BoundingBox
Definition nanoflann.hpp:889
BoundingBox root_bbox_
Definition nanoflann.hpp:896
typename decltype(vAcc_)::size_type Size
Definition nanoflann.hpp:844
void saveIndex(const Derived &obj, std::ostream &stream) const
Definition nanoflann.hpp:1211
void middleSplit_(const Derived &obj, const Offset ind, const Size count, Offset &index, Dimension &cutfeat, DistanceType &cutval, const BoundingBox &bbox)
Definition nanoflann.hpp:1081
typename Distance::ElementType ElementType
Definition nanoflann.hpp:835
PooledAllocator pool_
Definition nanoflann.hpp:905
NodePtr divideTree(Derived &obj, const Offset left, const Offset right, BoundingBox &bbox)
Definition nanoflann.hpp:944
typename Distance::DistanceType DistanceType
Definition nanoflann.hpp:836
ElementType dataset_get(const Derived &obj, IndexType element, Dimension component) const
Helper accessor to the dataset points:
Definition nanoflann.hpp:914
Size veclen(const Derived &obj)
Definition nanoflann.hpp:911
static void save_tree(const Derived &obj, std::ostream &stream, const NodeConstPtr tree)
Definition nanoflann.hpp:1185
int32_t Dimension
Definition nanoflann.hpp:845
typename decltype(vAcc_)::size_type Offset
Definition nanoflann.hpp:843
Definition nanoflann.hpp:1278
const KDTreeSingleIndexAdaptorParams indexParams
Definition nanoflann.hpp:1286
Size radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1481
Size rknnSearch(const ElementType *query_point, const Size num_closest, IndexType *out_indices, DistanceType *out_distances, const DistanceType &radius) const
Definition nanoflann.hpp:1503
KDTreeSingleIndexAdaptor(const KDTreeSingleIndexAdaptor< Distance, DatasetAdaptor, DIM, IndexType > &)=delete
KDTreeSingleIndexAdaptor(const Dimension dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams &params, Args &&... args)
Definition nanoflann.hpp:1334
Distance distance_
Definition nanoflann.hpp:1288
typename Base::Size Size
Definition nanoflann.hpp:1294
typename Base::ElementType ElementType
Definition nanoflann.hpp:1297
Size radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< ResultItem< IndexType, DistanceType > > &IndicesDists, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1467
typename Base::distance_vector_t distance_vector_t
Definition nanoflann.hpp:1311
typename nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexAdaptor< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType > Base
Definition nanoflann.hpp:1291
void loadIndex(std::istream &stream)
Definition nanoflann.hpp:1626
typename Base::Node Node
Definition nanoflann.hpp:1300
typename Base::BoundingBox BoundingBox
Definition nanoflann.hpp:1307
typename Base::DistanceType DistanceType
Definition nanoflann.hpp:1298
KDTreeSingleIndexAdaptor(const Dimension dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams &params={})
Definition nanoflann.hpp:1340
typename Base::Interval Interval
Definition nanoflann.hpp:1303
Size knnSearch(const ElementType *query_point, const Size num_closest, IndexType *out_indices, DistanceType *out_distances) const
Definition nanoflann.hpp:1441
typename Base::Dimension Dimension
Definition nanoflann.hpp:1295
void init_vind()
Definition nanoflann.hpp:1516
const DatasetAdaptor & dataset_
Definition nanoflann.hpp:1284
void saveIndex(std::ostream &stream) const
Definition nanoflann.hpp:1619
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1407
Node * NodePtr
Definition nanoflann.hpp:1301
typename Base::Offset Offset
Definition nanoflann.hpp:1293
void buildIndex()
Definition nanoflann.hpp:1369
bool searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindist, distance_vector_t &dists, const float epsError) const
Definition nanoflann.hpp:1554
void computeBoundingBox(BoundingBox &bbox)
Definition nanoflann.hpp:1523
Definition nanoflann.hpp:1669
Size radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< ResultItem< IndexType, DistanceType > > &IndicesDists, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1852
KDTreeSingleIndexDynamicAdaptor_(const Dimension dimensionality, const DatasetAdaptor &inputData, std::vector< int > &treeIndex, const KDTreeSingleIndexAdaptorParams &params=KDTreeSingleIndexAdaptorParams())
Definition nanoflann.hpp:1719
std::vector< int > & treeIndex_
Definition nanoflann.hpp:1678
typename Base::Dimension Dimension
Definition nanoflann.hpp:1690
typename Base::BoundingBox BoundingBox
Definition nanoflann.hpp:1698
const DatasetAdaptor & dataset_
The source of our data.
Definition nanoflann.hpp:1674
Size radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1866
typename Base::DistanceType DistanceType
Definition nanoflann.hpp:1686
KDTreeSingleIndexAdaptorParams index_params_
Definition nanoflann.hpp:1676
KDTreeSingleIndexDynamicAdaptor_(const KDTreeSingleIndexDynamicAdaptor_ &rhs)=default
typename Base::Offset Offset
Definition nanoflann.hpp:1688
void buildIndex()
Definition nanoflann.hpp:1756
typename Base::ElementType ElementType
Definition nanoflann.hpp:1685
void saveIndex(std::ostream &stream)
Definition nanoflann.hpp:1963
void computeBoundingBox(BoundingBox &bbox)
Definition nanoflann.hpp:1875
typename Base::Node Node
Definition nanoflann.hpp:1692
typename Base::Size Size
Definition nanoflann.hpp:1689
Node * NodePtr
Definition nanoflann.hpp:1693
typename Base::distance_vector_t distance_vector_t
Definition nanoflann.hpp:1702
void loadIndex(std::istream &stream)
Definition nanoflann.hpp:1970
typename Base::Interval Interval
Definition nanoflann.hpp:1695
Size knnSearch(const ElementType *query_point, const Size num_closest, IndexType *out_indices, DistanceType *out_distances, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1825
typename nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType > Base
Definition nanoflann.hpp:1683
void searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindist, distance_vector_t &dists, const float epsError) const
Definition nanoflann.hpp:1905
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:1796
Distance distance_
Definition nanoflann.hpp:1680
KDTreeSingleIndexDynamicAdaptor_ operator=(const KDTreeSingleIndexDynamicAdaptor_ &rhs)
Definition nanoflann.hpp:1739
Definition nanoflann.hpp:1988
typename KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM >::Dimension Dimension
Definition nanoflann.hpp:1995
typename Distance::ElementType ElementType
Definition nanoflann.hpp:1990
Size treeCount_
Definition nanoflann.hpp:1999
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParameters &searchParams={}) const
Definition nanoflann.hpp:2137
typename Distance::DistanceType DistanceType
Definition nanoflann.hpp:1991
Size leaf_max_size_
Definition nanoflann.hpp:1998
Distance distance_
Definition nanoflann.hpp:2043
const DatasetAdaptor & dataset_
The source of our data.
Definition nanoflann.hpp:2005
void removePoint(size_t idx)
Definition nanoflann.hpp:2114
std::unordered_set< int > removedPoints_
Definition nanoflann.hpp:2010
Size pointCount_
Definition nanoflann.hpp:2000
typename KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM >::Offset Offset
Definition nanoflann.hpp:1993
void addPoints(IndexType start, IndexType end)
Definition nanoflann.hpp:2081
std::vector< index_container_t > index_
Definition nanoflann.hpp:2017
KDTreeSingleIndexDynamicAdaptor(const int dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams &params=KDTreeSingleIndexAdaptorParams(), const size_t maximumPointCount=1000000000U)
Definition nanoflann.hpp:2060
std::vector< int > treeIndex_
Definition nanoflann.hpp:2009
const std::vector< index_container_t > & getAllIndices() const
Definition nanoflann.hpp:2022
KDTreeSingleIndexAdaptorParams index_params_
Definition nanoflann.hpp:2012
Dimension dim_
Dimensionality of each data point.
Definition nanoflann.hpp:2014
KDTreeSingleIndexDynamicAdaptor(const KDTreeSingleIndexDynamicAdaptor< Distance, DatasetAdaptor, DIM, IndexType > &)=delete
typename KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM >::Size Size
Definition nanoflann.hpp:1994
Definition nanoflann.hpp:146
_CountType CountType
Definition nanoflann.hpp:150
void init(IndexType *indices_, DistanceType *dists_)
Definition nanoflann.hpp:161
_DistanceType DistanceType
Definition nanoflann.hpp:148
bool addPoint(DistanceType dist, IndexType index)
Definition nanoflann.hpp:177
CountType size() const
Definition nanoflann.hpp:168
bool empty() const
Definition nanoflann.hpp:169
KNNResultSet(CountType capacity_)
Definition nanoflann.hpp:159
_IndexType IndexType
Definition nanoflann.hpp:149
DistanceType worstDist() const
Definition nanoflann.hpp:204
bool full() const
Definition nanoflann.hpp:170
Definition nanoflann.hpp:680
~PooledAllocator()
Definition nanoflann.hpp:717
void free_all()
Definition nanoflann.hpp:720
void * malloc(const size_t req_size)
Definition nanoflann.hpp:734
T * allocate(const size_t count=1)
Definition nanoflann.hpp:785
PooledAllocator()
Definition nanoflann.hpp:712
Definition nanoflann.hpp:209
CountType size() const
Definition nanoflann.hpp:233
bool addPoint(DistanceType dist, IndexType index)
Definition nanoflann.hpp:242
void init(IndexType *indices_, DistanceType *dists_)
Definition nanoflann.hpp:226
RKNNResultSet(CountType capacity_, DistanceType maximumSearchDistanceSquared_)
Definition nanoflann.hpp:223
bool empty() const
Definition nanoflann.hpp:234
_CountType CountType
Definition nanoflann.hpp:213
_IndexType IndexType
Definition nanoflann.hpp:212
_DistanceType DistanceType
Definition nanoflann.hpp:211
bool full() const
Definition nanoflann.hpp:235
DistanceType worstDist() const
Definition nanoflann.hpp:269
Definition nanoflann.hpp:302
void init()
Definition nanoflann.hpp:317
const DistanceType radius
Definition nanoflann.hpp:308
RadiusResultSet(DistanceType radius_, std::vector< ResultItem< IndexType, DistanceType > > &indices_dists)
Definition nanoflann.hpp:312
size_t empty() const
Definition nanoflann.hpp:321
DistanceType worstDist() const
Definition nanoflann.hpp:335
ResultItem< IndexType, DistanceType > worst_item() const
Definition nanoflann.hpp:341
_DistanceType DistanceType
Definition nanoflann.hpp:304
bool full() const
Definition nanoflann.hpp:323
size_t size() const
Definition nanoflann.hpp:320
std::vector< ResultItem< IndexType, DistanceType > > & m_indices_dists
Definition nanoflann.hpp:310
void clear()
Definition nanoflann.hpp:318
_IndexType IndexType
Definition nanoflann.hpp:305
bool addPoint(DistanceType dist, IndexType index)
Definition nanoflann.hpp:330
void load_value(std::istream &stream, T &value)
Definition nanoflann.hpp:368
void save_value(std::ostream &stream, const T &value)
Definition nanoflann.hpp:356
std::enable_if< has_assign< Container >::value, void >::type assign(Container &c, const size_t nElements, const T &value)
Definition nanoflann.hpp:129
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:112
std::underlying_type< KDTreeSingleIndexAdaptorFlags >::type operator&(KDTreeSingleIndexAdaptorFlags lhs, KDTreeSingleIndexAdaptorFlags rhs)
Definition nanoflann.hpp:635
KDTreeSingleIndexAdaptorFlags
Definition nanoflann.hpp:633
Definition nanoflann.hpp:82
void generateRandomPointCloud(PointCloud< T > &pc, const size_t N, const T max_range=10)
Definition nanoflann.hpp:2432
void dump_mem_usage()
Definition nanoflann.hpp:2537
void generateRandomPointCloud_Quat(PointCloud_Quat< T > &point, const size_t N)
Definition nanoflann.hpp:2475
void generateRandomPointCloudRanges(PointCloud< T > &pc, const size_t N, const T max_range_x, const T max_range_y, const T max_range_z)
Definition nanoflann.hpp:2421
void generateRandomPointCloud_Orient(PointCloud_Orient< T > &point, const size_t N)
Definition nanoflann.hpp:2528
Definition nanoflann.hpp:2315
KDTreeVectorOfVectorsAdaptor(const size_t, const VectorOfVectorsType &mat, const int leaf_max_size=10, const unsigned int n_thread_build=1)
Definition nanoflann.hpp:2326
void query(const num_t *query_point, const size_t num_closest, IndexType *out_indices, num_t *out_distances_sq) const
Definition nanoflann.hpp:2349
num_t kdtree_get_pt(const size_t idx, const size_t dim) const
Definition nanoflann.hpp:2365
size_t kdtree_get_point_count() const
Definition nanoflann.hpp:2362
const self_t & derived() const
Definition nanoflann.hpp:2358
const VectorOfVectorsType & m_data
Definition nanoflann.hpp:2342
typename Distance::template traits< num_t, self_t >::distance_t metric_t
Definition nanoflann.hpp:2317
self_t & derived()
Definition nanoflann.hpp:2359
bool kdtree_get_bbox(BBOX &) const
Definition nanoflann.hpp:2373
~KDTreeVectorOfVectorsAdaptor()
Definition nanoflann.hpp:2340
Definition nanoflann.hpp:2385
T x
Definition nanoflann.hpp:2386
Definition nanoflann.hpp:2501
T theta
Definition nanoflann.hpp:2502
Definition nanoflann.hpp:2500
size_t kdtree_get_point_count() const
Definition nanoflann.hpp:2508
bool kdtree_get_bbox(BBOX &) const
Definition nanoflann.hpp:2522
std::vector< Point > pts
Definition nanoflann.hpp:2505
T kdtree_get_pt(const size_t idx, const size_t dim=0) const
Definition nanoflann.hpp:2514
Definition nanoflann.hpp:2439
T w
Definition nanoflann.hpp:2440
Definition nanoflann.hpp:2438
bool kdtree_get_bbox(BBOX &) const
Definition nanoflann.hpp:2469
size_t kdtree_get_point_count() const
Definition nanoflann.hpp:2446
T kdtree_get_pt(const size_t idx, const size_t dim) const
Definition nanoflann.hpp:2452
std::vector< Point > pts
Definition nanoflann.hpp:2443
Definition nanoflann.hpp:2384
bool kdtree_get_bbox(BBOX &) const
Definition nanoflann.hpp:2415
std::vector< Point > pts
Definition nanoflann.hpp:2391
size_t kdtree_get_point_count() const
Definition nanoflann.hpp:2394
T coord_t
The type of each coordinate.
Definition nanoflann.hpp:2389
T kdtree_get_pt(const size_t idx, const size_t dim) const
Definition nanoflann.hpp:2400
Definition nanoflann.hpp:273
bool operator()(const PairType &p1, const PairType &p2) const
Definition nanoflann.hpp:276
Definition nanoflann.hpp:871
ElementType high
Definition nanoflann.hpp:872
Definition nanoflann.hpp:850
DistanceType divhigh
Definition nanoflann.hpp:860
Offset left
Definition nanoflann.hpp:855
Node * child1
Definition nanoflann.hpp:865
Dimension divfeat
Definition nanoflann.hpp:858
struct nanoflann::KDTreeBaseClass::Node::@1::leaf lr
struct nanoflann::KDTreeBaseClass::Node::@1::nonleaf sub
Node * child2
Definition nanoflann.hpp:865
union nanoflann::KDTreeBaseClass::Node::@1 node_type
Definition nanoflann.hpp:2171
void query(const num_t *query_point, const Size num_closest, IndexType *out_indices, num_t *out_distances) const
Definition nanoflann.hpp:2219
typename MatrixType::Scalar num_t
Definition nanoflann.hpp:2173
num_t kdtree_get_pt(const IndexType idx, size_t dim) const
Definition nanoflann.hpp:2240
Size kdtree_get_point_count() const
Definition nanoflann.hpp:2232
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:2188
typename index_t::Size Size
Definition nanoflann.hpp:2184
bool kdtree_get_bbox(BBOX &) const
Definition nanoflann.hpp:2253
const std::reference_wrapper< const MatrixType > m_data_matrix
Definition nanoflann.hpp:2209
KDTreeEigenMatrixAdaptor(const self_t &)=delete
const self_t & derived() const
Definition nanoflann.hpp:2228
index_t * index_
Definition nanoflann.hpp:2180
typename Distance::template traits< num_t, self_t, IndexType >::distance_t metric_t
Definition nanoflann.hpp:2175
self_t & derived()
Definition nanoflann.hpp:2229
typename MatrixType::Index IndexType
Definition nanoflann.hpp:2174
typename index_t::Dimension Dimension
Definition nanoflann.hpp:2185
typename index_t::Offset Offset
Definition nanoflann.hpp:2183
~KDTreeEigenMatrixAdaptor()
Definition nanoflann.hpp:2207
Definition nanoflann.hpp:642
KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size=10, KDTreeSingleIndexAdaptorFlags _flags=KDTreeSingleIndexAdaptorFlags::None, unsigned int _n_thread_build=1)
Definition nanoflann.hpp:643
size_t leaf_max_size
Definition nanoflann.hpp:648
unsigned int n_thread_build
Definition nanoflann.hpp:650
KDTreeSingleIndexAdaptorFlags flags
Definition nanoflann.hpp:649
Definition nanoflann.hpp:397
T ElementType
Definition nanoflann.hpp:398
DistanceType evalMetric(const T *a, const IndexType b_idx, size_t size, DistanceType worst_dist=-1) const
Definition nanoflann.hpp:405
const DataSource & data_source
Definition nanoflann.hpp:401
DistanceType accum_dist(const U a, const V b, const size_t) const
Definition nanoflann.hpp:432
_DistanceType DistanceType
Definition nanoflann.hpp:399
L1_Adaptor(const DataSource &_data_source)
Definition nanoflann.hpp:403
Definition nanoflann.hpp:448
_DistanceType DistanceType
Definition nanoflann.hpp:450
DistanceType accum_dist(const U a, const V b, const size_t) const
Definition nanoflann.hpp:484
DistanceType evalMetric(const T *a, const IndexType b_idx, size_t size, DistanceType worst_dist=-1) const
Definition nanoflann.hpp:456
T ElementType
Definition nanoflann.hpp:449
L2_Adaptor(const DataSource &_data_source)
Definition nanoflann.hpp:454
const DataSource & data_source
Definition nanoflann.hpp:452
Definition nanoflann.hpp:500
const DataSource & data_source
Definition nanoflann.hpp:504
DistanceType evalMetric(const T *a, const IndexType b_idx, size_t size) const
Definition nanoflann.hpp:508
DistanceType accum_dist(const U a, const V b, const size_t) const
Definition nanoflann.hpp:518
L2_Simple_Adaptor(const DataSource &_data_source)
Definition nanoflann.hpp:506
_DistanceType DistanceType
Definition nanoflann.hpp:502
T ElementType
Definition nanoflann.hpp:501
Definition nanoflann.hpp:384
Definition nanoflann.hpp:290
DistanceType second
Distance from sample to query point.
Definition nanoflann.hpp:295
ResultItem(const IndexType index, const DistanceType distance)
Definition nanoflann.hpp:292
IndexType first
Index of the sample in the dataset.
Definition nanoflann.hpp:294
Definition nanoflann.hpp:534
const DataSource & data_source
Definition nanoflann.hpp:538
_DistanceType DistanceType
Definition nanoflann.hpp:536
T ElementType
Definition nanoflann.hpp:535
DistanceType evalMetric(const T *a, const IndexType b_idx, size_t size) const
Definition nanoflann.hpp:542
SO2_Adaptor(const DataSource &_data_source)
Definition nanoflann.hpp:540
DistanceType accum_dist(const U a, const V b, const size_t) const
Definition nanoflann.hpp:549
Definition nanoflann.hpp:572
_DistanceType DistanceType
Definition nanoflann.hpp:574
L2_Simple_Adaptor< T, DataSource, DistanceType, IndexType > distance_L2_Simple
Definition nanoflann.hpp:576
T ElementType
Definition nanoflann.hpp:573
DistanceType evalMetric(const T *a, const IndexType b_idx, size_t size) const
Definition nanoflann.hpp:580
SO3_Adaptor(const DataSource &_data_source)
Definition nanoflann.hpp:578
DistanceType accum_dist(const U a, const V b, const size_t idx) const
Definition nanoflann.hpp:585
Definition nanoflann.hpp:654
SearchParameters(float eps_=0, bool sorted_=true)
Definition nanoflann.hpp:655
bool sorted
Definition nanoflann.hpp:658
float eps
search for eps-approximate neighbours (default: 0)
Definition nanoflann.hpp:657
std::vector< T > type
Definition nanoflann.hpp:805
Definition nanoflann.hpp:799
std::array< T, DIM > type
Definition nanoflann.hpp:800
Definition nanoflann.hpp:103
Definition nanoflann.hpp:97
Definition nanoflann.hpp:593
Definition nanoflann.hpp:591
Definition nanoflann.hpp:601
Definition nanoflann.hpp:609
Definition nanoflann.hpp:607
Definition nanoflann.hpp:599
Definition nanoflann.hpp:616
Definition nanoflann.hpp:614
Definition nanoflann.hpp:623
Definition nanoflann.hpp:621