9 #ifndef CUBBYFLOW_OCTREE_IMPL_H 10 #define CUBBYFLOW_OCTREE_IMPL_H 18 bool Octree<T>::Node::IsLeaf()
const 20 return firstChild == std::numeric_limits<size_t>::max();
34 m_maxDepth = maxDepth;
40 double maxEdgeLen = std::max({ m_bbox.GetWidth(), m_bbox.GetHeight(), m_bbox.GetDepth() });
45 m_nodes[0].items.resize(m_items.size());
46 std::iota(m_nodes[0].items.begin(), m_nodes[0].items.end(),
ZERO_SIZE);
48 Build(0, 1, m_bbox, testFunc);
66 best.
distance = std::numeric_limits<double>::max();
70 std::stack<std::pair<const Node*, BoundingBox3D>> todo;
73 const Node* node = m_nodes.data();
76 while (node !=
nullptr)
80 for (
size_t itemIdx : node->items)
82 double d = distanceFunc(m_items[itemIdx], pt);
86 best.
item = &m_items[itemIdx];
96 node = todo.top().first;
97 bound = todo.top().second;
102 using NodeDistBox = std::tuple<const Node*, double, BoundingBox3D>;
105 std::array<NodeDistBox, 8> childDistSqrPairs;
106 const auto midPoint = bound.
MidPoint();
108 for (
int i = 0; i < 8; ++i)
110 const Node* child = &m_nodes[node->firstChild + i];
115 childDistSqrPairs[i] = std::make_tuple(child, distMinSqr, childBound);
118 std::sort(childDistSqrPairs.begin(), childDistSqrPairs.end(),
119 [](
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), std::get<2>(childPair));
139 node = todo.top().first;
140 bound = todo.top().second;
148 template <
typename T>
152 return IsIntersects(box, testFunc, 0, m_bbox);
155 template <
typename T>
159 return IsIntersects(ray, testFunc, 0, m_bbox);
162 template <
typename T>
167 ForEachIntersectingItem(box, testFunc, visitorFunc, 0, m_bbox);
170 template <
typename T>
175 ForEachIntersectingItem(ray, testFunc, visitorFunc, 0, m_bbox);
178 template <
typename T>
183 best.
distance = std::numeric_limits<double>::max();
186 return GetClosestIntersection(ray, testFunc, 0, m_bbox, best);
189 template <
typename T>
192 return m_items.begin();
195 template <
typename T>
198 return m_items.end();
201 template <
typename T>
204 return m_items.begin();
207 template <
typename T>
210 return m_items.end();
213 template <
typename T>
216 return m_items.size();
219 template <
typename T>
225 template <
typename T>
228 return m_nodes.size();
231 template <
typename T>
234 return m_nodes[nodeIdx].items;
237 template <
typename T>
240 return m_nodes[nodeIdx].firstChild + childIdx;
243 template <
typename T>
249 template <
typename T>
255 template <
typename T>
259 if (depth < m_maxDepth && !m_nodes[nodeIdx].items.empty())
261 size_t firstChild = m_nodes[nodeIdx].firstChild = m_nodes.size();
262 m_nodes.resize(m_nodes[nodeIdx].firstChild + 8);
266 for (
int i = 0; i < 8; ++i)
271 auto& currentItems = m_nodes[nodeIdx].items;
272 for (
size_t i = 0; i < currentItems.size(); ++i)
274 size_t currentItem = currentItems[i];
275 for (
int j = 0; j < 8; ++j)
277 if (testFunc(m_items[currentItem], bboxPerNode[j]))
279 m_nodes[firstChild + j].items.push_back(currentItem);
285 currentItems.clear();
288 for (
int i = 0; i < 8; ++i)
290 Build(firstChild + i, depth + 1, bboxPerNode[i], testFunc);
295 template <
typename T>
297 const BoxIntersectionTestFunc3<T>& testFunc,
300 if (!box.Overlaps(bound))
305 const Node& node = m_nodes[nodeIdx];
307 if (node.items.size() > 0)
309 for (
size_t itemIdx : node.items)
311 if (testFunc(m_items[itemIdx], box))
318 if (node.firstChild != std::numeric_limits<size_t>::max())
320 for (
int i = 0; i < 8; ++i)
322 if (IsIntersects(box, testFunc, node.firstChild + i,
BoundingBox3D(bound.Corner(i), bound.MidPoint())))
332 template <
typename T>
334 const RayIntersectionTestFunc3<T>& testFunc,
337 if (!bound.Intersects(ray))
342 const Node& node = m_nodes[nodeIdx];
344 if (node.items.size() > 0)
346 for (
size_t itemIdx : node.items)
348 if (testFunc(m_items[itemIdx], ray))
355 if (node.firstChild != std::numeric_limits<size_t>::max())
357 for (
int i = 0; i < 8; ++i)
359 if (IsIntersects(ray, testFunc, node.firstChild + i,
BoundingBox3D(bound.Corner(i), bound.MidPoint())))
369 template <
typename T>
371 const BoundingBox3D& box,
const BoxIntersectionTestFunc3<T>& testFunc,
372 const IntersectionVisitorFunc3<T>& visitorFunc,
size_t nodeIdx,
375 if (!box.Overlaps(bound))
380 const Node& node = m_nodes[nodeIdx];
382 if (node.items.size() > 0)
384 for (
size_t itemIdx : node.items)
386 if (testFunc(m_items[itemIdx], box))
388 visitorFunc(m_items[itemIdx]);
393 if (node.firstChild != std::numeric_limits<size_t>::max())
395 for (
int i = 0; i < 8; ++i)
397 ForEachIntersectingItem(
398 box, testFunc, visitorFunc, node.firstChild + i,
404 template <
typename T>
406 const Ray3D& ray,
const RayIntersectionTestFunc3<T>& testFunc,
407 const IntersectionVisitorFunc3<T>& visitorFunc,
size_t nodeIdx,
410 if (!bound.Intersects(ray))
415 const Node& node = m_nodes[nodeIdx];
417 if (node.items.size() > 0)
419 for (
size_t itemIdx : node.items)
421 if (testFunc(m_items[itemIdx], ray))
423 visitorFunc(m_items[itemIdx]);
428 if (node.firstChild != std::numeric_limits<size_t>::max())
430 for (
int i = 0; i < 8; ++i)
432 ForEachIntersectingItem(
433 ray, testFunc, visitorFunc, node.firstChild + i,
439 template <
typename T>
441 const Ray3D& ray,
const GetRayIntersectionFunc3<T>& testFunc,
443 ClosestIntersectionQueryResult3<T> best)
const 445 if (!bound.Intersects(ray))
450 const Node& node = m_nodes[nodeIdx];
452 if (node.items.size() > 0)
454 for (
size_t itemIdx : node.items)
456 double dist = testFunc(m_items[itemIdx], ray);
457 if (dist < best.distance)
459 best.distance = dist;
460 best.item = &m_items[itemIdx];
465 if (node.firstChild != std::numeric_limits<size_t>::max())
467 for (
int i = 0; i < 8; ++i)
469 best = GetClosestIntersection(
470 ray, testFunc, node.firstChild + i,
Vector3< T > Corner(size_t idx) const
Returns corner position. Index starts from x-first order.
Definition: BoundingBox3-Impl.h:237
void Clear()
Clears all the contents of this instance.
Definition: Octree-Impl.h:52
3-D vector class.
Definition: Vector3.h:26
const BoundingBox3D & GetBoundingBox() const
Returns the bounding box of this octree.
Definition: Octree-Impl.h:244
size_t GetMaxDepth() const
Returns the maximum depth of the tree.
Definition: Octree-Impl.h:250
typename ContainerType::iterator Iterator
Definition: Octree.h:31
size_t GetNumberOfItems() const
Returns the number of items.
Definition: Octree-Impl.h:214
const T * item
Definition: NearestNeighborQueryEngine3.h:20
ClosestIntersectionQueryResult3< T > GetClosestIntersection(const Ray3D &ray, const GetRayIntersectionFunc3< T > &testFunc) const override
Returns the closest intersection for given ray.
Definition: Octree-Impl.h:179
const std::vector< size_t > & GetItemsAtNode(size_t nodeIdx) const
Returns the list of the items for given node index.
Definition: Octree-Impl.h:232
const T & GetItem(size_t i) const
Returns the item at i.
Definition: Octree-Impl.h:220
typename ContainerType::const_iterator ConstIterator
Definition: Octree.h:32
std::function< bool(const T &, const BoundingBox3D &)> BoxIntersectionTestFunc3
Box-item intersection test function.
Definition: IntersectionQueryEngine3.h:31
T DistanceSquaredTo(const Vector &other) const
Returns the squared distance to the other vector.
Definition: Vector3-Impl.h:332
Ray3< double > Ray3D
Double-type 3-D ray.
Definition: Ray3.h:54
const T * item
Definition: IntersectionQueryEngine3.h:21
NearestNeighborQueryResult3< T > GetNearestNeighbor(const Vector3D &pt, const NearestNeighborDistanceFunc3< T > &distanceFunc) const override
Definition: Octree-Impl.h:61
BoundingBox3< double > BoundingBox3D
Double-type 3-D BoundingBox.
Definition: BoundingBox3.h:129
std::function< double(const T &, const Ray3D &)> GetRayIntersectionFunc3
Ray-item closest intersection evaluation function.
Definition: IntersectionQueryEngine3.h:39
double distance
Definition: IntersectionQueryEngine3.h:22
Definition: pybind11Utils.h:24
Vector3< T > upperCorner
Upper corner of the bounding box.
Definition: BoundingBox3.h:51
Octree()
Default constructor.
Definition: Octree-Impl.h:24
3-D axis-aligned bounding box class.
Definition: BoundingBox3.h:44
Closest intersection query result.
Definition: IntersectionQueryEngine3.h:19
double distance
Definition: NearestNeighborQueryEngine3.h:21
size_t GetNumberOfNodes() const
Returns the number of octree nodes.
Definition: Octree-Impl.h:226
Vector3< T > MidPoint() const
Returns the mid-point of this box.
Definition: BoundingBox3-Impl.h:179
bool IsIntersects(const BoundingBox3D &box, const BoxIntersectionTestFunc3< T > &testFunc) const override
Returns true if given box intersects with any of the stored items.
Definition: Octree-Impl.h:149
constexpr size_t ZERO_SIZE
Zero size_t.
Definition: Constants.h:18
void Build(const std::vector< T > &items, const BoundingBox3D &bound, const BoxIntersectionTestFunc3< T > &testFunc, size_t maxDepth)
Definition: Octree-Impl.h:30
size_t GetChildIndex(size_t nodeIdx, size_t childIdx) const
Returns a child's index for given node.
Definition: Octree-Impl.h:238
std::function< void(const T &)> IntersectionVisitorFunc3
Visitor function which is invoked for each intersecting item.
Definition: IntersectionQueryEngine3.h:43
std::function< bool(const T &, const Ray3D &)> RayIntersectionTestFunc3
Ray-item intersection test function.
Definition: IntersectionQueryEngine3.h:35
Nearest neighbor query result.
Definition: NearestNeighborQueryEngine3.h:18
Iterator begin()
Returns the begin iterator of the item.
Definition: Octree-Impl.h:190
Class for 3-D ray.
Definition: Ray3.h:23
void ForEachIntersectingItem(const BoundingBox3D &box, const BoxIntersectionTestFunc3< T > &testFunc, const IntersectionVisitorFunc3< T > &visitorFunc) const override
Invokes visitorFunc for every intersecting items.
Definition: Octree-Impl.h:163
Iterator end()
Returns the end iterator of the item.
Definition: Octree-Impl.h:196
Vector3< double > Vector3D
Double-type 3D vector.
Definition: Vector3.h:353
std::function< double(const T &, const Vector3D &)> NearestNeighborDistanceFunc3
Nearest neighbor distance measure function.
Definition: NearestNeighborQueryEngine3.h:26