Skip to content

measure: exact and mesh mass properties summed about the world origin lose precision at site coordinates #343

Closed

Description

@GeneralPawz

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 IfcCartesianPoint coordinate × (1 + 2e-16).

Observed

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

  1. Reproduce the worst products in the kernel. The fixtures are public, so the graphs can be committed.
  2. 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.
  3. 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.
  4. 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.
  5. Explain the unperturbed mesh/exact disagreement: is the mesh off its exact body, or does exact_properties read the body differently?

Priority: high. A certified bound that does not hold is the one failure the kernel promises not to have.

Activity

  1. GeneralPawz commented on Oct 20, 2026

    @GeneralPawz
    ContributorAuthor

    Full per-product table from openbimrs/ifc (main 988cdb5c, Tolerance::MILLIMETRE).

    • Mesh: default_backend().compile_mesh_with_deviation.
    • Exact: ReferenceExactCompiler::compile_exact_with_report + axiolid_measure::exact_properties.
    • Δ = |ΔV| / V.
    • rt: feet and back. ulp: every IfcCartesianPoint coordinate × (1 + 2e-16).
    • The bound is unchanged by both perturbations, and meets_requested is true everywhere, before and after.
    • Selection: the products whose mesh volume moved more than 1e-9 relative (29 of 181).
    fixture / product tris V₀ mesh (m³) Δrt Δulp bound (m) area (m²) bound × area exact Δrt / Δulp mesh − exact (m³, unperturbed)
    flush #194 12 3.3408 1.0e-2 2.0e-2 4.97e-9 30.45 1.5e-7 5.3e-3 / 2.0e-2 1.6e-2
    flush #213 12 0.5291 7.5e-8 1.1e-7 4.97e-9 6.20 3.1e-8 7.4e-8 / 3.1e-4 4.7e-3
    flush #227 12 0.5634 7.0e-8 4.0e-8 4.97e-9 6.20 3.1e-8 3.0e-4 / 3.7e-8 1.9e-2
    flush #251, #301 12 3.3195 4.2e-4 5.1e-3 4.97e-9 30.45 1.5e-7 6.6e-3 / 2.0e-3 3.0e-2
    flush #270, #324, #382 12 0.6067 9.1e-4 1.0e-1 4.97e-9 6.20 3.1e-8 6.1e-4 / 5.0e-2 5.2e-3
    flush #284, #338, #396 12 0.6553 7.3e-2 1.7e-1 4.97e-9 6.20 3.1e-8 8.3e-2 / 1.8e-1 8.5e-3
    flush #363 24 3.3587 1.0e-2 2.3e-2 4.97e-9 32.29 1.6e-7 refused (collection) –
    issue_098 #928204 (wall) 12 42.3676 0 9.8e-6 4.48e-9 183.39 8.2e-7 0 / 2.3e-4 5.0e-3
    issue_098 #928638 96 0.18643 0 5.3e-1 4.48e-9 7.45 3.3e-8 refused (collection) –
    issue_098 #928672 96 0.17232 0 7.3e-1 4.48e-9 7.45 3.3e-8 refused –
    issue_098 #928894 132 0.23878 0 1.1e-1 4.48e-9 10.89 4.9e-8 refused –
    issue_098 #928928 132 0.19689 0 7.8e-2 4.48e-9 10.89 4.9e-8 refused –
    issue_098 #928962 96 0.12466 0 3.5e-1 4.48e-9 7.45 3.3e-8 refused –
    issue_098 #1459222 96 0.10523 0 1.01 4.48e-9 7.45 3.3e-8 refused –
    issue_098 #1459256 96 0.11675 0 6.9e-2 4.48e-9 7.45 3.3e-8 refused –
    issue_098 #1952597 44 4.3073 0 3.7e-4 0.0 17.44 0 refused (B-rep) –
    issue_098 #1952768 44 4.2862 0 9.3e-3 0.0 17.44 0 refused –
    issue_098 #1952954 56 1.6405 0 1.5e-2 0.0 12.46 0 refused –
    issue_098 #1953140 56 1.6207 0 1.4e-2 0.0 12.46 0 refused –
    issue_098 #1953326 56 1.6352 0 4.1e-3 0.0 12.46 0 refused –
    issue_098 #1953512 56 1.6405 0 4.4e-3 0.0 12.46 0 refused –
    issue_098 #1953698 56 1.6298 0 5.8e-3 0.0 12.46 0 refused –
    binding_geometry #36 12 2.23953 0 4.4e-4 4.80e-9 25.12 1.2e-7 0 / 3.4e-4 2.5e-4
    binding_geometry #46 12 5.99959 0 4.1e-5 4.80e-9 64.40 3.1e-7 0 / 5.8e-6 4.2e-5

    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.

  2. GeneralPawz commented on Oct 20, 2026

    @GeneralPawz
    ContributorAuthor

    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.

  3. changed the title [-]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[/+] on Oct 20, 2026
  4. GeneralPawz commented on Oct 20, 2026

    @GeneralPawz
    ContributorAuthor

    Findings: the boolean bounds held, and no coplanar boolean was at fault.

    • Reproduction: all 29 products were reproduced, and the table's numbers match exactly. Every volume in it was summed about the world origin at georeferenced coordinates of about (6e5, 5.6e6) m. That sum was the naive a·(b×c) over the mesh in the consumer's harness, and axiolid_measure::exact_properties on 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.
    • 12-triangle bodies: these are the gross Body meshes and the opening elements' own boxes. No cut is dropped.
    • Net (cut) bodies: mesh and exact agree within 2.4e-10 m³ (brep-boolean: a report at Tolerance::ZERO can carry a decision with linear 0 (breaks the #236 contract) #251: 2.2075750000614 against 2.2075750003022). That is within bound × area, and meets_requested holds.
    • Item 4: no rescaling-invariance decision is needed.
    • Item 5: the mesh/exact gap was exact_properties itself. It measured a 0.57 m³ box at site coordinates up to 18 % wrong, with no error.

    Fixed on main:

    • 0db1151: exact_properties integrates about a point of the solid, shifting the centroid and second moments back by the parallel-axis terms.
    • d14b03c: mesh::second_moments does the same.
    • c0dfcd7 (maintainer decision): a face without a surface that is not exactly coplanar reports its slab width 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.

  5. GeneralPawz commented on Oct 20, 2026

    @GeneralPawz
    ContributorAuthor

    Fixed in 0db1151, c0dfcd7 and d14b03c. Released as axiolid-measure 0.3.11 and axiolid-mesh-compile 0.3.31 (ff837f2).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions