EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
EBGeometry_SphereCloudBVH.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Robert Marskar <robert.marskar@sintef.no>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
12#ifndef EBGEOMETRY_SPHERECLOUDBVH_HPP
13#define EBGEOMETRY_SPHERECLOUDBVH_HPP
14
15// Std includes
16#include <cmath>
17#include <cstddef>
18#include <cstdint>
19#include <type_traits>
20#include <vector>
21
22// Our includes
27#include "EBGeometry_Pool.hpp"
30#include "EBGeometry_Vec.hpp"
31
32namespace EBGeometry {
33
34namespace PointCloudDetail {
35
43template <class T, class Source>
45{
47 Source m_source;
48
54 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
56 operator()(const uint32_t a_index) const noexcept
57 {
58 const T radius = m_source(a_index).m_radius;
59
60 return Vec3T<T>(radius, radius, radius);
61 }
62};
63
71template <class T, size_t W>
73{
76
79
82
84 static constexpr const char* ClassName = "SphereCloudBVH";
85
87 static constexpr const char* Singular = "sphere";
88
90 static constexpr const char* Plural = "spheres";
91
93 static constexpr const char* MaxParameter = "a_maxSpheres";
94
100 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
101 static inline const Vec3T<T>&
102 center(const Item& a_item) noexcept
103 {
104 return a_item.m_center;
105 }
106
114 static inline void
115 grow(Vec3T<T>& a_lo, Vec3T<T>& a_hi, const Item& a_item) noexcept
116 {
117 const Vec3T<T> radius = a_item.m_radius * Vec3T<T>::ones();
118
119 a_lo = min(a_lo, a_item.m_center - radius);
120 a_hi = max(a_hi, a_item.m_center + radius);
121 }
122
130 static inline void
131 requireValid(const char* a_who, const std::vector<Item>& a_items) noexcept
132 {
133 for (std::size_t i = 0; i < a_items.size(); i++) {
134 const Item& sphere = a_items[i];
135
136 EBGEOMETRY_REQUIRE(std::isfinite(sphere.m_center[0]) && std::isfinite(sphere.m_center[1]) &&
137 std::isfinite(sphere.m_center[2]),
138 "%s: sphere %zu of %zu has a non-finite coordinate",
139 a_who,
140 i,
141 a_items.size());
142 EBGEOMETRY_REQUIRE(std::isfinite(sphere.m_radius) && sphere.m_radius >= T(0),
143 "%s: sphere %zu of %zu has a non-finite or negative radius",
144 a_who,
145 i,
146 a_items.size());
147 }
148 }
149
167 template <class Source>
169 static inline void
170 requireValidWhereBuilt(const Source& a_source,
171 const uint32_t a_numItems,
172 const bool a_parallel,
173 Vec3T<T>* a_scratch,
174 const char* a_who) noexcept
175 {
176 if (a_numItems == 0) {
177 return;
178 }
179
180 if (a_parallel) {
181 const BoundingVolumes::AABBT<T> box =
182 GPU::boundingBoxOf<T>(RadiiAsPoints<T, Source>{a_source}, a_numItems, a_scratch);
183
184 const T smallest = box.getLowCorner()[0];
185 const T largest = box.getHighCorner()[0];
186
187 EBGEOMETRY_REQUIRE(std::isfinite(smallest) && std::isfinite(largest) && smallest >= T(0),
188 "%s: a sphere has a non-finite or negative radius",
189 a_who);
190
191 return;
192 }
193
194 for (uint32_t i = 0; i < a_numItems; i++) {
195 const T radius = a_source(i).m_radius;
196
197 EBGEOMETRY_REQUIRE(std::isfinite(radius) && radius >= T(0),
198 "%s: sphere %u of %u has a non-finite or negative radius",
199 a_who,
200 unsigned(i),
201 unsigned(a_numItems));
202 }
203 }
204};
205
206} // namespace PointCloudDetail
207
231template <class T, size_t K = BVH::DefaultBranchingRatio<T>(), size_t W = PointSoA::DefaultWidth<T>()>
232class SphereCloudBVH : public PointCloudDetail::CloudBVH<T, K, W, PointCloudDetail::SpherePrimitive<T, W>>
233{
234public:
239
244
249
254
259
268 inline SphereCloudBVH(Pool& a_pool, const std::vector<Sphere>& a_spheres, std::size_t a_targetLeafSize = 16 * W);
269
280 inline SphereCloudBVH(Pool& a_pool,
281 const std::vector<Vec3T<T>>& a_centers,
282 const std::vector<T>& a_radii,
283 std::size_t a_targetLeafSize = 16 * W);
284
305 template <class Source>
306 [[nodiscard]] EBGEOMETRY_HOST
307 static inline SphereCloudBVH
308 build(Pool& a_pool,
309 const Source& a_source,
310 uint32_t a_numSpheres,
311 std::size_t a_targetLeafSize = 16 * W,
312 uint32_t a_maxSpheres = 0);
313
323 [[nodiscard]] EBGEOMETRY_HOST
324 static inline SphereCloudBVH
325 build(Pool& a_pool,
326 const std::vector<Sphere>& a_spheres,
327 std::size_t a_targetLeafSize = 16 * W,
328 uint32_t a_maxSpheres = 0);
329
341 [[nodiscard]] EBGEOMETRY_HOST
342 static inline SphereCloudBVH
343 build(Pool& a_pool,
344 const std::vector<Vec3T<T>>& a_centers,
345 const std::vector<T>& a_radii,
346 std::size_t a_targetLeafSize = 16 * W,
347 uint32_t a_maxSpheres = 0);
348
360 template <class Source>
362 inline void
363 rebuild(const Source& a_source, uint32_t a_numSpheres);
364
369 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
370 inline uint32_t
371 maxSpheres() const noexcept;
372
378 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
379 inline T
380 signedDistance(const Vec3T<T>& a_point) const noexcept;
381
388 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
389 inline Hit
390 closestSphere(const Vec3T<T>& a_point) const noexcept;
391
396 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
397 inline AABB
398 computeBoundingVolume() const noexcept;
399
404 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
405 inline uint32_t
406 numSpheres() const noexcept;
407
413 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
414 inline Sphere
415 sphere(uint32_t a_index) const noexcept;
416
421 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
422 inline Packed
423 getBVH() const noexcept;
424
432 [[nodiscard]] EBGEOMETRY_HOST
433 inline SphereCloudBVH
434 rebasedView(const Pool& a_pool) const noexcept;
435
441 [[nodiscard]] EBGEOMETRY_HOST
442 inline SphereCloudBVH
443 deepCopy(Pool& a_dstPool) const;
444
449 using PoolHandle::base;
450
451private:
455 using Base = PointCloudDetail::CloudBVH<T, K, W, PointCloudDetail::SpherePrimitive<T, W>>;
456
457 using Base::m_bvhLayout;
458 using Base::m_items;
459 using Base::m_maxItems;
460
464 SphereCloudBVH() noexcept = default;
465};
466
471static_assert(std::is_trivially_copyable_v<SphereCloudBVH<float>>, "SphereCloudBVH<float> must be trivially copyable");
472static_assert(std::is_trivially_copyable_v<SphereCloudBVH<double>>,
473 "SphereCloudBVH<double> must be trivially copyable");
474
475} // namespace EBGeometry
476
477#include "EBGeometry_SphereCloudBVHImplem.hpp"
478
479#endif
Declarations of bounding volume types used in bounding volume hierarchies.
The linear BVH build shared by PointCloudBVH and SphereCloudBVH, over a cloud of points or spheres.
Building blocks for builds that run with GPU::parallelFor(): a bounding-box reduction,...
#define EBGEOMETRY_HOST_DEVICE
Mark a function as callable from both host and device code (no-op on host compilers).
Definition EBGeometry_GPU.hpp:80
#define EBGEOMETRY_HOST
Mark a function as callable from host code only (no-op on host compilers).
Definition EBGeometry_GPU.hpp:83
#define EBGEOMETRY_REQUIRE(cond,...)
Always-on check of user input and one-time host setup.
Definition EBGeometry_Macros.hpp:84
The flattened, device-callable bounding volume hierarchy: PackedBVH, its node layout,...
Growable bump arena for the GPU memory foundation.
Declaration of a PointAoSoA group with a radius lane: a group of spheres carrying their ids.
The sphere, query result and sphere sources of SphereCloudBVH.
Declaration of 2D and 3D point/vector classes with templated precision, and free functions on them.
Forward declaration of the linearised BVH, defined below.
Definition EBGeometry_PackedBVH.hpp:365
Axis-aligned bounding box (AABB) enclosing a set of 3D points.
Definition EBGeometry_BoundingVolumes.hpp:37
Vec3T< T > & getLowCorner() noexcept
Get a modifiable reference to the low corner of the AABB.
Vec3T< T > & getHighCorner() noexcept
Get a modifiable reference to the high corner of the AABB.
The state and build of a linear BVH over a cloud of primitives (points or spheres),...
Definition EBGeometry_CloudBVH.hpp:210
CloudBVH() noexcept=default
An empty BVH, to be reserved and filled.
Base of every pool-resident handle: the one PoolLocation its arrays resolve against.
Definition EBGeometry_Pool.hpp:506
Growable bump arena over a MemoryResource.
Definition EBGeometry_Pool.hpp:188
A BVH over spheres of differing radii (polydisperse particles), with the signed distance to their uni...
Definition EBGeometry_SphereCloudBVH.hpp:233
SphereCloudBVH(Pool &a_pool, const std::vector< Sphere > &a_spheres, std::size_t a_targetLeafSize=16 *W)
Build a BVH over spheres on the host: shorthand for build(a_pool, a_spheres, a_targetLeafSize).
T signedDistance(const Vec3T< T > &a_point) const noexcept
Signed distance to the union of the spheres: min_i(|p - c_i| - r_i); see the class.
Hit closestSphere(const Vec3T< T > &a_point) const noexcept
The sphere whose surface is nearest to a point, in the signed sense of signedDistance().
SphereCloudBVH(Pool &a_pool, const std::vector< Vec3T< T > > &a_centers, const std::vector< T > &a_radii, std::size_t a_targetLeafSize=16 *W)
Build a BVH over spheres given as centers and radii, on the host: shorthand for build(a_pool,...
SphereCloudBVH deepCopy(Pool &a_dstPool) const
Duplicate this object's storage into a_dstPool.
SphereCloudBVH rebasedView(const Pool &a_pool) const noexcept
Produce a copy of this object that resolves against a_pool.
AABB computeBoundingVolume() const noexcept
The box of all the spheres.
static SphereCloudBVH build(Pool &a_pool, const std::vector< Sphere > &a_spheres, std::size_t a_targetLeafSize=16 *W, uint32_t a_maxSpheres=0)
Build a BVH over spheres on the host, where the pool's memory is; see the build() above.
uint32_t numSpheres() const noexcept
Number of spheres in the cloud.
void rebuild(const Source &a_source, uint32_t a_numSpheres)
Build the BVH again, in the arrays build() reserved, from new spheres.
Packed getBVH() const noexcept
The held packed BVH over the sphere groups.
static SphereCloudBVH build(Pool &a_pool, const std::vector< Vec3T< T > > &a_centers, const std::vector< T > &a_radii, std::size_t a_targetLeafSize=16 *W, uint32_t a_maxSpheres=0)
Build a BVH over spheres given as centers and radii, on the host, where the pool's memory is; see the...
void * base() noexcept
The base address this object's arrays are offsets from; see PoolHandle::base().
Definition EBGeometry_Pool.hpp:582
Sphere sphere(uint32_t a_index) const noexcept
The sphere with a cloud index.
static SphereCloudBVH build(Pool &a_pool, const Source &a_source, uint32_t a_numSpheres, std::size_t a_targetLeafSize=16 *W, uint32_t a_maxSpheres=0)
Build a BVH over spheres, where the pool's memory is.
uint32_t maxSpheres() const noexcept
The most spheres rebuild() can take.
Three-dimensional vector class with arithmetic operators.
Definition EBGeometry_Vec.hpp:258
static constexpr Vec3T< T > ones() noexcept
Return a vector with x = y = z = 1.
Namespace containing all of EBGeometry's functionality.
Definition EBGeometry_Affine.hpp:26
Vec2T< T > min(const Vec2T< T > &u, const Vec2T< T > &v) noexcept
Component-wise minimum of two vectors.
Vec2T< T > max(const Vec2T< T > &u, const Vec2T< T > &v) noexcept
Component-wise maximum of two vectors.
A source of points that are a sphere's radius in every coordinate: GPU::boundingBoxOf() over it finds...
Definition EBGeometry_SphereCloudBVH.hpp:45
Source m_source
The spheres.
Definition EBGeometry_SphereCloudBVH.hpp:47
Vec3T< T > operator()(const uint32_t a_index) const noexcept
The radius of a sphere, in every coordinate.
Definition EBGeometry_SphereCloudBVH.hpp:56
The primitive of SphereCloudBVH: a sphere, keyed at its center and packed into SphereAoSoA groups; se...
Definition EBGeometry_SphereCloudBVH.hpp:73
static void requireValid(const char *a_who, const std::vector< Item > &a_items) noexcept
Abort with a message unless the spheres of a host array can be built over: a finite center,...
Definition EBGeometry_SphereCloudBVH.hpp:131
static constexpr const char * Singular
One primitive, for the messages.
Definition EBGeometry_SphereCloudBVH.hpp:87
static const Vec3T< T > & center(const Item &a_item) noexcept
The point a sphere's Morton key is taken at.
Definition EBGeometry_SphereCloudBVH.hpp:102
static constexpr const char * ClassName
The class built over these primitives, for the messages.
Definition EBGeometry_SphereCloudBVH.hpp:84
static constexpr const char * Plural
Primitives, for the messages.
Definition EBGeometry_SphereCloudBVH.hpp:90
static void requireValidWhereBuilt(const Source &a_source, const uint32_t a_numItems, const bool a_parallel, Vec3T< T > *a_scratch, const char *a_who) noexcept
Check every radius, where the build runs: finite, and at least 0.
Definition EBGeometry_SphereCloudBVH.hpp:170
static void grow(Vec3T< T > &a_lo, Vec3T< T > &a_hi, const Item &a_item) noexcept
Grow a box to hold a sphere.
Definition EBGeometry_SphereCloudBVH.hpp:115
static constexpr const char * MaxParameter
build()'s parameter giving the room for a rebuild, for the messages.
Definition EBGeometry_SphereCloudBVH.hpp:93
A group of up to W spheres carrying their cloud indices: a PointAoSoA<T, W> of the centers,...
Definition EBGeometry_SphereAoSoA.hpp:37
A source of spheres reading one array of Sphere<T>, indexed by cloud index.
Definition EBGeometry_SphereCloud.hpp:86
One query result: the cloud index of a sphere and the signed distance to its surface.
Definition EBGeometry_SphereCloud.hpp:62
A sphere of a sphere cloud: a center and a radius.
Definition EBGeometry_SphereCloud.hpp:48
Vec3T< T > m_center
The center.
Definition EBGeometry_SphereCloud.hpp:49
T m_radius
The radius, at least 0.
Definition EBGeometry_SphereCloud.hpp:50