46 #ifndef NANOFLANN_HPP_
47 #define NANOFLANN_HPP_
59 #if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_) || defined(WIN32) || defined(_WIN64))
73 #define NANOFLANN_VERSION 0x123
77 template <
typename DistanceType,
typename IndexType =
size_t,
typename CountType =
size_t>
90 inline void init(IndexType* indices_, DistanceType* dists_)
96 dists[
capacity-1] = (std::numeric_limits<DistanceType>::max)();
99 inline CountType
size()
const
114 inline bool addPoint(DistanceType dist, IndexType index)
117 for (i=
count; i>0; --i) {
118 #ifdef NANOFLANN_FIRST_MATCH // If defined and two points have the same distance, the one with the lowest-index will be returned first.
121 if (
dists[i-1]>dist) {
150 template <
typename PairType>
151 inline bool operator()(
const PairType &p1,
const PairType &p2)
const {
152 return p1.second < p2.second;
159 template <
typename DistanceType,
typename IndexType =
size_t>
167 inline RadiusResultSet(DistanceType radius_, std::vector<std::pair<IndexType,DistanceType> >& indices_dists) : radius(radius_), m_indices_dists(indices_dists)
174 inline void init() { clear(); }
175 inline void clear() { m_indices_dists.clear(); }
177 inline size_t size()
const {
return m_indices_dists.size(); }
179 inline bool full()
const {
return true; }
185 inline bool addPoint(DistanceType dist, IndexType index)
188 m_indices_dists.push_back(std::make_pair(index,dist));
192 inline DistanceType
worstDist()
const {
return radius; }
200 if (m_indices_dists.empty())
throw std::runtime_error(
"Cannot invoke RadiusResultSet::worst_item() on an empty list of results.");
201 typedef typename std::vector<std::pair<IndexType,DistanceType> >::const_iterator DistIt;
202 DistIt it = std::max_element(m_indices_dists.begin(), m_indices_dists.end(),
IndexDist_Sorter());
216 fwrite(&value,
sizeof(value),
count, stream);
222 size_t size = value.size();
223 fwrite(&
size,
sizeof(
size_t), 1, stream);
224 fwrite(&value[0],
sizeof(T),
size, stream);
230 size_t read_cnt = fread(&value,
sizeof(value),
count, stream);
231 if (read_cnt !=
count) {
232 throw std::runtime_error(
"Cannot read from file");
241 size_t read_cnt = fread(&
size,
sizeof(
size_t), 1, stream);
243 throw std::runtime_error(
"Cannot read from file");
246 read_cnt = fread(&value[0],
sizeof(T),
size, stream);
247 if (read_cnt!=
size) {
248 throw std::runtime_error(
"Cannot read from file");
262 template<
class T,
class DataSource,
typename _DistanceType = T>
270 L1_Adaptor(
const DataSource &_data_source) : data_source(_data_source) { }
275 const T* last = a +
size;
276 const T* lastgroup = last - 3;
280 while (a < lastgroup) {
281 const DistanceType diff0 = std::abs(a[0] - data_source.kdtree_get_pt(b_idx,d++));
282 const DistanceType diff1 = std::abs(a[1] - data_source.kdtree_get_pt(b_idx,d++));
283 const DistanceType diff2 = std::abs(a[2] - data_source.kdtree_get_pt(b_idx,d++));
284 const DistanceType diff3 = std::abs(a[3] - data_source.kdtree_get_pt(b_idx,d++));
285 result += diff0 + diff1 + diff2 + diff3;
287 if ((worst_dist>0)&&(result>worst_dist)) {
293 result += std::abs( *a++ - data_source.kdtree_get_pt(b_idx,d++) );
298 template <
typename U,
typename V>
301 return std::abs(a-b);
310 template<
class T,
class DataSource,
typename _DistanceType = T>
318 L2_Adaptor(
const DataSource &_data_source) : data_source(_data_source) { }
323 const T* last = a +
size;
324 const T* lastgroup = last - 3;
328 while (a < lastgroup) {
329 const DistanceType diff0 = a[0] - data_source.kdtree_get_pt(b_idx,d++);
330 const DistanceType diff1 = a[1] - data_source.kdtree_get_pt(b_idx,d++);
331 const DistanceType diff2 = a[2] - data_source.kdtree_get_pt(b_idx,d++);
332 const DistanceType diff3 = a[3] - data_source.kdtree_get_pt(b_idx,d++);
333 result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
335 if ((worst_dist>0)&&(result>worst_dist)) {
341 const DistanceType diff0 = *a++ - data_source.kdtree_get_pt(b_idx,d++);
342 result += diff0 * diff0;
347 template <
typename U,
typename V>
359 template<
class T,
class DataSource,
typename _DistanceType = T>
370 return data_source.kdtree_distance(a,b_idx,
size);
373 template <
typename U,
typename V>
382 template<
class T,
class DataSource>
389 template<
class T,
class DataSource>
396 template<
class T,
class DataSource>
411 leaf_max_size(_leaf_max_size)
421 SearchParams(
int checks_IGNORED_ = 32,
float eps_ = 0,
bool sorted_ =
true ) :
422 checks(checks_IGNORED_), eps(eps_), sorted(sorted_) {}
441 template <
typename T>
444 T* mem =
static_cast<T*
>( ::malloc(
sizeof(T)*
count));
508 while (base != NULL) {
509 void *prev = *(
static_cast<void**
>( base));
531 if (
size > remaining) {
533 wastedMemory += remaining;
540 void* m = ::malloc(blocksize);
542 fprintf(stderr,
"Failed to allocate memory.\n");
547 static_cast<void**
>(m)[0] = base;
553 remaining = blocksize -
sizeof(
void*) - shift;
554 loc = (
static_cast<char*
>(m) +
sizeof(
void*) + shift);
557 loc =
static_cast<char*
>(loc) +
size;
572 template <
typename T>
575 T* mem =
static_cast<T*
>(this->malloc(
sizeof(T)*
count));
611 template <
typename T, std::
size_t N>
633 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
636 #elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310)
665 static bool empty() {
return false; }
667 enum { static_size = N };
669 inline void resize(
const size_t nElements) {
if (nElements!=N)
throw std::logic_error(
"Try to change the size of a CArray."); }
673 const T*
data()
const {
return elems; }
682 inline void assign (
const T& value) {
for (
size_t i=0;i<N;i++) elems[i]=value; }
684 void assign (
const size_t n,
const T& value) { assert(N==n);
for (
size_t i=0;i<N;i++) elems[i]=value; }
693 template <
int DIM,
typename T>
699 template <
typename T>
744 template <
typename Distance,
class DatasetAdaptor,
int DIM = -1,
typename IndexType =
size_t>
837 dataset(inputData), index_params(params), root_node(NULL),
distance(inputData)
839 m_size = dataset.kdtree_get_point_count();
840 m_size_at_index_build = m_size;
841 dim = dimensionality;
843 m_leaf_max_size = params.leaf_max_size;
857 m_size_at_index_build = 0;
867 m_size_at_index_build = m_size;
868 if(m_size == 0)
return;
869 computeBoundingBox(root_bbox);
870 root_node = divideTree(0, m_size, root_bbox );
874 size_t size()
const {
return m_size; }
878 return static_cast<size_t>(DIM>0 ? DIM : dim);
905 template <
typename RESULTSET>
912 throw std::runtime_error(
"[nanoflann] findNeighbors() called before building the index.");
913 float epsError = 1+searchParams.
eps;
916 dists.assign((DIM>0 ? DIM : dim) ,0);
918 searchLevel(result, vec, root_node, distsq,
dists, epsError);
919 return result.full();
933 resultSet.
init(out_indices, out_distances_sq);
935 return resultSet.
size();
953 const size_t nFound = radiusSearchCustomCallback(query_point,resultSet,searchParams);
964 template <
class SEARCH_CALLBACK>
967 this->findNeighbors(resultSet, query_point, searchParams);
968 return resultSet.size();
978 m_size = dataset.kdtree_get_point_count();
979 if (vind.size()!=m_size) vind.resize(m_size);
980 for (
size_t i = 0; i < m_size; i++) vind[i] = i;
985 return dataset.kdtree_get_pt(idx,component);
993 save_tree(stream, tree->
child1);
996 save_tree(stream, tree->
child2);
1005 if (tree->
child1!=NULL) {
1006 load_tree(stream, tree->
child1);
1008 if (tree->
child2!=NULL) {
1009 load_tree(stream, tree->
child2);
1016 bbox.
resize((DIM>0 ? DIM : dim));
1017 if (dataset.kdtree_get_bbox(bbox))
1023 const size_t N = dataset.kdtree_get_point_count();
1024 if (!N)
throw std::runtime_error(
"[nanoflann] computeBoundingBox() called but no data points found.");
1025 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1027 bbox[i].high = dataset_get(0,i);
1029 for (
size_t k=1; k<N; ++k) {
1030 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1031 if (dataset_get(k,i)<bbox[i].low) bbox[i].low = dataset_get(k,i);
1032 if (dataset_get(k,i)>bbox[i].high) bbox[i].high = dataset_get(k,i);
1051 if ( (right-left) <=
static_cast<IndexType
>(m_leaf_max_size) ) {
1057 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1058 bbox[i].low = dataset_get(vind[left],i);
1059 bbox[i].high = dataset_get(vind[left],i);
1061 for (IndexType k=left+1; k<right; ++k) {
1062 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1063 if (bbox[i].low>dataset_get(vind[k],i)) bbox[i].low=dataset_get(vind[k],i);
1064 if (bbox[i].high<dataset_get(vind[k],i)) bbox[i].high=dataset_get(vind[k],i);
1072 middleSplit_(&vind[0]+left, right-left, idx, cutfeat, cutval, bbox);
1077 left_bbox[cutfeat].high = cutval;
1078 node->
child1 = divideTree(left, left+idx, left_bbox);
1081 right_bbox[cutfeat].low = cutval;
1082 node->
child2 = divideTree(left+idx, right, right_bbox);
1087 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1088 bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
1089 bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
1099 min_elem = dataset_get(ind[0],
element);
1100 max_elem = dataset_get(ind[0],
element);
1101 for (IndexType i=1; i<
count; ++i) {
1103 if (val<min_elem) min_elem = val;
1104 if (val>max_elem) max_elem = val;
1112 for (
int i=1; i<(DIM>0 ? DIM : dim); ++i) {
1114 if (span>max_span) {
1120 for (
int i=0; i<(DIM>0 ? DIM : dim); ++i) {
1122 if (span>(1-EPS)*max_span) {
1124 computeMinMax(ind,
count, i, min_elem, max_elem);
1126 if (spread>max_spread) {
1128 max_spread = spread;
1133 DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2;
1135 computeMinMax(ind,
count, cutfeat, min_elem, max_elem);
1137 if (split_val<min_elem) cutval = min_elem;
1138 else if (split_val>max_elem) cutval = max_elem;
1139 else cutval = split_val;
1141 IndexType lim1, lim2;
1142 planeSplit(ind,
count, cutfeat, cutval, lim1, lim2);
1144 if (lim1>
count/2) index = lim1;
1145 else if (lim2<
count/2) index = lim2;
1146 else index =
count/2;
1163 IndexType right =
count-1;
1165 while (left<=right && dataset_get(ind[left],cutfeat)<cutval) ++left;
1166 while (right && left<=right && dataset_get(ind[right],cutfeat)>=cutval) --right;
1167 if (left>right || !right)
break;
1178 while (left<=right && dataset_get(ind[left],cutfeat)<=cutval) ++left;
1179 while (right && left<=right && dataset_get(ind[right],cutfeat)>cutval) --right;
1180 if (left>right || !right)
break;
1193 for (
int i = 0; i < (DIM>0 ? DIM : dim); ++i) {
1194 if (vec[i] < root_bbox[i].low) {
1195 dists[i] =
distance.accum_dist(vec[i], root_bbox[i].low, i);
1198 if (vec[i] > root_bbox[i].high) {
1199 dists[i] =
distance.accum_dist(vec[i], root_bbox[i].high, i);
1212 template <
class RESULTSET>
1220 for (IndexType i=node->
node_type.
lr.left; i<node->node_type.lr.right; ++i) {
1221 const IndexType index = vind[i];
1223 if (dist<worst_dist) {
1224 if(!result_set.addPoint(dist,vind[i])) {
1242 if ((diff1+diff2)<0) {
1243 bestChild = node->
child1;
1244 otherChild = node->
child2;
1248 bestChild = node->
child2;
1249 otherChild = node->
child1;
1254 if(!searchLevel(result_set, vec, bestChild, mindistsq,
dists, epsError)) {
1260 mindistsq = mindistsq + cut_dist - dst;
1261 dists[idx] = cut_dist;
1262 if (mindistsq*epsError<=result_set.worstDist()) {
1263 if(!searchLevel(result_set, vec, otherChild, mindistsq,
dists, epsError)) {
1284 save_tree(stream, root_node);
1298 load_tree(stream, root_node);
1326 typedef typename MatrixType::Scalar
num_t;
1328 typedef typename Distance::template traits<num_t,self_t>::distance_t
metric_t;
1337 if (dims!=dimensionality)
throw std::runtime_error(
"Error: 'dimensionality' must match column count in data matrix");
1338 if (DIM>0 &&
static_cast<int>(dims)!=DIM)
1339 throw std::runtime_error(
"Data set dimensionality does not match the 'DIM' template argument");
1359 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
1362 resultSet.
init(out_indices, out_distances_sq);
1378 return m_data_matrix.rows();
1386 const num_t d= p1[i]-m_data_matrix.coeff(idx_p2,i);
1394 return m_data_matrix.coeff(idx,
IndexType(dim));
1400 template <
class BBOX>