KdTree.hpp
Go to the documentation of this file.
1
2namespace GfxTL
3{
4 template <class ValueT, class BaseT>
6 {
7 memset(&_children, NULL, sizeof(_children));
8 }
9
10 template <class ValueT, class BaseT>
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>
33 KdTreeCell<ValueT, BaseT>::~KdTreeCell()
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>*
44 KdTreeCell<ValueT, BaseT>::operator[](unsigned int index) const
45 {
46 return _children[index];
47 }
48
49 template <class ValueT, class BaseT>
50 KdTreeCell<ValueT, BaseT>*
51 KdTreeCell<ValueT, BaseT>::operator[](unsigned int index)
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&
65 KdTreeCell<ValueT, BaseT>::Split() const
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
79 KdTree<Strategies>::Build()
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,
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,
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
uint8_t index
if(!yyvaluep)
Definition Grammar.cpp:645
void push_back(const T &nn)
bool Contains(const PointT &p, DereferencedType *dref) const
Definition KdTree.h:512
KdTreeCell< typename GfxTL::IncrementalDistanceKdTreeStrategy< GfxTL::MaxIntervalSplittingKdTreeStrategy< GfxTL::CellBBoxBuildInformationKdTreeStrategy< GfxTL::BBoxBuildInformationTreeStrategy< GfxTL::BucketSizeMaxLevelSubdivisionTreeStrategy< GfxTL::CellLevelTreeStrategy< GfxTL::BaseKdTreeStrategy< GfxTL::CellRangeDataTreeStrategy< GfxTL::NullTreeStrategy, GfxTL::IndexedIteratorTreeDataKernel< PointCloud::const_iterator, MiscLib::Vector< size_t > > > > > > > > > >::CellData > CellType
Definition KdTree.h:174
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
void NearestNeighbors(const PointT &p, unsigned int k, LimitedHeapT *neighbors) const
Definition KdTree.h:403
void Limit(size_type limit)
Definition LimitedHeap.h:44
void PushHeap(const value_type &t)
Definition AABox.h:10
void SortedNearestNeighborInsert(const NN &nn, unsigned int k, NNs *n)
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
std::pair< ssize_t, ssize_t > Range
Definition httplib.h:609