Problem
axiolid_measure::mesh_distance reports a NONZERO separation for two meshes whose triangles genuinely interpenetrate, contradicting the module doc:
two that interpenetrate deeply [report distance zero], because their surfaces cross
Observed on a real fixture: kernel distance_squared = 3808.65, exhaustive local reference 0, for two 12-triangle beam meshes that cross.
Reproduction
Added to crates/algorithms/query/measure/tests/mesh_proximity.rs, reduced from a real beam/duct fixture. A beam box (x 0..8000, y -500..500, z 0..1000) is pierced by a duct box (x 3900..4100, y -1000..1000, z 400..600). The duct is narrower in x and z but WIDER in y, so it enters one face and exits the opposite one.
a pierced box must report zero separation, got distance_squared 3808.6532602071893
Root cause
closest_points_on_triangles in crates/algorithms/query/measure/src/proximity.rs samples three families:
- each vertex of A against triangle B
- each vertex of B against triangle A
- each edge of A against each edge of B
For two triangles crossing transversally, the minimum separation is realised where an EDGE passes THROUGH a FACE. No vertex is involved and no two edges approach, so all three families miss it and the pair reports its nearest non-intersecting feature instead of zero.
Coplanar overlap is caught (edge/edge finds it), which is why the existing touching_and_crossing_both_report_zero_separation test passes: both its cases are coplanar squares. The transverse case is untested.
Impact
Contradicts the documented contract in the module header and on MeshDistance::surfaces_cross, which both state that interpenetrating surfaces report zero.
A consumer asking "do these clash?" via mesh_distance gets a confident nonzero separation for a genuine interpenetration — a missed clash rather than a refusal. Fail-open, and indistinguishable from a real gap.
Done when
- transverse triangle crossings report distance_squared == 0 and surfaces_cross == true
- the fix adds a segment/triangle intersection family to closest_points_on_triangles rather than special-casing meshes
- a regression test covers the NON-coplanar crossing
- proximity_components is checked for the same gap: it shares the pairwise scan
Problem
axiolid_measure::mesh_distancereports a NONZERO separation for two meshes whose triangles genuinely interpenetrate, contradicting the module doc:Observed on a real fixture: kernel
distance_squared = 3808.65, exhaustive local reference0, for two 12-triangle beam meshes that cross.Reproduction
Added to
crates/algorithms/query/measure/tests/mesh_proximity.rs, reduced from a real beam/duct fixture. A beam box (x 0..8000, y -500..500, z 0..1000) is pierced by a duct box (x 3900..4100, y -1000..1000, z 400..600). The duct is narrower in x and z but WIDER in y, so it enters one face and exits the opposite one.Root cause
closest_points_on_trianglesincrates/algorithms/query/measure/src/proximity.rssamples three families:For two triangles crossing transversally, the minimum separation is realised where an EDGE passes THROUGH a FACE. No vertex is involved and no two edges approach, so all three families miss it and the pair reports its nearest non-intersecting feature instead of zero.
Coplanar overlap is caught (edge/edge finds it), which is why the existing
touching_and_crossing_both_report_zero_separationtest passes: both its cases are coplanar squares. The transverse case is untested.Impact
Contradicts the documented contract in the module header and on
MeshDistance::surfaces_cross, which both state that interpenetrating surfaces report zero.A consumer asking "do these clash?" via
mesh_distancegets a confident nonzero separation for a genuine interpenetration — a missed clash rather than a refusal. Fail-open, and indistinguishable from a real gap.Done when