PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
AabbKdTreeHierarchy.h
Go to the documentation of this file.
1
9
10#ifndef PBAT_GEOMETRY_AABBKDTREEHIERARCHY_H
11#define PBAT_GEOMETRY_AABBKDTREEHIERARCHY_H
12
13#include "KdTree.h"
14#include "SpatialSearch.h"
15#include "pbat/Aliases.h"
18#include "pbat/math/linalg/mini/Eigen.h"
20
21#include <Eigen/Core>
22
23namespace pbat::geometry {
38template <auto Dims>
39class AabbKdTreeHierarchy
40{
41public:
42 static auto constexpr kDims = Dims;
43 using SelfType = AabbKdTreeHierarchy<kDims>;
44
45 AabbKdTreeHierarchy() = default;
57 template <class TDerivedL, class TDerivedU>
59 Eigen::DenseBase<TDerivedL> const& L,
60 Eigen::DenseBase<TDerivedU> const& U,
61 Index maxPointsInLeaf = 8);
73 template <class TDerivedL, class TDerivedU>
75 Eigen::DenseBase<TDerivedL> const& L,
76 Eigen::DenseBase<TDerivedU> const& U,
77 Index maxPointsInLeaf = 8);
93 template <class TDerivedL, class TDerivedU>
94 void Update(Eigen::DenseBase<TDerivedL> const& L, Eigen::DenseBase<TDerivedU> const& U);
106 template <class FNodeOverlaps, class FObjectOverlaps, class FOnOverlap>
107 void
109 FNodeOverlaps fNodeOverlaps,
110 FObjectOverlaps fObjectOverlaps,
111 FOnOverlap fOnOverlap)
112 const;
127 template <class FDistanceToNode, class FDistanceToObject, class FOnNearestNeighbour>
129 FDistanceToNode fDistanceToNode,
130 FDistanceToObject fDistanceToObject,
131 FOnNearestNeighbour fOnNearestNeighbour,
132 Scalar radius = std::numeric_limits<Scalar>::max(),
133 Scalar eps = Scalar(0)) const;
147 template <class FDistanceToNode, class FDistanceToObject, class FOnNearestNeighbour>
149 FDistanceToNode fDistanceToNode,
150 FDistanceToObject fDistanceToObject,
151 FOnNearestNeighbour fOnNearestNeighbour,
152 Index K,
153 Scalar radius = std::numeric_limits<Scalar>::max()) const;
162 template <class FObjectsOverlap, class FOnSelfOverlap>
163 void SelfOverlaps(FObjectsOverlap fObjectsOverlap, FOnSelfOverlap fOnSelfOverlap) const;
175 template <class FObjectsOverlap, class FOnOverlap>
176 void
177 Overlaps(SelfType const& rhs, FObjectsOverlap fObjectsOverlap, FOnOverlap fOnOverlap) const;
178
185 auto InternalNodeBoundingBoxes() const -> Matrix<2 * kDims, Eigen::Dynamic> const&
186 {
187 return IB;
188 }
189
194 auto Tree() const -> KdTree<kDims> const& { return tree; }
201 auto Lower(Index node) const { return IB.col(node).template head<kDims>(); }
208 auto Upper(Index node) const { return IB.col(node).template tail<kDims>(); }
209
210private:
212 IB;
216 KdTree<kDims> tree;
217};
218
219template <auto Dims>
220template <class TDerivedL, class TDerivedU>
221inline AabbKdTreeHierarchy<Dims>::AabbKdTreeHierarchy(
222 Eigen::DenseBase<TDerivedL> const& L,
223 Eigen::DenseBase<TDerivedU> const& U,
224 Index maxPointsInLeaf)
225{
226 Construct(L, U, maxPointsInLeaf);
227}
228
229template <auto Dims>
230template <class TDerivedL, class TDerivedU>
232 Eigen::DenseBase<TDerivedL> const& L,
233 Eigen::DenseBase<TDerivedU> const& U,
234 Index maxPointsInLeaf)
235{
236 PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.AabbKdTreeHierarchy.Construct");
237 Matrix<kDims, Eigen::Dynamic> P = 0.5 * (L.derived() + U.derived());
238 tree.Construct(P, maxPointsInLeaf);
239 auto const nNodes = static_cast<Index>(tree.Nodes().size());
240 IB.resize(2 * kDims, nNodes);
241 IB.template topRows<kDims>().setConstant(std::numeric_limits<Scalar>::max());
242 IB.template bottomRows<kDims>().setConstant(std::numeric_limits<Scalar>::lowest());
243}
244
245template <auto Dims>
246template <class TDerivedL, class TDerivedU>
248 Eigen::DenseBase<TDerivedL> const& L,
249 Eigen::DenseBase<TDerivedU> const& U)
250{
251 PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.AabbKdTreeHierarchy.Update");
252 KdTreeNode const* nodes = tree.Nodes().data();
253 IndexVectorX const& perm = tree.Permutation();
255 [&](Index n) {
256 KdTreeNode const& node = nodes[n];
257 if (node.IsLeaf())
258 {
259 auto inds = perm(Eigen::seqN(node.begin, node.n));
260 IB.col(n).template head<kDims>() = L(Eigen::placeholders::all, inds).rowwise().
261 minCoeff();
262 IB.col(n).template tail<kDims>() = U(Eigen::placeholders::all, inds).rowwise().
263 maxCoeff();
264 }
265 else
266 {
267 // Our k-D tree's internal nodes always have both children.
268 auto nbox = IB.col(n);
269 auto lbox = IB.col(node.Left());
270 auto rbox = IB.col(node.Right());
271 nbox.template head<kDims>() = lbox.template head<kDims>().cwiseMin(
272 rbox.template head<kDims>());
273 nbox.template tail<kDims>() = lbox.template tail<kDims>().cwiseMax(
274 rbox.template tail<kDims>());
275 }
276 },
277 [&]<auto c>(Index n) -> Index {
278 if constexpr (c == 0)
279 return nodes[n].Left();
280 else
281 return nodes[n].Right();
282 });
283}
284
285template <auto Dims>
286template <class FNodeOverlaps, class FObjectOverlaps, class FOnOverlap>
288 FNodeOverlaps fNodeOverlaps,
289 FObjectOverlaps fObjectOverlaps,
290 FOnOverlap fOnOverlap) const
291{
292 PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.AabbKdTreeHierarchy.Overlaps");
293 KdTreeNode const* nodes = tree.Nodes().data();
294 IndexVectorX const& perm = tree.Permutation();
296 [&]<auto c>(Index n) -> Index {
297 if constexpr (c == 0)
298 return nodes[n].Left();
299 else
300 return nodes[n].Right();
301 },
302 [&](Index n) { return nodes[n].IsLeaf(); },
303 [&](Index n) { return nodes[n].n; },
304 [&](Index n, Index i) { return perm(nodes[n].begin + i); },
305 [&](Index n) {
306 auto L = IB.col(n).template head<kDims>();
307 auto U = IB.col(n).template tail<kDims>();
308 using TDerivedL = decltype(L);
309 using TDerivedU = decltype(U);
310 return fNodeOverlaps.template operator()<TDerivedL, TDerivedU>(L, U);
311 },
312 fObjectOverlaps,
313 fOnOverlap);
314}
315
316template <auto Dims>
317template <class FDistanceToNode, class FDistanceToObject, class FOnNearestNeighbour>
319 FDistanceToNode fDistanceToNode,
320 FDistanceToObject fDistanceToObject,
321 FOnNearestNeighbour fOnNearestNeighbour,
322 Scalar radius,
323 Scalar eps) const
324{
325 PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.AabbKdTreeHierarchy.NearestNeighbours");
326 KdTreeNode const* nodes = tree.Nodes().data();
327 IndexVectorX const& perm = tree.Permutation();
329 [&]<auto c>(Index n) -> Index {
330 if constexpr (c == 0)
331 return nodes[n].Left();
332 else
333 return nodes[n].Right();
334 },
335 [&](Index n) { return nodes[n].IsLeaf(); },
336 [&](Index n) { return nodes[n].n; },
337 [&](Index n, Index i) { return perm(nodes[n].begin + i); },
338 [&](Index n) {
339 auto L = IB.col(n).template head<kDims>();
340 auto U = IB.col(n).template tail<kDims>();
341 using TDerivedL = decltype(L);
342 using TDerivedU = decltype(U);
343 return fDistanceToNode.template operator()<TDerivedL, TDerivedU>(L, U);
344 },
345 fDistanceToObject,
346 fOnNearestNeighbour,
347 false /*bUseBestFirstSearch*/,
348 radius,
349 eps);
350}
351
352template <auto Dims>
353template <class FDistanceToNode, class FDistanceToObject, class FOnNearestNeighbour>
355 FDistanceToNode fDistanceToNode,
356 FDistanceToObject fDistanceToObject,
357 FOnNearestNeighbour fOnNearestNeighbour,
358 Index K,
359 Scalar radius) const
360{
361 PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.AabbKdTreeHierarchy.KNearestNeighbours");
362 KdTreeNode const* nodes = tree.Nodes().data();
363 IndexVectorX const& perm = tree.Permutation();
365 [&]<auto c>(Index n) -> Index {
366 if constexpr (c == 0)
367 return nodes[n].Left();
368 else
369 return nodes[n].Right();
370 },
371 [&](Index n) { return nodes[n].IsLeaf(); },
372 [&](Index n) { return nodes[n].n; },
373 [&](Index n, Index i) { return perm(nodes[n].begin + i); },
374 [&](Index n) {
375 auto L = IB.col(n).template head<kDims>();
376 auto U = IB.col(n).template tail<kDims>();
377 using TDerivedL = decltype(L);
378 using TDerivedU = decltype(U);
379 return fDistanceToNode.template operator()<TDerivedL, TDerivedU>(L, U);
380 },
381 fDistanceToObject,
382 fOnNearestNeighbour,
383 K,
384 radius);
385}
386
387template <auto Dims>
388template <class FObjectsOverlap, class FOnSelfOverlap>
390 FObjectsOverlap fObjectsOverlap,
391 FOnSelfOverlap fOnSelfOverlap) const
392{
393 PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.AabbKdTreeHierarchy.SelfOverlaps");
394 KdTreeNode const* nodes = tree.Nodes().data();
395 IndexVectorX const& perm = tree.Permutation();
397 [&]<auto c>(Index n) -> Index {
398 if constexpr (c == 0)
399 return nodes[n].Left();
400 else
401 return nodes[n].Right();
402 },
403 [&](Index n) { return nodes[n].IsLeaf(); },
404 [&](Index n) { return nodes[n].n; },
405 [&](Index n, Index i) { return perm(nodes[n].begin + i); },
406 [&](Index n1, Index n2) {
407 using math::linalg::mini::FromEigen;
408 auto L1 = IB.col(n1).template head<kDims>();
409 auto U1 = IB.col(n1).template tail<kDims>();
410 auto L2 = IB.col(n2).template head<kDims>();
411 auto U2 = IB.col(n2).template tail<kDims>();
413 FromEigen(L1),
414 FromEigen(U1),
415 FromEigen(L2),
416 FromEigen(U2));
417 },
418 fObjectsOverlap,
419 fOnSelfOverlap);
420}
421
422template <auto Dims>
423template <class FObjectsOverlap, class FOnOverlap>
425 SelfType const& rhs,
426 FObjectsOverlap fObjectsOverlap,
427 FOnOverlap fOnOverlap) const
428{
429 PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.AabbKdTreeHierarchy.Overlaps");
430 // This tree will be the left-hand side tree
431 KdTreeNode const* nodes = tree.Nodes().data();
432 IndexVectorX const& perm = tree.Permutation();
433 auto const fChildLhs = [&]<auto c>(Index n) -> Index {
434 if constexpr (c == 0)
435 return nodes[n].Left();
436 else
437 return nodes[n].Right();
438 };
439 auto const fIsLeafLhs = [&](Index n) {
440 return nodes[n].IsLeaf();
441 };
442 auto const fLeafSizeLhs = [&]([[maybe_unused]] Index n) {
443 return nodes[n].n;
444 };
445 auto const fLeafObjectLhs = [&](Index n, [[maybe_unused]] Index i) {
446 return perm(nodes[n].begin + i);
447 };
448 // This tree will be the right-hand side tree
449 KdTreeNode const* nodesRhs = rhs.tree.Nodes().data();
450 IndexVectorX const& permRhs = rhs.tree.Permutation();
451 auto const fChildRhs = [&]<auto c>(Index n) -> Index {
452 if constexpr (c == 0)
453 return nodesRhs[n].Left();
454 else
455 return nodesRhs[n].Right();
456 };
457 auto const fIsLeafRhs = [&](Index n) {
458 return nodesRhs[n].IsLeaf();
459 };
460 auto const fLeafSizeRhs = [&]([[maybe_unused]] Index n) {
461 return nodesRhs[n].n;
462 };
463 auto const fLeafObjectRhs = [&](Index n, [[maybe_unused]] Index i) {
464 return permRhs(nodesRhs[n].begin + i);
465 };
466 // Register overlaps
468 fChildLhs,
469 fIsLeafLhs,
470 fLeafSizeLhs,
471 fLeafObjectLhs,
472 fChildRhs,
473 fIsLeafRhs,
474 fLeafSizeRhs,
475 fLeafObjectRhs,
476 [&](Index n1, Index n2) {
477 using math::linalg::mini::FromEigen;
478 auto L1 = IB.col(n1).template head<kDims>();
479 auto U1 = IB.col(n1).template tail<kDims>();
480 auto L2 = rhs.IB.col(n2).template head<kDims>();
481 auto U2 = rhs.IB.col(n2).template tail<kDims>();
483 FromEigen(L1),
484 FromEigen(U1),
485 FromEigen(L2),
486 FromEigen(U2));
487 },
488 fObjectsOverlap,
489 fOnOverlap);
490}
491} // namespace pbat::geometry
492
493#endif // PBAT_GEOMETRY_AABBKDTREEHIERARCHY_H
This file contains the KdTree class.
Generic n-ary tree traversals.
This file contains functions to answer overlap queries.
Generic efficient spatial search query implementations.
auto Tree() const -> KdTree< kDims > const &
Get the underlying k-D tree.
Definition AabbKdTreeHierarchy.h:194
static auto constexpr kDims
Definition AabbKdTreeHierarchy.h:42
void Overlaps(FNodeOverlaps fNodeOverlaps, FObjectOverlaps fObjectOverlaps, FOnOverlap fOnOverlap) const
Find all objects that overlap with some user-defined query.
Definition AabbKdTreeHierarchy.h:287
auto InternalNodeBoundingBoxes() const -> Matrix< 2 *kDims, Eigen::Dynamic > const &
Get the internal node bounding boxes.
Definition AabbKdTreeHierarchy.h:185
AabbKdTreeHierarchy(Eigen::DenseBase< TDerivedL > const &L, Eigen::DenseBase< TDerivedU > const &U, Index maxPointsInLeaf=8)
Construct an Aabb Hierarchy from an input AABB matrices L, U.
Definition AabbKdTreeHierarchy.h:221
void Overlaps(SelfType const &rhs, FObjectsOverlap fObjectsOverlap, FOnOverlap fOnOverlap) const
Find all object pairs that overlap with another hierarchy.
Definition AabbKdTreeHierarchy.h:424
AabbKdTreeHierarchy< kDims > SelfType
Type of this template instantiation.
Definition AabbKdTreeHierarchy.h:43
void Construct(Eigen::DenseBase< TDerivedL > const &L, Eigen::DenseBase< TDerivedU > const &U, Index maxPointsInLeaf=8)
Construct an Aabb Hierarchy from an input AABB matrix B.
Definition AabbKdTreeHierarchy.h:231
void NearestNeighbours(FDistanceToNode fDistanceToNode, FDistanceToObject fDistanceToObject, FOnNearestNeighbour fOnNearestNeighbour, Scalar radius=std::numeric_limits< Scalar >::max(), Scalar eps=Scalar(0)) const
Find the nearest neighbour to some user-defined query. If there are multiple nearest neighbours,...
Definition AabbKdTreeHierarchy.h:318
void Update(Eigen::DenseBase< TDerivedL > const &L, Eigen::DenseBase< TDerivedU > const &U)
Recomputes k-D tree node AABBs given the object AABBs.
Definition AabbKdTreeHierarchy.h:247
void KNearestNeighbours(FDistanceToNode fDistanceToNode, FDistanceToObject fDistanceToObject, FOnNearestNeighbour fOnNearestNeighbour, Index K, Scalar radius=std::numeric_limits< Scalar >::max()) const
Find the K nearest neighbours to some user-defined query.
Definition AabbKdTreeHierarchy.h:354
auto Upper(Index node) const
Obtain the upper bound of the AABB of a node.
Definition AabbKdTreeHierarchy.h:208
auto Lower(Index node) const
Obtain the lower bound of the AABB of a node.
Definition AabbKdTreeHierarchy.h:201
void SelfOverlaps(FObjectsOverlap fObjectsOverlap, FOnSelfOverlap fOnSelfOverlap) const
Find all object pairs that overlap.
Definition AabbKdTreeHierarchy.h:389
KDTree class.
Definition KdTree.h:66
std::vector< KdTreeNode > const & Nodes() const
Returns the nodes of the k-D tree.
Definition KdTree.h:120
IndexVectorX const & Permutation() const
Returns the permutation of the points in the k-D tree.
Definition KdTree.h:129
PBAT_HOST_DEVICE void TraverseNAryTreePseudoPostOrder(FVisit fVisit, FChild fChild, TIndex root=0)
Post-order traversal over an n-ary tree starting from root.
Definition NAryTreeTraversal.h:84
PBAT_HOST_DEVICE bool AxisAlignedBoundingBoxes(TMatrixL1 const &L1, TMatrixU1 const &U1, TMatrixL2 const &L2, TMatrixU2 const &U2)
Tests for overlap between axis-aligned bounding box (L1,U1) and axis-aligned bounding box (L2,...
Definition OverlapQueries.h:608
Geometric queries, quantities and data structures.
Definition AabbKdTreeHierarchy.h:23
PBAT_HOST_DEVICE bool KNearestNeighbours(FChild fChild, FIsLeaf fIsLeaf, FLeafSize fLeafSize, FLeafObject fLeafObject, FDistanceLowerBound fLower, FDistance fDistance, FOnFound fOnFound, TIndex K, TScalar fUpper=std::numeric_limits< TScalar >::max(), TIndex root=0)
Find the (sorted) K objects with the smallest distances in a branch and bound tree rooted in root.
Definition SpatialSearch.h:1050
PBAT_HOST_DEVICE bool DfsAllNearestNeighbours(FChild fChild, FIsLeaf fIsLeaf, FLeafSize fLeafSize, FLeafObject fLeafObject, FDistanceLowerBound fLower, FDistance fDistance, FOnFound fOnFound, bool bUseBestFirstSearch=false, TScalar fUpper=std::numeric_limits< TScalar >::max(), TScalar eps=TScalar(0), TIndex root=0)
Find distance minimizing objects in branch and bound tree rooted in root.
Definition SpatialSearch.h:763
PBAT_HOST_DEVICE bool SelfOverlaps(FChild fChild, FIsLeaf fIsLeaf, FLeafSize fLeafSize, FLeafObject fLeafObject, FNodesOverlap fNodesOverlap, FObjectsOverlap fObjectsOverlap, FOnFound fOnFound, TIndex root=0)
Compute overlapping nodes from a branch and bound tree rooted in root.
Definition SpatialSearch.h:612
PBAT_HOST_DEVICE bool Overlaps(FChild fChild, FIsLeaf fIsLeaf, FLeafSize fLeafSize, FLeafObject fLeafObject, FNodeOverlap fNodeOverlaps, FObjectOverlap fObjectOverlaps, FOnFound fOnFound, TIndex root=0)
Find all nodes in a branch and bound tree that overlap with a given object.
Definition SpatialSearch.h:438
Eigen::Vector< Index, Eigen::Dynamic > IndexVectorX
Dynamic-size index vector type.
Definition Aliases.h:49
std::ptrdiff_t Index
Index type.
Definition Aliases.h:17
double Scalar
Scalar type.
Definition Aliases.h:18
Eigen::Matrix< Scalar, Rows, Cols > Matrix
Fixed-size matrix type.
Definition Aliases.h:31
Profiling utilities for the Physics-Based Animation Toolkit (PBAT)
Node of a KDTree.
Definition KdTree.h:31
Index begin
Index to first point encapsulated in this node's AABB in the permutation list.
Definition KdTree.h:33
bool IsLeaf() const
Returns true if this node is a leaf node, false otherwise.
Definition KdTree.h:42
Index n
Definition KdTree.h:34
auto Right() const
Returns right child node.
Definition KdTree.h:57
auto Left() const
Returns left child node.
Definition KdTree.h:52