11 #ifndef CUBBYFLOW_OCTREE_IMPL_HPP 12 #define CUBBYFLOW_OCTREE_IMPL_HPP 20 bool Octree<T>::Node::IsLeaf()
const 22 return firstChild == std::numeric_limits<size_t>::max();
31 m_maxDepth = maxDepth;
37 const double maxEdgeLen =
38 std::max({ m_bbox.Width(), m_bbox.Height(), m_bbox.Depth() });
40 m_bbox.lowerCorner +
Vector3D{ maxEdgeLen, maxEdgeLen, maxEdgeLen };
44 m_nodes[0].items.resize(m_items.size());
45 std::iota(m_nodes[0].items.begin(), m_nodes[0].items.end(),
ZERO_SIZE);
47 Build(0, 1, m_bbox, testFunc);
65 best.
distance = std::numeric_limits<double>::max();
69 std::stack<std::pair<const Node*, BoundingBox3D>> todo;
72 const Node* node = m_nodes.data();
75 while (node !=
nullptr)
79 for (
size_t itemIdx : node->items)
81 double d = distanceFunc(m_items[itemIdx], pt);
85 best.
item = &m_items[itemIdx];
95 node = todo.top().first;
96 bound = todo.top().second;
101 using NodeDistBox = std::tuple<const Node*, double, BoundingBox3D>;
104 std::array<NodeDistBox, 8> childDistSqrPairs;
105 const auto midPoint = bound.
MidPoint();
107 for (
int i = 0; i < 8; ++i)
109 const Node* child = &m_nodes[node->firstChild + i];
110 const auto childBound =
115 childDistSqrPairs[i] =
116 std::make_tuple(child, distMinSqr, childBound);
119 std::sort(childDistSqrPairs.begin(), childDistSqrPairs.end(),
120 [](
const NodeDistBox& a,
const NodeDistBox& b) {
121 return std::get<1>(a) > std::get<1>(b);
124 for (
int i = 0; i < 8; ++i)
126 const auto& childPair = childDistSqrPairs[i];
128 if (std::get<1>(childPair) < bestDistSqr)
130 todo.emplace(std::get<0>(childPair),
131 std::get<2>(childPair));
140 node = todo.top().first;
141 bound = todo.top().second;
149 template <
typename T>
153 return Intersects(box, testFunc, 0, m_bbox);
156 template <
typename T>
160 return Intersects(ray, testFunc, 0, m_bbox);
163 template <
typename T>
168 ForEachIntersectingItem(box, testFunc, visitorFunc, 0, m_bbox);
171 template <
typename T>
176 ForEachIntersectingItem(ray, testFunc, visitorFunc, 0, m_bbox);
179 template <
typename T>
184 best.
distance = std::numeric_limits<double>::max();
187 return ClosestIntersection(ray, testFunc, 0, m_bbox, best);
190 template <
typename T>
193 return m_items.begin();
196 template <
typename T>
199 return m_items.end();
202 template <
typename T>
205 return m_items.begin();
208 template <
typename T>
211 return m_items.end();
214 template <
typename T>
217 return m_items.size();
220 template <
typename T>
226 template <
typename T>
229 return m_nodes.size();
232 template <
typename T>
235 return m_nodes[nodeIdx].items;
238 template <
typename T>
241 return m_nodes[nodeIdx].firstChild + childIdx;
244 template <
typename T>
250 template <
typename T>
256 template <
typename T>
260 if (depth < m_maxDepth && !m_nodes[nodeIdx].items.empty())
262 const size_t firstChild = m_nodes[nodeIdx].firstChild = m_nodes.size();
263 m_nodes.resize(m_nodes[nodeIdx].firstChild + 8);
267 for (
int i = 0; i < 8; ++i)
272 auto& currentItems = m_nodes[nodeIdx].items;
273 for (
size_t i = 0; i < currentItems.size(); ++i)
275 size_t currentItem = currentItems[i];
276 for (
int j = 0; j < 8; ++j)
278 if (testFunc(m_items[currentItem], bboxPerNode[j]))
280 m_nodes[firstChild + j].items.push_back(currentItem);
286 currentItems.clear();
289 for (
int i = 0; i < 8; ++i)
291 Build(firstChild + i, depth + 1, bboxPerNode[i], testFunc);
296 template <
typename T>
306 const Node& node = m_nodes[nodeIdx];
308 if (!node.items.empty())
310 for (
size_t itemIdx : node.items)
312 if (testFunc(m_items[itemIdx], box))
319 if (node.firstChild != std::numeric_limits<size_t>::max())
321 for (
int i = 0; i < 8; ++i)
323 if (Intersects(box, testFunc, node.firstChild + i,
334 template <
typename T>
344 const Node& node = m_nodes[nodeIdx];
346 if (!node.items.empty())
348 for (
size_t itemIdx : node.items)
350 if (testFunc(m_items[itemIdx], ray))
357 if (node.firstChild != std::numeric_limits<size_t>::max())
359 for (
int i = 0; i < 8; ++i)
361 if (Intersects(ray, testFunc, node.firstChild + i,
372 template <
typename T>
383 const Node& node = m_nodes[nodeIdx];
385 if (!node.items.empty())
387 for (
size_t itemIdx : node.items)
389 if (testFunc(m_items[itemIdx], box))
391 visitorFunc(m_items[itemIdx]);
396 if (node.firstChild != std::numeric_limits<size_t>::max())
398 for (
int i = 0; i < 8; ++i)
400 ForEachIntersectingItem(
401 box, testFunc, visitorFunc, node.firstChild + i,
407 template <
typename T>
418 const Node& node = m_nodes[nodeIdx];
420 if (!node.items.empty())
422 for (
size_t itemIdx : node.items)
424 if (testFunc(m_items[itemIdx], ray))
426 visitorFunc(m_items[itemIdx]);
431 if (node.firstChild != std::numeric_limits<size_t>::max())
433 for (
int i = 0; i < 8; ++i)
435 ForEachIntersectingItem(
436 ray, testFunc, visitorFunc, node.firstChild + i,
442 template <
typename T>
453 const Node& node = m_nodes[nodeIdx];
455 if (!node.items.empty())
457 for (
size_t itemIdx : node.items)
459 double dist = testFunc(m_items[itemIdx], ray);
463 best.
item = &m_items[itemIdx];
468 if (node.firstChild != std::numeric_limits<size_t>::max())
470 for (
int i = 0; i < 8; ++i)
472 best = ClosestIntersection(
473 ray, testFunc, node.firstChild + i,
ValueType DistanceSquaredTo(const MatrixExpression< T, R, C, E > &other) const
Returns the squared distance to the other vector.
void Clear()
Clears all the contents of this instance.
Definition: Octree-Impl.hpp:51
const BoundingBox3D & GetBoundingBox() const
Returns the bounding box of this octree.
Definition: Octree-Impl.hpp:245
NearestNeighborQueryResult3< T > Nearest(const Vector3D &pt, const NearestNeighborDistanceFunc3< T > &distanceFunc) const override
Definition: Octree-Impl.hpp:60
VectorType upperCorner
Upper corner of the bounding box.
Definition: BoundingBox.hpp:148
void ForEachIntersectingItem(const BoundingBox3D &box, const BoxIntersectionTestFunc3< T > &testFunc, const IntersectionVisitorFunc< T > &visitorFunc) const override
Invokes visitorFunc for every intersecting items.
Definition: Octree-Impl.hpp:164
size_t GetMaxDepth() const
Returns the maximum depth of the tree.
Definition: Octree-Impl.hpp:251
N-D nearest neighbor query result.
Definition: NearestNeighborQueryEngine.hpp:23
typename ContainerType::iterator Iterator
Definition: Octree.hpp:34
VectorType Corner(size_t idx) const
Returns corner position. Index starts from x-first order.
Definition: BoundingBox-Impl.hpp:240
Class for N-D ray.
Definition: Ray.hpp:25
ClosestIntersectionQueryResult3< T > ClosestIntersection(const Ray3D &ray, const GetRayIntersectionFunc3< T > &testFunc) const override
Returns the closest intersection for given ray.
Definition: Octree-Impl.hpp:180
size_t GetNumberOfItems() const
Returns the number of items.
Definition: Octree-Impl.hpp:215
bool Intersects(const BoundingBox3D &box, const BoxIntersectionTestFunc3< T > &testFunc) const override
Returns true if given box intersects with any of the stored items.
Definition: Octree-Impl.hpp:150
N-D axis-aligned bounding box class.
Definition: BoundingBox.hpp:46
const std::vector< size_t > & GetItemsAtNode(size_t nodeIdx) const
Returns the list of the items for given node index.
Definition: Octree-Impl.hpp:233
const T & GetItem(size_t i) const
Returns the item at i.
Definition: Octree-Impl.hpp:221
typename ContainerType::const_iterator ConstIterator
Definition: Octree.hpp:35
bool Intersects(const RayType &ray) const
Returns true if the input ray is intersecting with this box.
Definition: BoundingBox-Impl.hpp:119
Definition: Matrix.hpp:27
BoundingBox3< double > BoundingBox3D
Definition: BoundingBox.hpp:163
N-D closest intersection query result.
Definition: IntersectionQueryEngine.hpp:25
Definition: pybind11Utils.hpp:20
RayIntersectionTestFunc< T, 3 > RayIntersectionTestFunc3
3-D ray-item intersection test function.
Definition: IntersectionQueryEngine.hpp:76
const T * item
Definition: NearestNeighborQueryEngine.hpp:25
double distance
Definition: IntersectionQueryEngine.hpp:28
GetRayIntersectionFunc< T, 3 > GetRayIntersectionFunc3
3-D ray-item closest intersection evaluation function.
Definition: IntersectionQueryEngine.hpp:89
size_t GetNumberOfNodes() const
Returns the number of octree nodes.
Definition: Octree-Impl.hpp:227
BoxIntersectionTestFunc< T, 3 > BoxIntersectionTestFunc3
3-D box-item intersection test function.
Definition: IntersectionQueryEngine.hpp:63
constexpr size_t ZERO_SIZE
Zero size_t.
Definition: Constants.hpp:20
void Build(const std::vector< T > &items, const BoundingBox3D &bound, const BoxIntersectionTestFunc3< T > &testFunc, size_t maxDepth)
Definition: Octree-Impl.hpp:26
NearestNeighborDistanceFunc< T, 3 > NearestNeighborDistanceFunc3
3-D nearest neighbor distance measure function.
Definition: NearestNeighborQueryEngine.hpp:48
size_t GetChildIndex(size_t nodeIdx, size_t childIdx) const
Returns a child's index for given node.
Definition: Octree-Impl.hpp:239
bool Overlaps(const BoundingBox &other) const
Returns true of this box and other box overlaps.
Definition: BoundingBox-Impl.hpp:90
const T * item
Definition: IntersectionQueryEngine.hpp:27
VectorType MidPoint() const
Returns the mid-point of this box.
Definition: BoundingBox-Impl.hpp:194
Iterator begin()
Returns the begin iterator of the item.
Definition: Octree-Impl.hpp:191
double distance
Definition: NearestNeighborQueryEngine.hpp:26
std::function< void(const T &)> IntersectionVisitorFunc
Visitor function which is invoked for each intersecting item.
Definition: IntersectionQueryEngine.hpp:93
Iterator end()
Returns the end iterator of the item.
Definition: Octree-Impl.hpp:197