11#ifndef PBAT_GEOMETRY_HASHGRID_H
12#define PBAT_GEOMETRY_HASHGRID_H
30template <common::CIndex THashed>
33 return []<
class TDerivedX>(Eigen::DenseBase<TDerivedX> const& X) {
35 TDerivedX::SizeAtCompileTime == 2 or TDerivedX::SizeAtCompileTime == 3,
36 "Only eigen vectors of compile-time size 2 or 3 are supported.");
37 if constexpr (TDerivedX::SizeAtCompileTime == 2)
39 return static_cast<THashed
>(X(0) * 73856093) ^
static_cast<THashed
>(X(1) * 19349663);
41 if constexpr (TDerivedX::SizeAtCompileTime == 3)
43 return static_cast<THashed
>(X(0) * 73856093) ^
static_cast<THashed
>(X(1) * 19349663) ^
44 static_cast<THashed
>(X(2) * 83492791);
58template <
int Dims, common::CFloatingPo
int TScalar = Scalar, common::CIndex TIndex = Index>
64 static constexpr int kDims = Dims;
65 static_assert(Dims >= 2 and Dims <= 3,
"HashGrid only supports 2D and 3D");
100 template <
class FHash,
class TDerivedL,
class TDerivedU>
102 Eigen::DenseBase<TDerivedL>
const& L,
103 Eigen::DenseBase<TDerivedU>
const& U,
113 template <
class FHash,
class TDerivedX>
114 void Construct(Eigen::DenseBase<TDerivedX>
const& X, FHash fHash);
127 template <
class FOnPair,
class FHash,
class TDerivedX>
128 void BroadPhase(Eigen::DenseBase<TDerivedX>
const& X, FOnPair fOnPair, FHash fHash)
const;
139 template <
class TDerivedX>
140 auto Cell(Eigen::DenseBase<TDerivedX>
const& X)
const -> Eigen::Matrix<ScalarType, kDims, 2>;
147 template <
class TDerivedX>
149 -> Eigen::Vector<IndexType, kDims>;
153 Eigen::Vector<IndexType, Eigen::Dynamic>
155 Eigen::Vector<IndexType, Eigen::Dynamic>
157 Eigen::Vector<IndexType, Eigen::Dynamic>
162template <
int Dims, common::CFloatingPo
int TScalar, common::CIndex TIndex>
169template <
int Dims, common::CFloatingPo
int TScalar, common::CIndex TIndex>
172 mCellSize = cellSize;
173 mPrefix.resize(nBuckets + 1);
176template <
int Dims, common::CFloatingPo
int TScalar, common::CIndex TIndex>
179 mBucketIds.resize(nPrimitives);
180 mPrimitiveIds.resize(nPrimitives);
183template <
int Dims, common::CFloatingPo
int TScalar, common::CIndex TIndex>
184template <
class FHash,
class TDerivedL,
class TDerivedU>
186 Eigen::DenseBase<TDerivedL>
const& L,
187 Eigen::DenseBase<TDerivedU>
const& U,
190 assert(L.rows() == U.rows());
191 assert(L.cols() == U.cols());
195template <
int Dims, common::CFloatingPo
int TScalar, common::CIndex TIndex>
196template <
class FHash,
class TDerivedX>
200 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.HashGrid.Construct");
201 auto const nPrimitives =
static_cast<IndexType>(X.cols());
203 assert(nBuckets >= nPrimitives);
204 assert(nPrimitives ==
static_cast<IndexType>(X.cols()));
205 assert(X.rows() ==
kDims);
208 for (
IndexType i = 0; i < nPrimitives; ++i)
211 mBucketIds[i] = common::Modulo(fHash(ixyz), nBuckets);
215 mPrefix(mBucketIds).array() += 1;
217 std::inclusive_scan(mPrefix.begin(), mPrefix.end(), mPrefix.begin());
219 for (
IndexType i = 0; i < nPrimitives; ++i)
221 auto bucketId = mBucketIds[i];
222 mPrimitiveIds[--mPrefix[bucketId]] = i;
226template <
int Dims, common::CFloatingPo
int TScalar, common::CIndex TIndex>
227template <
class FOnPair,
class FHash,
class TDerivedX>
229 Eigen::DenseBase<TDerivedX>
const& X,
233 PBAT_PROFILE_NAMED_SCOPE(
"pbat.geometry.HashGrid.BroadPhase");
234 assert(X.rows() ==
kDims);
235 auto const nQueries =
static_cast<IndexType>(X.cols());
237 auto const fVisitCell = [&](
IndexType q, Eigen::Vector<IndexType, kDims>
const& ixyz) {
238 auto bucketId = common::Modulo(fHash(ixyz), nBuckets);
239 auto begin = mPrefix[bucketId];
240 auto end = mPrefix[bucketId + 1];
241 for (
auto j = begin; j < end; ++j)
242 fOnPair(q, mPrimitiveIds[j]);
247 if constexpr (
kDims == 2)
249 for (
auto cx = -1; cx <= 1; ++cx)
252 for (
auto cy = -1; cy <= 1; ++cy)
261 if constexpr (
kDims == 3)
263 for (
auto cx = -1; cx <= 1; ++cx)
266 for (
auto cy = -1; cy <= 1; ++cy)
269 for (
auto cz = -1; cz <= 1; ++cz)
283template <
int Dims, common::CFloatingPo
int TScalar, common::CIndex TIndex>
284template <
class TDerivedX>
286 -> Eigen::Matrix<ScalarType, kDims, 2>
288 Eigen::Matrix<ScalarType, kDims, 2> cell{};
290 cell.col(0) = ixyz.template cast<ScalarType>() * mCellSize;
291 cell.col(1) = cell.col(0).array() +
static_cast<ScalarType>(mCellSize);
295template <
int Dims, common::CFloatingPo
int TScalar, common::CIndex TIndex>
296template <
class TDerivedX>
299 -> Eigen::Vector<IndexType, kDims>
301 return Eigen::Vector<ScalarType, kDims>(
302 X.derived().array() /
static_cast<ScalarType>(mCellSize))
305 .template cast<IndexType>();
void Construct(Eigen::DenseBase< TDerivedL > const &L, Eigen::DenseBase< TDerivedU > const &U, FHash fHash)
Construct a HashGrid from lower and upper bounds of input axis-aligned bounding boxes (aabbs).
Definition HashGrid.h:185
auto ToIntegerCoordinates(Eigen::DenseBase< TDerivedX > const &X) const -> Eigen::Vector< IndexType, kDims >
Convert a point X to integer coordinates in the grid.
Definition HashGrid.h:298
void Configure(ScalarType cellSize, IndexType nBuckets)
Configure the hash grid with a specific cell size and number of buckets.
Definition HashGrid.h:170
TIndex IndexType
Type alias for index values (e.g., int or long).
Definition HashGrid.h:63
void BroadPhase(Eigen::DenseBase< TDerivedX > const &X, FOnPair fOnPair, FHash fHash) const
Find all primitives whose cell overlaps with points X.
Definition HashGrid.h:228
static constexpr int kDims
Number of spatial dimensions.
Definition HashGrid.h:64
IndexType NumberOfBuckets() const
Get the number of buckets in the hash table.
Definition HashGrid.h:133
HashGrid()=default
Default constructor for HashGrid.
void Reserve(IndexType nPrimitives)
Reserve space for a specific number of primitives in the hash grid.
Definition HashGrid.h:177
TScalar ScalarType
Type alias for scalar values (e.g., float or double).
Definition HashGrid.h:62
auto Cell(Eigen::DenseBase< TDerivedX > const &X) const -> Eigen::Matrix< ScalarType, kDims, 2 >
Get the hash grid's cell (i.e. aabb) corresponding to a point X.
Definition HashGrid.h:285
Concepts for common types.
Geometric queries, quantities and data structures.
Definition AabbKdTreeHierarchy.h:23
auto HashByXorOfPrimeMultiples()
Returns a hash function used in teschner2003 for 2 or 3-vectors suitable as input to HashGrid's API.
Definition HashGrid.h:31
Profiling utilities for the Physics-Based Animation Toolkit (PBAT)