From 5589049a47002db4cc86b7a4309181cc827f4a97 Mon Sep 17 00:00:00 2001 From: adambelis Date: Sun, 8 Nov 2026 21:57:19 +0100 Subject: [PATCH] M2.1: blend Align-to-Path smooth on curved spines Spine::at_length computed tangents from flattened polyline chords, which are piecewise constant and jump discretely between chords on curved spines. Steps oriented to the spine with Align to Path stuttered at large step counts. Fix: store the original PathData in Spine and compute the tangent from the original cubic at the true arc-length position via ParamCurveDeriv, proportionally mapping flattened arc-length s onto each segment's curve arclength using anchor_length values, instead of using piecewise-constant chord directions. Reviewed-by: craft-house-rules Co-authored-by: Craft Bot --- crates/doc/src/blend.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/doc/src/blend.rs b/crates/doc/src/blend.rs index 850d5cc6d..0af701405 100644 --- a/crates/doc/src/blend.rs +++ b/crates/doc/src/blend.rs @@ -1014,17 +1014,20 @@ impl Spine { let mut start = 0.0; for i in 0..n { let c = sp.segment(i); - let len = c.arclen(1e-9); - if s <= start + len || i + 1 == n { - let t = c.inv_arclen((s - start).max(0.0), 1e-9).clamp(1e-9, 1.0 - 1e-9); + let end = self.anchor_length(i + 1).unwrap_or(self.length()); + if s <= end || i + 1 == n { + let local_s = (s - start).max(0.0) / (end - start).max(1e-12) * c.arclen(1e-9); + let t = c.inv_arclen(local_s, 1e-9).clamp(1e-9, 1.0 - 1e-9); let e = c.eval(t); let tv = c.deriv().eval(t); return (Point::new(e.x, e.y), tv.y.atan2(tv.x)); } - start += len; + start = end; } let c = sp.segment(n - 1); - let t = c.inv_arclen(c.arclen(1e-9), 1e-9).clamp(1e-9, 1.0 - 1e-9); + let end = self.length(); + let local_s = (s - start).max(0.0) / (end - start).max(1e-12) * c.arclen(1e-9); + let t = c.inv_arclen(local_s, 1e-9).clamp(1e-9, 1.0 - 1e-9); let e = c.eval(t); let tv = c.deriv().eval(t); (Point::new(e.x, e.y), tv.y.atan2(tv.x))