mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-09 03:51:42 +00:00
Geometry: measurement allows a capped arc's control points past the cap
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
5f89b05b74
commit
a6e7920b24
2 files changed
+25
-6
No files matched your search
@@ -8,11 +8,16 @@ pub const FLATTEN_TOL: f64 = 0.05;
|
||||
/// The most flattened points a path is measured with; longer paths are refused.
|
||||
pub const MAX_SAMPLES: usize = 40_000;
|
||||
|
||||
/// Every coordinate is finite and of a sane magnitude: within [`crate::MAX_COORD`], the cap the
|
||||
/// shape builders hold their sizes, radii and angles to (inclusive, so a path built at the cap
|
||||
/// still measures).
|
||||
/// How far out a measured coordinate may lie. The shape builders hold their sizes, radii and
|
||||
/// angles to [`crate::MAX_COORD`], so a path built at the cap has its points there and the
|
||||
/// control points of its curves a little past them (the cubics approximating an arc reach past
|
||||
/// the arc's box by up to about a tenth of the radius). Half as much again keeps every built path
|
||||
/// measurable and still refuses the absurd.
|
||||
pub const MAX_MEASURED_COORD: f64 = crate::MAX_COORD * 1.5;
|
||||
|
||||
/// Every coordinate is finite and of a sane magnitude (within [`MAX_MEASURED_COORD`]).
|
||||
pub fn finite_path(path: &BezPath) -> bool {
|
||||
let ok = |p: &Point| p.x.is_finite() && p.y.is_finite() && p.x.abs() <= crate::MAX_COORD && p.y.abs() <= crate::MAX_COORD;
|
||||
let ok = |p: &Point| p.x.is_finite() && p.y.is_finite() && p.x.abs() <= MAX_MEASURED_COORD && p.y.abs() <= MAX_MEASURED_COORD;
|
||||
path.elements().iter().all(|el| match el {
|
||||
PathEl::MoveTo(p) | PathEl::LineTo(p) => ok(p),
|
||||
PathEl::QuadTo(a, b) => ok(a) && ok(b),
|
||||
|
||||
@@ -68,11 +68,25 @@ fn paths_at_the_cap_still_measure() {
|
||||
line.move_to(Point::new(-MAX_COORD, 0.0));
|
||||
line.line_to(Point::new(MAX_COORD, -MAX_COORD));
|
||||
assert!(polylines(&line).is_some(), "a line between the cap's corners measures");
|
||||
// A curve at the cap: the cubics approximating the arc have control points past the cap, and
|
||||
// the path still measures.
|
||||
let arc = ellipse(MAX_COORD, 1.0, -0.15, 0.2, 0.0);
|
||||
let reach = arc
|
||||
.elements()
|
||||
.iter()
|
||||
.flat_map(|el| match el {
|
||||
kurbo::PathEl::CurveTo(a, b, _) => vec![a.x, b.x],
|
||||
_ => vec![],
|
||||
})
|
||||
.fold(0.0, f64::max);
|
||||
assert!(reach > MAX_COORD, "a control point lies past the cap: {reach}");
|
||||
assert!(finite_path(&arc));
|
||||
assert!(polylines(&arc).is_some(), "an arc at the cap measures");
|
||||
let mut past = BezPath::new();
|
||||
past.move_to(Point::new(0.0, 0.0));
|
||||
past.line_to(Point::new(MAX_COORD + 1.0, 0.0));
|
||||
past.line_to(Point::new(2.0 * MAX_COORD, 0.0));
|
||||
assert!(!finite_path(&past));
|
||||
assert!(polylines(&past).is_none(), "a coordinate past the cap is refused");
|
||||
assert!(polylines(&past).is_none(), "a coordinate well past the cap is refused");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user