Skip to content

0045 — Boolean construction arithmetic is f64; predicates verify, they do not construct ​

  • Status: Accepted
  • Date: 2026-09-04
  • Deciders: Friedrich Schrödter
  • Supersedes: —

Context ​

axiolid-predicates provides certified filtered orient3d and orient2d: static filter, then exact expansion, then dyadic fallback. A reader finding that in the tree reasonably infers that the production mesh boolean is exact.

It is not. In crates/providers/mesh/boolmesh/Cargo.toml, axiolid-predicates is a dev-dependency. Predicates re-decide orientation after the fact in tests; they do not drive intersection-point construction. Intersection coordinates are computed and stored as f64 in TriMesh { positions: Vec<Point3>, .. }.

This was never written down, so the gap between what the tree implies and what the production path provides was left for a reader to discover.

Measured behaviour ​

From axiolid/benchmarks, driving axiolid, upstream boolmesh, Manifold, CGAL (Exact_predicates_exact_constructions_kernel) and OCCT through their own APIs on byte-identical operands.

Well-conditioned input: f64 construction costs nothing. Relative error against derived ground truth after N chained subtractions of 30°-rotated cutters:

naxiolidraw boolmeshmanifoldcgalocct
10002.05e-160
83.97e-160003.97e-16
645.62e-162.81e-1501.12e-153.71e-15

Error does not grow with chain length, and axiolid is at or better than the exact-arithmetic kernels.

Near-degenerate input: it does cost. Two unit cubes overlapping by d along one axis, sweeping d toward an exactly coincident face. Exact answer is d; the table is relative error. 1.00e0 means the kernel returned zero volume — total loss, not degradation.

overlap daxiolidmanifoldcgalocct
1e-31.10e-131.10e-131.10e-131.10e-13
1e-69.81e-117.50e-118.43e-111.21e-10
1e-94.11e-81.80e-82.72e-81.00e0
1e-124.73e-51.00e03.34e-51.00e0
1e-158.52e-11.00e01.12e-11.00e0

Axiolid tracks CGAL closely to 1e-12 and never collapses; it is the second most robust of the four on this probe. At 1e-15 CGAL is ~8x more accurate, and that difference is exact rational constructions. OCCT collapses earliest (1e-9) because BRepBuilderAPI_Sewing runs at a fixed 1e-9 tolerance — "exact kernel" does not imply robust here.

The cost of exactness is real: rebuilding the CGAL shim with Exact_predicates_inexact_constructions_kernel and changing nothing else made it ~20% faster at n=1 and then abort at n=4.

Decision ​

We will keep f64 construction in the production mesh boolean, and we will stop leaving that implicit.

  • Certified predicates remain verification-only. They re-decide orientation in tests and must not be read as an exactness claim about constructed coordinates.
  • The provider measures conditioning and reports it in BooleanEvidence, rather than returning a badly wrong answer with no signal. At 1e-15 overlap the boolean previously returned 0.15x the right volume and said nothing.
  • Conditioning is reported as evidence, not policy. Axiolid does not choose a refusal threshold on the caller's behalf; a caller decides what its domain can tolerate, exactly as it already does with coincident_faces_encountered and output_components.

Published thresholds, from the sweep above, expressed relative to operand size:

relative overlapbehaviour
above 1e-6degradation invisible; treat as trustworthy
1e-6 to 1e-12degrades smoothly; usable with the conditioning flag observed
below 1e-12severe; results must not be trusted without independent checking

Alternatives considered ​

OptionWhy not
Rational/exact constructions throughoutdocs/ROADMAP.md refuses OCCT parity and full CGAL reimplementation. Measured cost is real (the EPICK probe aborted at n=4), and the benefit appears only below 1e-12 relative overlap
Refuse below a fixed thresholdPicks a policy for every caller from one probe family. A structural model at millimetre scale and a mechanism at micron scale disagree about what is degenerate. Refusal remains available to the caller on the reported evidence
Say nothing and keep the status quoThe 1e-15 case returns a badly wrong volume silently, which contradicts the fail-closed stance in #16
Snap near-coincident geometrySilently changes the caller's input — the same class of hidden approximation the kernel exists to avoid

Consequences ​

  • A reader of the tree can no longer mistake verification-only predicates for exact construction.
  • Callers gain a conditioning signal they can act on, and Axiolid does not invent a domain-specific threshold.
  • The gap to CGAL below 1e-12 remains open and is now documented rather than unmeasured. Closing it would require exact constructions, which this ADR declines.

Amendment 2026-09-28: coordinate magnitude, and no RTC facility ​

A boolean measured at survey coordinates (1e6 to 1e7) looked badly wrong, which was first read as a case for exact construction. Probes showed the error was already present in the input's volume, before any boolean ran. It came from catastrophic cancellation in a divergence-theorem sum taken about the world origin. volume_properties and surface_properties in axiolid-measure now sum about the mesh's first vertex, and tests/conditioning.rs there holds thin plates at 1e7 to within 1e-12 relative. Re-basing per triangle was also measured. It was worse by up to six orders of magnitude because it leaves one operand of a . (b x c) at world magnitude, so it was not adopted. second_moments stays about the origin because its value depends on that origin by contract.

Two further arguments for a relative-to-centre (RTC) coordinate facility were measured and refuted (axiolid-predicates and axiolid-mesh-boolean-boolmesh, tests/survey_scale.rs). Coincidence that both sides author the same way survives rounding at every magnitude, so orient3d still certifies Zero and a flush union is exact at 1e7. The filter's escalation rate does not change with magnitude either, so RTC would not make predicates faster. Axiolid therefore has no RTC or local-origin facility and no offset ownership model. The input's own grid, about 1.9e-9 m at 1e7, is a property of the caller's coordinates. Revisit this only if a real workload fails in a way these probes do not cover.

Released under the Mozilla Public License 2.0.