sdf.Shell

sdf.Shell(sdf, thickness)

Hollow shell of a shape’s surface: |f(p)| - thickness/2.

The result is a wall of the given total thickness centered on the child’s surface. Exact wherever the child field is exact.

Parameters

Name Type Description Default
sdf Child shape (SDF node or plain callable). required
thickness float | Scalar Total wall thickness. required

Methods

Name Description
patch_fields Both offsets of every child patch: outward first, then inward.
sdf Pure function for the shell operation.

patch_fields

sdf.Shell.patch_fields()

Both offsets of every child patch: outward first, then inward.

sdf(p) = |f(p)| - t/2 is the max composition max(f - t/2, -(f + t/2)), so the wall’s two surfaces sit where the child field reads +t/2 and -t/2. Splitting that over the child’s own patches, child patch f_i contributes exactly two fields, kept adjacent and always in this sense:

  • f_i - t/2 — the outward offset, patch index 2*i, whose zero set is child patch i pushed out by half the thickness;
  • -(f_i + t/2) — the inward offset, patch index 2*i + 1, child patch i pulled in by half the thickness, negated so it too reads positive outside the wall.

Two caveats a reader needs, neither of which the consumer minds:

The offsets are only as exact as the child’s patch field is a true distance near its own surface — f_i(p) = ±t/2 has to mean “half a thickness off patch i”. Every primitive that declares patch fields satisfies this (they are plane, cylinder and revolved-profile distances, exact along their own normal), so the offset surfaces are exact for them; an approximate child field would offset by the wrong amount.

The trims between the offset patches are not the child’s trims. Offsetting outward pushes neighbouring patches apart and the node’s own |f| - t/2 rounds the gap over, while the max composition here continues both patches to a sharp intersection. The consumer re-derives every trim curve from surface-surface intersections rather than inheriting it, so the untrimmed surfaces are what matters — but do not read argmin_i |f_i| as exact ownership in the rounded sliver just outside a convex child edge.

sdf

sdf.Shell.sdf(child_sdf, p, thickness)

Pure function for the shell operation.