STEP import: a spline face's edges are measured on their pcurves only, not by nearest point first

The nearest point on a spline (5cb015fae measured spline faces up front too) may settle on
another part of the surface, or on its boundary for a point a hair past it, and reported gaps
the edges do not have: 2.9 mm on Poppy Humanoid's leg shells, whose edges lie within 0.003 mm
of their faces, and widened tolerances past what SMLib takes (it then refused
models/vertices-off-curves.step). The up-front measure is again for faces whose nearest point
is in closed form (plane, cylinder, cone, sphere, torus); a spline face's gaps are measured
on the pcurves its kernel makes, as the record check measures them.

The corpus survey is back to 53 of 56 files; Poppy imports 238 bodies (10 solids refused,
most for SMLib's pcurves on spline faces: solidcore#1383).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-27 20:45:43 -04:00
committed by Irakli Kourtis
parent 77bd85cabf
commit 1404bc1f5e
+16 -3
View File
@@ -458,10 +458,23 @@ impl<'b, 'a> Builder<'b, 'a> {
/// and the edge's tolerance covers it. A spline face's gaps are measured on the pcurves its
/// kernel makes (`raise_edges`): an iterative nearest point may settle elsewhere on it.
fn measure_edges(&mut self, surface: &BSurface, edge_loops: &[Vec<(u32, bool)>]) -> R<()> {
// Only where the nearest point is in closed form: on a spline the search may settle on
// another part of the surface, or on its boundary for a point a hair past it, and report a
// gap the edge does not have (2.9 mm on Poppy Humanoid's leg shells, whose edges lie within
// 0.003 mm), widening tolerances past what SMLib takes. A spline face's gaps are measured
// on the pcurves its kernel makes (`raise_edges`).
if !matches!(
surface,
BSurface::Plane { .. }
| BSurface::PlaneThrough { .. }
| BSurface::Cylinder { .. }
| BSurface::Cone { .. }
| BSurface::Sphere { .. }
| BSurface::Torus { .. }
) {
return Ok(());
}
let on = SurfaceEval::new(surface).map_err(|m| m.to_string())?;
// One search grid for all of the face's points, each searched from the whole grid: a
// nearest point carried on as the next one's start can settle on another part of a
// closed spline.
let starts = solidcraft_geom::tess::uv::Starts::default();
for l in edge_loops {
for &(e, _) in l {