Tolerant topology — declare the gap, name the weld
A tolerant edge, vertex or face carries its own statement of how well it is
known: "this curve/corner/surface is only known to within r". ops/stitch.js's
sew tolerance is a single number by default (the model's own resabs); a declared
per-entity tolerance widens only the entities that declare it, through one shared
accessor (CoincidencePolicy.tolFor / widenOf). Every case below is the
same two-rim seam — the exact fixture
tests/test_cadsf-948.js and tests/test_cadsf-949.js use — that does not
pair at the model's own tolerance, paired (or, in the last case, deliberately refused) by one
declaration, with the heal report saying which entity bought the radius.
CP.tolFor(topology, edgeOrVertexOrFaceId, fallbackTol) // → max(fallback, what the id declares) CP.widenOf(topology, id) // → what the id declares ABOVE the model default
A declaration above TOLERANCE_CAP_MULTIPLIER × resabs (the ADR-2
widening ceiling) is named in the report and not silently used — see the last card.
Nothing declared ⇒ every number below is byte-identical to a model with no tolerant topology at all
(the inertness rule, docs/TOLERANT_TOPOLOGY.md).
Five declarations, one seam
Each card: the entity/entities that declare, a viewer pane (the seam before the weld,
after the weld, and re-parsed out of the shipped STEP — posters until you press View in 3D,
then NativeCAD's own glTF viewer), the weld before and after (from ops/stitch.js directly,
and from the orchestration layer ops/healPipeline.js), and a STEP
NativeCAD.tolerance property-block round trip plus a Parasolid XT write-back, both
verified exact on every run this generator makes. The download is the seam. Each
case writes the body ops/stitch.js published — a MANIFOLD_SOLID_BREP where
the declaration paired the rims, a SHELL_BASED_SURFACE_MODEL where it did not — so the
.step and .x_t beside each card hold the body the card is about, and the
third pane is that file read back in. The two rims are coincident coplanar half-discs
0.2 µm apart, so every pane draws rim B 1.5 mm below rim A (a node offset in the GLB,
stated in index.json) — the weld is a change of topology, not of anything you could
see; the declared face is tinted, a refused one tinted red.
One asymmetry, stated rather than hidden: STEP is written from the whole model and XT
from the one body, so where the weld merged rim A and rim B into a single edge, the superseded
edge's declaration is still in the .step but is not in the .x_t.
index.json carries both sets (modelByKind, bodyByKind) and each
file is checked against the one that is actually its own.
Why a declaration is not a blank cheque
- Per entity, not per model. A declared tolerance widens the sew radius only for the edges/vertices/faces that carry it; a sibling entity that declares nothing is judged at the model's own tolerance, unchanged.
- Faces speak for their own rim. A tolerant FACE's declaration is the pairing
ceiling for its own edges and corners too — a gap inside the face tolerance but outside every
edge tolerance still closes (
tests/test_cadsf-949.js's "sheet bag" case). - Two declarations take the max, never a sum. Both sides of a seam declaring the same number welds at that number, not double it.
- A ceiling, not a suggestion. A face declaration over the ADR-2 cap is
refused outright —
appliedis exactly 0, and the report says so by name (overCap: true), never silently clamped and used. - The declaration survives the trip out and back. The same number, written to
STEP as a documented
NativeCAD.toleranceproperty block or to Parasolid XT, reads back exactly — verified on every run, not asserted once and trusted forever.
More demos
All demos →One solid, every triangle budget
The same solid exported at coarser and coarser detail, watertight at every level, ready for game engines.
5 detail levels per part glTF galleryCAD models any glTF viewer can run
Runtime-ready models with real materials, sharp creases and animation clips, ready to drop into any viewer.
19 models to download 3D-PDF galleryCAD models your PDF reader can rotate
3D PDFs of real parts and assemblies, with dimensions on the model, each shipped beside its STEP file.
V12 engineA V12 engine you can run, slice and take apart
Every crank, rod, cam and valve is a real solid, turning in your browser from one dial: the crank angle.
361 parts · 2,850 placementsBuild your own part with NativeCAD
Free for education and makers with a registered key · $200 per seat per year · Kernel SDK for products.