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-2016 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 
47 #ifndef NANOFLANN_HPP_
48 #define NANOFLANN_HPP_
49 
50 #include <algorithm>
51 #include <array>
52 #include <cassert>
53 #include <cmath> // for abs()
54 #include <cstdio> // for fwrite()
55 #include <cstdlib> // for abs()
56 #include <functional>
57 #include <limits> // std::reference_wrapper
58 #include <stdexcept>
59 #include <vector>
60 
62 #define NANOFLANN_VERSION 0x132
63 
64 // Avoid conflicting declaration of min/max macros in windows headers
65 #if !defined(NOMINMAX) && \
66  (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
67 #define NOMINMAX
68 #ifdef max
69 #undef max
70 #undef min
71 #endif
72 #endif
73 
74 namespace nanoflann {
79 template <typename T> T pi_const() {
80  return static_cast<T>(3.14159265358979323846);
81 }
82 
87 template <typename T, typename = int> struct has_resize : std::false_type {};
88 
89 template <typename T>
90 struct has_resize<T, decltype((void)std::declval<T>().resize(1), 0)>
91  : std::true_type {};
92 
93 template <typename T, typename = int> struct has_assign : std::false_type {};
94 
95 template <typename T>
96 struct has_assign<T, decltype((void)std::declval<T>().assign(1, 0), 0)>
97  : std::true_type {};
98 
102 template <typename Container>
103 inline typename std::enable_if<has_resize<Container>::value, void>::type
104 resize(Container &c, const size_t nElements) {
105  c.resize(nElements);
106 }
107 
112 template <typename Container>
113 inline typename std::enable_if<!has_resize<Container>::value, void>::type
114 resize(Container &c, const size_t nElements) {
115  if (nElements != c.size())
116  throw std::logic_error("Try to change the size of a std::array.");
117 }
118 
122 template <typename Container, typename T>
123 inline typename std::enable_if<has_assign<Container>::value, void>::type
124 assign(Container &c, const size_t nElements, const T &value) {
125  c.assign(nElements, value);
126 }
127 
131 template <typename Container, typename T>
132 inline typename std::enable_if<!has_assign<Container>::value, void>::type
133 assign(Container &c, const size_t nElements, const T &value) {
134  for (size_t i = 0; i < nElements; i++)
135  c[i] = value;
136 }
137 
140 template <typename _DistanceType, typename _IndexType = size_t,
141  typename _CountType = size_t>
142 class KNNResultSet {
143 public:
144  typedef _DistanceType DistanceType;
145  typedef _IndexType IndexType;
146  typedef _CountType CountType;
147 
148 private:
149  IndexType *indices;
150  DistanceType *dists;
151  CountType capacity;
152  CountType count;
153 
154 public:
155  inline KNNResultSet(CountType capacity_)
156  : indices(0), dists(0), capacity(capacity_), count(0) {}
157 
158  inline void init(IndexType *indices_, DistanceType *dists_) {
159  indices = indices_;
160  dists = dists_;
161  count = 0;
162  if (capacity)
163  dists[capacity - 1] = (std::numeric_limits<DistanceType>::max)();
164  }
165 
166  inline CountType size() const { return count; }
167 
168  inline bool full() const { return count == capacity; }
169 
175  inline bool addPoint(DistanceType dist, IndexType index) {
176  CountType i;
177  for (i = count; i > 0; --i) {
178 #ifdef NANOFLANN_FIRST_MATCH // If defined and two points have the same
179  // distance, the one with the lowest-index will be
180  // returned first.
181  if ((dists[i - 1] > dist) ||
182  ((dist == dists[i - 1]) && (indices[i - 1] > index))) {
183 #else
184  if (dists[i - 1] > dist) {
185 #endif
186  if (i < capacity) {
187  dists[i] = dists[i - 1];
188  indices[i] = indices[i - 1];
189  }
190  } else
191  break;
192  }
193  if (i < capacity) {
194  dists[i] = dist;
195  indices[i] = index;
196  }
197  if (count < capacity)
198  count++;
199 
200  // tell caller that the search shall continue
201  return true;
202  }
203 
204  inline DistanceType worstDist() const { return dists[capacity - 1]; }
205 };
206 
208 struct IndexDist_Sorter {
210  template <typename PairType>
211  inline bool operator()(const PairType &p1, const PairType &p2) const {
212  return p1.second < p2.second;
213  }
214 };
215 
219 template <typename _DistanceType, typename _IndexType = size_t>
220 class RadiusResultSet {
221 public:
222  typedef _DistanceType DistanceType;
223  typedef _IndexType IndexType;
224 
225 public:
226  const DistanceType radius;
227 
228  std::vector<std::pair<IndexType, DistanceType>> &m_indices_dists;
229 
230  inline RadiusResultSet(
231  DistanceType radius_,
232  std::vector<std::pair<IndexType, DistanceType>> &indices_dists)
233  : radius(radius_), m_indices_dists(indices_dists) {
234  init();
235  }
236 
237  inline void init() { clear(); }
238  inline void clear() { m_indices_dists.clear(); }
239 
240  inline size_t size() const { return m_indices_dists.size(); }
241 
242  inline bool full() const { return true; }
243 
249  inline bool addPoint(DistanceType dist, IndexType index) {
250  if (dist < radius)
251  m_indices_dists.push_back(std::make_pair(index, dist));
252  return true;
253  }
254 
255  inline DistanceType worstDist() const { return radius; }
256 
261  std::pair<IndexType, DistanceType> worst_item() const {
262  if (m_indices_dists.empty())
263  throw std::runtime_error("Cannot invoke RadiusResultSet::worst_item() on "
264  "an empty list of results.");
265  typedef
266  typename std::vector<std::pair<IndexType, DistanceType>>::const_iterator
267  DistIt;
268  DistIt it = std::max_element(m_indices_dists.begin(), m_indices_dists.end(),
269  IndexDist_Sorter());
270  return *it;
271  }
272 };
273 
278 template <typename T>
279 void save_value(FILE *stream, const T &value, size_t count = 1) {
280  fwrite(&value, sizeof(value), count, stream);
281 }
282 
283 template <typename T>
284 void save_value(FILE *stream, const std::vector<T> &value) {
285  size_t size = value.size();
286  fwrite(&size, sizeof(size_t), 1, stream);
287  fwrite(&value[0], sizeof(T), size, stream);
288 }
289 
290 template <typename T>
291 void load_value(FILE *stream, T &value, size_t count = 1) {
292  size_t read_cnt = fread(&value, sizeof(value), count, stream);
293  if (read_cnt != count) {
294  throw std::runtime_error("Cannot read from file");
295  }
296 }
297 
298 template <typename T> void load_value(FILE *stream, std::vector<T> &value) {
299  size_t size;
300  size_t read_cnt = fread(&size, sizeof(size_t), 1, stream);
301  if (read_cnt != 1) {
302  throw std::runtime_error("Cannot read from file");
303  }
304  value.resize(size);
305  read_cnt = fread(&value[0], sizeof(T), size, stream);
306  if (read_cnt != size) {
307  throw std::runtime_error("Cannot read from file");
308  }
309 }
315 struct Metric {};
316 
323 template <class T, class DataSource, typename _DistanceType = T>
324 struct L1_Adaptor {
325  typedef T ElementType;
326  typedef _DistanceType DistanceType;
327 
328  const DataSource &data_source;
329 
330  L1_Adaptor(const DataSource &_data_source) : data_source(_data_source) {}
331 
332  inline DistanceType evalMetric(const T *a, const size_t b_idx, size_t size,
333  DistanceType worst_dist = -1) const {
334  DistanceType result = DistanceType();
335  const T *last = a + size;
336  const T *lastgroup = last - 3;
337  size_t d = 0;
338 
339  /* Process 4 items with each loop for efficiency. */
340  while (a < lastgroup) {
341  const DistanceType diff0 =
342  std::abs(a[0] - data_source.kdtree_get_pt(b_idx, d++));
343  const DistanceType diff1 =
344  std::abs(a[1] - data_source.kdtree_get_pt(b_idx, d++));
345  const DistanceType diff2 =
346  std::abs(a[2] - data_source.kdtree_get_pt(b_idx, d++));
347  const DistanceType diff3 =
348  std::abs(a[3] - data_source.kdtree_get_pt(b_idx, d++));
349  result += diff0 + diff1 + diff2 + diff3;
350  a += 4;
351  if ((worst_dist > 0) && (result > worst_dist)) {
352  return result;
353  }
354  }
355  /* Process last 0-3 components. Not needed for standard vector lengths. */
356  while (a < last) {
357  result += std::abs(*a++ - data_source.kdtree_get_pt(b_idx, d++));
358  }
359  return result;
360  }
361 
362  template <typename U, typename V>
363  inline DistanceType accum_dist(const U a, const V b, const size_t) const {
364  return std::abs(a - b);
365  }
366 };
367 
374 template <class T, class DataSource, typename _DistanceType = T>
375 struct L2_Adaptor {
376  typedef T ElementType;
377  typedef _DistanceType DistanceType;
378 
379  const DataSource &data_source;
380 
381  L2_Adaptor(const DataSource &_data_source) : data_source(_data_source) {}
382 
383  inline DistanceType evalMetric(const T *a, const size_t b_idx, size_t size,
384  DistanceType worst_dist = -1) const {
385  DistanceType result = DistanceType();
386  const T *last = a + size;
387  const T *lastgroup = last - 3;
388  size_t d = 0;
389 
390  /* Process 4 items with each loop for efficiency. */
391  while (a < lastgroup) {
392  const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx, d++);
393  const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx, d++);
394  const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx, d++);
395  const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx, d++);
396  result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
397  a += 4;
398  if ((worst_dist > 0) && (result > worst_dist)) {
399  return result;
400  }
401  }
402  /* Process last 0-3 components. Not needed for standard vector lengths. */
403  while (a < last) {
404  const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx, d++);
405  result += diff0 * diff0;
406  }
407  return result;
408  }
409 
410  template <typename U, typename V>
411  inline DistanceType accum_dist(const U a, const V b, const size_t) const {
412  return (a - b) * (a - b);
413  }
414 };
415 
422 template <class T, class DataSource, typename _DistanceType = T>
423 struct L2_Simple_Adaptor {
424  typedef T ElementType;
425  typedef _DistanceType DistanceType;
426 
427  const DataSource &data_source;
428 
429  L2_Simple_Adaptor(const DataSource &_data_source)
430  : data_source(_data_source) {}
431 
432  inline DistanceType evalMetric(const T *a, const size_t b_idx,
433  size_t size) const {
434  DistanceType result = DistanceType();
435  for (size_t i = 0; i < size; ++i) {
436  const DistanceType diff = a[i] - data_source.kdtree_get_pt(b_idx, i);
437  result += diff * diff;
438  }
439  return result;
440  }
441 
442  template <typename U, typename V>
443  inline DistanceType accum_dist(const U a, const V b, const size_t) const {
444  return (a - b) * (a - b);
445  }
446 };
447 
454 template <class T, class DataSource, typename _DistanceType = T>
455 struct SO2_Adaptor {
456  typedef T ElementType;
457  typedef _DistanceType DistanceType;
458 
459  const DataSource &data_source;
460 
461  SO2_Adaptor(const DataSource &_data_source) : data_source(_data_source) {}
462 
463  inline DistanceType evalMetric(const T *a, const size_t b_idx,
464  size_t size) const {
465  return accum_dist(a[size - 1], data_source.kdtree_get_pt(b_idx, size - 1),
466  size - 1);
467  }
468 
470  template <typename U, typename V>
471  inline DistanceType accum_dist(const U a, const V b, const size_t) const {
472  DistanceType result = DistanceType();
473  DistanceType PI = pi_const<DistanceType>();
474  result = b - a;
475  if (result > PI)
476  result -= 2 * PI;
477  else if (result < -PI)
478  result += 2 * PI;
479  return result;
480  }
481 };
482 
489 template <class T, class DataSource, typename _DistanceType = T>
490 struct SO3_Adaptor {
491  typedef T ElementType;
492  typedef _DistanceType DistanceType;
493 
495 
496  SO3_Adaptor(const DataSource &_data_source)
497  : distance_L2_Simple(_data_source) {}
498 
499  inline DistanceType evalMetric(const T *a, const size_t b_idx,
500  size_t size) const {
501  return distance_L2_Simple.evalMetric(a, b_idx, size);
502  }
503 
504  template <typename U, typename V>
505  inline DistanceType accum_dist(const U a, const V b, const size_t idx) const {
506  return distance_L2_Simple.accum_dist(a, b, idx);
507  }
508 };
509 
511 struct metric_L1 : public Metric {
512  template <class T, class DataSource> struct traits {
513  typedef L1_Adaptor<T, DataSource> distance_t;
514  };
515 };
517 struct metric_L2 : public Metric {
518  template <class T, class DataSource> struct traits {
519  typedef L2_Adaptor<T, DataSource> distance_t;
520  };
521 };
523 struct metric_L2_Simple : public Metric {
524  template <class T, class DataSource> struct traits {
525  typedef L2_Simple_Adaptor<T, DataSource> distance_t;
526  };
527 };
529 struct metric_SO2 : public Metric {
530  template <class T, class DataSource> struct traits {
532  };
533 };
535 struct metric_SO3 : public Metric {
536  template <class T, class DataSource> struct traits {
538  };
539 };
540 
548  KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size = 10)
549  : leaf_max_size(_leaf_max_size) {}
550 
551  size_t leaf_max_size;
552 };
553 
555 struct SearchParams {
558  SearchParams(int checks_IGNORED_ = 32, float eps_ = 0, bool sorted_ = true)
559  : checks(checks_IGNORED_), eps(eps_), sorted(sorted_) {}
560 
561  int checks;
562  float eps;
564  bool sorted;
565 };
579 template <typename T> inline T *allocate(size_t count = 1) {
580  T *mem = static_cast<T *>(::malloc(sizeof(T) * count));
581  return mem;
582 }
583 
599 const size_t WORDSIZE = 16;
600 const size_t BLOCKSIZE = 8192;
601 
602 class PooledAllocator {
603  /* We maintain memory alignment to word boundaries by requiring that all
604  allocations be in multiples of the machine wordsize. */
605  /* Size of machine word in bytes. Must be power of 2. */
606  /* Minimum number of bytes requested at a time from the system. Must be
607  * multiple of WORDSIZE. */
608 
609  size_t remaining; /* Number of bytes left in current block of storage. */
610  void *base; /* Pointer to base of current block of storage. */
611  void *loc; /* Current location in block to next allocate memory. */
612 
613  void internal_init() {
614  remaining = 0;
615  base = NULL;
616  usedMemory = 0;
617  wastedMemory = 0;
618  }
619 
620 public:
621  size_t usedMemory;
622  size_t wastedMemory;
623 
627  PooledAllocator() { internal_init(); }
628 
632  ~PooledAllocator() { free_all(); }
633 
635  void free_all() {
636  while (base != NULL) {
637  void *prev =
638  *(static_cast<void **>(base)); /* Get pointer to prev block. */
639  ::free(base);
640  base = prev;
641  }
642  internal_init();
643  }
644 
649  void *malloc(const size_t req_size) {
650  /* Round size up to a multiple of wordsize. The following expression
651  only works for WORDSIZE that is a power of 2, by masking last bits of
652  incremented size to zero.
653  */
654  const size_t size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1);
655 
656  /* Check whether a new block must be allocated. Note that the first word
657  of a block is reserved for a pointer to the previous block.
658  */
659  if (size > remaining) {
660 
661  wastedMemory += remaining;
662 
663  /* Allocate new storage. */
664  const size_t blocksize =
665  (size + sizeof(void *) + (WORDSIZE - 1) > BLOCKSIZE)
666  ? size + sizeof(void *) + (WORDSIZE - 1)
667  : BLOCKSIZE;
668 
669  // use the standard C malloc to allocate memory
670  void *m = ::malloc(blocksize);
671  if (!m) {
672  fprintf(stderr, "Failed to allocate memory.\n");
673  throw std::bad_alloc();
674  }
675 
676  /* Fill first word of new block with pointer to previous block. */
677  static_cast<void **>(m)[0] = base;
678  base = m;
679 
680  size_t shift = 0;
681  // int size_t = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) &
682  // (WORDSIZE-1))) & (WORDSIZE-1);
683 
684  remaining = blocksize - sizeof(void *) - shift;
685  loc = (static_cast<char *>(m) + sizeof(void *) + shift);
686  }
687  void *rloc = loc;
688  loc = static_cast<char *>(loc) + size;
689  remaining -= size;
690 
691  usedMemory += size;
692 
693  return rloc;
694  }
695 
703  template <typename T> T *allocate(const size_t count = 1) {
704  T *mem = static_cast<T *>(this->malloc(sizeof(T) * count));
705  return mem;
706  }
707 };
716 template <int DIM, typename T> struct array_or_vector_selector {
717  typedef std::array<T, DIM> container_t;
718 };
720 template <typename T> struct array_or_vector_selector<-1, T> {
721  typedef std::vector<T> container_t;
722 };
723 
738 template <class Derived, typename Distance, class DatasetAdaptor, int DIM = -1,
739  typename IndexType = size_t>
741 
742 public:
745  void freeIndex(Derived &obj) {
746  obj.pool.free_all();
747  obj.root_node = NULL;
748  obj.m_size_at_index_build = 0;
749  }
750 
751  typedef typename Distance::ElementType ElementType;
752  typedef typename Distance::DistanceType DistanceType;
753 
754  /*--------------------- Internal Data Structures --------------------------*/
755  struct Node {
758  union {
759  struct leaf {
760  IndexType left, right;
761  } lr;
762  struct nonleaf {
763  int divfeat;
764  DistanceType divlow, divhigh;
765  } sub;
766  } node_type;
767  Node *child1, *child2;
768  };
769 
770  typedef Node *NodePtr;
771 
772  struct Interval {
773  ElementType low, high;
774  };
775 
779  std::vector<IndexType> vind;
780 
781  NodePtr root_node;
782 
784 
785  size_t m_size;
787  int dim;
789 
792  typedef
794 
799 
802  BoundingBox root_bbox;
803 
812 
814  size_t size(const Derived &obj) const { return obj.m_size; }
815 
817  size_t veclen(const Derived &obj) {
818  return static_cast<size_t>(DIM > 0 ? DIM : obj.dim);
819  }
820 
822  inline ElementType dataset_get(const Derived &obj, size_t idx,
823  int component) const {
824  return obj.dataset.kdtree_get_pt(idx, component);
825  }
826 
831  size_t usedMemory(Derived &obj) {
832  return obj.pool.usedMemory + obj.pool.wastedMemory +
833  obj.dataset.kdtree_get_point_count() *
834  sizeof(IndexType); // pool memory and vind array memory
835  }
836 
837  void computeMinMax(const Derived &obj, IndexType *ind, IndexType count,
838  int element, ElementType &min_elem,
839  ElementType &max_elem) {
840  min_elem = dataset_get(obj, ind[0], element);
841  max_elem = dataset_get(obj, ind[0], element);
842  for (IndexType i = 1; i < count; ++i) {
843  ElementType val = dataset_get(obj, ind[i], element);
844  if (val < min_elem)
845  min_elem = val;
846  if (val > max_elem)
847  max_elem = val;
848  }
849  }
850 
858  NodePtr divideTree(Derived &obj, const IndexType left, const IndexType right,
859  BoundingBox &bbox) {
860  NodePtr node = obj.pool.template allocate<Node>(); // allocate memory
861 
862  /* If too few exemplars remain, then make this a leaf node. */
863  if ((right - left) <= static_cast<IndexType>(obj.m_leaf_max_size)) {
864  node->child1 = node->child2 = NULL; /* Mark as leaf node. */
865  node->node_type.lr.left = left;
866  node->node_type.lr.right = right;
867 
868  // compute bounding-box of leaf points
869  for (int i = 0; i < (DIM > 0 ? DIM : obj.dim); ++i) {
870  bbox[i].low = dataset_get(obj, obj.vind[left], i);
871  bbox[i].high = dataset_get(obj, obj.vind[left], i);
872  }
873  for (IndexType k = left + 1; k < right; ++k) {
874  for (int i = 0; i < (DIM > 0 ? DIM : obj.dim); ++i) {
875  if (bbox[i].low > dataset_get(obj, obj.vind[k], i))
876  bbox[i].low = dataset_get(obj, obj.vind[k], i);
877  if (bbox[i].high < dataset_get(obj, obj.vind[k], i))
878  bbox[i].high = dataset_get(obj, obj.vind[k], i);
879  }
880  }
881  } else {
882  IndexType idx;
883  int cutfeat;
884  DistanceType cutval;
885  middleSplit_(obj, &obj.vind[0] + left, right - left, idx, cutfeat, cutval,
886  bbox);
887 
888  node->node_type.sub.divfeat = cutfeat;
889 
890  BoundingBox left_bbox(bbox);
891  left_bbox[cutfeat].high = cutval;
892  node->child1 = divideTree(obj, left, left + idx, left_bbox);
893 
894  BoundingBox right_bbox(bbox);
895  right_bbox[cutfeat].low = cutval;
896  node->child2 = divideTree(obj, left + idx, right, right_bbox);
897 
898  node->node_type.sub.divlow = left_bbox[cutfeat].high;
899  node->node_type.sub.divhigh = right_bbox[cutfeat].low;
900 
901  for (int i = 0; i < (DIM > 0 ? DIM : obj.dim); ++i) {
902  bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
903  bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
904  }
905  }
906 
907  return node;
908  }
909 
910  void middleSplit_(Derived &obj, IndexType *ind, IndexType count,
911  IndexType &index, int &cutfeat, DistanceType &cutval,
912  const BoundingBox &bbox) {
913  const DistanceType EPS = static_cast<DistanceType>(0.00001);
914  ElementType max_span = bbox[0].high - bbox[0].low;
915  for (int i = 1; i < (DIM > 0 ? DIM : obj.dim); ++i) {
916  ElementType span = bbox[i].high - bbox[i].low;
917  if (span > max_span) {
918  max_span = span;
919  }
920  }
921  ElementType max_spread = -1;
922  cutfeat = 0;
923  for (int i = 0; i < (DIM > 0 ? DIM : obj.dim); ++i) {
924  ElementType span = bbox[i].high - bbox[i].low;
925  if (span > (1 - EPS) * max_span) {
926  ElementType min_elem, max_elem;
927  computeMinMax(obj, ind, count, i, min_elem, max_elem);
928  ElementType spread = max_elem - min_elem;
929  ;
930  if (spread > max_spread) {
931  cutfeat = i;
932  max_spread = spread;
933  }
934  }
935  }
936  // split in the middle
937  DistanceType split_val = (bbox[cutfeat].low + bbox[cutfeat].high) / 2;
938  ElementType min_elem, max_elem;
939  computeMinMax(obj, ind, count, cutfeat, min_elem, max_elem);
940 
941  if (split_val < min_elem)
942  cutval = min_elem;
943  else if (split_val > max_elem)
944  cutval = max_elem;
945  else
946  cutval = split_val;
947 
948  IndexType lim1, lim2;
949  planeSplit(obj, ind, count, cutfeat, cutval, lim1, lim2);
950 
951  if (lim1 > count / 2)
952  index = lim1;
953  else if (lim2 < count / 2)
954  index = lim2;
955  else
956  index = count / 2;
957  }
958 
968  void planeSplit(Derived &obj, IndexType *ind, const IndexType count,
969  int cutfeat, DistanceType &cutval, IndexType &lim1,
970  IndexType &lim2) {
971  /* Move vector indices for left subtree to front of list. */
972  IndexType left = 0;
973  IndexType right = count - 1;
974  for (;;) {
975  while (left <= right && dataset_get(obj, ind[left], cutfeat) < cutval)
976  ++left;
977  while (right && left <= right &&
978  dataset_get(obj, ind[right], cutfeat) >= cutval)
979  --right;
980  if (left > right || !right)
981  break; // "!right" was added to support unsigned Index types
982  std::swap(ind[left], ind[right]);
983  ++left;
984  --right;
985  }
986  /* If either list is empty, it means that all remaining features
987  * are identical. Split in the middle to maintain a balanced tree.
988  */
989  lim1 = left;
990  right = count - 1;
991  for (;;) {
992  while (left <= right && dataset_get(obj, ind[left], cutfeat) <= cutval)
993  ++left;
994  while (right && left <= right &&
995  dataset_get(obj, ind[right], cutfeat) > cutval)
996  --right;
997  if (left > right || !right)
998  break; // "!right" was added to support unsigned Index types
999  std::swap(ind[left], ind[right]);
1000  ++left;
1001  --right;
1002  }
1003  lim2 = left;
1004  }
1005 
1006  DistanceType computeInitialDistances(const Derived &obj,
1007  const ElementType *vec,
1008  distance_vector_t &dists) const {
1009  assert(vec);
1010  DistanceType distsq = DistanceType();
1011 
1012  for (int i = 0; i < (DIM > 0 ? DIM : obj.dim); ++i) {
1013  if (vec[i] < obj.root_bbox[i].low) {
1014  dists[i] = obj.distance.accum_dist(vec[i], obj.root_bbox[i].low, i);
1015  distsq += dists[i];
1016  }
1017  if (vec[i] > obj.root_bbox[i].high) {
1018  dists[i] = obj.distance.accum_dist(vec[i], obj.root_bbox[i].high, i);
1019  distsq += dists[i];
1020  }
1021  }
1022  return distsq;
1023  }
1024 
1025  void save_tree(Derived &obj, FILE *stream, NodePtr tree) {
1026  save_value(stream, *tree);
1027  if (tree->child1 != NULL) {
1028  save_tree(obj, stream, tree->child1);
1029  }
1030  if (tree->child2 != NULL) {
1031  save_tree(obj, stream, tree->child2);
1032  }
1033  }
1034 
1035  void load_tree(Derived &obj, FILE *stream, NodePtr &tree) {
1036  tree = obj.pool.template allocate<Node>();
1037  load_value(stream, *tree);
1038  if (tree->child1 != NULL) {
1039  load_tree(obj, stream, tree->child1);
1040  }
1041  if (tree->child2 != NULL) {
1042  load_tree(obj, stream, tree->child2);
1043  }
1044  }
1045 
1051  void saveIndex_(Derived &obj, FILE *stream) {
1052  save_value(stream, obj.m_size);
1053  save_value(stream, obj.dim);
1054  save_value(stream, obj.root_bbox);
1055  save_value(stream, obj.m_leaf_max_size);
1056  save_value(stream, obj.vind);
1057  save_tree(obj, stream, obj.root_node);
1058  }
1059 
1065  void loadIndex_(Derived &obj, FILE *stream) {
1066  load_value(stream, obj.m_size);
1067  load_value(stream, obj.dim);
1068  load_value(stream, obj.root_bbox);
1069  load_value(stream, obj.m_leaf_max_size);
1070  load_value(stream, obj.vind);
1071  load_tree(obj, stream, obj.root_node);
1072  }
1073 };
1074 
1115 template <typename Distance, class DatasetAdaptor, int DIM = -1,
1116  typename IndexType = size_t>
1118  : public KDTreeBaseClass<
1119  KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM, IndexType>,
1120  Distance, DatasetAdaptor, DIM, IndexType> {
1121 public:
1125  &) = delete;
1126 
1130  const DatasetAdaptor &dataset;
1131 
1132  const KDTreeSingleIndexAdaptorParams index_params;
1133 
1134  Distance distance;
1135 
1136  typedef typename nanoflann::KDTreeBaseClass<
1137  nanoflann::KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM,
1138  IndexType>,
1139  Distance, DatasetAdaptor, DIM, IndexType>
1140  BaseClassRef;
1141 
1142  typedef typename BaseClassRef::ElementType ElementType;
1143  typedef typename BaseClassRef::DistanceType DistanceType;
1144 
1145  typedef typename BaseClassRef::Node Node;
1146  typedef Node *NodePtr;
1147 
1148  typedef typename BaseClassRef::Interval Interval;
1151  typedef typename BaseClassRef::BoundingBox BoundingBox;
1152 
1155  typedef typename BaseClassRef::distance_vector_t distance_vector_t;
1156 
1171  KDTreeSingleIndexAdaptor(const int dimensionality,
1172  const DatasetAdaptor &inputData,
1173  const KDTreeSingleIndexAdaptorParams &params =
1175  : dataset(inputData), index_params(params), distance(inputData) {
1176  BaseClassRef::root_node = NULL;
1177  BaseClassRef::m_size = dataset.kdtree_get_point_count();
1178  BaseClassRef::m_size_at_index_build = BaseClassRef::m_size;
1179  BaseClassRef::dim = dimensionality;
1180  if (DIM > 0)
1181  BaseClassRef::dim = DIM;
1182  BaseClassRef::m_leaf_max_size = params.leaf_max_size;
1183 
1184  // Create a permutable array of indices to the input vectors.
1185  init_vind();
1186  }
1187 
1191  void buildIndex() {
1192  BaseClassRef::m_size = dataset.kdtree_get_point_count();
1193  BaseClassRef::m_size_at_index_build = BaseClassRef::m_size;
1194  init_vind();
1195  this->freeIndex(*this);
1196  BaseClassRef::m_size_at_index_build = BaseClassRef::m_size;
1197  if (BaseClassRef::m_size == 0)
1198  return;
1199  computeBoundingBox(BaseClassRef::root_bbox);
1200  BaseClassRef::root_node =
1201  this->divideTree(*this, 0, BaseClassRef::m_size,
1202  BaseClassRef::root_bbox); // construct the tree
1203  }
1204 
1221  template <typename RESULTSET>
1222  bool findNeighbors(RESULTSET &result, const ElementType *vec,
1223  const SearchParams &searchParams) const {
1224  assert(vec);
1225  if (this->size(*this) == 0)
1226  return false;
1227  if (!BaseClassRef::root_node)
1228  throw std::runtime_error(
1229  "[nanoflann] findNeighbors() called before building the index.");
1230  float epsError = 1 + searchParams.eps;
1231 
1232  distance_vector_t
1233  dists; // fixed or variable-sized container (depending on DIM)
1234  auto zero = static_cast<decltype(result.worstDist())>(0);
1235  assign(dists, (DIM > 0 ? DIM : BaseClassRef::dim),
1236  zero); // Fill it with zeros.
1237  DistanceType distsq = this->computeInitialDistances(*this, vec, dists);
1238  searchLevel(result, vec, BaseClassRef::root_node, distsq, dists,
1239  epsError); // "count_leaf" parameter removed since was neither
1240  // used nor returned to the user.
1241  return result.full();
1242  }
1243 
1253  size_t knnSearch(const ElementType *query_point, const size_t num_closest,
1254  IndexType *out_indices, DistanceType *out_distances_sq,
1255  const int /* nChecks_IGNORED */ = 10) const {
1256  nanoflann::KNNResultSet<DistanceType, IndexType> resultSet(num_closest);
1257  resultSet.init(out_indices, out_distances_sq);
1258  this->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
1259  return resultSet.size();
1260  }
1261 
1278  size_t
1279  radiusSearch(const ElementType *query_point, const DistanceType &radius,
1280  std::vector<std::pair<IndexType, DistanceType>> &IndicesDists,
1281  const SearchParams &searchParams) const {
1282  RadiusResultSet<DistanceType, IndexType> resultSet(radius, IndicesDists);
1283  const size_t nFound =
1284  radiusSearchCustomCallback(query_point, resultSet, searchParams);
1285  if (searchParams.sorted)
1286  std::sort(IndicesDists.begin(), IndicesDists.end(), IndexDist_Sorter());
1287  return nFound;
1288  }
1289 
1295  template <class SEARCH_CALLBACK>
1296  size_t radiusSearchCustomCallback(
1297  const ElementType *query_point, SEARCH_CALLBACK &resultSet,
1298  const SearchParams &searchParams = SearchParams()) const {
1299  this->findNeighbors(resultSet, query_point, searchParams);
1300  return resultSet.size();
1301  }
1302 
1305 public:
1308  void init_vind() {
1309  // Create a permutable array of indices to the input vectors.
1310  BaseClassRef::m_size = dataset.kdtree_get_point_count();
1311  if (BaseClassRef::vind.size() != BaseClassRef::m_size)
1312  BaseClassRef::vind.resize(BaseClassRef::m_size);
1313  for (size_t i = 0; i < BaseClassRef::m_size; i++)
1314  BaseClassRef::vind[i] = i;
1315  }
1316 
1317  void computeBoundingBox(BoundingBox &bbox) {
1318  resize(bbox, (DIM > 0 ? DIM : BaseClassRef::dim));
1319  if (dataset.kdtree_get_bbox(bbox)) {
1320  // Done! It was implemented in derived class
1321  } else {
1322  const size_t N = dataset.kdtree_get_point_count();
1323  if (!N)
1324  throw std::runtime_error("[nanoflann] computeBoundingBox() called but "
1325  "no data points found.");
1326  for (int i = 0; i < (DIM > 0 ? DIM : BaseClassRef::dim); ++i) {
1327  bbox[i].low = bbox[i].high = this->dataset_get(*this, 0, i);
1328  }
1329  for (size_t k = 1; k < N; ++k) {
1330  for (int i = 0; i < (DIM > 0 ? DIM : BaseClassRef::dim); ++i) {
1331  if (this->dataset_get(*this, k, i) < bbox[i].low)
1332  bbox[i].low = this->dataset_get(*this, k, i);
1333  if (this->dataset_get(*this, k, i) > bbox[i].high)
1334  bbox[i].high = this->dataset_get(*this, k, i);
1335  }
1336  }
1337  }
1338  }
1339 
1346  template <class RESULTSET>
1347  bool searchLevel(RESULTSET &result_set, const ElementType *vec,
1348  const NodePtr node, DistanceType mindistsq,
1349  distance_vector_t &dists, const float epsError) const {
1350  /* If this is a leaf node, then do check and return. */
1351  if ((node->child1 == NULL) && (node->child2 == NULL)) {
1352  // count_leaf += (node->lr.right-node->lr.left); // Removed since was
1353  // neither used nor returned to the user.
1354  DistanceType worst_dist = result_set.worstDist();
1355  for (IndexType i = node->node_type.lr.left; i < node->node_type.lr.right;
1356  ++i) {
1357  const IndexType index = BaseClassRef::vind[i]; // reorder... : i;
1358  DistanceType dist = distance.evalMetric(
1359  vec, index, (DIM > 0 ? DIM : BaseClassRef::dim));
1360  if (dist < worst_dist) {
1361  if (!result_set.addPoint(dist, BaseClassRef::vind[i])) {
1362  // the resultset doesn't want to receive any more points, we're done
1363  // searching!
1364  return false;
1365  }
1366  }
1367  }
1368  return true;
1369  }
1370 
1371  /* Which child branch should be taken first? */
1372  int idx = node->node_type.sub.divfeat;
1373  ElementType val = vec[idx];
1374  DistanceType diff1 = val - node->node_type.sub.divlow;
1375  DistanceType diff2 = val - node->node_type.sub.divhigh;
1376 
1377  NodePtr bestChild;
1378  NodePtr otherChild;
1379  DistanceType cut_dist;
1380  if ((diff1 + diff2) < 0) {
1381  bestChild = node->child1;
1382  otherChild = node->child2;
1383  cut_dist = distance.accum_dist(val, node->node_type.sub.divhigh, idx);
1384  } else {
1385  bestChild = node->child2;
1386  otherChild = node->child1;
1387  cut_dist = distance.accum_dist(val, node->node_type.sub.divlow, idx);
1388  }
1389 
1390  /* Call recursively to search next level down. */
1391  if (!searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError)) {
1392  // the resultset doesn't want to receive any more points, we're done
1393  // searching!
1394  return false;
1395  }
1396 
1397  DistanceType dst = dists[idx];
1398  mindistsq = mindistsq + cut_dist - dst;
1399  dists[idx] = cut_dist;
1400  if (mindistsq * epsError <= result_set.worstDist()) {
1401  if (!searchLevel(result_set, vec, otherChild, mindistsq, dists,
1402  epsError)) {
1403  // the resultset doesn't want to receive any more points, we're done
1404  // searching!
1405  return false;
1406  }
1407  }
1408  dists[idx] = dst;
1409  return true;
1410  }
1411 
1412 public:
1418  void saveIndex(FILE *stream) { this->saveIndex_(*this, stream); }
1419 
1425  void loadIndex(FILE *stream) { this->loadIndex_(*this, stream); }
1426 
1427 }; // class KDTree
1428 
1465 template <typename Distance, class DatasetAdaptor, int DIM = -1,
1466  typename IndexType = size_t>
1468  : public KDTreeBaseClass<KDTreeSingleIndexDynamicAdaptor_<
1469  Distance, DatasetAdaptor, DIM, IndexType>,
1470  Distance, DatasetAdaptor, DIM, IndexType> {
1471 public:
1475  const DatasetAdaptor &dataset;
1476 
1478 
1479  std::vector<int> &treeIndex;
1480 
1481  Distance distance;
1482 
1483  typedef typename nanoflann::KDTreeBaseClass<
1484  nanoflann::KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM,
1485  IndexType>,
1486  Distance, DatasetAdaptor, DIM, IndexType>
1488 
1491 
1492  typedef typename BaseClassRef::Node Node;
1493  typedef Node *NodePtr;
1494 
1499 
1503 
1519  const int dimensionality, const DatasetAdaptor &inputData,
1520  std::vector<int> &treeIndex_,
1521  const KDTreeSingleIndexAdaptorParams &params =
1523  : dataset(inputData), index_params(params), treeIndex(treeIndex_),
1524  distance(inputData) {
1525  BaseClassRef::root_node = NULL;
1526  BaseClassRef::m_size = 0;
1527  BaseClassRef::m_size_at_index_build = 0;
1528  BaseClassRef::dim = dimensionality;
1529  if (DIM > 0)
1530  BaseClassRef::dim = DIM;
1531  BaseClassRef::m_leaf_max_size = params.leaf_max_size;
1532  }
1533 
1538  std::swap(BaseClassRef::vind, tmp.BaseClassRef::vind);
1539  std::swap(BaseClassRef::m_leaf_max_size, tmp.BaseClassRef::m_leaf_max_size);
1540  std::swap(index_params, tmp.index_params);
1541  std::swap(treeIndex, tmp.treeIndex);
1542  std::swap(BaseClassRef::m_size, tmp.BaseClassRef::m_size);
1543  std::swap(BaseClassRef::m_size_at_index_build,
1544  tmp.BaseClassRef::m_size_at_index_build);
1545  std::swap(BaseClassRef::root_node, tmp.BaseClassRef::root_node);
1546  std::swap(BaseClassRef::root_bbox, tmp.BaseClassRef::root_bbox);
1547  std::swap(BaseClassRef::pool, tmp.BaseClassRef::pool);
1548  return *this;
1549  }
1550 
1554  void buildIndex() {
1555  BaseClassRef::m_size = BaseClassRef::vind.size();
1556  this->freeIndex(*this);
1557  BaseClassRef::m_size_at_index_build = BaseClassRef::m_size;
1558  if (BaseClassRef::m_size == 0)
1559  return;
1560  computeBoundingBox(BaseClassRef::root_bbox);
1561  BaseClassRef::root_node =
1562  this->divideTree(*this, 0, BaseClassRef::m_size,
1563  BaseClassRef::root_bbox); // construct the tree
1564  }
1565 
1582  template <typename RESULTSET>
1583  bool findNeighbors(RESULTSET &result, const ElementType *vec,
1584  const SearchParams &searchParams) const {
1585  assert(vec);
1586  if (this->size(*this) == 0)
1587  return false;
1588  if (!BaseClassRef::root_node)
1589  return false;
1590  float epsError = 1 + searchParams.eps;
1591 
1592  // fixed or variable-sized container (depending on DIM)
1593  distance_vector_t dists;
1594  // Fill it with zeros.
1595  assign(dists, (DIM > 0 ? DIM : BaseClassRef::dim),
1596  static_cast<typename distance_vector_t::value_type>(0));
1597  DistanceType distsq = this->computeInitialDistances(*this, vec, dists);
1598  searchLevel(result, vec, BaseClassRef::root_node, distsq, dists,
1599  epsError); // "count_leaf" parameter removed since was neither
1600  // used nor returned to the user.
1601  return result.full();
1602  }
1603 
1613  size_t knnSearch(const ElementType *query_point, const size_t num_closest,
1614  IndexType *out_indices, DistanceType *out_distances_sq,
1615  const int /* nChecks_IGNORED */ = 10) const {
1616  nanoflann::KNNResultSet<DistanceType, IndexType> resultSet(num_closest);
1617  resultSet.init(out_indices, out_distances_sq);
1618  this->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
1619  return resultSet.size();
1620  }
1621 
1638  size_t
1639  radiusSearch(const ElementType *query_point, const DistanceType &radius,
1640  std::vector<std::pair<IndexType, DistanceType>> &IndicesDists,
1641  const SearchParams &searchParams) const {
1642  RadiusResultSet<DistanceType, IndexType> resultSet(radius, IndicesDists);
1643  const size_t nFound =
1644  radiusSearchCustomCallback(query_point, resultSet, searchParams);
1645  if (searchParams.sorted)
1646  std::sort(IndicesDists.begin(), IndicesDists.end(), IndexDist_Sorter());
1647  return nFound;
1648  }
1649 
1655  template <class SEARCH_CALLBACK>
1657  const ElementType *query_point, SEARCH_CALLBACK &resultSet,
1658  const SearchParams &searchParams = SearchParams()) const {
1659  this->findNeighbors(resultSet, query_point, searchParams);
1660  return resultSet.size();
1661  }
1662 
1665 public:
1666  void computeBoundingBox(BoundingBox &bbox) {
1667  resize(bbox, (DIM > 0 ? DIM : BaseClassRef::dim));
1668 
1669  if (dataset.kdtree_get_bbox(bbox)) {
1670  // Done! It was implemented in derived class
1671  } else {
1672  const size_t N = BaseClassRef::m_size;
1673  if (!N)
1674  throw std::runtime_error("[nanoflann] computeBoundingBox() called but "
1675  "no data points found.");
1676  for (int i = 0; i < (DIM > 0 ? DIM : BaseClassRef::dim); ++i) {
1677  bbox[i].low = bbox[i].high =
1678  this->dataset_get(*this, BaseClassRef::vind[0], i);
1679  }
1680  for (size_t k = 1; k < N; ++k) {
1681  for (int i = 0; i < (DIM > 0 ? DIM : BaseClassRef::dim); ++i) {
1682  if (this->dataset_get(*this, BaseClassRef::vind[k], i) < bbox[i].low)
1683  bbox[i].low = this->dataset_get(*this, BaseClassRef::vind[k], i);
1684  if (this->dataset_get(*this, BaseClassRef::vind[k], i) > bbox[i].high)
1685  bbox[i].high = this->dataset_get(*this, BaseClassRef::vind[k], i);
1686  }
1687  }
1688  }
1689  }
1690 
1695  template <class RESULTSET>
1696  void searchLevel(RESULTSET &result_set, const ElementType *vec,
1697  const NodePtr node, DistanceType mindistsq,
1698  distance_vector_t &dists, const float epsError) const {
1699  /* If this is a leaf node, then do check and return. */
1700  if ((node->child1 == NULL) && (node->child2 == NULL)) {
1701  // count_leaf += (node->lr.right-node->lr.left); // Removed since was
1702  // neither used nor returned to the user.
1703  DistanceType worst_dist = result_set.worstDist();
1704  for (IndexType i = node->node_type.lr.left; i < node->node_type.lr.right;
1705  ++i) {
1706  const IndexType index = BaseClassRef::vind[i]; // reorder... : i;
1707  if (treeIndex[index] == -1)
1708  continue;
1709  DistanceType dist = distance.evalMetric(
1710  vec, index, (DIM > 0 ? DIM : BaseClassRef::dim));
1711  if (dist < worst_dist) {
1712  if (!result_set.addPoint(
1713  static_cast<typename RESULTSET::DistanceType>(dist),
1714  static_cast<typename RESULTSET::IndexType>(
1715  BaseClassRef::vind[i]))) {
1716  // the resultset doesn't want to receive any more points, we're done
1717  // searching!
1718  return; // false;
1719  }
1720  }
1721  }
1722  return;
1723  }
1724 
1725  /* Which child branch should be taken first? */
1726  int idx = node->node_type.sub.divfeat;
1727  ElementType val = vec[idx];
1728  DistanceType diff1 = val - node->node_type.sub.divlow;
1729  DistanceType diff2 = val - node->node_type.sub.divhigh;
1730 
1731  NodePtr bestChild;
1732  NodePtr otherChild;
1733  DistanceType cut_dist;
1734  if ((diff1 + diff2) < 0) {
1735  bestChild = node->child1;
1736  otherChild = node->child2;
1737  cut_dist = distance.accum_dist(val, node->node_type.sub.divhigh, idx);
1738  } else {
1739  bestChild = node->child2;
1740  otherChild = node->child1;
1741  cut_dist = distance.accum_dist(val, node->node_type.sub.divlow, idx);
1742  }
1743 
1744  /* Call recursively to search next level down. */
1745  searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError);
1746 
1747  DistanceType dst = dists[idx];
1748  mindistsq = mindistsq + cut_dist - dst;
1749  dists[idx] = cut_dist;
1750  if (mindistsq * epsError <= result_set.worstDist()) {
1751  searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError);
1752  }
1753  dists[idx] = dst;
1754  }
1755 
1756 public:
1762  void saveIndex(FILE *stream) { this->saveIndex_(*this, stream); }
1763 
1769  void loadIndex(FILE *stream) { this->loadIndex_(*this, stream); }
1770 };
1771 
1786 template <typename Distance, class DatasetAdaptor, int DIM = -1,
1787  typename IndexType = size_t>
1789 public:
1790  typedef typename Distance::ElementType ElementType;
1791  typedef typename Distance::DistanceType DistanceType;
1792 
1793 protected:
1795  size_t treeCount;
1796  size_t pointCount;
1797 
1801  const DatasetAdaptor &dataset;
1802 
1803  std::vector<int> treeIndex;
1804 
1808 
1809  int dim;
1810 
1813  std::vector<index_container_t> index;
1814 
1815 public:
1818  const std::vector<index_container_t> &getAllIndices() const { return index; }
1819 
1820 private:
1822  int First0Bit(IndexType num) {
1823  int pos = 0;
1824  while (num & 1) {
1825  num = num >> 1;
1826  pos++;
1827  }
1828  return pos;
1829  }
1830 
1832  void init() {
1834  my_kd_tree_t;
1835  std::vector<my_kd_tree_t> index_(
1836  treeCount, my_kd_tree_t(dim /*dim*/, dataset, treeIndex, index_params));
1837  index = index_;
1838  }
1839 
1840 public:
1841  Distance distance;
1842 
1857  KDTreeSingleIndexDynamicAdaptor(const int dimensionality,
1858  const DatasetAdaptor &inputData,
1859  const KDTreeSingleIndexAdaptorParams &params =
1861  const size_t maximumPointCount = 1000000000U)
1862  : dataset(inputData), index_params(params), distance(inputData) {
1863  treeCount = static_cast<size_t>(std::log2(maximumPointCount));
1864  pointCount = 0U;
1865  dim = dimensionality;
1866  treeIndex.clear();
1867  if (DIM > 0)
1868  dim = DIM;
1869  m_leaf_max_size = params.leaf_max_size;
1870  init();
1871  const size_t num_initial_points = dataset.kdtree_get_point_count();
1872  if (num_initial_points > 0) {
1873  addPoints(0, num_initial_points - 1);
1874  }
1875  }
1876 
1879  const KDTreeSingleIndexDynamicAdaptor<Distance, DatasetAdaptor, DIM,
1880  IndexType> &) = delete;
1881 
1883  void addPoints(IndexType start, IndexType end) {
1884  size_t count = end - start + 1;
1885  treeIndex.resize(treeIndex.size() + count);
1886  for (IndexType idx = start; idx <= end; idx++) {
1887  int pos = First0Bit(pointCount);
1888  index[pos].vind.clear();
1889  treeIndex[pointCount] = pos;
1890  for (int i = 0; i < pos; i++) {
1891  for (int j = 0; j < static_cast<int>(index[i].vind.size()); j++) {
1892  index[pos].vind.push_back(index[i].vind[j]);
1893  if (treeIndex[index[i].vind[j]] != -1)
1894  treeIndex[index[i].vind[j]] = pos;
1895  }
1896  index[i].vind.clear();
1897  index[i].freeIndex(index[i]);
1898  }
1899  index[pos].vind.push_back(idx);
1900  index[pos].buildIndex();
1901  pointCount++;
1902  }
1903  }
1904 
1906  void removePoint(size_t idx) {
1907  if (idx >= pointCount)
1908  return;
1909  treeIndex[idx] = -1;
1910  }
1911 
1925  template <typename RESULTSET>
1926  bool findNeighbors(RESULTSET &result, const ElementType *vec,
1927  const SearchParams &searchParams) const {
1928  for (size_t i = 0; i < treeCount; i++) {
1929  index[i].findNeighbors(result, &vec[0], searchParams);
1930  }
1931  return result.full();
1932  }
1933 };
1934 
1955 template <class MatrixType, int DIM = -1, class Distance = nanoflann::metric_L2,
1956  bool row_major = true>
1957 struct KDTreeEigenMatrixAdaptor {
1959  typedef typename MatrixType::Scalar num_t;
1960  typedef typename MatrixType::Index IndexType;
1961  typedef
1962  typename Distance::template traits<num_t, self_t>::distance_t metric_t;
1963  typedef KDTreeSingleIndexAdaptor<metric_t, self_t,
1964  MatrixType::ColsAtCompileTime, IndexType>
1965  index_t;
1966 
1967  index_t *index;
1968 
1971  KDTreeEigenMatrixAdaptor(const size_t dimensionality,
1972  const std::reference_wrapper<const MatrixType> &mat,
1973  const int leaf_max_size = 10)
1974  : m_data_matrix(mat) {
1975  const auto dims = row_major ? mat.get().cols() : mat.get().rows();
1976  if (size_t(dims) != dimensionality)
1977  throw std::runtime_error(
1978  "Error: 'dimensionality' must match column count in data matrix");
1979  if (DIM > 0 && int(dims) != DIM)
1980  throw std::runtime_error(
1981  "Data set dimensionality does not match the 'DIM' template argument");
1982  index =
1983  new index_t(static_cast<int>(dims), *this /* adaptor */,
1985  index->buildIndex();
1986  }
1987 
1988 public:
1990  KDTreeEigenMatrixAdaptor(const self_t &) = delete;
1991 
1992  ~KDTreeEigenMatrixAdaptor() { delete index; }
1993 
1994  const std::reference_wrapper<const MatrixType> m_data_matrix;
1995 
2002  inline void query(const num_t *query_point, const size_t num_closest,
2003  IndexType *out_indices, num_t *out_distances_sq,
2004  const int /* nChecks_IGNORED */ = 10) const {
2005  nanoflann::KNNResultSet<num_t, IndexType> resultSet(num_closest);
2006  resultSet.init(out_indices, out_distances_sq);
2007  index->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
2008  }
2009 
2013  const self_t &derived() const { return *this; }
2014  self_t &derived() { return *this; }
2015 
2016  // Must return the number of data points
2017  inline size_t kdtree_get_point_count() const {
2018  if(row_major)
2019  return m_data_matrix.get().rows();
2020  else
2021  return m_data_matrix.get().cols();
2022  }
2023 
2024  // Returns the dim'th component of the idx'th point in the class:
2025  inline num_t kdtree_get_pt(const IndexType idx, size_t dim) const {
2026  if(row_major)
2027  return m_data_matrix.get().coeff(idx, IndexType(dim));
2028  else
2029  return m_data_matrix.get().coeff(IndexType(dim), idx);
2030  }
2031 
2032  // Optional bounding-box computation: return false to default to a standard
2033  // bbox computation loop.
2034  // Return true if the BBOX was already computed by the class and returned in
2035  // "bb" so it can be avoided to redo it again. Look at bb.size() to find out
2036  // the expected dimensionality (e.g. 2 or 3 for point clouds)
2037  template <class BBOX> bool kdtree_get_bbox(BBOX & /*bb*/) const {
2038  return false;
2039  }
2040 
2043 }; // end of KDTreeEigenMatrixAdaptor // end of grouping
2047 } // namespace nanoflann
2048 
2049 #endif /* NANOFLANN_HPP_ */
d
size_t veclen(const Derived &obj)
Definition: nanoflann.hpp:817
void computeBoundingBox(BoundingBox &bbox)
Definition: nanoflann.hpp:1666
L2_Simple_Adaptor< T, DataSource > distance_L2_Simple
Definition: nanoflann.hpp:494
size_t radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< std::pair< IndexType, DistanceType >> &IndicesDists, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1639
void addPoints(IndexType start, IndexType end)
Definition: nanoflann.hpp:1883
void middleSplit_(Derived &obj, IndexType *ind, IndexType count, IndexType &index, int &cutfeat, DistanceType &cutval, const BoundingBox &bbox)
Definition: nanoflann.hpp:910
SO3_Adaptor< T, DataSource > distance_t
Definition: nanoflann.hpp:537
void init(const M_string &remappings)
BaseClassRef::DistanceType DistanceType
Definition: nanoflann.hpp:1490
const double PI
KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM > index_container_t
Definition: nanoflann.hpp:1812
void load_tree(Derived &obj, FILE *stream, NodePtr &tree)
Definition: nanoflann.hpp:1035
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
DistanceType accum_dist(const U a, const V b, int dim) const
CountType size() const
SO2_Adaptor(const DataSource &_data_source)
Definition: nanoflann.hpp:461
const DatasetAdaptor & dataset
The source of our data.
Definition: nanoflann.hpp:1475
size_t size(const Derived &obj) const
Definition: nanoflann.hpp:814
const DatasetAdaptor & dataset
The source of our data.
Definition: nanoflann.hpp:1801
void load_value(FILE *stream, T &value, size_t count=1)
Definition: nanoflann.hpp:291
KDTreeSingleIndexAdaptorParams index_params
Definition: nanoflann.hpp:1807
int divfeat
Dimension used for subdivision.
Definition: nanoflann.hpp:763
SO2_Adaptor< T, DataSource > distance_t
Definition: nanoflann.hpp:531
Distance::ElementType ElementType
Definition: nanoflann.hpp:751
void freeIndex(Derived &obj)
Definition: nanoflann.hpp:745
std::enable_if< has_resize< Container >::value, void >::type resize(Container &c, const size_t nElements)
Definition: nanoflann.hpp:104
KDTreeSingleIndexAdaptorParams index_params
Definition: nanoflann.hpp:1477
DistanceType accum_dist(const U a, const V b, const size_t) const
Definition: nanoflann.hpp:471
array_or_vector_selector< DIM, DistanceType >::container_t distance_vector_t
Definition: nanoflann.hpp:798
void loadIndex_(Derived &obj, FILE *stream)
Definition: nanoflann.hpp:1065
const size_t BLOCKSIZE
std::array< T, DIM > container_t
Definition: nanoflann.hpp:717
void searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindistsq, distance_vector_t &dists, const float epsError) const
Definition: nanoflann.hpp:1696
size_t knnSearch(const ElementType *query_point, const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq, const int=10) const
Definition: nanoflann.hpp:1613
IndexType right
Indices of points in leaf node.
Definition: nanoflann.hpp:760
Distance::DistanceType DistanceType
Definition: nanoflann.hpp:752
T pi_const()
Definition: nanoflann.hpp:79
DistanceType evalMetric(const T *a, const size_t b_idx, size_t size) const
Definition: nanoflann.hpp:463
size_t m_size
Number of current points in the dataset.
Definition: nanoflann.hpp:785
const DataSource & data_source
Definition: nanoflann.hpp:459
T abs(T x)
T * allocate(size_t count=1)
Definition: nanoflann.hpp:579
KDTreeSingleIndexDynamicAdaptor_ operator=(const KDTreeSingleIndexDynamicAdaptor_ &rhs)
Definition: nanoflann.hpp:1536
void init(IndexType *indices_, DistanceType *dists_)
BaseClassRef::distance_vector_t distance_vector_t
Definition: nanoflann.hpp:1502
NodePtr divideTree(Derived &obj, const IndexType left, const IndexType right, BoundingBox &bbox)
Definition: nanoflann.hpp:858
void saveIndex_(Derived &obj, FILE *stream)
Definition: nanoflann.hpp:1051
Node * child2
Child nodes (both=NULL mean its a leaf node)
Definition: nanoflann.hpp:767
DistanceType accum_dist(const U a, const V b, const size_t idx) const
Definition: nanoflann.hpp:505
void planeSplit(Derived &obj, IndexType *ind, const IndexType count, int cutfeat, DistanceType &cutval, IndexType &lim1, IndexType &lim2)
Definition: nanoflann.hpp:968
KDTreeSingleIndexDynamicAdaptor(const int dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams &params=KDTreeSingleIndexAdaptorParams(), const size_t maximumPointCount=1000000000U)
Definition: nanoflann.hpp:1857
DistanceType computeInitialDistances(const Derived &obj, const ElementType *vec, distance_vector_t &dists) const
Definition: nanoflann.hpp:1006
int dim
Dimensionality of each data point.
Definition: nanoflann.hpp:1809
size_t radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParams &searchParams=SearchParams()) const
Definition: nanoflann.hpp:1656
DistanceType evalMetric(const T *a, const size_t b_idx, size_t size) const
Definition: nanoflann.hpp:499
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1583
struct nanoflann::KDTreeBaseClass::Node::@0::nonleaf sub
std::vector< index_container_t > index
Definition: nanoflann.hpp:1813
nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType > BaseClassRef
Definition: nanoflann.hpp:1487
const size_t WORDSIZE
KDTreeSingleIndexDynamicAdaptor_(const int dimensionality, const DatasetAdaptor &inputData, std::vector< int > &treeIndex_, const KDTreeSingleIndexAdaptorParams &params=KDTreeSingleIndexAdaptorParams())
Definition: nanoflann.hpp:1518
ElementType dataset_get(const Derived &obj, size_t idx, int component) const
Helper accessor to the dataset points:
Definition: nanoflann.hpp:822
void computeMinMax(const Derived &obj, IndexType *ind, IndexType count, int element, ElementType &min_elem, ElementType &max_elem)
Definition: nanoflann.hpp:837
void save_value(FILE *stream, const T &value, size_t count=1)
Definition: nanoflann.hpp:279
_DistanceType DistanceType
Definition: nanoflann.hpp:457
array_or_vector_selector< DIM, Interval >::container_t BoundingBox
Definition: nanoflann.hpp:793
void save_tree(Derived &obj, FILE *stream, NodePtr tree)
Definition: nanoflann.hpp:1025
struct nanoflann::KDTreeBaseClass::Node::@0::leaf lr
size_t usedMemory(Derived &obj)
Definition: nanoflann.hpp:831
_DistanceType DistanceType
Definition: nanoflann.hpp:492
SO3_Adaptor(const DataSource &_data_source)
Definition: nanoflann.hpp:496
float eps
search for eps-approximate neighbours (default: 0)
Definition: nanoflann.hpp:563
const std::vector< index_container_t > & getAllIndices() const
Definition: nanoflann.hpp:1818
#define NULL
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1926
std::vector< IndexType > vind
Definition: nanoflann.hpp:779
union nanoflann::KDTreeBaseClass::Node::@0 node_type
std::enable_if< has_assign< Container >::value, void >::type assign(Container &c, const size_t nElements, const T &value)
Definition: nanoflann.hpp:124


mesh_map
Author(s): Sebastian Pütz
autogenerated on Tue May 24 2022 02:57:54