11#ifndef CUBBYFLOW_OCTREE_IMPL_HPP
12#define CUBBYFLOW_OCTREE_IMPL_HPP
20bool Octree<T>::Node::IsLeaf()
const
22 return firstChild == std::numeric_limits<size_t>::max();
38 std::max({ m_bbox.Width(), m_bbox.Height(), m_bbox.Depth() });
44 m_nodes[0].items.resize(m_items.size());
45 std::iota(m_nodes[0].items.begin(), m_nodes[0].items.end(),
ZERO_SIZE);
65 best.distance = std::numeric_limits<double>::max();
69 std::stack<std::pair<const Node*, BoundingBox3D>>
todo;
75 while (
node !=
nullptr)
79 std::ranges::for_each(
81 const double distance = distanceFunc(m_items[itemIdx], pt);
83 if (distance < best.distance)
85 best.distance = distance;
86 best.item = &m_items[itemIdx];
92 using NodeDistBox = std::tuple<const Node*, double, BoundingBox3D>;
98 for (
int i = 0; i < 8; ++i)
100 const Node* child = &m_nodes[
node->firstChild + i];
112 return std::get<1>(a) > std::get<1>(b);
115 std::ranges::for_each(
133 bound =
todo.top().second;
175 best.distance = std::numeric_limits<double>::max();
184 return m_items.
begin();
190 return m_items.
end();
196 return m_items.
begin();
202 return m_items.
end();
208 return m_items.size();
220 return m_nodes.size();
251 if (
depth >= m_maxDepth || m_nodes[
nodeIdx].items.empty())
256 const size_t firstChild = m_nodes[nodeIdx].firstChild = m_nodes.size();
257 m_nodes.resize(m_nodes[nodeIdx].firstChild + 8);
259 BoundingBox3D bboxPerNode[8];
261 for (
int i = 0; i < 8; ++i)
263 bboxPerNode[i] = BoundingBox3D{ bound.
Corner(i), bound.
MidPoint() };
266 auto& currentItems = m_nodes[nodeIdx].items;
267 for (
size_t i = 0; i < currentItems.size(); ++i)
269 size_t currentItem = currentItems[i];
270 for (
int j = 0; j < 8; ++j)
272 if (testFunc(m_items[currentItem], bboxPerNode[j]))
274 m_nodes[firstChild + j].items.push_back(currentItem);
280 currentItems.clear();
283 for (
int i = 0; i < 8; ++i)
285 Build(firstChild + i, depth + 1, bboxPerNode[i], testFunc);
290bool Octree<T>::Intersects(
const BoundingBox3D& box,
291 const BoxIntersectionTestFunc3<T>& testFunc,
292 size_t nodeIdx,
const BoundingBox3D& bound)
const
294 if (!box.Overlaps(bound))
299 const Node& node = m_nodes[nodeIdx];
301 if (!node.items.empty())
303 for (
size_t itemIdx : node.items)
305 if (testFunc(m_items[itemIdx], box))
312 if (node.firstChild != std::numeric_limits<size_t>::max())
314 for (
int i = 0; i < 8; ++i)
316 if (Intersects(box, testFunc, node.firstChild + i,
317 BoundingBox3D{ bound.Corner(i), bound.MidPoint() }))
328bool Octree<T>::Intersects(
const Ray3D& ray,
329 const RayIntersectionTestFunc3<T>& testFunc,
330 size_t nodeIdx,
const BoundingBox3D& bound)
const
332 if (!bound.Intersects(ray))
337 const Node& node = m_nodes[nodeIdx];
339 if (!node.items.empty())
341 for (
size_t itemIdx : node.items)
343 if (testFunc(m_items[itemIdx], ray))
350 if (node.firstChild != std::numeric_limits<size_t>::max())
352 for (
int i = 0; i < 8; ++i)
354 if (Intersects(ray, testFunc, node.firstChild + i,
355 BoundingBox3D{ bound.Corner(i), bound.MidPoint() }))
366void Octree<T>::ForEachIntersectingItem(
367 const BoundingBox3D& box,
const BoxIntersectionTestFunc3<T>& testFunc,
368 const IntersectionVisitorFunc<T>& visitorFunc,
size_t nodeIdx,
369 const BoundingBox3D& bound)
const
371 if (!box.Overlaps(bound))
376 const Node& node = m_nodes[nodeIdx];
378 if (!node.items.empty())
380 for (
size_t itemIdx : node.items)
382 if (testFunc(m_items[itemIdx], box))
384 visitorFunc(m_items[itemIdx]);
389 if (node.firstChild != std::numeric_limits<size_t>::max())
391 for (
int i = 0; i < 8; ++i)
393 ForEachIntersectingItem(
394 box, testFunc, visitorFunc, node.firstChild + i,
395 BoundingBox3D{ bound.Corner(i), bound.MidPoint() });
401void Octree<T>::ForEachIntersectingItem(
402 const Ray3D& ray,
const RayIntersectionTestFunc3<T>& testFunc,
403 const IntersectionVisitorFunc<T>& visitorFunc,
size_t nodeIdx,
404 const BoundingBox3D& bound)
const
406 if (!bound.Intersects(ray))
411 const Node& node = m_nodes[nodeIdx];
413 if (!node.items.empty())
415 for (
size_t itemIdx : node.items)
417 if (testFunc(m_items[itemIdx], ray))
419 visitorFunc(m_items[itemIdx]);
424 if (node.firstChild != std::numeric_limits<size_t>::max())
426 for (
int i = 0; i < 8; ++i)
428 ForEachIntersectingItem(
429 ray, testFunc, visitorFunc, node.firstChild + i,
430 BoundingBox3D{ bound.Corner(i), bound.MidPoint() });
436ClosestIntersectionQueryResult3<T> Octree<T>::ClosestIntersection(
437 const Ray3D& ray,
const GetRayIntersectionFunc3<T>& testFunc,
438 size_t nodeIdx,
const BoundingBox3D& bound,
439 ClosestIntersectionQueryResult3<T> best)
const
441 if (!bound.Intersects(ray))
446 const Node& node = m_nodes[nodeIdx];
448 if (!node.items.empty())
450 for (
size_t itemIdx : node.items)
452 double dist = testFunc(m_items[itemIdx], ray);
453 if (dist < best.distance)
455 best.distance = dist;
456 best.item = &m_items[itemIdx];
461 if (node.firstChild != std::numeric_limits<size_t>::max())
463 for (
int i = 0; i < 8; ++i)
465 best = ClosestIntersection(
466 ray, testFunc, node.firstChild + i,
467 BoundingBox3D{ 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 octree data structure.
Definition Octree.hpp:31
NearestNeighborQueryResult3< T > Nearest(const Vector3D &pt, const NearestNeighborDistanceFunc3< T > &distanceFunc) const override
Definition Octree-Impl.hpp:60
void Build(const std::vector< T > &items, const BoundingBox3D &bound, const BoxIntersectionTestFunc3< T > &testFunc, size_t maxDepth)
Definition Octree-Impl.hpp:26
void Clear()
Clears all the contents of this instance.
Definition Octree-Impl.hpp:51
typename ContainerType::iterator Iterator
Definition Octree.hpp:34
typename ContainerType::const_iterator ConstIterator
Definition Octree.hpp:35
Iterator begin()
Returns the begin iterator of the item.
Definition Octree-Impl.hpp:182
Iterator end()
Returns the end iterator of the item.
Definition Octree-Impl.hpp:188
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
Matrix< T, Rows, 1 > Vector
Definition Matrix.hpp:719
BoundingBox3< double > BoundingBox3D
Definition BoundingBox.hpp:163