1#ifndef PBAT_GEOMETRY_AABBRADIXTREEHIERARCHY_H
2#define PBAT_GEOMETRY_AABBRADIXTREEHIERARCHY_H
13#include "pbat/math/linalg/mini/Eigen.h"
16#include <cpp-sort/sorters/ska_sorter.h>
34class AabbRadixTreeHierarchy
38 static auto constexpr kDims = Dims;
39 using SelfType = AabbRadixTreeHierarchy<kDims>;
41 AabbRadixTreeHierarchy() =
default;
51 template <
class TDerivedL,
class TDerivedU>
53 Eigen::DenseBase<TDerivedL>
const& L,
54 Eigen::DenseBase<TDerivedU>
const& U);
66 template <
class TDerivedL,
class TDerivedU>
67 void Construct(Eigen::DenseBase<TDerivedL>
const& L, Eigen::DenseBase<TDerivedU>
const& U);
80 template <
class TDerivedL,
class TDerivedU>
81 void Update(Eigen::DenseBase<TDerivedL>
const& L, Eigen::DenseBase<TDerivedU>
const& U);
93 template <
class FNodeOverlaps,
class FObjectOverlaps,
class FOnOverlap>
96 FNodeOverlaps fNodeOverlaps,
97 FObjectOverlaps fObjectOverlaps,
98 FOnOverlap fOnOverlap)
114 template <
class FDistanceToNode,
class FDistanceToObject,
class FOnNearestNeighbour>
116 FDistanceToNode fDistanceToNode,
117 FDistanceToObject fDistanceToObject,
118 FOnNearestNeighbour fOnNearestNeighbour,
119 Scalar radius = std::numeric_limits<Scalar>::max(),
134 template <
class FDistanceToNode,
class FDistanceToObject,
class FOnNearestNeighbour>
136 FDistanceToNode fDistanceToNode,
137 FDistanceToObject fDistanceToObject,
138 FOnNearestNeighbour fOnNearestNeighbour,
140 Scalar radius = std::numeric_limits<Scalar>::max())
const;
149 template <
class FObjectsOverlap,
class FOnSelfOverlap>
150 void SelfOverlaps(FObjectsOverlap fObjectsOverlap, FOnSelfOverlap fOnSelfOverlap)
const;
162 template <
class FObjectsOverlap,
class FOnOverlap>
164 Overlaps(
SelfType const& rhs, FObjectsOverlap fObjectsOverlap, FOnOverlap fOnOverlap)
const;
189 template <
class TDerivedL,
class TDerivedU>
198 Eigen::Vector<MortonCodeType, Eigen::Dynamic> codes;
199 Eigen::Vector<IndexType, Eigen::Dynamic> inds;
209template <
class TDerivedL,
class TDerivedU>
210inline AabbRadixTreeHierarchy<Dims>::AabbRadixTreeHierarchy(
211 Eigen::DenseBase<TDerivedL>
const& L,
212 Eigen::DenseBase<TDerivedU>
const& U)
218template <
class TDerivedL,
class TDerivedU>
220 Eigen::DenseBase<TDerivedL>
const& L,
221 Eigen::DenseBase<TDerivedU>
const& U)
223 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.AabbRadixTreeHierarchy.Construct");
224 auto const n = L.cols();
229 tree.Construct(codes);
230 IB.resize(2 *
kDims, tree.InternalNodeCount());
234template <
class TDerivedL,
class TDerivedU>
236 Eigen::DenseBase<TDerivedL>
const& L,
237 Eigen::DenseBase<TDerivedU>
const& U)
239 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.AabbRadixTreeHierarchy.Update");
240 IB.template topRows<kDims>().setConstant(std::numeric_limits<Scalar>::max());
241 IB.template bottomRows<kDims>().setConstant(std::numeric_limits<Scalar>::lowest());
245 auto const lc = tree.Left(n);
246 auto const rc = tree.Right(n);
250 auto i = inds(tree.CodeIndex(lc));
251 LL = L.col(i).template head<kDims>();
252 LU = U.col(i).template head<kDims>();
256 LL = IB.col(lc).template head<kDims>();
257 LU = IB.col(lc).template tail<kDims>();
261 auto i = inds(tree.CodeIndex(rc));
262 RL = L.col(i).template head<kDims>();
263 RU = U.col(i).template head<kDims>();
267 RL = IB.col(rc).template head<kDims>();
268 RU = IB.col(rc).template tail<kDims>();
270 IB.col(n).template head<kDims>() = LL.cwiseMin(RL);
271 IB.col(n).template tail<kDims>() = LU.cwiseMax(RU);
275 if constexpr (c == 0)
276 return tree.IsLeaf(tree.Left(n)) ? -1 : tree.Left(n);
278 return tree.IsLeaf(tree.Right(n)) ? -1 : tree.Right(n);
283template <
class FNodeOverlaps,
class FObjectOverlaps,
class FOnOverlap>
285 FNodeOverlaps fNodeOverlaps,
286 FObjectOverlaps fObjectOverlaps,
287 FOnOverlap fOnOverlap)
const
289 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.AabbRadixTreeHierarchy.Overlaps");
292 if constexpr (c == 0)
293 return tree.IsLeaf(n) ? -1 : tree.Left(n);
295 return tree.IsLeaf(n) ? -1 : tree.Right(n);
297 [&](
Index n) {
return tree.IsLeaf(n); },
298 []([[maybe_unused]]
Index n) {
return 1; },
299 [&](
Index n, [[maybe_unused]]
Index i) {
return inds(tree.CodeIndex(n)); },
303 auto L = IB.col(n).template head<kDims>();
304 auto U = IB.col(n).template tail<kDims>();
305 using TDerivedL =
decltype(L);
306 using TDerivedU =
decltype(U);
307 return fNodeOverlaps.template operator()<TDerivedL, TDerivedU>(L, U);
314template <
class FDistanceToNode,
class FDistanceToObject,
class FOnNearestNeighbour>
316 FDistanceToNode fDistanceToNode,
317 FDistanceToObject fDistanceToObject,
318 FOnNearestNeighbour fOnNearestNeighbour,
322 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.AabbRadixTreeHierarchy.NearestNeighbours");
325 if constexpr (c == 0)
326 return tree.IsLeaf(n) ? -1 : tree.Left(n);
328 return tree.IsLeaf(n) ? -1 : tree.Right(n);
330 [&](
Index n) {
return tree.IsLeaf(n); },
331 []([[maybe_unused]]
Index n) {
return 1; },
332 [&](
Index n, [[maybe_unused]]
Index i) {
return inds(tree.CodeIndex(n)); },
334 using TDerivedL =
decltype(IB.col(n).
template head<kDims>());
335 using TDerivedU =
decltype(IB.col(n).
template tail<kDims>());
336 using ScalarType = std::invoke_result_t<FDistanceToNode, TDerivedL, TDerivedU>;
338 return ScalarType(0);
339 auto L = IB.col(n).template head<kDims>();
340 auto U = IB.col(n).template tail<kDims>();
341 return fDistanceToNode.template operator()<TDerivedL, TDerivedU>(L, U);
351template <
class FDistanceToNode,
class FDistanceToObject,
class FOnNearestNeighbour>
353 FDistanceToNode fDistanceToNode,
354 FDistanceToObject fDistanceToObject,
355 FOnNearestNeighbour fOnNearestNeighbour,
359 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.AabbRadixTreeHierarchy.KNearestNeighbours");
362 if constexpr (c == 0)
363 return tree.IsLeaf(n) ? -1 : tree.Left(n);
365 return tree.IsLeaf(n) ? -1 : tree.Right(n);
367 [&](
Index n) {
return tree.IsLeaf(n); },
368 []([[maybe_unused]]
Index n) {
return 1; },
369 [&](
Index n, [[maybe_unused]]
Index i) {
return inds(tree.CodeIndex(n)); },
371 using TDerivedL =
decltype(IB.col(n).
template head<kDims>());
372 using TDerivedU =
decltype(IB.col(n).
template tail<kDims>());
373 using ScalarType = std::invoke_result_t<FDistanceToNode, TDerivedL, TDerivedU>;
375 return ScalarType(0);
376 auto L = IB.col(n).template head<kDims>();
377 auto U = IB.col(n).template tail<kDims>();
378 return fDistanceToNode.template operator()<TDerivedL, TDerivedU>(L, U);
387template <
class FObjectsOverlap,
class FOnSelfOverlap>
389 FObjectsOverlap fObjectsOverlap,
390 FOnSelfOverlap fOnSelfOverlap)
const
392 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.AabbRadixTreeHierarchy.SelfOverlaps");
395 if constexpr (c == 0)
396 return tree.IsLeaf(n) ? -1 : tree.Left(n);
398 return tree.IsLeaf(n) ? -1 : tree.Right(n);
400 [&](
Index n) {
return tree.IsLeaf(n); },
401 []([[maybe_unused]]
Index n) {
return 1; },
402 [&](
Index n, [[maybe_unused]]
Index i) {
return inds(tree.CodeIndex(n)); },
404 if (tree.IsLeaf(n1) or tree.IsLeaf(n2))
406 using math::linalg::mini::FromEigen;
407 auto L1 = IB.col(n1).template head<kDims>();
408 auto U1 = IB.col(n1).template tail<kDims>();
409 auto L2 = IB.col(n2).template head<kDims>();
410 auto U2 = IB.col(n2).template tail<kDims>();
422template <
class FObjectsOverlap,
class FOnOverlap>
425 FObjectsOverlap fObjectsOverlap,
426 FOnOverlap fOnOverlap)
const
428 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.AabbRadixTreeHierarchy.Overlaps");
430 auto const fChildLhs = [&]<
auto c>(
Index n) ->
Index {
431 if constexpr (c == 0)
432 return tree.IsLeaf(n) ? -1 : tree.Left(n);
434 return tree.IsLeaf(n) ? -1 : tree.Right(n);
436 auto const fIsLeafLhs = [&](
Index n) {
437 return tree.IsLeaf(n);
439 auto const fLeafSizeLhs = []([[maybe_unused]]
Index n) {
442 auto const fLeafObjectLhs = [&](
Index n, [[maybe_unused]]
Index i) {
443 return inds(tree.CodeIndex(n));
446 auto const fChildRhs = [&]<
auto c>(
Index n) ->
Index {
447 if constexpr (c == 0)
448 return rhs.tree.
IsLeaf(n) ? -1 : rhs.tree.
Left(n);
450 return rhs.tree.
IsLeaf(n) ? -1 : rhs.tree.
Right(n);
452 auto const fIsLeafRhs = [&](
Index n) {
453 return rhs.tree.
IsLeaf(n);
455 auto const fLeafSizeRhs = []([[maybe_unused]]
Index n) {
458 auto const fLeafObjectRhs = [&](
Index n, [[maybe_unused]]
Index i) {
472 if (tree.IsLeaf(n1) or rhs.tree.
IsLeaf(n2))
474 using math::linalg::mini::FromEigen;
475 auto L1 = IB.col(n1).template head<kDims>();
476 auto U1 = IB.col(n1).template tail<kDims>();
477 auto L2 = rhs.IB.col(n2).template head<kDims>();
478 auto U2 = rhs.IB.col(n2).template tail<kDims>();
490template <
class TDerivedL,
class TDerivedU>
492 Eigen::DenseBase<TDerivedL>
const& L,
493 Eigen::DenseBase<TDerivedU>
const& U)
495 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.AabbRadixTreeHierarchy.ComputeMortonCodes");
499 auto C = 0.5 * (L.derived() + U.derived());
500 for (
Index i = 0; i < L.cols(); ++i)
511 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.AabbRadixTreeHierarchy.SortMortonCodes");
520 std::iota(inds.begin(), inds.end(), 0);
521 cppsort::ska_sort(inds.begin(), inds.end(), [&](
IndexType i) { return codes(i); });
Axis-aligned bounding box class.
Radix Tree implementation.
This file contains functions to compute Morton codes.
Generic n-ary tree traversals.
This file contains functions to answer overlap queries.
Permutation of values in-place.
Generic efficient spatial search query implementations.
Binary radix tree implementation.
Definition BinaryRadixTree.h:28
TIndex CodeIndex(TIndex leaf) const
Get the index of the code associated with a leaf node.
Definition BinaryRadixTree.h:150
TIndex Right(TIndex i) const
Get the right child of internal node i
Definition BinaryRadixTree.h:111
TIndex Left(TIndex i) const
Get the left child of internal node i
Definition BinaryRadixTree.h:103
bool IsLeaf(TIndex i) const
Check if a node is a leaf.
Definition BinaryRadixTree.h:137
void SelfOverlaps(FObjectsOverlap fObjectsOverlap, FOnSelfOverlap fOnSelfOverlap) const
Find all object pairs that overlap.
Definition AabbRadixTreeHierarchy.h:388
static auto constexpr kDims
Definition AabbRadixTreeHierarchy.h:38
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 AabbRadixTreeHierarchy.h:315
void ComputeMortonCodes(Eigen::DenseBase< TDerivedL > const &L, Eigen::DenseBase< TDerivedU > const &U)
Compute Morton codes for the AABBs.
Definition AabbRadixTreeHierarchy.h:491
void Overlaps(SelfType const &rhs, FObjectsOverlap fObjectsOverlap, FOnOverlap fOnOverlap) const
Find all object pairs that overlap with another hierarchy.
Definition AabbRadixTreeHierarchy.h:423
void SortMortonCodes()
Sort the Morton codes.
Definition AabbRadixTreeHierarchy.h:509
AabbRadixTreeHierarchy(Eigen::DenseBase< TDerivedL > const &L, Eigen::DenseBase< TDerivedU > const &U)
Construct an AabbRadixTreeHierarchy from an input AABB matrix B.
Definition AabbRadixTreeHierarchy.h:210
auto InternalNodeBoundingBoxes() const
Get the internal node bounding boxes.
Definition AabbRadixTreeHierarchy.h:172
void Construct(Eigen::DenseBase< TDerivedL > const &L, Eigen::DenseBase< TDerivedU > const &U)
Construct an AabbRadixTreeHierarchy from an input AABB matrix B.
Definition AabbRadixTreeHierarchy.h:219
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 AabbRadixTreeHierarchy.h:352
auto Tree() const -> common::BinaryRadixTree< IndexType > const &
Get the underlying tree hierarchy.
Definition AabbRadixTreeHierarchy.h:177
Index IndexType
Type of the indices.
Definition AabbRadixTreeHierarchy.h:37
void Overlaps(FNodeOverlaps fNodeOverlaps, FObjectOverlaps fObjectOverlaps, FOnOverlap fOnOverlap) const
Find all objects that overlap with some user-defined query.
Definition AabbRadixTreeHierarchy.h:284
AabbRadixTreeHierarchy< kDims > SelfType
Type of this template instantiation.
Definition AabbRadixTreeHierarchy.h:39
void Update(Eigen::DenseBase< TDerivedL > const &L, Eigen::DenseBase< TDerivedU > const &U)
Recomputes k-D tree node AABBs given the object AABBs.
Definition AabbRadixTreeHierarchy.h:235
Common functionality.
Definition ArgSort.h:20
void Permute(TValuesBegin vb, TValuesEnd ve, TPermutationBegin pb)
Permute the values in-place according to the permutation.
Definition Permute.h:39
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
constexpr void ForRange(F &&f)
Compile-time for loop over a range of values.
Definition ConstexprFor.h:55
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 MortonCodeType Morton3D(Point x)
Calculates a 30-bit Morton code for the given 3D point located within the unit cube [0,...
Definition Morton.h:69
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< Scalar, N > Vector
Fixed-size vector type.
Definition Aliases.h:24
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)