145template <
typename O,
typename OT,
typename SH>
inline
152 return doContains(0, point, info);
159template <
typename O,
typename OT,
typename SH>
160template <
typename OutputIterator>
inline
167 return doFind(0, point, result, info);
174template <
typename O,
typename OT,
typename SH>
175template <
typename OutputIterator>
inline
182 return doFind(0, box, result, info);
189template <
typename O,
typename OT,
typename SH>
190template <
typename OutputIterator>
inline
197 const TVector& dir = ray.direction();
198 const TVector invDir = TObjectTraits::vectorReciprocal(dir);
199#if LASS_SPAT_AABB_TREE_STACK_SIZE
200 TIndex stack[LASS_SPAT_AABB_TREE_STACK_SIZE];
201 TIndex stackSize = 0;
202 stack[stackSize++] = 0;
203 while (stackSize > 0)
205 const TIndex index = stack[--stackSize];
206 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
207 LASS_ASSERT(index < nodes_.size());
208 const Node& node = nodes_[index];
210 if (!volumeIntersects(node.aabb(), ray, invDir, tMin, tMax))
214 if (node.isInternal())
216 if (stackSize + 2 >= LASS_SPAT_AABB_TREE_STACK_SIZE)
219 result = doFind(index + 1, ray, invDir, tMin, tMax, result, info);
220 result = doFind(node.right(), ray, invDir, tMin, tMax, result, info);
223 LASS_ASSERT(stackSize + 2 < LASS_SPAT_AABB_TREE_STACK_SIZE);
224 stack[stackSize++] = node.right();
225 stack[stackSize++] = index + 1;
228 for (TIndex i = node.first(); i != node.last(); ++i)
230 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
231 if (TObjectTraits::objectIntersects(objects_[i], ray, tMin, tMax, info))
233 *result++ = objects_[i];
239 return doFind(0, ray, invDir, tMin, tMax, result, info);
245template <
typename O,
typename OT,
typename SH>
246typename AabbTree<O, OT, SH>::TObjectIterator
inline
247AabbTree<O, OT, SH>::intersect(
const TRay& ray, TReference t, TParam tMin,
const TInfo* info)
const
249 const TVector& dir = ray.direction();
250 const TVector invDir = TObjectTraits::vectorReciprocal(dir);
252 if (isEmpty() || !volumeIntersect(nodes_.front().aabb(), ray, invDir, tRoot, tMin))
256#if LASS_SPAT_AABB_TREE_STACK_SIZE
261 Visit(TIndex index = 0, TValue tNear = 0) : index(index), tNear(tNear) {}
263 Visit stack[LASS_SPAT_AABB_TREE_STACK_SIZE];
264 TIndex stackSize = 0;
265 stack[stackSize++] = Visit(0, tRoot);
267 TObjectIterator best = *end_;
268 while (stackSize > 0)
270 const Visit visit = stack[--stackSize];
271 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
272 LASS_ASSERT(visit.index < nodes_.size());
273 const Node& node = nodes_[visit.index];
275 if (best != *end_ && tBest < visit.tNear)
280 if (stackSize + 2 >= LASS_SPAT_AABB_TREE_STACK_SIZE)
284 TObjectIterator b = doIntersect(0, ray, invDir, tb, tMin, info);
285 if (best == *end_ || tb < tBest)
295 for (TIndex i = node.first(); i != node.last(); ++i)
297 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
298 TValue tCandidate = 0;
299 if (TObjectTraits::objectIntersect(objects_[i], ray, tCandidate, tMin, info))
301 if (best == *end_ || tCandidate < tBest)
311 TIndex left = visit.index + 1;
312 TIndex right = node.right();
313 TValue tLeftBox = 0, tRightBox = 0;
314 const bool hitsLeft = volumeIntersect(nodes_[left].aabb(), ray, invDir, tLeftBox, tMin);
315 const bool hitsRight = volumeIntersect(nodes_[right].aabb(), ray, invDir, tRightBox, tMin);
322 if (tRightBox < tLeftBox)
324 std::swap(tLeftBox, tRightBox);
325 std::swap(left, right);
328 stack[stackSize++] = Visit(right, tRightBox);
329 stack[stackSize++] = Visit(left, tLeftBox);
333 stack[stackSize++] = Visit(left, tLeftBox);
339 stack[stackSize++] = Visit(right, tRightBox);
348 return doIntersect(0, ray, invDir, t, tMin, info);
354template <
typename O,
typename OT,
typename SH>
355bool inline AabbTree<O, OT, SH>::intersects(
const TRay& ray, TParam tMin, TParam tMax,
const TInfo* info)
const
361 const TVector& dir = ray.direction();
362 const TVector invDir = TObjectTraits::vectorReciprocal(dir);
363#if LASS_SPAT_AABB_TREE_STACK_SIZE
364 TIndex stack[LASS_SPAT_AABB_TREE_STACK_SIZE];
365 TIndex stackSize = 0;
366 stack[stackSize++] = 0;
367 while (stackSize > 0)
369 const TIndex index = stack[--stackSize];
371 if (stackSize + 2 >= LASS_SPAT_AABB_TREE_STACK_SIZE)
374 if (doIntersects(index, ray, invDir, tMin, tMax, info))
381 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
382 LASS_ASSERT(index < nodes_.size());
383 const Node& node = nodes_[index];
385 if (!volumeIntersects(node.aabb(), ray, invDir, tMin, tMax))
392 for (TIndex i = node.first(); i != node.last(); ++i)
394 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
395 if (TObjectTraits::objectIntersects(objects_[i], ray, tMin, tMax, info))
403 LASS_ASSERT(stackSize + 2 < LASS_SPAT_AABB_TREE_STACK_SIZE);
404 stack[stackSize++] = node.right();
405 stack[stackSize++] = index + 1;
409 return doIntersects(0, ray, invDir, tMin, tMax, info);
415template <
typename O,
typename OT,
typename SH>
416const typename AabbTree<O, OT, SH>::Neighbour
417AabbTree<O, OT, SH>::nearestNeighbour(
const TPoint& point,
const TInfo* info)
const
419 Neighbour nearest(*end_, std::numeric_limits<TValue>::infinity());
424#if LASS_SPAT_AABB_TREE_STACK_SIZE
428 TValue squaredDistance;
429 Visit(TIndex index = 0, TValue squaredDistance = 0) : index(index), squaredDistance(squaredDistance) {}
431 Visit stack[LASS_SPAT_AABB_TREE_STACK_SIZE];
432 TIndex stackSize = 0;
433 stack[stackSize++] = Visit(0, 0);
434 while (stackSize > 0)
436 const Visit visit = stack[--stackSize];
437 if (visit.squaredDistance >= nearest.squaredDistance())
442 if (stackSize + 2 >= LASS_SPAT_AABB_TREE_STACK_SIZE)
445 doNearestNeighbour(visit.index, point, info, nearest);
449 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
450 LASS_ASSERT(nearest.squaredDistance() >= 0);
451 LASS_ASSERT(visit.index < nodes_.size());
452 const Node& node = nodes_[visit.index];
456 for (TIndex i = node.first(); i != node.last(); ++i)
458 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
459 const TValue squaredDistance = TObjectTraits::objectSquaredDistance(objects_[i], point, info);
460 if (squaredDistance < nearest.squaredDistance())
462 nearest = Neighbour(objects_[i], squaredDistance);
469 TValue squaredDistances[2];
470 getChildren(visit.index, point, children, squaredDistances);
472 stack[stackSize++] = Visit(children[1], squaredDistances[1]);
473 stack[stackSize++] = Visit(children[0], squaredDistances[0]);
476 doNearestNeighbour(0, point, info, nearest);
483template <
class O,
class OT,
typename SH>
484template <
typename RandomAccessIterator>
486AabbTree<O, OT, SH>::rangeSearch(
487 const TPoint& target, TParam maxRadius,
size_t maxCount, RandomAccessIterator first,
488 const TInfo* info)
const
490 if (isEmpty() || maxRadius == 0)
494 TValue squaredRadius = maxRadius * maxRadius;
495#if LASS_SPAT_AABB_TREE_STACK_SIZE
496 RandomAccessIterator last = first;
500 TValue squaredDistance;
501 Visit(TIndex index = 0, TValue squaredDistance = 0) : index(index), squaredDistance(squaredDistance) {}
503 Visit stack[LASS_SPAT_AABB_TREE_STACK_SIZE];
504 TIndex stackSize = 0;
505 stack[stackSize++] = Visit(0, 0);
506 while (stackSize > 0)
508 const Visit visit = stack[--stackSize];
509 if (visit.squaredDistance >= squaredRadius)
514 if (stackSize + 2 >= LASS_SPAT_AABB_TREE_STACK_SIZE)
517 last = doRangeSearch(visit.index, target, squaredRadius, maxCount, first, last, info);
521 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
522 LASS_ASSERT(visit.index < nodes_.size());
523 const Node& node = nodes_[visit.index];
527 for (TIndex i = node.first(); i != node.last(); ++i)
529 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
530 const TValue sqrDist = TObjectTraits::objectSquaredDistance(objects_[i], target, info);
531 if (sqrDist < squaredRadius)
533 *last++ = Neighbour(objects_[i], sqrDist);
534 std::push_heap(first, last);
535 LASS_ASSERT(last >= first);
536 if (
static_cast<size_t>(last - first) > maxCount)
538 std::pop_heap(first, last);
540 squaredRadius = first->squaredDistance();
548 TValue squaredDistances[2];
549 getChildren(visit.index, target, children, squaredDistances);
551 stack[stackSize++] = Visit(children[1], squaredDistances[1]);
552 stack[stackSize++] = Visit(children[0], squaredDistances[0]);
556 return doRangeSearch(0, target, squaredRadius, maxCount, first, first, info);
562template <
typename O,
typename OT,
typename SH>
563void AabbTree<O, OT, SH>::swap(TSelf& other)
566 nodes_.swap(other.nodes_);
567 objects_.swap(other.objects_);
568 end_.swap(other.end_);
573template <
typename O,
typename OT,
typename SH>
574bool AabbTree<O, OT, SH>::isEmpty()
const
576 return objects_.empty();
581template <
typename O,
typename OT,
typename SH>
582const typename AabbTree<O, OT, SH>::TObjectIterator
583AabbTree<O, OT, SH>::end()
const
590template <
typename O,
typename OT,
typename SH>
591void AabbTree<O, OT, SH>::reset()
593 TSelf temp(
static_cast<const SH&
>(*
this));
605template <
typename O,
typename OT,
typename SH>
606typename AabbTree<O, OT, SH>::TIndex
607AabbTree<O, OT, SH>::balance(TInputIterator first, TInputIterator last)
609 const SplitInfo<OT>
split = TSplitHeuristics::template split<OT>(first, last);
612 return addLeafNode(
split.aabb, first, last);
615 TInputIterator middle = std::partition(first, last, impl::Splitter<TObjectTraits>(split));
616 if (middle == first || middle == last)
618 const std::ptrdiff_t halfSize = (last - first) / 2;
619 LASS_ASSERT(halfSize > 0);
620 middle = first + halfSize;
621 std::nth_element(first, middle, last, impl::LessAxis<TObjectTraits>(
split.axis));
623 LASS_ASSERT(middle != first && middle != last);
625 const TIndex node = addInternalNode(
split.aabb);
626 [[maybe_unused]]
const TIndex left = balance(first, middle);
627 LASS_ASSERT(left == node + 1);
628 const TIndex right = balance(middle, last);
629 nodes_[node].setRight(right);
635template <
typename O,
typename OT,
typename SH>
636typename AabbTree<O, OT, SH>::TIndex
637AabbTree<O, OT, SH>::addLeafNode(
638 const TAabb& aabb, TInputIterator first, TInputIterator last)
640 LASS_ASSERT(objects_.size() <= Node::sentinelInternal);
641 const TIndex begin =
static_cast<TIndex
>(objects_.size());
642 while (first != last)
644 objects_.push_back((first++)->
object);
646 LASS_ASSERT(objects_.size() <= Node::sentinelInternal);
647 const TIndex end =
static_cast<TIndex
>(objects_.size());
648 nodes_.push_back(Node(aabb, begin, end));
650 LASS_ASSERT(nodes_.size() > 0);
651 return static_cast<TIndex
>(nodes_.size() - 1);
656template <
typename O,
typename OT,
typename SH>
657typename AabbTree<O, OT, SH>::TIndex
658AabbTree<O, OT, SH>::addInternalNode(
const TAabb& aabb)
660 nodes_.push_back(Node(aabb));
661 LASS_ASSERT(objects_.size() <= Node::sentinelInternal);
662 return static_cast<TIndex
>(nodes_.size() - 1);
667template <
typename O,
typename OT,
typename SH>
668bool AabbTree<O, OT, SH>::doContains(TIndex rootIndex,
const TPoint& point,
const TInfo* info)
const
670#if LASS_SPAT_AABB_TREE_STACK_SIZE
671 TIndex stack[LASS_SPAT_AABB_TREE_STACK_SIZE];
672 TIndex stackSize = 0;
673 stack[stackSize++] = rootIndex;
674 while (stackSize > 0)
676 const TIndex index = stack[--stackSize];
677 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
678 LASS_ASSERT(index < nodes_.size());
679 const Node& node = nodes_[index];
681 if (!TObjectTraits::aabbContains(node.aabb(), point))
685 if (node.isInternal())
687 if (stackSize + 2 >= LASS_SPAT_AABB_TREE_STACK_SIZE)
690 if (doContains(index + 1, point, info) || doContains(node.right(), point, info))
696 LASS_ASSERT(stackSize + 2 < LASS_SPAT_AABB_TREE_STACK_SIZE);
697 stack[stackSize++] = node.right();
698 stack[stackSize++] = index + 1;
701 for (TIndex i = node.first(); i != node.last(); ++i)
703 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
704 if (TObjectTraits::objectContains(objects_[i], point, info))
711 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
712 LASS_ASSERT(rootIndex < nodes_.size());
713 const Node& node = nodes_[rootIndex];
715 if (!TObjectTraits::aabbContains(node.aabb(), point))
719 if (node.isInternal())
721 return doContains(rootIndex + 1, point, info) || doContains(node.right(), point, info);
723 for (TIndex i = node.first(); i != node.last(); ++i)
725 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
726 if (TObjectTraits::objectContains(objects_[i], point, info))
737template <
typename O,
typename OT,
typename SH>
738template <
typename OutputIterator>
739OutputIterator AabbTree<O, OT, SH>::doFind(TIndex rootIndex,
const TPoint& point, OutputIterator result,
const TInfo* info)
const
741#if LASS_SPAT_AABB_TREE_STACK_SIZE
742 TIndex stack[LASS_SPAT_AABB_TREE_STACK_SIZE];
743 TIndex stackSize = 0;
744 stack[stackSize++] = rootIndex;
745 while (stackSize > 0)
747 const TIndex index = stack[--stackSize];
748 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
749 LASS_ASSERT(index < nodes_.size());
750 const Node& node = nodes_[index];
752 if (!TObjectTraits::aabbContains(node.aabb(), point))
756 if (node.isInternal())
758 if (stackSize + 2 >= LASS_SPAT_AABB_TREE_STACK_SIZE)
761 result = doFind(index + 1, point, result, info);
762 result = doFind(node.right(), point, result, info);
765 LASS_ASSERT(stackSize + 2 < LASS_SPAT_AABB_TREE_STACK_SIZE);
766 stack[stackSize++] = node.right();
767 stack[stackSize++] = index + 1;
770 for (TIndex i = node.first(); i != node.last(); ++i)
772 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
773 if (TObjectTraits::objectContains(objects_[i], point, info))
775 *result++ = objects_[i];
781 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
782 LASS_ASSERT(rootIndex < nodes_.size());
783 const Node& node = nodes_[rootIndex];
785 if (!TObjectTraits::aabbContains(node.aabb(), point))
789 if (node.isInternal())
791 result = doFind(rootIndex + 1, point, result, info);
792 return doFind(node.right(), point, result, info);
794 for (TIndex i = node.first(); i != node.last(); ++i)
796 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
797 if (TObjectTraits::objectContains(objects_[i], point, info))
799 *result++ = objects_[i];
808template <
typename O,
typename OT,
typename SH>
809template <
typename OutputIterator>
810OutputIterator AabbTree<O, OT, SH>::doFind(TIndex rootIndex,
const TAabb& box, OutputIterator result,
const TInfo* info)
const
812#if LASS_SPAT_AABB_TREE_STACK_SIZE
813 TIndex stack[LASS_SPAT_AABB_TREE_STACK_SIZE];
814 TIndex stackSize = 0;
815 stack[stackSize++] = rootIndex;
816 while (stackSize > 0)
818 const TIndex index = stack[--stackSize];
819 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
820 LASS_ASSERT(index < nodes_.size());
821 const Node& node = nodes_[index];
823 if (!TObjectTraits::aabbIntersects(node.aabb(), box))
827 if (node.isInternal())
829 if (stackSize + 2 >= LASS_SPAT_AABB_TREE_STACK_SIZE)
832 result = doFind(index + 1, box, result, info);
833 result = doFind(node.right(), box, result, info);
836 LASS_ASSERT(stackSize + 2 < LASS_SPAT_AABB_TREE_STACK_SIZE);
837 stack[stackSize++] = node.right();
838 stack[stackSize++] = index + 1;
841 for (TIndex i = node.first(); i != node.last(); ++i)
843 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
844 if (TObjectTraits::objectIntersects(objects_[i], box, info))
846 *result++ = objects_[i];
852 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
853 LASS_ASSERT(rootIndex < nodes_.size());
854 const Node& node = nodes_[rootIndex];
856 if (!TObjectTraits::aabbIntersects(node.aabb(), box))
860 if (node.isInternal())
862 result = doFind(rootIndex + 1, box, result, info);
863 return doFind(node.right(), box, result, info);
865 for (TIndex i = node.first(); i != node.last(); ++i)
867 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
868 if (TObjectTraits::objectIntersects(objects_[i], box, info))
870 *result++ = objects_[i];
879template <
typename O,
typename OT,
typename SH>
880template <
typename OutputIterator>
881OutputIterator AabbTree<O, OT, SH>::doFind(TIndex index,
const TRay& ray,
const TVector& invDir, TParam tMin, TParam tMax, OutputIterator result,
const TInfo* info)
const
883 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
884 LASS_ASSERT(index < nodes_.size());
885 const Node& node = nodes_[index];
887 if (!volumeIntersects(node.aabb(), ray, invDir, tMin, tMax))
891 if (node.isInternal())
893 result = doFind(index + 1, ray, invDir, tMin, tMax, result, info);
894 return doFind(node.right(), ray, invDir, tMin, tMax, result, info);
896 for (TIndex i = node.first(); i != node.last(); ++i)
898 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
899 if (TObjectTraits::objectIntersects(objects_[i], ray, tMin, tMax, info))
901 *result++ = objects_[i];
909template <
typename O,
typename OT,
typename SH>
910typename AabbTree<O, OT, SH>::TObjectIterator
911AabbTree<O, OT, SH>::doIntersect(TIndex index,
const TRay& ray,
const TVector& invDir, TReference t, TParam tMin,
const TInfo* info)
const
913 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
914 LASS_ASSERT(index < nodes_.size());
915 const Node& node = nodes_[index];
920 TObjectIterator best = *end_;
921 for (TIndex i = node.first(); i != node.last(); ++i)
923 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
924 TValue tCandidate = 0;
925 if (TObjectTraits::objectIntersect(objects_[i], ray, tCandidate, tMin, info))
927 if (best == *end_ || tCandidate < tBest)
941 TIndex left = index + 1;
942 TIndex right = node.right();
943 TValue tLeftBox = 0, tRightBox = 0;
944 const bool hitsLeft = volumeIntersect(nodes_[left].aabb(), ray, invDir, tLeftBox, tMin);
945 const bool hitsRight = volumeIntersect(nodes_[right].aabb(), ray, invDir, tRightBox, tMin);
949 return hitsRight ? doIntersect(right, ray, invDir, t, tMin, info) : *end_;
953 return doIntersect(left, ray, invDir, t, tMin, info);
957 if (tRightBox < tLeftBox)
959 std::swap(tLeftBox, tRightBox);
960 std::swap(left, right);
964 const TObjectIterator leftBest = doIntersect(left, ray, invDir, tLeft, tMin, info);
965 if (leftBest == *end_)
967 return doIntersect(right, ray, invDir, t, tMin, info);
970 if (tRightBox <= tLeft)
974 const TObjectIterator rightBest = doIntersect(right, ray, invDir, tRight, tMin, info);
975 if (rightBest != *end_ && tRight < tLeft)
988template <
typename O,
typename OT,
typename SH>
989bool AabbTree<O, OT, SH>::doIntersects(
990 TIndex index,
const TRay& ray,
const TVector& invDir, TParam tMin,
const TParam tMax,
const TInfo* info)
const
992 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
993 LASS_ASSERT(index < nodes_.size());
994 const Node& node = nodes_[index];
996 if (!volumeIntersects(node.aabb(), ray, invDir, tMin, tMax))
1000 if (node.isInternal())
1002 return doIntersects(index + 1, ray, invDir, tMin, tMax, info)
1003 || doIntersects(node.right(), ray, invDir, tMin, tMax, info);
1005 for (TIndex i = node.first(); i != node.last(); ++i)
1007 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
1008 if (TObjectTraits::objectIntersects(objects_[i], ray, tMin, tMax, info))
1018template <
typename O,
typename OT,
typename SH>
1019void AabbTree<O, OT, SH>::doNearestNeighbour(
1020 TIndex index,
const TPoint& target,
const TInfo* info, Neighbour& best)
const
1022 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
1023 LASS_ASSERT(best.squaredDistance() >= 0);
1025 const Node& node = nodes_[index];
1029 for (TIndex i = node.first(); i != node.last(); ++i)
1031 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
1032 const TValue squaredDistance = TObjectTraits::objectSquaredDistance(objects_[i], target, info);
1033 if (squaredDistance < best.squaredDistance())
1035 best = Neighbour(objects_[i], squaredDistance);
1042 TValue squaredDistances[2];
1043 getChildren(index, target, children, squaredDistances);
1044 if (squaredDistances[0] < best.squaredDistance())
1046 doNearestNeighbour(children[0], target, info, best);
1047 if (squaredDistances[1] < best.squaredDistance())
1049 doNearestNeighbour(children[1], target, info, best);
1057template <
typename O,
typename OT,
typename SH>
1058template <
typename RandomIterator>
1059RandomIterator AabbTree<O, OT, SH>::doRangeSearch(
1060 TIndex index,
const TPoint& target, TReference squaredRadius,
size_t maxCount,
1061 RandomIterator first, RandomIterator last,
const TInfo* info)
const
1063 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
1064 LASS_ASSERT(squaredRadius >= 0);
1066 const Node& node = nodes_[index];
1070 for (TIndex i = node.first(); i != node.last(); ++i)
1072 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
1073 const TValue sqrDist = TObjectTraits::objectSquaredDistance(objects_[i], target, info);
1074 if (sqrDist < squaredRadius)
1076 *last++ = Neighbour(objects_[i], sqrDist);
1077 std::push_heap(first, last);
1078 LASS_ASSERT(last >= first);
1079 if (
static_cast<size_t>(last - first) > maxCount)
1081 std::pop_heap(first, last);
1083 squaredRadius = first->squaredDistance();
1091 TValue squaredDistances[2];
1092 getChildren(index, target, children, squaredDistances);
1093 if (squaredDistances[0] < squaredRadius)
1095 last = doRangeSearch(children[0], target, squaredRadius, maxCount, first, last, info);
1096 if (squaredDistances[1] < squaredRadius)
1098 last = doRangeSearch(children[1], target, squaredRadius, maxCount, first, last, info);
1107template <
typename O,
typename OT,
typename SH>
1108void AabbTree<O, OT, SH>::getChildren(
1109 TIndex index,
const TPoint& target, TIndex indices[2], TValue squaredDistances[2])
const
1111 const Node& node = nodes_[index];
1112 indices[0] = index + 1;
1113 indices[1] = node.right();
1115 for (
size_t i = 0; i < 2; ++i)
1117 const Node& child = nodes_[indices[i]];
1118 squaredDistances[i] = 0;
1119 const TPoint& min = TObjectTraits::aabbMin(child.aabb());
1120 const TPoint& max = TObjectTraits::aabbMax(child.aabb());
1121 for (
size_t k = 0; k < dimension; ++k)
1123 const TValue x = TObjectTraits::coord(target, k);
1124 const TValue d = std::max(TObjectTraits::coord(min, k) - x, x - TObjectTraits::coord(max, k));
1127 squaredDistances[i] += d * d;
1132 if (squaredDistances[1] < squaredDistances[0])
1134 std::swap(squaredDistances[0], squaredDistances[1]);
1135 std::swap(indices[0], indices[1]);
1141template <
typename O,
typename OT,
typename SH>
1142bool AabbTree<O, OT, SH>::volumeIntersect(
const TAabb& box,
const TRay& ray,
const TVector& invDir, TReference t, TParam tMin)
const
1144 if (TObjectTraits::aabbContains(box, TObjectTraits::rayPoint(ray, tMin)))
1149 return TObjectTraits::aabbIntersect(box, ray, invDir, t, tMin);
1154template <
typename O,
typename OT,
typename SH>
1155bool AabbTree<O, OT, SH>::volumeIntersects(
const TAabb& box,
const TRay& ray,
const TVector& invDir, TParam tMin, TParam tMax)
const
1158 return volumeIntersect(box, ray, invDir, t, tMin) && t <= tMax;