45#ifndef LASS_GUARDIAN_OF_INCLUSION_SPAT_AABP_TREE_INL
46#define LASS_GUARDIAN_OF_INCLUSION_SPAT_AABP_TREE_INL
60template <
typename O,
typename OT,
typename SH>
61AabpTree<O, OT, SH>::AabpTree(
const TSplitHeuristics& heuristics):
63 aabb_(TObjectTraits::aabbEmpty()),
66 end_(new TObjectIterator)
72template <
typename O,
typename OT,
typename SH>
73AabpTree<O, OT, SH>::AabpTree(TObjectIterator first, TObjectIterator last,
const TSplitHeuristics& heuristics):
75 aabb_(TObjectTraits::aabbEmpty()),
78 end_(new TObjectIterator(last))
80 const std::ptrdiff_t size = last - first;
83 LASS_THROW(
"AabpTree: invalid range");
85 if (
static_cast<size_t>(size) >= maxSize)
87 LASS_THROW(
"AabpTree: too many objects");
92 inputs.reserve(
static_cast<size_t>(size));
93 for (TObjectIterator i = first; i != last; ++i)
95 TAabb aabb = TObjectTraits::objectAabb(i);
96 aabb_ = TObjectTraits::aabbJoin(aabb_, aabb);
97 inputs.push_back(Input(aabb, i));
99 balance(inputs.begin(), inputs.end());
104template <
typename O,
typename OT,
typename SH>
105AabpTree<O, OT, SH>::AabpTree(TSelf&& other)
noexcept:
106 SH(std::forward< TSplitHeuristics>(other)),
107 aabb_(std::move(other.aabb_)),
108 objects_(std::move(other.objects_)),
109 nodes_(std::move(other.nodes_)),
110 end_(std::move(other.end_))
115template <
typename O,
typename OT,
typename SH>
116AabpTree<O, OT, SH>& AabpTree<O, OT, SH>::operator=(TSelf&& other)
noexcept
118 TSplitHeuristics::operator=(std::forward<TSplitHeuristics>(other));
119 aabb_ = std::move(other.aabb_);
120 objects_ = std::move(other.objects_);
121 nodes_ = std::move(other.nodes_);
122 end_ = std::move(other.end_);
127template <
typename O,
typename OT,
typename SH>
128void AabpTree<O, OT, SH>::reset()
130 TSelf temp(
static_cast<const SH&
>(*
this));
136template <
typename O,
typename OT,
typename SH>
137void AabpTree<O, OT, SH>::reset(TObjectIterator first, TObjectIterator last)
139 TSelf temp(first, last,
static_cast<const SH&
>(*
this));
145template <
typename O,
typename OT,
typename SH>
146const typename AabpTree<O, OT, SH>::TAabb&
147AabpTree<O, OT, SH>::aabb()
const
154template <
typename O,
typename OT,
typename SH>
155bool AabpTree<O, OT, SH>::contains(
const TPoint& point,
const TInfo* info)
const
157 if (isEmpty() || !TObjectTraits::aabbContains(aabb_, point))
161 return doContains(0, point, info);
166template <
typename O,
typename OT,
typename SH>
167template <
typename OutputIterator>
168OutputIterator AabpTree<O, OT, SH>::find(
const TPoint& point, OutputIterator result,
const TInfo* info)
const
170 if (isEmpty() || !TObjectTraits::aabbContains(aabb_, point))
174 return doFind(0, point, result, info);
179template <
typename O,
typename OT,
typename SH>
180template <
typename OutputIterator>
181OutputIterator AabpTree<O, OT, SH>::find(
const TAabb& box, OutputIterator result,
const TInfo* info)
const
183 if (isEmpty() || !TObjectTraits::aabbIntersects(aabb_, box))
187 return doFind(0, box, result, info);
192template <
typename O,
typename OT,
typename SH>
193template <
typename OutputIterator>
194OutputIterator AabpTree<O, OT, SH>::find(
const TRay& ray, TParam tMin, TParam tMax, OutputIterator result,
const TInfo* info)
const
197 if (isEmpty() || !TObjectTraits::aabbIntersect(aabb_, ray, tNear, tMin))
202 if (!TObjectTraits::aabbIntersect(aabb_, ray, tFar, tNear))
207 if (tNear > tMax || tFar < tMin)
211 const TVector reciprocalDirection = TObjectTraits::vectorReciprocal(TObjectTraits::rayDirection(ray));
212 return doFind(0, ray, tMin, tMax, result, info, reciprocalDirection, tNear, tFar);
217template <
typename O,
typename OT,
typename SH>
218const typename AabpTree<O, OT, SH>::TObjectIterator
219AabpTree<O, OT, SH>::intersect(
const TRay& ray, TReference t, TParam tMin,
const TInfo* info)
const
222 if (isEmpty() || !TObjectTraits::aabbIntersect(aabb_, ray, tNear, tMin))
227 if (!TObjectTraits::aabbIntersect(aabb_, ray, tFar, tNear))
232 const TVector reciprocalDirection = TObjectTraits::vectorReciprocal(TObjectTraits::rayDirection(ray));
233 TObjectIterator hit = doIntersect(0, ray, t, tMin, info, reciprocalDirection, tNear, tFar);
234 LASS_ASSERT((t > tMin && t >= tNear * (1 - 1e-7f) && t <= tFar * (1 + 1e-7f)) || hit == *end_);
240template <
typename O,
typename OT,
typename SH>
241bool AabpTree<O, OT, SH>::intersects(
242 const TRay& ray, TParam tMin, TParam tMax,
const TInfo* info)
const
244 LASS_ASSERT(tMax > tMin || (num::isInf(tMin) && num::isInf(tMax)));
246 if (isEmpty() || !TObjectTraits::aabbIntersect(aabb_, ray, tNear, tMin))
251 if (!TObjectTraits::aabbIntersect(aabb_, ray, tFar, tNear))
256 if (tNear > tMax || tFar < tMin)
260 const TPoint support = TObjectTraits::raySupport(ray);
261 const TVector direction = TObjectTraits::rayDirection(ray);
262 const TVector reciprocalDirection = TObjectTraits::vectorReciprocal(direction);
269 Visit(TIndex index = 0, TValue tNear = 0, TValue tFar = 0) : index(index), tNear(tNear), tFar(tFar) {}
272 TIndex stackSize = 0;
273 stack[stackSize++] = Visit(0, tNear, tFar);
274 while (stackSize > 0)
276 const Visit visit = stack[--stackSize];
277 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
278 LASS_ASSERT(visit.index < nodes_.size());
279 const Node& node = nodes_[visit.index];
283 for (TIndex i = node.first(); i != node.last(); ++i)
285 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
286 if (TObjectTraits::objectIntersects(objects_[i], ray, tMin, tMax, info))
294 const TIndex leftIndex = visit.index + 1;
295 const TIndex rightIndex = node.right();
296 const TValue s = TObjectTraits::coord(support, node.axis());
297 const TValue d = TObjectTraits::coord(direction, node.axis());
298 const TValue invD = TObjectTraits::coord(reciprocalDirection, node.axis());
299 const TValue tLeftBound = (node.leftBound() - s) * invD;
300 const TValue tRightBound = (node.rightBound() - s) * invD;
303 if (tRightBound < tFar)
305 stack[stackSize++] = Visit(rightIndex, std::max(tRightBound, visit.tNear), visit.tFar);
307 if (tLeftBound > tNear)
309 stack[stackSize++] = Visit(leftIndex, visit.tNear, std::min(tLeftBound, visit.tFar));
314 if (tRightBound > tNear)
316 stack[stackSize++] = Visit(rightIndex, visit.tNear, std::min(tRightBound, visit.tFar));
318 if (tLeftBound < tFar)
320 stack[stackSize++] = Visit(leftIndex, std::max(tLeftBound, visit.tNear), visit.tFar);
325 if (s >= node.rightBound())
327 stack[stackSize++] = Visit(rightIndex, visit.tNear, visit.tFar);
329 if (s <= node.leftBound())
331 stack[stackSize++] = Visit(leftIndex, visit.tNear, visit.tFar);
337 return doIntersects(0, ray, tMin, tMax, info, reciprocalDirection, tNear, tFar);
343template <
typename O,
typename OT,
typename SH>
344const typename AabpTree<O, OT, SH>::Neighbour
345AabpTree<O, OT, SH>::nearestNeighbour(
const TPoint& target,
const TInfo* info)
const
347 Neighbour nearest(*end_, std::numeric_limits<TValue>::infinity());
350 doNearestNeighbour(0, target, info, nearest);
357template <
class O,
class OT,
typename SH>
358template <
typename RandomAccessIterator>
360AabpTree<O, OT, SH>::rangeSearch(
361 const TPoint& target, TParam maxRadius,
size_t maxCount, RandomAccessIterator first,
362 const TInfo* info)
const
364 if (isEmpty() || maxRadius == 0)
368 TValue squaredRadius = maxRadius * maxRadius;
369 return doRangeSearch(0, target, squaredRadius, maxCount, first, first, info);
374template <
typename O,
typename OT,
typename SH>
375void AabpTree<O, OT, SH>::swap(TSelf& other)
378 std::swap(aabb_, other.aabb_);
379 nodes_.swap(other.nodes_);
380 objects_.swap(other.objects_);
381 end_.swap(other.end_);
386template <
typename O,
typename OT,
typename SH>
387bool AabpTree<O, OT, SH>::isEmpty()
const
389 return objects_.empty();
394template <
typename O,
typename OT,
typename SH>
395const typename AabpTree<O, OT, SH>::TObjectIterator
396AabpTree<O, OT, SH>::end()
const
409template <
typename O,
typename OT,
typename SH>
410const typename AabpTree<O, OT, SH>::BalanceResult
411AabpTree<O, OT, SH>::balance(TInputIterator first, TInputIterator last)
413 const SplitInfo<OT>
split = TSplitHeuristics::template split<OT>(first, last);
416 return BalanceResult(
split.aabb, addLeafNode(first, last));
419 TInputIterator middle = std::partition(first, last, impl::Splitter<TObjectTraits>(split));
420 if (middle == first || middle == last)
422 const std::ptrdiff_t halfSize = (last - first) / 2;
423 LASS_ASSERT(halfSize > 0);
424 middle = first + halfSize;
425 std::nth_element(first, middle, last, impl::LessAxis<TObjectTraits>(
split.axis));
427 LASS_ASSERT(middle != first && middle != last);
429 const TIndex index = addInternalNode(
split.axis);
430 const BalanceResult left = balance(first, middle);
431 const BalanceResult right = balance(middle, last);
433 Node& node = nodes_[index];
434 node.setLeftBound(TObjectTraits::coord(TObjectTraits::aabbMax(left.aabb),
split.axis));
435 node.setRightBound(TObjectTraits::coord(TObjectTraits::aabbMin(right.aabb),
split.axis));
436 LASS_ASSERT(left.index == index + 1);
437 node.setRight(right.index);
439 return BalanceResult(
split.aabb, index);
444template <
typename O,
typename OT,
typename SH>
445typename AabpTree<O, OT, SH>::TIndex
446AabpTree<O, OT, SH>::addLeafNode(TInputIterator first, TInputIterator last)
448 LASS_ASSERT(objects_.size() <= maxSize);
449 const TIndex begin =
static_cast<TIndex
>(objects_.size());
450 while (first != last)
452 objects_.push_back((first++)->
object);
455 LASS_ASSERT(objects_.size() <= maxSize);
456 const TIndex end =
static_cast<TIndex
>(objects_.size());
458 nodes_.push_back(Node(begin, end));
460 LASS_ASSERT(nodes_.size() > 0);
461 return static_cast<TIndex
>(nodes_.size() - 1);
466template <
typename O,
typename OT,
typename SH>
467typename AabpTree<O, OT, SH>::TIndex
468AabpTree<O, OT, SH>::addInternalNode(
size_t axis)
470 nodes_.push_back(Node(axis));
471 LASS_ASSERT(nodes_.size() > 0);
472 return static_cast<TIndex
>(nodes_.size() - 1);
477template <
typename O,
typename OT,
typename SH>
478bool AabpTree<O, OT, SH>::doContains(TIndex index,
const TPoint& point,
const TInfo* info)
const
480 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
481 LASS_ASSERT(index < nodes_.size());
482 const Node& node = nodes_[index];
486 for (TIndex i = node.first(); i != node.last(); ++i)
488 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
489 if (TObjectTraits::objectContains(objects_[i], point, info))
497 const TValue x = TObjectTraits::coord(point, node.axis());
498 if (x <= node.leftBound() && doContains(index + 1, point, info))
502 if (x >= node.rightBound() && doContains(node.right(), point, info))
511template <
typename O,
typename OT,
typename SH>
512template <
typename OutputIterator>
513OutputIterator AabpTree<O, OT, SH>::doFind(
514 TIndex index,
const TPoint& point, OutputIterator result,
const TInfo* info)
const
516 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
517 LASS_ASSERT(index < nodes_.size());
518 const Node& node = nodes_[index];
522 for (TIndex i = node.first(); i != node.last(); ++i)
524 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
525 if (TObjectTraits::objectContains(objects_[i], point, info))
527 *result++ = objects_[i];
533 const TValue x = TObjectTraits::coord(point, node.axis());
534 if (x <= node.leftBound())
536 result = doFind(index + 1, point, result, info);
538 if (x >= node.rightBound())
540 result = doFind(node.right(), point, result, info);
547template <
typename O,
typename OT,
typename SH>
548template <
typename OutputIterator>
549OutputIterator AabpTree<O, OT, SH>::doFind(
550 TIndex index,
const TAabb& box, OutputIterator result,
const TInfo* info)
const
552 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
553 LASS_ASSERT(index < nodes_.size());
554 const Node& node = nodes_[index];
558 for (TIndex i = node.first(); i != node.last(); ++i)
560 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
561 if (TObjectTraits::objectIntersects(objects_[i], box, info))
563 *result++ = objects_[i];
569 if (TObjectTraits::coord(TObjectTraits::aabbMin(box), node.axis()) <= node.leftBound())
571 result = doFind(index + 1, box, result, info);
573 if (TObjectTraits::coord(TObjectTraits::aabbMax(box), node.axis()) >= node.rightBound())
575 result = doFind(node.right(), box, result, info);
582template <
typename O,
typename OT,
typename SH>
583template <
typename OutputIterator>
584OutputIterator AabpTree<O, OT, SH>::doFind(
585 TIndex index,
const TRay& ray, TParam tMin, TParam tMax, OutputIterator result,
const TInfo* info,
586 const TVector& reciprocalDirection, TParam tNear, TParam tFar)
const
588 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
589 LASS_ASSERT(index < nodes_.size());
590 LASS_ASSERT(tFar >= tNear * (1 - 1e-6f));
591 const Node& node = nodes_[index];
595 for (TIndex i = node.first(); i != node.last(); ++i)
597 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
598 if (TObjectTraits::objectIntersects(objects_[i], ray, tMin, tMax, info))
600 *result++ = objects_[i];
607 const TIndex leftIndex = index + 1;
608 const TIndex rightIndex = node.right();
609 const TValue s = TObjectTraits::coord(TObjectTraits::raySupport(ray), node.axis());
610 const TValue d = TObjectTraits::coord(TObjectTraits::rayDirection(ray), node.axis());
611 const TValue invD = TObjectTraits::coord(reciprocalDirection, node.axis());
612 const TValue tLeftBound = (node.leftBound() - s) * invD;
613 const TValue tRightBound = (node.rightBound() - s) * invD;
617 if (tLeftBound > tNear)
619 result = doFind(leftIndex, ray, tMin, tMax, result, info, reciprocalDirection, tNear, std::min(tLeftBound, tFar));
621 if (tRightBound < tFar)
623 result = doFind(rightIndex, ray, tMin, tMax, result, info, reciprocalDirection, std::max(tRightBound, tNear), tFar);
628 if (tLeftBound < tFar)
630 result = doFind(leftIndex, ray, tMin, tMax, result, info, reciprocalDirection, std::max(tLeftBound, tNear), tFar);
632 if (tRightBound > tNear)
634 result = doFind(rightIndex, ray, tMin, tMax, result, info, reciprocalDirection, tNear, std::min(tRightBound, tFar));
639 if (s <= node.leftBound())
641 result = doFind(leftIndex, ray, tMin, tMax, result, info, reciprocalDirection, tNear, tFar);
643 if (s >= node.rightBound())
645 result = doFind(rightIndex, ray, tMin, tMax, result, info, reciprocalDirection, tNear, tFar);
653template <
typename O,
typename OT,
typename SH>
654const typename AabpTree<O, OT, SH>::TObjectIterator
655AabpTree<O, OT, SH>::doIntersect(
656 TIndex index,
const TRay& ray, TReference t, TParam tMin,
const TInfo* info,
657 const TVector& reciprocalDirection, TParam tNear, TParam tFar)
const
659 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
660 LASS_ASSERT(index < nodes_.size());
661 LASS_ASSERT(tFar >= tNear * (1 - 1e-6f));
662 const Node& node = nodes_[index];
667 TObjectIterator best = *end_;
668 for (TIndex i = node.first(); i != node.last(); ++i)
670 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
671 TValue tCandidate = 0;
672 if (TObjectTraits::objectIntersect(objects_[i], ray, tCandidate, tMin, info))
674 LASS_ASSERT(tCandidate > tMin);
675 if (best == *end_ || tCandidate < tBest)
677 LASS_ASSERT(tCandidate > tMin && tCandidate >= tNear * (1 - 1e-6f) && tCandidate <= tFar * (1 + 1e-6f));
691 const TIndex leftIndex = index + 1;
692 const TIndex rightIndex = node.right();
693 const TValue s = TObjectTraits::coord(TObjectTraits::raySupport(ray), node.axis());
694 const TValue d = TObjectTraits::coord(TObjectTraits::rayDirection(ray), node.axis());
695 const TValue invD = TObjectTraits::coord(reciprocalDirection, node.axis());
696 const TValue tLeftBound = (node.leftBound() - s) * invD;
697 const TValue tRightBound = (node.rightBound() - s) * invD;
701 TObjectIterator objectLeft = *end_;
702 TObjectIterator objectRight = *end_;
705 if (tLeftBound >= tNear * (1 - 1e-6f))
707 objectLeft = doIntersect(leftIndex, ray, tLeft, tMin, info, reciprocalDirection,
708 tNear, std::min(tLeftBound, tFar));
710 if (tRightBound <= tFar * (1 + 1e-6f))
712 objectRight = doIntersect(rightIndex, ray, tRight, tMin, info, reciprocalDirection,
713 std::max(tRightBound, tNear), tFar);
718 if (tLeftBound <= tFar * (1 + 1e-6f))
720 objectLeft = doIntersect(leftIndex, ray, tLeft, tMin, info, reciprocalDirection,
721 std::max(tLeftBound, tNear), tFar);
723 if (tRightBound >= tNear * (1 - 1e-6f))
725 objectRight = doIntersect(rightIndex, ray, tRight, tMin, info, reciprocalDirection,
726 tNear, std::min(tRightBound, tFar));
731 if (s <= node.leftBound())
733 objectLeft = doIntersect(leftIndex, ray, tLeft, tMin, info, reciprocalDirection,
736 if (s >= node.rightBound())
738 objectRight = doIntersect(rightIndex, ray, tRight, tMin, info, reciprocalDirection,
744 if (objectLeft != *end_ && (objectRight == *end_ || tLeft < tRight))
746 LASS_ASSERT(tLeft > tMin);
750 if (objectRight != *end_)
752 LASS_ASSERT(objectLeft == *end_ || !(tLeft < tRight));
753 LASS_ASSERT(tRight > tMin);
762template <
typename O,
typename OT,
typename SH>
763bool AabpTree<O, OT, SH>::doIntersects(
764 TIndex index,
const TRay& ray, TParam tMin, TParam tMax,
const TInfo* info,
765 const TVector& reciprocalDirection, TParam tNear, TParam tFar)
const
767 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
768 LASS_ASSERT(index < nodes_.size());
769 LASS_ASSERT(tMax > tMin);
770 const Node& node = nodes_[index];
774 for (TIndex i = node.first(); i != node.last(); ++i)
776 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
777 if (TObjectTraits::objectIntersects(objects_[i], ray, tMin, tMax, info))
786 const TIndex leftIndex = index + 1;
787 const TIndex rightIndex = node.right();
788 const TValue s = TObjectTraits::coord(TObjectTraits::raySupport(ray), node.axis());
789 const TValue d = TObjectTraits::coord(TObjectTraits::rayDirection(ray), node.axis());
790 const TValue invD = TObjectTraits::coord(reciprocalDirection, node.axis());
791 const TValue tLeftBound = (node.leftBound() - s) * invD;
792 const TValue tRightBound = (node.rightBound() - s) * invD;
796 if ((tLeftBound > tNear) && doIntersects(leftIndex, ray, tMin, tMax, info,
797 reciprocalDirection, tNear, std::min(tLeftBound, tFar)))
801 if ((tRightBound < tFar) && doIntersects(rightIndex, ray, tMin, tMax, info,
802 reciprocalDirection, std::max(tRightBound, tNear), tFar))
809 if ((tLeftBound < tFar) && doIntersects(leftIndex, ray, tMin, tMax, info,
810 reciprocalDirection, std::max(tLeftBound, tNear), tFar))
814 if ((tRightBound > tNear) && doIntersects(rightIndex, ray, tMin, tMax, info,
815 reciprocalDirection, tNear, std::min(tRightBound, tFar)))
822 if ((s <= node.leftBound()) && doIntersects(rightIndex, ray, tMin, tMax, info,
823 reciprocalDirection, tNear, tFar))
827 if ((s >= node.rightBound()) && doIntersects(rightIndex, ray, tMin, tMax, info,
828 reciprocalDirection, tNear, tFar))
838template <
typename O,
typename OT,
typename SH>
839void AabpTree<O, OT, SH>::doNearestNeighbour(
840 TIndex index,
const TPoint& target,
const TInfo* info, Neighbour& best)
const
842 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
843 LASS_ASSERT(index < nodes_.size());
844 LASS_ASSERT(best.squaredDistance() >= 0);
846 const Node& node = nodes_[index];
850 for (TIndex i = node.first(); i != node.last(); ++i)
852 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
853 const TValue squaredDistance =
854 TObjectTraits::objectSquaredDistance(objects_[i], target, info);
855 if (squaredDistance < best.squaredDistance())
857 best = Neighbour(objects_[i], squaredDistance);
864 TValue signedDist[2];
865 getChildren(index, target, children, signedDist);
866 if (signedDist[0] <= 0 || (signedDist[0] * signedDist[0]) < best.squaredDistance())
868 doNearestNeighbour(children[0], target, info, best);
869 if (signedDist[1] <= 0 || (signedDist[1] * signedDist[1]) < best.squaredDistance())
871 doNearestNeighbour(children[1], target, info, best);
879template <
typename O,
typename OT,
typename SH>
880template <
typename RandomIterator>
881RandomIterator AabpTree<O, OT, SH>::doRangeSearch(
882 TIndex index,
const TPoint& target, TReference squaredRadius,
size_t maxCount,
883 RandomIterator first, RandomIterator last,
const TInfo* info)
const
885 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
886 LASS_ASSERT(index < nodes_.size());
887 LASS_ASSERT(squaredRadius >= 0);
889 const Node& node = nodes_[index];
893 for (TIndex i = node.first(); i != node.last(); ++i)
895 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
896 const TValue sqrDist = TObjectTraits::objectSquaredDistance(objects_[i], target, info);
897 if (sqrDist < squaredRadius)
899 *last++ = Neighbour(objects_[i], sqrDist);
900 std::push_heap(first, last);
901 LASS_ASSERT(last >= first);
902 if (
static_cast<size_t>(last - first) > maxCount)
904 std::pop_heap(first, last);
906 squaredRadius = first->squaredDistance();
914 TValue signedDist[2];
915 getChildren(index, target, children, signedDist);
916 if (signedDist[0] <= 0 || (signedDist[0] * signedDist[0]) < squaredRadius)
918 last = doRangeSearch(children[0], target, squaredRadius, maxCount, first, last, info);
919 if (signedDist[1] <= 0 || (signedDist[1] * signedDist[1]) < squaredRadius)
921 last = doRangeSearch(children[1], target, squaredRadius, maxCount, first, last, info);
929template <
typename O,
typename OT,
typename SH>
930void AabpTree<O, OT, SH>::getChildren(
931 TIndex index,
const TPoint& target, TIndex indices[2], TValue signedDistances[2])
const
933 LASS_ASSERT(index < nodes_.size());
934 const Node& node = nodes_[index];
935 indices[0] = index + 1;
936 indices[1] = node.right();
937 const TValue x = TObjectTraits::coord(target, node.axis());
938 signedDistances[0] = x - node.leftBound();
939 signedDistances[1] = node.rightBound() - x;
941 if (signedDistances[1] < signedDistances[0])
943 std::swap(signedDistances[0], signedDistances[1]);
944 std::swap(indices[0], indices[1]);
std::vector< std::basic_string< Char, Traits, Alloc > > split(const std::basic_string< Char, Traits, Alloc > &to_be_split)
Reflects the Python function split without seperator argument.
spatial subdivisions, quadtrees, octrees, meshes in 2D and 3D, triangulators, ...
Library for Assembled Shared Sources.