From d7790f895eb7b31afd7358abf75bb7e90911f13c Mon Sep 17 00:00:00 2001 From: amosblomqvist Date: Mon, 14 Sep 2026 07:56:01 +0300 Subject: [PATCH] =?UTF-8?q?Plan-graph=20round=2013=20(owner):=20arrowheads?= =?UTF-8?q?=20point=20again=20=E2=80=94=20no=20zero-length=20final=20segme?= =?UTF-8?q?nt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round-12 regression: manually repeating the mouth point as a control point made d3 emit a degenerate final path command (a zero-length L). orient="auto" derives the marker angle from the direction of the LAST path segment; a zero-length segment has none, so every head fell back to 0° — pointing right. Fix: drop the manual repeat — curveBasis already repeats the endpoint internally, so controls ending [Q, M] keep the exact end tangent (the approach direction) AND a real final segment (the straight Q→M stub). Left a comment in edgePathD so this never regresses again. --- components/plan-block.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/components/plan-block.tsx b/components/plan-block.tsx index 014b3e3..5b3f469 100644 --- a/components/plan-block.tsx +++ b/components/plan-block.tsx @@ -248,13 +248,16 @@ export function edgePathD(points: Array<{ x: number; y: number }>): string { // The mouth: tip overhang + the docking gap back from the border. const back = HEAD_TIP_OVERHANG + DOCK_GAP; const M = { x: last.x - ux * back, y: last.y - uy * back }; - // From Q every control point lies on the approach line — the basis + // From Q the control points lie on the approach line — the basis // spline renders Q→M perfectly straight (a B-spline span with - // collinear control points IS the line), and the repeated M makes - // the end tangent exactly the approach direction, so the head - // squares onto its shaft. + // collinear control points IS the line), and curveBasis's internal + // endpoint repetition makes the end tangent exactly the approach + // direction. NOTE: do NOT repeat M manually — a duplicated final + // control point renders a zero-length last segment, and + // orient="auto" on a zero-length segment falls back to 0° (every + // head pointing right — the round-12 regression, fixed round 13). const Q = { x: M.x - ux * STRAIGHT_RUN, y: M.y - uy * STRAIGHT_RUN }; - pts.splice(pts.length - 1, 1, Q, M, M); + pts.splice(pts.length - 1, 1, Q, M); } return edgeLine(pts) ?? ""; }