Adaptively sampled distance fields in ℝᴺ, with Lipschitz-certified pruning.
An ADF stores a signed distance field as a 2^N-tree whose leaves each hold a handful of Primitives — a field
closure paired with an honest upper bound on its gradient. The tree represents their pointwise min, so a field
composed of millions of primitives is sampled in logarithmic time by descending to the leaf covering the query
point, instead of evaluating every primitive.
What makes that sound rather than merely fast is the Lipschitz bound. Every decision the structure makes — whether a new primitive can be skipped, whether a stored one has become redundant, which subtrees an insertion can possibly change — is settled by branch-and-bound over
f - g ≥ (f - g)(c) - (L_f + L_g)·h
which either proves a region clean or descends to a witness. A primitive is never dropped on a heuristic, only on
a proof, so the stored field never deviates from the min over everything inserted.
use ;
// seed a 3D field with the walls of the unit cube, positive inside
let mut field = ADF::new;
// climb to a local maximum of the free space — the deepest point around
let start = from;
let peak = default.optimize;
let clearance = field.sdf;
// drop a ball there, and let the tree work out which cells that can affect
let ball = move |p: | .length - clearance / 2.0;
field.insert_at_maximum;
Layout
geometry— the vocabulary:PointandVector(bothnalgebra's, re-exported so downstream code can name the same versions), the axis-alignedAabb,BoundingBox, and theCombinatortrait — every way to transform or combine one field into another. Each combinator preserves ormax-combines its operands' constants, so a composed chain still reports an honest bound.sdf— theSDFandLipschitztraits everything is written against, the field types the combinators return, andsdf_geq_everywhere: the branch-and-bound proof that underpins all of it.boundary_rectseeds a field with the walls of the unit cube.adf— the structure itself, over thequadtreearena.line_search— adaptive gradient ascent, for locating the maxima thatinsert_at_maximumconsumes.
Dimension count is a compile-time constant throughout, so ADF<f64, 2> and ADF<f64, 3> monomorphize separately
and the 2D case costs exactly what a quadtree-only implementation would.
Beyond this crate
The space-filling crate builds on this one: a catalogue of shape primitives in
2, 3, 4 and N dimensions, a discrete bitmap solver for exact global maxima, batched parallel maxima search, and 2D
rasterization. Its readme states the ADF algebra in full.
Licence
GPL-3.0 — see LICENCE.