mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Reject self-intersecting polygons in polygon_covers_rect
Found while testing crates/geom/src/hit.rs:12-48 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
committed by
bflatastic
co-authored by
Claude Haiku 5.5
parent
157679c1a8
commit
bdd5470dcf
@@ -28,9 +28,11 @@ pub fn polygon_covers_rect(path: &BezPath, r: Rect, tol: f64) -> bool {
|
||||
// Convex: every turn goes the same way (straight runs allowed).
|
||||
let n = pts.len();
|
||||
let mut sign = 0.0f64;
|
||||
let mut turning = 0.0f64;
|
||||
for i in 0..n {
|
||||
let (a, b, c) = (pts[i], pts[(i + 1) % n], pts[(i + 2) % n]);
|
||||
let cross = (b - a).cross(c - b);
|
||||
turning += cross.atan2((b - a).dot(c - b));
|
||||
if cross.abs() <= 1e-9 {
|
||||
continue;
|
||||
}
|
||||
@@ -40,6 +42,10 @@ pub fn polygon_covers_rect(path: &BezPath, r: Rect, tol: f64) -> bool {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// A simple convex polygon turns through exactly one full revolution; a star winds more.
|
||||
if (turning.abs() - std::f64::consts::TAU).abs() > 1e-6 {
|
||||
return false;
|
||||
}
|
||||
let inner = r.inflate(-tol, -tol);
|
||||
sign != 0.0
|
||||
&& [Point::new(inner.x0, inner.y0), Point::new(inner.x1, inner.y0), Point::new(inner.x1, inner.y1), Point::new(inner.x0, inner.y1)]
|
||||
@@ -244,4 +250,20 @@ mod regress_tests {
|
||||
let worst = (0..=200).map(|i| distance_to_outline(&bp, c.eval(i as f64 / 200.0))).fold(0.0, f64::max);
|
||||
assert!(worst < 1e-6, "{worst}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn polygon_covers_rect_rejects_self_intersecting_star() {
|
||||
let mut b = BezPath::new();
|
||||
for k in 0..5 {
|
||||
let a = (-90.0 + 144.0 * k as f64).to_radians();
|
||||
let p = Point::new(100.0 * a.cos(), 100.0 * a.sin());
|
||||
if k == 0 {
|
||||
b.move_to(p);
|
||||
} else {
|
||||
b.line_to(p);
|
||||
}
|
||||
}
|
||||
b.close_path();
|
||||
assert!(!polygon_covers_rect(&b, Rect::new(-55.0, -20.0, 55.0, 78.0), 0.01));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user