Geometry & modeling
Overview
Rasmah represents a shape not as a fixed list of numbers, but as a program. That program is built from small, immutable building blocks — a sphere, a box, a boolean cut — composed into a tree. To change the shape you change a parameter, and the whole downstream pipeline (geometry, mesh, simulation) recomputes from that one change.
This matters for a simple reason: if the model is a program, then its derivatives are programs too. The gradient of "how does the stress change when I move this face" can be computed automatically, which is what makes Rasmah's CAD → mesh → simulation → loss pipeline differentiable end to end.
This chapter introduces the three ideas that make this possible:
- the feature graph — the tree of immutable nodes that is the model;
- the signed distance field (SDF) — the implicit representation that lets any shape be a single scalar function of position;
- the backends — the three ways to evaluate the same feature graph (implicit SDF, exact boundary representation, or a mesh).
A model is a function
A parametric model in Rasmah is a plain Julia function of its free values:
model(r) = sphere(r)For any radius r this rebuilds the same feature graph. Because the feature nodes are immutable (they cannot be changed after they are built), the model is a pure function: the same r always gives the same shape.
To differentiate the model you use derivative (with respect to a single scalar) or gradient (with respect to a vector of values):
derivative(r -> volume(sphere(r)), 2.0)50.26548245743669 m^3Notice the $\mathrm{m}^3$ on the answer. Rasmah carries physical units on its results — a volume is a length cubed, so it is reported in cubic metres — and a bare number like $2.0$ is read in SI units. For now just read the number and trust the tag; the full units system is the Units chapter.
Here $\mathrm{d}V/\mathrm{d}r = 4\pi r^{2}$ is the surface area of the sphere — a good sanity check, because growing a sphere's radius by a tiny $\mathrm{d}r$ adds a thin shell of area $4\pi r^{2}$ and thickness $\mathrm{d}r$.
The feature graph
A feature graph is a tree of immutable nodes. The leaves are primitives (sphere, box, …) and the interior nodes are combinators (difference, translate, scale, …). The abstract supertype of every node is Feature:
Rasmah.Feature — Type
FeatureAbstract supertype of all parametric CAD nodes (primitives and combinators). A parametric model is a plain function of its free values, differentiable through derivative/gradient.
Each node exposes its children (its free parameters and sub-features) through children, which is how the differentiation machinery walks the tree.
Signed distance fields
A signed distance field is a function $s(\mathbf{x})$ that returns the shortest signed distance from the point $\mathbf{x}$ to the surface of a shape:
- $s(\mathbf{x}) < 0$ — the point is inside the shape;
- $s(\mathbf{x}) = 0$ — the point is on the surface;
- $s(\mathbf{x}) > 0$ — the point is outside the shape;
and $|s(\mathbf{x})|$ is always the actual distance to the nearest surface point. For a sphere of radius $r$ centred at the origin:
\[s(\mathbf{x}) = \|\mathbf{x}\| - r .\]
The magic of the exact SDF is that its gradient has unit length almost everywhere, $\|\nabla s\| = 1$. That makes the field smooth and predictable, so marching-cubes meshing, ray casting, and inside/outside tests all behave well. Rasmah's implicit geometry is exactly this:
Rasmah.ImplicitGeometry — Type
ImplicitGeometryAbstract supertype of all signed-distance-field (SDF) geometry.
A signed distance field is a function s(x) whose value at a point x is the shortest signed distance to the surface of a shape: it is negative inside, zero on the surface, and positive outside, and $|s(x)|$ is the distance to the surface. The gradient $\nabla s$ then has unit length wherever it is defined, which is what makes SDFs convenient for meshing (marching cubes/tetrahedra), ray casting, and physics that need an inside/outside test.
A concrete subtype is a callable g(x) returning the signed distance at x, and it supplies bounds(g) for its axis-aligned bounding box (lo, hi).
The feature nodes (sphere, box, …) are converted into ImplicitGeometry values through evaluate with the SDFBackend; the SDF types themselves are the backend's working form.
See also
Rasmah.field — Function
field(g, x) -> Float64Evaluate the signed distance field of the implicit geometry g at the point x (an alias for g(x)).
The result is negative inside the shape, zero on its surface, and positive outside, with |field(g, x)| the shortest distance to the surface.
Arguments
g: a feature (or implicit geometry) to sample.x: a 3-vector point.
Example
julia> using Rasmah
julia> field(sphere(1), [2.0, 0, 0])
1.0Rasmah.gradient — Function
gradient(f, x) -> Vector / QuantityVectorGradient ∂f/∂x of a scalar function f with respect to a vector of values x, computed with the default AD backend. Each component carries dimensions udim(f(x)) / udim(x); when that dimension is dimensionless (a plain vector input and a dimensionless output) a plain Vector is returned instead of a QuantityVector.
The three backends
The same feature graph can be turned into geometry in three different ways, selected by the backend you pass to evaluate:
| Backend | Result | What it stores |
|---|---|---|
SDFBackend | ImplicitGeometry | a signed-distance formula |
BRepBackend | BRep | exact topology — faces, edges, vertices |
MeshBackend | TriangleMesh / TetMesh | a discretized surface / volume |
The shorthand brep is evaluate(model, BRepBackend()). Because the parameters live in the feature graph and each backend re-derives its geometry from them, the parameters stay differentiable no matter which backend you use.
Rasmah.evaluate — Function
evaluate(model, backend) -> geometryEvaluate a model (a feature graph, sketch, or implicit geometry) through a geometry backend, returning the corresponding concrete geometry.
evaluate is the shared entry point for Rasmah's three geometry representations:
| backend | returns | stores |
|---|---|---|
SDFBackend | ImplicitGeometry | a signed-distance formula |
BRepBackend | BRep | exact topology (faces, edges, vertices) |
MeshBackend | TriangleMesh/TetMesh | a discretized surface/volume |
The same feature graph can be evaluated through any backend, which is what keeps the CAD → mesh → simulation pipeline differentiable: parameters live in the feature graph, and each backend re-derives its geometry from them.
Arguments
model: aFeature(e.g. fromsphere,difference), a sketch, or anImplicitGeometry.backend: the evaluation backend (default shorthandbrepisevaluate(model, BRepBackend())).
Example
julia> using Rasmah
julia> s = evaluate(box(2, 2, 2), SDFBackend());
julia> field(s, [0.0, 0.0, 0.0])
-1.0Rasmah.SDFBackend — Type
SDFBackendThe geometry backend that converts a feature tree (or sketch) into an ImplicitGeometry signed-distance field.
Pass it to evaluate to evaluate a feature graph as a signed distance field — for example evaluate(box(2, 2, 2), SDFBackend()) returns a BoxSDF. The SDF is the implicit representation: it stores a formula, not a mesh, so it stays differentiable in the feature parameters.
See also
evaluate, brep, MeshBackend.
Measuring geometry
Every shape can answer two basic questions — how big is it? and where is it? — via its analytic volume / area and its axis-aligned bounds:
Rasmah.volume — Function
volume(x) -> QuantityThe volume of a geometry or mesh x, as an SI Quantity of volume dimension (D_VOLUME; see the Units chapter).
For primitives and closed-form solids the volume is analytic (exact), e.g. $4\pi r^{3}/3$ for a sphere, $\pi r^{2} h$ for a cylinder, $2\pi^{2}\, R\, r^{2}$ for a torus, and Pappus's area(profile)·path length for sweeps. Translation and rotation preserve volume; uniform scale by s scales it by $|s|^{3}$. For a TetMesh the volume is the signed sum of the tetrahedron volumes.
Arguments
x: a feature,ImplicitGeometry, or mesh.
Returns
A Quantity with dimension m³ (or the current display unit).
Example
julia> using Rasmah
julia> volume(sphere(2))
33.510321638291124 m^3See also: area, surface_area.
Rasmah.area — Function
area(x) -> QuantityThe (surface) area of a 2D geometry x, as an SI Quantity of area dimension (D_AREA; see the Units chapter).
For sketches the area is analytic: $\pi r^{2}$ for a circle, the shoelace formula for a polygon, and the swept area for a slot/ellipse. For surface meshes use surface_area.
Example
julia> using Rasmah
julia> area(circle_2d(2.0))
12.566370614359172 m^2Rasmah.bounds — Function
bounds(g) -> (lo, hi)The axis-aligned bounding box of the geometry g, as a pair (lo, hi) of 3-vectors giving the minimum and maximum corners.
For primitives the box is tight (e.g. sphere(2) → ([-2,-2,-2], [2,2,2])); for boolean combinations and patterns it is the (possibly conservative) union or intersection of the operands' boxes. A plane has infinite extent and therefore no bounding box, so bounds throws for it; hand the finite region of interest explicitly to any operation that needs one (meshing or clipping a plane).
Arguments
g: anImplicitGeometry, feature (viaevaluate), or mesh.
Example
julia> using Rasmah
julia> bounds(evaluate(torus(2, 0.5), SDFBackend())) == ([-2.5, -2.5, -0.5], [2.5, 2.5, 0.5])
truebounds(f::PlanarBRepField) -> (lo, hi)Axis-aligned bounding box of f, the implicit signed field of a polyhedral (planar-faced) BRep (see PlanarBRepField). Returns the stored box.
volume(cylinder(1, 2))6.283185307179586 m^3For a cylinder, $V = \pi r^{2} h = \pi \cdot 1^{2} \cdot 2 \approx 6.283$.
Next steps
Now that you know how a model is represented and evaluated, move on to the shapes themselves: Primitives, SDFs, and CSG.
