Sketch: a sketch's bounds reach its circles' and arcs' extremes

Sketch::bounds took the points of each segment's polyline. Since 09c979a4b a whole circle is
one closed arc whose chords start at its start angle, so none lands on the circle's left or
bottom: a radius 5 circle at (-300, 0) spanned x from -304.50, and Home and Fit framed short
of it (home_and_fit_frame_the_moved_body_not_its_old_place). An arc's bounds now add the
quarter points of its circle it sweeps through, which are exact.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jyviko
2026-10-28 22:27:39 -04:00
committed by Irakli Kourtis
parent e657e40867
commit 6a6cd8f56c
2 changed files with 38 additions and 2 deletions
+22 -2
View File
@@ -1716,9 +1716,29 @@ impl Sketch {
}
}
/// Axis-aligned bounds of all geometry (for views).
/// Axis-aligned bounds of all geometry (for views). An arc's are exact: its polyline's points
/// need not reach the circle's extremes (a whole circle is one arc, whose chords start at its
/// start angle), so the quarter points it sweeps through are added.
pub fn bounds(&self) -> Option<(Vec2, Vec2)> {
let b: Aabb2 = (0..self.curves.len()).flat_map(|i| self.segs(i)).flat_map(|s| s.polyline(0.5)).collect();
let extremes = |s: &Seg2| -> Vec<Vec2> {
let Seg2::Arc { center, radius, start, sweep } = *s else { return Vec::new() };
let (lo, hi) = if sweep >= 0.0 { (start, start + sweep) } else { (start + sweep, start) };
let quarter = std::f64::consts::FRAC_PI_2;
let first = (lo / quarter).ceil() as i64;
let last = (hi / quarter).floor() as i64;
if !(lo.is_finite() && hi.is_finite()) || last - first > 4 {
return Vec::new();
}
(first..=last).map(|k| center + Vec2::from_angle(k as f64 * quarter) * radius).collect()
};
let b: Aabb2 = (0..self.curves.len())
.flat_map(|i| self.segs(i))
.flat_map(|s| {
let mut pts = s.polyline(0.5);
pts.extend(extremes(&s));
pts
})
.collect();
(!b.is_empty()).then_some((b.min, b.max))
}
}
+16
View File
@@ -1279,3 +1279,19 @@ fn a_fillet_folded_through_flat_is_refused_like_a_fold() {
}
assert!(refused.is_some_and(|s| (7..=9).contains(&s)), "refused at {refused:?}");
}
/// A sketch's bounds reach a circle's and an arc's extremes, not only the points of their
/// polylines: a whole circle is one arc whose chords start at its start angle, and a circle of
/// radius 5 at (-300, 0) spans x from -305 exactly.
#[test]
fn bounds_reach_the_extremes_of_circles_and_arcs() {
let mut sk = Sketch::new();
sk.add_circle(v(-300.0, 0.0), 5.0, None, None).unwrap();
let (lo, hi) = sk.bounds().unwrap();
assert!(lo.dist(v(-305.0, -5.0)) < 1e-9 && hi.dist(v(-295.0, 5.0)) < 1e-9, "{lo:?} {hi:?}");
// A quarter arc from (10, 0) to (0, 10) about the origin: its corners, no more.
let mut sk = Sketch::new();
sk.add_arc(v(0.0, 0.0), v(10.0, 0.0), v(0.0, 10.0), [None; 3], None).unwrap();
let (lo, hi) = sk.bounds().unwrap();
assert!(lo.dist(v(0.0, 0.0)) < 1e-9 && hi.dist(v(10.0, 10.0)) < 1e-9, "{lo:?} {hi:?}");
}