11#ifndef CUBBYFLOW_QUADTREE_IMPL_HPP
12#define CUBBYFLOW_QUADTREE_IMPL_HPP
20bool Quadtree<T>::Node::IsLeaf()
const
22 return firstChild == std::numeric_limits<size_t>::max();
37 const double maxEdgeLen = std::max(m_bbox.Width(), m_bbox.Height());
43 m_nodes[0].items.resize(m_items.size());
44 std::iota(m_nodes[0].items.begin(), m_nodes[0].items.end(),
ZERO_SIZE);
64 best.distance = std::numeric_limits<double>::max();
68 std::stack<std::pair<const Node*, BoundingBox2D>>
todo;
73 while (
node !=
nullptr)
77 std::ranges::for_each(
79 const double distance = distanceFunc(m_items[itemIdx], pt);
81 if (distance < best.distance)
83 best.distance = distance;
84 best.item = &m_items[itemIdx];
92 typedef std::tuple<const Node*, double, BoundingBox2D>
NodeDistBox;
94 const auto MidPoint = bound.
MidPoint();
95 for (
int i = 0; i < 4; ++i)
97 const Node* child = &m_nodes[
node->firstChild + i];
108 return std::get<1>(a) > std::get<1>(b);
111 std::ranges::for_each(
129 bound =
todo.top().second;
171 best.distance = std::numeric_limits<double>::max();
180 return m_items.
begin();
186 return m_items.
end();
192 return m_items.
begin();
198 return m_items.
end();
204 return m_items.size();
216 return m_nodes.size();
248 if (
depth >= m_maxDepth || m_nodes[
nodeIdx].items.empty())
253 const size_t firstChild = m_nodes[nodeIdx].firstChild = m_nodes.size();
254 m_nodes.resize(m_nodes[nodeIdx].firstChild + 4);
256 BoundingBox2D bboxPerNode[4];
258 for (
int i = 0; i < 4; ++i)
260 bboxPerNode[i] = BoundingBox2D{ bound.
Corner(i), bound.
MidPoint() };
263 auto& currentItems = m_nodes[nodeIdx].items;
264 for (
size_t i = 0; i < currentItems.size(); ++i)
266 size_t currentItem = currentItems[i];
267 for (
int j = 0; j < 4; ++j)
269 if (testFunc(m_items[currentItem], bboxPerNode[j]))
271 m_nodes[firstChild + j].items.push_back(currentItem);
277 currentItems.clear();
280 for (
int i = 0; i < 4; ++i)
282 Build(firstChild + i, depth + 1, bboxPerNode[i], testFunc);
287bool Quadtree<T>::Intersects(
const BoundingBox2D& box,
288 const BoxIntersectionTestFunc2<T>& testFunc,
289 size_t nodeIdx,
const BoundingBox2D& bound)
const
291 if (!box.Overlaps(bound))
296 const Node& node = m_nodes[nodeIdx];
298 if (node.items.size() > 0)
300 for (
size_t itemIdx : node.items)
302 if (testFunc(m_items[itemIdx], box))
309 if (node.firstChild != std::numeric_limits<size_t>::max())
311 for (
int i = 0; i < 4; ++i)
313 if (Intersects(box, testFunc, node.firstChild + i,
314 BoundingBox2D{ bound.Corner(i), bound.MidPoint() }))
325bool Quadtree<T>::Intersects(
const Ray2D& ray,
326 const RayIntersectionTestFunc2<T>& testFunc,
327 size_t nodeIdx,
const BoundingBox2D& bound)
const
329 if (!bound.Intersects(ray))
334 const Node& node = m_nodes[nodeIdx];
336 if (node.items.size() > 0)
338 for (
size_t itemIdx : node.items)
340 if (testFunc(m_items[itemIdx], ray))
347 if (node.firstChild != std::numeric_limits<size_t>::max())
349 for (
int i = 0; i < 4; ++i)
351 if (Intersects(ray, testFunc, node.firstChild + i,
352 BoundingBox2D{ bound.Corner(i), bound.MidPoint() }))
363void Quadtree<T>::ForEachIntersectingItem(
364 const BoundingBox2D& box,
const BoxIntersectionTestFunc2<T>& testFunc,
365 const IntersectionVisitorFunc<T>& visitorFunc,
size_t nodeIdx,
366 const BoundingBox2D& bound)
const
368 if (!box.Overlaps(bound))
373 const Node& node = m_nodes[nodeIdx];
375 if (node.items.size() > 0)
377 for (
size_t itemIdx : node.items)
379 if (testFunc(m_items[itemIdx], box))
381 visitorFunc(m_items[itemIdx]);
386 if (node.firstChild != std::numeric_limits<size_t>::max())
388 for (
int i = 0; i < 4; ++i)
390 ForEachIntersectingItem(
391 box, testFunc, visitorFunc, node.firstChild + i,
392 BoundingBox2D{ bound.Corner(i), bound.MidPoint() });
398void Quadtree<T>::ForEachIntersectingItem(
399 const Ray2D& ray,
const RayIntersectionTestFunc2<T>& testFunc,
400 const IntersectionVisitorFunc<T>& visitorFunc,
size_t nodeIdx,
401 const BoundingBox2D& bound)
const
403 if (!bound.Intersects(ray))
408 const Node& node = m_nodes[nodeIdx];
410 if (node.items.size() > 0)
412 for (
size_t itemIdx : node.items)
414 if (testFunc(m_items[itemIdx], ray))
416 visitorFunc(m_items[itemIdx]);
421 if (node.firstChild != std::numeric_limits<size_t>::max())
423 for (
int i = 0; i < 4; ++i)
425 ForEachIntersectingItem(
426 ray, testFunc, visitorFunc, node.firstChild + i,
427 BoundingBox2D{ bound.Corner(i), bound.MidPoint() });
433ClosestIntersectionQueryResult2<T> Quadtree<T>::ClosestIntersection(
434 const Ray2D& ray,
const GetRayIntersectionFunc2<T>& testFunc,
435 size_t nodeIdx,
const BoundingBox2D& bound,
436 ClosestIntersectionQueryResult2<T> best)
const
438 if (!bound.Intersects(ray))
443 const Node& node = m_nodes[nodeIdx];
445 if (node.items.size() > 0)
447 for (
size_t itemIdx : node.items)
449 double dist = testFunc(m_items[itemIdx], ray);
450 if (dist < best.distance)
452 best.distance = dist;
453 best.item = &m_items[itemIdx];
458 if (node.firstChild != std::numeric_limits<size_t>::max())
460 for (
int i = 0; i < 4; ++i)
462 best = ClosestIntersection(
463 ray, testFunc, node.firstChild + i,
464 BoundingBox2D{ bound.Corner(i), bound.MidPoint() }, best);
N-D axis-aligned bounding box class.
Definition BoundingBox.hpp:47
VectorType MidPoint() const
Returns the mid-point of this box.
Definition BoundingBox-Impl.hpp:189
VectorType Corner(size_t idx) const
Returns corner position. Index starts from x-first order.
Definition BoundingBox-Impl.hpp:235
ValueType DistanceSquaredTo(const MatrixExpression< T, R, C, E > &other) const
Returns the squared distance to the other vector.
Iterator begin()
Definition Matrix-Impl.hpp:272
Pointer data()
Definition Matrix-Impl.hpp:298
Iterator end()
Definition Matrix-Impl.hpp:285
Generic quadtree data structure.
Definition Quadtree.hpp:31
void Build(const std::vector< T > &items, const BoundingBox2D &bound, const BoxIntersectionTestFunc2< T > &testFunc, size_t maxDepth)
Definition Quadtree-Impl.hpp:26
Iterator begin()
Returns the begin iterator of the item.
Definition Quadtree-Impl.hpp:178
NearestNeighborQueryResult2< T > Nearest(const Vector2D &pt, const NearestNeighborDistanceFunc2< T > &distanceFunc) const override
Definition Quadtree-Impl.hpp:59
typename ContainerType::iterator Iterator
Definition Quadtree.hpp:34
void Clear()
Clears all the contents of this instance.
Definition Quadtree-Impl.hpp:50
typename ContainerType::const_iterator ConstIterator
Definition Quadtree.hpp:35
Iterator end()
Returns the end iterator of the item.
Definition Quadtree-Impl.hpp:184
Class for N-D ray.
Definition Ray.hpp:26
Definition pybind11Utils.hpp:22
constexpr size_t ZERO_SIZE
Zero size_t.
Definition Constants.hpp:20
BoundingBox2< double > BoundingBox2D
Definition BoundingBox.hpp:159
Matrix< T, Rows, 1 > Vector
Definition Matrix.hpp:719