BSplineSurface stores its NURB in a NurbSlot (a OnceLock) that read-only
queries can fill once from &self, as upstream's GetOrCreateGwNurbPointer
keeps a NURB made through a const_cast. Plane::base_with_nurb and
SurfOfExtrusion::base_with_nurb now make a missing NURB and keep it, so
IntersectWithPlane's has-NURB test, ToggleSwapUVBit, operator== and copies
see it. Plane::copy makes the source's NURB first and the source keeps it,
as the SmBSplineSurface copy constructor. Surface::kind_with_nurb fills the
extrusion's slot instead of the side memo; cone, sphere, torus and
revolution keep the whole-kind memo (their MakeNurb also rebuilds the polar
converter).
surface.plane_p1 drops its workarounds: the shim asks const queries of the
plane itself instead of a side-free copy, the state records whether the
plane holds its NURB, and ToggleSwapUVBit / operator== are generated
anywhere in a program.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SdcgEtgaA54W2nr8dK1EYp
Guard common and handwritten entrypoints through native cleanup and callback restoration. Add exclusion, recursive forwarding and exception-unwind probes; p2 adds its concurrent cross-wrapper regression with the port.
Co-Authored-By: GPT-6.1-Sol <noreply@openai.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
Shim: Reverse/Rebuild report SM_ERR when no NURB can be made (upstream
dereferences NULL); side_free_copy keeps a degenerate placement exactly.
ffi: reject |n|^2 < 1e-24 normals (uninitialised axes upstream) and
non-positive extension distances (endless loop upstream). New Extend op
(both CreateExtendedSurface overloads), generated and in extend.json; the
reviewer's adversarial cases in zz_adv.json minus the zero normal and the
lazy-NURB sequences.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V8ohWGLCzFPoZriCeSSero
Plane kind of Surface with constructors, evaluation, projection, MakeNurb,
DropPointFast, GlobalLineIntersect, TrimPlaneLineToPlaneDomain,
CreateIsoParametricCurve, DropCurve, CoincidenceCheck, Reparameterize,
ToggleSwapUVBit, RebuildSTEPFromNURBParameters and the re-dispatched
SmBSplineSurface methods; C++ shim, ffi binding, difftest runner and
fixtures. Wires the UNPORTED(surface.plane_p1) stubs in
nurbs.b_spline_surface_p1/p2.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V8ohWGLCzFPoZriCeSSero