EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
EBGeometry_Expr.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
16#ifndef EBGEOMETRY_EXPR_HPP
17#define EBGEOMETRY_EXPR_HPP
18
19// Std includes
20#include <cstddef>
21#include <cstdint>
22#include <memory>
23#include <type_traits>
24#include <typeindex>
25#include <typeinfo>
26#include <utility>
27#include <vector>
28
29// Our includes
30#include "EBGeometry_Affine.hpp"
33#include "EBGeometry_Pool.hpp"
34#include "EBGeometry_Vec.hpp"
35
36namespace EBGeometry {
37
41enum class BlendKind : uint8_t
42{
45};
46
47namespace ExprDetail {
48
54template <class B>
56{
57};
58
64template <class T>
65struct BoxPrecision<BoundingVolumes::AABBT<T>>
66{
70 using type = T;
71};
72
79template <class S, class T, class = void>
80struct HasSignedDistance : std::false_type
81{
82};
83
90template <class S, class T>
92 S,
93 T,
94 std::void_t<decltype(std::declval<const S&>().signedDistance(std::declval<const Vec3T<T>&>()))>>
95 : std::is_convertible<decltype(std::declval<const S&>().signedDistance(std::declval<const Vec3T<T>&>())), T>
96{
97};
98
104template <class S, class = void>
106{
110 static constexpr bool value = false;
111};
112
118template <class S>
120 S,
121 std::void_t<typename BoxPrecision<std::decay_t<decltype(std::declval<const S&>().computeBoundingVolume())>>::type>>
122{
126 using precision =
127 typename BoxPrecision<std::decay_t<decltype(std::declval<const S&>().computeBoundingVolume())>>::type;
128
132 static constexpr bool value = std::is_trivially_copyable_v<S> && HasSignedDistance<S, precision>::value;
133};
134
135} // namespace ExprDetail
136
150template <class S>
152
157template <class S>
159
160template <class T>
161class Expr;
162
163namespace ExprDetail {
164
170enum class Kind : uint8_t
171{
172 Primitive,
173 Affine,
174 Elongate,
175 Repeat,
176 Complement,
177 Offset,
178 Annular,
179 Blur,
180 Mollify,
181 Union,
185};
186
192struct Leaf
193{
197 std::shared_ptr<const void> m_object;
198
202 std::type_index m_type = std::type_index(typeid(void));
203
207 bool (*m_isAttachedTo)(const void*, const Pool&) = nullptr;
208};
209
216template <class T>
296
302template <class A, class = void>
304{
305};
306
312template <class T>
313struct ExprLike<Expr<T>, void>
314{
318 using type = T;
319};
320
326template <class S>
327struct ExprLike<S, std::enable_if_t<isShape<S>>>
328{
333};
334
335} // namespace ExprDetail
336
342template <class A>
344
355template <class T>
356class Expr
357{
358public:
359 static_assert(std::is_floating_point_v<T>, "Expr requires a floating-point type T");
360
365
369 Expr() = delete;
370
377 template <class S,
378 class = std::enable_if_t<!std::is_same_v<std::decay_t<S>, Expr> &&
379 !std::is_convertible_v<S, std::shared_ptr<const ExprDetail::Node<T>>>>>
381 Expr(const S& a_shape); // NOLINT(google-explicit-constructor): a shape is an expression
382
388 explicit Expr(std::shared_ptr<const ExprDetail::Node<T>> a_node) noexcept;
389
397 [[nodiscard]] EBGEOMETRY_HOST
398 const BV&
399 computeBoundingVolume() const noexcept;
400
407 [[nodiscard]] EBGEOMETRY_HOST
409 getDistanceQuality() const noexcept;
410
415 [[nodiscard]] EBGEOMETRY_HOST
416 const ExprDetail::Node<T>&
417 node() const noexcept;
418
419private:
423 std::shared_ptr<const ExprDetail::Node<T>> m_node;
424};
425
432template <class A>
433[[nodiscard]] EBGEOMETRY_HOST
434inline Expr<ExprPrecision<A>>
435toExpr(const A& a_operand);
436
445template <class A, class B>
446[[nodiscard]] EBGEOMETRY_HOST
447inline Expr<ExprPrecision<A>>
448Union(const A& a_first, const B& a_second);
449
459template <class A>
460[[nodiscard]] EBGEOMETRY_HOST
461inline Expr<ExprPrecision<A>>
462Union(const std::vector<A>& a_operands);
463
474template <class A, class B>
475[[nodiscard]] EBGEOMETRY_HOST
476inline Expr<ExprPrecision<A>>
477SmoothUnion(const A& a_first,
478 const B& a_second,
479 const ExprPrecision<A> a_smooth,
480 const BlendKind a_blend = BlendKind::Polynomial);
481
492template <class A>
493[[nodiscard]] EBGEOMETRY_HOST
494inline Expr<ExprPrecision<A>>
495SmoothUnion(const std::vector<A>& a_operands,
496 const ExprPrecision<A> a_smooth,
497 const BlendKind a_blend = BlendKind::Polynomial);
498
507template <class A, class B>
508[[nodiscard]] EBGEOMETRY_HOST
509inline Expr<ExprPrecision<A>>
510Intersection(const A& a_first, const B& a_second);
511
518template <class A>
519[[nodiscard]] EBGEOMETRY_HOST
520inline Expr<ExprPrecision<A>>
521Intersection(const std::vector<A>& a_operands);
522
533template <class A, class B>
534[[nodiscard]] EBGEOMETRY_HOST
535inline Expr<ExprPrecision<A>>
536SmoothIntersection(const A& a_first,
537 const B& a_second,
538 const ExprPrecision<A> a_smooth,
539 const BlendKind a_blend = BlendKind::Polynomial);
540
549template <class A>
550[[nodiscard]] EBGEOMETRY_HOST
551inline Expr<ExprPrecision<A>>
552SmoothIntersection(const std::vector<A>& a_operands,
553 const ExprPrecision<A> a_smooth,
554 const BlendKind a_blend = BlendKind::Polynomial);
555
564template <class A, class B>
565[[nodiscard]] EBGEOMETRY_HOST
566inline Expr<ExprPrecision<A>>
567Difference(const A& a_first, const B& a_second);
568
577template <class A, class B>
578[[nodiscard]] EBGEOMETRY_HOST
579inline Expr<ExprPrecision<A>>
580Difference(const A& a_first, const std::vector<B>& a_others);
581
592template <class A, class B>
593[[nodiscard]] EBGEOMETRY_HOST
594inline Expr<ExprPrecision<A>>
595SmoothDifference(const A& a_first,
596 const B& a_second,
597 const ExprPrecision<A> a_smooth,
598 const BlendKind a_blend = BlendKind::Polynomial);
599
610template <class A, class B>
611[[nodiscard]] EBGEOMETRY_HOST
612inline Expr<ExprPrecision<A>>
613SmoothDifference(const A& a_first,
614 const std::vector<B>& a_others,
615 const ExprPrecision<A> a_smooth,
616 const BlendKind a_blend = BlendKind::Polynomial);
617
633template <class A>
634[[nodiscard]] EBGEOMETRY_HOST
635inline Expr<ExprPrecision<A>>
636FiniteRepetition(const A& a_operand,
637 const Vec3T<ExprPrecision<A>>& a_period,
638 const Vec3T<ExprPrecision<A>>& a_repeatLo,
639 const Vec3T<ExprPrecision<A>>& a_repeatHi);
640
647template <class A>
648[[nodiscard]] EBGEOMETRY_HOST
649inline Expr<ExprPrecision<A>>
650Complement(const A& a_operand);
651
659template <class A>
660[[nodiscard]] EBGEOMETRY_HOST
661inline Expr<ExprPrecision<A>>
662Translate(const A& a_operand, const Vec3T<ExprPrecision<A>>& a_shift);
663
672template <class A>
673[[nodiscard]] EBGEOMETRY_HOST
674inline Expr<ExprPrecision<A>>
675Rotate(const A& a_operand, const ExprPrecision<A> a_degrees, const size_t a_axis);
676
685template <class A>
686[[nodiscard]] EBGEOMETRY_HOST
687inline Expr<ExprPrecision<A>>
688Rotate(const A& a_operand, const ExprPrecision<A> a_degrees, const Vec3T<ExprPrecision<A>>& a_axis);
689
699template <class A>
700[[nodiscard]] EBGEOMETRY_HOST
701inline Expr<ExprPrecision<A>>
702Scale(const A& a_operand, const ExprPrecision<A> a_factor);
703
711template <class A>
712[[nodiscard]] EBGEOMETRY_HOST
713inline Expr<ExprPrecision<A>>
714Reflect(const A& a_operand, const size_t a_axis);
715
724template <class A>
725[[nodiscard]] EBGEOMETRY_HOST
726inline Expr<ExprPrecision<A>>
727Offset(const A& a_operand, const ExprPrecision<A> a_offset);
728
736template <class A>
737[[nodiscard]] EBGEOMETRY_HOST
738inline Expr<ExprPrecision<A>>
739Annular(const A& a_operand, const ExprPrecision<A> a_delta);
740
749template <class A>
750[[nodiscard]] EBGEOMETRY_HOST
751inline Expr<ExprPrecision<A>>
752Elongate(const A& a_operand, const Vec3T<ExprPrecision<A>>& a_elongation);
753
765template <class A>
766[[nodiscard]] EBGEOMETRY_HOST
767inline Expr<ExprPrecision<A>>
768Blur(const A& a_operand, const ExprPrecision<A> a_blur, const ExprPrecision<A> a_alpha = ExprPrecision<A>(0.5));
769
781template <class A>
782[[nodiscard]] EBGEOMETRY_HOST
783inline Expr<ExprPrecision<A>>
784Mollify(const A& a_operand, const ExprPrecision<A> a_dist, const size_t a_samples);
785
786} // namespace EBGeometry
787
788#include "EBGeometry_ExprImplem.hpp"
789
790#endif
Declaration of Affine3T, an affine map of 3D space (a 3x3 matrix and a shift).
Declarations of bounding volume types used in bounding volume hierarchies.
How far a function's value can be trusted as a distance: DistanceQuality, and the distanceQualityOf t...
Kind
What an expression node does.
Definition EBGeometry_Expr.hpp:171
@ Affine
Evaluate the child at m_map(p) and multiply by m_valueScale.
@ Repeat
Evaluate the child at p folded into the home tile.
#define EBGEOMETRY_HOST
Mark a function as callable from host code only (no-op on host compilers).
Definition EBGeometry_GPU.hpp:83
Growable bump arena for the GPU memory foundation.
Declaration of 2D and 3D point/vector classes with templated precision, and free functions on them.
Axis-aligned bounding box (AABB) enclosing a set of 3D points.
Definition EBGeometry_BoundingVolumes.hpp:37
A composed object: an immutable tree of shapes and operations, built on the host and compiled by a Ta...
Definition EBGeometry_Expr.hpp:357
Expr()=delete
No empty expression.
const BV & computeBoundingVolume() const noexcept
A box enclosing the object.
DistanceQuality getDistanceQuality() const noexcept
How far the object's value can be trusted as a distance.
const ExprDetail::Node< T > & node() const noexcept
The root node, for the tape compiler.
Expr(std::shared_ptr< const ExprDetail::Node< T > > a_node) noexcept
Wrap a node; used by the builder functions.
Expr(const S &a_shape)
Wrap a shape.
Growable bump arena over a MemoryResource.
Definition EBGeometry_Pool.hpp:183
Three-dimensional vector class with arithmetic operators.
Definition EBGeometry_Vec.hpp:258
static constexpr Vec3T< T > zeros() noexcept
Return a vector with x = y = z = 0.
Namespace containing all of EBGeometry's functionality.
Definition EBGeometry_Affine.hpp:26
Expr< ExprPrecision< A > > Union(const A &a_first, const B &a_second)
Union of two objects: the minimum of their values.
BlendKind
How a smooth union, intersection or difference blends the two extreme values.
Definition EBGeometry_Expr.hpp:42
@ Polynomial
SmoothMinOp/SmoothMaxOp: quadratic blend over a band of width s; deepens by at most s/4.
@ Exponential
ExpMinOp/ExpMaxOp: log-sum-exp blend with length scale s; deepens by at most s ln 2.
Expr< ExprPrecision< A > > Reflect(const A &a_operand, const size_t a_axis)
Reflect an object in a coordinate plane through the origin.
Expr< ExprPrecision< A > > Difference(const A &a_first, const B &a_second)
Difference A \ B: max(A, -B), inside A and outside B.
Expr< ExprPrecision< A > > SmoothDifference(const A &a_first, const B &a_second, const ExprPrecision< A > a_smooth, const BlendKind a_blend=BlendKind::Polynomial)
Smooth difference A \ B: the smooth intersection of A and the complement of B.
Expr< ExprPrecision< A > > SmoothUnion(const A &a_first, const B &a_second, const ExprPrecision< A > a_smooth, const BlendKind a_blend=BlendKind::Polynomial)
Smooth union of two objects: a smooth minimum of their values.
constexpr bool isShape
Whether S is a shape: a trivially copyable type with a const signedDistance(const Vec3T<T>&) returnin...
Definition EBGeometry_Expr.hpp:151
Expr< ExprPrecision< A > > toExpr(const A &a_operand)
Convert a shape or an Expr to an Expr.
Expr< ExprPrecision< A > > Intersection(const A &a_first, const B &a_second)
Intersection of two objects: the maximum of their values.
typename ExprDetail::ShapeInfo< S >::precision ShapePrecision
The precision of a shape type: T for a shape whose box type is AABBT<T>.
Definition EBGeometry_Expr.hpp:158
Expr< ExprPrecision< A > > Blur(const A &a_operand, const ExprPrecision< A > a_blur, const ExprPrecision< A > a_alpha=ExprPrecision< A >(0.5))
Blur an object: a weighted average of its values at the 27 points p + d (i, j, k),...
Expr< ExprPrecision< A > > Translate(const A &a_operand, const Vec3T< ExprPrecision< A > > &a_shift)
Translate an object by a shift.
Expr< ExprPrecision< A > > Complement(const A &a_operand)
Complement: inside and outside swapped, -v.
Expr< ExprPrecision< A > > Elongate(const A &a_operand, const Vec3T< ExprPrecision< A > > &a_elongation)
Elongate an object: stretch it by inserting a box of half-lengths h at the origin.
Expr< ExprPrecision< A > > SmoothIntersection(const A &a_first, const B &a_second, const ExprPrecision< A > a_smooth, const BlendKind a_blend=BlendKind::Polynomial)
Smooth intersection of two objects: a smooth maximum of their values.
Expr< ExprPrecision< A > > Scale(const A &a_operand, const ExprPrecision< A > a_factor)
Scale an object uniformly about the origin.
DistanceQuality
How far the value of a signed distance function can be trusted, from strongest to weakest.
Definition EBGeometry_DistanceQuality.hpp:25
@ Exact
The value's magnitude is the Euclidean distance to the surface.
Expr< ExprPrecision< A > > Mollify(const A &a_operand, const ExprPrecision< A > a_dist, const size_t a_samples)
Mollify an object: convolve it with a smooth, non-negative bump kernel sampled on an n x n x n grid s...
Expr< ExprPrecision< A > > Annular(const A &a_operand, const ExprPrecision< A > a_delta)
A shell around an object's surface, |v| - delta.
Expr< ExprPrecision< A > > Offset(const A &a_operand, const ExprPrecision< A > a_offset)
Offset an object's surface outward by a distance, v - r.
Expr< ExprPrecision< A > > FiniteRepetition(const A &a_operand, const Vec3T< ExprPrecision< A > > &a_period, const Vec3T< ExprPrecision< A > > &a_repeatLo, const Vec3T< ExprPrecision< A > > &a_repeatHi)
Finite repetition: copies of an object on a grid of tiles, a_repeatLo tiles below and a_repeatHi tile...
Expr< ExprPrecision< A > > Rotate(const A &a_operand, const ExprPrecision< A > a_degrees, const size_t a_axis)
Rotate an object about a coordinate axis through the origin.
typename ExprDetail::ExprLike< A >::type ExprPrecision
The precision of an expression-like type: T for Expr<T> or for a shape of precision T....
Definition EBGeometry_Expr.hpp:343
An affine map of 3D space, x -> A x + b, with A stored by rows.
Definition EBGeometry_Affine.hpp:37
static Affine3T identity() noexcept
The identity map.
T type
The precision.
Definition EBGeometry_Expr.hpp:70
The precision of a bounding box type: T for AABBT<T>, nothing otherwise.
Definition EBGeometry_Expr.hpp:56
T type
The precision.
Definition EBGeometry_Expr.hpp:318
ShapePrecision< S > type
The precision.
Definition EBGeometry_Expr.hpp:332
Whether A is a shape or an Expr, and its precision: the primary template is neither.
Definition EBGeometry_Expr.hpp:304
Whether S has a const signedDistance(const Vec3T<T>&) returning something convertible to T.
Definition EBGeometry_Expr.hpp:81
A shape held by an expression, with its type erased.
Definition EBGeometry_Expr.hpp:193
std::shared_ptr< const void > m_object
Copy of the shape.
Definition EBGeometry_Expr.hpp:197
bool(* m_isAttachedTo)(const void *, const Pool &)
For a pool-resident shape: whether it lives in a given pool. Null otherwise.
Definition EBGeometry_Expr.hpp:207
std::type_index m_type
The shape's type.
Definition EBGeometry_Expr.hpp:202
An expression node.
Definition EBGeometry_Expr.hpp:218
BoundingVolumes::AABBT< T > m_boundingVolume
A box enclosing the node's object.
Definition EBGeometry_Expr.hpp:289
Affine3T< T > m_map
Point map applied before the child is evaluated (Affine).
Definition EBGeometry_Expr.hpp:238
Vec3T< T > m_vec1
Tiles in the decreasing direction of each axis, rounded to whole numbers (Repeat).
Definition EBGeometry_Expr.hpp:258
DistanceQuality m_quality
How far the node's value can be trusted as a distance.
Definition EBGeometry_Expr.hpp:294
BlendKind m_blend
Blend kind (smooth operations).
Definition EBGeometry_Expr.hpp:284
T m_scalar0
Offset distance (Offset), shell half-thickness (Annular), blur distance (Blur), mollification distanc...
Definition EBGeometry_Expr.hpp:269
Affine3T< T > m_inverse
Inverse of m_map, which maps the child's box to the node's (Affine).
Definition EBGeometry_Expr.hpp:243
Vec3T< T > m_vec0
Elongation half-lengths (Elongate) or tile period (Repeat).
Definition EBGeometry_Expr.hpp:253
std::vector< Expr< T > > m_children
Children (none for a primitive, one for a map or value operation, any number for a union or intersect...
Definition EBGeometry_Expr.hpp:228
T m_scalar1
Blend weight alpha (Blur).
Definition EBGeometry_Expr.hpp:274
Leaf m_leaf
The shape, for a primitive.
Definition EBGeometry_Expr.hpp:233
uint32_t m_count
Samples per axis (Mollify).
Definition EBGeometry_Expr.hpp:279
Vec3T< T > m_vec2
Tiles in the increasing direction of each axis, rounded to whole numbers (Repeat).
Definition EBGeometry_Expr.hpp:263
Kind m_kind
What the node does.
Definition EBGeometry_Expr.hpp:222
T m_valueScale
Value multiplier applied after the child is evaluated (Affine): |s| for a scaling by s.
Definition EBGeometry_Expr.hpp:248
typename BoxPrecision< std::decay_t< decltype(std::declval< const S & >().computeBoundingVolume())> >::type precision
The shape's precision, read from its bounding box type.
Definition EBGeometry_Expr.hpp:127
Shape detection: a type with computeBoundingVolume() returning AABBT<T>.
Definition EBGeometry_Expr.hpp:106
static constexpr bool value
Whether S is a shape.
Definition EBGeometry_Expr.hpp:110