187 TSelf temp(std::move(other));
194template <
typename O,
typename OT,
typename SH>
195void QuadTree<O, OT, SH>::reset()
197 QuadTree temp(aabb_, end_,
static_cast<const SH&
>(*
this));
203template <
typename O,
typename OT,
typename SH>
204void QuadTree<O, OT, SH>::reset(TObjectIterator first, TObjectIterator last)
206 QuadTree temp(first, last,
static_cast<const SH&
>(*
this));
212template <
typename O,
typename OT,
typename SH>
216 if (!TObjectTraits::aabbContains(aabb_, TObjectTraits::objectAabb(
object)))
218 LASS_THROW(
"object not within bounding box of tree");
220 root_->add(
object, *
this);
226template <
typename O,
typename OT,
typename SH>
227void QuadTree<O, OT, SH>::remove(TObjectIterator
object)
230 if (root_->remove(
object))
238template <
typename O,
typename OT,
typename SH>
243 if (!TObjectTraits::aabbContains(aabb_, point))
248 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
249 QuadNode* node = root_;
250 while (!node->isLeaf())
252 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_NODE;
253 node = &node->children[this->findSubNode(node->center(), point)];
257 for (
typename TObjectIterators::const_iterator i = node->data.begin(); i != node->data.end(); ++i)
259 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
260 if (TObjectTraits::objectContains(*i, point, info))
270template <
typename O,
typename OT,
typename SH>
271template <
typename OutputIterator>
276 if (!TObjectTraits::aabbContains(aabb_, point))
281 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
282 QuadNode* node = root_;
283 while (!node->isLeaf())
285 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_NODE;
286 node = &node->children[this->findSubNode(node->center(), point)];
290 for (
typename TObjectIterators::const_iterator i = node->data.begin(); i != node->data.end(); ++i)
292 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
293 if (TObjectTraits::objectContains(*i, point, info))
306template <
typename O,
typename OT,
typename SH>
307template <
typename OutputIterator>
311 if (!TObjectTraits::aabbIntersects(aabb_, box))
315 return doFind(*root_, box, result, info);
323template <
typename O,
typename OT,
typename SH>
324template <
typename OutputIterator>
329 const TPoint min = TObjectTraits::aabbMin(aabb_);
330 const TPoint max = TObjectTraits::aabbMax(aabb_);
331 const TPoint support = TObjectTraits::raySupport(ray);
332 const TVector direction = TObjectTraits::rayDirection(ray);
333 const TVector invDirection = TObjectTraits::vectorReciprocal(direction);
335 TVector tNear = invDirection * (min - support);
336 TVector tFar = invDirection * (max - support);
337 const size_t flipMask = this->forceMinToMax(tNear, tFar);
339 return doFind(*root_, ray, tMin, tMax, result, info, tNear, tFar, support, invDirection, flipMask);
343template <
typename O,
typename OT,
typename SH>
344const typename QuadTree<O, OT, SH>::TObjectIterator
345QuadTree<O, OT, SH>::intersect(
346 const TRay& ray, TReference t, TParam tMin,
const TInfo* info)
const
350 const TPoint min = TObjectTraits::aabbMin(aabb_);
351 const TPoint max = TObjectTraits::aabbMax(aabb_);
352 const TPoint support = TObjectTraits::raySupport(ray);
353 const TVector direction = TObjectTraits::rayDirection(ray);
354 const TVector invDirection = TObjectTraits::vectorReciprocal(direction);
356 TVector tNear = invDirection * (min - support);
357 TVector tFar = invDirection * (max - support);
358 const size_t flipMask = this->forceMinToMax(tNear, tFar);
360 return doIntersect(*root_, ray, t, tMin, info, tNear, tFar, support, invDirection, flipMask);
365template <
typename O,
typename OT,
typename SH>
366bool QuadTree<O, OT, SH>::intersects(
367 const TRay& ray, TParam tMin, TParam tMax,
const TInfo* info)
const
371 const TPoint min = TObjectTraits::aabbMin(aabb_);
372 const TPoint max = TObjectTraits::aabbMax(aabb_);
373 const TPoint support = TObjectTraits::raySupport(ray);
374 const TVector direction = TObjectTraits::rayDirection(ray);
375 const TVector invDirection = TObjectTraits::vectorReciprocal(direction);
377 TVector tNear = invDirection * (min - support);
378 TVector tFar = invDirection * (max - support);
379 const size_t flipMask = this->forceMinToMax(tNear, tFar);
381 return doIntersects(*root_, ray, tMin, tMax, info, tNear, tFar, support, invDirection, flipMask);
386template <
typename O,
typename OT,
typename SH>
387const typename QuadTree<O, OT, SH>::Neighbour
388QuadTree<O, OT, SH>::nearestNeighbour(
const TPoint& point,
const TInfo* info)
const
391 Neighbour nearest(end_, std::numeric_limits<TValue>::infinity());
392 doNearestNeighbour(*root_, point, info, nearest);
398template <
typename O,
typename OT,
typename SH>
399template <
typename RandomAccessIterator>
401QuadTree<O, OT, SH>::rangeSearch(
402 const TPoint& target, TParam maxRadius,
size_t maxCount, RandomAccessIterator first,
403 const TInfo* info)
const
410 TValue squaredRadius = maxRadius * maxRadius;
411 return doRangeSearch(*root_, target, squaredRadius, maxCount, first, first, info);
416template <
typename O,
typename OT,
typename SH>
417size_t QuadTree<O, OT, SH>::objectCount()
const
420 return root_->objectCount();
425template <
typename O,
typename OT,
typename SH>
426const typename QuadTree<O, OT, SH>::TAabb&
427QuadTree<O, OT, SH>::aabb()
const
434template <
typename O,
typename OT,
typename SH>
438 return root_->depth();
444template <
typename O,
typename OT,
typename SH>
445const typename QuadTree<O, OT, SH>::TValue
446QuadTree<O, OT, SH>::averageDepth()
const
449 return root_->averageDepth();
454template <
typename O,
typename OT,
typename SH>
455bool QuadTree<O, OT, SH>::isEmpty()
const
457 return numObjects_ == 0;
462template <
typename O,
typename OT,
typename SH>
463void QuadTree<O, OT, SH>::swap(QuadTree& other)
466 nodesAllocator_.swap(other.nodesAllocator_);
467 std::swap(aabb_, other.aabb_);
468 std::swap(root_, other.root_);
469 std::swap(end_, other.end_);
470 std::swap(numObjects_, other.numObjects_);
475template <
typename O,
typename OT,
typename SH>
476const typename QuadTree<O, OT, SH>::TObjectIterator
477QuadTree<O, OT, SH>::end()
const
487template <
typename O,
typename OT,
typename SH>
488template <
typename OutputIterator>
489OutputIterator QuadTree<O, OT, SH>::doFind(
490 const QuadNode& node,
const TAabb& box, OutputIterator output,
491 const TInfo* info)
const
493 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
497 const typename TObjectIterators::const_iterator end = node.data.end();
498 for (
typename TObjectIterators::const_iterator i = node.data.begin(); i != end; ++i)
500 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
501 if (TObjectTraits::objectIntersects(*i, box, info))
508 for (
size_t i = 0; i < numChildren; ++i)
510 if (node.children[i].bounds.intersects(box))
512 output = doFind(node.children[i], box, output, info);
520template <
typename O,
typename OT,
typename SH>
521template <
typename OutputIterator>
522OutputIterator QuadTree<O, OT, SH>::doFind(
523 const QuadNode& node,
524 const TRay& ray, TParam tMin, TParam tMax, OutputIterator output,
const TInfo* info,
525 const TVector& tNear,
const TVector& tFar,
const TPoint& support,
const TVector& invDir,
size_t flipMask)
const
527 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
529 const TValue tNearMax = this->maxComponent(tNear);
530 const TValue tFarMin = this->minComponent(tFar);
531 if (tNearMax > tFarMin * (1 +
num::sign(tFarMin) * 1e-3f))
538 const typename TObjectIterators::const_iterator end = node.data.end();
539 for (
typename TObjectIterators::const_iterator i = node.data.begin(); i != end; ++i)
541 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
542 if (TObjectTraits::objectIntersects(*i, ray, tMin, tMax, info))
550 const TVector tMiddle = invDir * (node.center() - support);
552 for (
size_t k = 0; k < dimension; ++k)
558 size_t i = this->entryNode(tNear, tMiddle);
561 const QuadNode& child = node.children[i ^ flipMask];
562 TVector tChildNear = tNear;
563 TVector tChildFar = tFar;
564 this->childNearAndFar(tChildNear, tChildFar, tMiddle, i);
565 output = doFind(child, ray, tMin, tMax, output, info, tChildNear, tChildFar, support, invDir, flipMask);
566 i = this->nextNode(i, tChildFar);
568 while (i !=
size_t(-1));
581template <
typename O,
typename OT,
typename SH>
582const typename QuadTree<O, OT, SH>::TObjectIterator
583QuadTree<O, OT, SH>::doIntersect(
584 const QuadNode& node,
585 const TRay& ray, TReference t, TParam tMin,
const TInfo* info,
586 const TVector& tNear,
const TVector& tFar,
const TPoint& support,
const TVector& invDir,
size_t flipMask)
const
588 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
590 const TValue tNearMax = std::max(this->maxComponent(tNear), tMin);
591 const TValue tFarMin = this->minComponent(tFar);
592 if (tNearMax > tFarMin * (1 +
num::sign(tFarMin) * 1e-3f))
599 const size_t n = node.data.size();
601 TObjectIterator best = end_;
602 for (
size_t i = 0; i < n; ++i)
604 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
605 TValue tCandidate = 0;
606 if (TObjectTraits::objectIntersect(node.data[i], ray, tCandidate, tMin, info))
608 LASS_ASSERT(tCandidate > tMin);
609 if (best == end_ || tCandidate < tBest)
611 LASS_ASSERT(tCandidate > tMin);
625 const TVector tMiddle = invDir * (node.center() - support);
627 for (
size_t k = 0; k < dimension; ++k)
633 TObjectIterator best = end_;
635 size_t i = this->entryNode(tNear, tMiddle);
638 const QuadNode& child = node.children[i ^ flipMask];
639 TVector tChildNear = tNear;
640 TVector tChildFar = tFar;
641 this->childNearAndFar(tChildNear, tChildFar, tMiddle, i);
644 TObjectIterator candidate = doIntersect(
645 child, ray, tCandidate, tMin, info, tChildNear, tChildFar, support, invDir, flipMask);
646 if (candidate != end_)
648 if (best == end_ || tCandidate < tBest)
655 const TValue tChildFarMin = this->minComponent(tChildFar);
656 if (best != end_ && tBest < tChildFarMin * (1 -
num::sign(tFarMin) * 1e-3f))
662 i = this->nextNode(i, tChildFar);
664 while (i !=
size_t(-1));
675template <
typename O,
typename OT,
typename SH>
676bool QuadTree<O, OT, SH>::doIntersects(
677 const QuadNode& node,
678 const TRay& ray, TParam tMin, TParam tMax,
const TInfo* info,
679 const TVector& tNear,
const TVector& tFar,
const TPoint& support,
const TVector& invDir,
size_t flipMask)
const
681 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
683 const TValue tNearMax = std::max(this->maxComponent(tNear), tMin);
684 const TValue tFarMin = std::min(this->minComponent(tFar), tMax);
685 if (tNearMax > tFarMin * (1 +
num::sign(tFarMin) * 1e-3f))
692 const size_t n = node.data.size();
693 for (
size_t i = 0; i < n; ++i)
695 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
696 if (TObjectTraits::objectIntersects(node.data[i], ray, tMin, tMax, info))
705 const TVector tMiddle = invDir * (node.center() - support);
707 for (
size_t k = 0; k < dimension; ++k)
713 size_t i = this->entryNode(tNear, tMiddle);
716 const QuadNode& child = node.children[i ^ flipMask];
717 TVector tChildNear = tNear;
718 TVector tChildFar = tFar;
719 this->childNearAndFar(tChildNear, tChildFar, tMiddle, i);
720 if (doIntersects(child, ray, tMin, tMax, info, tChildNear, tChildFar, support, invDir, flipMask))
724 i = this->nextNode(i, tChildFar);
726 while (i !=
size_t(-1));
733template <
typename O,
typename OT,
typename SH>
734void QuadTree<O, OT, SH>::doNearestNeighbour(
735 const QuadNode& node,
const TPoint& point,
const TInfo* info, Neighbour& best)
const
737 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
740 const size_t n = node.data.size();
741 for (
size_t i = 0; i < n; ++i)
743 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
744 const TValue squaredDistance =
745 TObjectTraits::objectSquaredDistance(node.data[i], point, info);
746 if (squaredDistance < best.squaredDistance())
748 best = Neighbour(node.data[i], squaredDistance);
755 TValue sqrNodeDists[numChildren];
756 size_t nearestNode = 0;
757 for (
size_t i = 0; i < numChildren; ++i)
759 sqrNodeDists[i] = node.children[i].sqrDistance(point);
760 if (sqrNodeDists[i] < sqrNodeDists[nearestNode])
767 if (sqrNodeDists[nearestNode] < best.squaredDistance())
769 doNearestNeighbour(node.children[nearestNode], point, info, best);
771 for (
size_t i = 0; i < numChildren; ++i)
773 if (sqrNodeDists[i] < best.squaredDistance() && i != nearestNode)
775 doNearestNeighbour(node.children[i], point, info, best);
783template <
typename O,
typename OT,
typename SH>
784template <
typename RandomIterator>
785RandomIterator QuadTree<O, OT, SH>::doRangeSearch(
786 const QuadNode& node,
const TPoint& target, TReference squaredRadius,
size_t maxCount,
787 RandomIterator first, RandomIterator last,
const TInfo* info)
const
789 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
790 LASS_ASSERT(squaredRadius >= 0);
794 const size_t n = node.data.size();
795 for (
size_t i = 0; i < n; ++i)
797 LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
798 const TValue sqrDist = TObjectTraits::objectSquaredDistance(node.data[i], target, info);
799 if (sqrDist < squaredRadius)
801 Neighbour candidate(node.data[i], sqrDist);
804 if (std::find(first, last, candidate) == last)
807 std::push_heap(first, last);
808 LASS_ASSERT(last >= first);
809 if (
static_cast<size_t>(last - first) > maxCount)
811 std::pop_heap(first, last);
813 squaredRadius = first->squaredDistance();
822 TValue sqrNodeDists[numChildren];
823 size_t nearestNode = 0;
824 for (
size_t i = 0; i < numChildren; ++i)
826 sqrNodeDists[i] = node.children[i].sqrDistance(target);
827 if (sqrNodeDists[i] < sqrNodeDists[nearestNode])
833 if (sqrNodeDists[nearestNode] < squaredRadius)
835 last = doRangeSearch(node.children[nearestNode], target, squaredRadius, maxCount, first, last, info);
837 for (
size_t i = 0; i < numChildren; ++i)
839 if (sqrNodeDists[i] < squaredRadius && i != nearestNode)
841 last = doRangeSearch(node.children[i], target, squaredRadius, maxCount, first, last, info);
851template <
typename O,
typename OT,
typename SH>
852QuadTree<O, OT, SH>::QuadNode::QuadNode(
const TAabb& bounds, TNodesAllocator& allocator):
855 allocator_(allocator)
861template <
typename O,
typename OT,
typename SH>
862QuadTree<O, OT, SH>::QuadNode::~QuadNode()
864 deleteChildren(numChildren);
869template <
typename O,
typename OT,
typename SH>
870const typename QuadTree<O, OT, SH>::TPoint
871QuadTree<O, OT, SH>::QuadNode::center()
const
873 return QuadTree::middle(TObjectTraits::aabbMin(bounds), TObjectTraits::aabbMax(bounds));
878template <
typename O,
typename OT,
typename SH>
879const typename QuadTree<O, OT, SH>::TValue
880QuadTree<O, OT, SH>::QuadNode::sqrDistance(
const TPoint& point)
const
883 const TPoint& min = TObjectTraits::aabbMin(bounds);
884 const TPoint& max = TObjectTraits::aabbMax(bounds);
885 for (
size_t k = 0; k < dimension; ++k)
887 const TValue x = TObjectTraits::coord(point, k);
888 const TValue d = std::max(x - TObjectTraits::coord(max, k), TObjectTraits::coord(min, k) - x);
899template <
typename O,
typename OT,
typename SH>
900size_t QuadTree<O, OT, SH>::QuadNode::objectCount()
const
902 size_t cumulCount = data.size();
905 for (
size_t i=0;i<numChildren;++i)
907 cumulCount += children[i].objectCount();
915template <
typename O,
typename OT,
typename SH>
916void QuadTree<O, OT, SH>::QuadNode::add(
917 TObjectIterator
object,
const TSplitHeuristics& heuristics,
size_t level,
bool mayDecompose)
921 data.push_back(
object);
922 if (mayDecompose && data.size() > heuristics.maxObjectsPerLeaf() && level < heuristics.maxDepth())
924 decompose(heuristics, level);
929 bool isAdded =
false;
930 for (
size_t i=0;i<numChildren;++i)
932 if (TObjectTraits::objectIntersects(
object, children[i].bounds, 0))
934 children[i].add(
object, heuristics, level + 1);
938 LASS_ENFORCE(isAdded)(
"didn't overlap with any of the child nodes");
946template <
typename O,
typename OT,
typename SH>
947bool QuadTree<O, OT, SH>::QuadNode::remove(
948 TObjectIterator
object)
950 bool isRemoved =
false;
953 typename TObjectIterators::iterator last = std::remove(data.begin(), data.end(),
object);
954 isRemoved = last != data.end();
955 data.erase(last, data.end());
959 for (
size_t i=0;i<numChildren;++i)
961 if (TObjectTraits::objectIntersects(
object, children[i].bounds, 0))
963 isRemoved |= children[i].remove(
object);
972template <
typename O,
typename OT,
typename SH>
973void QuadTree<O, OT, SH>::QuadNode::decompose(
const TSplitHeuristics& heuristics,
size_t level)
983 for (
typename TObjectIterators::iterator vit = data.begin(); vit != data.end(); ++vit)
989 bool isAdded =
false;
990 for (
size_t i = 0; i < numChildren; ++i)
992 if (TObjectTraits::objectIntersects(*vit, children[i].bounds, 0))
994 children[i].add(*vit, heuristics, level + 1,
false);
998 LASS_ENFORCE(isAdded)(
"object is not added to any of the sub nodes");
1006template <
typename O,
typename OT,
typename SH>
1007void QuadTree<O, OT, SH>::QuadNode::absorb()
1014 for (
size_t i=0;i<numChildren;++i)
1016 children[i].absorb();
1017 std::copy(children[i].data.begin(), children[i].data.end(), std::back_inserter(data));
1019 deleteChildren(numChildren);
1021 std::sort(data.begin(), data.end());
1022 typename TObjectIterators::iterator last = std::unique(data.begin(), data.end());
1023 data.erase(last, data.end());
1028template <
typename O,
typename OT,
typename SH>
1029size_t QuadTree<O, OT, SH>::QuadNode::depth()
const
1034 size_t depth=children[0].depth();
1035 for (
size_t i=1;i<numChildren;++i)
1042template <
typename O,
typename OT,
typename SH>
1043const typename QuadTree<O, OT, SH>::TValue
1044QuadTree<O, OT, SH>::QuadNode::averageDepth()
const
1050 for (
size_t i = 1; i < numChildren; ++i)
1051 depth += children[i].averageDepth();
1052 return depth / numChildren + 1;
1057template <
typename O,
typename OT,
typename SH>
1058void QuadTree<O, OT, SH>::QuadNode::makeChildren()
1065 const TPoint center = this->center();
1066 children =
static_cast<QuadNode*
>(allocator_.allocate());
1070 for (i = 0; i < numChildren; ++i)
1072 TPoint min = TObjectTraits::aabbMin(bounds);
1073 TPoint max = TObjectTraits::aabbMax(bounds);
1074 for (
size_t k = 0, mask = 1; k < dimension; ++k, mask *= 2)
1076 TObjectTraits::coord(i & mask ? min : max, k, TObjectTraits::coord(center, k));
1085 new (&children[i]) QuadNode(TObjectTraits::aabbMake(min, max), allocator_);
1097template <
typename O,
typename OT,
typename SH>
1098void QuadTree<O, OT, SH>::QuadNode::deleteChildren(
size_t count)
1106 children[--count].~QuadNode();
1108 allocator_.deallocate(children);