Main MRPT website > C++ reference
MRPT logo
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-2014 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 
33 #ifndef NANOFLANN_HPP_
34 #define NANOFLANN_HPP_
35 
36 #include <vector>
37 #include <cassert>
38 #include <algorithm>
39 #include <stdexcept>
40 #include <cstdio> // for fwrite()
41 #include <cmath> // for fabs(),...
42 #include <limits>
43 
44 // Avoid conflicting declaration of min/max macros in windows headers
45 #if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
46 # define NOMINMAX
47 # ifdef max
48 # undef max
49 # undef min
50 # endif
51 #endif
52 
53 namespace nanoflann
54 {
55 /** @addtogroup nanoflann_grp nanoflann C++ library for ANN
56  * @{ */
57 
58  /** Library version: 0xMmP (M=Major,m=minor,P=path) */
59  #define NANOFLANN_VERSION 0x118
60 
61  /** @addtogroup result_sets_grp Result set classes
62  * @{ */
63  template <typename DistanceType, typename IndexType = size_t, typename CountType = size_t>
65  {
66  IndexType * indices;
67  DistanceType* dists;
68  CountType capacity;
69  CountType count;
70 
71  public:
72  inline KNNResultSet(CountType capacity_) : capacity(capacity_), count(0)
73  {
74  }
75 
76  inline void init(IndexType* indices_, DistanceType* dists_)
77  {
78  indices = indices_;
79  dists = dists_;
80  count = 0;
81  dists[capacity-1] = (std::numeric_limits<DistanceType>::max)();
82  }
83 
84  inline CountType size() const
85  {
86  return count;
87  }
88 
89  inline bool full() const
90  {
91  return count == capacity;
92  }
93 
94 
95  inline void addPoint(DistanceType dist, IndexType index)
96  {
97  CountType i;
98  for (i=count; i>0; --i) {
99 #ifdef NANOFLANN_FIRST_MATCH // If defined and two poins have the same distance, the one with the lowest-index will be returned first.
100  if ( (dists[i-1]>dist) || ((dist==dists[i-1])&&(indices[i-1]>index)) ) {
101 #else
102  if (dists[i-1]>dist) {
103 #endif
104  if (i<capacity) {
105  dists[i] = dists[i-1];
106  indices[i] = indices[i-1];
107  }
108  }
109  else break;
110  }
111  if (i<capacity) {
112  dists[i] = dist;
113  indices[i] = index;
114  }
115  if (count<capacity) count++;
116  }
117 
118  inline DistanceType worstDist() const
119  {
120  return dists[capacity-1];
121  }
122  };
123 
124 
125  /**
126  * A result-set class used when performing a radius based search.
127  */
128  template <typename DistanceType, typename IndexType = size_t>
130  {
131  public:
132  const DistanceType radius;
133 
134  std::vector<std::pair<IndexType,DistanceType> >& m_indices_dists;
135 
136  inline RadiusResultSet(DistanceType radius_, std::vector<std::pair<IndexType,DistanceType> >& indices_dists) : radius(radius_), m_indices_dists(indices_dists)
137  {
138  init();
139  }
140 
141  inline ~RadiusResultSet() { }
142 
143  inline void init() { clear(); }
144  inline void clear() { m_indices_dists.clear(); }
145 
146  inline size_t size() const { return m_indices_dists.size(); }
147 
148  inline bool full() const { return true; }
149 
150  inline void addPoint(DistanceType dist, IndexType index)
151  {
152  if (dist<radius)
153  m_indices_dists.push_back(std::make_pair(index,dist));
154  }
155 
156  inline DistanceType worstDist() const { return radius; }
157 
158  /** Clears the result set and adjusts the search radius. */
159  inline void set_radius_and_clear( const DistanceType r )
160  {
161  radius = r;
162  clear();
163  }
164 
165  /**
166  * Find the worst result (furtherest neighbor) without copying or sorting
167  * Pre-conditions: size() > 0
168  */
169  std::pair<IndexType,DistanceType> worst_item() const
170  {
171  if (m_indices_dists.empty()) throw std::runtime_error("Cannot invoke RadiusResultSet::worst_item() on an empty list of results.");
172  typedef typename std::vector<std::pair<IndexType,DistanceType> >::const_iterator DistIt;
173  DistIt it = std::max_element(m_indices_dists.begin(), m_indices_dists.end());
174  return *it;
175  }
176  };
177 
178  /** operator "<" for std::sort() */
180  {
181  /** PairType will be typically: std::pair<IndexType,DistanceType> */
182  template <typename PairType>
183  inline bool operator()(const PairType &p1, const PairType &p2) const {
184  return p1.second < p2.second;
185  }
186  };
187 
188  /** @} */
189 
190 
191  /** @addtogroup loadsave_grp Load/save auxiliary functions
192  * @{ */
193  template<typename T>
194  void save_value(FILE* stream, const T& value, size_t count = 1)
195  {
196  fwrite(&value, sizeof(value),count, stream);
197  }
198 
199  template<typename T>
200  void save_value(FILE* stream, const std::vector<T>& value)
201  {
202  size_t size = value.size();
203  fwrite(&size, sizeof(size_t), 1, stream);
204  fwrite(&value[0], sizeof(T), size, stream);
205  }
206 
207  template<typename T>
208  void load_value(FILE* stream, T& value, size_t count = 1)
209  {
210  size_t read_cnt = fread(&value, sizeof(value), count, stream);
211  if (read_cnt != count) {
212  throw std::runtime_error("Cannot read from file");
213  }
214  }
215 
216 
217  template<typename T>
218  void load_value(FILE* stream, std::vector<T>& value)
219  {
220  size_t size;
221  size_t read_cnt = fread(&size, sizeof(size_t), 1, stream);
222  if (read_cnt!=1) {
223  throw std::runtime_error("Cannot read from file");
224  }
225  value.resize(size);
226  read_cnt = fread(&value[0], sizeof(T), size, stream);
227  if (read_cnt!=size) {
228  throw std::runtime_error("Cannot read from file");
229  }
230  }
231  /** @} */
232 
233 
234  /** @addtogroup metric_grp Metric (distance) classes
235  * @{ */
236 
237  template<typename T> inline T abs(T x) { return (x<0) ? -x : x; }
238  template<> inline int abs<int>(int x) { return ::abs(x); }
239  template<> inline float abs<float>(float x) { return fabsf(x); }
240  template<> inline double abs<double>(double x) { return fabs(x); }
241  template<> inline long double abs<long double>(long double x) { return fabsl(x); }
242 
243  /** Manhattan distance functor (generic version, optimized for high-dimensionality data sets).
244  * Corresponding distance traits: nanoflann::metric_L1
245  * \tparam T Type of the elements (e.g. double, float, uint8_t)
246  * \tparam DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t)
247  */
248  template<class T, class DataSource, typename _DistanceType = T>
249  struct L1_Adaptor
250  {
251  typedef T ElementType;
252  typedef _DistanceType DistanceType;
253 
254  const DataSource &data_source;
255 
256  L1_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
257 
258  inline DistanceType operator()(const T* a, const size_t b_idx, size_t size, DistanceType worst_dist = -1) const
259  {
260  DistanceType result = DistanceType();
261  const T* last = a + size;
262  const T* lastgroup = last - 3;
263  size_t d = 0;
264 
265  /* Process 4 items with each loop for efficiency. */
266  while (a < lastgroup) {
267  const DistanceType diff0 = nanoflann::abs(a[0] - data_source.kdtree_get_pt(b_idx,d++));
268  const DistanceType diff1 = nanoflann::abs(a[1] - data_source.kdtree_get_pt(b_idx,d++));
269  const DistanceType diff2 = nanoflann::abs(a[2] - data_source.kdtree_get_pt(b_idx,d++));
270  const DistanceType diff3 = nanoflann::abs(a[3] - data_source.kdtree_get_pt(b_idx,d++));
271  result += diff0 + diff1 + diff2 + diff3;
272  a += 4;
273  if ((worst_dist>0)&&(result>worst_dist)) {
274  return result;
275  }
276  }
277  /* Process last 0-3 components. Not needed for standard vector lengths. */
278  while (a < last) {
279  result += nanoflann::abs( *a++ - data_source.kdtree_get_pt(b_idx,d++) );
280  }
281  return result;
282  }
283 
284  template <typename U, typename V>
285  inline DistanceType accum_dist(const U a, const V b, int ) const
286  {
287  return nanoflann::abs(a-b);
288  }
289  };
290 
291  /** Squared Euclidean distance functor (generic version, optimized for high-dimensionality data sets).
292  * Corresponding distance traits: nanoflann::metric_L2
293  * \tparam T Type of the elements (e.g. double, float, uint8_t)
294  * \tparam DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t)
295  */
296  template<class T, class DataSource, typename _DistanceType = T>
297  struct L2_Adaptor
298  {
299  typedef T ElementType;
300  typedef _DistanceType DistanceType;
301 
302  const DataSource &data_source;
303 
304  L2_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
305 
306  inline DistanceType operator()(const T* a, const size_t b_idx, size_t size, DistanceType worst_dist = -1) const
307  {
308  DistanceType result = DistanceType();
309  const T* last = a + size;
310  const T* lastgroup = last - 3;
311  size_t d = 0;
312 
313  /* Process 4 items with each loop for efficiency. */
314  while (a < lastgroup) {
315  const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx,d++);
316  const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx,d++);
317  const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx,d++);
318  const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx,d++);
319  result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
320  a += 4;
321  if ((worst_dist>0)&&(result>worst_dist)) {
322  return result;
323  }
324  }
325  /* Process last 0-3 components. Not needed for standard vector lengths. */
326  while (a < last) {
327  const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx,d++);
328  result += diff0 * diff0;
329  }
330  return result;
331  }
332 
333  template <typename U, typename V>
334  inline DistanceType accum_dist(const U a, const V b, int ) const
335  {
336  return (a-b)*(a-b);
337  }
338  };
339 
340  /** Squared Euclidean distance functor (suitable for low-dimensionality datasets, like 2D or 3D point clouds)
341  * Corresponding distance traits: nanoflann::metric_L2_Simple
342  * \tparam T Type of the elements (e.g. double, float, uint8_t)
343  * \tparam DistanceType Type of distance variables (must be signed) (e.g. float, double, int64_t)
344  */
345  template<class T, class DataSource, typename _DistanceType = T>
347  {
348  typedef T ElementType;
349  typedef _DistanceType DistanceType;
350 
351  const DataSource &data_source;
352 
353  L2_Simple_Adaptor(const DataSource &_data_source) : data_source(_data_source) { }
354 
355  inline DistanceType operator()(const T* a, const size_t b_idx, size_t size) const {
356  return data_source.kdtree_distance(a,b_idx,size);
357  }
358 
359  template <typename U, typename V>
360  inline DistanceType accum_dist(const U a, const V b, int ) const
361  {
362  return (a-b)*(a-b);
363  }
364  };
365 
366  /** Metaprogramming helper traits class for the L1 (Manhattan) metric */
367  struct metric_L1 {
368  template<class T, class DataSource>
369  struct traits {
371  };
372  };
373  /** Metaprogramming helper traits class for the L2 (Euclidean) metric */
374  struct metric_L2 {
375  template<class T, class DataSource>
376  struct traits {
378  };
379  };
380  /** Metaprogramming helper traits class for the L2_simple (Euclidean) metric */
382  template<class T, class DataSource>
383  struct traits {
385  };
386  };
387 
388  /** @} */
389 
390 
391 
392  /** @addtogroup param_grp Parameter structs
393  * @{ */
394 
395  /** Parameters (see http://code.google.com/p/nanoflann/ for help choosing the parameters)
396  */
398  {
399  KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size = 10, int dim_ = -1) :
400  leaf_max_size(_leaf_max_size), dim(dim_)
401  {}
402 
404  int dim;
405  };
406 
407  /** Search options for KDTreeSingleIndexAdaptor::findNeighbors() */
409  {
410  /** Note: The first argument (checks_IGNORED_) is ignored, but kept for compatibility with the FLANN interface */
411  SearchParams(int checks_IGNORED_ = 32, float eps_ = 0, bool sorted_ = true ) :
412  checks(checks_IGNORED_), eps(eps_), sorted(sorted_) {}
413 
414  int checks; //!< Ignored parameter (Kept for compatibility with the FLANN interface).
415  float eps; //!< search for eps-approximate neighbours (default: 0)
416  bool sorted; //!< only for radius search, require neighbours sorted by distance (default: true)
417  };
418  /** @} */
419 
420 
421  /** @addtogroup memalloc_grp Memory allocation
422  * @{ */
423 
424  /**
425  * Allocates (using C's malloc) a generic type T.
426  *
427  * Params:
428  * count = number of instances to allocate.
429  * Returns: pointer (of type T*) to memory buffer
430  */
431  template <typename T>
432  inline T* allocate(size_t count = 1)
433  {
434  T* mem = (T*) ::malloc(sizeof(T)*count);
435  return mem;
436  }
437 
438 
439  /**
440  * Pooled storage allocator
441  *
442  * The following routines allow for the efficient allocation of storage in
443  * small chunks from a specified pool. Rather than allowing each structure
444  * to be freed individually, an entire pool of storage is freed at once.
445  * This method has two advantages over just using malloc() and free(). First,
446  * it is far more efficient for allocating small objects, as there is
447  * no overhead for remembering all the information needed to free each
448  * object or consolidating fragmented memory. Second, the decision about
449  * how long to keep an object is made at the time of allocation, and there
450  * is no need to track down all the objects to free them.
451  *
452  */
453 
454  const size_t WORDSIZE=16;
455  const size_t BLOCKSIZE=8192;
456 
458  {
459  /* We maintain memory alignment to word boundaries by requiring that all
460  allocations be in multiples of the machine wordsize. */
461  /* Size of machine word in bytes. Must be power of 2. */
462  /* Minimum number of bytes requested at a time from the system. Must be multiple of WORDSIZE. */
463 
464 
465  size_t remaining; /* Number of bytes left in current block of storage. */
466  void* base; /* Pointer to base of current block of storage. */
467  void* loc; /* Current location in block to next allocate memory. */
468  // size_t blocksize; // Not used
469 
471  {
472  remaining = 0;
473  base = NULL;
474  usedMemory = 0;
475  wastedMemory = 0;
476  }
477 
478  public:
479  size_t usedMemory;
480  size_t wastedMemory;
481 
482  /**
483  Default constructor. Initializes a new pool.
484  */
485  PooledAllocator(const size_t blocksize_ = BLOCKSIZE)
486 // : blocksize(blocksize_) // not used
487  {
488  MRPT_UNUSED_PARAM(blocksize_);
489  internal_init();
490  }
491 
492  /**
493  * Destructor. Frees all the memory allocated in this pool.
494  */
496  free_all();
497  }
498 
499  /** Frees all allocated memory chunks */
500  void free_all()
501  {
502  while (base != NULL) {
503  void *prev = *((void**) base); /* Get pointer to prev block. */
504  ::free(base);
505  base = prev;
506  }
507  internal_init();
508  }
509 
510  /**
511  * Returns a pointer to a piece of new memory of the given size in bytes
512  * allocated from the pool.
513  */
514  void* malloc(const size_t req_size)
515  {
516  /* Round size up to a multiple of wordsize. The following expression
517  only works for WORDSIZE that is a power of 2, by masking last bits of
518  incremented size to zero.
519  */
520  const size_t size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1);
521 
522  /* Check whether a new block must be allocated. Note that the first word
523  of a block is reserved for a pointer to the previous block.
524  */
525  if (size > remaining) {
526 
527  wastedMemory += remaining;
528 
529  /* Allocate new storage. */
530  const size_t blocksize = (size + sizeof(void*) + (WORDSIZE-1) > BLOCKSIZE) ?
531  size + sizeof(void*) + (WORDSIZE-1) : BLOCKSIZE;
532 
533  // use the standard C malloc to allocate memory
534  void* m = ::malloc(blocksize);
535  if (!m) {
536  fprintf(stderr,"Failed to allocate memory.\n");
537  return NULL;
538  }
539 
540  /* Fill first word of new block with pointer to previous block. */
541  ((void**) m)[0] = base;
542  base = m;
543 
544  size_t shift = 0;
545  //int size_t = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & (WORDSIZE-1))) & (WORDSIZE-1);
546 
547  remaining = blocksize - sizeof(void*) - shift;
548  loc = ((char*)m + sizeof(void*) + shift);
549  }
550  void* rloc = loc;
551  loc = (char*)loc + size;
552  remaining -= size;
553 
554  usedMemory += size;
555 
556  return rloc;
557  }
558 
559  /**
560  * Allocates (using this pool) a generic type T.
561  *
562  * Params:
563  * count = number of instances to allocate.
564  * Returns: pointer (of type T*) to memory buffer
565  */
566  template <typename T>
567  T* allocate(const size_t count = 1)
568  {
569  T* mem = (T*) this->malloc(sizeof(T)*count);
570  return mem;
571  }
572 
573  };
574  /** @} */
575 
576  /** @addtogroup nanoflann_metaprog_grp Auxiliary metaprogramming stuff
577  * @{ */
578 
579  // ---------------- CArray -------------------------
580  /** A STL container (as wrapper) for arrays of constant size defined at compile time (class imported from the MRPT project)
581  * This code is an adapted version from Boost, modifed for its integration
582  * within MRPT (JLBC, Dec/2009) (Renamed array -> CArray to avoid possible potential conflicts).
583  * See
584  * http://www.josuttis.com/cppcode
585  * for details and the latest version.
586  * See
587  * http://www.boost.org/libs/array for Documentation.
588  * for documentation.
589  *
590  * (C) Copyright Nicolai M. Josuttis 2001.
591  * Permission to copy, use, modify, sell and distribute this software
592  * is granted provided this copyright notice appears in all copies.
593  * This software is provided "as is" without express or implied
594  * warranty, and with no claim as to its suitability for any purpose.
595  *
596  * 29 Jan 2004 - minor fixes (Nico Josuttis)
597  * 04 Dec 2003 - update to synch with library TR1 (Alisdair Meredith)
598  * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries.
599  * 05 Aug 2001 - minor update (Nico Josuttis)
600  * 20 Jan 2001 - STLport fix (Beman Dawes)
601  * 29 Sep 2000 - Initial Revision (Nico Josuttis)
602  *
603  * Jan 30, 2004
604  */
605  template <typename T, std::size_t N>
606  class CArray {
607  public:
608  T elems[N]; // fixed-size array of elements of type T
609 
610  public:
611  // type definitions
612  typedef T value_type;
613  typedef T* iterator;
614  typedef const T* const_iterator;
615  typedef T& reference;
616  typedef const T& const_reference;
617  typedef std::size_t size_type;
618  typedef std::ptrdiff_t difference_type;
619 
620  // iterator support
621  inline iterator begin() { return elems; }
622  inline const_iterator begin() const { return elems; }
623  inline iterator end() { return elems+N; }
624  inline const_iterator end() const { return elems+N; }
625 
626  // reverse iterator support
627 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
628  typedef std::reverse_iterator<iterator> reverse_iterator;
629  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
630 #elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
631  // workaround for broken reverse_iterator in VC7
632  typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator,
633  reference, iterator, reference> > reverse_iterator;
634  typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,
635  const_reference, iterator, reference> > const_reverse_iterator;
636 #else
637  // workaround for broken reverse_iterator implementations
638  typedef std::reverse_iterator<iterator,T> reverse_iterator;
639  typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
640 #endif
641 
642  reverse_iterator rbegin() { return reverse_iterator(end()); }
643  const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
644  reverse_iterator rend() { return reverse_iterator(begin()); }
645  const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
646  // operator[]
647  inline reference operator[](size_type i) { return elems[i]; }
648  inline const_reference operator[](size_type i) const { return elems[i]; }
649  // at() with range check
650  reference at(size_type i) { rangecheck(i); return elems[i]; }
651  const_reference at(size_type i) const { rangecheck(i); return elems[i]; }
652  // front() and back()
653  reference front() { return elems[0]; }
654  const_reference front() const { return elems[0]; }
655  reference back() { return elems[N-1]; }
656  const_reference back() const { return elems[N-1]; }
657  // size is constant
658  static inline size_type size() { return N; }
659  static bool empty() { return false; }
660  static size_type max_size() { return N; }
661  enum { static_size = N };
662  /** This method has no effects in this class, but raises an exception if the expected size does not match */
663  inline void resize(const size_t nElements) { if (nElements!=N) throw std::logic_error("Try to change the size of a CArray."); }
664  // swap (note: linear complexity in N, constant for given instantiation)
665  void swap (CArray<T,N>& y) { std::swap_ranges(begin(),end(),y.begin()); }
666  // direct access to data (read-only)
667  const T* data() const { return elems; }
668  // use array as C array (direct read/write access to data)
669  T* data() { return elems; }
670  // assignment with type conversion
671  template <typename T2> CArray<T,N>& operator= (const CArray<T2,N>& rhs) {
672  std::copy(rhs.begin(),rhs.end(), begin());
673  return *this;
674  }
675  // assign one value to all elements
676  inline void assign (const T& value) { for (size_t i=0;i<N;i++) elems[i]=value; }
677  // assign (compatible with std::vector's one) (by JLBC for MRPT)
678  void assign (const size_t n, const T& value) {
679  assert(N==n);
680  for (size_t i=0;i<n;i++) elems[i]=value;
681  }
682  private:
683  // check range (may be private because it is static)
684  static void rangecheck (size_type i) { if (i >= size()) { throw std::out_of_range("CArray<>: index out of range"); } }
685  }; // end of CArray
686 
687  /** Used to declare fixed-size arrays when DIM>0, dynamically-allocated vectors when DIM=-1.
688  * Fixed size version for a generic DIM:
689  */
690  template <int DIM, typename T>
692  {
694  };
695  /** Dynamic size version */
696  template <typename T>
698  typedef std::vector<T> container_t;
699  };
700  /** @} */
701 
702  /** @addtogroup kdtrees_grp KD-tree classes and adaptors
703  * @{ */
704 
705  /** kd-tree index
706  *
707  * Contains the k-d trees and other information for indexing a set of points
708  * for nearest-neighbor matching.
709  *
710  * The class "DatasetAdaptor" must provide the following interface (can be non-virtual, inlined methods):
711  *
712  * \code
713  * // Must return the number of data points
714  * inline size_t kdtree_get_point_count() const { ... }
715  *
716  * // Must return the Euclidean (L2) distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
717  * inline DistanceType kdtree_distance(const T *p1, const size_t idx_p2,size_t size) const { ... }
718  *
719  * // Must return the dim'th component of the idx'th point in the class:
720  * inline T kdtree_get_pt(const size_t idx, int dim) const { ... }
721  *
722  * // Optional bounding-box computation: return false to default to a standard bbox computation loop.
723  * // Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
724  * // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
725  * template <class BBOX>
726  * bool kdtree_get_bbox(BBOX &bb) const
727  * {
728  * bb[0].low = ...; bb[0].high = ...; // 0th dimension limits
729  * bb[1].low = ...; bb[1].high = ...; // 1st dimension limits
730  * ...
731  * return true;
732  * }
733  *
734  * \endcode
735  *
736  * \tparam IndexType Will be typically size_t or int
737  */
738  template <typename Distance, class DatasetAdaptor,int DIM = -1, typename IndexType = size_t>
740  {
741  private:
742  /** Hidden copy constructor, to disallow copying indices (Not implemented) */
744  public:
745  typedef typename Distance::ElementType ElementType;
746  typedef typename Distance::DistanceType DistanceType;
747  protected:
748 
749  /**
750  * Array of indices to vectors in the dataset.
751  */
752  std::vector<IndexType> vind;
753 
755 
756 
757  /**
758  * The dataset used by this index
759  */
760  const DatasetAdaptor &dataset; //!< The source of our data
761 
763 
764  size_t m_size;
765  int dim; //!< Dimensionality of each data point
766 
767 
768  /*--------------------- Internal Data Structures --------------------------*/
769  struct LR
770  {
771  /**
772  * Indices of points in leaf node
773  */
774  IndexType left, right;
775  };
776  struct Sub
777  {
778  /**
779  * Dimension used for subdivision.
780  */
781  int divfeat;
782  /**
783  * The values used for subdivision.
784  */
785  DistanceType divlow, divhigh;
786  };
787  struct Node
788  {
789  union {
792  };
793  /**
794  * The child nodes.
795  */
796  Node* child1, * child2;
797  };
798  typedef Node* NodePtr;
799 
800 
801  struct Interval
802  {
803  ElementType low, high;
804  };
805 
806  /** Define "BoundingBox" as a fixed-size or variable-size container depending on "DIM" */
808 
809  /** Define "distance_vector_t" as a fixed-size or variable-size container depending on "DIM" */
811 
812  /** This record represents a branch point when finding neighbors in
813  the tree. It contains a record of the minimum distance to the query
814  point, as well as the node at which the search resumes.
815  */
816  template <typename T, typename DistanceType>
818  {
819  T node; /* Tree node at which search resumes */
820  DistanceType mindist; /* Minimum distance to query for all nodes below. */
821 
823  BranchStruct(const T& aNode, DistanceType dist) : node(aNode), mindist(dist) {}
824 
825  inline bool operator<(const BranchStruct<T, DistanceType>& rhs) const
826  {
827  return mindist<rhs.mindist;
828  }
829  };
830 
831  /**
832  * Array of k-d trees used to find neighbours.
833  */
834  NodePtr root_node;
836  typedef BranchSt* Branch;
837 
838  BoundingBox root_bbox;
839 
840  /**
841  * Pooled memory allocator.
842  *
843  * Using a pooled memory allocator is more efficient
844  * than allocating memory directly when there is a large
845  * number small of memory allocations.
846  */
848 
849  public:
850 
851  Distance distance;
852 
853  /**
854  * KDTree constructor
855  *
856  * Params:
857  * inputData = dataset with the input features
858  * params = parameters passed to the kdtree algorithm (see http://code.google.com/p/nanoflann/ for help choosing the parameters)
859  */
860  KDTreeSingleIndexAdaptor(const int dimensionality, const DatasetAdaptor& inputData, const KDTreeSingleIndexAdaptorParams& params = KDTreeSingleIndexAdaptorParams() ) :
861  dataset(inputData), index_params(params), root_node(NULL), distance(inputData)
862  {
863  m_size = dataset.kdtree_get_point_count();
864  dim = dimensionality;
865  if (DIM>0) dim=DIM;
866  else {
867  if (params.dim>0) dim = params.dim;
868  }
869  m_leaf_max_size = params.leaf_max_size;
870 
871  // Create a permutable array of indices to the input vectors.
872  init_vind();
873  }
874 
875  /**
876  * Standard destructor
877  */
879  {
880  }
881 
882  /** Frees the previously-built index. Automatically called within buildIndex(). */
883  void freeIndex()
884  {
885  pool.free_all();
886  root_node=NULL;
887  }
888 
889  /**
890  * Builds the index
891  */
892  void buildIndex()
893  {
894  init_vind();
895  freeIndex();
896  if(m_size == 0) return;
897  computeBoundingBox(root_bbox);
898  root_node = divideTree(0, m_size, root_bbox ); // construct the tree
899  }
900 
901  /**
902  * Returns size of index.
903  */
904  size_t size() const
905  {
906  return m_size;
907  }
908 
909  /**
910  * Returns the length of an index feature.
911  */
912  size_t veclen() const
913  {
914  return static_cast<size_t>(DIM>0 ? DIM : dim);
915  }
916 
917  /**
918  * Computes the inde memory usage
919  * Returns: memory used by the index
920  */
921  size_t usedMemory() const
922  {
923  return pool.usedMemory+pool.wastedMemory+dataset.kdtree_get_point_count()*sizeof(IndexType); // pool memory and vind array memory
924  }
925 
926  /** \name Query methods
927  * @{ */
928 
929  /**
930  * Find set of nearest neighbors to vec[0:dim-1]. Their indices are stored inside
931  * the result object.
932  *
933  * Params:
934  * result = the result object in which the indices of the nearest-neighbors are stored
935  * vec = the vector for which to search the nearest neighbors
936  *
937  * \tparam RESULTSET Should be any ResultSet<DistanceType>
938  * \sa knnSearch, radiusSearch
939  */
940  template <typename RESULTSET>
941  void findNeighbors(RESULTSET& result, const ElementType* vec, const SearchParams& searchParams) const
942  {
943  assert(vec);
944  if (!root_node) throw std::runtime_error("[nanoflann] findNeighbors() called before building the index or no data points.");
945  float epsError = 1+searchParams.eps;
946 
947  distance_vector_t dists; // fixed or variable-sized container (depending on DIM)
948  dists.assign((DIM>0 ? DIM : dim) ,0); // Fill it with zeros.
949  DistanceType distsq = computeInitialDistances(vec, dists);
950  searchLevel(result, vec, root_node, distsq, dists, epsError); // "count_leaf" parameter removed since was neither used nor returned to the user.
951  }
952 
953  /**
954  * Find the "num_closest" nearest neighbors to the \a query_point[0:dim-1]. Their indices are stored inside
955  * the result object.
956  * \sa radiusSearch, findNeighbors
957  * \note nChecks_IGNORED is ignored but kept for compatibility with the original FLANN interface.
958  */
959  inline void knnSearch(const ElementType *query_point, const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq, const int nChecks_IGNORED = 10) const
960  {
961  MRPT_UNUSED_PARAM(nChecks_IGNORED);
963  resultSet.init(out_indices, out_distances_sq);
964  this->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
965  }
966 
967  /**
968  * Find all the neighbors to \a query_point[0:dim-1] within a maximum radius.
969  * The output is given as a vector of pairs, of which the first element is a point index and the second the corresponding distance.
970  * Previous contents of \a IndicesDists are cleared.
971  *
972  * If searchParams.sorted==true, the output list is sorted by ascending distances.
973  *
974  * For a better performance, it is advisable to do a .reserve() on the vector if you have any wild guess about the number of expected matches.
975  *
976  * \sa knnSearch, findNeighbors
977  * \return The number of points within the given radius (i.e. indices.size() or dists.size() )
978  */
979  size_t radiusSearch(const ElementType *query_point,const DistanceType radius, std::vector<std::pair<IndexType,DistanceType> >& IndicesDists, const SearchParams& searchParams) const
980  {
981  RadiusResultSet<DistanceType,IndexType> resultSet(radius,IndicesDists);
982  this->findNeighbors(resultSet, query_point, searchParams);
983 
984  if (searchParams.sorted)
985  std::sort(IndicesDists.begin(),IndicesDists.end(), IndexDist_Sorter() );
986 
987  return resultSet.size();
988  }
989 
990  /** @} */
991 
992  private:
993  /** Make sure the auxiliary list \a vind has the same size than the current dataset, and re-generate if size has changed. */
994  void init_vind()
995  {
996  // Create a permutable array of indices to the input vectors.
997  m_size = dataset.kdtree_get_point_count();
998  if (vind.size()!=m_size) vind.resize(m_size);
999  for (size_t i = 0; i < m_size; i++) vind[i] = i;
1000  }
1001 
1002  /// Helper accessor to the dataset points:
1003  inline ElementType dataset_get(size_t idx, int component) const {
1004  return dataset.kdtree_get_pt(idx,component);
1005  }
1006 
1007 
1008  void save_tree(FILE* stream, NodePtr tree)
1009  {
1010  save_value(stream, *tree);
1011  if (tree->child1!=NULL) {
1012  save_tree(stream, tree->child1);
1013  }
1014  if (tree->child2!=NULL) {
1015  save_tree(stream, tree->child2);
1016  }
1017  }
1018 
1019 
1020  void load_tree(FILE* stream, NodePtr& tree)
1021  {
1022  tree = pool.allocate<Node>();
1023  load_value(stream, *tree);
1024  if (tree->child1!=NULL) {
1025  load_tree(stream, tree->child1);
1026  }
1027  if (tree->child2!=NULL) {
1028  load_tree(stream, tree->child2);
1029  }
1030  }
1031 
1032 
1033  void computeBoundingBox(BoundingBox& bbox)
1034  {
1035  bbox.resize((DIM>0 ? DIM : dim));
1036  if (dataset.kdtree_get_bbox(bbox))
1037  {
1038  // Done! It was implemented in derived class
1039  }
1040  else
1041  {
1042  const size_t N = dataset.kdtree_get_point_count();
1043  if (!N) throw std::runtime_error("[nanoflann] computeBoundingBox() called but no data points found.");
1044  for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1045  bbox[i].low =
1046  bbox[i].high = dataset_get(0,i);
1047  }
1048  for (size_t k=1; k<N; ++k) {
1049  for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1050  if (dataset_get(k,i)<bbox[i].low) bbox[i].low = dataset_get(k,i);
1051  if (dataset_get(k,i)>bbox[i].high) bbox[i].high = dataset_get(k,i);
1052  }
1053  }
1054  }
1055  }
1056 
1057 
1058  /**
1059  * Create a tree node that subdivides the list of vecs from vind[first]
1060  * to vind[last]. The routine is called recursively on each sublist.
1061  * Place a pointer to this new tree node in the location pTree.
1062  *
1063  * Params: pTree = the new node to create
1064  * first = index of the first vector
1065  * last = index of the last vector
1066  */
1067  NodePtr divideTree(const IndexType left, const IndexType right, BoundingBox& bbox)
1068  {
1069  NodePtr node = pool.allocate<Node>(); // allocate memory
1070 
1071  /* If too few exemplars remain, then make this a leaf node. */
1072  if ( (right-left) <= m_leaf_max_size) {
1073  node->child1 = node->child2 = NULL; /* Mark as leaf node. */
1074  node->lr.left = left;
1075  node->lr.right = right;
1076 
1077  // compute bounding-box of leaf points
1078  for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1079  bbox[i].low = dataset_get(vind[left],i);
1080  bbox[i].high = dataset_get(vind[left],i);
1081  }
1082  for (IndexType k=left+1; k<right; ++k) {
1083  for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1084  if (bbox[i].low>dataset_get(vind[k],i)) bbox[i].low=dataset_get(vind[k],i);
1085  if (bbox[i].high<dataset_get(vind[k],i)) bbox[i].high=dataset_get(vind[k],i);
1086  }
1087  }
1088  }
1089  else {
1090  IndexType idx;
1091  int cutfeat;
1092  DistanceType cutval;
1093  middleSplit_(&vind[0]+left, right-left, idx, cutfeat, cutval, bbox);
1094 
1095  node->sub.divfeat = cutfeat;
1096 
1097  BoundingBox left_bbox(bbox);
1098  left_bbox[cutfeat].high = cutval;
1099  node->child1 = divideTree(left, left+idx, left_bbox);
1100 
1101  BoundingBox right_bbox(bbox);
1102  right_bbox[cutfeat].low = cutval;
1103  node->child2 = divideTree(left+idx, right, right_bbox);
1104 
1105  node->sub.divlow = left_bbox[cutfeat].high;
1106  node->sub.divhigh = right_bbox[cutfeat].low;
1107 
1108  for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1109  bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
1110  bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
1111  }
1112  }
1113 
1114  return node;
1115  }
1116 
1117  void computeMinMax(IndexType* ind, IndexType count, int element, ElementType& min_elem, ElementType& max_elem)
1118  {
1119  min_elem = dataset_get(ind[0],element);
1120  max_elem = dataset_get(ind[0],element);
1121  for (IndexType i=1; i<count; ++i) {
1122  ElementType val = dataset_get(ind[i],element);
1123  if (val<min_elem) min_elem = val;
1124  if (val>max_elem) max_elem = val;
1125  }
1126  }
1127 
1128  void middleSplit(IndexType* ind, IndexType count, IndexType& index, int& cutfeat, DistanceType& cutval, const BoundingBox& bbox)
1129  {
1130  // find the largest span from the approximate bounding box
1131  ElementType max_span = bbox[0].high-bbox[0].low;
1132  cutfeat = 0;
1133  cutval = (bbox[0].high+bbox[0].low)/2;
1134  for (int i=1; i<(DIM>0 ? DIM : dim); ++i) {
1135  ElementType span = bbox[i].low-bbox[i].low;
1136  if (span>max_span) {
1137  max_span = span;
1138  cutfeat = i;
1139  cutval = (bbox[i].high+bbox[i].low)/2;
1140  }
1141  }
1142 
1143  // compute exact span on the found dimension
1144  ElementType min_elem, max_elem;
1145  computeMinMax(ind, count, cutfeat, min_elem, max_elem);
1146  cutval = (min_elem+max_elem)/2;
1147  max_span = max_elem - min_elem;
1148 
1149  // check if a dimension of a largest span exists
1150  size_t k = cutfeat;
1151  for (size_t i=0; i<(DIM>0 ? DIM : dim); ++i) {
1152  if (i==k) continue;
1153  ElementType span = bbox[i].high-bbox[i].low;
1154  if (span>max_span) {
1155  computeMinMax(ind, count, i, min_elem, max_elem);
1156  span = max_elem - min_elem;
1157  if (span>max_span) {
1158  max_span = span;
1159  cutfeat = i;
1160  cutval = (min_elem+max_elem)/2;
1161  }
1162  }
1163  }
1164  IndexType lim1, lim2;
1165  planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
1166 
1167  if (lim1>count/2) index = lim1;
1168  else if (lim2<count/2) index = lim2;
1169  else index = count/2;
1170  }
1171 
1172 
1173  void middleSplit_(IndexType* ind, IndexType count, IndexType& index, int& cutfeat, DistanceType& cutval, const BoundingBox& bbox)
1174  {
1175  const DistanceType EPS=static_cast<DistanceType>(0.00001);
1176  ElementType max_span = bbox[0].high-bbox[0].low;
1177  for (int i=1; i<(DIM>0 ? DIM : dim); ++i) {
1178  ElementType span = bbox[i].high-bbox[i].low;
1179  if (span>max_span) {
1180  max_span = span;
1181  }
1182  }
1183  ElementType max_spread = -1;
1184  cutfeat = 0;
1185  for (int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1186  ElementType span = bbox[i].high-bbox[i].low;
1187  if (span>(1-EPS)*max_span) {
1188  ElementType min_elem, max_elem;
1189  computeMinMax(ind, count, cutfeat, min_elem, max_elem);
1190  ElementType spread = max_elem-min_elem;;
1191  if (spread>max_spread) {
1192  cutfeat = i;
1193  max_spread = spread;
1194  }
1195  }
1196  }
1197  // split in the middle
1198  DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2;
1199  ElementType min_elem, max_elem;
1200  computeMinMax(ind, count, cutfeat, min_elem, max_elem);
1201 
1202  if (split_val<min_elem) cutval = min_elem;
1203  else if (split_val>max_elem) cutval = max_elem;
1204  else cutval = split_val;
1205 
1206  IndexType lim1, lim2;
1207  planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
1208 
1209  if (lim1>count/2) index = lim1;
1210  else if (lim2<count/2) index = lim2;
1211  else index = count/2;
1212  }
1213 
1214 
1215  /**
1216  * Subdivide the list of points by a plane perpendicular on axe corresponding
1217  * to the 'cutfeat' dimension at 'cutval' position.
1218  *
1219  * On return:
1220  * dataset[ind[0..lim1-1]][cutfeat]<cutval
1221  * dataset[ind[lim1..lim2-1]][cutfeat]==cutval
1222  * dataset[ind[lim2..count]][cutfeat]>cutval
1223  */
1224  void planeSplit(IndexType* ind, const IndexType count, int cutfeat, DistanceType cutval, IndexType& lim1, IndexType& lim2)
1225  {
1226  /* Move vector indices for left subtree to front of list. */
1227  IndexType left = 0;
1228  IndexType right = count-1;
1229  for (;; ) {
1230  while (left<=right && dataset_get(ind[left],cutfeat)<cutval) ++left;
1231  while (right && left<=right && dataset_get(ind[right],cutfeat)>=cutval) --right;
1232  if (left>right || !right) break; // "!right" was added to support unsigned Index types
1233  std::swap(ind[left], ind[right]);
1234  ++left;
1235  --right;
1236  }
1237  /* If either list is empty, it means that all remaining features
1238  * are identical. Split in the middle to maintain a balanced tree.
1239  */
1240  lim1 = left;
1241  right = count-1;
1242  for (;; ) {
1243  while (left<=right && dataset_get(ind[left],cutfeat)<=cutval) ++left;
1244  while (right && left<=right && dataset_get(ind[right],cutfeat)>cutval) --right;
1245  if (left>right || !right) break; // "!right" was added to support unsigned Index types
1246  std::swap(ind[left], ind[right]);
1247  ++left;
1248  --right;
1249  }
1250  lim2 = left;
1251  }
1252 
1253  DistanceType computeInitialDistances(const ElementType* vec, distance_vector_t& dists) const
1254  {
1255  assert(vec);
1256  DistanceType distsq = 0.0;
1257 
1258  for (int i = 0; i < (DIM>0 ? DIM : dim); ++i) {
1259  if (vec[i] < root_bbox[i].low) {
1260  dists[i] = distance.accum_dist(vec[i], root_bbox[i].low, i);
1261  distsq += dists[i];
1262  }
1263  if (vec[i] > root_bbox[i].high) {
1264  dists[i] = distance.accum_dist(vec[i], root_bbox[i].high, i);
1265  distsq += dists[i];
1266  }
1267  }
1268 
1269  return distsq;
1270  }
1271 
1272  /**
1273  * Performs an exact search in the tree starting from a node.
1274  * \tparam RESULTSET Should be any ResultSet<DistanceType>
1275  */
1276  template <class RESULTSET>
1277  void searchLevel(RESULTSET& result_set, const ElementType* vec, const NodePtr node, DistanceType mindistsq,
1278  distance_vector_t& dists, const float epsError) const
1279  {
1280  /* If this is a leaf node, then do check and return. */
1281  if ((node->child1 == NULL)&&(node->child2 == NULL)) {
1282  //count_leaf += (node->lr.right-node->lr.left); // Removed since was neither used nor returned to the user.
1283  DistanceType worst_dist = result_set.worstDist();
1284  for (IndexType i=node->lr.left; i<node->lr.right; ++i) {
1285  const IndexType index = vind[i];// reorder... : i;
1286  DistanceType dist = distance(vec, index, (DIM>0 ? DIM : dim));
1287  if (dist<worst_dist) {
1288  result_set.addPoint(dist,vind[i]);
1289  }
1290  }
1291  return;
1292  }
1293 
1294  /* Which child branch should be taken first? */
1295  int idx = node->sub.divfeat;
1296  ElementType val = vec[idx];
1297  DistanceType diff1 = val - node->sub.divlow;
1298  DistanceType diff2 = val - node->sub.divhigh;
1299 
1300  NodePtr bestChild;
1301  NodePtr otherChild;
1302  DistanceType cut_dist;
1303  if ((diff1+diff2)<0) {
1304  bestChild = node->child1;
1305  otherChild = node->child2;
1306  cut_dist = distance.accum_dist(val, node->sub.divhigh, idx);
1307  }
1308  else {
1309  bestChild = node->child2;
1310  otherChild = node->child1;
1311  cut_dist = distance.accum_dist( val, node->sub.divlow, idx);
1312  }
1313 
1314  /* Call recursively to search next level down. */
1315  searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError);
1316 
1317  DistanceType dst = dists[idx];
1318  mindistsq = mindistsq + cut_dist - dst;
1319  dists[idx] = cut_dist;
1320  if (mindistsq*epsError<=result_set.worstDist()) {
1321  searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError);
1322  }
1323  dists[idx] = dst;
1324  }
1325 
1326  public:
1327  /** Stores the index in a binary file.
1328  * IMPORTANT NOTE: The set of data points is NOT stored in the file, so when loading the index object it must be constructed associated to the same source of data points used while building it.
1329  * See the example: examples/saveload_example.cpp
1330  * \sa loadIndex */
1331  void saveIndex(FILE* stream)
1332  {
1333  save_value(stream, m_size);
1334  save_value(stream, dim);
1335  save_value(stream, root_bbox);
1336  save_value(stream, m_leaf_max_size);
1337  save_value(stream, vind);
1338  save_tree(stream, root_node);
1339  }
1340 
1341  /** Loads a previous index from a binary file.
1342  * IMPORTANT NOTE: The set of data points is NOT stored in the file, so the index object must be constructed associated to the same source of data points used while building the index.
1343  * See the example: examples/saveload_example.cpp
1344  * \sa loadIndex */
1345  void loadIndex(FILE* stream)
1346  {
1347  load_value(stream, m_size);
1348  load_value(stream, dim);
1349  load_value(stream, root_bbox);
1350  load_value(stream, m_leaf_max_size);
1351  load_value(stream, vind);
1352  load_tree(stream, root_node);
1353  }
1354 
1355  }; // class KDTree
1356 
1357 
1358  /** A simple KD-tree adaptor for working with data directly stored in an Eigen Matrix, without duplicating the data storage.
1359  * Each row in the matrix represents a point in the state space.
1360  *
1361  * Example of usage:
1362  * \code
1363  * Eigen::Matrix<num_t,Dynamic,Dynamic> mat;
1364  * // Fill out "mat"...
1365  *
1366  * typedef KDTreeEigenMatrixAdaptor< Eigen::Matrix<num_t,Dynamic,Dynamic> > my_kd_tree_t;
1367  * const int max_leaf = 10;
1368  * my_kd_tree_t mat_index(dimdim, mat, max_leaf );
1369  * mat_index.index->buildIndex();
1370  * mat_index.index->...
1371  * \endcode
1372  *
1373  * \tparam DIM If set to >0, it specifies a compile-time fixed dimensionality for the points in the data set, allowing more compiler optimizations.
1374  * \tparam Distance The distance metric to use: nanoflann::metric_L1, nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc.
1375  * \tparam IndexType The type for indices in the KD-tree index (typically, size_t of int)
1376  */
1377  template <class MatrixType, int DIM = -1, class Distance = nanoflann::metric_L2, typename IndexType = size_t>
1379  {
1381  typedef typename MatrixType::Scalar num_t;
1382  typedef typename Distance::template traits<num_t,self_t>::distance_t metric_t;
1384 
1385  index_t* index; //! The kd-tree index for the user to call its methods as usual with any other FLANN index.
1386 
1387  /// Constructor: takes a const ref to the matrix object with the data points
1388  KDTreeEigenMatrixAdaptor(const int dimensionality, const MatrixType &mat, const int leaf_max_size = 10) : m_data_matrix(mat)
1389  {
1390  MRPT_UNUSED_PARAM(dimensionality);
1391  const size_t dims = mat.cols();
1392  if (DIM>0 && static_cast<int>(dims)!=DIM)
1393  throw std::runtime_error("Data set dimensionality does not match the 'DIM' template argument");
1394  index = new index_t( dims, *this /* adaptor */, nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size, dims ) );
1395  index->buildIndex();
1396  }
1397  private:
1398  /** Hidden copy constructor, to disallow copying this class (Not implemented) */
1399  KDTreeEigenMatrixAdaptor(const self_t&);
1400  public:
1401 
1403  delete index;
1404  }
1405 
1406  const MatrixType &m_data_matrix;
1407 
1408  /** Query for the \a num_closest closest points to a given point (entered as query_point[0:dim-1]).
1409  * Note that this is a short-cut method for index->findNeighbors().
1410  * The user can also call index->... methods as desired.
1411  * \note nChecks_IGNORED is ignored but kept for compatibility with the original FLANN interface.
1412  */
1413  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
1414  {
1415  MRPT_UNUSED_PARAM(nChecks_IGNORED);
1417  resultSet.init(out_indices, out_distances_sq);
1418  index->findNeighbors(resultSet, query_point, nanoflann::SearchParams());
1419  }
1420 
1421  /** @name Interface expected by KDTreeSingleIndexAdaptor
1422  * @{ */
1423 
1424  const self_t & derived() const {
1425  return *this;
1426  }
1427  self_t & derived() {
1428  return *this;
1429  }
1430 
1431  // Must return the number of data points
1432  inline size_t kdtree_get_point_count() const {
1433  return m_data_matrix.rows();
1434  }
1435 
1436  // Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
1437  inline num_t kdtree_distance(const num_t *p1, const size_t idx_p2,size_t size) const
1438  {
1439  num_t s=0;
1440  for (size_t i=0; i<size; i++) {
1441  const num_t d= p1[i]-m_data_matrix.coeff(idx_p2,i);
1442  s+=d*d;
1443  }
1444  return s;
1445  }
1446 
1447  // Returns the dim'th component of the idx'th point in the class:
1448  inline num_t kdtree_get_pt(const size_t idx, int dim) const {
1449  return m_data_matrix.coeff(idx,dim);
1450  }
1451 
1452  // Optional bounding-box computation: return false to default to a standard bbox computation loop.
1453  // Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
1454  // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
1455  template <class BBOX>
1456  bool kdtree_get_bbox(BBOX &bb) const {
1457  MRPT_UNUSED_PARAM(bb);
1458  return false;
1459  }
1460 
1461  /** @} */
1462 
1463  }; // end of KDTreeEigenMatrixAdaptor
1464  /** @} */
1465 
1466 /** @} */ // end of grouping
1467 } // end of NS
1468 
1469 
1470 #endif /* NANOFLANN_HPP_ */
A simple KD-tree adaptor for working with data directly stored in an Eigen Matrix, without duplicating the data storage.
Definition: nanoflann.hpp:1378
long double abs< long double >(long double x)
Definition: nanoflann.hpp:241
std::reverse_iterator< iterator > reverse_iterator
Definition: nanoflann.hpp:628
DistanceType accum_dist(const U a, const V b, int) const
Definition: nanoflann.hpp:334
num_t kdtree_get_pt(const size_t idx, int dim) const
Definition: nanoflann.hpp:1448
PooledAllocator(const size_t blocksize_=BLOCKSIZE)
Default constructor.
Definition: nanoflann.hpp:485
const T * data() const
Definition: nanoflann.hpp:667
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:1388
size_t size() const
Returns size of index.
Definition: nanoflann.hpp:904
void freeIndex()
Frees the previously-built index.
Definition: nanoflann.hpp:883
EIGEN_STRONG_INLINE iterator end()
Definition: eigen_plugins.h:27
void swap(CArray< T, N > &y)
Definition: nanoflann.hpp:665
const DataSource & data_source
Definition: nanoflann.hpp:254
Metaprogramming helper traits class for the L2 (Euclidean) metric.
Definition: nanoflann.hpp:374
std::vector< IndexType > vind
Array of indices to vectors in the dataset.
Definition: nanoflann.hpp:752
Manhattan distance functor (generic version, optimized for high-dimensionality data sets)...
Definition: nanoflann.hpp:249
iterator begin()
Definition: nanoflann.hpp:621
void loadIndex(FILE *stream)
Loads a previous index from a binary file.
Definition: nanoflann.hpp:1345
Squared Euclidean distance functor (suitable for low-dimensionality datasets, like 2D or 3D point clo...
Definition: nanoflann.hpp:346
BranchStruct(const T &aNode, DistanceType dist)
Definition: nanoflann.hpp:823
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
Query for the num_closest closest points to a given point (entered as query_point[0:dim-1]).
Definition: nanoflann.hpp:1413
void searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindistsq, distance_vector_t &dists, const float epsError) const
Performs an exact search in the tree starting from a node.
Definition: nanoflann.hpp:1277
const DistanceType radius
Definition: nanoflann.hpp:132
~PooledAllocator()
Destructor.
Definition: nanoflann.hpp:495
double abs< double >(double x)
Definition: nanoflann.hpp:240
DistanceType worstDist() const
Definition: nanoflann.hpp:156
std::ptrdiff_t difference_type
Definition: nanoflann.hpp:618
RadiusResultSet(DistanceType radius_, std::vector< std::pair< IndexType, DistanceType > > &indices_dists)
Definition: nanoflann.hpp:136
static size_type size()
Definition: nanoflann.hpp:658
size_t usedMemory() const
Computes the inde memory usage Returns: memory used by the index.
Definition: nanoflann.hpp:921
~KDTreeSingleIndexAdaptor()
Standard destructor.
Definition: nanoflann.hpp:878
const KDTreeSingleIndexAdaptorParams index_params
Definition: nanoflann.hpp:762
static void rangecheck(size_type i)
Definition: nanoflann.hpp:684
reverse_iterator rbegin()
Definition: nanoflann.hpp:642
std::pair< IndexType, DistanceType > worst_item() const
Find the worst result (furtherest neighbor) without copying or sorting Pre-conditions: size() > 0...
Definition: nanoflann.hpp:169
Scalar * iterator
Definition: eigen_plugins.h:23
void init(IndexType *indices_, DistanceType *dists_)
Definition: nanoflann.hpp:76
CountType size() const
Definition: nanoflann.hpp:84
EIGEN_STRONG_INLINE iterator begin()
Definition: eigen_plugins.h:26
DistanceType * dists
Definition: nanoflann.hpp:67
iterator end()
Definition: nanoflann.hpp:623
const Scalar * const_iterator
Definition: eigen_plugins.h:24
L2_Simple_Adaptor< T, DataSource > distance_t
Definition: nanoflann.hpp:384
float eps
search for eps-approximate neighbours (default: 0)
Definition: nanoflann.hpp:415
bool kdtree_get_bbox(BBOX &bb) const
Definition: nanoflann.hpp:1456
DistanceType accum_dist(const U a, const V b, int) const
Definition: nanoflann.hpp:360
void resize(const size_t nElements)
This method has no effects in this class, but raises an exception if the expected size does not match...
Definition: nanoflann.hpp:663
L2_Adaptor< T, DataSource > distance_t
Definition: nanoflann.hpp:377
L1_Adaptor< T, DataSource > distance_t
Definition: nanoflann.hpp:370
void load_value(FILE *stream, T &value, size_t count=1)
Definition: nanoflann.hpp:208
Used to declare fixed-size arrays when DIM>0, dynamically-allocated vectors when DIM=-1.
Definition: nanoflann.hpp:691
const DataSource & data_source
Definition: nanoflann.hpp:302
DistanceType operator()(const T *a, const size_t b_idx, size_t size, DistanceType worst_dist=-1) const
Definition: nanoflann.hpp:258
reference back()
Definition: nanoflann.hpp:655
bool full() const
Definition: nanoflann.hpp:89
reverse_iterator rend()
Definition: nanoflann.hpp:644
void init_vind()
Make sure the auxiliary list vind has the same size than the current dataset, and re-generate if size...
Definition: nanoflann.hpp:994
L2_Adaptor(const DataSource &_data_source)
Definition: nanoflann.hpp:304
void addPoint(DistanceType dist, IndexType index)
Definition: nanoflann.hpp:150
const size_t BLOCKSIZE
Definition: nanoflann.hpp:455
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
array_or_vector_selector< DIM, DistanceType >::container_t distance_vector_t
Define "distance_vector_t" as a fixed-size or variable-size container depending on "DIM"...
Definition: nanoflann.hpp:810
int divfeat
Dimension used for subdivision.
Definition: nanoflann.hpp:781
const_reference operator[](size_type i) const
Definition: nanoflann.hpp:648
static size_type max_size()
Definition: nanoflann.hpp:660
bool sorted
only for radius search, require neighbours sorted by distance (default: true)
Definition: nanoflann.hpp:416
const DatasetAdaptor & dataset
The dataset used by this index.
Definition: nanoflann.hpp:760
operator "<" for std::sort()
Definition: nanoflann.hpp:179
void middleSplit(IndexType *ind, IndexType count, IndexType &index, int &cutfeat, DistanceType &cutval, const BoundingBox &bbox)
Definition: nanoflann.hpp:1128
void knnSearch(const ElementType *query_point, const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq, const int nChecks_IGNORED=10) const
Find the "num_closest" nearest neighbors to the query_point[0:dim-1].
Definition: nanoflann.hpp:959
reference operator[](size_type i)
Definition: nanoflann.hpp:647
Distance::DistanceType DistanceType
Definition: nanoflann.hpp:746
void middleSplit_(IndexType *ind, IndexType count, IndexType &index, int &cutfeat, DistanceType &cutval, const BoundingBox &bbox)
Definition: nanoflann.hpp:1173
const T * const_iterator
Definition: nanoflann.hpp:614
DistanceType accum_dist(const U a, const V b, int) const
Definition: nanoflann.hpp:285
bool operator()(const PairType &p1, const PairType &p2) const
PairType will be typically: std::pair
Definition: nanoflann.hpp:183
DistanceType worstDist() const
Definition: nanoflann.hpp:118
KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size=10, int dim_=-1)
Definition: nanoflann.hpp:399
DistanceType operator()(const T *a, const size_t b_idx, size_t size) const
Definition: nanoflann.hpp:355
std::vector< std::pair< IndexType, DistanceType > > & m_indices_dists
Definition: nanoflann.hpp:134
T abs(T x)
Definition: nanoflann.hpp:237
T * allocate(size_t count=1)
Allocates (using C's malloc) a generic type T.
Definition: nanoflann.hpp:432
Distance::ElementType ElementType
Definition: nanoflann.hpp:745
reference at(size_type i)
Definition: nanoflann.hpp:650
std::size_t size_type
Definition: nanoflann.hpp:617
KNNResultSet(CountType capacity_)
Definition: nanoflann.hpp:72
void saveIndex(FILE *stream)
Stores the index in a binary file.
Definition: nanoflann.hpp:1331
A result-set class used when performing a radius based search.
Definition: nanoflann.hpp:129
KDTreeSingleIndexAdaptor(const int dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams &params=KDTreeSingleIndexAdaptorParams())
KDTree constructor.
Definition: nanoflann.hpp:860
T * allocate(const size_t count=1)
Allocates (using this pool) a generic type T.
Definition: nanoflann.hpp:567
A STL container (as wrapper) for arrays of constant size defined at compile time (class imported from...
Definition: nanoflann.hpp:606
int checks
Ignored parameter (Kept for compatibility with the FLANN interface).
Definition: nanoflann.hpp:414
L1_Adaptor(const DataSource &_data_source)
Definition: nanoflann.hpp:256
const_reference front() const
Definition: nanoflann.hpp:654
ElementType dataset_get(size_t idx, int component) const
Helper accessor to the dataset points:
Definition: nanoflann.hpp:1003
void addPoint(DistanceType dist, IndexType index)
Definition: nanoflann.hpp:95
IndexType left
Indices of points in leaf node.
Definition: nanoflann.hpp:774
void free_all()
Frees all allocated memory chunks.
Definition: nanoflann.hpp:500
const self_t & derived() const
Definition: nanoflann.hpp:1424
KDTreeEigenMatrixAdaptor< MatrixType, DIM, Distance, IndexType > self_t
Definition: nanoflann.hpp:1380
void planeSplit(IndexType *ind, const IndexType count, int cutfeat, DistanceType cutval, IndexType &lim1, IndexType &lim2)
Subdivide the list of points by a plane perpendicular on axe corresponding to the 'cutfeat' dimension...
Definition: nanoflann.hpp:1224
This record represents a branch point when finding neighbors in the tree.
Definition: nanoflann.hpp:817
_DistanceType DistanceType
Definition: nanoflann.hpp:252
array_or_vector_selector< DIM, Interval >::container_t BoundingBox
Define "BoundingBox" as a fixed-size or variable-size container depending on "DIM".
Definition: nanoflann.hpp:807
Squared Euclidean distance functor (generic version, optimized for high-dimensionality data sets)...
Definition: nanoflann.hpp:297
NodePtr root_node
Array of k-d trees used to find neighbours.
Definition: nanoflann.hpp:834
const DataSource & data_source
Definition: nanoflann.hpp:351
void assign(const T &value)
Definition: nanoflann.hpp:676
Parameters (see http://code.google.com/p/nanoflann/ for help choosing the parameters) ...
Definition: nanoflann.hpp:397
static bool empty()
Definition: nanoflann.hpp:659
void computeMinMax(IndexType *ind, IndexType count, int element, ElementType &min_elem, ElementType &max_elem)
Definition: nanoflann.hpp:1117
NodePtr divideTree(const IndexType left, const IndexType right, BoundingBox &bbox)
Create a tree node that subdivides the list of vecs from vind[first] to vind[last].
Definition: nanoflann.hpp:1067
L2_Simple_Adaptor(const DataSource &_data_source)
Definition: nanoflann.hpp:353
const_reverse_iterator rend() const
Definition: nanoflann.hpp:645
void assign(const size_t n, const T &value)
Definition: nanoflann.hpp:678
Distance::template traits< num_t, self_t >::distance_t metric_t
Definition: nanoflann.hpp:1382
void save_tree(FILE *stream, NodePtr tree)
Definition: nanoflann.hpp:1008
DistanceType computeInitialDistances(const ElementType *vec, distance_vector_t &dists) const
Definition: nanoflann.hpp:1253
int dim
Dimensionality of each data point.
Definition: nanoflann.hpp:765
const_iterator begin() const
Definition: nanoflann.hpp:622
BranchStruct< NodePtr, DistanceType > BranchSt
Definition: nanoflann.hpp:835
Search options for KDTreeSingleIndexAdaptor::findNeighbors()
Definition: nanoflann.hpp:408
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: nanoflann.hpp:629
const size_t WORDSIZE
Pooled storage allocator.
Definition: nanoflann.hpp:454
int abs< int >(int x)
Definition: nanoflann.hpp:238
const_reference back() const
Definition: nanoflann.hpp:656
void computeBoundingBox(BoundingBox &bbox)
Definition: nanoflann.hpp:1033
void save_value(FILE *stream, const T &value, size_t count=1)
Definition: nanoflann.hpp:194
void load_tree(FILE *stream, NodePtr &tree)
Definition: nanoflann.hpp:1020
PooledAllocator pool
Pooled memory allocator.
Definition: nanoflann.hpp:847
void findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParams &searchParams) const
Find set of nearest neighbors to vec[0:dim-1].
Definition: nanoflann.hpp:941
size_t veclen() const
Returns the length of an index feature.
Definition: nanoflann.hpp:912
Metaprogramming helper traits class for the L1 (Manhattan) metric.
Definition: nanoflann.hpp:367
const_reference at(size_type i) const
Definition: nanoflann.hpp:651
int BASE_IMPEXP fprintf(FILE *fil, const char *format,...) MRPT_NO_THROWS MRPT_printf_format_check(2
An OS-independent version of fprintf.
void * malloc(const size_t req_size)
Returns a pointer to a piece of new memory of the given size in bytes allocated from the pool...
Definition: nanoflann.hpp:514
num_t kdtree_distance(const num_t *p1, const size_t idx_p2, size_t size) const
Definition: nanoflann.hpp:1437
SearchParams(int checks_IGNORED_=32, float eps_=0, bool sorted_=true)
Note: The first argument (checks_IGNORED_) is ignored, but kept for compatibility with the FLANN inte...
Definition: nanoflann.hpp:411
Metaprogramming helper traits class for the L2_simple (Euclidean) metric.
Definition: nanoflann.hpp:381
float abs< float >(float x)
Definition: nanoflann.hpp:239
_DistanceType DistanceType
Definition: nanoflann.hpp:300
void set_radius_and_clear(const DistanceType r)
Clears the result set and adjusts the search radius.
Definition: nanoflann.hpp:159
KDTreeSingleIndexAdaptor< metric_t, self_t, DIM, IndexType > index_t
Definition: nanoflann.hpp:1383
size_t radiusSearch(const ElementType *query_point, const DistanceType radius, std::vector< std::pair< IndexType, DistanceType > > &IndicesDists, const SearchParams &searchParams) const
Find all the neighbors to query_point[0:dim-1] within a maximum radius.
Definition: nanoflann.hpp:979
const_reverse_iterator rbegin() const
Definition: nanoflann.hpp:643
reference front()
Definition: nanoflann.hpp:653
DistanceType divlow
The values used for subdivision.
Definition: nanoflann.hpp:785
double BASE_IMPEXP distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
const_iterator end() const
Definition: nanoflann.hpp:624
void buildIndex()
Builds the index.
Definition: nanoflann.hpp:892
const T & const_reference
Definition: nanoflann.hpp:616
DistanceType operator()(const T *a, const size_t b_idx, size_t size, DistanceType worst_dist=-1) const
Definition: nanoflann.hpp:306



Page generated by Doxygen 1.8.8 for MRPT 1.2.2 SVN:Unversioned directory at Tue Oct 14 02:14:08 UTC 2014