.. _Chap:ImplemCSG: Geometries =========== This page covers the concrete classes behind two Concepts pages: :ref:`Chap:GeometryRepresentations` (signed distance fields and implicit functions in general) and :ref:`Chap:ConstructiveSolidGeometry` (transformations and CSG combinators) -- read those first for the conceptual picture, and use this page for the class/function-level detail and Doxygen links. ImplicitFunction ----------------- ``ImplicitFunction`` (:file:`Source/EBGeometry_ImplicitFunction.hpp`) is the root of EBGeometry's polymorphic geometry hierarchy. Every concrete piece of geometry the library can represent -- analytic shapes, DCEL/triangle-mesh distance fields, and CSG combinations of either -- ultimately derives from it. It declares a single pure virtual member function, .. math:: \texttt{value}(\mathbf{x}) : \mathbb{R}^3 \rightarrow \mathbb{R}, returning a value that is negative for points inside the object and positive for points outside it, plus a call operator (``operator()``) that simply forwards to ``value()``. Because every concrete geometry type honors exactly this same contract, code elsewhere in the library (and in user code) can hold a ``shared_ptr>`` and call ``value()`` on it through ordinary virtual dispatch without ever needing to know which concrete class it actually points to -- this is what lets the transform and CSG machinery below wrap or combine *any* implicit function interchangeably. ``ImplicitFunction`` also provides one concrete (non-virtual) member function, ``approximateBoundingVolumeOctree``, for shapes that have no closed-form bounding volume. It refines an octree over a caller-supplied initial box, marking a cell as intersecting the surface once the implicit function's value at the cell center falls within a safety-scaled margin of the cell's half-width, then builds a bounding volume of the caller-chosen type ``BV`` from the corners of the intersected leaf cells. This is the same octree-refinement idea described conceptually in :ref:`Chap:Octree`; see that page for how the subdivision itself works. The result is only meaningful when ``value()`` is reasonably close to a true signed distance, since the safety margin is interpreted in units of distance. For the full API (including the exact parameters and defaults of ``approximateBoundingVolumeOctree``), see the Doxygen page for `ImplicitFunction `__. SignedDistanceFunction ----------------------- ``SignedDistanceFunction`` (:file:`Source/EBGeometry_SignedDistanceFunction.hpp`) inherits from ``ImplicitFunction`` and refines its contract, without adding to the public ``value()`` interface itself: it implements ``value()`` (marked ``final``) to delegate to a new pure virtual member function, ``signedDistance(point)``, which subclasses must implement instead. The distinction is one of guarantee rather than signature -- an arbitrary ``ImplicitFunction`` only promises that the sign of its output indicates inside/outside, whereas a ``SignedDistanceFunction`` additionally promises that the *magnitude* of its output is the true Euclidean distance to the surface (the Eikonal property, :math:`|\nabla S| = 1`; see :ref:`Chap:GeometryRepresentations` for why this property matters). Every analytic shape and mesh distance field shipped with EBGeometry is a ``SignedDistanceFunction``. Because the true distance is available, ``SignedDistanceFunction`` also provides a concrete ``normal(point, delta)`` member function that estimates the outward unit normal from central finite differences of ``signedDistance`` with step size ``delta`` -- something that cannot be done reliably from an arbitrary implicit function's value alone. For the full API, see the Doxygen page for `SignedDistanceFunction `__. .. tip:: Various ready-to-use implementations of both interfaces are declared in :file:`Source/EBGeometry_AnalyticDistanceFunctions.hpp` (spheres, boxes, planes, cylinders, tori, and other closed-form primitives) and in :file:`Source/EBGeometry_MeshDistanceFunctions.hpp` (the DCEL/triangle-mesh-backed classes ``FlatMeshSDF``, ``MeshSDF``, and ``TriMeshSDF`` -- see :ref:`Chap:MeshSDFClasses`). Transformations ---------------- EBGeometry implements every transformation as a small wrapper class that stores a ``shared_ptr>`` to the wrapped function together with the transformation's own parameters, and implements ``value()`` by applying the (typically inverse) transformation to the query point before evaluating the wrapped function. Since every such wrapper is itself an ``ImplicitFunction``, transformations compose freely -- wrapping a wrapper is just as valid as wrapping a leaf shape. Each wrapper class has a same-named free function that constructs it and returns it already cast to ``shared_ptr>``, ready to be passed into further transformations or CSG combinators without the caller ever naming the concrete wrapper type. Both are declared in :file:`Source/EBGeometry_Transform.hpp`. The five simplest transformations -- translation, rotation, scaling, the complement, and reflection -- are described mathematically in :ref:`Chap:ConstructiveSolidGeometry`; the table below just maps each to its wrapper class, free function, and Doxygen entry: .. list-table:: :header-rows: 1 :widths: 20 20 20 40 * - Transformation - Wrapper class - Free function - Doxygen * - Translation - ``TranslateIF`` - ``Translate`` - `class `__ / `function `__ * - Rotation - ``RotateIF`` - ``Rotate`` - `class `__ / `function `__ * - Scaling - ``ScaleIF`` - ``Scale`` - `class `__ / `function `__ * - Complement - ``ComplementIF`` - ``Complement`` - `class `__ / `function `__ * - Reflection - ``ReflectIF`` - ``Reflect`` - `class `__ / `function `__ EBGeometry implements several further transformations that have no closed-form counterpart in :ref:`Chap:ConstructiveSolidGeometry` and are only described here: * **Offset** (``OffsetIF``/``Offset``) subtracts a constant from the wrapped function's value, growing the object if the offset is positive and shrinking it if negative. For a true signed distance function this simply moves the isosurface outward or inward by the offset distance. * **Annular** (``AnnularIF``/``Annular``) turns a solid into a hollow shell of total thickness :math:`2\delta` by evaluating :math:`|I(\mathbf{x})| - \delta`: the two new zero-isosurfaces sit where :math:`I(\mathbf{x}) = \pm\delta`, i.e. the original surface offset inward and outward by :math:`\delta` each, hollowing out everything in between. * **Blur** (``BlurIF``/``Blur``) smooths sharp features by passing the wrapped function through a 3D box filter sampled at the face centers, edge centers, and corners of a cube of half-width equal to the blur distance, with per-sample weights controlled by a blend factor ``alpha`` (``1`` = no blur, ``0`` = maximal blur). * **Mollify** (``MollifyIF``/``Mollify``) is a more general smoothing operation: it convolves the wrapped function with a caller-supplied mollifier implicit function (typically a small sphere SDF) sampled on a uniform grid of offsets, normalizing the sample weights to sum to one. * **Elongate** (``ElongateIF``/``Elongate``) stretches a shape along one or more axes without changing its cross-section: the query point is clamped component-wise to :math:`[-\mathbf{e}, \mathbf{e}]` for a per-axis elongation vector :math:`\mathbf{e}`, and the clamped offset is subtracted from the point before evaluating the wrapped function. .. list-table:: :header-rows: 1 :widths: 20 20 20 40 * - Transformation - Wrapper class - Free function - Doxygen * - Offset - ``OffsetIF`` - ``Offset`` - `class `__ / `function `__ * - Annular (shell) - ``AnnularIF`` - ``Annular`` - `class `__ / `function `__ * - Blur - ``BlurIF`` - ``Blur`` - `class `__ / `function `__ * - Mollification - ``MollifyIF`` - ``Mollify`` - `class `__ / `function `__ * - Elongation - ``ElongateIF`` - ``Elongate`` - `class `__ / `function `__ .. warning:: Not every transformation preserves the signed distance property. Rotation, translation, and the complement always do; scaling does provided the value is rescaled alongside the query point (which ``ScaleIF`` does); offset, annular, blur, mollification, and elongation generally do not produce an exact signed distance even when the input is one. Every wrapper class and free function above is declared in :file:`Source/EBGeometry_Transform.hpp`; see the Doxygen page for the file itself, `EBGeometry_Transform.hpp `__, for the complete, single-page API listing. CSG ---- The Boolean combinators for combining multiple implicit functions into one -- union, intersection, difference, and their smooth-blended variants -- are described conceptually in :ref:`Chap:ConstructiveSolidGeometry`. EBGeometry implements each with the same wrapper-class pattern as the transformations above: a class stores the combined implicit functions and implements ``value()`` as the appropriate combination over them, with a matching free function returning it as a ``shared_ptr>``. All of the following are declared in :file:`Source/EBGeometry_CSG.hpp`: .. list-table:: :header-rows: 1 :widths: 20 20 20 40 * - Combinator - Wrapper class - Free function - Doxygen * - Union - ``UnionIF`` - ``Union`` - `class `__ / `function `__ * - Smooth union - ``SmoothUnionIF`` - ``SmoothUnion`` - `class `__ / `function `__ * - Intersection - ``IntersectionIF`` - ``Intersection`` - `class `__ / `function `__ * - Smooth intersection - ``SmoothIntersectionIF`` - ``SmoothIntersection`` - `class `__ / `function `__ * - Difference - ``DifferenceIF`` - ``Difference`` - `class `__ / `function `__ * - Smooth difference - ``SmoothDifferenceIF`` - ``SmoothDifference`` - `class `__ / `function `__ ``Union``, ``SmoothUnion``, ``Intersection``, and ``SmoothIntersection`` each have two overloads in the Doxygen listing above -- one taking a ``std::vector`` of any number of implicit functions, and one taking exactly two -- both constructing the same underlying wrapper class. The "smooth" combinators blend the transition between objects instead of leaving a sharp crease, using a caller-replaceable blending functor rather than a plain ``min``/``max``. Two are provided as ``std::function`` template variables in :file:`Source/EBGeometry_CSG.hpp`: ``SmoothMin`` (a cheap polynomial smooth-minimum, the default for ``SmoothUnion``) and ``SmoothMax`` (its symmetric counterpart, the default for both ``SmoothIntersection`` and ``SmoothDifference`` -- difference is implemented internally as the intersection of ``A`` with the complement of ``B``, which is why it defaults to the same operator as intersection rather than to ``SmoothMin``), plus a more expensive exponential alternative, ``ExpMin``. Any of the three -- or a user-supplied functor of the same signature, ``T(const T&, const T&, const T&)`` -- can be passed as the smoothing operator to the smooth combinators' constructors/free functions. Because a plain CSG union is evaluated as :math:`\min(I_1, \ldots, I_N)`, querying it costs :math:`\mathcal{O}(N)` per point for :math:`N` objects. ``BVHUnionIF``/``BVHUnion`` and ``BVHSmoothUnionIF``/``BVHSmoothUnion`` accelerate this by placing the objects' bounding volumes in a ``PackedBVH`` and reducing a closest-object query to an :math:`\mathcal{O}(\log N)` tree traversal instead of a linear scan -- see :ref:`Chap:ImplemBVH` for how the BVH itself is built and traversed; this section only concerns how CSG uses it. Unlike the plain combinators, the BVH variants take the objects' bounding volumes explicitly (a ``std::vector``, one per object) since these are needed up front to build the tree. .. list-table:: :header-rows: 1 :widths: 20 20 20 40 * - Combinator - Wrapper class - Free function - Doxygen * - BVH-accelerated union - ``BVHUnionIF`` - ``BVHUnion`` - `class `__ / `function `__ * - BVH-accelerated smooth union - ``BVHSmoothUnionIF`` - ``BVHSmoothUnion`` - `class `__ / `function `__ Finally, ``FiniteRepetitionIF``/``FiniteRepetition`` tiles a single base implicit function periodically over a finite number of repetitions per axis, by mapping the query point into the nearest tile before evaluating the wrapped function -- effectively a cheap way to instance the same shape many times without constructing a separate ``ImplicitFunction`` (or a CSG union) per copy. See its Doxygen entries for `FiniteRepetitionIF `__ and `FiniteRepetition `__. For the complete, single-page API listing of every class and free function on this page, see the Doxygen page for `EBGeometry_CSG.hpp `__.