11 #ifndef CUBBYFLOW_BVH_IMPL_HPP 12 #define CUBBYFLOW_BVH_IMPL_HPP 18 template <
typename T,
size_t N>
19 BVH<T, N>::Node::Node() : flags(0)
21 child = std::numeric_limits<size_t>::max();
24 template <
typename T,
size_t N>
25 void BVH<T, N>::Node::InitLeaf(
size_t it,
const BoundingBox<double, N>& b)
27 flags =
static_cast<char>(N);
32 template <
typename T,
size_t N>
33 void BVH<T, N>::Node::InitInternal(uint8_t axis,
size_t c,
34 const BoundingBox<double, N>& b)
41 template <
typename T,
size_t N>
42 bool BVH<T, N>::Node::IsLeaf()
const 44 return flags ==
static_cast<char>(N);
47 template <
typename T,
size_t N>
53 m_itemBounds = itemsBounds;
55 if (m_items.IsEmpty())
63 for (
size_t i = 0; i < m_items.Length(); ++i)
65 m_bound.
Merge(m_itemBounds[i]);
69 std::iota(std::begin(itemIndices), std::end(itemIndices), 0);
71 Build(0, itemIndices.data(), m_items.Length(), 0);
74 template <
typename T,
size_t N>
83 template <
typename T,
size_t N>
89 best.
distance = std::numeric_limits<double>::max();
93 static const int kMaxTreeDepth = 8 *
sizeof(size_t);
94 const Node* todo[kMaxTreeDepth];
98 const Node* node = m_nodes.data();
99 while (node !=
nullptr)
103 if (
double dist = distanceFunc(m_items[node->item], pt);
107 best.
item = &m_items[node->item];
115 node = todo[todoPos];
126 const Node* left = node + 1;
127 const Node* right = &m_nodes[node->child];
139 const bool shouldVisitLeft = distMinLeftSqr < bestDistSqr;
140 const bool shouldVisitRight = distMinRightSqr < bestDistSqr;
142 if (shouldVisitLeft && shouldVisitRight)
144 const Node* secondChild;
145 const Node* firstChild;
147 if (distMinLeftSqr < distMinRightSqr)
159 todo[todoPos] = secondChild;
163 else if (shouldVisitLeft)
167 else if (shouldVisitRight)
177 node = todo[todoPos];
190 template <
typename T,
size_t N>
194 if (!m_bound.Overlaps(box))
200 static const int MAX_TREE_DEPTH = 8 *
sizeof(size_t);
201 const Node* todo[MAX_TREE_DEPTH];
205 const Node* node = m_nodes.data();
207 while (node !=
nullptr)
211 if (testFunc(m_items[node->item], box))
221 node = todo[todoPos];
231 const Node* firstChild = node + 1;
232 const Node* secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
235 if (!firstChild->bound.Overlaps(box))
239 else if (!secondChild->bound.Overlaps(box))
246 todo[todoPos] = secondChild;
256 template <
typename T,
size_t N>
260 if (!m_bound.Intersects(ray))
266 static const int kMaxTreeDepth = 8 *
sizeof(size_t);
267 const Node* todo[kMaxTreeDepth];
271 const Node* node = m_nodes.data();
273 while (node !=
nullptr)
277 if (testFunc(m_items[node->item], ray))
287 node = todo[todoPos];
297 const Node* firstChild;
298 const Node* secondChild;
302 firstChild = node + 1;
303 secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
307 firstChild =
const_cast<Node*
>(&m_nodes[node->child]);
308 secondChild = node + 1;
312 if (!firstChild->bound.Intersects(ray))
316 else if (!secondChild->bound.Intersects(ray))
323 todo[todoPos] = secondChild;
333 template <
typename T,
size_t N>
339 if (!m_bound.Overlaps(box))
345 static const int MAX_TREE_DEPTH = 8 *
sizeof(size_t);
346 const Node* todo[MAX_TREE_DEPTH];
350 const Node* node = m_nodes.data();
352 while (node !=
nullptr)
356 if (testFunc(m_items[node->item], box))
358 visitorFunc(m_items[node->item]);
366 node = todo[todoPos];
376 const Node* firstChild = node + 1;
377 const Node* secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
380 if (!firstChild->bound.Overlaps(box))
384 else if (!secondChild->bound.Overlaps(box))
391 todo[todoPos] = secondChild;
399 template <
typename T,
size_t N>
404 if (!m_bound.Intersects(ray))
410 static const int MAX_TREE_DEPTH = 8 *
sizeof(size_t);
411 const Node* todo[MAX_TREE_DEPTH];
415 const Node* node = m_nodes.data();
417 while (node !=
nullptr)
421 if (testFunc(m_items[node->item], ray))
423 visitorFunc(m_items[node->item]);
431 node = todo[todoPos];
441 const Node* firstChild;
442 const Node* secondChild;
446 firstChild = node + 1;
447 secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
451 firstChild =
const_cast<Node*
>(&m_nodes[node->child]);
452 secondChild = node + 1;
456 if (!firstChild->bound.Intersects(ray))
460 else if (!secondChild->bound.Intersects(ray))
467 todo[todoPos] = secondChild;
475 template <
typename T,
size_t N>
481 best.
distance = std::numeric_limits<double>::max();
484 if (!m_bound.Intersects(ray))
490 static const int MAX_TREE_DEPTH = 8 *
sizeof(size_t);
491 const Node* todo[MAX_TREE_DEPTH];
495 const Node* node = m_nodes.data();
497 while (node !=
nullptr)
501 if (
double dist = testFunc(m_items[node->item], ray);
505 best.
item = m_items.data() + node->item;
513 node = todo[todoPos];
523 const Node* firstChild;
524 const Node* secondChild;
528 firstChild = node + 1;
529 secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
533 firstChild =
const_cast<Node*
>(&m_nodes[node->child]);
534 secondChild = node + 1;
538 if (!firstChild->bound.Intersects(ray))
542 else if (!secondChild->bound.Intersects(ray))
549 todo[todoPos] = secondChild;
559 template <
typename T,
size_t N>
565 template <
typename T,
size_t N>
568 return m_items.
begin();
571 template <
typename T,
size_t N>
574 return m_items.
end();
577 template <
typename T,
size_t N>
580 return m_items.
begin();
583 template <
typename T,
size_t N>
586 return m_items.
end();
589 template <
typename T,
size_t N>
592 return m_items.Length();
595 template <
typename T,
size_t N>
601 template <
typename T,
size_t N>
604 return m_nodes.Length();
607 template <
typename T,
size_t N>
612 return std::make_pair(std::numeric_limits<size_t>::max(),
613 std::numeric_limits<size_t>::max());
616 return std::make_pair(i + 1, m_nodes[i].child);
619 template <
typename T,
size_t N>
622 return m_nodes[i].
IsLeaf();
625 template <
typename T,
size_t N>
628 return m_nodes[i].bound;
631 template <
typename T,
size_t N>
636 return m_nodes[i].item + begin();
642 template <
typename T,
size_t N>
647 return m_nodes[i].item + begin();
653 template <
typename T,
size_t N>
654 size_t BVH<T, N>::Build(
size_t nodeIndex,
size_t* itemIndices,
size_t nItems,
658 m_nodes.Append(Node{});
663 m_nodes[nodeIndex].InitLeaf(itemIndices[0],
664 m_itemBounds[itemIndices[0]]);
665 return currentDepth + 1;
670 for (
size_t i = 0; i < nItems; ++i)
672 nodeBound.
Merge(m_itemBounds[itemIndices[i]]);
684 const size_t midPoint = QSplit(itemIndices, nItems, pivot, axis);
688 Build(nodeIndex + 1, itemIndices, midPoint, currentDepth + 1);
689 m_nodes[nodeIndex].InitInternal(axis, m_nodes.Length(), nodeBound);
690 const size_t d1 = Build(m_nodes[nodeIndex].child, itemIndices + midPoint,
691 nItems - midPoint, currentDepth + 1);
693 return std::max(d0, d1);
696 template <
typename T,
size_t N>
702 for (
size_t i = 0; i < numItems; ++i)
706 if (
const double centroid =
710 std::swap(itemIndices[i], itemIndices[ret]);
715 if (ret == 0 || ret == numItems)
ValueType DistanceSquaredTo(const MatrixExpression< T, R, C, E > &other) const
Returns the squared distance to the other vector.
VectorType upperCorner
Upper corner of the bounding box.
Definition: BoundingBox.hpp:148
N-D nearest neighbor query result.
Definition: NearestNeighborQueryEngine.hpp:23
Class for N-D ray.
Definition: Ray.hpp:25
Definition: Matrix.hpp:27
N-D closest intersection query result.
Definition: IntersectionQueryEngine.hpp:25
Definition: pybind11Utils.hpp:20
size_t DominantAxis() const
Definition: MatrixExpression-Impl.hpp:206
Definition: Array-Impl.hpp:19
Iterator begin()
Returns the begin Iterator of the item.
Definition: BVH-Impl.hpp:566
const T * item
Definition: NearestNeighborQueryEngine.hpp:25
std::function< bool(const T &, const BoundingBox< double, N > &)> BoxIntersectionTestFunc
N-D box-item intersection test function.
Definition: IntersectionQueryEngine.hpp:55
double distance
Definition: IntersectionQueryEngine.hpp:28
Iterator end()
Returns the end Iterator of the item.
Definition: BVH-Impl.hpp:572
typename ContainerType::Iterator Iterator
Definition: BVH.hpp:35
VectorType lowerCorner
Lower corner of the bounding box.
Definition: BoundingBox.hpp:145
void Merge(const VectorType &point)
Merges this and other point.
Definition: BoundingBox-Impl.hpp:219
VectorType direction
The direction of the ray.
Definition: Ray.hpp:38
Generic N-dimensional array class interface.
Definition: Array.hpp:32
typename ContainerType::ConstIterator ConstIterator
Definition: BVH.hpp:36
const T * item
Definition: IntersectionQueryEngine.hpp:27
std::function< double(const T &, const Vector< double, N > &)> NearestNeighborDistanceFunc
N-D nearest neighbor distance measure function.
Definition: NearestNeighborQueryEngine.hpp:40
std::function< bool(const T &, const Ray< double, N > &)> RayIntersectionTestFunc
N-D ray-item intersection test function.
Definition: IntersectionQueryEngine.hpp:68
Bounding Volume Hierarchy (BVH) in N-D.
Definition: BVH.hpp:30
std::function< double(const T &, const Ray< double, N > &)> GetRayIntersectionFunc
N-D ray-item closest intersection evaluation function.
Definition: IntersectionQueryEngine.hpp:81
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
bool IsLeaf(size_t i) const
Returns true if i-th node is a leaf node.
Definition: BVH-Impl.hpp:620