9 #ifndef CUBBYFLOW_BVH2_IMPL_H 10 #define CUBBYFLOW_BVH2_IMPL_H 17 BVH2<T>::Node::Node() : flags(0)
19 child = std::numeric_limits<size_t>::max();
23 void BVH2<T>::Node::InitLeaf(
size_t it,
const BoundingBox2D& b)
31 void BVH2<T>::Node::InitInternal(uint8_t axis,
size_t c,
const BoundingBox2D& b)
39 bool BVH2<T>::Node::IsLeaf()
const 52 const std::vector<BoundingBox2D>& itemsBounds)
55 m_itemBounds = itemsBounds;
64 for (
size_t i = 0; i < m_items.size(); ++i)
66 m_bound.Merge(m_itemBounds[i]);
69 std::vector<size_t> itemIndices(m_items.size());
70 std::iota(std::begin(itemIndices), std::end(itemIndices), 0);
72 Build(0, itemIndices.data(), m_items.size(), 0);
90 best.
distance = std::numeric_limits<double>::max();
94 static const int maxTreeDepth = 8 *
sizeof(size_t);
95 const Node* todo[maxTreeDepth];
99 const Node* node = m_nodes.data();
100 while (node !=
nullptr)
104 double dist = distanceFunc(m_items[node->item], pt);
108 best.
item = &m_items[node->item];
116 node = todo[todoPos];
127 const Node* left = node + 1;
128 const Node* right = &m_nodes[node->child];
134 Vector2D closestLeft = left->bound.Clamp(pt);
135 Vector2D closestRight = right->bound.Clamp(pt);
140 bool shouldVisitLeft = distMinLeftSqr < bestDistSqr;
141 bool shouldVisitRight = distMinRightSqr < bestDistSqr;
143 const Node* firstChild;
144 const Node* secondChild;
146 if (shouldVisitLeft && shouldVisitRight)
148 if (distMinLeftSqr < distMinRightSqr)
160 todo[todoPos] = secondChild;
164 else if (shouldVisitLeft)
168 else if (shouldVisitRight)
178 node = todo[todoPos];
191 template <
typename T>
195 if (!m_bound.Overlaps(box))
201 static const int kMaxTreeDepth = 8 *
sizeof(size_t);
202 const Node* todo[kMaxTreeDepth];
206 const Node* node = m_nodes.data();
208 while (node !=
nullptr)
212 if (testFunc(m_items[node->item], box))
222 node = todo[todoPos];
232 const Node* firstChild = node + 1;
233 const Node* secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
236 if (!firstChild->bound.Overlaps(box))
240 else if (!secondChild->bound.Overlaps(box))
247 todo[todoPos] = secondChild;
257 template <
typename T>
261 if (!m_bound.Intersects(ray))
267 static const int maxTreeDepth = 8 *
sizeof(size_t);
268 const Node* todo[maxTreeDepth];
272 const Node* node = m_nodes.data();
274 while (node !=
nullptr)
278 if (testFunc(m_items[node->item], ray))
288 node = todo[todoPos];
298 const Node* firstChild;
299 const Node* secondChild;
303 firstChild = node + 1;
304 secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
308 firstChild =
const_cast<Node*
>(&m_nodes[node->child]);
309 secondChild = node + 1;
313 if (!firstChild->bound.Intersects(ray))
317 else if (!secondChild->bound.Intersects(ray))
324 todo[todoPos] = secondChild;
334 template <
typename T>
339 if (!m_bound.Overlaps(box))
345 static const int maxTreeDepth = 8 *
sizeof(size_t);
346 const Node* todo[maxTreeDepth];
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>
404 if (!m_bound.Intersects(ray))
410 static const int maxTreeDepth = 8 *
sizeof(size_t);
411 const Node* todo[maxTreeDepth];
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>
480 best.
distance = std::numeric_limits<double>::max();
483 if (!m_bound.Intersects(ray))
489 static const int maxTreeDepth = 8 *
sizeof(size_t);
490 const Node* todo[maxTreeDepth];
494 const Node* node = m_nodes.data();
496 while (node !=
nullptr)
500 double dist = testFunc(m_items[node->item], ray);
504 best.
item = m_items.data() + node->item;
512 node = todo[todoPos];
522 const Node* firstChild;
523 const Node* secondChild;
527 firstChild = node + 1;
528 secondChild =
const_cast<Node*
>(&m_nodes[node->child]);
532 firstChild =
const_cast<Node*
>(&m_nodes[node->child]);
533 secondChild = node + 1;
537 if (!firstChild->bound.Intersects(ray))
541 else if (!secondChild->bound.Intersects(ray))
548 todo[todoPos] = secondChild;
558 template <
typename T>
564 template <
typename T>
567 return m_items.begin();
570 template <
typename T>
573 return m_items.end();
576 template <
typename T>
579 return m_items.begin();
582 template <
typename T>
585 return m_items.end();
588 template <
typename T>
591 return m_items.size();
594 template <
typename T>
600 template <
typename T>
601 size_t BVH2<T>::Build(
size_t nodeIndex,
size_t* itemIndices,
size_t nItems,
size_t currentDepth)
604 m_nodes.push_back(Node());
609 m_nodes[nodeIndex].InitLeaf(itemIndices[0], m_itemBounds[itemIndices[0]]);
610 return currentDepth + 1;
615 for (
size_t i = 0; i < nItems; ++i)
617 nodeBound.Merge(m_itemBounds[itemIndices[i]]);
620 Vector2D d = nodeBound.upperCorner - nodeBound.lowerCorner;
633 double pivot = 0.5 * (nodeBound.upperCorner[axis] + nodeBound.lowerCorner[axis]);
636 size_t midPoint = QSplit(itemIndices, nItems, pivot, axis);
639 size_t d0 = Build(nodeIndex + 1, itemIndices, midPoint, currentDepth + 1);
640 m_nodes[nodeIndex].InitInternal(axis, m_nodes.size(), nodeBound);
641 size_t d1 = Build(m_nodes[nodeIndex].child, itemIndices + midPoint, nItems - midPoint, currentDepth + 1);
643 return std::max(d0, d1);
646 template <
typename T>
647 size_t BVH2<T>::QSplit(
size_t* itemIndices,
size_t numItems,
double pivot, uint8_t axis)
651 for (
size_t i = 0; i < numItems; ++i)
654 double centroid = 0.5f * (b.lowerCorner[axis] + b.upperCorner[axis]);
656 if (centroid < pivot)
658 std::swap(itemIndices[i], itemIndices[ret]);
663 if (ret == 0 || ret == numItems)
double distance
Definition: NearestNeighborQueryEngine2.h:21
Iterator end()
Returns the end iterator of the item.
Definition: BVH2-Impl.h:571
Closest intersection query result.
Definition: IntersectionQueryEngine2.h:19
Class for 2-D ray.
Definition: Ray2.h:23
void Clear()
Clears all the contents of this instance.
Definition: BVH2-Impl.h:76
Vector2< T > direction
The direction of the ray.
Definition: Ray2.h:32
const T * item
Definition: IntersectionQueryEngine2.h:21
BoundingBox2< double > BoundingBox2D
Double-type 2-D BoundingBox.
Definition: BoundingBox2.h:126
std::function< bool(const T &, const BoundingBox2D &)> BoxIntersectionTestFunc2
Box-item intersection test function.
Definition: IntersectionQueryEngine2.h:31
Nearest neighbor query result.
Definition: NearestNeighborQueryEngine2.h:18
T DistanceSquaredTo(const Vector &other) const
Returns the squared distance to the other vector.
Definition: Vector2-Impl.h:308
typename ContainerType::const_iterator ConstIterator
Definition: BVH2.h:31
const T & GetItem(size_t i) const
Returns the item at i.
Definition: BVH2-Impl.h:595
const T * item
Definition: NearestNeighborQueryEngine2.h:20
void ForEachIntersectingItem(const BoundingBox2D &box, const BoxIntersectionTestFunc2< T > &testFunc, const IntersectionVisitorFunc2< T > &visitorFunc) const override
Invokes visitorFunc for every intersecting items.
Definition: BVH2-Impl.h:335
2-D axis-aligned bounding box class.
Definition: BoundingBox2.h:44
Definition: pybind11Utils.h:24
Vector2< double > Vector2D
Double-type 2D vector.
Definition: Vector2.h:341
std::function< void(const T &)> IntersectionVisitorFunc2
Visitor function which is invoked for each intersecting item.
Definition: IntersectionQueryEngine2.h:43
BVH2()
Default constructor.
Definition: BVH2-Impl.h:45
double distance
Definition: IntersectionQueryEngine2.h:22
NearestNeighborQueryResult2< T > GetNearestNeighbor(const Vector2D &pt, const NearestNeighborDistanceFunc2< T > &distanceFunc) const override
Definition: BVH2-Impl.h:85
bool IsIntersects(const BoundingBox2D &box, const BoxIntersectionTestFunc2< T > &testFunc) const override
Returns true if given box intersects with any of the stored items.
Definition: BVH2-Impl.h:192
Iterator begin()
Returns the begin iterator of the item.
Definition: BVH2-Impl.h:565
void Build(const std::vector< T > &items, const std::vector< BoundingBox2D > &itemsBounds)
Builds bounding volume hierarchy.
Definition: BVH2-Impl.h:51
2-D vector class.
Definition: Vector2.h:26
ClosestIntersectionQueryResult2< T > GetClosestIntersection(const Ray2D &ray, const GetRayIntersectionFunc2< T > &testFunc) const override
Returns the closest intersection for given ray.
Definition: BVH2-Impl.h:476
const BoundingBox2D & GetBoundingBox() const
Returns bounding box of every items.
Definition: BVH2-Impl.h:559
std::function< double(const T &, const Ray2D &)> GetRayIntersectionFunc2
Ray-item closest intersection evaluation function.
Definition: IntersectionQueryEngine2.h:39
BoundingBox3D bound
Bounding box of this box.
Definition: Box3.h:29
typename ContainerType::iterator Iterator
Definition: BVH2.h:30
size_t GetNumberOfItems() const
Returns the number of items.
Definition: BVH2-Impl.h:589
std::function< bool(const T &, const Ray2D &)> RayIntersectionTestFunc2
Ray-item intersection test function.
Definition: IntersectionQueryEngine2.h:35
std::function< double(const T &, const Vector2D &)> NearestNeighborDistanceFunc2
Nearest neighbor distance measure function.
Definition: NearestNeighborQueryEngine2.h:26