picoflann.h
Go to the documentation of this file.
1 
16 #ifndef PicoFlann_H
17 #define PicoFlann_H
18 #include <vector>
19 #include <cassert>
20 #include <iostream>
21 #include <cstdint>
22 #include <limits>
23 #include <algorithm>
24 #include <cstring>
25 namespace picoflann
26 {
27 
28 
70 
120 
129 struct L2
130 {
131  template <typename ElementType, typename ElementType2, typename Adapter>
132  double compute_distance(const ElementType &elema, const ElementType2 &elemb,
133  const Adapter &adapter, int ndims, double worstDist) const
134  {
135  // compute dist
136  double sqd = 0;
137  for (int i = 0; i < ndims; i++)
138  {
139  double d = adapter(elema, i) - adapter(elemb, i);
140  sqd += d * d;
141  if (sqd > worstDist)
142  return sqd;
143  }
144  return sqd;
145  }
146 };
147 
148 template <int DIMS, typename Adapter, typename DistanceType = L2>
150 {
151 public:
155  template <typename Container>
156  inline void build(const Container &container)
157  {
158  _index.clear();
159  _index.reserve(container.size() * 2);
160  _index.dims = DIMS;
161  _index.nValues = container.size();
162  // Create root and assign all items
163  all_indices.resize(container.size());
164  for (size_t i = 0; i < container.size(); i++)
165  all_indices[i] = i;
166  if (container.size() == 0)
167  return;
168  computeBoundingBox<Container>(_index.rootBBox, 0, all_indices.size(), container);
169  _index.push_back(Node());
170  divideTree<Container>(_index, 0, 0, all_indices.size(), _index.rootBBox, container);
171  }
172 
173 
174  inline void clear()
175  {
176  _index.clear();
177  all_indices.clear();
178  }
179 
180  // saves to a stream. Note that the container is not saved!
181  inline void toStream(std::ostream &str) const;
182  // reads from an stream. Note that the container is not readed!
183  inline void fromStream(std::istream &str);
184 
185  template <typename Type, typename Container>
186  inline std::vector<std::pair<uint32_t, double> > searchKnn(const Container &container,
187  const Type &val, int nn,
188  bool sorted = true)
189  {
190  std::vector<std::pair<uint32_t, double> > res;
191  generalSearch<Type, Container>(res, container, val, -1, sorted, nn);
192  return res;
193  }
194 
195 
196  template <typename Type, typename Container>
197  inline std::vector<std::pair<uint32_t, double> > radiusSearch(const Container &container,
198  const Type &val, double dist,
199  bool sorted = true,
200  int maxNN = -1) const
201  {
202  std::vector<std::pair<uint32_t, double> > res;
203  generalSearch<Type, Container>(res, container, val, dist, sorted, maxNN);
204  return res;
205  }
206 
207 
208  template <typename Type, typename Container>
209  inline void radiusSearch(std::vector<std::pair<uint32_t, double> > &res,
210  const Container &container, const Type &val, double dist,
211  bool sorted = true, int maxNN = -1)
212  {
213  generalSearch<Type, Container>(res, container, val, dist, sorted, maxNN);
214  }
215 
216 
217 
218 private:
219  struct Node
220  {
221  inline bool isLeaf() const
222  {
223  return _ileft == -1 && _iright == -1;
224  }
225  inline void setNodesInfo(uint32_t l, uint32_t r)
226  {
227  _ileft = l;
228  _iright = r;
229  }
230  double div_val;
231  uint16_t col_index; // column index of the feature vector
232  std::vector<int> idx;
233  float divhigh, divlow;
234  int64_t _ileft = -1, _iright = -1; // children
235  void toStream(std::ostream &str) const;
236  void fromStream(std::istream &str);
237  };
238 
239 
240  typedef std::vector<std::pair<double, double> > BoundingBox;
241 
242  struct Index : public std::vector<Node>
243  {
245  int dims = 0;
246  int nValues = 0; // number of elements of the set when call to build
247  inline void toStream(std::ostream &str) const;
248  inline void fromStream(std::istream &str);
249  };
250  Index _index;
251  DistanceType _distance;
252  Adapter adapter;
253  // next are only used during build
254  std::vector<uint32_t> all_indices;
255  int _maxLeafSize = 10;
256 
257 
258 
259  // temporal used during creation of the tree
260  template <typename Container>
261  void divideTree(Index &index, uint64_t nodeIdx, int startIndex, int endIndex,
262  BoundingBox &bbox, const Container &container)
263  {
264  // std::cout<<"CREATE="<<startIndex<<"-"<<endIndex<<"|";toStream(std::cout,bbox);
265  Node &currNode = index[nodeIdx];
266  int count = endIndex - startIndex;
267  assert(startIndex < endIndex);
268 
269  if (count <= _maxLeafSize)
270  {
271  currNode.idx.resize(count);
272  for (int i = 0; i < count; i++)
273  currNode.idx[i] = all_indices[startIndex + i];
274  computeBoundingBox<Container>(bbox, startIndex, endIndex, container);
275  // std::cout<<std::endl;
276  return;
277  }
278 
279 
280  currNode.setNodesInfo(index.size(), index.size() + 1);
281  index.push_back(Node());
282  int leftNode = index.size() - 1;
283  index.push_back(Node());
284  int rightNode = index.size() - 1;
285 
286 
288  if (0)
289  {
290  BoundingBox _bbox;
291  computeBoundingBox<Container>(_bbox, startIndex, endIndex, container);
292  // //get the dimension with highest distnaces
293  double max_spread = -1;
294  currNode.col_index = 0;
295  for (int i = 0; i < DIMS; i++)
296  {
297  double spread = _bbox[i].second - _bbox[i].first; // maxV[i]-minV[i];
298  if (spread > max_spread)
299  {
300  max_spread = spread;
301  currNode.col_index = i;
302  }
303  }
304  // select the split val
305  double split_val = (bbox[currNode.col_index].first + bbox[currNode.col_index].second) / 2;
306  if (split_val < _bbox[currNode.col_index].first)
307  currNode.div_val = _bbox[currNode.col_index].first;
308  else if (split_val > _bbox[currNode.col_index].second)
309  currNode.div_val = _bbox[currNode.col_index].second;
310  else
311  currNode.div_val = split_val;
312  }
313  else
314  {
316  double var[DIMS], mean[DIMS];
317  // compute the variance of the features to select the highest one
318  mean_var_calculate<Container>(startIndex, endIndex, var, mean, container);
319  currNode.col_index = 0;
320  // select element with highest variance
321  for (int i = 1; i < DIMS; i++)
322  if (var[i] > var[currNode.col_index])
323  currNode.col_index = i;
324 
325  // now sort all indices according to the selected value
326 
327  currNode.div_val = mean[currNode.col_index];
328  }
329 
330 
331 
332  // compute the variance of the features to select the highest one
333  // now sort all indices according to the selected value
334 
335  // std::cout<<" CUT FEAT="<<currNode.col_index<< " VAL="<<currNode.div_val<<std::endl;
336  int lim1, lim2;
337  planeSplit<Container>(&all_indices[startIndex], count, currNode.col_index,
338  currNode.div_val, lim1, lim2, container);
339 
340  int split_index;
341 
342  if (lim1 > count / 2)
343  split_index = lim1;
344  else if (lim2 < count / 2)
345  split_index = lim2;
346  else
347  split_index = count / 2;
348 
349  // /* If either list is empty, it means that all remaining features
350  // * are identical. Split in the middle to maintain a balanced tree.
351  // */
352  if ((lim1 == count) || (lim2 == 0))
353  split_index = count / 2;
354  // create partitions with at least minLeafSize elements
355  if (_maxLeafSize != 1)
356  if (split_index < _maxLeafSize || count - split_index < _maxLeafSize)
357  {
358  std::sort(all_indices.begin() + startIndex, all_indices.begin() + endIndex,
359  [&](const uint32_t &a, const uint32_t &b)
360  {
361  return adapter(container.at(a), currNode.col_index) <
362  adapter(container.at(b), currNode.col_index);
363  });
364  split_index = count / 2;
365  currNode.div_val =
366  adapter(container.at(all_indices[startIndex + split_index]), currNode.col_index);
367  }
368 
369 
370 
371  // currNode.div_val=_features.ptr<float>(all_indices[split_index])[currNode.col_index];
372 
373  BoundingBox left_bbox(bbox);
374  left_bbox[currNode.col_index].second = currNode.div_val;
375  divideTree<Container>(index, leftNode, startIndex, startIndex + split_index,
376  left_bbox, container);
377  left_bbox[currNode.col_index].second = currNode.div_val;
378  assert(left_bbox[currNode.col_index].second <= currNode.div_val);
379  BoundingBox right_bbox(bbox);
380  right_bbox[currNode.col_index].first = currNode.div_val;
381  divideTree<Container>(index, rightNode, startIndex + split_index, endIndex,
382  right_bbox, container);
383 
384  currNode.divlow = left_bbox[currNode.col_index].second;
385  currNode.divhigh = right_bbox[currNode.col_index].first;
386  assert(currNode.divlow <= currNode.divhigh);
387 
388  for (int i = 0; i < DIMS; ++i)
389  {
390  bbox[i].first = std::min(left_bbox[i].first, right_bbox[i].first);
391  bbox[i].second = std::max(left_bbox[i].second, right_bbox[i].second);
392  }
393  }
394 
395 
396 
397  template <typename Container>
398  void computeBoundingBox(BoundingBox &bbox, int start, int end, const Container &container)
399  {
400  bbox.resize(DIMS);
401  for (int i = 0; i < DIMS; ++i)
402  bbox[i].second = bbox[i].first = adapter(container.at(all_indices[start]), i);
403 
404  for (int k = start + 1; k < end; ++k)
405  {
406  for (int i = 0; i < DIMS; ++i)
407  {
408  float v = adapter(container.at(all_indices[k]), i);
409  if (v < bbox[i].first)
410  bbox[i].first = v;
411  if (v > bbox[i].second)
412  bbox[i].second = v;
413  }
414  }
415  }
416 
417  template <typename Container>
418  void mean_var_calculate(int startindex, int endIndex, double var[], double mean[],
419  const Container &container)
420  {
421  const int MAX_ELEM_MEAN = 100;
422  // recompute centers
423  // compute new center
424  memset(mean, 0, sizeof(double) * DIMS);
425  double sum2[DIMS];
426  memset(sum2, 0, sizeof(double) * DIMS);
427  // finish when at least MAX_ELEM_MEAN elements computed
428  int cnt = 0;
429  // std::min(MAX_ELEM_MEAN,endIndex-startindex );
430  int increment = 1;
431  if (endIndex - startindex >= 2 * MAX_ELEM_MEAN)
432  increment = (endIndex - startindex) / MAX_ELEM_MEAN;
433  for (int i = startindex; i < endIndex; i += increment)
434  {
435  for (int c = 0; c < DIMS; c++)
436  {
437  auto val = adapter(container.at(all_indices[i]), c);
438  mean[c] += val;
439  sum2[c] += val * val;
440  }
441  cnt++;
442  }
443 
444  double invcnt = 1. / double(cnt);
445  for (int c = 0; c < DIMS; c++)
446  {
447  mean[c] *= invcnt;
448  var[c] = sum2[c] * invcnt - mean[c] * mean[c];
449  }
450  }
451 
452 
462  template <typename Container>
463  void planeSplit(uint32_t *ind, int count, int cutfeat, float cutval, int &lim1,
464  int &lim2, const Container &container)
465  {
466  /* Move vector indices for left subtree to front of list. */
467  int left = 0;
468  int right = count - 1;
469  for (;;)
470  {
471  while (left <= right && adapter(container.at(ind[left]), cutfeat) < cutval)
472  ++left;
473  while (left <= right && adapter(container.at(ind[right]), cutfeat) >= cutval)
474  --right;
475  if (left > right)
476  break;
477  std::swap(ind[left], ind[right]);
478  ++left;
479  --right;
480  }
481  lim1 = left;
482  right = count - 1;
483  for (;;)
484  {
485  while (left <= right && adapter(container.at(ind[left]), cutfeat) <= cutval)
486  ++left;
487  while (left <= right && adapter(container.at(ind[right]), cutfeat) > cutval)
488  --right;
489  if (left > right)
490  break;
491  std::swap(ind[left], ind[right]);
492  ++left;
493  --right;
494  }
495  lim2 = left;
496  }
497 
498 
499  template <typename Type>
500  inline double computeInitialDistances(const Type &elem, double dists[],
501  const BoundingBox &bbox) const
502  {
503  float distsq = 0.0;
504 
505  for (int i = 0; i < DIMS; ++i)
506  {
507  double elem_i = adapter(elem, i);
508  if (elem_i < bbox[i].first)
509  {
510  auto d = elem_i - bbox[i].first;
511  dists[i] = d * d; // distance_.accum_dist(vec[i], root_bbox_[i].first, i);
512  distsq += dists[i];
513  }
514  if (elem_i > bbox[i].second)
515  {
516  auto d = elem_i - bbox[i].second;
517  dists[i] = d * d; // distance_.accum_dist(vec[i], root_bbox_[i].second, i);
518  distsq += dists[i];
519  }
520  }
521  return distsq;
522  }
523  // THe function that does the search in all exact methods
524  template <typename Type, typename Container>
525  inline void generalSearch(std::vector<std::pair<uint32_t, double> > &res,
526  const Container &container, const Type &val, double dist,
527  bool sorted = true,
528  uint32_t maxNn = std::numeric_limits<int>::max()) const
529  {
530  double dists[DIMS];
531  memset(dists, 0, sizeof(double) * DIMS);
532  res.clear();
533  ResultSet hres(res, maxNn, dist > 0 ? dist * dist : -1.f);
534  float distsq = computeInitialDistances<Type>(val, dists, _index.rootBBox);
535  searchExactLevel<Type, Container>(_index, 0, val, hres, distsq, dists, 1, container);
536  if (sorted && res.size() > 1)
537  std::sort(res.begin(), res.end(),
538  [](const std::pair<uint32_t, double> &a, const std::pair<uint32_t, double> &b)
539  { return a.second < b.second; });
540  }
541 
542  // heap having at the top the maximum element
543 
544  class ResultSet
545  {
546  public:
547  std::vector<std::pair<uint32_t, double> > &array;
548  int maxSize;
549  double maxValue = std::numeric_limits<double>::max();
550  bool radius_search = false;
551 
552  public:
553  ResultSet(std::vector<std::pair<uint32_t, double> > &data_ref,
554  uint32_t MaxSize = std::numeric_limits<uint32_t>::max(), double MaxV = -1)
555  : array(data_ref)
556  {
557  maxSize = MaxSize;
558  // set value for radius search
559  if (MaxV > 0)
560  {
561  maxValue = MaxV;
562  radius_search = true;
563  }
564  }
565 
566 
567  inline void push(const std::pair<uint32_t, double> &val)
568  {
569  if (radius_search && val.second < maxValue)
570  {
571  array.push_back(val);
572  }
573  else
574  {
575  if (array.size() >= size_t(maxSize))
576  {
577  // check if the maxium must be replaced by this
578  if (val.second < array[0].second)
579  {
580  swap(array.front(), array.back());
581  array.pop_back();
582  if (array.size() > 1)
583  up(0);
584  }
585  else
586  return;
587  }
588  array.push_back(val);
589  if (array.size() > 1)
590  down(array.size() - 1);
591  }
592  // array_size++;
593  }
594 
595  inline double worstDist() const
596  {
597  if (radius_search)
598  return maxValue; // radius search
599  else if (array.size() < size_t(maxSize))
600  return std::numeric_limits<double>::max();
601  return array[0].second;
602  }
603  inline double top() const
604  {
605  assert(!array.empty());
606  return array[0].second;
607  }
608 
609  private:
610  inline void down(size_t index)
611  {
612  if (index == 0)
613  return;
614  size_t parentIndex = (index - 1) / 2;
615  if (array[parentIndex].second < array[index].second)
616  {
617  swap(array[index], array[parentIndex]);
618  down(parentIndex);
619  }
620  }
621  inline void up(size_t index)
622  {
623  size_t leftIndex = 2 * index + 1; // vl_heap_left_child (index) ;
624  size_t rightIndex = 2 * index + 2; // vl_heap_right_child (index) ;
625 
626  /* no childer: stop */
627  if (leftIndex >= array.size())
628  return;
629 
630  /* only left childer: easy */
631  if (rightIndex >= array.size())
632  {
633  if (array[index].second < array[leftIndex].second)
634  swap(array[index], array[leftIndex]);
635  return;
636  }
637 
638  /* both childern */
639  {
640  if (array[rightIndex].second < array[leftIndex].second)
641  {
642  /* swap with left */
643  if (array[index].second < array[leftIndex].second)
644  {
645  swap(array[index], array[leftIndex]);
646  up(leftIndex);
647  }
648  }
649  else
650  {
651  /* swap with right */
652  if (array[index].second < array[rightIndex].second)
653  {
654  swap(array[index], array[rightIndex]);
655  up(rightIndex);
656  }
657  }
658  }
659  }
660  };
661 
662  template <typename Type, typename Container>
663  inline void searchExactLevel(const Index &index, int64_t nodeIdx, const Type &elem,
664  ResultSet &res, double mindistsq, double dists[],
665  double epsError, const Container &container) const
666  {
667  const Node &currNode = index[nodeIdx];
668  if (currNode.isLeaf())
669  {
670  double worstDist = res.worstDist();
671  for (size_t i = 0; i < currNode.idx.size(); i++)
672  {
673  double sqd = _distance.compute_distance(elem, container.at(currNode.idx[i]),
674  adapter, DIMS, worstDist);
675  if (sqd < worstDist)
676  {
677  res.push({ currNode.idx[i], sqd });
678  worstDist = res.worstDist();
679  }
680  }
681  }
682  else
683  {
684  double val = adapter(elem, currNode.col_index);
685  double diff1 = val - currNode.divlow;
686  double diff2 = val - currNode.divhigh;
687 
688  uint32_t bestChild;
689  uint32_t otherChild;
690  double cut_dist;
691  if ((diff1 + diff2) < 0)
692  {
693  bestChild = currNode._ileft;
694  otherChild = currNode._iright;
695  cut_dist = diff2 * diff2;
696  }
697  else
698  {
699  bestChild = currNode._iright;
700  otherChild = currNode._ileft;
701  cut_dist = diff1 * diff1;
702  }
703  /* Call recursively to search next level down. */
704  searchExactLevel<Type, Container>(index, bestChild, elem, res, mindistsq, dists,
705  epsError, container);
706 
707  float dst = dists[currNode.col_index];
708  mindistsq = mindistsq + cut_dist - dst;
709  dists[currNode.col_index] = cut_dist;
710  if (mindistsq * epsError <= res.worstDist())
711  searchExactLevel<Type, Container>(index, otherChild, elem, res, mindistsq, dists,
712  epsError, container);
713  dists[currNode.col_index] = dst;
714  }
715  }
716 };
717 template <int DIMS, typename AAdapter, typename DistanceType>
719 {
720  str.write((char *)&div_val, sizeof(div_val));
721  str.write((char *)&col_index, sizeof(col_index));
722  str.write((char *)&divhigh, sizeof(divhigh));
723  str.write((char *)&divlow, sizeof(divlow));
724  str.write((char *)&_ileft, sizeof(_ileft));
725  str.write((char *)&_iright, sizeof(_iright));
726  uint64_t s = idx.size();
727  str.write((char *)&s, sizeof(s));
728  str.write((char *)&idx[0], sizeof(idx[0]) * idx.size());
729 }
730 
731 template <int DIMS, typename AAdapter, typename DistanceType>
733 {
734  str.read((char *)&div_val, sizeof(div_val));
735  str.read((char *)&col_index, sizeof(col_index));
736  str.read((char *)&divhigh, sizeof(divhigh));
737  str.read((char *)&divlow, sizeof(divlow));
738  str.read((char *)&_ileft, sizeof(_ileft));
739  str.read((char *)&_iright, sizeof(_iright));
740  uint64_t s;
741  str.read((char *)&s, sizeof(s));
742  idx.resize(s);
743  str.read((char *)&idx[0], sizeof(idx[0]) * idx.size());
744 }
745 
746 template <int DIMS, typename AAdapter, typename DistanceType>
748 {
749  str.write((char *)&dims, sizeof(dims));
750  str.write((char *)&rootBBox[0], sizeof(rootBBox[0]) * dims);
751  str.write((char *)&nValues, sizeof(nValues));
752 
753  uint64_t s = std::vector<Node>::size();
754  str.write((char *)&s, sizeof(s));
755  for (size_t i = 0; i < std::vector<Node>::size(); i++)
756  std::vector<Node>::at(i).toStream(str);
757 }
758 
759 template <int DIMS, typename AAdapter, typename DistanceType>
761 {
762  str.read((char *)&dims, sizeof(dims));
763  rootBBox.resize(dims);
764  str.read((char *)&rootBBox[0], sizeof(rootBBox[0]) * dims);
765  str.read((char *)&nValues, sizeof(nValues));
766 
767 
768  uint64_t s;
769  ;
770  str.read((char *)&s, sizeof(s));
771  std::vector<Node>::resize(s);
772  for (size_t i = 0; i < std::vector<Node>::size(); i++)
773  std::vector<Node>::at(i).fromStream(str);
774  if (dims != DIMS && this->size() != 0 && nValues != 0)
775  throw std::runtime_error(
776  "Number of dimensions of the index in the stream is different from the number of dimensions of this");
777 }
778 
779 template <int DIMS, typename AAdapter, typename DistanceType>
781 {
782  _index.toStream(str);
783 }
784 
785 template <int DIMS, typename AAdapter, typename DistanceType>
787 {
788  _index.fromStream(str);
789 }
790 } // namespace picoflann
791 
792 #endif
picoflann::KdTreeIndex::Index::nValues
int nValues
Definition: picoflann.h:246
picoflann::KdTreeIndex::Index::dims
int dims
Definition: picoflann.h:245
picoflann::KdTreeIndex::ResultSet::array
std::vector< std::pair< uint32_t, double > > & array
Definition: picoflann.h:547
picoflann::KdTreeIndex::Node::isLeaf
bool isLeaf() const
Definition: picoflann.h:221
picoflann::KdTreeIndex::radiusSearch
void radiusSearch(std::vector< std::pair< uint32_t, double > > &res, const Container &container, const Type &val, double dist, bool sorted=true, int maxNN=-1)
Definition: picoflann.h:209
picoflann::KdTreeIndex::computeBoundingBox
void computeBoundingBox(BoundingBox &bbox, int start, int end, const Container &container)
Definition: picoflann.h:398
picoflann::KdTreeIndex::Node
Definition: picoflann.h:219
picoflann
Definition: picoflann.h:25
picoflann::KdTreeIndex::toStream
void toStream(std::ostream &str) const
Definition: picoflann.h:780
picoflann::KdTreeIndex::mean_var_calculate
void mean_var_calculate(int startindex, int endIndex, double var[], double mean[], const Container &container)
Definition: picoflann.h:418
picoflann::KdTreeIndex::ResultSet::top
double top() const
Definition: picoflann.h:603
picoflann::KdTreeIndex::all_indices
std::vector< uint32_t > all_indices
Definition: picoflann.h:254
picoflann::KdTreeIndex::Node::fromStream
void fromStream(std::istream &str)
Definition: picoflann.h:732
picoflann::KdTreeIndex::Index::toStream
void toStream(std::ostream &str) const
Definition: picoflann.h:747
picoflann::KdTreeIndex::radiusSearch
std::vector< std::pair< uint32_t, double > > radiusSearch(const Container &container, const Type &val, double dist, bool sorted=true, int maxNN=-1) const
Definition: picoflann.h:197
picoflann::KdTreeIndex::Index::fromStream
void fromStream(std::istream &str)
Definition: picoflann.h:760
picoflann::KdTreeIndex::ResultSet
Definition: picoflann.h:544
picoflann::KdTreeIndex::ResultSet::maxValue
double maxValue
Definition: picoflann.h:549
picoflann::KdTreeIndex::ResultSet::ResultSet
ResultSet(std::vector< std::pair< uint32_t, double > > &data_ref, uint32_t MaxSize=std::numeric_limits< uint32_t >::max(), double MaxV=-1)
Definition: picoflann.h:553
f
f
picoflann::KdTreeIndex::build
void build(const Container &container)
Definition: picoflann.h:156
picoflann::KdTreeIndex::Node::idx
std::vector< int > idx
Definition: picoflann.h:232
picoflann::KdTreeIndex::ResultSet::push
void push(const std::pair< uint32_t, double > &val)
Definition: picoflann.h:567
picoflann::KdTreeIndex::generalSearch
void generalSearch(std::vector< std::pair< uint32_t, double > > &res, const Container &container, const Type &val, double dist, bool sorted=true, uint32_t maxNn=std::numeric_limits< int >::max()) const
Definition: picoflann.h:525
picoflann::KdTreeIndex::Node::col_index
uint16_t col_index
Definition: picoflann.h:231
picoflann::KdTreeIndex::Node::div_val
double div_val
Definition: picoflann.h:230
picoflann::KdTreeIndex::Index
Definition: picoflann.h:242
picoflann::KdTreeIndex::Index::rootBBox
BoundingBox rootBBox
Definition: picoflann.h:244
picoflann::KdTreeIndex::Node::_iright
int64_t _iright
Definition: picoflann.h:234
picoflann::KdTreeIndex::Node::toStream
void toStream(std::ostream &str) const
Definition: picoflann.h:718
picoflann::KdTreeIndex::Node::divlow
float divlow
Definition: picoflann.h:233
d
d
picoflann::KdTreeIndex::ResultSet::maxSize
int maxSize
Definition: picoflann.h:548
picoflann::KdTreeIndex::_distance
DistanceType _distance
Definition: picoflann.h:251
picoflann::KdTreeIndex::ResultSet::up
void up(size_t index)
Definition: picoflann.h:621
picoflann::KdTreeIndex::Node::divhigh
float divhigh
Definition: picoflann.h:233
picoflann::L2
The KdTreeIndex class is the simplest an minimal method to use kdtrees. You only must define an adapt...
Definition: picoflann.h:129
picoflann::KdTreeIndex::BoundingBox
std::vector< std::pair< double, double > > BoundingBox
Definition: picoflann.h:240
picoflann::KdTreeIndex::searchKnn
std::vector< std::pair< uint32_t, double > > searchKnn(const Container &container, const Type &val, int nn, bool sorted=true)
Definition: picoflann.h:186
picoflann::KdTreeIndex::clear
void clear()
Definition: picoflann.h:174
picoflann::KdTreeIndex::fromStream
void fromStream(std::istream &str)
Definition: picoflann.h:786
picoflann::KdTreeIndex::ResultSet::down
void down(size_t index)
Definition: picoflann.h:610
picoflann::KdTreeIndex::ResultSet::radius_search
bool radius_search
Definition: picoflann.h:550
picoflann::KdTreeIndex
Definition: picoflann.h:149
picoflann::KdTreeIndex::adapter
Adapter adapter
Definition: picoflann.h:252
picoflann::KdTreeIndex::computeInitialDistances
double computeInitialDistances(const Type &elem, double dists[], const BoundingBox &bbox) const
Definition: picoflann.h:500
picoflann::KdTreeIndex::searchExactLevel
void searchExactLevel(const Index &index, int64_t nodeIdx, const Type &elem, ResultSet &res, double mindistsq, double dists[], double epsError, const Container &container) const
Definition: picoflann.h:663
picoflann::KdTreeIndex::ResultSet::worstDist
double worstDist() const
Definition: picoflann.h:595
picoflann::KdTreeIndex::_maxLeafSize
int _maxLeafSize
Definition: picoflann.h:255
picoflann::KdTreeIndex::_index
Index _index
Definition: picoflann.h:250
picoflann::KdTreeIndex::Node::setNodesInfo
void setNodesInfo(uint32_t l, uint32_t r)
Definition: picoflann.h:225
picoflann::L2::compute_distance
double compute_distance(const ElementType &elema, const ElementType2 &elemb, const Adapter &adapter, int ndims, double worstDist) const
Definition: picoflann.h:132
picoflann::KdTreeIndex::Node::_ileft
int64_t _ileft
Definition: picoflann.h:234
picoflann::KdTreeIndex::planeSplit
void planeSplit(uint32_t *ind, int count, int cutfeat, float cutval, int &lim1, int &lim2, const Container &container)
Definition: picoflann.h:463
picoflann::KdTreeIndex::divideTree
void divideTree(Index &index, uint64_t nodeIdx, int startIndex, int endIndex, BoundingBox &bbox, const Container &container)
Definition: picoflann.h:261


aruco
Author(s): Rafael Muñoz Salinas , Bence Magyar
autogenerated on Sat Sep 23 2023 02:26:45