33 #ifndef NANOFLANN_HPP_
34 #define NANOFLANN_HPP_
45 #if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
59 #define NANOFLANN_VERSION 0x113
63 template <
typename DistanceType,
typename IndexType =
size_t,
typename CountType =
size_t>
76 inline void init(IndexType* indices_, DistanceType* dists_)
81 dists[
capacity-1] = (std::numeric_limits<DistanceType>::max)();
84 inline CountType
size()
const
95 inline void addPoint(DistanceType dist, IndexType index)
99 #ifdef NANOFLANN_FIRST_MATCH // If defined and two poins have the same distance, the one with the lowest-index will be returned first.
128 template <
typename DistanceType,
typename IndexType =
size_t>
129 class RadiusResultSet
132 const DistanceType radius;
134 std::vector<std::pair<IndexType,DistanceType> >& m_indices_dists;
136 inline RadiusResultSet(DistanceType radius_, std::vector<std::pair<IndexType,DistanceType> >& indices_dists) : radius(radius_), m_indices_dists(indices_dists)
141 inline ~RadiusResultSet() { }
143 inline void init() { clear(); }
144 inline void clear() { m_indices_dists.clear(); }
146 inline size_t size()
const {
return m_indices_dists.size(); }
148 inline bool full()
const {
return true; }
150 inline void addPoint(DistanceType dist, IndexType index)
153 m_indices_dists.push_back(std::make_pair<IndexType,DistanceType>(index,dist));
156 inline DistanceType
worstDist()
const {
return radius; }
159 inline void set_radius_and_clear(
const DistanceType r )
169 std::pair<IndexType,DistanceType> worst_item()
const
171 if (m_indices_dists.empty())
throw std::runtime_error(
"Cannot invoke RadiusResultSet::worst_item() on an empty list of results.");
172 typedef typename std::vector<std::pair<IndexType,DistanceType> >::const_iterator DistIt;
173 DistIt it = std::max_element(m_indices_dists.begin(), m_indices_dists.end());
182 template <
typename PairType>
183 inline bool operator()(
const PairType &p1,
const PairType &p2)
const {
184 return p1.second < p2.second;
196 fwrite(&value,
sizeof(value),
count, stream);
200 void save_value(FILE* stream,
const std::vector<T>& value)
202 size_t size = value.size();
203 fwrite(&
size,
sizeof(
size_t), 1, stream);
204 fwrite(&value[0],
sizeof(T),
size, stream);
210 size_t read_cnt = fread(&value,
sizeof(value),
count, stream);
211 if (read_cnt !=
count) {
212 throw std::runtime_error(
"Cannot read from file");
218 void load_value(FILE* stream, std::vector<T>& value)
221 size_t read_cnt = fread(&
size,
sizeof(
size_t), 1, stream);
223 throw std::runtime_error(
"Cannot read from file");
226 read_cnt = fread(&value[0],
sizeof(T),
size, stream);
227 if (read_cnt!=
size) {
228 throw std::runtime_error(
"Cannot read from file");
237 template<
typename T>
inline T
abs(T x) {
return (x<0) ? -x : x; }
239 template<>
inline float abs<float>(
float x) {
return fabsf(x); }
240 template<>
inline double abs<double>(
double x) {
return fabs(x); }
241 template<>
inline long double abs<long double>(
long double x) {
return fabsl(x); }
248 template<
class T,
class DataSource,
typename _DistanceType = T>
251 typedef T ElementType;
252 typedef _DistanceType DistanceType;
254 const DataSource &data_source;
256 L1_Adaptor(
const DataSource &_data_source) : data_source(_data_source) { }
258 inline DistanceType operator()(
const T* a,
const size_t b_idx,
size_t size, DistanceType worst_dist = -1)
const
260 DistanceType result = DistanceType();
261 const T* last = a +
size;
262 const T* lastgroup = last - 3;
266 while (a < lastgroup) {
267 const DistanceType diff0 =
nanoflann::abs(a[0] - data_source.kdtree_get_pt(b_idx,d++));
268 const DistanceType diff1 =
nanoflann::abs(a[1] - data_source.kdtree_get_pt(b_idx,d++));
269 const DistanceType diff2 =
nanoflann::abs(a[2] - data_source.kdtree_get_pt(b_idx,d++));
270 const DistanceType diff3 =
nanoflann::abs(a[3] - data_source.kdtree_get_pt(b_idx,d++));
271 result += diff0 + diff1 + diff2 + diff3;
273 if ((worst_dist>0)&&(result>worst_dist)) {
284 template <
typename U,
typename V>
285 inline DistanceType accum_dist(
const U a,
const V b,
int dim)
const
296 template<
class T,
class DataSource,
typename _DistanceType = T>
299 typedef T ElementType;
300 typedef _DistanceType DistanceType;
302 const DataSource &data_source;
304 L2_Adaptor(
const DataSource &_data_source) : data_source(_data_source) { }
306 inline DistanceType operator()(
const T* a,
const size_t b_idx,
size_t size, DistanceType worst_dist = -1)
const
308 DistanceType result = DistanceType();
309 const T* last = a +
size;
310 const T* lastgroup = last - 3;
314 while (a < lastgroup) {
315 const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx,d++);
316 const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx,d++);
317 const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx,d++);
318 const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx,d++);
319 result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
321 if ((worst_dist>0)&&(result>worst_dist)) {
327 const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx,d++);
328 result += diff0 * diff0;
333 template <
typename U,
typename V>
345 template<
class T,
class DataSource,
typename _DistanceType = T>
346 struct L2_Simple_Adaptor
348 typedef T ElementType;
349 typedef _DistanceType DistanceType;
351 const DataSource &data_source;
353 L2_Simple_Adaptor(
const DataSource &_data_source) : data_source(_data_source) { }
355 inline DistanceType operator()(
const T* a,
const size_t b_idx,
size_t size)
const {
356 return data_source.kdtree_distance(a,b_idx,
size);
359 template <
typename U,
typename V>
360 inline DistanceType accum_dist(
const U a,
const V b,
int dim)
const
368 template<
class T,
class DataSource>
375 template<
class T,
class DataSource>
382 template<
class T,
class DataSource>
400 leaf_max_size(_leaf_max_size), dim(dim_)
403 size_t leaf_max_size;
411 SearchParams(
int checks_IGNORED_ = 32,
float eps_ = 0,
bool sorted_ =
true ) :
412 eps(eps_), sorted(sorted_) {}
431 template <
typename T>
434 T* mem = (T*) ::malloc(
sizeof(T)*
count);
480 this->blocksize = blocksize;
493 while (base !=
NULL) {
494 void *prev = *((
void**) base);
504 void* malloc(
const size_t req_size)
515 if (
size > remaining) {
517 wastedMemory += remaining;
524 void* m = ::malloc(blocksize);
526 fprintf(stderr,
"Failed to allocate memory.\n");
531 ((
void**) m)[0] = base;
537 remaining = blocksize -
sizeof(
void*) - shift;
538 loc = ((
char*)m +
sizeof(
void*) + shift);
541 loc = (
char*)loc +
size;
556 template <
typename T>
559 T* mem = (T*) this->malloc(
sizeof(T)*
count);
603 template <
typename Distance,
class DatasetAdaptor,
int DIM = -1,
typename IndexType =
size_t>
604 class KDTreeSingleIndexAdaptor
607 typedef typename Distance::ElementType ElementType;
608 typedef typename Distance::DistanceType DistanceType;
614 std::vector<IndexType> vind;
616 size_t m_leaf_max_size;
622 const DatasetAdaptor &dataset;
624 const KDTreeSingleIndexAdaptorParams index_params;
639 IndexType left, right;
658 typedef Node* NodePtr;
673 template <
typename T,
typename DistanceType>
718 dataset(inputData), index_params(params), distance(inputData)
720 m_size = dataset.kdtree_get_point_count();
721 dim = dimensionality;
724 if (params.dim>0) dim = params.dim;
726 m_leaf_max_size = params.leaf_max_size;
735 ~KDTreeSingleIndexAdaptor()
745 computeBoundingBox(root_bbox);
746 root_node = divideTree(0, m_size, root_bbox );
760 size_t veclen()
const
762 return static_cast<size_t>(DIM>0 ? DIM : dim);
769 size_t usedMemory()
const
788 template <
typename RESULTSET>
789 void findNeighbors(RESULTSET& result,
const ElementType* vec,
const SearchParams& searchParams)
const
792 float epsError = 1+searchParams.
eps;
794 std::vector<DistanceType>
dists( (DIM>0 ? DIM : dim) ,0);
796 searchLevel(result, vec, root_node, distsq,
dists, epsError);
805 inline void knnSearch(
const ElementType *query_point,
const size_t num_closest, IndexType *out_indices, DistanceType *out_distances_sq,
const int nChecks_IGNORED = 10)
const
808 resultSet.init(out_indices, out_distances_sq);
824 size_t radiusSearch(
const ElementType *query_point,
const DistanceType radius, std::vector<std::pair<IndexType,DistanceType> >& IndicesDists,
const SearchParams& searchParams)
const
826 RadiusResultSet<DistanceType,IndexType> resultSet(radius,IndicesDists);
827 this->findNeighbors(resultSet, query_point, searchParams);
829 if (searchParams.sorted)
830 std::sort(IndicesDists.begin(),IndicesDists.end(), IndexDist_Sorter() );
832 return resultSet.size();
842 m_size = dataset.kdtree_get_point_count();
843 if (vind.size()!=m_size)
846 for (
size_t i = 0; i < m_size; i++) vind[i] = i;
851 inline ElementType dataset_get(
size_t idx,
int component)
const {
852 return dataset.kdtree_get_pt(idx,component);
856 void save_tree(FILE* stream,
NodePtr tree)
860 save_tree(stream, tree->
child1);
863 save_tree(stream, tree->
child2);
868 void load_tree(FILE* stream, NodePtr& tree)
872 if (tree->child1!=
NULL) {
873 load_tree(stream, tree->child1);
875 if (tree->child2!=
NULL) {
876 load_tree(stream, tree->child2);
883 bbox.resize((DIM>0 ? DIM : dim));
884 if (dataset.kdtree_get_bbox(bbox))
890 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
892 bbox[i].high = dataset_get(0,i);
894 const size_t N = dataset.kdtree_get_point_count();
895 for (
size_t k=1; k<N; ++k) {
896 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
897 if (dataset_get(k,i)<bbox[i].low) bbox[i].low = dataset_get(k,i);
898 if (dataset_get(k,i)>bbox[i].high) bbox[i].high = dataset_get(k,i);
914 NodePtr divideTree(
const IndexType left,
const IndexType right, BoundingBox& bbox)
916 NodePtr node = pool.
allocate<Node>();
919 if ( (right-left) <= m_leaf_max_size) {
920 node->child1 = node->child2 =
NULL;
921 node->lr.left = left;
922 node->lr.right = right;
925 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
926 bbox[i].low = dataset_get(vind[left],i);
927 bbox[i].high = dataset_get(vind[left],i);
929 for (IndexType k=left+1; k<right; ++k) {
930 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
931 if (bbox[i].low>dataset_get(vind[k],i)) bbox[i].low=dataset_get(vind[k],i);
932 if (bbox[i].high<dataset_get(vind[k],i)) bbox[i].high=dataset_get(vind[k],i);
940 middleSplit_(&vind[0]+left, right-left, idx, cutfeat, cutval, bbox);
942 node->sub.divfeat = cutfeat;
945 left_bbox[cutfeat].high = cutval;
946 node->child1 = divideTree(left, left+idx, left_bbox);
949 right_bbox[cutfeat].low = cutval;
950 node->child2 = divideTree(left+idx, right, right_bbox);
952 node->sub.divlow = left_bbox[cutfeat].high;
953 node->sub.divhigh = right_bbox[cutfeat].low;
955 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
956 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
957 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
964 void computeMinMax(IndexType* ind, IndexType
count,
int element, ElementType& min_elem, ElementType& max_elem)
966 min_elem = dataset_get(ind[0],element);
967 max_elem = dataset_get(ind[0],element);
968 for (IndexType i=1; i<
count; ++i) {
969 ElementType val = dataset_get(ind[i],element);
970 if (val<min_elem) min_elem = val;
971 if (val>max_elem) max_elem = val;
975 void middleSplit(IndexType* ind, IndexType
count, IndexType& index,
int& cutfeat, DistanceType& cutval,
const BoundingBox& bbox)
978 ElementType max_span = bbox[0].high-bbox[0].low;
980 cutval = (bbox[0].high+bbox[0].low)/2;
981 for (
int i=1; i<(DIM>0 ? DIM : dim); ++i) {
982 ElementType span = bbox[i].low-bbox[i].low;
986 cutval = (bbox[i].high+bbox[i].low)/2;
991 ElementType min_elem, max_elem;
992 computeMinMax(ind,
count, cutfeat, min_elem, max_elem);
993 cutval = (min_elem+max_elem)/2;
994 max_span = max_elem - min_elem;
998 for (
size_t i=0; i<(DIM>0 ? DIM : dim); ++i) {
1001 if (span>max_span) {
1002 computeMinMax(ind,
count, i, min_elem, max_elem);
1003 span = max_elem - min_elem;
1004 if (span>max_span) {
1007 cutval = (min_elem+max_elem)/2;
1011 IndexType lim1, lim2;
1012 planeSplit(ind,
count, cutfeat, cutval, lim1, lim2);
1014 if (lim1>
count/2) index = lim1;
1015 else if (lim2<
count/2) index = lim2;
1016 else index =
count/2;
1020 void middleSplit_(IndexType* ind, IndexType
count, IndexType& index,
int& cutfeat, DistanceType& cutval,
const BoundingBox& bbox)
1022 const DistanceType EPS=
static_cast<DistanceType
>(0.00001);
1023 ElementType max_span = bbox[0].high-bbox[0].low;
1024 for (
int i=1; i<(DIM>0 ? DIM : dim); ++i) {
1025 ElementType span = bbox[i].high-bbox[i].low;
1026 if (span>max_span) {
1030 ElementType max_spread = -1;
1032 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1033 ElementType span = bbox[i].high-bbox[i].low;
1034 if (span>(1-EPS)*max_span) {
1035 ElementType min_elem, max_elem;
1036 computeMinMax(ind,
count, cutfeat, min_elem, max_elem);
1037 ElementType spread = max_elem-min_elem;;
1038 if (spread>max_spread) {
1040 max_spread = spread;
1045 DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2;
1046 ElementType min_elem, max_elem;
1047 computeMinMax(ind,
count, cutfeat, min_elem, max_elem);
1049 if (split_val<min_elem) cutval = min_elem;
1050 else if (split_val>max_elem) cutval = max_elem;
1051 else cutval = split_val;
1053 IndexType lim1, lim2;
1054 planeSplit(ind,
count, cutfeat, cutval, lim1, lim2);
1056 if (lim1>
count/2) index = lim1;
1057 else if (lim2<
count/2) index = lim2;
1058 else index =
count/2;
1071 void planeSplit(IndexType* ind,
const IndexType
count,
int cutfeat, DistanceType cutval, IndexType& lim1, IndexType& lim2)
1075 IndexType right =
count-1;
1077 while (left<=right && dataset_get(ind[left],cutfeat)<cutval) ++left;
1078 while (right && left<=right && dataset_get(ind[right],cutfeat)>=cutval) --right;
1079 if (left>right || !right)
break;
1090 while (left<=right && dataset_get(ind[left],cutfeat)<=cutval) ++left;
1091 while (right && left<=right && dataset_get(ind[right],cutfeat)>cutval) --right;
1092 if (left>right || !right)
break;
1100 DistanceType computeInitialDistances(
const ElementType* vec, std::vector<DistanceType>&
dists)
const
1105 for (
int i = 0; i < (DIM>0 ? DIM : dim); ++i) {
1106 if (vec[i] < root_bbox[i].low) {
1107 dists[i] = distance.accum_dist(vec[i], root_bbox[i].low, i);
1110 if (vec[i] > root_bbox[i].high) {
1111 dists[i] = distance.accum_dist(vec[i], root_bbox[i].high, i);
1123 template <
class RESULTSET>
1124 void searchLevel(RESULTSET& result_set,
const ElementType* vec,
const NodePtr node, DistanceType mindistsq,
1125 std::vector<DistanceType>&
dists,
const float epsError)
const
1128 if ((node->child1 ==
NULL)&&(node->child2 ==
NULL)) {
1131 for (IndexType i=node->lr.left; i<node->lr.right; ++i) {
1132 const IndexType index = vind[i];
1133 DistanceType dist = distance(vec, index, (DIM>0 ? DIM : dim));
1134 if (dist<worst_dist) {
1135 result_set.addPoint(dist,vind[i]);
1142 int idx = node->sub.divfeat;
1143 ElementType val = vec[idx];
1144 DistanceType diff1 = val - node->sub.divlow;
1145 DistanceType diff2 = val - node->sub.divhigh;
1149 DistanceType cut_dist;
1150 if ((diff1+diff2)<0) {
1151 bestChild = node->child1;
1152 otherChild = node->child2;
1153 cut_dist = distance.accum_dist(val, node->sub.divhigh, idx);
1156 bestChild = node->child2;
1157 otherChild = node->child1;
1158 cut_dist = distance.accum_dist( val, node->sub.divlow, idx);
1162 searchLevel(result_set, vec, bestChild, mindistsq,
dists, epsError);
1164 DistanceType dst =
dists[idx];
1165 mindistsq = mindistsq + cut_dist - dst;
1166 dists[idx] = cut_dist;
1167 if (mindistsq*epsError<=result_set.worstDist()) {
1168 searchLevel(result_set, vec, otherChild, mindistsq,
dists, epsError);
1174 void saveIndex(FILE* stream)
1181 save_tree(stream, root_node);
1184 void loadIndex(FILE* stream)
1191 load_tree(stream, root_node);
1216 template <
class MatrixType,
int DIM = -1,
class Distance =
nanoflann::metric_L2,
typename IndexType =
size_t>
1217 struct KDTreeEigenMatrixAdaptor
1219 typedef KDTreeEigenMatrixAdaptor<MatrixType,DIM,Distance> self_t;
1220 typedef typename MatrixType::Scalar num_t;
1221 typedef typename Distance::template traits<num_t,self_t>::distance_t metric_t;
1222 typedef KDTreeSingleIndexAdaptor< metric_t,self_t,DIM,IndexType> index_t;
1227 KDTreeEigenMatrixAdaptor(
const int dimensionality,
const MatrixType &mat,
const int leaf_max_size = 10) : m_data_matrix(mat)
1229 const size_t dims = mat.cols();
1230 if (DIM>0 &&
static_cast<int>(dims)!=DIM)
1231 throw std::runtime_error(
"Data set dimensionality does not match the 'DIM' template argument");
1233 index->buildIndex();
1236 ~KDTreeEigenMatrixAdaptor() {
1240 const MatrixType &m_data_matrix;
1247 inline void query(
const num_t *query_point,
const size_t num_closest, IndexType *out_indices,
num_t *out_distances_sq,
const int nChecks_IGNORED = 10)
const
1250 resultSet.init(out_indices, out_distances_sq);
1260 self_t & derived() {
1265 inline size_t kdtree_get_point_count()
const {
1266 return m_data_matrix.rows();
1273 for (
size_t i=0; i<
size; i++) {
1274 const num_t d= p1[i]-m_data_matrix.coeff(idx_p2,i);
1281 inline num_t kdtree_get_pt(
const size_t idx,
int dim)
const {
1282 return m_data_matrix.coeff(idx,dim);
1288 template <
class BBOX>
1289 bool kdtree_get_bbox(BBOX &bb)
const {