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 33 /** \mainpage nanoflann C++ API documentation 34 * nanoflann is a C++ header-only library for building KD-Trees, mostly 35 * optimized for 2D or 3D point clouds. 36 * 37 * nanoflann does not require compiling or installing, just an 38 * #include <nanoflann.hpp> in your code. 39 * 40 * See: 41 * - <a href="modules.html" >C++ API organized by modules</a> 42 * - <a href="https://github.com/jlblancoc/nanoflann" >Online README</a> 43 * - <a href="http://jlblancoc.github.io/nanoflann/" >Doxygen 44 * documentation</a> 45 */ 46 47 #ifndef NANOFLANN_HPP_ 48 #define NANOFLANN_HPP_ 49 50 #include <algorithm> 51 #include <array> 52 #include <cassert> 53 #include <cmath> // for abs() 54 #include <cstdio> // for fwrite() 55 #include <cstdlib> // for abs() 56 #include <functional> 57 #include <limits> // std::reference_wrapper 58 #include <stdexcept> 59 #include <vector> 60 61 /** Library version: 0xMmP (M=Major,m=minor,P=patch) */ 62 #define NANOFLANN_VERSION 0x130 63 64 // Avoid conflicting declaration of min/max macros in windows headers 65 #if !defined(NOMINMAX) && \ 66 (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64)) 67 #define NOMINMAX 68 #ifdef max 69 #undef max 70 #undef min 71 #endif 72 #endif 73 74 namespace nanoflann { 75 /** @addtogroup nanoflann_grp nanoflann C++ library for ANN 76 * @{ */ 77 78 /** the PI constant (required to avoid MSVC missing symbols) */ pi_const()79 template <typename T> T pi_const() { 80 return static_cast<T>(3.14159265358979323846); 81 } 82 83 /** 84 * Traits if object is resizable and assignable (typically has a resize | assign 85 * method) 86 */ 87 template <typename T, typename = int> struct has_resize : std::false_type {}; 88 89 template <typename T> 90 struct has_resize<T, decltype((void)std::declval<T>().resize(1), 0)> 91 : std::true_type {}; 92 93 template <typename T, typename = int> struct has_assign : std::false_type {}; 94 95 template <typename T> 96 struct has_assign<T, decltype((void)std::declval<T>().assign(1, 0), 0)> 97 : std::true_type {}; 98 99 /** 100 * Free function to resize a resizable object 101 */ 102 template <typename Container> 103 inline typename std::enable_if<has_resize<Container>::value, void>::type resize(Container & c,const size_t nElements)104 resize(Container &c, const size_t nElements) { 105 c.resize(nElements); 106 } 107 108 /** 109 * Free function that has no effects on non resizable containers (e.g. 110 * std::array) It raises an exception if the expected size does not match 111 */ 112 template <typename Container> 113 inline typename std::enable_if<!has_resize<Container>::value, void>::type resize(Container & c,const size_t nElements)114 resize(Container &c, const size_t nElements) { 115 if (nElements != c.size()) 116 throw std::logic_error("Try to change the size of a std::array."); 117 } 118 119 /** 120 * Free function to assign to a container 121 */ 122 template <typename Container, typename T> 123 inline typename std::enable_if<has_assign<Container>::value, void>::type assign(Container & c,const size_t nElements,const T & value)124 assign(Container &c, const size_t nElements, const T &value) { 125 c.assign(nElements, value); 126 } 127 128 /** 129 * Free function to assign to a std::array 130 */ 131 template <typename Container, typename T> 132 inline typename std::enable_if<!has_assign<Container>::value, void>::type assign(Container & c,const size_t nElements,const T & value)133 assign(Container &c, const size_t nElements, const T &value) { 134 for (size_t i = 0; i < nElements; i++) 135 c[i] = value; 136 } 137 138 /** @addtogroup result_sets_grp Result set classes 139 * @{ */ 140 template <typename _DistanceType, typename _IndexType = size_t, 141 typename _CountType = size_t> 142 class KNNResultSet { 143 public: 144 typedef _DistanceType DistanceType; 145 typedef _IndexType IndexType; 146 typedef _CountType CountType; 147 148 private: 149 IndexType *indices; 150 DistanceType *dists; 151 CountType capacity; 152 CountType count; 153 154 public: KNNResultSet(CountType capacity_)155 inline KNNResultSet(CountType capacity_) 156 : indices(0), dists(0), capacity(capacity_), count(0) {} 157 init(IndexType * indices_,DistanceType * dists_)158 inline void init(IndexType *indices_, DistanceType *dists_) { 159 indices = indices_; 160 dists = dists_; 161 count = 0; 162 if (capacity) 163 dists[capacity - 1] = (std::numeric_limits<DistanceType>::max)(); 164 } 165 size() const166 inline CountType size() const { return count; } 167 full() const168 inline bool full() const { return count == capacity; } 169 170 /** 171 * Called during search to add an element matching the criteria. 172 * @return true if the search should be continued, false if the results are 173 * sufficient 174 */ addPoint(DistanceType dist,IndexType index)175 inline bool addPoint(DistanceType dist, IndexType index) { 176 CountType i; 177 for (i = count; i > 0; --i) { 178 #ifdef NANOFLANN_FIRST_MATCH // If defined and two points have the same 179 // distance, the one with the lowest-index will be 180 // returned first. 181 if ((dists[i - 1] > dist) || 182 ((dist == dists[i - 1]) && (indices[i - 1] > index))) { 183 #else 184 if (dists[i - 1] > dist) { 185 #endif 186 if (i < capacity) { 187 dists[i] = dists[i - 1]; 188 indices[i] = indices[i - 1]; 189 } 190 } else 191 break; 192 } 193 if (i < capacity) { 194 dists[i] = dist; 195 indices[i] = index; 196 } 197 if (count < capacity) 198 count++; 199 200 // tell caller that the search shall continue 201 return true; 202 } 203 204 inline DistanceType worstDist() const { return dists[capacity - 1]; } 205 }; 206 207 /** operator "<" for std::sort() */ 208 struct IndexDist_Sorter { 209 /** PairType will be typically: std::pair<IndexType,DistanceType> */ 210 template <typename PairType> operator ()nanoflann::IndexDist_Sorter211 inline bool operator()(const PairType &p1, const PairType &p2) const { 212 return p1.second < p2.second; 213 } 214 }; 215 216 /** 217 * A result-set class used when performing a radius based search. 218 */ 219 template <typename _DistanceType, typename _IndexType = size_t> 220 class RadiusResultSet { 221 public: 222 typedef _DistanceType DistanceType; 223 typedef _IndexType IndexType; 224 225 public: 226 const DistanceType radius; 227 228 std::vector<std::pair<IndexType, DistanceType>> &m_indices_dists; 229 RadiusResultSet(DistanceType radius_,std::vector<std::pair<IndexType,DistanceType>> & indices_dists)230 inline RadiusResultSet( 231 DistanceType radius_, 232 std::vector<std::pair<IndexType, DistanceType>> &indices_dists) 233 : radius(radius_), m_indices_dists(indices_dists) { 234 init(); 235 } 236 init()237 inline void init() { clear(); } clear()238 inline void clear() { m_indices_dists.clear(); } 239 size() const240 inline size_t size() const { return m_indices_dists.size(); } 241 full() const242 inline bool full() const { return true; } 243 244 /** 245 * Called during search to add an element matching the criteria. 246 * @return true if the search should be continued, false if the results are 247 * sufficient 248 */ addPoint(DistanceType dist,IndexType index)249 inline bool addPoint(DistanceType dist, IndexType index) { 250 if (dist < radius) 251 m_indices_dists.push_back(std::make_pair(index, dist)); 252 return true; 253 } 254 worstDist() const255 inline DistanceType worstDist() const { return radius; } 256 257 /** 258 * Find the worst result (furtherest neighbor) without copying or sorting 259 * Pre-conditions: size() > 0 260 */ worst_item() const261 std::pair<IndexType, DistanceType> worst_item() const { 262 if (m_indices_dists.empty()) 263 throw std::runtime_error("Cannot invoke RadiusResultSet::worst_item() on " 264 "an empty list of results."); 265 typedef 266 typename std::vector<std::pair<IndexType, DistanceType>>::const_iterator 267 DistIt; 268 DistIt it = std::max_element(m_indices_dists.begin(), m_indices_dists.end(), 269 IndexDist_Sorter()); 270 return *it; 271 } 272 }; 273 274 /** @} */ 275 276 /** @addtogroup loadsave_grp Load/save auxiliary functions 277 * @{ */ 278 template <typename T> save_value(FILE * stream,const T & value,size_t count=1)279 void save_value(FILE *stream, const T &value, size_t count = 1) { 280 fwrite(&value, sizeof(value), count, stream); 281 } 282 283 template <typename T> save_value(FILE * stream,const std::vector<T> & value)284 void save_value(FILE *stream, const std::vector<T> &value) { 285 size_t size = value.size(); 286 fwrite(&size, sizeof(size_t), 1, stream); 287 fwrite(&value[0], sizeof(T), size, stream); 288 } 289 290 template <typename T> load_value(FILE * stream,T & value,size_t count=1)291 void load_value(FILE *stream, T &value, size_t count = 1) { 292 size_t read_cnt = fread(&value, sizeof(value), count, stream); 293 if (read_cnt != count) { 294 throw std::runtime_error("Cannot read from file"); 295 } 296 } 297 load_value(FILE * stream,std::vector<T> & value)298 template <typename T> void load_value(FILE *stream, std::vector<T> &value) { 299 size_t size; 300 size_t read_cnt = fread(&size, sizeof(size_t), 1, stream); 301 if (read_cnt != 1) { 302 throw std::runtime_error("Cannot read from file"); 303 } 304 value.resize(size); 305 read_cnt = fread(&value[0], sizeof(T), size, stream); 306 if (read_cnt != size) { 307 throw std::runtime_error("Cannot read from file"); 308 } 309 } 310 /** @} */ 311 312 /** @addtogroup metric_grp Metric (distance) classes 313 * @{ */ 314 315 struct Metric {}; 316 317 /** Manhattan distance functor (generic version, optimized for 318 * high-dimensionality data sets). Corresponding distance traits: 319 * nanoflann::metric_L1 \tparam T Type of the elements (e.g. double, float, 320 * uint8_t) \tparam _DistanceType Type of distance variables (must be signed) 321 * (e.g. float, double, int64_t) 322 */ 323 template <class T, class DataSource, typename _DistanceType = T> 324 struct L1_Adaptor { 325 typedef T ElementType; 326 typedef _DistanceType DistanceType; 327 328 const DataSource &data_source; 329 L1_Adaptornanoflann::L1_Adaptor330 L1_Adaptor(const DataSource &_data_source) : data_source(_data_source) {} 331 evalMetricnanoflann::L1_Adaptor332 inline DistanceType evalMetric(const T *a, const size_t b_idx, size_t size, 333 DistanceType worst_dist = -1) const { 334 DistanceType result = DistanceType(); 335 const T *last = a + size; 336 const T *lastgroup = last - 3; 337 size_t d = 0; 338 339 /* Process 4 items with each loop for efficiency. */ 340 while (a < lastgroup) { 341 const DistanceType diff0 = 342 std::abs(a[0] - data_source.kdtree_get_pt(b_idx, d++)); 343 const DistanceType diff1 = 344 std::abs(a[1] - data_source.kdtree_get_pt(b_idx, d++)); 345 const DistanceType diff2 = 346 std::abs(a[2] - data_source.kdtree_get_pt(b_idx, d++)); 347 const DistanceType diff3 = 348 std::abs(a[3] - data_source.kdtree_get_pt(b_idx, d++)); 349 result += diff0 + diff1 + diff2 + diff3; 350 a += 4; 351 if ((worst_dist > 0) && (result > worst_dist)) { 352 return result; 353 } 354 } 355 /* Process last 0-3 components. Not needed for standard vector lengths. */ 356 while (a < last) { 357 result += std::abs(*a++ - data_source.kdtree_get_pt(b_idx, d++)); 358 } 359 return result; 360 } 361 362 template <typename U, typename V> accum_distnanoflann::L1_Adaptor363 inline DistanceType accum_dist(const U a, const V b, const size_t) const { 364 return std::abs(a - b); 365 } 366 }; 367 368 /** Squared Euclidean distance functor (generic version, optimized for 369 * high-dimensionality data sets). Corresponding distance traits: 370 * nanoflann::metric_L2 \tparam T Type of the elements (e.g. double, float, 371 * uint8_t) \tparam _DistanceType Type of distance variables (must be signed) 372 * (e.g. float, double, int64_t) 373 */ 374 template <class T, class DataSource, typename _DistanceType = T> 375 struct L2_Adaptor { 376 typedef T ElementType; 377 typedef _DistanceType DistanceType; 378 379 const DataSource &data_source; 380 L2_Adaptornanoflann::L2_Adaptor381 L2_Adaptor(const DataSource &_data_source) : data_source(_data_source) {} 382 evalMetricnanoflann::L2_Adaptor383 inline DistanceType evalMetric(const T *a, const size_t b_idx, size_t size, 384 DistanceType worst_dist = -1) const { 385 DistanceType result = DistanceType(); 386 const T *last = a + size; 387 const T *lastgroup = last - 3; 388 size_t d = 0; 389 390 /* Process 4 items with each loop for efficiency. */ 391 while (a < lastgroup) { 392 const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx, d++); 393 const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx, d++); 394 const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx, d++); 395 const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx, d++); 396 result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3; 397 a += 4; 398 if ((worst_dist > 0) && (result > worst_dist)) { 399 return result; 400 } 401 } 402 /* Process last 0-3 components. Not needed for standard vector lengths. */ 403 while (a < last) { 404 const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx, d++); 405 result += diff0 * diff0; 406 } 407 return result; 408 } 409 410 template <typename U, typename V> accum_distnanoflann::L2_Adaptor411 inline DistanceType accum_dist(const U a, const V b, const size_t) const { 412 return (a - b) * (a - b); 413 } 414 }; 415 416 /** Squared Euclidean (L2) distance functor (suitable for low-dimensionality 417 * datasets, like 2D or 3D point clouds) Corresponding distance traits: 418 * nanoflann::metric_L2_Simple \tparam T Type of the elements (e.g. double, 419 * float, uint8_t) \tparam _DistanceType Type of distance variables (must be 420 * signed) (e.g. float, double, int64_t) 421 */ 422 template <class T, class DataSource, typename _DistanceType = T> 423 struct L2_Simple_Adaptor { 424 typedef T ElementType; 425 typedef _DistanceType DistanceType; 426 427 const DataSource &data_source; 428 L2_Simple_Adaptornanoflann::L2_Simple_Adaptor429 L2_Simple_Adaptor(const DataSource &_data_source) 430 : data_source(_data_source) {} 431 evalMetricnanoflann::L2_Simple_Adaptor432 inline DistanceType evalMetric(const T *a, const size_t b_idx, 433 size_t size) const { 434 DistanceType result = DistanceType(); 435 for (size_t i = 0; i < size; ++i) { 436 const DistanceType diff = a[i] - data_source.kdtree_get_pt(b_idx, i); 437 result += diff * diff; 438 } 439 return result; 440 } 441 442 template <typename U, typename V> accum_distnanoflann::L2_Simple_Adaptor443 inline DistanceType accum_dist(const U a, const V b, const size_t) const { 444 return (a - b) * (a - b); 445 } 446 }; 447 448 /** SO2 distance functor 449 * Corresponding distance traits: nanoflann::metric_SO2 450 * \tparam T Type of the elements (e.g. double, float) 451 * \tparam _DistanceType Type of distance variables (must be signed) (e.g. 452 * float, double) orientation is constrained to be in [-pi, pi] 453 */ 454 template <class T, class DataSource, typename _DistanceType = T> 455 struct SO2_Adaptor { 456 typedef T ElementType; 457 typedef _DistanceType DistanceType; 458 459 const DataSource &data_source; 460 SO2_Adaptornanoflann::SO2_Adaptor461 SO2_Adaptor(const DataSource &_data_source) : data_source(_data_source) {} 462 evalMetricnanoflann::SO2_Adaptor463 inline DistanceType evalMetric(const T *a, const size_t b_idx, 464 size_t size) const { 465 return accum_dist(a[size - 1], data_source.kdtree_get_pt(b_idx, size - 1), 466 size - 1); 467 } 468 469 /** Note: this assumes that input angles are already in the range [-pi,pi] */ 470 template <typename U, typename V> accum_distnanoflann::SO2_Adaptor471 inline DistanceType accum_dist(const U a, const V b, const size_t) const { 472 DistanceType result = DistanceType(), PI = pi_const<DistanceType>(); 473 result = b - a; 474 if (result > PI) 475 result -= 2 * PI; 476 else if (result < -PI) 477 result += 2 * PI; 478 return result; 479 } 480 }; 481 482 /** SO3 distance functor (Uses L2_Simple) 483 * Corresponding distance traits: nanoflann::metric_SO3 484 * \tparam T Type of the elements (e.g. double, float) 485 * \tparam _DistanceType Type of distance variables (must be signed) (e.g. 486 * float, double) 487 */ 488 template <class T, class DataSource, typename _DistanceType = T> 489 struct SO3_Adaptor { 490 typedef T ElementType; 491 typedef _DistanceType DistanceType; 492 493 L2_Simple_Adaptor<T, DataSource> distance_L2_Simple; 494 SO3_Adaptornanoflann::SO3_Adaptor495 SO3_Adaptor(const DataSource &_data_source) 496 : distance_L2_Simple(_data_source) {} 497 evalMetricnanoflann::SO3_Adaptor498 inline DistanceType evalMetric(const T *a, const size_t b_idx, 499 size_t size) const { 500 return distance_L2_Simple.evalMetric(a, b_idx, size); 501 } 502 503 template <typename U, typename V> accum_distnanoflann::SO3_Adaptor504 inline DistanceType accum_dist(const U a, const V b, const size_t idx) const { 505 return distance_L2_Simple.accum_dist(a, b, idx); 506 } 507 }; 508 509 /** Metaprogramming helper traits class for the L1 (Manhattan) metric */ 510 struct metric_L1 : public Metric { 511 template <class T, class DataSource> struct traits { 512 typedef L1_Adaptor<T, DataSource> distance_t; 513 }; 514 }; 515 /** Metaprogramming helper traits class for the L2 (Euclidean) metric */ 516 struct metric_L2 : public Metric { 517 template <class T, class DataSource> struct traits { 518 typedef L2_Adaptor<T, DataSource> distance_t; 519 }; 520 }; 521 /** Metaprogramming helper traits class for the L2_simple (Euclidean) metric */ 522 struct metric_L2_Simple : public Metric { 523 template <class T, class DataSource> struct traits { 524 typedef L2_Simple_Adaptor<T, DataSource> distance_t; 525 }; 526 }; 527 /** Metaprogramming helper traits class for the SO3_InnerProdQuat metric */ 528 struct metric_SO2 : public Metric { 529 template <class T, class DataSource> struct traits { 530 typedef SO2_Adaptor<T, DataSource> distance_t; 531 }; 532 }; 533 /** Metaprogramming helper traits class for the SO3_InnerProdQuat metric */ 534 struct metric_SO3 : public Metric { 535 template <class T, class DataSource> struct traits { 536 typedef SO3_Adaptor<T, DataSource> distance_t; 537 }; 538 }; 539 540 /** @} */ 541 542 /** @addtogroup param_grp Parameter structs 543 * @{ */ 544 545 /** Parameters (see README.md) */ 546 struct KDTreeSingleIndexAdaptorParams { KDTreeSingleIndexAdaptorParamsnanoflann::KDTreeSingleIndexAdaptorParams547 KDTreeSingleIndexAdaptorParams(size_t _leaf_max_size = 10) 548 : leaf_max_size(_leaf_max_size) {} 549 550 size_t leaf_max_size; 551 }; 552 553 /** Search options for KDTreeSingleIndexAdaptor::findNeighbors() */ 554 struct SearchParams { 555 /** Note: The first argument (checks_IGNORED_) is ignored, but kept for 556 * compatibility with the FLANN interface */ SearchParamsnanoflann::SearchParams557 SearchParams(int checks_IGNORED_ = 32, float eps_ = 0, bool sorted_ = true) 558 : checks(checks_IGNORED_), eps(eps_), sorted(sorted_) {} 559 560 int checks; //!< Ignored parameter (Kept for compatibility with the FLANN 561 //!< interface). 562 float eps; //!< search for eps-approximate neighbours (default: 0) 563 bool sorted; //!< only for radius search, require neighbours sorted by 564 //!< distance (default: true) 565 }; 566 /** @} */ 567 568 /** @addtogroup memalloc_grp Memory allocation 569 * @{ */ 570 571 /** 572 * Allocates (using C's malloc) a generic type T. 573 * 574 * Params: 575 * count = number of instances to allocate. 576 * Returns: pointer (of type T*) to memory buffer 577 */ allocate(size_t count=1)578 template <typename T> inline T *allocate(size_t count = 1) { 579 T *mem = static_cast<T *>(::malloc(sizeof(T) * count)); 580 return mem; 581 } 582 583 /** 584 * Pooled storage allocator 585 * 586 * The following routines allow for the efficient allocation of storage in 587 * small chunks from a specified pool. Rather than allowing each structure 588 * to be freed individually, an entire pool of storage is freed at once. 589 * This method has two advantages over just using malloc() and free(). First, 590 * it is far more efficient for allocating small objects, as there is 591 * no overhead for remembering all the information needed to free each 592 * object or consolidating fragmented memory. Second, the decision about 593 * how long to keep an object is made at the time of allocation, and there 594 * is no need to track down all the objects to free them. 595 * 596 */ 597 598 const size_t WORDSIZE = 16; 599 const size_t BLOCKSIZE = 8192; 600 601 class PooledAllocator { 602 /* We maintain memory alignment to word boundaries by requiring that all 603 allocations be in multiples of the machine wordsize. */ 604 /* Size of machine word in bytes. Must be power of 2. */ 605 /* Minimum number of bytes requested at a time from the system. Must be 606 * multiple of WORDSIZE. */ 607 608 size_t remaining; /* Number of bytes left in current block of storage. */ 609 void *base; /* Pointer to base of current block of storage. */ 610 void *loc; /* Current location in block to next allocate memory. */ 611 internal_init()612 void internal_init() { 613 remaining = 0; 614 base = NULL; 615 usedMemory = 0; 616 wastedMemory = 0; 617 } 618 619 public: 620 size_t usedMemory; 621 size_t wastedMemory; 622 623 /** 624 Default constructor. Initializes a new pool. 625 */ PooledAllocator()626 PooledAllocator() { internal_init(); } 627 628 /** 629 * Destructor. Frees all the memory allocated in this pool. 630 */ ~PooledAllocator()631 ~PooledAllocator() { free_all(); } 632 633 /** Frees all allocated memory chunks */ free_all()634 void free_all() { 635 while (base != NULL) { 636 void *prev = 637 *(static_cast<void **>(base)); /* Get pointer to prev block. */ 638 ::free(base); 639 base = prev; 640 } 641 internal_init(); 642 } 643 644 /** 645 * Returns a pointer to a piece of new memory of the given size in bytes 646 * allocated from the pool. 647 */ malloc(const size_t req_size)648 void *malloc(const size_t req_size) { 649 /* Round size up to a multiple of wordsize. The following expression 650 only works for WORDSIZE that is a power of 2, by masking last bits of 651 incremented size to zero. 652 */ 653 const size_t size = (req_size + (WORDSIZE - 1)) & ~(WORDSIZE - 1); 654 655 /* Check whether a new block must be allocated. Note that the first word 656 of a block is reserved for a pointer to the previous block. 657 */ 658 if (size > remaining) { 659 660 wastedMemory += remaining; 661 662 /* Allocate new storage. */ 663 const size_t blocksize = 664 (size + sizeof(void *) + (WORDSIZE - 1) > BLOCKSIZE) 665 ? size + sizeof(void *) + (WORDSIZE - 1) 666 : BLOCKSIZE; 667 668 // use the standard C malloc to allocate memory 669 void *m = ::malloc(blocksize); 670 if (!m) { 671 fprintf(stderr, "Failed to allocate memory.\n"); 672 return NULL; 673 } 674 675 /* Fill first word of new block with pointer to previous block. */ 676 static_cast<void **>(m)[0] = base; 677 base = m; 678 679 size_t shift = 0; 680 // int size_t = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & 681 // (WORDSIZE-1))) & (WORDSIZE-1); 682 683 remaining = blocksize - sizeof(void *) - shift; 684 loc = (static_cast<char *>(m) + sizeof(void *) + shift); 685 } 686 void *rloc = loc; 687 loc = static_cast<char *>(loc) + size; 688 remaining -= size; 689 690 usedMemory += size; 691 692 return rloc; 693 } 694 695 /** 696 * Allocates (using this pool) a generic type T. 697 * 698 * Params: 699 * count = number of instances to allocate. 700 * Returns: pointer (of type T*) to memory buffer 701 */ allocate(const size_t count=1)702 template <typename T> T *allocate(const size_t count = 1) { 703 T *mem = static_cast<T *>(this->malloc(sizeof(T) * count)); 704 return mem; 705 } 706 }; 707 /** @} */ 708 709 /** @addtogroup nanoflann_metaprog_grp Auxiliary metaprogramming stuff 710 * @{ */ 711 712 /** Used to declare fixed-size arrays when DIM>0, dynamically-allocated vectors 713 * when DIM=-1. Fixed size version for a generic DIM: 714 */ 715 template <int DIM, typename T> struct array_or_vector_selector { 716 typedef std::array<T, DIM> container_t; 717 }; 718 /** Dynamic size version */ 719 template <typename T> struct array_or_vector_selector<-1, T> { 720 typedef std::vector<T> container_t; 721 }; 722 723 /** @} */ 724 725 /** kd-tree base-class 726 * 727 * Contains the member functions common to the classes KDTreeSingleIndexAdaptor 728 * and KDTreeSingleIndexDynamicAdaptor_. 729 * 730 * \tparam Derived The name of the class which inherits this class. 731 * \tparam DatasetAdaptor The user-provided adaptor (see comments above). 732 * \tparam Distance The distance metric to use, these are all classes derived 733 * from nanoflann::Metric \tparam DIM Dimensionality of data points (e.g. 3 for 734 * 3D points) \tparam IndexType Will be typically size_t or int 735 */ 736 737 template <class Derived, typename Distance, class DatasetAdaptor, int DIM = -1, 738 typename IndexType = size_t> 739 class KDTreeBaseClass { 740 741 public: 742 /** Frees the previously-built index. Automatically called within 743 * buildIndex(). */ freeIndex(Derived & obj)744 void freeIndex(Derived &obj) { 745 obj.pool.free_all(); 746 obj.root_node = NULL; 747 obj.m_size_at_index_build = 0; 748 } 749 750 typedef typename Distance::ElementType ElementType; 751 typedef typename Distance::DistanceType DistanceType; 752 753 /*--------------------- Internal Data Structures --------------------------*/ 754 struct Node { 755 /** Union used because a node can be either a LEAF node or a non-leaf node, 756 * so both data fields are never used simultaneously */ 757 union { 758 struct leaf { 759 IndexType left, right; //!< Indices of points in leaf node 760 } lr; 761 struct nonleaf { 762 int divfeat; //!< Dimension used for subdivision. 763 DistanceType divlow, divhigh; //!< The values used for subdivision. 764 } sub; 765 } node_type; 766 Node *child1, *child2; //!< Child nodes (both=NULL mean its a leaf node) 767 }; 768 769 typedef Node *NodePtr; 770 771 struct Interval { 772 ElementType low, high; 773 }; 774 775 /** 776 * Array of indices to vectors in the dataset. 777 */ 778 std::vector<IndexType> vind; 779 780 NodePtr root_node; 781 782 size_t m_leaf_max_size; 783 784 size_t m_size; //!< Number of current points in the dataset 785 size_t m_size_at_index_build; //!< Number of points in the dataset when the 786 //!< index was built 787 int dim; //!< Dimensionality of each data point 788 789 /** Define "BoundingBox" as a fixed-size or variable-size container depending 790 * on "DIM" */ 791 typedef 792 typename array_or_vector_selector<DIM, Interval>::container_t BoundingBox; 793 794 /** Define "distance_vector_t" as a fixed-size or variable-size container 795 * depending on "DIM" */ 796 typedef typename array_or_vector_selector<DIM, DistanceType>::container_t 797 distance_vector_t; 798 799 /** The KD-tree used to find neighbours */ 800 801 BoundingBox root_bbox; 802 803 /** 804 * Pooled memory allocator. 805 * 806 * Using a pooled memory allocator is more efficient 807 * than allocating memory directly when there is a large 808 * number small of memory allocations. 809 */ 810 PooledAllocator pool; 811 812 /** Returns number of points in dataset */ size(const Derived & obj) const813 size_t size(const Derived &obj) const { return obj.m_size; } 814 815 /** Returns the length of each point in the dataset */ veclen(const Derived & obj)816 size_t veclen(const Derived &obj) { 817 return static_cast<size_t>(DIM > 0 ? DIM : obj.dim); 818 } 819 820 /// Helper accessor to the dataset points: dataset_get(const Derived & obj,size_t idx,int component) const821 inline ElementType dataset_get(const Derived &obj, size_t idx, 822 int component) const { 823 return obj.dataset.kdtree_get_pt(idx, component); 824 } 825 826 /** 827 * Computes the inde memory usage 828 * Returns: memory used by the index 829 */ usedMemory(Derived & obj)830 size_t usedMemory(Derived &obj) { 831 return obj.pool.usedMemory + obj.pool.wastedMemory + 832 obj.dataset.kdtree_get_point_count() * 833 sizeof(IndexType); // pool memory and vind array memory 834 } 835 computeMinMax(const Derived & obj,IndexType * ind,IndexType count,int element,ElementType & min_elem,ElementType & max_elem)836 void computeMinMax(const Derived &obj, IndexType *ind, IndexType count, 837 int element, ElementType &min_elem, 838 ElementType &max_elem) { 839 min_elem = dataset_get(obj, ind[0], element); 840 max_elem = dataset_get(obj, ind[0], element); 841 for (IndexType i = 1; i < count; ++i) { 842 ElementType val = dataset_get(obj, ind[i], element); 843 if (val < min_elem) 844 min_elem = val; 845 if (val > max_elem) 846 max_elem = val; 847 } 848 } 849 850 /** 851 * Create a tree node that subdivides the list of vecs from vind[first] 852 * to vind[last]. The routine is called recursively on each sublist. 853 * 854 * @param left index of the first vector 855 * @param right index of the last vector 856 */ divideTree(Derived & obj,const IndexType left,const IndexType right,BoundingBox & bbox)857 NodePtr divideTree(Derived &obj, const IndexType left, const IndexType right, 858 BoundingBox &bbox) { 859 NodePtr node = obj.pool.template allocate<Node>(); // allocate memory 860 861 /* If too few exemplars remain, then make this a leaf node. */ 862 if ((right - left) <= static_cast<IndexType>(obj.m_leaf_max_size)) { 863 node->child1 = node->child2 = NULL; /* Mark as leaf node. */ 864 node->node_type.lr.left = left; 865 node->node_type.lr.right = right; 866 867 // compute bounding-box of leaf points 868 for (int i = 0; i < (DIM > 0 ? DIM : obj.dim); ++i) { 869 bbox[i].low = dataset_get(obj, obj.vind[left], i); 870 bbox[i].high = dataset_get(obj, obj.vind[left], i); 871 } 872 for (IndexType k = left + 1; k < right; ++k) { 873 for (int i = 0; i < (DIM > 0 ? DIM : obj.dim); ++i) { 874 if (bbox[i].low > dataset_get(obj, obj.vind[k], i)) 875 bbox[i].low = dataset_get(obj, obj.vind[k], i); 876 if (bbox[i].high < dataset_get(obj, obj.vind[k], i)) 877 bbox[i].high = dataset_get(obj, obj.vind[k], i); 878 } 879 } 880 } else { 881 IndexType idx; 882 int cutfeat; 883 DistanceType cutval; 884 middleSplit_(obj, &obj.vind[0] + left, right - left, idx, cutfeat, cutval, 885 bbox); 886 887 node->node_type.sub.divfeat = cutfeat; 888 889 BoundingBox left_bbox(bbox); 890 left_bbox[cutfeat].high = cutval; 891 node->child1 = divideTree(obj, left, left + idx, left_bbox); 892 893 BoundingBox right_bbox(bbox); 894 right_bbox[cutfeat].low = cutval; 895 node->child2 = divideTree(obj, left + idx, right, right_bbox); 896 897 node->node_type.sub.divlow = left_bbox[cutfeat].high; 898 node->node_type.sub.divhigh = right_bbox[cutfeat].low; 899 900 for (int i = 0; i < (DIM > 0 ? DIM : obj.dim); ++i) { 901 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low); 902 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high); 903 } 904 } 905 906 return node; 907 } 908 middleSplit_(Derived & obj,IndexType * ind,IndexType count,IndexType & index,int & cutfeat,DistanceType & cutval,const BoundingBox & bbox)909 void middleSplit_(Derived &obj, IndexType *ind, IndexType count, 910 IndexType &index, int &cutfeat, DistanceType &cutval, 911 const BoundingBox &bbox) { 912 const DistanceType EPS = static_cast<DistanceType>(0.00001); 913 ElementType max_span = bbox[0].high - bbox[0].low; 914 for (int i = 1; i < (DIM > 0 ? DIM : obj.dim); ++i) { 915 ElementType span = bbox[i].high - bbox[i].low; 916 if (span > max_span) { 917 max_span = span; 918 } 919 } 920 ElementType max_spread = -1; 921 cutfeat = 0; 922 for (int i = 0; i < (DIM > 0 ? DIM : obj.dim); ++i) { 923 ElementType span = bbox[i].high - bbox[i].low; 924 if (span > (1 - EPS) * max_span) { 925 ElementType min_elem, max_elem; 926 computeMinMax(obj, ind, count, i, min_elem, max_elem); 927 ElementType spread = max_elem - min_elem; 928 ; 929 if (spread > max_spread) { 930 cutfeat = i; 931 max_spread = spread; 932 } 933 } 934 } 935 // split in the middle 936 DistanceType split_val = (bbox[cutfeat].low + bbox[cutfeat].high) / 2; 937 ElementType min_elem, max_elem; 938 computeMinMax(obj, ind, count, cutfeat, min_elem, max_elem); 939 940 if (split_val < min_elem) 941 cutval = min_elem; 942 else if (split_val > max_elem) 943 cutval = max_elem; 944 else 945 cutval = split_val; 946 947 IndexType lim1, lim2; 948 planeSplit(obj, ind, count, cutfeat, cutval, lim1, lim2); 949 950 if (lim1 > count / 2) 951 index = lim1; 952 else if (lim2 < count / 2) 953 index = lim2; 954 else 955 index = count / 2; 956 } 957 958 /** 959 * Subdivide the list of points by a plane perpendicular on axe corresponding 960 * to the 'cutfeat' dimension at 'cutval' position. 961 * 962 * On return: 963 * dataset[ind[0..lim1-1]][cutfeat]<cutval 964 * dataset[ind[lim1..lim2-1]][cutfeat]==cutval 965 * dataset[ind[lim2..count]][cutfeat]>cutval 966 */ planeSplit(Derived & obj,IndexType * ind,const IndexType count,int cutfeat,DistanceType & cutval,IndexType & lim1,IndexType & lim2)967 void planeSplit(Derived &obj, IndexType *ind, const IndexType count, 968 int cutfeat, DistanceType &cutval, IndexType &lim1, 969 IndexType &lim2) { 970 /* Move vector indices for left subtree to front of list. */ 971 IndexType left = 0; 972 IndexType right = count - 1; 973 for (;;) { 974 while (left <= right && dataset_get(obj, ind[left], cutfeat) < cutval) 975 ++left; 976 while (right && left <= right && 977 dataset_get(obj, ind[right], cutfeat) >= cutval) 978 --right; 979 if (left > right || !right) 980 break; // "!right" was added to support unsigned Index types 981 std::swap(ind[left], ind[right]); 982 ++left; 983 --right; 984 } 985 /* If either list is empty, it means that all remaining features 986 * are identical. Split in the middle to maintain a balanced tree. 987 */ 988 lim1 = left; 989 right = count - 1; 990 for (;;) { 991 while (left <= right && dataset_get(obj, ind[left], cutfeat) <= cutval) 992 ++left; 993 while (right && left <= right && 994 dataset_get(obj, ind[right], cutfeat) > cutval) 995 --right; 996 if (left > right || !right) 997 break; // "!right" was added to support unsigned Index types 998 std::swap(ind[left], ind[right]); 999 ++left; 1000 --right; 1001 } 1002 lim2 = left; 1003 } 1004 computeInitialDistances(const Derived & obj,const ElementType * vec,distance_vector_t & dists) const1005 DistanceType computeInitialDistances(const Derived &obj, 1006 const ElementType *vec, 1007 distance_vector_t &dists) const { 1008 assert(vec); 1009 DistanceType distsq = DistanceType(); 1010 1011 for (int i = 0; i < (DIM > 0 ? DIM : obj.dim); ++i) { 1012 if (vec[i] < obj.root_bbox[i].low) { 1013 dists[i] = obj.distance.accum_dist(vec[i], obj.root_bbox[i].low, i); 1014 distsq += dists[i]; 1015 } 1016 if (vec[i] > obj.root_bbox[i].high) { 1017 dists[i] = obj.distance.accum_dist(vec[i], obj.root_bbox[i].high, i); 1018 distsq += dists[i]; 1019 } 1020 } 1021 return distsq; 1022 } 1023 save_tree(Derived & obj,FILE * stream,NodePtr tree)1024 void save_tree(Derived &obj, FILE *stream, NodePtr tree) { 1025 save_value(stream, *tree); 1026 if (tree->child1 != NULL) { 1027 save_tree(obj, stream, tree->child1); 1028 } 1029 if (tree->child2 != NULL) { 1030 save_tree(obj, stream, tree->child2); 1031 } 1032 } 1033 load_tree(Derived & obj,FILE * stream,NodePtr & tree)1034 void load_tree(Derived &obj, FILE *stream, NodePtr &tree) { 1035 tree = obj.pool.template allocate<Node>(); 1036 load_value(stream, *tree); 1037 if (tree->child1 != NULL) { 1038 load_tree(obj, stream, tree->child1); 1039 } 1040 if (tree->child2 != NULL) { 1041 load_tree(obj, stream, tree->child2); 1042 } 1043 } 1044 1045 /** Stores the index in a binary file. 1046 * IMPORTANT NOTE: The set of data points is NOT stored in the file, so when 1047 * loading the index object it must be constructed associated to the same 1048 * source of data points used while building it. See the example: 1049 * examples/saveload_example.cpp \sa loadIndex */ saveIndex_(Derived & obj,FILE * stream)1050 void saveIndex_(Derived &obj, FILE *stream) { 1051 save_value(stream, obj.m_size); 1052 save_value(stream, obj.dim); 1053 save_value(stream, obj.root_bbox); 1054 save_value(stream, obj.m_leaf_max_size); 1055 save_value(stream, obj.vind); 1056 save_tree(obj, stream, obj.root_node); 1057 } 1058 1059 /** Loads a previous index from a binary file. 1060 * IMPORTANT NOTE: The set of data points is NOT stored in the file, so the 1061 * index object must be constructed associated to the same source of data 1062 * points used while building the index. See the example: 1063 * examples/saveload_example.cpp \sa loadIndex */ loadIndex_(Derived & obj,FILE * stream)1064 void loadIndex_(Derived &obj, FILE *stream) { 1065 load_value(stream, obj.m_size); 1066 load_value(stream, obj.dim); 1067 load_value(stream, obj.root_bbox); 1068 load_value(stream, obj.m_leaf_max_size); 1069 load_value(stream, obj.vind); 1070 load_tree(obj, stream, obj.root_node); 1071 } 1072 }; 1073 1074 /** @addtogroup kdtrees_grp KD-tree classes and adaptors 1075 * @{ */ 1076 1077 /** kd-tree static index 1078 * 1079 * Contains the k-d trees and other information for indexing a set of points 1080 * for nearest-neighbor matching. 1081 * 1082 * The class "DatasetAdaptor" must provide the following interface (can be 1083 * non-virtual, inlined methods): 1084 * 1085 * \code 1086 * // Must return the number of data poins 1087 * inline size_t kdtree_get_point_count() const { ... } 1088 * 1089 * 1090 * // Must return the dim'th component of the idx'th point in the class: 1091 * inline T kdtree_get_pt(const size_t idx, const size_t dim) const { ... } 1092 * 1093 * // Optional bounding-box computation: return false to default to a standard 1094 * bbox computation loop. 1095 * // Return true if the BBOX was already computed by the class and returned 1096 * in "bb" so it can be avoided to redo it again. 1097 * // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 1098 * for point clouds) template <class BBOX> bool kdtree_get_bbox(BBOX &bb) const 1099 * { 1100 * bb[0].low = ...; bb[0].high = ...; // 0th dimension limits 1101 * bb[1].low = ...; bb[1].high = ...; // 1st dimension limits 1102 * ... 1103 * return true; 1104 * } 1105 * 1106 * \endcode 1107 * 1108 * \tparam DatasetAdaptor The user-provided adaptor (see comments above). 1109 * \tparam Distance The distance metric to use: nanoflann::metric_L1, 1110 * nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc. \tparam DIM 1111 * Dimensionality of data points (e.g. 3 for 3D points) \tparam IndexType Will 1112 * be typically size_t or int 1113 */ 1114 template <typename Distance, class DatasetAdaptor, int DIM = -1, 1115 typename IndexType = size_t> 1116 class KDTreeSingleIndexAdaptor 1117 : public KDTreeBaseClass< 1118 KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM, IndexType>, 1119 Distance, DatasetAdaptor, DIM, IndexType> { 1120 public: 1121 /** Deleted copy constructor*/ 1122 KDTreeSingleIndexAdaptor( 1123 const KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM, IndexType> 1124 &) = delete; 1125 1126 /** 1127 * The dataset used by this index 1128 */ 1129 const DatasetAdaptor &dataset; //!< The source of our data 1130 1131 const KDTreeSingleIndexAdaptorParams index_params; 1132 1133 Distance distance; 1134 1135 typedef typename nanoflann::KDTreeBaseClass< 1136 nanoflann::KDTreeSingleIndexAdaptor<Distance, DatasetAdaptor, DIM, 1137 IndexType>, 1138 Distance, DatasetAdaptor, DIM, IndexType> 1139 BaseClassRef; 1140 1141 typedef typename BaseClassRef::ElementType ElementType; 1142 typedef typename BaseClassRef::DistanceType DistanceType; 1143 1144 typedef typename BaseClassRef::Node Node; 1145 typedef Node *NodePtr; 1146 1147 typedef typename BaseClassRef::Interval Interval; 1148 /** Define "BoundingBox" as a fixed-size or variable-size container depending 1149 * on "DIM" */ 1150 typedef typename BaseClassRef::BoundingBox BoundingBox; 1151 1152 /** Define "distance_vector_t" as a fixed-size or variable-size container 1153 * depending on "DIM" */ 1154 typedef typename BaseClassRef::distance_vector_t distance_vector_t; 1155 1156 /** 1157 * KDTree constructor 1158 * 1159 * Refer to docs in README.md or online in 1160 * https://github.com/jlblancoc/nanoflann 1161 * 1162 * The KD-Tree point dimension (the length of each point in the datase, e.g. 3 1163 * for 3D points) is determined by means of: 1164 * - The \a DIM template parameter if >0 (highest priority) 1165 * - Otherwise, the \a dimensionality parameter of this constructor. 1166 * 1167 * @param inputData Dataset with the input features 1168 * @param params Basically, the maximum leaf node size 1169 */ KDTreeSingleIndexAdaptor(const int dimensionality,const DatasetAdaptor & inputData,const KDTreeSingleIndexAdaptorParams & params=KDTreeSingleIndexAdaptorParams ())1170 KDTreeSingleIndexAdaptor(const int dimensionality, 1171 const DatasetAdaptor &inputData, 1172 const KDTreeSingleIndexAdaptorParams ¶ms = 1173 KDTreeSingleIndexAdaptorParams()) 1174 : dataset(inputData), index_params(params), distance(inputData) { 1175 BaseClassRef::root_node = NULL; 1176 BaseClassRef::m_size = dataset.kdtree_get_point_count(); 1177 BaseClassRef::m_size_at_index_build = BaseClassRef::m_size; 1178 BaseClassRef::dim = dimensionality; 1179 if (DIM > 0) 1180 BaseClassRef::dim = DIM; 1181 BaseClassRef::m_leaf_max_size = params.leaf_max_size; 1182 1183 // Create a permutable array of indices to the input vectors. 1184 init_vind(); 1185 } 1186 1187 /** 1188 * Builds the index 1189 */ buildIndex()1190 void buildIndex() { 1191 BaseClassRef::m_size = dataset.kdtree_get_point_count(); 1192 BaseClassRef::m_size_at_index_build = BaseClassRef::m_size; 1193 init_vind(); 1194 this->freeIndex(*this); 1195 BaseClassRef::m_size_at_index_build = BaseClassRef::m_size; 1196 if (BaseClassRef::m_size == 0) 1197 return; 1198 computeBoundingBox(BaseClassRef::root_bbox); 1199 BaseClassRef::root_node = 1200 this->divideTree(*this, 0, BaseClassRef::m_size, 1201 BaseClassRef::root_bbox); // construct the tree 1202 } 1203 1204 /** \name Query methods 1205 * @{ */ 1206 1207 /** 1208 * Find set of nearest neighbors to vec[0:dim-1]. Their indices are stored 1209 * inside the result object. 1210 * 1211 * Params: 1212 * result = the result object in which the indices of the 1213 * nearest-neighbors are stored vec = the vector for which to search the 1214 * nearest neighbors 1215 * 1216 * \tparam RESULTSET Should be any ResultSet<DistanceType> 1217 * \return True if the requested neighbors could be found. 1218 * \sa knnSearch, radiusSearch 1219 */ 1220 template <typename RESULTSET> findNeighbors(RESULTSET & result,const ElementType * vec,const SearchParams & searchParams) const1221 bool findNeighbors(RESULTSET &result, const ElementType *vec, 1222 const SearchParams &searchParams) const { 1223 assert(vec); 1224 if (this->size(*this) == 0) 1225 return false; 1226 if (!BaseClassRef::root_node) 1227 throw std::runtime_error( 1228 "[nanoflann] findNeighbors() called before building the index."); 1229 float epsError = 1 + searchParams.eps; 1230 1231 distance_vector_t 1232 dists; // fixed or variable-sized container (depending on DIM) 1233 auto zero = static_cast<decltype(result.worstDist())>(0); 1234 assign(dists, (DIM > 0 ? DIM : BaseClassRef::dim), 1235 zero); // Fill it with zeros. 1236 DistanceType distsq = this->computeInitialDistances(*this, vec, dists); 1237 searchLevel(result, vec, BaseClassRef::root_node, distsq, dists, 1238 epsError); // "count_leaf" parameter removed since was neither 1239 // used nor returned to the user. 1240 return result.full(); 1241 } 1242 1243 /** 1244 * Find the "num_closest" nearest neighbors to the \a query_point[0:dim-1]. 1245 * Their indices are stored inside the result object. \sa radiusSearch, 1246 * findNeighbors \note nChecks_IGNORED is ignored but kept for compatibility 1247 * with the original FLANN interface. \return Number `N` of valid points in 1248 * the result set. Only the first `N` entries in `out_indices` and 1249 * `out_distances_sq` will be valid. Return may be less than `num_closest` 1250 * only if the number of elements in the tree is less than `num_closest`. 1251 */ knnSearch(const ElementType * query_point,const size_t num_closest,IndexType * out_indices,DistanceType * out_distances_sq,const int=10) const1252 size_t knnSearch(const ElementType *query_point, const size_t num_closest, 1253 IndexType *out_indices, DistanceType *out_distances_sq, 1254 const int /* nChecks_IGNORED */ = 10) const { 1255 nanoflann::KNNResultSet<DistanceType, IndexType> resultSet(num_closest); 1256 resultSet.init(out_indices, out_distances_sq); 1257 this->findNeighbors(resultSet, query_point, nanoflann::SearchParams()); 1258 return resultSet.size(); 1259 } 1260 1261 /** 1262 * Find all the neighbors to \a query_point[0:dim-1] within a maximum radius. 1263 * The output is given as a vector of pairs, of which the first element is a 1264 * point index and the second the corresponding distance. Previous contents of 1265 * \a IndicesDists are cleared. 1266 * 1267 * If searchParams.sorted==true, the output list is sorted by ascending 1268 * distances. 1269 * 1270 * For a better performance, it is advisable to do a .reserve() on the vector 1271 * if you have any wild guess about the number of expected matches. 1272 * 1273 * \sa knnSearch, findNeighbors, radiusSearchCustomCallback 1274 * \return The number of points within the given radius (i.e. indices.size() 1275 * or dists.size() ) 1276 */ 1277 size_t radiusSearch(const ElementType * query_point,const DistanceType & radius,std::vector<std::pair<IndexType,DistanceType>> & IndicesDists,const SearchParams & searchParams) const1278 radiusSearch(const ElementType *query_point, const DistanceType &radius, 1279 std::vector<std::pair<IndexType, DistanceType>> &IndicesDists, 1280 const SearchParams &searchParams) const { 1281 RadiusResultSet<DistanceType, IndexType> resultSet(radius, IndicesDists); 1282 const size_t nFound = 1283 radiusSearchCustomCallback(query_point, resultSet, searchParams); 1284 if (searchParams.sorted) 1285 std::sort(IndicesDists.begin(), IndicesDists.end(), IndexDist_Sorter()); 1286 return nFound; 1287 } 1288 1289 /** 1290 * Just like radiusSearch() but with a custom callback class for each point 1291 * found in the radius of the query. See the source of RadiusResultSet<> as a 1292 * start point for your own classes. \sa radiusSearch 1293 */ 1294 template <class SEARCH_CALLBACK> radiusSearchCustomCallback(const ElementType * query_point,SEARCH_CALLBACK & resultSet,const SearchParams & searchParams=SearchParams ()) const1295 size_t radiusSearchCustomCallback( 1296 const ElementType *query_point, SEARCH_CALLBACK &resultSet, 1297 const SearchParams &searchParams = SearchParams()) const { 1298 this->findNeighbors(resultSet, query_point, searchParams); 1299 return resultSet.size(); 1300 } 1301 1302 /** @} */ 1303 1304 public: 1305 /** Make sure the auxiliary list \a vind has the same size than the current 1306 * dataset, and re-generate if size has changed. */ init_vind()1307 void init_vind() { 1308 // Create a permutable array of indices to the input vectors. 1309 BaseClassRef::m_size = dataset.kdtree_get_point_count(); 1310 if (BaseClassRef::vind.size() != BaseClassRef::m_size) 1311 BaseClassRef::vind.resize(BaseClassRef::m_size); 1312 for (size_t i = 0; i < BaseClassRef::m_size; i++) 1313 BaseClassRef::vind[i] = i; 1314 } 1315 computeBoundingBox(BoundingBox & bbox)1316 void computeBoundingBox(BoundingBox &bbox) { 1317 resize(bbox, (DIM > 0 ? DIM : BaseClassRef::dim)); 1318 if (dataset.kdtree_get_bbox(bbox)) { 1319 // Done! It was implemented in derived class 1320 } else { 1321 const size_t N = dataset.kdtree_get_point_count(); 1322 if (!N) 1323 throw std::runtime_error("[nanoflann] computeBoundingBox() called but " 1324 "no data points found."); 1325 for (int i = 0; i < (DIM > 0 ? DIM : BaseClassRef::dim); ++i) { 1326 bbox[i].low = bbox[i].high = this->dataset_get(*this, 0, i); 1327 } 1328 for (size_t k = 1; k < N; ++k) { 1329 for (int i = 0; i < (DIM > 0 ? DIM : BaseClassRef::dim); ++i) { 1330 if (this->dataset_get(*this, k, i) < bbox[i].low) 1331 bbox[i].low = this->dataset_get(*this, k, i); 1332 if (this->dataset_get(*this, k, i) > bbox[i].high) 1333 bbox[i].high = this->dataset_get(*this, k, i); 1334 } 1335 } 1336 } 1337 } 1338 1339 /** 1340 * Performs an exact search in the tree starting from a node. 1341 * \tparam RESULTSET Should be any ResultSet<DistanceType> 1342 * \return true if the search should be continued, false if the results are 1343 * sufficient 1344 */ 1345 template <class RESULTSET> searchLevel(RESULTSET & result_set,const ElementType * vec,const NodePtr node,DistanceType mindistsq,distance_vector_t & dists,const float epsError) const1346 bool searchLevel(RESULTSET &result_set, const ElementType *vec, 1347 const NodePtr node, DistanceType mindistsq, 1348 distance_vector_t &dists, const float epsError) const { 1349 /* If this is a leaf node, then do check and return. */ 1350 if ((node->child1 == NULL) && (node->child2 == NULL)) { 1351 // count_leaf += (node->lr.right-node->lr.left); // Removed since was 1352 // neither used nor returned to the user. 1353 DistanceType worst_dist = result_set.worstDist(); 1354 for (IndexType i = node->node_type.lr.left; i < node->node_type.lr.right; 1355 ++i) { 1356 const IndexType index = BaseClassRef::vind[i]; // reorder... : i; 1357 DistanceType dist = distance.evalMetric( 1358 vec, index, (DIM > 0 ? DIM : BaseClassRef::dim)); 1359 if (dist < worst_dist) { 1360 if (!result_set.addPoint(dist, BaseClassRef::vind[i])) { 1361 // the resultset doesn't want to receive any more points, we're done 1362 // searching! 1363 return false; 1364 } 1365 } 1366 } 1367 return true; 1368 } 1369 1370 /* Which child branch should be taken first? */ 1371 int idx = node->node_type.sub.divfeat; 1372 ElementType val = vec[idx]; 1373 DistanceType diff1 = val - node->node_type.sub.divlow; 1374 DistanceType diff2 = val - node->node_type.sub.divhigh; 1375 1376 NodePtr bestChild; 1377 NodePtr otherChild; 1378 DistanceType cut_dist; 1379 if ((diff1 + diff2) < 0) { 1380 bestChild = node->child1; 1381 otherChild = node->child2; 1382 cut_dist = distance.accum_dist(val, node->node_type.sub.divhigh, idx); 1383 } else { 1384 bestChild = node->child2; 1385 otherChild = node->child1; 1386 cut_dist = distance.accum_dist(val, node->node_type.sub.divlow, idx); 1387 } 1388 1389 /* Call recursively to search next level down. */ 1390 if (!searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError)) { 1391 // the resultset doesn't want to receive any more points, we're done 1392 // searching! 1393 return false; 1394 } 1395 1396 DistanceType dst = dists[idx]; 1397 mindistsq = mindistsq + cut_dist - dst; 1398 dists[idx] = cut_dist; 1399 if (mindistsq * epsError <= result_set.worstDist()) { 1400 if (!searchLevel(result_set, vec, otherChild, mindistsq, dists, 1401 epsError)) { 1402 // the resultset doesn't want to receive any more points, we're done 1403 // searching! 1404 return false; 1405 } 1406 } 1407 dists[idx] = dst; 1408 return true; 1409 } 1410 1411 public: 1412 /** Stores the index in a binary file. 1413 * IMPORTANT NOTE: The set of data points is NOT stored in the file, so when 1414 * loading the index object it must be constructed associated to the same 1415 * source of data points used while building it. See the example: 1416 * examples/saveload_example.cpp \sa loadIndex */ saveIndex(FILE * stream)1417 void saveIndex(FILE *stream) { this->saveIndex_(*this, stream); } 1418 1419 /** Loads a previous index from a binary file. 1420 * IMPORTANT NOTE: The set of data points is NOT stored in the file, so the 1421 * index object must be constructed associated to the same source of data 1422 * points used while building the index. See the example: 1423 * examples/saveload_example.cpp \sa loadIndex */ loadIndex(FILE * stream)1424 void loadIndex(FILE *stream) { this->loadIndex_(*this, stream); } 1425 1426 }; // class KDTree 1427 1428 /** kd-tree dynamic index 1429 * 1430 * Contains the k-d trees and other information for indexing a set of points 1431 * for nearest-neighbor matching. 1432 * 1433 * The class "DatasetAdaptor" must provide the following interface (can be 1434 * non-virtual, inlined methods): 1435 * 1436 * \code 1437 * // Must return the number of data poins 1438 * inline size_t kdtree_get_point_count() const { ... } 1439 * 1440 * // Must return the dim'th component of the idx'th point in the class: 1441 * inline T kdtree_get_pt(const size_t idx, const size_t dim) const { ... } 1442 * 1443 * // Optional bounding-box computation: return false to default to a standard 1444 * bbox computation loop. 1445 * // Return true if the BBOX was already computed by the class and returned 1446 * in "bb" so it can be avoided to redo it again. 1447 * // Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 1448 * for point clouds) template <class BBOX> bool kdtree_get_bbox(BBOX &bb) const 1449 * { 1450 * bb[0].low = ...; bb[0].high = ...; // 0th dimension limits 1451 * bb[1].low = ...; bb[1].high = ...; // 1st dimension limits 1452 * ... 1453 * return true; 1454 * } 1455 * 1456 * \endcode 1457 * 1458 * \tparam DatasetAdaptor The user-provided adaptor (see comments above). 1459 * \tparam Distance The distance metric to use: nanoflann::metric_L1, 1460 * nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc. \tparam DIM 1461 * Dimensionality of data points (e.g. 3 for 3D points) \tparam IndexType Will 1462 * be typically size_t or int 1463 */ 1464 template <typename Distance, class DatasetAdaptor, int DIM = -1, 1465 typename IndexType = size_t> 1466 class KDTreeSingleIndexDynamicAdaptor_ 1467 : public KDTreeBaseClass<KDTreeSingleIndexDynamicAdaptor_< 1468 Distance, DatasetAdaptor, DIM, IndexType>, 1469 Distance, DatasetAdaptor, DIM, IndexType> { 1470 public: 1471 /** 1472 * The dataset used by this index 1473 */ 1474 const DatasetAdaptor &dataset; //!< The source of our data 1475 1476 KDTreeSingleIndexAdaptorParams index_params; 1477 1478 std::vector<int> &treeIndex; 1479 1480 Distance distance; 1481 1482 typedef typename nanoflann::KDTreeBaseClass< 1483 nanoflann::KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM, 1484 IndexType>, 1485 Distance, DatasetAdaptor, DIM, IndexType> 1486 BaseClassRef; 1487 1488 typedef typename BaseClassRef::ElementType ElementType; 1489 typedef typename BaseClassRef::DistanceType DistanceType; 1490 1491 typedef typename BaseClassRef::Node Node; 1492 typedef Node *NodePtr; 1493 1494 typedef typename BaseClassRef::Interval Interval; 1495 /** Define "BoundingBox" as a fixed-size or variable-size container depending 1496 * on "DIM" */ 1497 typedef typename BaseClassRef::BoundingBox BoundingBox; 1498 1499 /** Define "distance_vector_t" as a fixed-size or variable-size container 1500 * depending on "DIM" */ 1501 typedef typename BaseClassRef::distance_vector_t distance_vector_t; 1502 1503 /** 1504 * KDTree constructor 1505 * 1506 * Refer to docs in README.md or online in 1507 * https://github.com/jlblancoc/nanoflann 1508 * 1509 * The KD-Tree point dimension (the length of each point in the datase, e.g. 3 1510 * for 3D points) is determined by means of: 1511 * - The \a DIM template parameter if >0 (highest priority) 1512 * - Otherwise, the \a dimensionality parameter of this constructor. 1513 * 1514 * @param inputData Dataset with the input features 1515 * @param params Basically, the maximum leaf node size 1516 */ KDTreeSingleIndexDynamicAdaptor_(const int dimensionality,const DatasetAdaptor & inputData,std::vector<int> & treeIndex_,const KDTreeSingleIndexAdaptorParams & params=KDTreeSingleIndexAdaptorParams ())1517 KDTreeSingleIndexDynamicAdaptor_( 1518 const int dimensionality, const DatasetAdaptor &inputData, 1519 std::vector<int> &treeIndex_, 1520 const KDTreeSingleIndexAdaptorParams ¶ms = 1521 KDTreeSingleIndexAdaptorParams()) 1522 : dataset(inputData), index_params(params), treeIndex(treeIndex_), 1523 distance(inputData) { 1524 BaseClassRef::root_node = NULL; 1525 BaseClassRef::m_size = 0; 1526 BaseClassRef::m_size_at_index_build = 0; 1527 BaseClassRef::dim = dimensionality; 1528 if (DIM > 0) 1529 BaseClassRef::dim = DIM; 1530 BaseClassRef::m_leaf_max_size = params.leaf_max_size; 1531 } 1532 1533 /** Assignment operator definiton */ 1534 KDTreeSingleIndexDynamicAdaptor_ operator =(const KDTreeSingleIndexDynamicAdaptor_ & rhs)1535 operator=(const KDTreeSingleIndexDynamicAdaptor_ &rhs) { 1536 KDTreeSingleIndexDynamicAdaptor_ tmp(rhs); 1537 std::swap(BaseClassRef::vind, tmp.BaseClassRef::vind); 1538 std::swap(BaseClassRef::m_leaf_max_size, tmp.BaseClassRef::m_leaf_max_size); 1539 std::swap(index_params, tmp.index_params); 1540 std::swap(treeIndex, tmp.treeIndex); 1541 std::swap(BaseClassRef::m_size, tmp.BaseClassRef::m_size); 1542 std::swap(BaseClassRef::m_size_at_index_build, 1543 tmp.BaseClassRef::m_size_at_index_build); 1544 std::swap(BaseClassRef::root_node, tmp.BaseClassRef::root_node); 1545 std::swap(BaseClassRef::root_bbox, tmp.BaseClassRef::root_bbox); 1546 std::swap(BaseClassRef::pool, tmp.BaseClassRef::pool); 1547 return *this; 1548 } 1549 1550 /** 1551 * Builds the index 1552 */ buildIndex()1553 void buildIndex() { 1554 BaseClassRef::m_size = BaseClassRef::vind.size(); 1555 this->freeIndex(*this); 1556 BaseClassRef::m_size_at_index_build = BaseClassRef::m_size; 1557 if (BaseClassRef::m_size == 0) 1558 return; 1559 computeBoundingBox(BaseClassRef::root_bbox); 1560 BaseClassRef::root_node = 1561 this->divideTree(*this, 0, BaseClassRef::m_size, 1562 BaseClassRef::root_bbox); // construct the tree 1563 } 1564 1565 /** \name Query methods 1566 * @{ */ 1567 1568 /** 1569 * Find set of nearest neighbors to vec[0:dim-1]. Their indices are stored 1570 * inside the result object. 1571 * 1572 * Params: 1573 * result = the result object in which the indices of the 1574 * nearest-neighbors are stored vec = the vector for which to search the 1575 * nearest neighbors 1576 * 1577 * \tparam RESULTSET Should be any ResultSet<DistanceType> 1578 * \return True if the requested neighbors could be found. 1579 * \sa knnSearch, radiusSearch 1580 */ 1581 template <typename RESULTSET> findNeighbors(RESULTSET & result,const ElementType * vec,const SearchParams & searchParams) const1582 bool findNeighbors(RESULTSET &result, const ElementType *vec, 1583 const SearchParams &searchParams) const { 1584 assert(vec); 1585 if (this->size(*this) == 0) 1586 return false; 1587 if (!BaseClassRef::root_node) 1588 return false; 1589 float epsError = 1 + searchParams.eps; 1590 1591 // fixed or variable-sized container (depending on DIM) 1592 distance_vector_t dists; 1593 // Fill it with zeros. 1594 assign(dists, (DIM > 0 ? DIM : BaseClassRef::dim), 1595 static_cast<typename distance_vector_t::value_type>(0)); 1596 DistanceType distsq = this->computeInitialDistances(*this, vec, dists); 1597 searchLevel(result, vec, BaseClassRef::root_node, distsq, dists, 1598 epsError); // "count_leaf" parameter removed since was neither 1599 // used nor returned to the user. 1600 return result.full(); 1601 } 1602 1603 /** 1604 * Find the "num_closest" nearest neighbors to the \a query_point[0:dim-1]. 1605 * Their indices are stored inside the result object. \sa radiusSearch, 1606 * findNeighbors \note nChecks_IGNORED is ignored but kept for compatibility 1607 * with the original FLANN interface. \return Number `N` of valid points in 1608 * the result set. Only the first `N` entries in `out_indices` and 1609 * `out_distances_sq` will be valid. Return may be less than `num_closest` 1610 * only if the number of elements in the tree is less than `num_closest`. 1611 */ knnSearch(const ElementType * query_point,const size_t num_closest,IndexType * out_indices,DistanceType * out_distances_sq,const int=10) const1612 size_t knnSearch(const ElementType *query_point, const size_t num_closest, 1613 IndexType *out_indices, DistanceType *out_distances_sq, 1614 const int /* nChecks_IGNORED */ = 10) const { 1615 nanoflann::KNNResultSet<DistanceType, IndexType> resultSet(num_closest); 1616 resultSet.init(out_indices, out_distances_sq); 1617 this->findNeighbors(resultSet, query_point, nanoflann::SearchParams()); 1618 return resultSet.size(); 1619 } 1620 1621 /** 1622 * Find all the neighbors to \a query_point[0:dim-1] within a maximum radius. 1623 * The output is given as a vector of pairs, of which the first element is a 1624 * point index and the second the corresponding distance. Previous contents of 1625 * \a IndicesDists are cleared. 1626 * 1627 * If searchParams.sorted==true, the output list is sorted by ascending 1628 * distances. 1629 * 1630 * For a better performance, it is advisable to do a .reserve() on the vector 1631 * if you have any wild guess about the number of expected matches. 1632 * 1633 * \sa knnSearch, findNeighbors, radiusSearchCustomCallback 1634 * \return The number of points within the given radius (i.e. indices.size() 1635 * or dists.size() ) 1636 */ 1637 size_t radiusSearch(const ElementType * query_point,const DistanceType & radius,std::vector<std::pair<IndexType,DistanceType>> & IndicesDists,const SearchParams & searchParams) const1638 radiusSearch(const ElementType *query_point, const DistanceType &radius, 1639 std::vector<std::pair<IndexType, DistanceType>> &IndicesDists, 1640 const SearchParams &searchParams) const { 1641 RadiusResultSet<DistanceType, IndexType> resultSet(radius, IndicesDists); 1642 const size_t nFound = 1643 radiusSearchCustomCallback(query_point, resultSet, searchParams); 1644 if (searchParams.sorted) 1645 std::sort(IndicesDists.begin(), IndicesDists.end(), IndexDist_Sorter()); 1646 return nFound; 1647 } 1648 1649 /** 1650 * Just like radiusSearch() but with a custom callback class for each point 1651 * found in the radius of the query. See the source of RadiusResultSet<> as a 1652 * start point for your own classes. \sa radiusSearch 1653 */ 1654 template <class SEARCH_CALLBACK> radiusSearchCustomCallback(const ElementType * query_point,SEARCH_CALLBACK & resultSet,const SearchParams & searchParams=SearchParams ()) const1655 size_t radiusSearchCustomCallback( 1656 const ElementType *query_point, SEARCH_CALLBACK &resultSet, 1657 const SearchParams &searchParams = SearchParams()) const { 1658 this->findNeighbors(resultSet, query_point, searchParams); 1659 return resultSet.size(); 1660 } 1661 1662 /** @} */ 1663 1664 public: computeBoundingBox(BoundingBox & bbox)1665 void computeBoundingBox(BoundingBox &bbox) { 1666 resize(bbox, (DIM > 0 ? DIM : BaseClassRef::dim)); 1667 1668 if (dataset.kdtree_get_bbox(bbox)) { 1669 // Done! It was implemented in derived class 1670 } else { 1671 const size_t N = BaseClassRef::m_size; 1672 if (!N) 1673 throw std::runtime_error("[nanoflann] computeBoundingBox() called but " 1674 "no data points found."); 1675 for (int i = 0; i < (DIM > 0 ? DIM : BaseClassRef::dim); ++i) { 1676 bbox[i].low = bbox[i].high = 1677 this->dataset_get(*this, BaseClassRef::vind[0], i); 1678 } 1679 for (size_t k = 1; k < N; ++k) { 1680 for (int i = 0; i < (DIM > 0 ? DIM : BaseClassRef::dim); ++i) { 1681 if (this->dataset_get(*this, BaseClassRef::vind[k], i) < bbox[i].low) 1682 bbox[i].low = this->dataset_get(*this, BaseClassRef::vind[k], i); 1683 if (this->dataset_get(*this, BaseClassRef::vind[k], i) > bbox[i].high) 1684 bbox[i].high = this->dataset_get(*this, BaseClassRef::vind[k], i); 1685 } 1686 } 1687 } 1688 } 1689 1690 /** 1691 * Performs an exact search in the tree starting from a node. 1692 * \tparam RESULTSET Should be any ResultSet<DistanceType> 1693 */ 1694 template <class RESULTSET> searchLevel(RESULTSET & result_set,const ElementType * vec,const NodePtr node,DistanceType mindistsq,distance_vector_t & dists,const float epsError) const1695 void searchLevel(RESULTSET &result_set, const ElementType *vec, 1696 const NodePtr node, DistanceType mindistsq, 1697 distance_vector_t &dists, const float epsError) const { 1698 /* If this is a leaf node, then do check and return. */ 1699 if ((node->child1 == NULL) && (node->child2 == NULL)) { 1700 // count_leaf += (node->lr.right-node->lr.left); // Removed since was 1701 // neither used nor returned to the user. 1702 DistanceType worst_dist = result_set.worstDist(); 1703 for (IndexType i = node->node_type.lr.left; i < node->node_type.lr.right; 1704 ++i) { 1705 const IndexType index = BaseClassRef::vind[i]; // reorder... : i; 1706 if (treeIndex[index] == -1) 1707 continue; 1708 DistanceType dist = distance.evalMetric( 1709 vec, index, (DIM > 0 ? DIM : BaseClassRef::dim)); 1710 if (dist < worst_dist) { 1711 if (!result_set.addPoint( 1712 static_cast<typename RESULTSET::DistanceType>(dist), 1713 static_cast<typename RESULTSET::IndexType>( 1714 BaseClassRef::vind[i]))) { 1715 // the resultset doesn't want to receive any more points, we're done 1716 // searching! 1717 return; // false; 1718 } 1719 } 1720 } 1721 return; 1722 } 1723 1724 /* Which child branch should be taken first? */ 1725 int idx = node->node_type.sub.divfeat; 1726 ElementType val = vec[idx]; 1727 DistanceType diff1 = val - node->node_type.sub.divlow; 1728 DistanceType diff2 = val - node->node_type.sub.divhigh; 1729 1730 NodePtr bestChild; 1731 NodePtr otherChild; 1732 DistanceType cut_dist; 1733 if ((diff1 + diff2) < 0) { 1734 bestChild = node->child1; 1735 otherChild = node->child2; 1736 cut_dist = distance.accum_dist(val, node->node_type.sub.divhigh, idx); 1737 } else { 1738 bestChild = node->child2; 1739 otherChild = node->child1; 1740 cut_dist = distance.accum_dist(val, node->node_type.sub.divlow, idx); 1741 } 1742 1743 /* Call recursively to search next level down. */ 1744 searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError); 1745 1746 DistanceType dst = dists[idx]; 1747 mindistsq = mindistsq + cut_dist - dst; 1748 dists[idx] = cut_dist; 1749 if (mindistsq * epsError <= result_set.worstDist()) { 1750 searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError); 1751 } 1752 dists[idx] = dst; 1753 } 1754 1755 public: 1756 /** Stores the index in a binary file. 1757 * IMPORTANT NOTE: The set of data points is NOT stored in the file, so when 1758 * loading the index object it must be constructed associated to the same 1759 * source of data points used while building it. See the example: 1760 * examples/saveload_example.cpp \sa loadIndex */ saveIndex(FILE * stream)1761 void saveIndex(FILE *stream) { this->saveIndex_(*this, stream); } 1762 1763 /** Loads a previous index from a binary file. 1764 * IMPORTANT NOTE: The set of data points is NOT stored in the file, so the 1765 * index object must be constructed associated to the same source of data 1766 * points used while building the index. See the example: 1767 * examples/saveload_example.cpp \sa loadIndex */ loadIndex(FILE * stream)1768 void loadIndex(FILE *stream) { this->loadIndex_(*this, stream); } 1769 }; 1770 1771 /** kd-tree dynaimic index 1772 * 1773 * class to create multiple static index and merge their results to behave as 1774 * single dynamic index as proposed in Logarithmic Approach. 1775 * 1776 * Example of usage: 1777 * examples/dynamic_pointcloud_example.cpp 1778 * 1779 * \tparam DatasetAdaptor The user-provided adaptor (see comments above). 1780 * \tparam Distance The distance metric to use: nanoflann::metric_L1, 1781 * nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc. \tparam DIM 1782 * Dimensionality of data points (e.g. 3 for 3D points) \tparam IndexType Will 1783 * be typically size_t or int 1784 */ 1785 template <typename Distance, class DatasetAdaptor, int DIM = -1, 1786 typename IndexType = size_t> 1787 class KDTreeSingleIndexDynamicAdaptor { 1788 public: 1789 typedef typename Distance::ElementType ElementType; 1790 typedef typename Distance::DistanceType DistanceType; 1791 1792 protected: 1793 size_t m_leaf_max_size; 1794 size_t treeCount; 1795 size_t pointCount; 1796 1797 /** 1798 * The dataset used by this index 1799 */ 1800 const DatasetAdaptor &dataset; //!< The source of our data 1801 1802 std::vector<int> treeIndex; //!< treeIndex[idx] is the index of tree in which 1803 //!< point at idx is stored. treeIndex[idx]=-1 1804 //!< means that point has been removed. 1805 1806 KDTreeSingleIndexAdaptorParams index_params; 1807 1808 int dim; //!< Dimensionality of each data point 1809 1810 typedef KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM> 1811 index_container_t; 1812 std::vector<index_container_t> index; 1813 1814 public: 1815 /** Get a const ref to the internal list of indices; the number of indices is 1816 * adapted dynamically as the dataset grows in size. */ getAllIndices() const1817 const std::vector<index_container_t> &getAllIndices() const { return index; } 1818 1819 private: 1820 /** finds position of least significant unset bit */ First0Bit(IndexType num)1821 int First0Bit(IndexType num) { 1822 int pos = 0; 1823 while (num & 1) { 1824 num = num >> 1; 1825 pos++; 1826 } 1827 return pos; 1828 } 1829 1830 /** Creates multiple empty trees to handle dynamic support */ init()1831 void init() { 1832 typedef KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM> 1833 my_kd_tree_t; 1834 std::vector<my_kd_tree_t> index_( 1835 treeCount, my_kd_tree_t(dim /*dim*/, dataset, treeIndex, index_params)); 1836 index = index_; 1837 } 1838 1839 public: 1840 Distance distance; 1841 1842 /** 1843 * KDTree constructor 1844 * 1845 * Refer to docs in README.md or online in 1846 * https://github.com/jlblancoc/nanoflann 1847 * 1848 * The KD-Tree point dimension (the length of each point in the datase, e.g. 3 1849 * for 3D points) is determined by means of: 1850 * - The \a DIM template parameter if >0 (highest priority) 1851 * - Otherwise, the \a dimensionality parameter of this constructor. 1852 * 1853 * @param inputData Dataset with the input features 1854 * @param params Basically, the maximum leaf node size 1855 */ KDTreeSingleIndexDynamicAdaptor(const int dimensionality,const DatasetAdaptor & inputData,const KDTreeSingleIndexAdaptorParams & params=KDTreeSingleIndexAdaptorParams (),const size_t maximumPointCount=1000000000U)1856 KDTreeSingleIndexDynamicAdaptor(const int dimensionality, 1857 const DatasetAdaptor &inputData, 1858 const KDTreeSingleIndexAdaptorParams ¶ms = 1859 KDTreeSingleIndexAdaptorParams(), 1860 const size_t maximumPointCount = 1000000000U) 1861 : dataset(inputData), index_params(params), distance(inputData) { 1862 treeCount = static_cast<size_t>(std::log2(maximumPointCount)); 1863 pointCount = 0U; 1864 dim = dimensionality; 1865 treeIndex.clear(); 1866 if (DIM > 0) 1867 dim = DIM; 1868 m_leaf_max_size = params.leaf_max_size; 1869 init(); 1870 const size_t num_initial_points = dataset.kdtree_get_point_count(); 1871 if (num_initial_points > 0) { 1872 addPoints(0, num_initial_points - 1); 1873 } 1874 } 1875 1876 /** Deleted copy constructor*/ 1877 KDTreeSingleIndexDynamicAdaptor( 1878 const KDTreeSingleIndexDynamicAdaptor<Distance, DatasetAdaptor, DIM, 1879 IndexType> &) = delete; 1880 1881 /** Add points to the set, Inserts all points from [start, end] */ addPoints(IndexType start,IndexType end)1882 void addPoints(IndexType start, IndexType end) { 1883 size_t count = end - start + 1; 1884 treeIndex.resize(treeIndex.size() + count); 1885 for (IndexType idx = start; idx <= end; idx++) { 1886 int pos = First0Bit(pointCount); 1887 index[pos].vind.clear(); 1888 treeIndex[pointCount] = pos; 1889 for (int i = 0; i < pos; i++) { 1890 for (int j = 0; j < static_cast<int>(index[i].vind.size()); j++) { 1891 index[pos].vind.push_back(index[i].vind[j]); 1892 if (treeIndex[index[i].vind[j]] != -1) 1893 treeIndex[index[i].vind[j]] = pos; 1894 } 1895 index[i].vind.clear(); 1896 index[i].freeIndex(index[i]); 1897 } 1898 index[pos].vind.push_back(idx); 1899 index[pos].buildIndex(); 1900 pointCount++; 1901 } 1902 } 1903 1904 /** Remove a point from the set (Lazy Deletion) */ removePoint(size_t idx)1905 void removePoint(size_t idx) { 1906 if (idx >= pointCount) 1907 return; 1908 treeIndex[idx] = -1; 1909 } 1910 1911 /** 1912 * Find set of nearest neighbors to vec[0:dim-1]. Their indices are stored 1913 * inside the result object. 1914 * 1915 * Params: 1916 * result = the result object in which the indices of the 1917 * nearest-neighbors are stored vec = the vector for which to search the 1918 * nearest neighbors 1919 * 1920 * \tparam RESULTSET Should be any ResultSet<DistanceType> 1921 * \return True if the requested neighbors could be found. 1922 * \sa knnSearch, radiusSearch 1923 */ 1924 template <typename RESULTSET> findNeighbors(RESULTSET & result,const ElementType * vec,const SearchParams & searchParams) const1925 bool findNeighbors(RESULTSET &result, const ElementType *vec, 1926 const SearchParams &searchParams) const { 1927 for (size_t i = 0; i < treeCount; i++) { 1928 index[i].findNeighbors(result, &vec[0], searchParams); 1929 } 1930 return result.full(); 1931 } 1932 }; 1933 1934 /** An L2-metric KD-tree adaptor for working with data directly stored in an 1935 * Eigen Matrix, without duplicating the data storage. Each row in the matrix 1936 * represents a point in the state space. 1937 * 1938 * Example of usage: 1939 * \code 1940 * Eigen::Matrix<num_t,Dynamic,Dynamic> mat; 1941 * // Fill out "mat"... 1942 * 1943 * typedef KDTreeEigenMatrixAdaptor< Eigen::Matrix<num_t,Dynamic,Dynamic> > 1944 * my_kd_tree_t; const int max_leaf = 10; my_kd_tree_t mat_index(mat, max_leaf 1945 * ); mat_index.index->buildIndex(); mat_index.index->... \endcode 1946 * 1947 * \tparam DIM If set to >0, it specifies a compile-time fixed dimensionality 1948 * for the points in the data set, allowing more compiler optimizations. \tparam 1949 * Distance The distance metric to use: nanoflann::metric_L1, 1950 * nanoflann::metric_L2, nanoflann::metric_L2_Simple, etc. 1951 */ 1952 template <class MatrixType, int DIM = -1, class Distance = nanoflann::metric_L2> 1953 struct KDTreeEigenMatrixAdaptor { 1954 typedef KDTreeEigenMatrixAdaptor<MatrixType, DIM, Distance> self_t; 1955 typedef typename MatrixType::Scalar num_t; 1956 typedef typename MatrixType::Index IndexType; 1957 typedef 1958 typename Distance::template traits<num_t, self_t>::distance_t metric_t; 1959 typedef KDTreeSingleIndexAdaptor<metric_t, self_t, 1960 MatrixType::ColsAtCompileTime, IndexType> 1961 index_t; 1962 1963 index_t *index; //! The kd-tree index for the user to call its methods as 1964 //! usual with any other FLANN index. 1965 1966 /// Constructor: takes a const ref to the matrix object with the data points KDTreeEigenMatrixAdaptornanoflann::KDTreeEigenMatrixAdaptor1967 KDTreeEigenMatrixAdaptor(const size_t dimensionality, 1968 const std::reference_wrapper<const MatrixType> &mat, 1969 const int leaf_max_size = 10) 1970 : m_data_matrix(mat) { 1971 const auto dims = mat.get().cols(); 1972 if (size_t(dims) != dimensionality) 1973 throw std::runtime_error( 1974 "Error: 'dimensionality' must match column count in data matrix"); 1975 if (DIM > 0 && int(dims) != DIM) 1976 throw std::runtime_error( 1977 "Data set dimensionality does not match the 'DIM' template argument"); 1978 index = 1979 new index_t(static_cast<int>(dims), *this /* adaptor */, 1980 nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size)); 1981 index->buildIndex(); 1982 } 1983 1984 public: 1985 /** Deleted copy constructor */ 1986 KDTreeEigenMatrixAdaptor(const self_t &) = delete; 1987 ~KDTreeEigenMatrixAdaptornanoflann::KDTreeEigenMatrixAdaptor1988 ~KDTreeEigenMatrixAdaptor() { delete index; } 1989 1990 const std::reference_wrapper<const MatrixType> m_data_matrix; 1991 1992 /** Query for the \a num_closest closest points to a given point (entered as 1993 * query_point[0:dim-1]). Note that this is a short-cut method for 1994 * index->findNeighbors(). The user can also call index->... methods as 1995 * desired. \note nChecks_IGNORED is ignored but kept for compatibility with 1996 * the original FLANN interface. 1997 */ querynanoflann::KDTreeEigenMatrixAdaptor1998 inline void query(const num_t *query_point, const size_t num_closest, 1999 IndexType *out_indices, num_t *out_distances_sq, 2000 const int /* nChecks_IGNORED */ = 10) const { 2001 nanoflann::KNNResultSet<num_t, IndexType> resultSet(num_closest); 2002 resultSet.init(out_indices, out_distances_sq); 2003 index->findNeighbors(resultSet, query_point, nanoflann::SearchParams()); 2004 } 2005 2006 /** @name Interface expected by KDTreeSingleIndexAdaptor 2007 * @{ */ 2008 derivednanoflann::KDTreeEigenMatrixAdaptor2009 const self_t &derived() const { return *this; } derivednanoflann::KDTreeEigenMatrixAdaptor2010 self_t &derived() { return *this; } 2011 2012 // Must return the number of data points kdtree_get_point_countnanoflann::KDTreeEigenMatrixAdaptor2013 inline size_t kdtree_get_point_count() const { 2014 return m_data_matrix.get().rows(); 2015 } 2016 2017 // Returns the dim'th component of the idx'th point in the class: kdtree_get_ptnanoflann::KDTreeEigenMatrixAdaptor2018 inline num_t kdtree_get_pt(const IndexType idx, size_t dim) const { 2019 return m_data_matrix.get().coeff(idx, IndexType(dim)); 2020 } 2021 2022 // Optional bounding-box computation: return false to default to a standard 2023 // bbox computation loop. 2024 // Return true if the BBOX was already computed by the class and returned in 2025 // "bb" so it can be avoided to redo it again. Look at bb.size() to find out 2026 // the expected dimensionality (e.g. 2 or 3 for point clouds) kdtree_get_bboxnanoflann::KDTreeEigenMatrixAdaptor2027 template <class BBOX> bool kdtree_get_bbox(BBOX & /*bb*/) const { 2028 return false; 2029 } 2030 2031 /** @} */ 2032 2033 }; // end of KDTreeEigenMatrixAdaptor 2034 /** @} */ 2035 2036 /** @} */ // end of grouping 2037 } // namespace nanoflann 2038 2039 #endif /* NANOFLANN_HPP_ */ 2040