Repository navigation
fix: a failed end tangent reads SmVector3d's UNDEF default, as upstream (#521) - #704
Conversation
…am (tangency-labs#521) At c9c5979 SmVector3d defaults to SM_UNDEF_DOUBLE, so the tangent a failed GetEndTangent leaves in SmVertex::AreEdgesTangent / IsTopologicalVertex is defined: AngleBetween reports 0 and both answer TRUE. The port returned InvalidInput there and the topology.vertex shim refused the input. Read Vec3::UNDEF instead, refuse only a null curve in the shim, and record WR-255 (correcting UB-106) plus the per-site tangency-labs#521 audit in findings. 70 compared cases in fixtures/topology.vertex/end_tangents.json (zero end tangents, 1e-30 end spans) and a unit test on a composite-curve edge, whose evaluation always fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o fix/521-vertex-undef-tangent
…on main) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o fix/521-vertex-undef-tangent
|
Update after #704 landed: #700 is being narrowed to the remaining topology/healing failure paths, while retaining #704’s tangent behavior, tests and fixture coverage. Correction to my earlier comment: #700’s 20 constant-segment fixtures exercise failed angle calculations / zero tangents. They do not establish failed The remaining follow-up covers failed edge reversal, UV corner/loop-gap/deviation evaluations and healing classification/retry state. Its updated native comparisons and explicit known records will be published after revalidation. |
Keep tangency-labs#704 implementation and coverage. Remove only proven obsolete vertex exceptions; retain six remaining failure/retry regressions and four explicit healing differences. Co-Authored-By: Codex <noreply@openai.com>
Keep tangency-labs#704 implementation and coverage. Remove only proven obsolete vertex exceptions; retain six remaining failure/retry regressions and four explicit healing differences. Co-Authored-By: Codex <noreply@openai.com>
Keep tangency-labs#704 implementation and coverage. Remove only proven obsolete vertex exceptions; retain six remaining failure/retry regressions and four explicit healing differences. Co-Authored-By: Codex <noreply@openai.com>
Keep tangency-labs#704 implementation and coverage. Remove only proven obsolete vertex exceptions; retain six remaining failure/retry regressions and four explicit healing differences. Co-Authored-By: Codex <noreply@openai.com>
Fixes #521. Standalone on main (no other PR stacked).
I checked every site #521 lists against the port at
c9c5979. The issue was written from the fork. Atc9c5979none of these sites reads uninitialised memory:SmVector3d,SmPoint3dandSmPoint2ddefault toSM_UNDEF_DOUBLE(SmVector3d.h:56-58).SmExtent1ddefaults to an empty interval.AngleBetweenwrites0before it can fail.The port matches upstream at every site but one:
SmVertex::AreEdgesTangent/IsTopologicalVertex. This PR fixes that site and records the others.Fixed:
AreEdgesTangent/IsTopologicalVertexafter a failedGetEndTangent(WR-256)Upstream. The ignored failure leaves the caller's tangent as it was. That is the
SmVector3ddefault, or inIsTopologicalVertexthe line vectorIsLinewrote.AngleBetweensees a zero-length vector and reports0, so both functions answerTRUE. UB-106 had called that tangent uninitialised; a correction line now points it to WR-256. Only the curveless edge is really UB.What changes:
topology::vertexreturnedInvalidInputhere. It now readsVec3::UNDEF, as upstream does.topology_vertexshim guard (ok_tangent,ok_topological) also refused these inputs, and calledGetEndTangentto decide. It now refuses only the real crash: a null curve whose tangent upstream would read.Reachability. No input the
topology.vertexharness can build makesGetEndTangentfail, so no existing case changes value:SmBSplineCurve::Evaluateclamps the parameter.N_BasisFindSpanskips end spans shorter than1e-12, sosm_BasisDerivsnever sees the tiny knot difference it rejects.An
SmCompositeCurveedge always gets there: that class keepsSmCurve::Evaluate, which returnsSM_ERR. The new unit testfailed_end_tangent_reads_the_default_vectorbuilds that case.New fixtures.
fixtures/topology.vertex/end_tangents.jsonadds 70 compared cases around this path:AngleBetweenfailure1e-30end spans with matching parameters, which exercise the end-span skipTo be clear: these cases agree with or without the port change. They pin the neighbouring behaviour; the unit test is what covers the changed lines.
Recorded, no code change (
plan/findings.md, "#521 audit")SmLoop::GetUVCornerBoundaries: "keeps the previous edgeuse's curve" doesn't hold atc9c5979.GetOrCreateUVTrimCurvesets its out-pointer before it builds (SmEdgeuse.cpp:4275), so a failed build leaves NULL and the drop-point branch runs. Stale UV ends after a failedEvaluatePoint/DropPointare ported as they are.SmEdge::ReverseOrientation: the default interval after a failedReverseParameterizationis already ported and documented.SmLoop::ContainsUVPoint: the four ignored evaluations read UNDEF points or the previous step's derivatives. The port returns their error (its documented deviation, reached only by a failing surface evaluation, a NaN parameter or a degenerate span). The doc wording there said "uninitialised"; this PR corrects it.GetStartPointUVLoopGapis faithful.GetEndPointUVLoopGapandHasDogLegNearPoleare unreachable and not ported.sm_CalcDistAndDev: faithful, with one open difference noted for a follow-up. The port propagates anevaluate_normalerror that upstream ignores. That matters only for a zero-radius sphere or aSrfInVolumewhose evaluation fails.SmFaceProps::SetProps_Stage3: no unset reads. A failed Stage 3 leaves the stage at3a, which the port copies.The fork's status propagation isn't ported. As with #465 and #468, the port keeps
c9c5979's results because difftest compares against them.Preserved invariants
No tolerance loosened, no case dropped, generators unchanged. The guard change only lets through inputs the C++ handles without UB.
topology.vertexstays green.Difftest
Verified on head
fb0aec152(x86-64):cargo fmt --all --check(+ rustfmt on the touched FFI unit file), clippy-D warnings(plain and--features difftest/cpp),cargo test -p solidcore(2080 passed), the difftest runner tests, the wasm32 check,harness/plan/units.py check, and a cleangit merge-treeagainst main.--green --jobs 4above.Since then: merged main (no conflicts locally; #703 took WR-255, so this PR's entry is now WR-256, renumbered in its own commit). Re-checked on
f3df18881: fmt,units.py check, clippy, the vertex unit tests andtopology.vertex5578/5578.🤖 Generated with Claude Code