difftest: preserve exact face classification geometry

Reuse lossless analytic surface and edge-curve transport. All 1401 cases now compare values, replacing 27 both-error comparisons; retain original fixture identities, guards, and tolerances.

Co-Authored-By: OpenAI GPT-6.1 <noreply@openai.com>
This commit is contained in:
Alex Lytvynenko
2026-10-26 22:00:35 +01:00
parent 345834a8c8
commit e6da98ef94
3 changed files with 25 additions and 13 deletions
+11 -12
View File
@@ -5,13 +5,14 @@
//! file, optionally with rebuilt UV trim curves, or `CreateFaceFromSurface` over a
//! B-spline surface or a real `SmPlane`), optionally overwrites stored face, edge and
//! vertex tolerances, then runs `SmFace::PointClassify`, `sm_ClassifyParamOnFaces` (a
//! verbatim copy) or `SmFace::CurveOnClassify`. There is no Rust B-rep reader or builder
//! yet, so the Rust side imports the edited graph the shim exports (unit
//! `topology.face_p2`'s layout and importer: topology, tolerances, UV domains, planes and
//! B-spline surfaces, B-spline and line curves, UV trim curves) and runs the port on it.
//! A face whose surface, or one of whose loop edges' curves, is an `SmBSplineSurface` /
//! `SmBSplineCurve` subclass the export carries only as its B-spline part is not
//! compared (both sides report `inexact_geometry`).
//! verbatim copy) or `SmFace::CurveOnClassify`. The Rust side imports the edited graph
//! the shim exports using `topology.face_p2`'s importer: topology, tolerances, UV
//! domains, planes, B-splines and losslessly round-tripped analytic surfaces and EDGE
//! curves. UV trim curves retain their ordinary B-spline export. The shared exporters
//! preserve supported revolution/extrusion surfaces and ellipse/circle EDGE curves,
//! including their analytic data and flags. Unsupported subclasses and representations
//! that fail the exporters' lossless round-trip checks remain `inexact_geometry`;
//! neither engine's classification is compared for those faces.
//!
//! **Points.** The classified parameter point is computed from the imported B-rep
//! (identically for both sides, then passed to both): a fraction of the face's UV
@@ -1062,11 +1063,9 @@ fn gen_at(rng: &mut Rng) -> At {
}
}
/// The upstream `.smb` files whose faces the export carries exactly (B-spline surfaces
/// and curves; the other files of `topology.edgeuse_p1`'s list have surfaces of
/// revolution, extrusion, cones, spheres or tori, which the export carries only as
/// their B-spline parts). `Mouse.smb` and `box_with_large_fillet.smb` have several
/// faces (two and one of them inexact).
/// The historically preferred upstream files with mostly plain B-spline geometry.
/// Keep this selection and its random draw order stable as exact analytic transport
/// broadens coverage; each selected face still passes the runtime losslessness check.
const EXACT_FILES: [&str; 7] = [
"Endcap.smb",
"Mouse.smb",
+4 -1
View File
@@ -26,6 +26,8 @@
// Before classifying, the trimmed surface cache of each face surface involved is deleted
// (SmCacheMgr::DeleteObjectsCache): reading a file can leave one, and the port has no
// object caches, so both sides classify through the loops.
#include "sc_analytic_export.h"
#include "sc_exact_curve_export.h"
#include "sc_shim.h"
#include "support/topology_fixture.h"
@@ -664,6 +666,7 @@ void export_graph(SmBrep* brep, Graph& g, std::vector<double>& o)
for (SmFace* p : g.faces)
{
SmSurface* s = p->*FPeek::srf();
sc_analytic_export::put_exact_head(o, s, the_context());
put_surface(o, s);
o.push_back((double)g.find(2, p->*FPeek::fu()));
SmExtent2d d = p->*FPeek::dom();
@@ -719,7 +722,7 @@ void export_graph(SmBrep* brep, Graph& g, std::vector<double>& o)
for (SmTopology* t : list_of(p->GetList()))
v.push_back(g.find(6, t));
put_list(o, v);
put_curve(o, p->GetCurve());
sc_exact_curve_export::put_export_curve(o, p->GetCurve(), the_context(), put_curve);
}
for (SmVertexuse* p : g.vertexuses)
{
+10
View File
@@ -9,4 +9,14 @@ tests = ["prog_test:my_test_surface_closest_point", "prog_test:my_test_drop_poin
status = "green"
claimed_by = ""
claimed_at = ""
# PR #1216: query shim now emits shared lossless analytic surface heads and exact
# ellipse/circle EDGE records; ordinary UV trim/output curve records are unchanged.
# Verified locally against Apple-Clang C++: 1401/1401 pass, all with values,
# zero failed/deferred/both-error cases, max_rel_err=0; perturbation detects 1401/1401.
# Unchanged-main baseline: 1374 with values and 27 both-error cases.
# Existing PointClassify grids/boundaries and CurveOnClassify inputs are unchanged.
# Canonical Linux CI remains the merge gate; historical notes below retain their dates.
# Unsupported subclasses and records failing shared lossless round-trip checks stay
# inexact, including revolution/extrusion forms whose required NURBs are absent or
# whose serialized representation cannot be restored identically.
notes = "GREEN (2026-10-25, PR #970): all 1401 cases pass (1374 with values, 27 both_errored, 0 failed, 0 deferred, max_rel_err=0e0, --perturb SENSITIVE) with PR #754 on main; bare-surface fallback arms marked DISPATCH GAP. PARTIAL (PR #800): difftest 1401 cases (1101 fixture: grids over the 13 exactly exported faces of the upstream .smb files Endcap, Mouse, box_with_large_fillet, disk, ellips_ts2, plane_circ, plane_square; points on, near and at the ends of every trim curve at offsets 0..1e-3; target-loop selections on ellips_ts2's face with two inner loops; SM_API_test TestSmCreateRectangle's 10x6 rectangle at the origin and at 1e10 on a real SmPlane; sm_ClassifyParamOnFaces face pairs; SmProtoVertex containment at the tolerance/capture limits; CurveOnClassify; trim-cache fixtures from #826; 300 generated incl. tiny/huge B-spline and plane faces, tolerance edits and out-of-domain points), 1400 passed, 0 failed, 1 deferred (blocked_by=surface.surface_p2(1), gen0142 awaiting PR #754), bit-identical (max_rel_err 0); --perturb SENSITIVE. In PR #800: implemented topology_entity and topology_handle on Objects to resolve SmEdge::GetCurve and SmFace::Point3DClassify, matched SM_UNINIT_TOL default in CurveOnClassify, and wired face_surface_cache in Point3DClassify (query.face_p1). main CI e33985411 (2026-10-23): PARTIAL query.face_p2 cases=1344 passed=1326 failed=0 deferred=18 blocked_by=query.face_p1(4),topology.edge(14). After intersect.curve_class_p2 (PR #85) merged: CurveOnClassify cases now compared (status, modified flag, every interval and its three point classifications; line is SmBSplineCurve::CreateLineSegment on both sides): 1344 cases, 1310 pass, 0 fail, 34 deferred; --perturb 1310/1310. PARTIAL: difftest 1344 cases (1044 fixture: grids over the 13 exactly exported faces of the upstream .smb files Endcap, Mouse, box_with_large_fillet, disk, ellips_ts2, plane_circ, plane_square; points on, near and at the ends of every trim curve at offsets 0..1e-3; target-loop selections on ellips_ts2's face with two inner loops; SM_API_test TestSmCreateRectangle's 10x6 rectangle at the origin and at 1e10 on a real SmPlane; sm_ClassifyParamOnFaces face pairs; SmProtoVertex containment at the tolerance/capture limits; CurveOnClassify; 300 generated incl. tiny/huge B-spline and plane faces, tolerance edits and out-of-domain points), 1309 pass bit-identical (max_rel_err 0), 0 failed, 35 deferred (intersect.curve_class_p2 20: SmCurveClassification::ReSet, the first call of CurveOnClassify, whose body also needs curve_class_p5/p7/p9 and topology.face_p4 GetEdges; intersect.surface_drop_lib_p3 15: SmSurface::DropCurve in GetOrCreateUVTrimCurve of faces without trim curves); --perturb SENSITIVE. Not compared: PointClassify's SmTrimSrfCache branch (the shim deletes the cache a file read leaves; B-rep surfaces carry no object cache in the port) and faces with surfaces of revolution/extrusion/cones/spheres/tori (the shared export carries them as B-spline parts). Built on topology.loopuse (PR #102: loopuse::vertices). Wired: SmProtoVertex::ContainsPoint in ProtoTopologyManager::find_proto_vertex / which_pv_to_combine (topology.proto_topology_p1: 63 cases no longer deferred). Not wired, still UNPORTED(query.face_p2): surface::trim_srf_cache, intersect::ray_tracer, intersect::topology_solver p1 (callers hold object handles without a Brep) and the CurveOnClassify calls of topology::face::p2 / intersect::topology_solver p2 (behind UNPORTED(intersect.curve_class_p4)). CO-PORTED in intersect.curve_class_p5 (PR #150): CurveOnClassify vertex handle mapping -> CurveOnClassifyObjects::vertex and ClassGeometry callback bound; IntersectVertices now calls p5. Existing ReSet and classification stubs are retained. Merge of PR #65: ClassifyFaceInterval (p7) and IntersectVertices (p5) both wired; difftest then 1344 cases, 1271 passed, 0 failed, 73 deferred. [topology.edgeuse_p3 wired (PR #117): SmLoop::ContainsUVPoint takes &mut Brep and calls GetOrCreateUVTrimCurve, so the former topology.face_p2 (38) and topology.edgeuse_p3 (15) deferrals are gone: 1344 cases, 1309 pass, 0 failed, 35 deferred (intersect.curve_class_p2 20, intersect.surface_drop_lib_p3 15)]"