46 #ifndef NANOFLANN_HPP_
47 #define NANOFLANN_HPP_
54 #define _USE_MATH_DEFINES // Required by MSVC to define M_PI,etc. in <cmath>
60 #if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
74 #define NANOFLANN_VERSION 0x123
78 template <
typename DistanceType,
typename IndexType =
size_t,
typename CountType =
size_t>
87 inline KNNResultSet(CountType capacity_) : indices(0), dists(0), capacity(capacity_), count(0)
91 inline void init(IndexType* indices_, DistanceType* dists_)
97 dists[capacity-1] = (std::numeric_limits<DistanceType>::max)();
100 inline CountType size()
const
105 inline bool full()
const
107 return count == capacity;
115 inline bool addPoint(DistanceType dist, IndexType index)
118 for (i=count; i>0; --i) {
119 #ifdef NANOFLANN_FIRST_MATCH // If defined and two points have the same distance, the one with the lowest-index will be returned first.
120 if ( (dists[i-1]>dist) || ((dist==dists[i-1])&&(indices[i-1]>index)) ) {
122 if (dists[i-1]>dist) {
125 dists[i] = dists[i-1];
126 indices[i] = indices[i-1];
135 if (count<capacity) count++;
141 inline DistanceType worstDist()
const
143 return dists[capacity-1];
151 template <
typename PairType>
152 inline bool operator()(
const PairType &p1,
const PairType &p2)
const {
153 return p1.second < p2.second;
160 template <
typename DistanceType,
typename IndexType =
size_t>
164 const DistanceType radius;
166 std::vector<std::pair<IndexType,DistanceType> >& m_indices_dists;
168 inline RadiusResultSet(DistanceType radius_, std::vector<std::pair<IndexType,DistanceType> >& indices_dists) : radius(radius_), m_indices_dists(indices_dists)
175 inline void init() { clear(); }
176 inline void clear() { m_indices_dists.clear(); }
178 inline size_t size()
const {
return m_indices_dists.size(); }
180 inline bool full()
const {
return true; }
186 inline bool addPoint(DistanceType dist, IndexType index)
189 m_indices_dists.push_back(std::make_pair(index,dist));
193 inline DistanceType worstDist()
const {
return radius; }
201 if (m_indices_dists.empty())
throw std::runtime_error(
"Cannot invoke RadiusResultSet::worst_item() on an empty list of results.");
202 typedef typename std::vector<std::pair<IndexType,DistanceType> >::const_iterator DistIt;
203 DistIt it = std::max_element(m_indices_dists.begin(), m_indices_dists.end(),
IndexDist_Sorter());
215 void save_value(FILE* stream,
const T& value,
size_t count = 1)
217 fwrite(&value,
sizeof(value),count, stream);
221 void save_value(FILE* stream,
const std::vector<T>& value)
223 size_t size = value.size();
224 fwrite(&size,
sizeof(
size_t), 1, stream);
225 fwrite(&value[0],
sizeof(T), size, stream);
229 void load_value(FILE* stream, T& value,
size_t count = 1)
231 size_t read_cnt = fread(&value,
sizeof(value), count, stream);
232 if (read_cnt != count) {
233 throw std::runtime_error(
"Cannot read from file");
239 void load_value(FILE* stream, std::vector<T>& value)
242 size_t read_cnt = fread(&size,
sizeof(
size_t), 1, stream);
244 throw std::runtime_error(
"Cannot read from file");
247 read_cnt = fread(&value[0],
sizeof(T), size, stream);
248 if (read_cnt!=size) {
249 throw std::runtime_error(
"Cannot read from file");
267 template<
class T,
class DataSource,
typename _DistanceType = T>
270 typedef T ElementType;
271 typedef _DistanceType DistanceType;
273 const DataSource &data_source;
275 L1_Adaptor(
const DataSource &_data_source) : data_source(_data_source) { }
277 inline DistanceType evalMetric(
const T* a,
const size_t b_idx,
size_t size, DistanceType worst_dist = -1)
const
279 DistanceType result = DistanceType();
280 const T* last = a + size;
281 const T* lastgroup = last - 3;
285 while (a < lastgroup) {
286 const DistanceType diff0 = std::abs(a[0] - data_source.kdtree_get_pt(b_idx,d++));
287 const DistanceType diff1 = std::abs(a[1] - data_source.kdtree_get_pt(b_idx,d++));
288 const DistanceType diff2 = std::abs(a[2] - data_source.kdtree_get_pt(b_idx,d++));
289 const DistanceType diff3 = std::abs(a[3] - data_source.kdtree_get_pt(b_idx,d++));
290 result += diff0 + diff1 + diff2 + diff3;
292 if ((worst_dist>0)&&(result>worst_dist)) {
298 result += std::abs( *a++ - data_source.kdtree_get_pt(b_idx,d++) );
303 template <
typename U,
typename V>
304 inline DistanceType accum_dist(
const U a,
const V b,
int )
const
306 return std::abs(a-b);
315 template<
class T,
class DataSource,
typename _DistanceType = T>
318 typedef T ElementType;
319 typedef _DistanceType DistanceType;
321 const DataSource &data_source;
323 L2_Adaptor(
const DataSource &_data_source) : data_source(_data_source) { }
325 inline DistanceType evalMetric(
const T* a,
const size_t b_idx,
size_t size, DistanceType worst_dist = -1)
const
327 DistanceType result = DistanceType();
328 const T* last = a + size;
329 const T* lastgroup = last - 3;
333 while (a < lastgroup) {
334 const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx,d++);
335 const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx,d++);
336 const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx,d++);
337 const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx,d++);
338 result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
340 if ((worst_dist>0)&&(result>worst_dist)) {
346 const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx,d++);
347 result += diff0 * diff0;
352 template <
typename U,
typename V>
353 inline DistanceType accum_dist(
const U a,
const V b,
int )
const
364 template<
class T,
class DataSource,
typename _DistanceType = T>
367 typedef T ElementType;
368 typedef _DistanceType DistanceType;
370 const DataSource &data_source;
372 L2_Simple_Adaptor(
const DataSource &_data_source) : data_source(_data_source) { }
374 inline DistanceType evalMetric(
const T* a,
const size_t b_idx,
size_t size)
const {
375 DistanceType result = DistanceType();
376 for (
int i=0; i<size; ++i) {
377 const DistanceType diff = a[i] - data_source.kdtree_get_pt(b_idx, i);
378 result += diff * diff;
383 template <
typename U,
typename V>
384 inline DistanceType accum_dist(
const U a,
const V b,
int )
const
396 template<
class T,
class DataSource,
typename _DistanceType = T>
399 typedef T ElementType;
400 typedef _DistanceType DistanceType;
402 const DataSource &data_source;
404 SO2_Adaptor(
const DataSource &_data_source) : data_source(_data_source) { }
406 inline DistanceType evalMetric(
const T* a,
const size_t b_idx,
size_t size)
const {
407 DistanceType result = DistanceType();
408 result = data_source.kdtree_get_pt(b_idx, 0) - a[0];
411 else if (result < -M_PI)
416 template <
typename U,
typename V>
417 inline DistanceType accum_dist(
const U a,
const V b,
int )
const
419 DistanceType result = DistanceType();
423 else if (result < -M_PI)
434 template<
class T,
class DataSource,
typename _DistanceType = T>
437 typedef T ElementType;
438 typedef _DistanceType DistanceType;
440 const DataSource &data_source;
444 inline DistanceType evalMetric(
const T* a,
const size_t b_idx,
size_t size)
const {
445 DistanceType result = DistanceType();
446 for (
int i=0; i<size; ++i) {
447 const DistanceType diff = a[i] * data_source.kdtree_get_pt(b_idx, i);
450 result = 1 - std::abs(result);
454 template <
typename U,
typename V>
455 inline DistanceType accum_dist(
const U a,
const V b,
int )
const
466 template<
class T,
class DataSource,
typename _DistanceType = T>
469 typedef T ElementType;
470 typedef _DistanceType DistanceType;
472 const DataSource &data_source;
476 inline DistanceType evalMetric(
const T* a,
const size_t b_idx,
size_t size)
const {
477 DistanceType result = DistanceType();
478 for (
int i=0; i<size; ++i) {
479 const DistanceType diff = a[i] * data_source.kdtree_get_pt(b_idx, i);
482 result = std::acos(std::abs(result));
486 template <
typename U,
typename V>
487 inline DistanceType accum_dist(
const U a,
const V b,
int )
const
496 template<
class T,
class DataSource>
504 template<
class T,
class DataSource>
512 template<
class T,
class DataSource>
520 template<
class T,
class DataSource>
528 template<
class T,
class DataSource>
536 template<
class T,
class DataSource>
551 leaf_max_size(_leaf_max_size)
554 size_t leaf_max_size;
561 SearchParams(
int checks_IGNORED_ = 32,
float eps_ = 0,
bool sorted_ =
true ) :
562 checks(checks_IGNORED_), eps(eps_), sorted(sorted_) {}
581 template <
typename T>
584 T* mem =
static_cast<T*
>( ::malloc(
sizeof(T)*count));
605 const size_t BLOCKSIZE=8192;
648 while (base != NULL) {
649 void *prev = *(
static_cast<void**
>( base));
671 if (size > remaining) {
673 wastedMemory += remaining;
676 const size_t blocksize = (size +
sizeof(
void*) + (
WORDSIZE-1) > BLOCKSIZE) ?
677 size +
sizeof(
void*) + (
WORDSIZE-1) : BLOCKSIZE;
680 void* m = ::malloc(blocksize);
682 fprintf(stderr,
"Failed to allocate memory.\n");
687 static_cast<void**
>(m)[0] = base;
693 remaining = blocksize -
sizeof(
void*) - shift;
694 loc = (
static_cast<char*
>(m) +
sizeof(
void*) + shift);
697 loc =
static_cast<char*
>(loc) + size;
712 template <
typename T>
715 T* mem =
static_cast<T*
>(this->malloc(
sizeof(T)*count));
751 template <
typename T, std::
size_t N>
758 typedef T value_type;
760 typedef const T* const_iterator;
761 typedef T& reference;
762 typedef const T& const_reference;
763 typedef std::size_t size_type;
764 typedef std::ptrdiff_t difference_type;
767 inline iterator begin() {
return elems; }
768 inline const_iterator begin()
const {
return elems; }
769 inline iterator end() {
return elems+N; }
770 inline const_iterator end()
const {
return elems+N; }
773 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
774 typedef std::reverse_iterator<iterator> reverse_iterator;
775 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
776 #elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
778 typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator,
779 reference, iterator, reference> > reverse_iterator;
780 typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator,
781 const_reference, iterator, reference> > const_reverse_iterator;
784 typedef std::reverse_iterator<iterator,T> reverse_iterator;
785 typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator;
788 reverse_iterator rbegin() {
return reverse_iterator(end()); }
789 const_reverse_iterator rbegin()
const {
return const_reverse_iterator(end()); }
790 reverse_iterator rend() {
return reverse_iterator(begin()); }
791 const_reverse_iterator rend()
const {
return const_reverse_iterator(begin()); }
793 inline reference operator[](size_type i) {
return elems[i]; }
794 inline const_reference operator[](size_type i)
const {
return elems[i]; }
796 reference at(size_type i) { rangecheck(i);
return elems[i]; }
797 const_reference at(size_type i)
const { rangecheck(i);
return elems[i]; }
799 reference front() {
return elems[0]; }
800 const_reference front()
const {
return elems[0]; }
801 reference back() {
return elems[N-1]; }
802 const_reference back()
const {
return elems[N-1]; }
804 static inline size_type size() {
return N; }
805 static bool empty() {
return false; }
806 static size_type max_size() {
return N; }
807 enum { static_size = N };
809 inline void resize(
const size_t nElements) {
if (nElements!=N)
throw std::logic_error(
"Try to change the size of a CArray."); }
811 void swap (
CArray<T,N>& y) { std::swap_ranges(begin(),end(),y.begin()); }
813 const T* data()
const {
return elems; }
815 T* data() {
return elems; }
817 template <
typename T2> CArray<T,N>& operator= (
const CArray<T2,N>& rhs) {
818 std::copy(rhs.begin(),rhs.end(), begin());
822 inline void assign (
const T& value) {
for (
size_t i=0;i<N;i++) elems[i]=value; }
824 void assign (
const size_t n,
const T& value) { assert(N==n);
for (
size_t i=0;i<N;i++) elems[i]=value; }
827 static void rangecheck (size_type i) {
if (i >= size()) {
throw std::out_of_range(
"CArray<>: index out of range"); } }
833 template <
int DIM,
typename T>
839 template <
typename T>
841 typedef std::vector<T> container_t;
857 template<
class Derived,
typename Distance,
class DatasetAdaptor,
int DIM = -1,
typename IndexType =
size_t>
867 obj.m_size_at_index_build = 0;
871 typedef typename Distance::ElementType ElementType;
872 typedef typename Distance::DistanceType DistanceType;
896 ElementType low, high;
906 size_t size(
const Derived &obj)
const {
return obj.m_size; }
910 return static_cast<size_t>(DIM>0 ? DIM : obj.dim);
919 return obj.pool.usedMemory+obj.pool.wastedMemory+obj.dataset.kdtree_get_point_count()*
sizeof(IndexType);
922 void computeMinMax(
const Derived &obj, IndexType* ind, IndexType count,
int element, ElementType& min_elem, ElementType& max_elem)
924 min_elem = obj.dataset_get(ind[0],element);
925 max_elem = obj.dataset_get(ind[0],element);
926 for (IndexType i=1; i<count; ++i) {
927 ElementType val = obj.dataset_get(ind[i],element);
928 if (val<min_elem) min_elem = val;
929 if (val>max_elem) max_elem = val;
942 NodePtr node = obj.pool.allocate<Node>();
945 if ( (right-left) <=
static_cast<IndexType
>(obj.m_leaf_max_size) ) {
946 node->child1 = node->child2 = NULL;
947 node->node_type.lr.left = left;
948 node->node_type.lr.right = right;
951 for (
int i=0; i<(DIM>0 ? DIM : obj.dim); ++i) {
952 bbox[i].low = obj.dataset_get(obj.vind[left],i);
953 bbox[i].high = obj.dataset_get(obj.vind[left],i);
955 for (IndexType k=left+1; k<right; ++k) {
956 for (
int i=0; i<(DIM>0 ? DIM : obj.dim); ++i) {
957 if (bbox[i].low>obj.dataset_get(obj.vind[k],i)) bbox[i].low=obj.dataset_get(obj.vind[k],i);
958 if (bbox[i].high<obj.dataset_get(obj.vind[k],i)) bbox[i].high=obj.dataset_get(obj.vind[k],i);
966 middleSplit_(obj, &obj.vind[0]+left, right-left, idx, cutfeat, cutval, bbox);
968 node->node_type.sub.divfeat = cutfeat;
971 left_bbox[cutfeat].high = cutval;
972 node->child1 = divideTree(obj, left, left+idx, left_bbox);
975 right_bbox[cutfeat].low = cutval;
976 node->child2 = divideTree(obj, left+idx, right, right_bbox);
978 node->node_type.sub.divlow = left_bbox[cutfeat].high;
979 node->node_type.sub.divhigh = right_bbox[cutfeat].low;
981 for (
int i=0; i<(DIM>0 ? DIM : obj.dim); ++i) {
982 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
983 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
990 void middleSplit_(Derived &obj, IndexType* ind, IndexType count, IndexType& index,
int& cutfeat, DistanceType& cutval,
const BoundingBox& bbox)
992 const DistanceType EPS=
static_cast<DistanceType
>(0.00001);
993 ElementType max_span = bbox[0].high-bbox[0].low;
994 for (
int i=1; i<(DIM>0 ? DIM : obj.dim); ++i) {
995 ElementType span = bbox[i].high-bbox[i].low;
1000 ElementType max_spread = -1;
1002 for (
int i=0; i<(DIM>0 ? DIM : obj.dim); ++i) {
1003 ElementType span = bbox[i].high-bbox[i].low;
1004 if (span>(1-EPS)*max_span) {
1005 ElementType min_elem, max_elem;
1006 computeMinMax(obj, ind, count, i, min_elem, max_elem);
1007 ElementType spread = max_elem-min_elem;;
1008 if (spread>max_spread) {
1010 max_spread = spread;
1015 DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2;
1016 ElementType min_elem, max_elem;
1017 computeMinMax(obj, ind, count, cutfeat, min_elem, max_elem);
1019 if (split_val<min_elem) cutval = min_elem;
1020 else if (split_val>max_elem) cutval = max_elem;
1021 else cutval = split_val;
1023 IndexType lim1, lim2;
1024 planeSplit(obj, ind, count, cutfeat, cutval, lim1, lim2);
1026 if (lim1>count/2) index = lim1;
1027 else if (lim2<count/2) index = lim2;
1028 else index = count/2;
1040 void planeSplit(Derived &obj, IndexType* ind,
const IndexType count,
int cutfeat, DistanceType &cutval, IndexType& lim1, IndexType& lim2)
1044 IndexType right = count-1;
1046 while (left<=right && obj.dataset_get(ind[left],cutfeat)<cutval) ++left;
1047 while (right && left<=right && obj.dataset_get(ind[right],cutfeat)>=cutval) --right;
1048 if (left>right || !right)
break;
1049 std::swap(ind[left], ind[right]);
1059 while (left<=right && obj.dataset_get(ind[left],cutfeat)<=cutval) ++left;
1060 while (right && left<=right && obj.dataset_get(ind[right],cutfeat)>cutval) --right;
1061 if (left>right || !right)
break;
1062 std::swap(ind[left], ind[right]);
1069 DistanceType computeInitialDistances(
const Derived &obj,
const ElementType* vec, distance_vector_t& dists)
const
1072 DistanceType distsq = DistanceType();
1074 for (
int i = 0; i < (DIM>0 ? DIM : obj.dim); ++i) {
1075 if (vec[i] < obj.root_bbox[i].low) {
1076 dists[i] = obj.distance.accum_dist(vec[i], obj.root_bbox[i].low, i);
1079 if (vec[i] > obj.root_bbox[i].high) {
1080 dists[i] = obj.distance.accum_dist(vec[i], obj.root_bbox[i].high, i);
1127 template <
typename Distance,
class DatasetAdaptor,
int DIM = -1,
typename IndexType =
size_t>
1134 typedef typename Distance::ElementType ElementType;
1135 typedef typename Distance::DistanceType DistanceType;
1142 size_t m_leaf_max_size;
1197 dataset(inputData), index_params(params), root_node(NULL), distance(inputData)
1199 m_size = dataset.kdtree_get_point_count();
1200 m_size_at_index_build = m_size;
1201 dim = dimensionality;
1203 m_leaf_max_size = params.leaf_max_size;
1218 this->freeIndex(*
this);
1219 m_size_at_index_build = m_size;
1220 if(m_size == 0)
return;
1221 computeBoundingBox(root_bbox);
1222 root_node = this->divideTree(*
this, 0, m_size, root_bbox );
1240 template <
typename RESULTSET>
1244 if (this->size(*
this) == 0)
1247 throw std::runtime_error(
"[nanoflann] findNeighbors() called before building the index.");
1248 float epsError = 1+searchParams.
eps;
1251 dists.assign((DIM>0 ? DIM : dim) ,0);
1252 DistanceType distsq = this->computeInitialDistances(*
this, vec, dists);
1253 searchLevel(result, vec, root_node, distsq, dists, epsError);
1254 return result.full();
1265 size_t knnSearch(
const ElementType *query_point,
const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq,
const int = 10)
const
1268 resultSet.init(out_indices, out_distances_sq);
1270 return resultSet.size();
1285 size_t radiusSearch(
const ElementType *query_point,
const DistanceType &radius, std::vector<std::pair<IndexType,DistanceType> >& IndicesDists,
const SearchParams& searchParams)
const
1288 const size_t nFound = radiusSearchCustomCallback(query_point,resultSet,searchParams);
1299 template <
class SEARCH_CALLBACK>
1302 this->findNeighbors(resultSet, query_point, searchParams);
1303 return resultSet.size();
1313 m_size = dataset.kdtree_get_point_count();
1314 if (vind.size()!=m_size) vind.resize(m_size);
1315 for (
size_t i = 0; i < m_size; i++) vind[i] = i;
1320 return dataset.kdtree_get_pt(idx,component);
1324 void save_tree(FILE* stream, NodePtr tree)
1326 save_value(stream, *tree);
1327 if (tree->child1!=NULL) {
1328 save_tree(stream, tree->child1);
1330 if (tree->child2!=NULL) {
1331 save_tree(stream, tree->child2);
1336 void load_tree(FILE* stream, NodePtr& tree)
1338 tree = pool.allocate<Node>();
1339 load_value(stream, *tree);
1340 if (tree->child1!=NULL) {
1341 load_tree(stream, tree->child1);
1343 if (tree->child2!=NULL) {
1344 load_tree(stream, tree->child2);
1348 void computeBoundingBox(BoundingBox& bbox)
1350 bbox.resize((DIM>0 ? DIM : dim));
1351 if (dataset.kdtree_get_bbox(bbox))
1357 const size_t N = dataset.kdtree_get_point_count();
1358 if (!N)
throw std::runtime_error(
"[nanoflann] computeBoundingBox() called but no data points found.");
1359 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1361 bbox[i].high = dataset_get(0,i);
1363 for (
size_t k=1; k<N; ++k) {
1364 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1365 if (dataset_get(k,i)<bbox[i].low) bbox[i].low = dataset_get(k,i);
1366 if (dataset_get(k,i)>bbox[i].high) bbox[i].high = dataset_get(k,i);
1377 template <
class RESULTSET>
1378 bool searchLevel(RESULTSET& result_set,
const ElementType* vec,
const NodePtr node, DistanceType mindistsq,
1382 if ((node->child1 == NULL)&&(node->
child2 == NULL)) {
1384 DistanceType worst_dist = result_set.worstDist();
1385 for (IndexType i=node->
node_type.lr.left; i<node->node_type.lr.right; ++i) {
1386 const IndexType index = vind[i];
1387 DistanceType dist = distance.evalMetric(vec, index, (DIM>0 ? DIM : dim));
1388 if (dist<worst_dist) {
1389 if(!result_set.addPoint(dist,vind[i])) {
1400 ElementType val = vec[idx];
1401 DistanceType diff1 = val - node->
node_type.sub.divlow;
1402 DistanceType diff2 = val - node->
node_type.sub.divhigh;
1406 DistanceType cut_dist;
1407 if ((diff1+diff2)<0) {
1408 bestChild = node->child1;
1409 otherChild = node->
child2;
1410 cut_dist = distance.accum_dist(val, node->
node_type.sub.divhigh, idx);
1413 bestChild = node->
child2;
1414 otherChild = node->child1;
1415 cut_dist = distance.accum_dist( val, node->
node_type.sub.divlow, idx);
1419 if(!searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError)) {
1424 DistanceType dst = dists[idx];
1425 mindistsq = mindistsq + cut_dist - dst;
1426 dists[idx] = cut_dist;
1427 if (mindistsq*epsError<=result_set.worstDist()) {
1428 if(!searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError)) {
1444 save_value(stream, m_size);
1445 save_value(stream, dim);
1446 save_value(stream, root_bbox);
1447 save_value(stream, m_leaf_max_size);
1448 save_value(stream, vind);
1449 save_tree(stream, root_node);
1458 load_value(stream, m_size);
1459 load_value(stream, dim);
1460 load_value(stream, root_bbox);
1461 load_value(stream, m_leaf_max_size);
1462 load_value(stream, vind);
1463 load_tree(stream, root_node);
1502 template <
typename Distance,
class DatasetAdaptor,
int DIM = -1,
typename IndexType =
size_t>
1506 typedef typename Distance::ElementType ElementType;
1507 typedef typename Distance::DistanceType DistanceType;
1514 size_t m_leaf_max_size;
1524 std::vector<int> &treeIndex;
1572 dataset(inputData), index_params(params), treeIndex(treeIndex_), root_node(NULL), distance(inputData)
1575 m_size_at_index_build = 0;
1576 dim = dimensionality;
1578 m_leaf_max_size = params.leaf_max_size;
1585 std::swap( vind, tmp.
vind );
1586 std::swap( m_leaf_max_size, tmp.m_leaf_max_size );
1587 std::swap( index_params, tmp.index_params );
1588 std::swap( treeIndex, tmp.treeIndex );
1589 std::swap( m_size, tmp.
m_size );
1592 std::swap( root_bbox, tmp.root_bbox );
1593 std::swap( pool, tmp.
pool );
1605 m_size = vind.size();
1606 this->freeIndex(*
this);
1607 m_size_at_index_build = m_size;
1608 if(m_size == 0)
return;
1609 computeBoundingBox(root_bbox);
1610 root_node = this->divideTree(*
this, 0, m_size, root_bbox );
1628 template <
typename RESULTSET>
1632 if (this->size(*
this) == 0)
1636 float epsError = 1+searchParams.
eps;
1639 dists.assign((DIM>0 ? DIM : dim) ,0);
1640 DistanceType distsq = this->computeInitialDistances(*
this, vec, dists);
1641 searchLevel(result, vec, root_node, distsq, dists, epsError);
1642 return result.full();
1653 size_t knnSearch(
const ElementType *query_point,
const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq,
const int = 10)
const
1656 resultSet.init(out_indices, out_distances_sq);
1658 return resultSet.size();
1673 size_t radiusSearch(
const ElementType *query_point,
const DistanceType &radius, std::vector<std::pair<IndexType,DistanceType> >& IndicesDists,
const SearchParams& searchParams)
const
1676 const size_t nFound = radiusSearchCustomCallback(query_point,resultSet,searchParams);
1687 template <
class SEARCH_CALLBACK>
1690 this->findNeighbors(resultSet, query_point, searchParams);
1691 return resultSet.size();
1699 return dataset.kdtree_get_pt(idx,component);
1703 void save_tree(FILE* stream, NodePtr tree)
1705 save_value(stream, *tree);
1706 if (tree->child1!=NULL) {
1707 save_tree(stream, tree->child1);
1709 if (tree->child2!=NULL) {
1710 save_tree(stream, tree->child2);
1715 void load_tree(FILE* stream, NodePtr& tree)
1717 tree = pool.allocate<Node>();
1718 load_value(stream, *tree);
1719 if (tree->child1!=NULL) {
1720 load_tree(stream, tree->child1);
1722 if (tree->child2!=NULL) {
1723 load_tree(stream, tree->child2);
1728 void computeBoundingBox(BoundingBox& bbox)
1730 bbox.resize((DIM>0 ? DIM : dim));
1731 if (dataset.kdtree_get_bbox(bbox))
1737 const size_t N = m_size;
1738 if (!N)
throw std::runtime_error(
"[nanoflann] computeBoundingBox() called but no data points found.");
1739 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1741 bbox[i].high = dataset_get(vind[0],i);
1743 for (
size_t k=1; k<N; ++k) {
1744 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1745 if (dataset_get(vind[k],i)<bbox[i].low) bbox[i].low = dataset_get(vind[k],i);
1746 if (dataset_get(vind[k],i)>bbox[i].high) bbox[i].high = dataset_get(vind[k],i);
1756 template <
class RESULTSET>
1757 void searchLevel(RESULTSET& result_set,
const ElementType* vec,
const NodePtr node, DistanceType mindistsq,
1761 if ((node->child1 == NULL)&&(node->
child2 == NULL)) {
1763 DistanceType worst_dist = result_set.worstDist();
1764 for (IndexType i=node->
node_type.lr.left; i<node->node_type.lr.right; ++i) {
1765 const IndexType index = vind[i];
1766 if(treeIndex[index]==-1)
1768 DistanceType dist = distance.evalMetric(vec, index, (DIM>0 ? DIM : dim));
1769 if (dist<worst_dist) {
1770 result_set.addPoint(dist,vind[i]);
1778 ElementType val = vec[idx];
1779 DistanceType diff1 = val - node->
node_type.sub.divlow;
1780 DistanceType diff2 = val - node->
node_type.sub.divhigh;
1784 DistanceType cut_dist;
1785 if ((diff1+diff2)<0) {
1786 bestChild = node->child1;
1787 otherChild = node->
child2;
1788 cut_dist = distance.accum_dist(val, node->
node_type.sub.divhigh, idx);
1791 bestChild = node->
child2;
1792 otherChild = node->child1;
1793 cut_dist = distance.accum_dist( val, node->
node_type.sub.divlow, idx);
1797 searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError);
1799 DistanceType dst = dists[idx];
1800 mindistsq = mindistsq + cut_dist - dst;
1801 dists[idx] = cut_dist;
1802 if (mindistsq*epsError<=result_set.worstDist()) {
1803 searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError);
1815 save_value(stream, m_size);
1816 save_value(stream, dim);
1817 save_value(stream, root_bbox);
1818 save_value(stream, m_leaf_max_size);
1819 save_value(stream, vind);
1820 save_tree(stream, root_node);
1829 load_value(stream, m_size);
1830 load_value(stream, dim);
1831 load_value(stream, root_bbox);
1832 load_value(stream, m_leaf_max_size);
1833 load_value(stream, vind);
1834 load_tree(stream, root_node);
1852 template <
typename Distance,
class DatasetAdaptor,
int DIM = -1,
typename IndexType =
size_t>
1856 typedef typename Distance::ElementType ElementType;
1857 typedef typename Distance::DistanceType DistanceType;
1860 size_t m_leaf_max_size;
1875 std::vector<KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM> > index;
1880 int First0Bit(IndexType num)
1892 inline ElementType dataset_get(
size_t idx,
int component)
const {
1893 return dataset.kdtree_get_pt(idx,component);
1899 typedef KDTreeSingleIndexDynamicAdaptor_<Distance, DatasetAdaptor, DIM> my_kd_tree_t;
1900 std::vector<my_kd_tree_t> index_(treeCount, my_kd_tree_t(dim , dataset, treeIndex, index_params));
1922 dataset(inputData), index_params(params), distance(inputData)
1924 if (dataset.kdtree_get_point_count())
throw std::runtime_error(
"[nanoflann] cannot handle non empty point cloud.");
1925 treeCount = log2(maximumPointCount);
1927 dim = dimensionality;
1930 m_leaf_max_size = params.leaf_max_size;
1940 int count = end-start;
1941 treeIndex.resize(treeIndex.size()+count);
1942 for(IndexType idx=start;idx<end;idx++)
1944 int pos = First0Bit(pointCount);
1945 index[pos].vind.clear();
1946 treeIndex[pointCount]=pos;
1947 for(
int i=0;i<pos;i++)
1949 for(
int j=0;j<index[i].vind.size();j++)
1951 index[pos].vind.push_back(index[i].vind[j]);
1952 treeIndex[index[i].vind[j]] = pos;
1954 index[i].vind.clear();
1955 index[i].freeIndex(index[i]);
1957 index[pos].vind.push_back(idx);
1958 index[pos].buildIndex();
1966 if(idx<0 || idx>=pointCount)
1968 treeIndex[idx] = -1;
1983 template <
typename RESULTSET>
1986 for(
int i=0;i<treeCount;i++)
1988 index[i].findNeighbors(result, &vec[0], searchParams);
1990 return result.full();
2017 typedef typename MatrixType::Scalar num_t;
2018 typedef typename MatrixType::Index IndexType;
2019 typedef typename Distance::template traits<num_t,self_t>::distance_t metric_t;
2027 const IndexType dims = mat.cols();
2028 if (dims!=dimensionality)
throw std::runtime_error(
"Error: 'dimensionality' must match column count in data matrix");
2029 if (DIM>0 && static_cast<int>(dims)!=DIM)
2030 throw std::runtime_error(
"Data set dimensionality does not match the 'DIM' template argument");
2032 index->buildIndex();
2043 const MatrixType &m_data_matrix;
2050 inline void query(
const num_t *query_point,
const size_t num_closest, IndexType *out_indices, num_t *out_distances_sq,
const int = 10)
const
2053 resultSet.init(out_indices, out_distances_sq);
2060 const self_t & derived()
const {
2063 self_t & derived() {
2068 inline size_t kdtree_get_point_count()
const {
2069 return m_data_matrix.rows();
2073 inline num_t kdtree_distance(
const num_t *p1,
const IndexType idx_p2,IndexType size)
const
2076 for (IndexType i=0; i<size; i++) {
2077 const num_t d= p1[i]-m_data_matrix.coeff(idx_p2,i);
2084 inline num_t kdtree_get_pt(
const IndexType idx,
int dim)
const {
2085 return m_data_matrix.coeff(idx,IndexType(dim));
2091 template <
class BBOX>
2092 bool kdtree_get_bbox(BBOX& )
const {
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1241
~KDTreeSingleIndexDynamicAdaptor()
Definition: nanoflann.hpp:1935
size_t veclen(const Derived &obj)
Definition: nanoflann.hpp:909
Definition: nanoflann.hpp:467
Definition: nanoflann.hpp:534
std::vector< IndexType > vind
Definition: nanoflann.hpp:1140
nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexAdaptor< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType >::BoundingBox BoundingBox
Definition: nanoflann.hpp:1162
void addPoints(IndexType start, IndexType end)
Definition: nanoflann.hpp:1938
Definition: nanoflann.hpp:875
void buildIndex()
Definition: nanoflann.hpp:1603
void query(const num_t *query_point, const size_t num_closest, IndexType *out_indices, num_t *out_distances_sq, const int=10) const
Definition: nanoflann.hpp:2050
Definition: nanoflann.hpp:548
KDTreeSingleIndexAdaptor(const int dimensionality, const DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams ¶ms=KDTreeSingleIndexAdaptorParams())
Definition: nanoflann.hpp:1196
Definition: nanoflann.hpp:494
NodePtr root_node
Definition: nanoflann.hpp:1542
Definition: nanoflann.hpp:752
size_t knnSearch(const ElementType *query_point, const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq, const int=10) const
Definition: nanoflann.hpp:1265
bool operator()(const PairType &p1, const PairType &p2) const
Definition: nanoflann.hpp:152
DatasetAdaptor & dataset
The source of our data.
Definition: nanoflann.hpp:1520
Definition: nanoflann.hpp:497
Definition: nanoflann.hpp:858
union nanoflann::KDTreeBaseClass::Node::@1 node_type
Definition: nanoflann.hpp:607
KDTreeEigenMatrixAdaptor(const int dimensionality, const MatrixType &mat, const int leaf_max_size=10)
The kd-tree index for the user to call its methods as usual with any other FLANN index.
Definition: nanoflann.hpp:2025
Definition: nanoflann.hpp:435
Definition: nanoflann.hpp:526
KDTreeSingleIndexDynamicAdaptor_(const int dimensionality, DatasetAdaptor &inputData, std::vector< int > &treeIndex_, const KDTreeSingleIndexAdaptorParams ¶ms=KDTreeSingleIndexAdaptorParams())
Definition: nanoflann.hpp:1571
size_t radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParams &searchParams=SearchParams()) const
Definition: nanoflann.hpp:1300
Definition: nanoflann.hpp:894
~KDTreeSingleIndexAdaptor()
Definition: nanoflann.hpp:1210
size_t radiusSearchCustomCallback(const ElementType *query_point, SEARCH_CALLBACK &resultSet, const SearchParams &searchParams=SearchParams()) const
Definition: nanoflann.hpp:1688
Definition: nanoflann.hpp:834
const DatasetAdaptor & dataset
The source of our data.
Definition: nanoflann.hpp:1148
Definition: nanoflann.hpp:510
int divfeat
Dimension used for subdivision.
Definition: nanoflann.hpp:885
Definition: nanoflann.hpp:258
Definition: nanoflann.hpp:397
KDTreeSingleIndexDynamicAdaptor(const int dimensionality, DatasetAdaptor &inputData, const KDTreeSingleIndexAdaptorParams ¶ms=KDTreeSingleIndexAdaptorParams(), const int maximumPointCount=1e9)
Definition: nanoflann.hpp:1921
Definition: nanoflann.hpp:521
void freeIndex(Derived &obj)
Definition: nanoflann.hpp:863
void saveIndex(FILE *stream)
Definition: nanoflann.hpp:1442
void free_all()
Definition: nanoflann.hpp:646
Definition: nanoflann.hpp:1128
int checks
Ignored parameter (Kept for compatibility with the FLANN interface).
Definition: nanoflann.hpp:564
~KDTreeSingleIndexDynamicAdaptor_()
Definition: nanoflann.hpp:1598
void loadIndex(FILE *stream)
Definition: nanoflann.hpp:1456
Definition: nanoflann.hpp:161
int dim
Dimensionality of each data point.
Definition: nanoflann.hpp:1528
IndexType right
Indices of points in leaf node.
Definition: nanoflann.hpp:881
size_t m_size_at_index_build
Number of points in the dataset when the index was built.
Definition: nanoflann.hpp:1153
void resize(const size_t nElements)
Definition: nanoflann.hpp:809
bool searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindistsq, distance_vector_t &dists, const float epsError) const
Definition: nanoflann.hpp:1378
Definition: nanoflann.hpp:1853
size_t size(const Derived &obj) const
Definition: nanoflann.hpp:906
int dim
Dimensionality of each data point.
Definition: nanoflann.hpp:1154
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1984
~PooledAllocator()
Definition: nanoflann.hpp:641
nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType >::BoundingBox BoundingBox
Definition: nanoflann.hpp:1536
Definition: nanoflann.hpp:558
size_t m_size
Number of current points in the dataset.
Definition: nanoflann.hpp:1526
T * allocate(const size_t count=1)
Definition: nanoflann.hpp:713
PooledAllocator pool
Definition: nanoflann.hpp:1552
DatasetAdaptor & dataset
The source of our data.
Definition: nanoflann.hpp:1867
Definition: nanoflann.hpp:268
NodePtr root_node
Definition: nanoflann.hpp:1168
T * allocate(size_t count=1)
Definition: nanoflann.hpp:582
KDTreeSingleIndexDynamicAdaptor_ operator=(const KDTreeSingleIndexDynamicAdaptor_ &rhs)
Definition: nanoflann.hpp:1583
void saveIndex(FILE *stream)
Definition: nanoflann.hpp:1813
NodePtr divideTree(Derived &obj, const IndexType left, const IndexType right, BoundingBox &bbox)
Definition: nanoflann.hpp:940
Definition: nanoflann.hpp:148
std::pair< IndexType, DistanceType > worst_item() const
Definition: nanoflann.hpp:199
Node * child2
Child nodes (both=NULL mean its a leaf node)
Definition: nanoflann.hpp:889
void planeSplit(Derived &obj, IndexType *ind, const IndexType count, int cutfeat, DistanceType &cutval, IndexType &lim1, IndexType &lim2)
Definition: nanoflann.hpp:1040
Definition: nanoflann.hpp:316
PooledAllocator pool
Definition: nanoflann.hpp:1178
Definition: nanoflann.hpp:513
void init_vind()
Definition: nanoflann.hpp:1310
size_t knnSearch(const ElementType *query_point, const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq, const int=10) const
Definition: nanoflann.hpp:1653
int dim
Dimensionality of each data point.
Definition: nanoflann.hpp:1873
std::vector< IndexType > vind
Definition: nanoflann.hpp:1512
void removePoint(int idx)
Definition: nanoflann.hpp:1964
Definition: nanoflann.hpp:518
void buildIndex()
Definition: nanoflann.hpp:1215
void * malloc(const size_t req_size)
Definition: nanoflann.hpp:660
ElementType dataset_get(size_t idx, int component) const
Helper accessor to the dataset points:
Definition: nanoflann.hpp:1698
nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexAdaptor< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType >::distance_vector_t distance_vector_t
Definition: nanoflann.hpp:1165
Definition: nanoflann.hpp:529
Definition: nanoflann.hpp:2014
Definition: nanoflann.hpp:505
const size_t WORDSIZE
Definition: nanoflann.hpp:604
Definition: nanoflann.hpp:79
Definition: nanoflann.hpp:1503
bool findNeighbors(RESULTSET &result, const ElementType *vec, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1629
Definition: nanoflann.hpp:365
std::vector< int > treeIndex
treeIndex[idx] is the index of tree in which point at idx is stored. treeIndex[idx]=-1 means that poi...
Definition: nanoflann.hpp:1869
nanoflann::KDTreeBaseClass< nanoflann::KDTreeSingleIndexDynamicAdaptor_< Distance, DatasetAdaptor, DIM, IndexType >, Distance, DatasetAdaptor, DIM, IndexType >::distance_vector_t distance_vector_t
Definition: nanoflann.hpp:1539
bool sorted
only for radius search, require neighbours sorted by distance (default: true)
Definition: nanoflann.hpp:566
SearchParams(int checks_IGNORED_=32, float eps_=0, bool sorted_=true)
Definition: nanoflann.hpp:561
array_or_vector_selector< DIM, Interval >::container_t BoundingBox
Definition: nanoflann.hpp:900
Definition: nanoflann.hpp:537
DistanceType divhigh
The values used for subdivision.
Definition: nanoflann.hpp:886
void loadIndex(FILE *stream)
Definition: nanoflann.hpp:1827
size_t radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< std::pair< IndexType, DistanceType > > &IndicesDists, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1285
size_t usedMemory(Derived &obj)
Definition: nanoflann.hpp:917
void searchLevel(RESULTSET &result_set, const ElementType *vec, const NodePtr node, DistanceType mindistsq, distance_vector_t &dists, const float epsError) const
Definition: nanoflann.hpp:1757
size_t radiusSearch(const ElementType *query_point, const DistanceType &radius, std::vector< std::pair< IndexType, DistanceType > > &IndicesDists, const SearchParams &searchParams) const
Definition: nanoflann.hpp:1673
array_or_vector_selector< DIM, DistanceType >::container_t distance_vector_t
Definition: nanoflann.hpp:903
size_t m_size
Number of current points in the dataset.
Definition: nanoflann.hpp:1152
size_t m_size_at_index_build
Number of points in the dataset when the index was built.
Definition: nanoflann.hpp:1527
bool addPoint(DistanceType dist, IndexType index)
Definition: nanoflann.hpp:186
float eps
search for eps-approximate neighbours (default: 0)
Definition: nanoflann.hpp:565
PooledAllocator()
Definition: nanoflann.hpp:634
ElementType dataset_get(size_t idx, int component) const
Helper accessor to the dataset points:
Definition: nanoflann.hpp:1319
Definition: nanoflann.hpp:502
bool addPoint(DistanceType dist, IndexType index)
Definition: nanoflann.hpp:115