187 SH::operator=(std::forward<TSelf>(other));
190 other.root_ =
nullptr;
192 nodesAllocator_ = std::move(other.nodesAllocator_);
193 numObjects_ = other.numObjects_;
199template <
typename O,
typename OT,
typename SH>
200void QuadTree<O, OT, SH>::reset()
202 QuadTree temp(aabb_, end_,
static_cast<const SH&
>(*
this));
208template <
typename O,
typename OT,
typename SH>
209void QuadTree<O, OT, SH>::reset(TObjectIterator first, TObjectIterator last)
211 QuadTree temp(first, last,
static_cast<const SH&
>(*
this));
217template <
typename O,
typename OT,
typename SH>
221 if (!TObjectTraits::aabbContains(aabb_, TObjectTraits::objectAabb(
object)))
223 LASS_THROW(
"object not within bounding box of tree");
225 root_->add(
object, *
this);
231template <
typename O,
typename OT,
typename SH>
232void QuadTree<O, OT, SH>::remove(TObjectIterator
object)
235 if (root_->remove(
object))
243template <
typename O,
typename OT,
typename SH>
248 if (!TObjectTraits::aabbContains(aabb_, point))
253 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
254 QuadNode* node = root_;
255 while (!node->isLeaf())
257 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_NODE;
258 node = &node->children[this->findSubNode(node->center(), point)];
262 for (
typename TObjectIterators::const_iterator i = node->data.begin(); i != node->data.end(); ++i)
264 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
265 if (TObjectTraits::objectContains(*i, point, info))
275template <
typename O,
typename OT,
typename SH>
276template <
typename OutputIterator>
281 if (!TObjectTraits::aabbContains(aabb_, point))
286 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
287 QuadNode* node = root_;
288 while (!node->isLeaf())
290 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_NODE;
291 node = &node->children[this->findSubNode(node->center(), point)];
295 for (
typename TObjectIterators::const_iterator i = node->data.begin(); i != node->data.end(); ++i)
297 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
298 if (TObjectTraits::objectContains(*i, point, info))
311template <
typename O,
typename OT,
typename SH>
312template <
typename OutputIterator>
316 if (!TObjectTraits::aabbIntersects(aabb_, box))
320 return doFind(*root_, box, result, info);
328template <
typename O,
typename OT,
typename SH>
329template <
typename OutputIterator>
334 const TPoint min = TObjectTraits::aabbMin(aabb_);
335 const TPoint max = TObjectTraits::aabbMax(aabb_);
336 const TPoint support = TObjectTraits::raySupport(ray);
337 const TVector direction = TObjectTraits::rayDirection(ray);
338 const TVector invDirection = TObjectTraits::vectorReciprocal(direction);
340 TVector tNear = invDirection * (min - support);
341 TVector tFar = invDirection * (max - support);
342 const size_t flipMask = this->forceMinToMax(tNear, tFar);
344 return doFind(*root_, ray, tMin, tMax, result, info, tNear, tFar, support, invDirection, flipMask);
348template <
typename O,
typename OT,
typename SH>
349const typename QuadTree<O, OT, SH>::TObjectIterator
350QuadTree<O, OT, SH>::intersect(
351 const TRay& ray, TReference t, TParam tMin,
const TInfo* info)
const
355 const TPoint min = TObjectTraits::aabbMin(aabb_);
356 const TPoint max = TObjectTraits::aabbMax(aabb_);
357 const TPoint support = TObjectTraits::raySupport(ray);
358 const TVector direction = TObjectTraits::rayDirection(ray);
359 const TVector invDirection = TObjectTraits::vectorReciprocal(direction);
361 TVector tNear = invDirection * (min - support);
362 TVector tFar = invDirection * (max - support);
363 const size_t flipMask = this->forceMinToMax(tNear, tFar);
365 return doIntersect(*root_, ray, t, tMin, info, tNear, tFar, support, invDirection, flipMask);
370template <
typename O,
typename OT,
typename SH>
371bool QuadTree<O, OT, SH>::intersects(
372 const TRay& ray, TParam tMin, TParam tMax,
const TInfo* info)
const
376 const TPoint min = TObjectTraits::aabbMin(aabb_);
377 const TPoint max = TObjectTraits::aabbMax(aabb_);
378 const TPoint support = TObjectTraits::raySupport(ray);
379 const TVector direction = TObjectTraits::rayDirection(ray);
380 const TVector invDirection = TObjectTraits::vectorReciprocal(direction);
382 TVector tNear = invDirection * (min - support);
383 TVector tFar = invDirection * (max - support);
384 const size_t flipMask = this->forceMinToMax(tNear, tFar);
386 return doIntersects(*root_, ray, tMin, tMax, info, tNear, tFar, support, invDirection, flipMask);
391template <
typename O,
typename OT,
typename SH>
392const typename QuadTree<O, OT, SH>::Neighbour
393QuadTree<O, OT, SH>::nearestNeighbour(
const TPoint& point,
const TInfo* info)
const
396 Neighbour nearest(end_, std::numeric_limits<TValue>::infinity());
397 doNearestNeighbour(*root_, point, info, nearest);
403template <
typename O,
typename OT,
typename SH>
404template <
typename RandomAccessIterator>
406QuadTree<O, OT, SH>::rangeSearch(
407 const TPoint& target, TParam maxRadius,
size_t maxCount, RandomAccessIterator first,
408 const TInfo* info)
const
415 TValue squaredRadius = maxRadius * maxRadius;
416 return doRangeSearch(*root_, target, squaredRadius, maxCount, first, first, info);
421template <
typename O,
typename OT,
typename SH>
422size_t QuadTree<O, OT, SH>::objectCount()
const
425 return root_->objectCount();
430template <
typename O,
typename OT,
typename SH>
431const typename QuadTree<O, OT, SH>::TAabb&
432QuadTree<O, OT, SH>::aabb()
const
439template <
typename O,
typename OT,
typename SH>
443 return root_->depth();
449template <
typename O,
typename OT,
typename SH>
450const typename QuadTree<O, OT, SH>::TValue
451QuadTree<O, OT, SH>::averageDepth()
const
454 return root_->averageDepth();
459template <
typename O,
typename OT,
typename SH>
460bool QuadTree<O, OT, SH>::isEmpty()
const
462 return numObjects_ == 0;
467template <
typename O,
typename OT,
typename SH>
468void QuadTree<O, OT, SH>::swap(QuadTree& other)
471 nodesAllocator_.swap(other.nodesAllocator_);
472 std::swap(aabb_, other.aabb_);
473 std::swap(root_, other.root_);
474 std::swap(end_, other.end_);
475 std::swap(numObjects_, other.numObjects_);
480template <
typename O,
typename OT,
typename SH>
481const typename QuadTree<O, OT, SH>::TObjectIterator
482QuadTree<O, OT, SH>::end()
const
492template <
typename O,
typename OT,
typename SH>
493template <
typename OutputIterator>
494OutputIterator QuadTree<O, OT, SH>::doFind(
495 const QuadNode& node,
const TAabb& box, OutputIterator output,
496 const TInfo* info)
const
498 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
502 const typename TObjectIterators::const_iterator end = node.data.end();
503 for (
typename TObjectIterators::const_iterator i = node.data.begin(); i != end; ++i)
505 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
506 if (TObjectTraits::objectIntersects(*i, box, info))
513 for (
size_t i = 0; i < numChildren; ++i)
515 if (node.children[i].bounds.intersects(box))
517 output = doFind(node.children[i], box, output, info);
525template <
typename O,
typename OT,
typename SH>
526template <
typename OutputIterator>
527OutputIterator QuadTree<O, OT, SH>::doFind(
528 const QuadNode& node,
529 const TRay& ray, TParam tMin, TParam tMax, OutputIterator output,
const TInfo* info,
530 const TVector& tNear,
const TVector& tFar,
const TPoint& support,
const TVector& invDir,
size_t flipMask)
const
532 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
534 const TValue tNearMax = this->maxComponent(tNear);
535 const TValue tFarMin = this->minComponent(tFar);
536 if (tNearMax > tFarMin * (1 +
num::sign(tFarMin) * 1e-3f))
543 const typename TObjectIterators::const_iterator end = node.data.end();
544 for (
typename TObjectIterators::const_iterator i = node.data.begin(); i != end; ++i)
546 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
547 if (TObjectTraits::objectIntersects(*i, ray, tMin, tMax, info))
555 const TVector tMiddle = invDir * (node.center() - support);
557 for (
size_t k = 0; k < dimension; ++k)
563 size_t i = this->entryNode(tNear, tMiddle);
566 const QuadNode& child = node.children[i ^ flipMask];
567 TVector tChildNear = tNear;
568 TVector tChildFar = tFar;
569 this->childNearAndFar(tChildNear, tChildFar, tMiddle, i);
570 output = doFind(child, ray, tMin, tMax, output, info, tChildNear, tChildFar, support, invDir, flipMask);
571 i = this->nextNode(i, tChildFar);
573 while (i !=
size_t(-1));
586template <
typename O,
typename OT,
typename SH>
587const typename QuadTree<O, OT, SH>::TObjectIterator
588QuadTree<O, OT, SH>::doIntersect(
589 const QuadNode& node,
590 const TRay& ray, TReference t, TParam tMin,
const TInfo* info,
591 const TVector& tNear,
const TVector& tFar,
const TPoint& support,
const TVector& invDir,
size_t flipMask)
const
593 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
595 const TValue tNearMax = std::max(this->maxComponent(tNear), tMin);
596 const TValue tFarMin = this->minComponent(tFar);
597 if (tNearMax > tFarMin * (1 +
num::sign(tFarMin) * 1e-3f))
604 const size_t n = node.data.size();
606 TObjectIterator best = end_;
607 for (
size_t i = 0; i < n; ++i)
609 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
610 TValue tCandidate = 0;
611 if (TObjectTraits::objectIntersect(node.data[i], ray, tCandidate, tMin, info))
613 LASS_ASSERT(tCandidate > tMin);
614 if (best == end_ || tCandidate < tBest)
616 LASS_ASSERT(tCandidate > tMin);
630 const TVector tMiddle = invDir * (node.center() - support);
632 for (
size_t k = 0; k < dimension; ++k)
638 TObjectIterator best = end_;
640 size_t i = this->entryNode(tNear, tMiddle);
643 const QuadNode& child = node.children[i ^ flipMask];
644 TVector tChildNear = tNear;
645 TVector tChildFar = tFar;
646 this->childNearAndFar(tChildNear, tChildFar, tMiddle, i);
649 TObjectIterator candidate = doIntersect(
650 child, ray, tCandidate, tMin, info, tChildNear, tChildFar, support, invDir, flipMask);
651 if (candidate != end_)
653 if (best == end_ || tCandidate < tBest)
660 const TValue tChildFarMin = this->minComponent(tChildFar);
661 if (best != end_ && tBest < tChildFarMin * (1 -
num::sign(tFarMin) * 1e-3f))
667 i = this->nextNode(i, tChildFar);
669 while (i !=
size_t(-1));
680template <
typename O,
typename OT,
typename SH>
681bool QuadTree<O, OT, SH>::doIntersects(
682 const QuadNode& node,
683 const TRay& ray, TParam tMin, TParam tMax,
const TInfo* info,
684 const TVector& tNear,
const TVector& tFar,
const TPoint& support,
const TVector& invDir,
size_t flipMask)
const
686 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
688 const TValue tNearMax = std::max(this->maxComponent(tNear), tMin);
689 const TValue tFarMin = std::min(this->minComponent(tFar), tMax);
690 if (tNearMax > tFarMin * (1 +
num::sign(tFarMin) * 1e-3f))
697 const size_t n = node.data.size();
698 for (
size_t i = 0; i < n; ++i)
700 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
701 if (TObjectTraits::objectIntersects(node.data[i], ray, tMin, tMax, info))
710 const TVector tMiddle = invDir * (node.center() - support);
712 for (
size_t k = 0; k < dimension; ++k)
718 size_t i = this->entryNode(tNear, tMiddle);
721 const QuadNode& child = node.children[i ^ flipMask];
722 TVector tChildNear = tNear;
723 TVector tChildFar = tFar;
724 this->childNearAndFar(tChildNear, tChildFar, tMiddle, i);
725 if (doIntersects(child, ray, tMin, tMax, info, tChildNear, tChildFar, support, invDir, flipMask))
729 i = this->nextNode(i, tChildFar);
731 while (i !=
size_t(-1));
738template <
typename O,
typename OT,
typename SH>
739void QuadTree<O, OT, SH>::doNearestNeighbour(
740 const QuadNode& node,
const TPoint& point,
const TInfo* info, Neighbour& best)
const
742 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
745 const size_t n = node.data.size();
746 for (
size_t i = 0; i < n; ++i)
748 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
749 const TValue squaredDistance =
750 TObjectTraits::objectSquaredDistance(node.data[i], point, info);
751 if (squaredDistance < best.squaredDistance())
753 best = Neighbour(node.data[i], squaredDistance);
760 TValue sqrNodeDists[numChildren];
761 size_t nearestNode = 0;
762 for (
size_t i = 0; i < numChildren; ++i)
764 sqrNodeDists[i] = node.children[i].sqrDistance(point);
765 if (sqrNodeDists[i] < sqrNodeDists[nearestNode])
772 if (sqrNodeDists[nearestNode] < best.squaredDistance())
774 doNearestNeighbour(node.children[nearestNode], point, info, best);
776 for (
size_t i = 0; i < numChildren; ++i)
778 if (sqrNodeDists[i] < best.squaredDistance() && i != nearestNode)
780 doNearestNeighbour(node.children[i], point, info, best);
788template <
typename O,
typename OT,
typename SH>
789template <
typename RandomIterator>
790RandomIterator QuadTree<O, OT, SH>::doRangeSearch(
791 const QuadNode& node,
const TPoint& target, TReference squaredRadius,
size_t maxCount,
792 RandomIterator first, RandomIterator last,
const TInfo* info)
const
794 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
795 LASS_ASSERT(squaredRadius >= 0);
799 const size_t n = node.data.size();
800 for (
size_t i = 0; i < n; ++i)
802 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
803 const TValue sqrDist = TObjectTraits::objectSquaredDistance(node.data[i], target, info);
804 if (sqrDist < squaredRadius)
806 Neighbour candidate(node.data[i], sqrDist);
809 if (std::find(first, last, candidate) == last)
812 std::push_heap(first, last);
813 LASS_ASSERT(last >= first);
814 if (
static_cast<size_t>(last - first) > maxCount)
816 std::pop_heap(first, last);
818 squaredRadius = first->squaredDistance();
827 TValue sqrNodeDists[numChildren];
828 size_t nearestNode = 0;
829 for (
size_t i = 0; i < numChildren; ++i)
831 sqrNodeDists[i] = node.children[i].sqrDistance(target);
832 if (sqrNodeDists[i] < sqrNodeDists[nearestNode])
838 if (sqrNodeDists[nearestNode] < squaredRadius)
840 last = doRangeSearch(node.children[nearestNode], target, squaredRadius, maxCount, first, last, info);
842 for (
size_t i = 0; i < numChildren; ++i)
844 if (sqrNodeDists[i] < squaredRadius && i != nearestNode)
846 last = doRangeSearch(node.children[i], target, squaredRadius, maxCount, first, last, info);
856template <
typename O,
typename OT,
typename SH>
857QuadTree<O, OT, SH>::QuadNode::QuadNode(
const TAabb& bounds, TNodesAllocator& allocator):
860 allocator_(allocator)
866template <
typename O,
typename OT,
typename SH>
867QuadTree<O, OT, SH>::QuadNode::~QuadNode()
869 deleteChildren(numChildren);
874template <
typename O,
typename OT,
typename SH>
875const typename QuadTree<O, OT, SH>::TPoint
876QuadTree<O, OT, SH>::QuadNode::center()
const
878 return QuadTree::middle(TObjectTraits::aabbMin(bounds), TObjectTraits::aabbMax(bounds));
883template <
typename O,
typename OT,
typename SH>
884const typename QuadTree<O, OT, SH>::TValue
885QuadTree<O, OT, SH>::QuadNode::sqrDistance(
const TPoint& point)
const
888 const TPoint& min = TObjectTraits::aabbMin(bounds);
889 const TPoint& max = TObjectTraits::aabbMax(bounds);
890 for (
size_t k = 0; k < dimension; ++k)
892 const TValue x = TObjectTraits::coord(point, k);
893 const TValue d = std::max(x - TObjectTraits::coord(max, k), TObjectTraits::coord(min, k) - x);
904template <
typename O,
typename OT,
typename SH>
905size_t QuadTree<O, OT, SH>::QuadNode::objectCount()
const
907 size_t cumulCount = data.size();
910 for (
size_t i=0;i<numChildren;++i)
912 cumulCount += children[i].objectCount();
920template <
typename O,
typename OT,
typename SH>
921void QuadTree<O, OT, SH>::QuadNode::add(
922 TObjectIterator
object,
const TSplitHeuristics& heuristics,
size_t level,
bool mayDecompose)
926 data.push_back(
object);
927 if (mayDecompose && data.size() > heuristics.maxObjectsPerLeaf() && level < heuristics.maxDepth())
929 decompose(heuristics, level);
934 bool isAdded =
false;
935 for (
size_t i=0;i<numChildren;++i)
937 if (TObjectTraits::objectIntersects(
object, children[i].bounds, 0))
939 children[i].add(
object, heuristics, level + 1);
943 LASS_ENFORCE(isAdded)(
"didn't overlap with any of the child nodes");
951template <
typename O,
typename OT,
typename SH>
952bool QuadTree<O, OT, SH>::QuadNode::remove(
953 TObjectIterator
object)
955 bool isRemoved =
false;
958 typename TObjectIterators::iterator last = std::remove(data.begin(), data.end(),
object);
959 isRemoved = last != data.end();
960 data.erase(last, data.end());
964 for (
size_t i=0;i<numChildren;++i)
966 if (TObjectTraits::objectIntersects(
object, children[i].bounds, 0))
968 isRemoved |= children[i].remove(
object);
977template <
typename O,
typename OT,
typename SH>
978void QuadTree<O, OT, SH>::QuadNode::decompose(
const TSplitHeuristics& heuristics,
size_t level)
988 for (
typename TObjectIterators::iterator vit = data.begin(); vit != data.end(); ++vit)
994 bool isAdded =
false;
995 for (
size_t i = 0; i < numChildren; ++i)
997 if (TObjectTraits::objectIntersects(*vit, children[i].bounds, 0))
999 children[i].add(*vit, heuristics, level + 1,
false);
1003 LASS_ENFORCE(isAdded)(
"object is not added to any of the sub nodes");
1011template <
typename O,
typename OT,
typename SH>
1012void QuadTree<O, OT, SH>::QuadNode::absorb()
1019 for (
size_t i=0;i<numChildren;++i)
1021 children[i].absorb();
1022 std::copy(children[i].data.begin(), children[i].data.end(), std::back_inserter(data));
1024 deleteChildren(numChildren);
1026 std::sort(data.begin(), data.end());
1027 typename TObjectIterators::iterator last = std::unique(data.begin(), data.end());
1028 data.erase(last, data.end());
1033template <
typename O,
typename OT,
typename SH>
1034size_t QuadTree<O, OT, SH>::QuadNode::depth()
const
1039 size_t depth=children[0].depth();
1040 for (
size_t i=1;i<numChildren;++i)
1047template <
typename O,
typename OT,
typename SH>
1048const typename QuadTree<O, OT, SH>::TValue
1049QuadTree<O, OT, SH>::QuadNode::averageDepth()
const
1055 for (
size_t i = 1; i < numChildren; ++i)
1056 depth += children[i].averageDepth();
1057 return depth / numChildren + 1;
1062template <
typename O,
typename OT,
typename SH>
1063void QuadTree<O, OT, SH>::QuadNode::makeChildren()
1070 const TPoint center = this->center();
1071 children =
static_cast<QuadNode*
>(allocator_.allocate());
1075 for (i = 0; i < numChildren; ++i)
1077 TPoint min = TObjectTraits::aabbMin(bounds);
1078 TPoint max = TObjectTraits::aabbMax(bounds);
1079 for (
size_t k = 0, mask = 1; k < dimension; ++k, mask *= 2)
1081 TObjectTraits::coord(i & mask ? min : max, k, TObjectTraits::coord(center, k));
1090 new (&children[i]) QuadNode(TObjectTraits::aabbMake(min, max), allocator_);
1102template <
typename O,
typename OT,
typename SH>
1103void QuadTree<O, OT, SH>::QuadNode::deleteChildren(
size_t count)
1111 children[--count].~QuadNode();
1113 allocator_.deallocate(children);