New shim ops (surface.cone_p2 OP_RECOGNIZE_CYLINDER, surface.torus
OP_IS_NURB) and fixture-only runner ops: 77 cylinder cases (the issue's
r 5 about +Z, partial/full turns, both UV orders, scaled, tiny, cones,
tapers, twists) and 126 torus cases (the issue's R 10 r 3, partial
domains below the equator and past 180, scaled, tiny, horn/spindle,
perturbed and anisotropically scaled NURBS), flags off. WR-493 records the
fork's 7ea6a96; a WR-408 addendum covers IsNurbSurfaceTorus.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SdcgEtgaA54W2nr8dK1EYp
Build each kind without MakeNurb in the shim and in Rust, run the const natural-domain
query that makes the NURB lazily, then point/normal evaluations at the domain corners,
Copy, == and Transform, comparing has-NURB, the NURB data and evaluations. Cases cover
swap/inside-out, partial domains, sphere caps ending at a pole, a torus with minor radius
equal to and above the major radius, and revolutions about an axis touched or crossed by
the generator.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SdcgEtgaA54W2nr8dK1EYp
SmTorus inherits SmSurfOfRevolution::IntersectWithPlane, whose sweep iso
circles (a plane normal to the axis) come from the virtual
CreateIsoParametricCurve. intersect_with_plane_owned_using takes that hook;
Torus::intersect_with_plane passes the torus's iso circles.
SurfaceKind::Torus dispatches IntersectWithPlane to it, and its
GlobalSurfaceIntersect takes the plane special case (the plane's face
tolerance for its box), then the general intersection when it needs more.
surface.torus difftests IntersectWithPlane and GlobalSurfaceIntersect with
planes through, normal to and oblique to the axis.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H9QwJFBTKLZ9FFK3nVd1X4
SmSphere and SmTorus inherit SmSurfOfRevolution::TrimWithDomain; its
virtual ConvertUVFromNURBSToSTEP (UpdateAnalyticalDomain) and
CreateIsoParametricCurve (MakeNurb, Reparameterize, RebuildPolarConverter)
now reach the sphere/torus overrides through trim_with_domain_using, and
SurfaceKind::Sphere/Torus dispatch to it instead of a dispatch gap.
surface.sphere and surface.torus difftest a TrimDomain op.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H9QwJFBTKLZ9FFK3nVd1X4
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
Torus construction (CreateCanonical/MakeNurb), operator==, Copy, offset,
STEP/NURB conversions, STEP evaluation, iso circles,
RebuildSTEPFromNURBParameters, Transform and ReadFromDB (the last two end
in the unported SmSurfOfRevolution part). SurfOfRevolution's NURB and
polar-converter rebuilds take the iso-curve maker so the torus override is
used, as upstream's virtual call. Surface::read_from_db reads the torus
record before the unported base record.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>