nanoflann
C++ header-only ANN library
 All Classes Functions Variables Typedefs Groups Pages
nanoflann.hpp
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 
46 #ifndef NANOFLANN_HPP_
47 #define NANOFLANN_HPP_
48 
49 #include <vector>
50 #include <cassert>
51 #include <algorithm>
52 #include <stdexcept>
53 #include <cstdio> // for fwrite()
54 #define _USE_MATH_DEFINES // Required by MSVC to define M_PI,etc. in <cmath>
55 #include <cmath> // for abs()
56 #include <cstdlib> // for abs()
57 #include <limits>
58 
59 // Avoid conflicting declaration of min/max macros in windows headers
60 #if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
61 # define NOMINMAX
62 # ifdef max
63 # undef max
64 # undef min
65 # endif
66 #endif
67 
68 namespace nanoflann
69 {
74  #define NANOFLANN_VERSION 0x123
75 
78  template <typename DistanceType, typename IndexType = size_t, typename CountType = size_t>
80  {
81  IndexType * indices;
82  DistanceType* dists;
83  CountType capacity;
84  CountType count;
85 
86  public:
87  inline KNNResultSet(CountType capacity_) : indices(0), dists(0), capacity(capacity_), count(0)
88  {
89  }
90 
91  inline void init(IndexType* indices_, DistanceType* dists_)
92  {
93  indices = indices_;
94  dists = dists_;
95  count = 0;
96  if (capacity)
97  dists[capacity-1] = (std::numeric_limits<DistanceType>::max)();
98  }
99 
100  inline CountType size() const
101  {
102  return count;
103  }
104 
105  inline bool full() const
106  {
107  return count == capacity;
108  }
109 
110 
115  inline bool addPoint(DistanceType dist, IndexType index)
116  {
117  CountType i;
118  for (i=count; i>0; --i) {
119 #ifdef NANOFLANN_FIRST_MATCH // If defined and two points have the same distance, the one with the lowest-index will be returned first.
120  if ( (dists[i-1]>dist) || ((dist==dists[i-1])&&(indices[i-1]>index)) ) {
121 #else
122  if (dists[i-1]>dist) {
123 #endif
124  if (i<capacity) {
125  dists[i] = dists[i-1];
126  indices[i] = indices[i-1];
127  }
128  }
129  else break;
130  }
131  if (i<capacity) {
132  dists[i] = dist;
133  indices[i] = index;
134  }
135  if (count<capacity) count++;
136 
137  // tell caller that the search shall continue
138  return true;
139  }
140 
141  inline DistanceType worstDist() const
142  {
143  return dists[capacity-1];
144  }
145  };
146 
149  {
151  template <typename PairType>
152  inline bool operator()(const PairType &p1, const PairType &p2) const {
153  return p1.second < p2.second;
154  }
155  };
156 
160  template <typename DistanceType, typename IndexType = size_t>
162  {
163  public:
164  const DistanceType radius;
165 
166  std::vector<std::pair<IndexType,DistanceType> >& m_indices_dists;
167 
168  inline RadiusResultSet(DistanceType radius_, std::vector<std::pair<IndexType,DistanceType> >& indices_dists) : radius(radius_), m_indices_dists(indices_dists)
169  {
170  init();
171  }
172 
173  inline ~RadiusResultSet() { }
174 
175  inline void init() { clear(); }
176  inline void clear() { m_indices_dists.clear(); }
177 
178  inline size_t size() const { return m_indices_dists.size(); }
179 
180  inline bool full() const { return true; }
181 
186  inline bool addPoint(DistanceType dist, IndexType index)
187  {
188  if (dist<radius)
189  m_indices_dists.push_back(std::make_pair(index,dist));
190  return true;
191  }
192 
193  inline DistanceType worstDist() const { return radius; }
194 
199  std::pair<IndexType,DistanceType> worst_item() const
200  {
201  if (m_indices_dists.empty()) throw std::runtime_error("Cannot invoke RadiusResultSet::worst_item() on an empty list of results.");
202  typedef typename std::vector<std::pair<IndexType,DistanceType> >::const_iterator DistIt;
203  DistIt it = std::max_element(m_indices_dists.begin(), m_indices_dists.end(), IndexDist_Sorter());
204  return *it;
205  }
206  };
207 
208 
214  template<typename T>
215  void save_value(FILE* stream, const T& value, size_t count = 1)
216  {
217  fwrite(&value, sizeof(value),count, stream);
218  }
219 
220  template<typename T>
221  void save_value(FILE* stream, const std::vector<T>& value)
222  {
223  size_t size = value.size();
224  fwrite(&size, sizeof(size_t), 1, stream);
225  fwrite(&value[0], sizeof(T), size, stream);
226  }
227 
228  template<typename T>
229  void load_value(FILE* stream, T& value, size_t count = 1)
230  {
231  size_t read_cnt = fread(&value, sizeof(value), count, stream);
232  if (read_cnt != count) {
233  throw std::runtime_error("Cannot read from file");
234  }
235  }
236 
237 
238  template<typename T>
239  void load_value(FILE* stream, std::vector<T>& value)
240  {
241  size_t size;
242  size_t read_cnt = fread(&size, sizeof(size_t), 1, stream);
243  if (read_cnt!=1) {
244  throw std::runtime_error("Cannot read from file");
245  }
246  value.resize(size);
247  read_cnt = fread(&value[0], sizeof(T), size, stream);
248  if (read_cnt!=size) {
249  throw std::runtime_error("Cannot read from file");
250  }
251  }
258  struct Metric
259  {
260  };
261 
267  template<class T, class DataSource, typename _DistanceType = T>
268  struct L1_Adaptor
269  {
270  typedef T ElementType;
271  typedef _DistanceType DistanceType;
272 
273  const DataSource &data_source;
274 
275  L1_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
276 
277  inline DistanceType evalMetric(const T* a, const size_t b_idx, size_t size, DistanceType worst_dist = -1) const
278  {
279  DistanceType result = DistanceType();
280  const T* last = a + size;
281  const T* lastgroup = last - 3;
282  size_t d = 0;
283 
284  /* Process 4 items with each loop for efficiency. */
285  while (a < lastgroup) {
286  const DistanceType diff0 = std::abs(a[0] - data_source.kdtree_get_pt(b_idx,d++));
287  const DistanceType diff1 = std::abs(a[1] - data_source.kdtree_get_pt(b_idx,d++));
288  const DistanceType diff2 = std::abs(a[2] - data_source.kdtree_get_pt(b_idx,d++));
289  const DistanceType diff3 = std::abs(a[3] - data_source.kdtree_get_pt(b_idx,d++));
290  result += diff0 + diff1 + diff2 + diff3;
291  a += 4;
292  if ((worst_dist>0)&&(result>worst_dist)) {
293  return result;
294  }
295  }
296  /* Process last 0-3 components. Not needed for standard vector lengths. */
297  while (a < last) {
298  result += std::abs( *a++ - data_source.kdtree_get_pt(b_idx,d++) );
299  }
300  return result;
301  }
302 
303  template <typename U, typename V>
304  inline DistanceType accum_dist(const U a, const V b, int ) const
305  {
306  return std::abs(a-b);
307  }
308  };
309 
315  template<class T, class DataSource, typename _DistanceType = T>
316  struct L2_Adaptor
317  {
318  typedef T ElementType;
319  typedef _DistanceType DistanceType;
320 
321  const DataSource &data_source;
322 
323  L2_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
324 
325  inline DistanceType evalMetric(const T* a, const size_t b_idx, size_t size, DistanceType worst_dist = -1) const
326  {
327  DistanceType result = DistanceType();
328  const T* last = a + size;
329  const T* lastgroup = last - 3;
330  size_t d = 0;
331 
332  /* Process 4 items with each loop for efficiency. */
333  while (a < lastgroup) {
334  const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx,d++);
335  const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx,d++);
336  const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx,d++);
337  const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx,d++);
338  result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
339  a += 4;
340  if ((worst_dist>0)&&(result>worst_dist)) {
341  return result;
342  }
343  }
344  /* Process last 0-3 components. Not needed for standard vector lengths. */
345  while (a < last) {
346  const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx,d++);
347  result += diff0 * diff0;
348  }
349  return result;
350  }
351 
352  template <typename U, typename V>
353  inline DistanceType accum_dist(const U a, const V b, int ) const
354  {
355  return (a-b)*(a-b);
356  }
357  };
358 
364  template<class T, class DataSource, typename _DistanceType = T>
366  {
367  typedef T ElementType;
368  typedef _DistanceType DistanceType;
369 
370  const DataSource &data_source;
371 
372  L2_Simple_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
373 
374  inline DistanceType evalMetric(const T* a, const size_t b_idx, size_t size) const {
375  DistanceType result = DistanceType();
376  for (int i=0; i<size; ++i) {
377  const DistanceType diff = a[i] - data_source.kdtree_get_pt(b_idx, i);
378  result += diff * diff;
379  }
380  return result;
381  }
382 
383  template <typename U, typename V>
384  inline DistanceType accum_dist(const U a, const V b, int ) const
385  {
386  return (a-b)*(a-b);
387  }
388  };
389 
396  template<class T, class DataSource, typename _DistanceType = T>
397  struct SO2_Adaptor
398  {
399  typedef T ElementType;
400  typedef _DistanceType DistanceType;
401 
402  const DataSource &data_source;
403 
404  SO2_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
405 
406  inline DistanceType evalMetric(const T* a, const size_t b_idx, size_t size) const {
407  DistanceType result = DistanceType();
408  result = data_source.kdtree_get_pt(b_idx, 0) - a[0];
409  if (result > M_PI)
410  result -= 2. * M_PI;
411  else if (result < -M_PI)
412  result += 2. * M_PI;
413  return result;
414  }
415 
416  template <typename U, typename V>
417  inline DistanceType accum_dist(const U a, const V b, int ) const
418  {
419  DistanceType result = DistanceType();
420  result = b - a;
421  if (result > M_PI)
422  result -= 2. * M_PI;
423  else if (result < -M_PI)
424  result += 2. * M_PI;
425  return result;
426  }
427  };
428 
434  template<class T, class DataSource, typename _DistanceType = T>
436  {
437  typedef T ElementType;
438  typedef _DistanceType DistanceType;
439 
440  const DataSource &data_source;
441 
442  SO3_InnerProdQuat_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
443 
444  inline DistanceType evalMetric(const T* a, const size_t b_idx, size_t size) const {
445  DistanceType result = DistanceType();
446  for (int i=0; i<size; ++i) {
447  const DistanceType diff = a[i] * data_source.kdtree_get_pt(b_idx, i);
448  result += diff;
449  }
450  result = 1 - std::abs(result);
451  return result;
452  }
453 
454  template <typename U, typename V>
455  inline DistanceType accum_dist(const U a, const V b, int ) const
456  {
457  return (a-b)*(a-b); // Update this
458  }
459  };
460 
466  template<class T, class DataSource, typename _DistanceType = T>
468  {
469  typedef T ElementType;
470  typedef _DistanceType DistanceType;
471 
472  const DataSource &data_source;
473 
474  SO3_acosInnerProdQuat_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
475 
476  inline DistanceType evalMetric(const T* a, const size_t b_idx, size_t size) const {
477  DistanceType result = DistanceType();
478  for (int i=0; i<size; ++i) {
479  const DistanceType diff = a[i] * data_source.kdtree_get_pt(b_idx, i);
480  result += diff;
481  }
482  result = std::acos(std::abs(result));
483  return result;
484  }
485 
486  template <typename U, typename V>
487  inline DistanceType accum_dist(const U a, const V b, int ) const
488  {
489  return (a-b)*(a-b); // Update this
490  }
491  };
492 
494  struct metric_L1 : public Metric
495  {
496  template<class T, class DataSource>
497  struct traits {
499  };
500  };
502  struct metric_L2 : public Metric
503  {
504  template<class T, class DataSource>
505  struct traits {
507  };
508  };
510  struct metric_L2_Simple : public Metric
511  {
512  template<class T, class DataSource>
513  struct traits {
515  };
516  };
518  struct metric_SO2 : public Metric
519  {
520  template<class T, class DataSource>
521  struct traits {
523  };
524  };
527  {
528  template<class T, class DataSource>
529  struct traits {
531  };
532  };
535  {
536  template<class T, class DataSource>
537  struct traits {
539  };
540  };
541 
549  {
550  KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size = 10) :
551  leaf_max_size(_leaf_max_size)
552  {}
553 
554  size_t leaf_max_size;
555  };
556 
559  {
561  SearchParams(int checks_IGNORED_ = 32, float eps_ = 0, bool sorted_ = true ) :
562  checks(checks_IGNORED_), eps(eps_), sorted(sorted_) {}
563 
564  int checks;
565  float eps;
566  bool sorted;
567  };
581  template <typename T>
582  inline T* allocate(size_t count = 1)
583  {
584  T* mem = static_cast<T*>( ::malloc(sizeof(T)*count));
585  return mem;
586  }
587 
588 
604  const size_t WORDSIZE=16;
605  const size_t BLOCKSIZE=8192;
606 
608  {
609  /* We maintain memory alignment to word boundaries by requiring that all
610  allocations be in multiples of the machine wordsize. */
611  /* Size of machine word in bytes. Must be power of 2. */
612  /* Minimum number of bytes requested at a time from the system. Must be multiple of WORDSIZE. */
613 
614 
615  size_t remaining; /* Number of bytes left in current block of storage. */
616  void* base; /* Pointer to base of current block of storage. */
617  void* loc; /* Current location in block to next allocate memory. */
618 
619  void internal_init()
620  {
621  remaining = 0;
622  base = NULL;
623  usedMemory = 0;
624  wastedMemory = 0;
625  }
626 
627  public:
628  size_t usedMemory;
629  size_t wastedMemory;
630 
635  internal_init();
636  }
637 
642  free_all();
643  }
644 
646  void free_all()
647  {
648  while (base != NULL) {
649  void *prev = *(static_cast<void**>( base)); /* Get pointer to prev block. */
650  ::free(base);
651  base = prev;
652  }
653  internal_init();
654  }
655 
660  void* malloc(const size_t req_size)
661  {
662  /* Round size up to a multiple of wordsize. The following expression
663  only works for WORDSIZE that is a power of 2, by masking last bits of
664  incremented size to zero.
665  */
666  const size_t size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1);
667 
668  /* Check whether a new block must be allocated. Note that the first word
669  of a block is reserved for a pointer to the previous block.
670  */
671  if (size > remaining) {
672 
673  wastedMemory += remaining;
674 
675  /* Allocate new storage. */
676  const size_t blocksize = (size + sizeof(void*) + (WORDSIZE-1) > BLOCKSIZE) ?
677  size + sizeof(void*) + (WORDSIZE-1) : BLOCKSIZE;
678 
679  // use the standard C malloc to allocate memory
680  void* m = ::malloc(blocksize);
681  if (!m) {
682  fprintf(stderr,"Failed to allocate memory.\n");
683  return NULL;
684  }
685 
686  /* Fill first word of new block with pointer to previous block. */
687  static_cast<void**>(m)[0] = base;
688  base = m;
689 
690  size_t shift = 0;
691  //int size_t = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & (WORDSIZE-1))) & (WORDSIZE-1);
692 
693  remaining = blocksize - sizeof(void*) - shift;
694  loc = (static_cast<char*>(m) + sizeof(void*) + shift);
695  }
696  void* rloc = loc;
697  loc = static_cast<char*>(loc) + size;
698  remaining -= size;
699 
700  usedMemory += size;
701 
702  return rloc;
703  }
704 
712  template <typename T>
713  T* allocate(const size_t count = 1)
714  {
715  T* mem = static_cast<T*>(this->malloc(sizeof(T)*count));
716  return mem;
717  }
718 
719  };
725  // ---------------- CArray -------------------------
751  template <typename T, std::size_t N>
752  class CArray {
753  public:
754  T elems[N]; // fixed-size array of elements of type T
755 
756  public:
757  // type definitions
758  typedef T value_type;
759  typedef T* iterator;
760  typedef const T* const_iterator;
761  typedef T& reference;
762  typedef const T& const_reference;
763  typedef std::size_t size_type;
764  typedef std::ptrdiff_t difference_type;
765 
766  // iterator support
767  inline iterator begin() { return elems; }
768  inline const_iterator begin() const { return elems; }
769  inline iterator end() { return elems+N; }
770  inline const_iterator end() const { return elems+N; }
771 
772  // reverse iterator support
773 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
774  typedef std::reverse_iterator<iterator> reverse_iterator;
775  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
776 #elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
777  // workaround for broken reverse_iterator in VC7
778  typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator,
779  reference, iterator, reference> > reverse_iterator;
780  typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,
781  const_reference, iterator, reference> > const_reverse_iterator;
782 #else
783  // workaround for broken reverse_iterator implementations
784  typedef std::reverse_iterator<iterator,T> reverse_iterator;
785  typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
786 #endif
787 
788  reverse_iterator rbegin() { return reverse_iterator(end()); }
789  const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
790  reverse_iterator rend() { return reverse_iterator(begin()); }
791  const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
792  // operator[]
793  inline reference operator[](size_type i) { return elems[i]; }
794  inline const_reference operator[](size_type i) const { return elems[i]; }
795  // at() with range check
796  reference at(size_type i) { rangecheck(i); return elems[i]; }
797  const_reference at(size_type i) const { rangecheck(i); return elems[i]; }
798  // front() and back()
799  reference front() { return elems[0]; }
800  const_reference front() const { return elems[0]; }
801  reference back() { return elems[N-1]; }
802  const_reference back() const { return elems[N-1]; }
803  // size is constant
804  static inline size_type size() { return N; }
805  static bool empty() { return false; }
806  static size_type max_size() { return N; }
807  enum { static_size = N };
809  inline void resize(const size_t nElements) { if (nElements!=N) throw std::logic_error("Try to change the size of a CArray."); }
810  // swap (note: linear complexity in N, constant for given instantiation)
811  void swap (CArray<T,N>& y) { std::swap_ranges(begin(),end(),y.begin()); }
812  // direct access to data (read-only)
813  const T* data() const { return elems; }
814  // use array as C array (direct read/write access to data)
815  T* data() { return elems; }
816  // assignment with type conversion
817  template <typename T2> CArray<T,N>& operator= (const CArray<T2,N>& rhs) {
818  std::copy(rhs.begin(),rhs.end(), begin());
819  return *this;
820  }
821  // assign one value to all elements
822  inline void assign (const T& value) { for (size_t i=0;i<N;i++) elems[i]=value; }
823  // assign (compatible with std::vector's one) (by JLBC for MRPT)
824  void assign (const size_t n, const T& value) { assert(N==n); for (size_t i=0;i<N;i++) elems[i]=value; }
825  private:
826  // check range (may be private because it is static)
827  static void rangecheck (size_type i) { if (i >= size()) { throw std::out_of_range("CArray<>: index out of range"); } }
828  }; // end of CArray
829 
833  template <int DIM, typename T>
835  {
836  typedef CArray<T,DIM> container_t;
837  };
839  template <typename T>
841  typedef std::vector<T> container_t;
842  };
843 
857  template<class Derived, typename Distance, class DatasetAdaptor,int DIM = -1, typename IndexType = size_t>
859  {
860 
861  public:
863  void freeIndex(Derived &obj)
864  {
865  obj.pool.free_all();
866  obj.root_node=NULL;
867  obj.m_size_at_index_build = 0;
868  }
869 
870  protected:
871  typedef typename Distance::ElementType ElementType;
872  typedef typename Distance::DistanceType DistanceType;
873 
874  /*--------------------- Internal Data Structures --------------------------*/
875  struct Node
876  {
878  union {
879  struct leaf
880  {
881  IndexType left, right;
882  } lr;
883  struct nonleaf
884  {
885  int divfeat;
886  DistanceType divlow, divhigh;
887  } sub;
888  } node_type;
889  Node* child1, * child2;
890  };
891 
892  typedef Node* NodePtr;
893 
894  struct Interval
895  {
896  ElementType low, high;
897  };
898 
901 
904 
906  size_t size(const Derived &obj) const { return obj.m_size; }
907 
909  size_t veclen(const Derived &obj) {
910  return static_cast<size_t>(DIM>0 ? DIM : obj.dim);
911  }
912 
917  size_t usedMemory(Derived &obj)
918  {
919  return obj.pool.usedMemory+obj.pool.wastedMemory+obj.dataset.kdtree_get_point_count()*sizeof(IndexType); // pool memory and vind array memory
920  }
921 
922  void computeMinMax(const Derived &obj, IndexType* ind, IndexType count, int element, ElementType& min_elem, ElementType& max_elem)
923  {
924  min_elem = obj.dataset_get(ind[0],element);
925  max_elem = obj.dataset_get(ind[0],element);
926  for (IndexType i=1; i<count; ++i) {
927  ElementType val = obj.dataset_get(ind[i],element);
928  if (val<min_elem) min_elem = val;
929  if (val>max_elem) max_elem = val;
930  }
931  }
932 
940  NodePtr divideTree(Derived &obj, const IndexType left, const IndexType right, BoundingBox& bbox)
941  {
942  NodePtr node = obj.pool.allocate<Node>(); // allocate memory
943 
944  /* If too few exemplars remain, then make this a leaf node. */
945  if ( (right-left) <= static_cast<IndexType>(obj.m_leaf_max_size) ) {
946  node->child1 = node->child2 = NULL; /* Mark as leaf node. */
947  node->node_type.lr.left = left;
948  node->node_type.lr.right = right;
949 
950  // compute bounding-box of leaf points
951  for (int i=0; i<(DIM>0 ? DIM : obj.dim); ++i) {
952  bbox[i].low = obj.dataset_get(obj.vind[left],i);
953  bbox[i].high = obj.dataset_get(obj.vind[left],i);
954  }
955  for (IndexType k=left+1; k<right; ++k) {
956  for (int i=0; i<(DIM>0 ? DIM : obj.dim); ++i) {
957  if (bbox[i].low>obj.dataset_get(obj.vind[k],i)) bbox[i].low=obj.dataset_get(obj.vind[k],i);
958  if (bbox[i].high<obj.dataset_get(obj.vind[k],i)) bbox[i].high=obj.dataset_get(obj.vind[k],i);
959  }
960  }
961  }
962  else {
963  IndexType idx;
964  int cutfeat;
965  DistanceType cutval;
966  middleSplit_(obj, &obj.vind[0]+left, right-left, idx, cutfeat, cutval, bbox);
967 
968  node->node_type.sub.divfeat = cutfeat;
969 
970  BoundingBox left_bbox(bbox);
971  left_bbox[cutfeat].high = cutval;
972  node->child1 = divideTree(obj, left, left+idx, left_bbox);
973 
974  BoundingBox right_bbox(bbox);
975  right_bbox[cutfeat].low = cutval;
976  node->child2 = divideTree(obj, left+idx, right, right_bbox);
977 
978  node->node_type.sub.divlow = left_bbox[cutfeat].high;
979  node->node_type.sub.divhigh = right_bbox[cutfeat].low;
980 
981  for (int i=0; i<(DIM>0 ? DIM : obj.dim); ++i) {
982  bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
983  bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
984  }
985  }
986 
987  return node;
988  }
989 
990  void middleSplit_(Derived &obj, IndexType* ind, IndexType count, IndexType& index, int& cutfeat, DistanceType& cutval, const BoundingBox& bbox)
991  {
992  const DistanceType EPS=static_cast<DistanceType>(0.00001);
993  ElementType max_span = bbox[0].high-bbox[0].low;
994  for (int i=1; i<(DIM>0 ? DIM : obj.dim); ++i) {
995  ElementType span = bbox[i].high-bbox[i].low;
996  if (span>max_span) {
997  max_span = span;
998  }
999  }
1000  ElementType max_spread = -1;
1001  cutfeat = 0;
1002  for (int i=0; i<(DIM>0 ? DIM : obj.dim); ++i) {
1003  ElementType span = bbox[i].high-bbox[i].low;
1004  if (span>(1-EPS)*max_span) {
1005  ElementType min_elem, max_elem;
1006  computeMinMax(obj, ind, count, i, min_elem, max_elem);
1007  ElementType spread = max_elem-min_elem;;
1008  if (spread>max_spread) {
1009  cutfeat = i;
1010  max_spread = spread;
1011  }
1012  }
1013  }
1014  // split in the middle
1015  DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2;
1016  ElementType min_elem, max_elem;
1017  computeMinMax(obj, ind, count, cutfeat, min_elem, max_elem);
1018 
1019  if (split_val<min_elem) cutval = min_elem;
1020  else if (split_val>max_elem) cutval = max_elem;
1021  else cutval = split_val;
1022 
1023  IndexType lim1, lim2;
1024  planeSplit(obj, ind, count, cutfeat, cutval, lim1, lim2);
1025 
1026  if (lim1>count/2) index = lim1;
1027  else if (lim2<count/2) index = lim2;
1028  else index = count/2;
1029  }
1030 
1040  void planeSplit(Derived &obj, IndexType* ind, const IndexType count, int cutfeat, DistanceType &cutval, IndexType& lim1, IndexType& lim2)
1041  {
1042  /* Move vector indices for left subtree to front of list. */
1043  IndexType left = 0;
1044  IndexType right = count-1;
1045  for (;; ) {
1046  while (left<=right && obj.dataset_get(ind[left],cutfeat)<cutval) ++left;
1047  while (right && left<=right && obj.dataset_get(ind[right],cutfeat)>=cutval) --right;
1048  if (left>right || !right) break; // "!right" was added to support unsigned Index types
1049  std::swap(ind[left], ind[right]);
1050  ++left;
1051  --right;
1052  }
1053  /* If either list is empty, it means that all remaining features
1054  * are identical. Split in the middle to maintain a balanced tree.
1055  */
1056  lim1 = left;
1057  right = count-1;
1058  for (;; ) {
1059  while (left<=right && obj.dataset_get(ind[left],cutfeat)<=cutval) ++left;
1060  while (right && left<=right && obj.dataset_get(ind[right],cutfeat)>cutval) --right;
1061  if (left>right || !right) break; // "!right" was added to support unsigned Index types
1062  std::swap(ind[left], ind[right]);
1063  ++left;
1064  --right;
1065  }
1066  lim2 = left;
1067  }
1068 
1069  DistanceType computeInitialDistances(const Derived &obj, const ElementType* vec, distance_vector_t& dists) const
1070  {
1071  assert(vec);
1072  DistanceType distsq = DistanceType();
1073 
1074  for (int i = 0; i < (DIM>0 ? DIM : obj.dim); ++i) {
1075  if (vec[i] < obj.root_bbox[i].low) {
1076  dists[i] = obj.distance.accum_dist(vec[i], obj.root_bbox[i].low, i);
1077  distsq += dists[i];
1078  }
1079  if (vec[i] > obj.root_bbox[i].high) {
1080  dists[i] = obj.distance.accum_dist(vec[i], obj.root_bbox[i].high, i);
1081  distsq += dists[i];
1082  }
1083  }
1084  return distsq;
1085  }
1086 
1087  };
1088 
1089 
1127  template <typename Distance, class DatasetAdaptor,int DIM = -1, typename IndexType = size_t>
1128  class KDTreeSingleIndexAdaptor : public KDTreeBaseClass<KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM, IndexType>, Distance, DatasetAdaptor, DIM, IndexType>
1129  {
1130  private:
1133  public:
1134  typedef typename Distance::ElementType ElementType;
1135  typedef typename Distance::DistanceType DistanceType;
1136 
1140  std::vector<IndexType> vind;
1141 
1142  size_t m_leaf_max_size;
1143 
1144 
1148  const DatasetAdaptor &dataset;
1149 
1150  const KDTreeSingleIndexAdaptorParams index_params;
1151 
1152  size_t m_size;
1154  int dim;
1155 
1156 
1158  typedef Node* NodePtr;
1159 
1163 
1166 
1169  BoundingBox root_bbox;
1170 
1179 
1180 
1181  Distance distance;
1182 
1196  KDTreeSingleIndexAdaptor(const int dimensionality, const DatasetAdaptor& inputData, const KDTreeSingleIndexAdaptorParams& params = KDTreeSingleIndexAdaptorParams() ) :
1197  dataset(inputData), index_params(params), root_node(NULL), distance(inputData)
1198  {
1199  m_size = dataset.kdtree_get_point_count();
1200  m_size_at_index_build = m_size;
1201  dim = dimensionality;
1202  if (DIM>0) dim=DIM;
1203  m_leaf_max_size = params.leaf_max_size;
1204 
1205  // Create a permutable array of indices to the input vectors.
1206  init_vind();
1207  }
1208 
1211 
1215  void buildIndex()
1216  {
1217  init_vind();
1218  this->freeIndex(*this);
1219  m_size_at_index_build = m_size;
1220  if(m_size == 0) return;
1221  computeBoundingBox(root_bbox);
1222  root_node = this->divideTree(*this, 0, m_size, root_bbox ); // construct the tree
1223  }
1224 
1240  template <typename RESULTSET>
1241  bool findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParams& searchParams) const
1242  {
1243  assert(vec);
1244  if (this->size(*this) == 0)
1245  return false;
1246  if (!root_node)
1247  throw std::runtime_error("[nanoflann] findNeighbors() called before building the index.");
1248  float epsError = 1+searchParams.eps;
1249 
1250  distance_vector_t dists; // fixed or variable-sized container (depending on DIM)
1251  dists.assign((DIM>0 ? DIM : dim) ,0); // Fill it with zeros.
1252  DistanceType distsq = this->computeInitialDistances(*this, vec, dists);
1253  searchLevel(result, vec, root_node, distsq, dists, epsError); // "count_leaf" parameter removed since was neither used nor returned to the user.
1254  return result.full();
1255  }
1256 
1265  size_t knnSearch(const ElementType *query_point, const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq, const int /* nChecks_IGNORED */ = 10) const
1266  {
1267  nanoflann::KNNResultSet<DistanceType,IndexType> resultSet(num_closest);
1268  resultSet.init(out_indices, out_distances_sq);
1269  this->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
1270  return resultSet.size();
1271  }
1272 
1285  size_t radiusSearch(const ElementType *query_point,const DistanceType &radius, std::vector<std::pair<IndexType,DistanceType> >& IndicesDists, const SearchParams& searchParams) const
1286  {
1287  RadiusResultSet<DistanceType,IndexType> resultSet(radius,IndicesDists);
1288  const size_t nFound = radiusSearchCustomCallback(query_point,resultSet,searchParams);
1289  if (searchParams.sorted)
1290  std::sort(IndicesDists.begin(),IndicesDists.end(), IndexDist_Sorter() );
1291  return nFound;
1292  }
1293 
1299  template <class SEARCH_CALLBACK>
1300  size_t radiusSearchCustomCallback(const ElementType *query_point,SEARCH_CALLBACK &resultSet, const SearchParams& searchParams = SearchParams() ) const
1301  {
1302  this->findNeighbors(resultSet, query_point, searchParams);
1303  return resultSet.size();
1304  }
1305 
1308  public:
1310  void init_vind()
1311  {
1312  // Create a permutable array of indices to the input vectors.
1313  m_size = dataset.kdtree_get_point_count();
1314  if (vind.size()!=m_size) vind.resize(m_size);
1315  for (size_t i = 0; i < m_size; i++) vind[i] = i;
1316  }
1317 
1319  inline ElementType dataset_get(size_t idx, int component) const {
1320  return dataset.kdtree_get_pt(idx,component);
1321  }
1322 
1323 
1324  void save_tree(FILE* stream, NodePtr tree)
1325  {
1326  save_value(stream, *tree);
1327  if (tree->child1!=NULL) {
1328  save_tree(stream, tree->child1);
1329  }
1330  if (tree->child2!=NULL) {
1331  save_tree(stream, tree->child2);
1332  }
1333  }
1334 
1335 
1336  void load_tree(FILE* stream, NodePtr& tree)
1337  {
1338  tree = pool.allocate<Node>();
1339  load_value(stream, *tree);
1340  if (tree->child1!=NULL) {
1341  load_tree(stream, tree->child1);
1342  }
1343  if (tree->child2!=NULL) {
1344  load_tree(stream, tree->child2);
1345  }
1346  }
1347 
1348  void computeBoundingBox(BoundingBox& bbox)
1349  {
1350  bbox.resize((DIM>0 ? DIM : dim));
1351  if (dataset.kdtree_get_bbox(bbox))
1352  {
1353  // Done! It was implemented in derived class
1354  }
1355  else
1356  {
1357  const size_t N = dataset.kdtree_get_point_count();
1358  if (!N) throw std::runtime_error("[nanoflann] computeBoundingBox() called but no data points found.");
1359  for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1360  bbox[i].low =
1361  bbox[i].high = dataset_get(0,i);
1362  }
1363  for (size_t k=1; k<N; ++k) {
1364  for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1365  if (dataset_get(k,i)<bbox[i].low) bbox[i].low = dataset_get(k,i);
1366  if (dataset_get(k,i)>bbox[i].high) bbox[i].high = dataset_get(k,i);
1367  }
1368  }
1369  }
1370  }
1371 
1377  template <class RESULTSET>
1378  bool searchLevel(RESULTSET& result_set, const ElementType* vec, const NodePtr node, DistanceType mindistsq,
1379  distance_vector_t& dists, const float epsError) const
1380  {
1381  /* If this is a leaf node, then do check and return. */
1382  if ((node->child1 == NULL)&&(node->child2 == NULL)) {
1383  //count_leaf += (node->lr.right-node->lr.left); // Removed since was neither used nor returned to the user.
1384  DistanceType worst_dist = result_set.worstDist();
1385  for (IndexType i=node->node_type.lr.left; i<node->node_type.lr.right; ++i) {
1386  const IndexType index = vind[i];// reorder... : i;
1387  DistanceType dist = distance.evalMetric(vec, index, (DIM>0 ? DIM : dim));
1388  if (dist<worst_dist) {
1389  if(!result_set.addPoint(dist,vind[i])) {
1390  // the resultset doesn't want to receive any more points, we're done searching!
1391  return false;
1392  }
1393  }
1394  }
1395  return true;
1396  }
1397 
1398  /* Which child branch should be taken first? */
1399  int idx = node->node_type.sub.divfeat;
1400  ElementType val = vec[idx];
1401  DistanceType diff1 = val - node->node_type.sub.divlow;
1402  DistanceType diff2 = val - node->node_type.sub.divhigh;
1403 
1404  NodePtr bestChild;
1405  NodePtr otherChild;
1406  DistanceType cut_dist;
1407  if ((diff1+diff2)<0) {
1408  bestChild = node->child1;
1409  otherChild = node->child2;
1410  cut_dist = distance.accum_dist(val, node->node_type.sub.divhigh, idx);
1411  }
1412  else {
1413  bestChild = node->child2;
1414  otherChild = node->child1;
1415  cut_dist = distance.accum_dist( val, node->node_type.sub.divlow, idx);
1416  }
1417 
1418  /* Call recursively to search next level down. */
1419  if(!searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError)) {
1420  // the resultset doesn't want to receive any more points, we're done searching!
1421  return false;
1422  }
1423 
1424  DistanceType dst = dists[idx];
1425  mindistsq = mindistsq + cut_dist - dst;
1426  dists[idx] = cut_dist;
1427  if (mindistsq*epsError<=result_set.worstDist()) {
1428  if(!searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError)) {
1429  // the resultset doesn't want to receive any more points, we're done searching!
1430  return false;
1431  }
1432  }
1433  dists[idx] = dst;
1434  return true;
1435  }
1436 
1437  public:
1442  void saveIndex(FILE* stream)
1443  {
1444  save_value(stream, m_size);
1445  save_value(stream, dim);
1446  save_value(stream, root_bbox);
1447  save_value(stream, m_leaf_max_size);
1448  save_value(stream, vind);
1449  save_tree(stream, root_node);
1450  }
1451 
1456  void loadIndex(FILE* stream)
1457  {
1458  load_value(stream, m_size);
1459  load_value(stream, dim);
1460  load_value(stream, root_bbox);
1461  load_value(stream, m_leaf_max_size);
1462  load_value(stream, vind);
1463  load_tree(stream, root_node);
1464  }
1465 
1466  }; // class KDTree
1467 
1468 
1502  template <typename Distance, class DatasetAdaptor,int DIM = -1, typename IndexType = size_t>
1503  class KDTreeSingleIndexDynamicAdaptor_ : public KDTreeBaseClass<KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM, IndexType>, Distance, DatasetAdaptor, DIM, IndexType>
1504  {
1505  public:
1506  typedef typename Distance::ElementType ElementType;
1507  typedef typename Distance::DistanceType DistanceType;
1508 
1512  std::vector<IndexType> vind;
1513 
1514  size_t m_leaf_max_size;
1515 
1516 
1520  DatasetAdaptor &dataset;
1521 
1522  KDTreeSingleIndexAdaptorParams index_params;
1523 
1524  std::vector<int> &treeIndex;
1525 
1526  size_t m_size;
1528  int dim;
1529 
1530 
1532  typedef Node* NodePtr;
1533 
1537 
1540 
1543  BoundingBox root_bbox;
1544 
1553 
1554  public:
1555 
1556  Distance distance;
1557 
1571  KDTreeSingleIndexDynamicAdaptor_(const int dimensionality, DatasetAdaptor& inputData, std::vector<int>& treeIndex_, const KDTreeSingleIndexAdaptorParams& params = KDTreeSingleIndexAdaptorParams()) :
1572  dataset(inputData), index_params(params), treeIndex(treeIndex_), root_node(NULL), distance(inputData)
1573  {
1574  m_size = 0;
1575  m_size_at_index_build = 0;
1576  dim = dimensionality;
1577  if (DIM>0) dim=DIM;
1578  m_leaf_max_size = params.leaf_max_size;
1579  }
1580 
1581 
1585  std::swap( vind, tmp.vind );
1586  std::swap( m_leaf_max_size, tmp.m_leaf_max_size );
1587  std::swap( index_params, tmp.index_params );
1588  std::swap( treeIndex, tmp.treeIndex );
1589  std::swap( m_size, tmp.m_size );
1590  std::swap( m_size_at_index_build, tmp.m_size_at_index_build );
1591  std::swap( root_node, tmp.root_node );
1592  std::swap( root_bbox, tmp.root_bbox );
1593  std::swap( pool, tmp.pool );
1594  return *this;
1595  }
1596 
1599 
1603  void buildIndex()
1604  {
1605  m_size = vind.size();
1606  this->freeIndex(*this);
1607  m_size_at_index_build = m_size;
1608  if(m_size == 0) return;
1609  computeBoundingBox(root_bbox);
1610  root_node = this->divideTree(*this, 0, m_size, root_bbox ); // construct the tree
1611  }
1612 
1628  template <typename RESULTSET>
1629  bool findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParams& searchParams) const
1630  {
1631  assert(vec);
1632  if (this->size(*this) == 0)
1633  return false;
1634  if (!root_node)
1635  return false;
1636  float epsError = 1+searchParams.eps;
1637 
1638  distance_vector_t dists; // fixed or variable-sized container (depending on DIM)
1639  dists.assign((DIM>0 ? DIM : dim) ,0); // Fill it with zeros.
1640  DistanceType distsq = this->computeInitialDistances(*this, vec, dists);
1641  searchLevel(result, vec, root_node, distsq, dists, epsError); // "count_leaf" parameter removed since was neither used nor returned to the user.
1642  return result.full();
1643  }
1644 
1653  size_t knnSearch(const ElementType *query_point, const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq, const int /* nChecks_IGNORED */ = 10) const
1654  {
1655  nanoflann::KNNResultSet<DistanceType,IndexType> resultSet(num_closest);
1656  resultSet.init(out_indices, out_distances_sq);
1657  this->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
1658  return resultSet.size();
1659  }
1660 
1673  size_t radiusSearch(const ElementType *query_point,const DistanceType &radius, std::vector<std::pair<IndexType,DistanceType> >& IndicesDists, const SearchParams& searchParams) const
1674  {
1675  RadiusResultSet<DistanceType,IndexType> resultSet(radius,IndicesDists);
1676  const size_t nFound = radiusSearchCustomCallback(query_point,resultSet,searchParams);
1677  if (searchParams.sorted)
1678  std::sort(IndicesDists.begin(),IndicesDists.end(), IndexDist_Sorter() );
1679  return nFound;
1680  }
1681 
1687  template <class SEARCH_CALLBACK>
1688  size_t radiusSearchCustomCallback(const ElementType *query_point,SEARCH_CALLBACK &resultSet, const SearchParams& searchParams = SearchParams() ) const
1689  {
1690  this->findNeighbors(resultSet, query_point, searchParams);
1691  return resultSet.size();
1692  }
1693 
1696  public:
1698  inline ElementType dataset_get(size_t idx, int component) const {
1699  return dataset.kdtree_get_pt(idx,component);
1700  }
1701 
1702 
1703  void save_tree(FILE* stream, NodePtr tree)
1704  {
1705  save_value(stream, *tree);
1706  if (tree->child1!=NULL) {
1707  save_tree(stream, tree->child1);
1708  }
1709  if (tree->child2!=NULL) {
1710  save_tree(stream, tree->child2);
1711  }
1712  }
1713 
1714 
1715  void load_tree(FILE* stream, NodePtr& tree)
1716  {
1717  tree = pool.allocate<Node>();
1718  load_value(stream, *tree);
1719  if (tree->child1!=NULL) {
1720  load_tree(stream, tree->child1);
1721  }
1722  if (tree->child2!=NULL) {
1723  load_tree(stream, tree->child2);
1724  }
1725  }
1726 
1727 
1728  void computeBoundingBox(BoundingBox& bbox)
1729  {
1730  bbox.resize((DIM>0 ? DIM : dim));
1731  if (dataset.kdtree_get_bbox(bbox))
1732  {
1733  // Done! It was implemented in derived class
1734  }
1735  else
1736  {
1737  const size_t N = m_size;
1738  if (!N) throw std::runtime_error("[nanoflann] computeBoundingBox() called but no data points found.");
1739  for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1740  bbox[i].low =
1741  bbox[i].high = dataset_get(vind[0],i);
1742  }
1743  for (size_t k=1; k<N; ++k) {
1744  for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1745  if (dataset_get(vind[k],i)<bbox[i].low) bbox[i].low = dataset_get(vind[k],i);
1746  if (dataset_get(vind[k],i)>bbox[i].high) bbox[i].high = dataset_get(vind[k],i);
1747  }
1748  }
1749  }
1750  }
1751 
1756  template <class RESULTSET>
1757  void searchLevel(RESULTSET& result_set, const ElementType* vec, const NodePtr node, DistanceType mindistsq,
1758  distance_vector_t& dists, const float epsError) const
1759  {
1760  /* If this is a leaf node, then do check and return. */
1761  if ((node->child1 == NULL)&&(node->child2 == NULL)) {
1762  //count_leaf += (node->lr.right-node->lr.left); // Removed since was neither used nor returned to the user.
1763  DistanceType worst_dist = result_set.worstDist();
1764  for (IndexType i=node->node_type.lr.left; i<node->node_type.lr.right; ++i) {
1765  const IndexType index = vind[i];// reorder... : i;
1766  if(treeIndex[index]==-1)
1767  continue;
1768  DistanceType dist = distance.evalMetric(vec, index, (DIM>0 ? DIM : dim));
1769  if (dist<worst_dist) {
1770  result_set.addPoint(dist,vind[i]);
1771  }
1772  }
1773  return;
1774  }
1775 
1776  /* Which child branch should be taken first? */
1777  int idx = node->node_type.sub.divfeat;
1778  ElementType val = vec[idx];
1779  DistanceType diff1 = val - node->node_type.sub.divlow;
1780  DistanceType diff2 = val - node->node_type.sub.divhigh;
1781 
1782  NodePtr bestChild;
1783  NodePtr otherChild;
1784  DistanceType cut_dist;
1785  if ((diff1+diff2)<0) {
1786  bestChild = node->child1;
1787  otherChild = node->child2;
1788  cut_dist = distance.accum_dist(val, node->node_type.sub.divhigh, idx);
1789  }
1790  else {
1791  bestChild = node->child2;
1792  otherChild = node->child1;
1793  cut_dist = distance.accum_dist( val, node->node_type.sub.divlow, idx);
1794  }
1795 
1796  /* Call recursively to search next level down. */
1797  searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError);
1798 
1799  DistanceType dst = dists[idx];
1800  mindistsq = mindistsq + cut_dist - dst;
1801  dists[idx] = cut_dist;
1802  if (mindistsq*epsError<=result_set.worstDist()) {
1803  searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError);
1804  }
1805  dists[idx] = dst;
1806  }
1807 
1808  public:
1813  void saveIndex(FILE* stream)
1814  {
1815  save_value(stream, m_size);
1816  save_value(stream, dim);
1817  save_value(stream, root_bbox);
1818  save_value(stream, m_leaf_max_size);
1819  save_value(stream, vind);
1820  save_tree(stream, root_node);
1821  }
1822 
1827  void loadIndex(FILE* stream)
1828  {
1829  load_value(stream, m_size);
1830  load_value(stream, dim);
1831  load_value(stream, root_bbox);
1832  load_value(stream, m_leaf_max_size);
1833  load_value(stream, vind);
1834  load_tree(stream, root_node);
1835  }
1836 
1837  };
1838 
1839 
1852  template <typename Distance, class DatasetAdaptor,int DIM = -1, typename IndexType = size_t>
1854  {
1855  public:
1856  typedef typename Distance::ElementType ElementType;
1857  typedef typename Distance::DistanceType DistanceType;
1858  protected:
1859 
1860  size_t m_leaf_max_size;
1861  int treeCount;
1862  int pointCount;
1863 
1867  DatasetAdaptor &dataset;
1868 
1869  std::vector<int> treeIndex;
1870 
1871  KDTreeSingleIndexAdaptorParams index_params;
1872 
1873  int dim;
1874 
1875  std::vector<KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM> > index;
1876 
1877 
1878  private:
1880  int First0Bit(IndexType num)
1881  {
1882  int pos = 0;
1883  while(num&1)
1884  {
1885  num = num>>1;
1886  pos++;
1887  }
1888  return pos;
1889  }
1890 
1892  inline ElementType dataset_get(size_t idx, int component) const {
1893  return dataset.kdtree_get_pt(idx,component);
1894  }
1895 
1897  void init()
1898  {
1899  typedef KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM> my_kd_tree_t;
1900  std::vector<my_kd_tree_t> index_(treeCount, my_kd_tree_t(dim /*dim*/, dataset, treeIndex, index_params));
1901  index=index_;
1902  }
1903 
1904  public:
1905 
1906  Distance distance;
1907 
1921  KDTreeSingleIndexDynamicAdaptor(const int dimensionality, DatasetAdaptor& inputData, const KDTreeSingleIndexAdaptorParams& params = KDTreeSingleIndexAdaptorParams() , const int maximumPointCount = 1e9) :
1922  dataset(inputData), index_params(params), distance(inputData)
1923  {
1924  if (dataset.kdtree_get_point_count()) throw std::runtime_error("[nanoflann] cannot handle non empty point cloud.");
1925  treeCount = log2(maximumPointCount);
1926  pointCount = 0;
1927  dim = dimensionality;
1928  treeIndex.clear();
1929  if (DIM>0) dim=DIM;
1930  m_leaf_max_size = params.leaf_max_size;
1931  init();
1932  }
1933 
1936 
1938  void addPoints(IndexType start, IndexType end)
1939  {
1940  int count = end-start;
1941  treeIndex.resize(treeIndex.size()+count);
1942  for(IndexType idx=start;idx<end;idx++)
1943  {
1944  int pos = First0Bit(pointCount);
1945  index[pos].vind.clear();
1946  treeIndex[pointCount]=pos;
1947  for(int i=0;i<pos;i++)
1948  {
1949  for(int j=0;j<index[i].vind.size();j++)
1950  {
1951  index[pos].vind.push_back(index[i].vind[j]);
1952  treeIndex[index[i].vind[j]] = pos;
1953  }
1954  index[i].vind.clear();
1955  index[i].freeIndex(index[i]);
1956  }
1957  index[pos].vind.push_back(idx);
1958  index[pos].buildIndex();
1959  pointCount++;
1960  }
1961  }
1962 
1964  void removePoint(int idx)
1965  {
1966  if(idx<0 || idx>=pointCount)
1967  return;
1968  treeIndex[idx] = -1;
1969  }
1970 
1983  template <typename RESULTSET>
1984  bool findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParams& searchParams) const
1985  {
1986  for(int i=0;i<treeCount;i++)
1987  {
1988  index[i].findNeighbors(result, &vec[0], searchParams);
1989  }
1990  return result.full();
1991  }
1992 
1993  };
1994 
2013  template <class MatrixType, int DIM = -1, class Distance = nanoflann::metric_L2>
2015  {
2017  typedef typename MatrixType::Scalar num_t;
2018  typedef typename MatrixType::Index IndexType;
2019  typedef typename Distance::template traits<num_t,self_t>::distance_t metric_t;
2021 
2022  index_t* index;
2023 
2025  KDTreeEigenMatrixAdaptor(const int dimensionality, const MatrixType &mat, const int leaf_max_size = 10) : m_data_matrix(mat)
2026  {
2027  const IndexType dims = mat.cols();
2028  if (dims!=dimensionality) throw std::runtime_error("Error: 'dimensionality' must match column count in data matrix");
2029  if (DIM>0 && static_cast<int>(dims)!=DIM)
2030  throw std::runtime_error("Data set dimensionality does not match the 'DIM' template argument");
2031  index = new index_t( dims, *this /* adaptor */, nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size ) );
2032  index->buildIndex();
2033  }
2034  private:
2036  KDTreeEigenMatrixAdaptor(const self_t&);
2037  public:
2038 
2040  delete index;
2041  }
2042 
2043  const MatrixType &m_data_matrix;
2044 
2050  inline void query(const num_t *query_point, const size_t num_closest, IndexType *out_indices, num_t *out_distances_sq, const int /* nChecks_IGNORED */ = 10) const
2051  {
2052  nanoflann::KNNResultSet<num_t,IndexType> resultSet(num_closest);
2053  resultSet.init(out_indices, out_distances_sq);
2054  index->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
2055  }
2056 
2060  const self_t & derived() const {
2061  return *this;
2062  }
2063  self_t & derived() {
2064  return *this;
2065  }
2066 
2067  // Must return the number of data points
2068  inline size_t kdtree_get_point_count() const {
2069  return m_data_matrix.rows();
2070  }
2071 
2072  // Returns the L2 distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
2073  inline num_t kdtree_distance(const num_t *p1, const IndexType idx_p2,IndexType size) const
2074  {
2075  num_t s=0;
2076  for (IndexType i=0; i<size; i++) {
2077  const num_t d= p1[i]-m_data_matrix.coeff(idx_p2,i);
2078  s+=d*d;
2079  }
2080  return s;
2081  }
2082 
2083  // Returns the dim'th component of the idx'th point in the class:
2084  inline num_t kdtree_get_pt(const IndexType idx, int dim) const {
2085  return m_data_matrix.coeff(idx,IndexType(dim));
2086  }
2087 
2088  // Optional bounding-box computation: return false to default to a standard bbox computation loop.
2089  // Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
2090  // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
2091  template <class BBOX>
2092  bool kdtree_get_bbox(BBOX& /*bb*/) const {
2093  return false;
2094  }
2095 
2098  }; // end of KDTreeEigenMatrixAdaptor // end of grouping
2102 } // end of NS
2103 
2104 
2105 #endif /* NANOFLANN_HPP_ */
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1241
~KDTreeSingleIndexDynamicAdaptor()
Definition: nanoflann.hpp:1935
size_t veclen(const Derived &obj)
Definition: nanoflann.hpp:909
Definition: nanoflann.hpp:467
Definition: nanoflann.hpp:534
std::vector< IndexType > vind
Definition: nanoflann.hpp:1140
nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexAdaptor< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType >::BoundingBox BoundingBox
Definition: nanoflann.hpp:1162
void addPoints(IndexType start, IndexType end)
Definition: nanoflann.hpp:1938
Definition: nanoflann.hpp:875
void buildIndex()
Definition: nanoflann.hpp:1603
void query(const num_t *query_point, const size_t num_closest, IndexType *out_indices, num_t *out_distances_sq, const int=10) const
Definition: nanoflann.hpp:2050
Definition: nanoflann.hpp:548
KDTreeSingleIndexAdaptor(const int dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams &params=KDTreeSingleIndexAdaptorParams())
Definition: nanoflann.hpp:1196
Definition: nanoflann.hpp:494
NodePtr root_node
Definition: nanoflann.hpp:1542
Definition: nanoflann.hpp:752
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:1265
bool operator()(const PairType &p1, const PairType &p2) const
Definition: nanoflann.hpp:152
DatasetAdaptor & dataset
The source of our data.
Definition: nanoflann.hpp:1520
Definition: nanoflann.hpp:497
Definition: nanoflann.hpp:858
union nanoflann::KDTreeBaseClass::Node::@1 node_type
Definition: nanoflann.hpp:607
KDTreeEigenMatrixAdaptor(const int dimensionality, const MatrixType &mat, const int leaf_max_size=10)
The kd-tree index for the user to call its methods as usual with any other FLANN index.
Definition: nanoflann.hpp:2025
Definition: nanoflann.hpp:435
Definition: nanoflann.hpp:526
KDTreeSingleIndexDynamicAdaptor_(const int dimensionality, DatasetAdaptor &inputData, std::vector< int > &treeIndex_, const KDTreeSingleIndexAdaptorParams &params=KDTreeSingleIndexAdaptorParams())
Definition: nanoflann.hpp:1571
size_t radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParams &searchParams=SearchParams()) const
Definition: nanoflann.hpp:1300
Definition: nanoflann.hpp:894
~KDTreeSingleIndexAdaptor()
Definition: nanoflann.hpp:1210
size_t radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParams &searchParams=SearchParams()) const
Definition: nanoflann.hpp:1688
Definition: nanoflann.hpp:834
const DatasetAdaptor & dataset
The source of our data.
Definition: nanoflann.hpp:1148
Definition: nanoflann.hpp:510
int divfeat
Dimension used for subdivision.
Definition: nanoflann.hpp:885
Definition: nanoflann.hpp:258
Definition: nanoflann.hpp:397
KDTreeSingleIndexDynamicAdaptor(const int dimensionality, DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams &params=KDTreeSingleIndexAdaptorParams(), const int maximumPointCount=1e9)
Definition: nanoflann.hpp:1921
Definition: nanoflann.hpp:521
void freeIndex(Derived &obj)
Definition: nanoflann.hpp:863
void saveIndex(FILE *stream)
Definition: nanoflann.hpp:1442
void free_all()
Definition: nanoflann.hpp:646
Definition: nanoflann.hpp:1128
int checks
Ignored parameter (Kept for compatibility with the FLANN interface).
Definition: nanoflann.hpp:564
~KDTreeSingleIndexDynamicAdaptor_()
Definition: nanoflann.hpp:1598
void loadIndex(FILE *stream)
Definition: nanoflann.hpp:1456
Definition: nanoflann.hpp:161
int dim
Dimensionality of each data point.
Definition: nanoflann.hpp:1528
IndexType right
Indices of points in leaf node.
Definition: nanoflann.hpp:881
size_t m_size_at_index_build
Number of points in the dataset when the index was built.
Definition: nanoflann.hpp:1153
void resize(const size_t nElements)
Definition: nanoflann.hpp:809
bool searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindistsq, distance_vector_t &dists, const float epsError) const
Definition: nanoflann.hpp:1378
Definition: nanoflann.hpp:1853
size_t size(const Derived &obj) const
Definition: nanoflann.hpp:906
int dim
Dimensionality of each data point.
Definition: nanoflann.hpp:1154
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1984
~PooledAllocator()
Definition: nanoflann.hpp:641
nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType >::BoundingBox BoundingBox
Definition: nanoflann.hpp:1536
Definition: nanoflann.hpp:558
size_t m_size
Number of current points in the dataset.
Definition: nanoflann.hpp:1526
T * allocate(const size_t count=1)
Definition: nanoflann.hpp:713
PooledAllocator pool
Definition: nanoflann.hpp:1552
DatasetAdaptor & dataset
The source of our data.
Definition: nanoflann.hpp:1867
Definition: nanoflann.hpp:268
NodePtr root_node
Definition: nanoflann.hpp:1168
T * allocate(size_t count=1)
Definition: nanoflann.hpp:582
KDTreeSingleIndexDynamicAdaptor_ operator=(const KDTreeSingleIndexDynamicAdaptor_ &rhs)
Definition: nanoflann.hpp:1583
void saveIndex(FILE *stream)
Definition: nanoflann.hpp:1813
NodePtr divideTree(Derived &obj, const IndexType left, const IndexType right, BoundingBox &bbox)
Definition: nanoflann.hpp:940
Definition: nanoflann.hpp:148
std::pair< IndexType, DistanceType > worst_item() const
Definition: nanoflann.hpp:199
Node * child2
Child nodes (both=NULL mean its a leaf node)
Definition: nanoflann.hpp:889
void planeSplit(Derived &obj, IndexType *ind, const IndexType count, int cutfeat, DistanceType &cutval, IndexType &lim1, IndexType &lim2)
Definition: nanoflann.hpp:1040
Definition: nanoflann.hpp:316
PooledAllocator pool
Definition: nanoflann.hpp:1178
Definition: nanoflann.hpp:513
void init_vind()
Definition: nanoflann.hpp:1310
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:1653
int dim
Dimensionality of each data point.
Definition: nanoflann.hpp:1873
std::vector< IndexType > vind
Definition: nanoflann.hpp:1512
void removePoint(int idx)
Definition: nanoflann.hpp:1964
Definition: nanoflann.hpp:518
void buildIndex()
Definition: nanoflann.hpp:1215
void * malloc(const size_t req_size)
Definition: nanoflann.hpp:660
ElementType dataset_get(size_t idx, int component) const
Helper accessor to the dataset points:
Definition: nanoflann.hpp:1698
nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexAdaptor< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType >::distance_vector_t distance_vector_t
Definition: nanoflann.hpp:1165
Definition: nanoflann.hpp:529
Definition: nanoflann.hpp:2014
Definition: nanoflann.hpp:505
const size_t WORDSIZE
Definition: nanoflann.hpp:604
Definition: nanoflann.hpp:79
Definition: nanoflann.hpp:1503
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1629
Definition: nanoflann.hpp:365
std::vector< int > treeIndex
treeIndex[idx] is the index of tree in which point at idx is stored. treeIndex[idx]=-1 means that poi...
Definition: nanoflann.hpp:1869
nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType >::distance_vector_t distance_vector_t
Definition: nanoflann.hpp:1539
bool sorted
only for radius search, require neighbours sorted by distance (default: true)
Definition: nanoflann.hpp:566
SearchParams(int checks_IGNORED_=32, float eps_=0, bool sorted_=true)
Definition: nanoflann.hpp:561
array_or_vector_selector< DIM, Interval >::container_t BoundingBox
Definition: nanoflann.hpp:900
DistanceType divhigh
The values used for subdivision.
Definition: nanoflann.hpp:886
void loadIndex(FILE *stream)
Definition: nanoflann.hpp:1827
size_t radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< std::pair< IndexType, DistanceType > > &IndicesDists, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1285
size_t usedMemory(Derived &obj)
Definition: nanoflann.hpp:917
void searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindistsq, distance_vector_t &dists, const float epsError) const
Definition: nanoflann.hpp:1757
size_t radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< std::pair< IndexType, DistanceType > > &IndicesDists, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1673
array_or_vector_selector< DIM, DistanceType >::container_t distance_vector_t
Definition: nanoflann.hpp:903
size_t m_size
Number of current points in the dataset.
Definition: nanoflann.hpp:1152
size_t m_size_at_index_build
Number of points in the dataset when the index was built.
Definition: nanoflann.hpp:1527
bool addPoint(DistanceType dist, IndexType index)
Definition: nanoflann.hpp:186
float eps
search for eps-approximate neighbours (default: 0)
Definition: nanoflann.hpp:565
PooledAllocator()
Definition: nanoflann.hpp:634
ElementType dataset_get(size_t idx, int component) const
Helper accessor to the dataset points:
Definition: nanoflann.hpp:1319
Definition: nanoflann.hpp:502
bool addPoint(DistanceType dist, IndexType index)
Definition: nanoflann.hpp:115