diff --git a/crates/geom/src/corners.rs b/crates/geom/src/corners.rs index fe64d9e64..6fe68e576 100644 --- a/crates/geom/src/corners.rs +++ b/crates/geom/src/corners.rs @@ -39,7 +39,11 @@ impl Side { /// The side's length. fn length(&self) -> f64 { - if self.straight() { self.curve.p0.distance(self.curve.p3) } else { crate::path::measured_arclen(&kurbo::PathSeg::Cubic(self.curve), ARCLEN_ACCURACY) } + if self.straight() { + self.curve.p0.distance(self.curve.p3) + } else { + crate::path::measured_arclen(&kurbo::PathSeg::Cubic(self.curve), ARCLEN_ACCURACY) + } } /// The parameter `s` along the side from the corner, the point there and the direction the diff --git a/crates/tools/src/distort/liquify.rs b/crates/tools/src/distort/liquify.rs index de40eef35..1e917ffc4 100644 --- a/crates/tools/src/distort/liquify.rs +++ b/crates/tools/src/distort/liquify.rs @@ -388,7 +388,8 @@ fn subdivide(sp: &mut SubPath, prm: &LiquifyParams, c: Point, spacing: f64) { continue; } let len = cub.arclen(1e-3); - let k = (len / spacing).ceil() as usize; + // (No more pieces than the anchors left under the ceiling.) + let k = ((len / spacing).ceil() as usize).min(MAX_ANCHORS.saturating_sub(sp.anchors.len()) + 1); if k <= 1 { seg += 1; continue; diff --git a/crates/tools/src/distort/perspective.rs b/crates/tools/src/distort/perspective.rs index 4f172760b..3d3042d6d 100644 --- a/crates/tools/src/distort/perspective.rs +++ b/crates/tools/src/distort/perspective.rs @@ -549,6 +549,11 @@ impl PerspectiveGrid { let Some(h) = self.homography(plane) else { return vec![] }; let d = self.domain(plane); let mut out = vec![]; + // A stored grid is not checked: no spacing, or an extent that isn't a number, has no lines. + let (w, h_len) = (d.width(), d.height()); + if !(self.cell.is_finite() && self.cell > 0.0 && w.is_finite() && h_len.is_finite()) { + return out; + } let step = |len: f64| { let mut s = self.cell; while len / s > 120.0 { @@ -556,20 +561,19 @@ impl PerspectiveGrid { } s }; - let (su, sv) = (step(d.width()), step(d.height())); - let mut u = 0.0; - while u <= d.width() + 1e-9 { - if let (Some(a), Some(b)) = (h.apply(Point::new(u, 0.0)), h.apply(Point::new(u, d.height()))) { + let (su, sv) = (step(w), step(h_len)); + // Counted, not summed: a count in whole lines (at most 121 a way). + for i in 0..=((w + 1e-9) / su).floor() as usize { + let u = i as f64 * su; + if let (Some(a), Some(b)) = (h.apply(Point::new(u, 0.0)), h.apply(Point::new(u, h_len))) { out.push((a, b)); } - u += su; } - let mut v = 0.0; - while v <= d.height() + 1e-9 { - if let (Some(a), Some(b)) = (h.apply(Point::new(0.0, v)), h.apply(Point::new(d.width(), v))) { + for i in 0..=((h_len + 1e-9) / sv).floor() as usize { + let v = i as f64 * sv; + if let (Some(a), Some(b)) = (h.apply(Point::new(0.0, v)), h.apply(Point::new(w, v))) { out.push((a, b)); } - v += sv; } out }