KdTree.hpp
Go to the documentation of this file.
1 
2 namespace GfxTL
3 {
4  template <class ValueT, class BaseT>
6  {
7  memset(&_children, NULL, sizeof(_children));
8  }
9 
10  template <class ValueT, class BaseT>
11  KdTreeCell<ValueT, BaseT>::KdTreeCell(const KdTreeCell<ValueT, BaseT>& cell) :
12  BaseT(cell), _split(cell._split), _box(cell._box)
13  {
14  if (cell._children[0])
15  {
16  _children[0] = new KdTreeCell<ValueT, BaseT>(*cell._children[0]);
17  }
18  else
19  {
20  _children[0] = NULL;
21  }
22  if (cell._children[1])
23  {
24  _children[1] = new KdTreeCell<ValueT, BaseT>(*cell._children[1]);
25  }
26  else
27  {
28  _children[1] = NULL;
29  }
30  }
31 
32  template <class ValueT, class BaseT>
34  {
35  for (unsigned int i = 0; i < 2; ++i)
36  if (_children[i])
37  {
38  delete _children[i];
39  }
40  }
41 
42  template <class ValueT, class BaseT>
43  const KdTreeCell<ValueT, BaseT>*
45  {
46  return _children[index];
47  }
48 
49  template <class ValueT, class BaseT>
50  KdTreeCell<ValueT, BaseT>*
52  {
53  return _children[index];
54  }
55 
56  template <class ValueT, class BaseT>
57  void
58  KdTreeCell<ValueT, BaseT>::Child(unsigned int index, ThisType* child)
59  {
60  _children[index] = child;
61  }
62 
63  template <class ValueT, class BaseT>
64  const typename KdTreeCell<ValueT, BaseT>::SplitterType&
66  {
67  return _split;
68  }
69 
70  template <class ValueT, class BaseT>
71  const typename KdTreeCell<ValueT, BaseT>::BoxType&
72  KdTreeCell<ValueT, BaseT>::Box() const
73  {
74  return _box;
75  }
76 
77  template <class Strategies>
78  void
80  {
81  Clear();
82 
83  CellType* root = new CellType;
84  CellRange range;
85  RootRange(&range);
86  root->_box.Infinite();
87  Root(root);
88  Init(range, NULL, root);
89 
90  typedef std::pair<CellType*, CellRange> Pair;
91  std::deque<Pair> stack;
92  stack.push_back(Pair(root, range));
93  while (stack.size())
94  {
95  Pair p = stack.back();
96  stack.pop_back();
97  if (ShouldSubdivide(p.second))
98  {
99  Subdivide(p.first, p.second);
100  if (IsLeaf(*p.first)) // couldn't subdivide?
101  {
102  continue;
103  }
104  for (unsigned int i = 0; i < CellType::NChildren; ++i)
105  {
106  Range(*p.first, p.second, i, &range);
107  //Init(range, p.first, (*p.first)[i]);
108  stack.push_back(Pair((*p.first)[i], range));
109  }
110  }
111  }
112  }
113 
114  template <class Strategies>
115  void
116  KdTree<Strategies>::Insert(DereferencedType s)
117  {
118  CellType* cell = Root();
119  CellRange range;
120  RootRange(&range);
121  if (!cell)
122  {
123  cell = new CellType;
124  Root(cell);
125  Init(range, NULL, cell);
126  }
127  Insert(cell, range, s);
128  }
129 
130  template <class Strategies>
131  template <class ContainerT>
132  void
134  unsigned int k,
135  ContainerT* neighbors,
136  ScalarType* dist) const
137  {
138  *dist = std::numeric_limits<ScalarType>::infinity();
139  neighbors->resize(0);
140  if (!Root())
141  {
142  return;
143  }
144  AABox<PointType> rootBox;
145  //rootBox.Infinite();
146  CellRange range;
147  RootRange(&range);
148  neighbors->reserve(k + 1);
149  NearestNeighbors(*Root(), range, rootBox, p, k, neighbors, dist);
150  if (*dist < std::numeric_limits<ScalarType>::infinity())
151  {
152  *dist = std::sqrt(*dist);
153  }
154  }
155 
156  template <class Strategies>
157  template <template <class> class ContainerT>
158  void
160  unsigned int k,
161  LimitedHeap<NN, ContainerT>* neighbors,
162  ScalarType* dist) const
163  {
164  *dist = std::numeric_limits<ScalarType>::infinity();
165  neighbors->resize(0);
166  if (!Root())
167  {
168  return;
169  }
170  neighbors->Limit(k);
171  CellRange range;
172  RootRange(&range);
173  NearestNeighborsL(*Root(), range, p, k, neighbors, dist);
174  //neighbors->sort_heap();
175  //std::sort_heap(neighbors->begin(), neighbors->end());
176  //if(*dist < std::numeric_limits< ScalarType >::infinity())
177  // *dist = std::sqrt(*dist);
178  }
179 
180  template <class Strategies>
181  template <class ContainerT>
182  void
184  unsigned int k,
185  ScalarType eps,
186  ContainerT* neighbors,
187  ScalarType* sqrDist) const
188  {
189  *sqrDist = std::numeric_limits<ScalarType>::infinity();
190  neighbors->resize(0);
191  if (!Root())
192  {
193  return;
194  }
195  AABox<PointType> rootBox;
196  //rootBox.Infinite();
197  CellRange range;
198  RootRange(&range);
199  neighbors->reserve(k + 1);
200  eps = 1 - eps;
201  ApproximateNearestNeighbors(*Root(), range, rootBox, p, k, eps * eps, neighbors, sqrDist);
202  //if(*dist < std::numeric_limits< ScalarType >::infinity())
203  // *dist = std::sqrt(*dist);
204  }
205 
206  template <class Strategies>
207  template <class ContainerT>
208  void
210  ScalarType sqrRadius,
211  ContainerT* points) const
212  {
213  points->resize(0);
214  if (!Root())
215  {
216  return;
217  }
218  CellRange range;
219  RootRange(&range);
220  PointsInSphere(*Root(), range, p, sqrRadius, points);
221  }
222 
223  template <class Strategies>
224  bool
226  {
227  if (!Root())
228  {
229  return false;
230  }
231  CellRange range;
232  RootRange(&range);
233  return Contains(*Root(), range, p, d);
234  }
235 
236  template <class Strategies>
237  bool
238  KdTree<Strategies>::ShouldSubdivide(CellRange range) const
239  {
240  return range.second - range.first > 10;
241  }
242 
243  template <class Strategies>
244  void
245  KdTree<Strategies>::Subdivide(CellType* cell, CellRange range)
246  {
247  PointType pmin = cell->_box.Min(), pmax = cell->_box.Max();
248  /*pmax = pmin = at(Dereference(range.first));
249  for(HandleType i = range.first + 1; i < range.second; ++i)
250  {
251  const PointType p = at(Dereference(i));
252  for(unsigned int j = 0; j < Dim; ++j)
253  {
254  if(pmin[j] > p[j])
255  pmin[j] = p[j];
256  else if(pmax[j] < p[j])
257  pmax[j] = p[j];
258  }
259  }*/
260 
261  PointType pdiff = pmax - pmin;
262  unsigned int axis = 0;
263  ScalarType length = pdiff[0];
264  for (unsigned int j = 1; j < Dim; ++j)
265  {
266  if (pdiff[j] > length)
267  {
268  axis = j;
269  length = pdiff[j];
270  }
271  }
272 
273  ScalarType split = (pmax[axis] + pmin[axis]) / 2;
274 
275  cell->_split.Set(axis, split);
276 
277  CellType *left, *right;
278  left = new CellType;
279  right = new CellType;
280  Split(cell->_split, range, left, right);
281  if (left->Size() == cell->Size() || right->Size() == cell->Size())
282  {
283  delete left;
284  delete right;
285  return;
286  }
287  //cell->_box.Split(cell->_split.Axis(), cell->_split.Value(),
288  // &left->_box, &right->_box);
289  cell->Child(0, left);
290  cell->Child(1, right);
291  CellRange childRange;
292  Range(*cell, range, 0, &childRange);
293  Init(childRange, cell, left);
294  Range(*cell, range, 1, &childRange);
295  Init(childRange, cell, right);
296  // refine split value
297  cell->_split.Value(
298  (right->Box().Min()[cell->_split.Axis()] + left->Box().Max()[cell->_split.Axis()]) / 2);
299  }
300 
301  template <class Strategies>
302  void
303  KdTree<Strategies>::Insert(CellType* cell, CellRange range, DereferencedType s)
304  {
305  cell->_box += at(s);
306  if (IsLeaf(*cell))
307  {
308  BaseType::Insert(range, s);
309  if (ShouldSubdivide(range))
310  {
311  Subdivide(cell, range);
312  }
313  return;
314  }
315  bool left;
316  BaseType::SplitAndInsert(cell->Split(), range, s, (*cell)[0], (*cell)[1], &left);
317  if (left)
318  {
319  CellRange lr;
320  Range(*cell, range, 0, &lr);
321  Insert((*cell)[0], lr, s);
322  }
323  else
324  {
325  CellRange rr;
326  Range(*cell, range, 1, &rr);
327  Insert((*cell)[1], rr, s);
328  }
329  }
330 
331  template <class Strategies>
332  template <class ContainerT>
333  void
335  CellRange range,
336  const AABox<PointType>& box,
337  const PointType& p,
338  unsigned int k,
339  ContainerT* neighbors,
340  ScalarType* dist2) const
341  {
342  if (IsLeaf(cell))
343  {
344  HandleType i = range.first, iend = range.second;
345  if (neighbors->size() + cell.Size() <= k)
346  {
347  for (; i != iend; ++i)
348  {
349  DereferencedType deref = Dereference(i);
350  PointType diff = at(deref);
351  diff -= p;
352  ScalarType d2 = diff * diff;
353  neighbors->push_back(NN(deref, d2));
354  }
355  std::sort(neighbors->begin(), neighbors->end());
356  *dist2 = neighbors->back().sqrDist;
357  return;
358  }
359  // let's find nearest neighbors from points within the cell
360  for (; i != iend; ++i)
361  {
362  DereferencedType deref = Dereference(i);
363  PointType diff = at(deref);
364  diff -= p;
365  ScalarType d2 = diff * diff;
366  if (neighbors->size() < k || d2 <= *dist2)
367  {
368  SortedNearestNeighborInsert(NN(deref, d2), k, neighbors);
369  *dist2 = neighbors->back().sqrDist;
370  }
371  }
372  return;
373  }
374  // descent into subtree containing p
375  unsigned int nearerChild, fartherChild;
376  if (cell.Split()(p) <= 0)
377  {
378  nearerChild = 0;
379  fartherChild = 1;
380  }
381  else
382  {
383  nearerChild = 1;
384  fartherChild = 0;
385  }
386  /*AABox< PointType > subBoxes[2];
387  box.Split(cell.Split().Axis(), cell.Split().Value(),
388  &subBoxes[0], &subBoxes[1]);*/
389 
390  CellRange childRange;
391  if (neighbors->size() < k || Intersect(cell[nearerChild]->Box(), p, *dist2))
392  {
393  Range(cell, range, nearerChild, &childRange);
394  NearestNeighbors(*cell[nearerChild],
395  childRange,
396  box /*subBoxes[nearerChild]*/,
397  p,
398  k,
399  neighbors,
400  dist2);
401  }
402 
403  // check if closer neighbor could be in other child
404  if (neighbors->size() < k ||
405  Intersect(cell[fartherChild]->Box() /*subBoxes[fartherChild]*/, p, *dist2))
406  {
407  Range(cell, range, fartherChild, &childRange);
408  NearestNeighbors(*cell[fartherChild],
409  childRange,
410  box /*subBoxes[fartherChild]*/,
411  p,
412  k,
413  neighbors,
414  dist2);
415  }
416  }
417 
418  template <class Strategies>
419  template <template <class> class ContainerT>
420  void
421  KdTree<Strategies>::NearestNeighborsL(const CellType& cell,
422  const CellRange& range,
423  const PointType& p,
424  unsigned int k,
425  LimitedHeap<NN, ContainerT>* neighbors,
426  ScalarType* dist2) const
427  {
428  if (IsLeaf(cell))
429  {
430  HandleType i = range.first, iend = range.second;
431  DereferencedType deref;
432  if (neighbors->size() + cell.Size() <= k)
433  {
434  for (; i != iend; ++i)
435  {
436  deref = Dereference(i);
437  neighbors->push_back(NN(deref, p.SqrDistance(at(deref).Point())));
438  }
439  neighbors->MakeHeap();
440  *dist2 = neighbors->front().sqrDist;
441  return;
442  }
443  // let's find nearest neighbors from points within the cell
444  for (; i != iend; ++i)
445  {
446  deref = Dereference(i);
447  neighbors->PushHeap(NN(deref, p.SqrDistance(at(deref).Point())));
448  *dist2 = neighbors->front().sqrDist;
449  }
450  return;
451  }
452  // descent into subtree containing p
453  unsigned int nearerChild, fartherChild;
454  const CellType *nChild, *fChild;
455  ScalarType splitDist = cell._split(p);
456  if (splitDist <= 0)
457  {
458  nearerChild = 0;
459  fartherChild = 1;
460  nChild = cell[0];
461  fChild = cell[1];
462  }
463  else
464  {
465  nearerChild = 1;
466  fartherChild = 0;
467  nChild = cell[1];
468  fChild = cell[0];
469  }
470 
471  CellRange childRange;
472  //if(neighbors->size() < k || Intersect(p, *dist2, nChild->_box.Min(),
473  // nChild->_box.Max()))
474  //{
475  Range(cell, range, nearerChild, &childRange);
476  NearestNeighborsL(*nChild, childRange, p, k, neighbors, dist2);
477  //}
478 
479  // check if closer neighbor could be in other child
480  if (neighbors->size() < k || (splitDist * splitDist < *dist2 &&
481  Intersect(p, *dist2, fChild->_box.Min(), fChild->_box.Max())))
482  {
483  Range(cell, range, fartherChild, &childRange);
484  NearestNeighborsL(*fChild, childRange, p, k, neighbors, dist2);
485  }
486  }
487 
488  template <class Strategies>
489  template <class ContainerT>
490  void
492  CellRange range,
493  const AABox<PointType>& box,
494  const PointType& p,
495  unsigned int k,
496  ScalarType eps,
497  ContainerT* neighbors,
498  ScalarType* sqrDist) const
499  {
500  if (IsLeaf(cell))
501  {
502  if (neighbors->size() + cell.Size() <= k)
503  {
504  for (HandleType i = range.first; i != range.second; ++i)
505  {
506  DereferencedType deref = Dereference(i);
507  PointType diff = at(deref);
508  diff -= p;
509  ScalarType d2 = diff * diff;
510  neighbors->push_back(NN(deref, d2));
511  }
512  std::sort(neighbors->begin(), neighbors->end());
513  *sqrDist = neighbors->back().sqrDist;
514  return;
515  }
516  // let's find nearest neighbors from points within the cell
517  for (HandleType i = range.first; i != range.second; ++i)
518  {
519  DereferencedType deref = Dereference(i);
520  PointType diff = at(deref);
521  diff -= p;
522  ScalarType d2 = diff * diff;
523  if (neighbors->size() < k || d2 <= *sqrDist)
524  {
525  SortedNearestNeighborInsert(NN(deref, d2), k, neighbors);
526  *sqrDist = neighbors->back().sqrDist;
527  }
528  }
529  return;
530  }
531  // descent into subtree containing p
532  unsigned int nearerChild, fartherChild;
533  if (cell.Split()(p) <= 0)
534  {
535  nearerChild = 0;
536  fartherChild = 1;
537  }
538  else
539  {
540  nearerChild = 1;
541  fartherChild = 0;
542  }
543  /*AABox< PointType > subBoxes[2];
544  box.Split(cell.Split().Axis(), cell.Split().Value(),
545  &subBoxes[0], &subBoxes[1]);*/
546 
547  CellRange childRange;
548  if (neighbors->size() < k || Intersect(cell[nearerChild]->Box(), p, eps * (*sqrDist)))
549  {
550  Range(cell, range, nearerChild, &childRange);
551  ApproximateNearestNeighbors(*cell[nearerChild],
552  childRange,
553  box /*subBoxes[nearerChild]*/,
554  p,
555  k,
556  eps,
557  neighbors,
558  sqrDist);
559  }
560 
561  // check if closer neighbor could be in other child
562  if (neighbors->size() < k ||
563  Intersect(cell[fartherChild]->Box() /*subBoxes[fartherChild]*/, p, eps * (*sqrDist)))
564  {
565  Range(cell, range, fartherChild, &childRange);
566  ApproximateNearestNeighbors(*cell[fartherChild],
567  childRange,
568  box /*subBoxes[fartherChild]*/,
569  p,
570  k,
571  eps,
572  neighbors,
573  sqrDist);
574  }
575  }
576 
577  template <class Strategies>
578  template <class ContainerT>
579  void
580  KdTree<Strategies>::PointsInSphere(const CellType& cell,
581  const CellRange& range,
582  const PointType& p,
583  ScalarType sqrRadius,
584  ContainerT* points) const
585  {
586  if (IsLeaf(cell))
587  {
588  for (HandleType i = range.first; i < range.second; ++i)
589  {
590  DereferencedType deref = Dereference(i);
591  ScalarType sqrDist = p.SqrDistance(at(deref));
592  if (sqrDist <= sqrRadius)
593  {
594  points->push_back(NN(deref, sqrDist));
595  }
596  }
597  }
598  else
599  {
600  CellRange childRange;
601  if (Intersect(p, sqrRadius, cell[0]->_box.Min(), cell[0]->_box.Max()))
602  {
603  Range(cell, range, 0, &childRange);
604  PointsInSphere(*(cell[0]), childRange, p, sqrRadius, points);
605  }
606  if (Intersect(p, sqrRadius, cell[1]->_box.Min(), cell[1]->_box.Max()))
607  {
608  Range(cell, range, 1, &childRange);
609  PointsInSphere(*(cell[1]), childRange, p, sqrRadius, points);
610  }
611  }
612  }
613 
614  template <class Strategies>
615  bool
617  const CellRange range,
618  const PointType& p,
619  DereferencedType* d) const
620  {
621  if (IsLeaf(cell))
622  {
623  for (HandleType i = range.first; i < range.second; ++i)
624  {
625  DereferencedType deref = Dereference(i);
626  if (p == at(deref))
627  {
628  *d = deref;
629  return true;
630  }
631  }
632  return false;
633  }
634  // descent into subtree containing p
635  unsigned int nearerChild = cell.Split()(p) <= 0 ? 0 : 1;
636  CellRange childRange;
637  Range(cell, range, nearerChild, &childRange);
638  return Contains(*cell[nearerChild], childRange, p, d);
639  }
640 
641  template <class Strategies>
642  void
643  KdTree<Strategies>::Init(const CellRange& range, const CellType*, CellType* cell)
644  {
645  PointType pmin, pmax;
646  pmax = pmin = at(Dereference(range.first));
647  for (HandleType i = range.first + 1; i != range.second; ++i)
648  {
649  const PointType p = at(Dereference(i));
650  for (unsigned int j = 0; j < Dim; ++j)
651  {
652  if (pmin[j] > p[j])
653  {
654  pmin[j] = p[j];
655  }
656  else if (pmax[j] < p[j])
657  {
658  pmax[j] = p[j];
659  }
660  }
661  }
662  cell->_box.Min() = pmin;
663  cell->_box.Max() = pmax;
664  }
665 }; // namespace GfxTL
GfxTL::KdTreeCell::operator[]
ThisType & operator[](unsigned int i)
Definition: KdTree.h:50
visionx::armem::pointcloud::PointType
PointType
Definition: constants.h:78
index
uint8_t index
Definition: EtherCATFrame.h:59
GfxTL::KdTree
Definition: KdTree.h:169
armarx::Contains
bool Contains(const ContainerType &container, const ElementType &searchElement)
Definition: algorithm.h:330
armarx::Split
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelperTemplates.h:36
GfxTL::KdTreeCell::Child
void Child(unsigned int i, ThisType *cell)
Definition: KdTree.h:62
GfxTL::NN::sqrDist
ScalarType sqrDist
Definition: NearestNeighbor.h:12
GfxTL::KdTree::ScalarType
ScalarTypeDeferer< value_type >::ScalarType ScalarType
Definition: KdTree.h:180
GfxTL::FlatCopyVector::push_back
void push_back(const T &nn)
Definition: FlatCopyVector.h:189
GfxTL::LimitedHeap::MakeHeap
void MakeHeap()
Definition: LimitedHeap.h:76
GfxTL::NN
Definition: NearestNeighbor.h:8
GfxTL::SortedNearestNeighborInsert
void SortedNearestNeighborInsert(const NN &nn, unsigned int k, NNs *n)
Definition: NearestNeighbors.h:63
GfxTL::FlatCopyVector::size
size_t size() const
Definition: FlatCopyVector.h:117
GfxTL::KdTreeCell
Definition: KdTree.h:23
GfxTL::KdTreeCell::KdTreeCell
KdTreeCell()
Definition: KdTree.h:35
GfxTL::KdTree::Build
void Build()
Definition: KdTree.h:246
visionx::Point
Eigen::Vector3f Point
Definition: ObjectShapeClassification.h:70
GfxTL
Definition: AABox.h:9
GfxTL::KdTreeCell::~KdTreeCell
~KdTreeCell()
Definition: KdTree.h:40
GfxTL::KdTree::ApproximateNearestNeighbors
void ApproximateNearestNeighbors(const PointT &p, unsigned int k, EpsilonT epsilon, LimitedHeap< typename NNTypeHelper< PointT >::NNType, std::less< typename NNTypeHelper< PointT >::NNType >, ContainerT > *neighbors) const
Definition: KdTree.h:487
GfxTL::sqrt
VectorXD< D, T > sqrt(const VectorXD< D, T > &a)
Definition: VectorXD.h:704
GfxTL::KdTree::DereferencedType
BaseType::DereferencedType DereferencedType
Definition: KdTree.h:179
GfxTL::NearestNeighbors
void NearestNeighbors(unsigned int k, const Point &p, const Points &points, size_t size, std::vector< NearestNeighbor< typename Points::size_type, typename Point::ScalarType >> *n)
Definition: NearestNeighbors.h:142
GfxTL::LimitedHeap
Definition: LimitedHeap.h:15
GfxTL::FlatCopyVector::front
T & front()
Definition: FlatCopyVector.h:318
GfxTL::LimitedHeap::PushHeap
void PushHeap(const value_type &t)
Definition: LimitedHeap.h:111
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
GfxTL::LimitedHeap::Limit
void Limit(size_type limit)
Definition: LimitedHeap.h:44
GfxTL::FlatCopyVector::resize
void resize(size_t s)
Definition: FlatCopyVector.h:129
GfxTL::KdTree::Contains
bool Contains(const PointT &p, DereferencedType *dref) const
Definition: KdTree.h:512
GfxTL::AABox
Definition: AABox.h:19
armarx::split
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelpers.cpp:38
GfxTL::KdTree::NearestNeighbors
void NearestNeighbors(const PointT &p, unsigned int k, LimitedHeapT *neighbors) const
Definition: KdTree.h:403