Repository navigation
measure: exact and mesh mass properties summed about the world origin lose precision at site coordinates #343
Description
Reported by openbimrs/ifc (main 988cdb5c, axiolid-mesh-compile 0.3.30, Tolerance::MILLIMETRE, default_backend().compile_mesh_with_deviation; exact path via ReferenceExactCompiler::compile_exact_with_report + axiolid_measure::exact_properties). It covers 29 products whose bodies are booleans with coplanar or flush operands, in three public fixtures in openbimrs/ifc test/fixtures: flush_openings_site_placements, issue_098_wall_W and binding_geometry.
There were two perturbations:
- rt: convert lengths to feet and back.
- ulp: every
IfcCartesianPointcoordinate × (1 + 2e-16).
Observed
-
Reported bounds stay tiny and unchanged. The bound is about 4.5–5e-9 m on all of them (exactly 0.0 on 7 IFC2X3 B-reps), unchanged by the perturbation, with
meets_requestedtrue before and after. -
The mesh volume moves anyway, by 4e-5 up to 101 % relative under the ulp perturbation. The worst products:
fixture product V₀ (m³) area (m²) Δ_ulp (relative) bound × area (m³) issue_098_wall_W #1459222 0.10523 7.45 1.01 3.3e-8 issue_098_wall_W #928672 0.73 issue_098_wall_W #928638 0.53 flush_openings_site_placements ci: bump source-map-js from 1.2.1 to 1.2.2 in /docs #284 / overlay: union of a soup of grown triangles needs gigabytes for a single-polygon result #338 / #396 0.6553 6.20 0.17 (rt: 0.073) 3.1e-8 flush_openings_site_placements construct: accept a ring that joins its hole by a seam traversed both ways (keyhole) on surface paths #270 / Exact boolean of a curved wall minus a cutter flush on its curved face #324 / #382 0.10 issue_098_wall_W #1952768 (bound 0.0) 4.2862 9.3e-3 0 28 of the 29 exceed bound × area by 300× to 10⁶×.
-
The exact path moves too, where it compiles, by the same order (up to 18 %): flush void subtraction tangent to a host face yields a non-manifold mesh #194–#396, issue_098 wall #928204, binding_geometry Exact B-rep is the primary currency; tessellation strictly a requested output #36/Exact planar shortest path over a visibility graph #46.
-
Mesh and exact disagree even unperturbed, by 4e-5 to 3e-2 m³. Examples: flush brep-boolean: a report at Tolerance::ZERO can carry a decision with linear 0 (breaks the #236 contract) #251 at 3.0e-2 m³, measure: boundary_hausdorff_distance misses the matched bound for translated prisms from boolean_arc_prisms_exact #227 at 1.9e-2 m³, the issue_098 wall at 5.0e-3 m³ on 42.37 m³. That is 300 to 200,000 × bound × area.
How to read it against the contract
Under ADR 0080, a boolean with coplanar or flush operands is the exact boolean of operands perturbed within the tolerance, and the measured bound is relative to the exact compiler's result. Its detail then says "operands within tolerance", not "of the given operands". So a flipped tolerance decision may legitimately move the volume by up to about tolerance × the affected area: here 1 mm × the area of the flush faces. Several observations are far outside even that:
- a 101 % change, a body roughly doubling or vanishing;
- mesh and exact differing by 3e-2 m³ on a body under 1 m³;
- reported bounds of 0.0 or about 5e-9 m next to volume changes of 1e-2 m³ and more.
These point at a real defect, for example an inside/outside classification flip, a dropped or doubled cut, or a deviation measurement that does not cover the shape. A strict reading would make it a soundness bug: a certified bound that does not hold. That needs checking first.
Needed
- Reproduce the worst products in the kernel. The fixtures are public, so the graphs can be committed.
- Classify each: (a) a legitimate within-tolerance decision flip, whose volume change is bounded by tolerance × affected area, so it is within contract and only a stability or determinism concern; or (b) a defect, where the mesh or exact result is not the boolean of any operands within tolerance, or the reported bound does not hold for the result it names.
- For (b): fix it. Until then, refuse by name rather than report a bound that does not hold. A test must pin each case: a result within its stated bound of an independently computed reference.
- For (a): decide whether decisions should be made invariant under unit rescaling, so the same model gives the same body in mm and in ft.
- Explain the unperturbed mesh/exact disagreement: is the mesh off its exact body, or does
exact_propertiesread the body differently?
Priority: high. A certified bound that does not hold is the one failure the kernel promises not to have.
Activity
GeneralPawz commentedon Oct 20, 2026
Full per-product table from openbimrs/ifc (main 988cdb5c,
Tolerance::MILLIMETRE).default_backend().compile_mesh_with_deviation.ReferenceExactCompiler::compile_exact_with_report+axiolid_measure::exact_properties.IfcCartesianPointcoordinate × (1 + 2e-16).meets_requestedis true everywhere, before and after.collection)collection)B-rep)The 7 IFC2X3 B-reps (#1952597–#1953698) are
IfcFacetedBrep-based, with a reported bound of exactly 0. In issue_098 and binding_geometry the rt conversion restores the coordinates bit-exactly, so only ulp moves them.Observation for the investigation: many affected products compile to 12 triangles, which is a plain box, although they are walls with openings. A 12-triangle box whose volume changes by 2 % under a 2e-16 relative perturbation of its inputs cannot come from moving its own vertices. That points at cuts being dropped, or applied differently, depending on ulp-level decisions upstream of the mesh, for example a flush opening read as not crossing the wall, or the subject's own extrusion/placement being read differently.
GeneralPawz commentedon Oct 20, 2026
Triage: confirmed high priority, work started. Plan as in "Needed": reproduce the worst products as kernel-level graphs, classify each as (a) a within-tolerance decision flip or (b) a defect, fix or refuse by name for (b), pin each with a test against an independent reference, and explain the unperturbed mesh/exact gap. Any decision on unit-rescaling invariance or the meaning of a bound comes back to the maintainer before it is implemented.
[-]mesh-compile/brep-boolean: coplanar booleans change volume far beyond their certified bound under ulp-level rescaling[/-][+]measure: exact and mesh mass properties summed about the world origin lose precision at site coordinates[/+]GeneralPawz commentedon Oct 20, 2026
Findings: the boolean bounds held, and no coplanar boolean was at fault.
a·(b×c)over the mesh in the consumer's harness, andaxiolid_measure::exact_propertieson the exact path. Summed about a point of the body instead, every mesh volume is unchanged under ulp and rt, to about 1e-15 relative.meets_requestedholds.exact_propertiesitself. It measured a 0.57 m³ box at site coordinates up to 18 % wrong, with no error.Fixed on main:
exact_propertiesintegrates about a point of the solid, shifting the centroid and second moments back by the parallel-axis terms.mesh::second_momentsdoes the same.Certified(w)instead of 0. A bound of 0 now means planar. See the ADR 0080 amendment.Each fix has tests that fail on the previous main, and mutation probes that kill 7/7, 5/5 and 6/6. Release: axiolid-measure 0.3.11 and axiolid-mesh-compile 0.3.31.
fix(measure): integrate exact mass properties about a point of the so…
fix(mesh-compile): a faceted face reports its slab unless exactly pla…
fix(measure): mesh second moments summed about the mesh's first vertex (
GeneralPawz commentedon Oct 20, 2026
Fixed in 0db1151, c0dfcd7 and d14b03c. Released as axiolid-measure 0.3.11 and axiolid-mesh-compile 0.3.31 (ff837f2).
build(axiolid): move to axiolid-measure 0.3.11, mesh-compile 0.3.31 a…