The surface.surface_p2 runner gets a revolution record constructor: each side
builds a canonical torus or cone, writes it to an ASCII database record, clears
the planar generator flag in the record when asked and reads it back with
SmSurface::ReadFromDB. The shim writes with fixed precision 16, the format
SmDatabaseIOFile::OpenFileForWrite sets for ASCII files (a caller's stream keeps
its 6-digit default). 768 STEPInversion cases run through SmSurface* on tori,
cones and an apex cone: interior, seam, pole and guessed points, points off the
surface and far away, over the STEP domain and a sub-domain.
The sub-domain cases exposed a cone bug: Surface::step_inversion passed the
caller's domain to the cone, but SmCone::STEPInversion ignores crAnalDomain and
inverts over its own m_vAnalUVDomain. Only the non-planar branch reads the
domain, so a point outside the caller's sub-domain failed in Rust and succeeded
in C++. The cone now always uses its own STEP domain.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SdcgEtgaA54W2nr8dK1EYp
Upstream's own advanced surface/surface intersection regression
(prog_test smAdvancedTest.cpp my_test_ssi_adv -> my_test_one_ssi ->
smTopoTest.cpp my_test_ssi) was never replicated: no fixture loaded its
pt_TestFiles/ssi_*.smp part files. harness/fixturegen/ssi_adv.py turns
every (face of B-rep 0, face of B-rep 1) pair into a `gssi` case on the
face surfaces (all SmBSplineSurface) over their stored UV domains, with
the test's translation and SmApproxTol3d 1e-3.
The gssi op now compares what GlobalSurfaceIntersect returns rather than
only the curve count: every 3D and UV curve (type, full NURB), the curve
types and the deviations. It takes the optional `tol` and `translate`
(both surfaces Transform'ed first, as the test moves both B-reps), passes
all output arrays as my_test_ssi does, and on failure records only the
status on both sides. MAX_INDEX rises to 128 for the bumpy-plane nets
(82 control points per direction).
Eight part files are left out (PENDING_PR140 in the generator): their
tangent/singular start points need the SmAdvSurfaceIntersector
ComputeSingularityPoint dispatch that PR #140 adds; on #140's head all
56 pairs pass or defer. See plan/findings.md.
PARTIAL surface.surface_p2 cases=917 passed=896 failed=0 deferred=21 max_rel_err=0e0
SENSITIVE surface.surface_p2 perturbed=896 detected=896
--fuzz 300 (gssi): FUZZ-PASS, 0 crashes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
125 shims carried private copies of the same small helpers (put_vec, st,
nl_status, Rd, dump_crv, read_nurb, ...). Move the most common, byte-identical
form of each into three headers grouped by the upstream API they need, and have
those shims pull them in with `using sc::<name>;`. Shims with a different
variant keep their own copy; files touched by open PRs are left alone.
`the_context()` stays per shim (its function-local SmContext must not be shared).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBLgPenT24P1dunqnZR1Dj