mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 10:35:58 +00:00
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:
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:?}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user