mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-08 21:10:40 +00:00
Envelopes: document how a straight segment's handles count in the top object corner test
A top object's corner test treats a straight segment as having its handles a third of the way along it, so an anchor between two straight segments is a corner only when it turns out of the outline. docs/mcp.md and the doc comment now say so, and a new test covers an inward anchor between straight segments. The bulging-curve corner test checks against a fixed point instead of the same nearest-point routine the code uses.
This commit is contained in:
+14
-5
@@ -262,18 +262,17 @@ mod tests {
|
||||
fn a_top_object_corner_inside_a_bulging_curve_is_the_nearest_outline_point() {
|
||||
// The top left anchor's handle bulges out past the corner, so the anchor turns inward
|
||||
// there and the corner falls inside the curve.
|
||||
let top = CubicBez::new((0.0, 0.0), (-50.0, -50.0), (150.0, 0.0), (200.0, 0.0));
|
||||
// The outline's bounding box starts at (-7.957, -22.222); the top curve's point nearest
|
||||
// that corner, found by sampling the curve 2,000,000 times, is (-5.072093, -18.127254).
|
||||
let path = outline(&[
|
||||
((0.0, 0.0), (0.0, 0.0), (-50.0, -50.0)),
|
||||
((200.0, 0.0), (150.0, 0.0), (200.0, 0.0)),
|
||||
((200.0, 100.0), (200.0, 100.0), (200.0, 100.0)),
|
||||
((0.0, 100.0), (0.0, 100.0), (0.0, 100.0)),
|
||||
]);
|
||||
use vectorcraft_geom::kurbo::ParamCurveNearest;
|
||||
let b = path.subpaths[0].segment(3).bounding_box().union(top.bounding_box());
|
||||
let want = top.eval(top.nearest(Point::new(b.x0, b.y0), 1e-12).t);
|
||||
let want = Point::new(-5.072093, -18.127254);
|
||||
let tl = Coons::from_top_object(&path, None).unwrap().corners()[0];
|
||||
assert!(tl.distance(want) < 1e-6, "{tl:?}, want {want:?}");
|
||||
assert!(tl.distance(want) < 1e-5, "{tl:?}, want {want:?}");
|
||||
assert!(tl.distance(Point::ZERO) > 1.0, "{tl:?}");
|
||||
}
|
||||
|
||||
@@ -316,6 +315,16 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_top_object_corner_skips_an_inward_anchor_between_straight_segments() {
|
||||
// A 200 × 100 outline of straight segments with a notch at its top left: (40,40) is the
|
||||
// anchor nearest the box corner, but it turns into the outline, so (60,0) is the corner.
|
||||
let c = |p: (f64, f64)| (p, p, p);
|
||||
let path = outline(&[c((60.0, 0.0)), c((200.0, 0.0)), c((200.0, 100.0)), c((0.0, 100.0)), c((0.0, 60.0)), c((40.0, 40.0))]);
|
||||
let tl = Coons::from_top_object(&path, None).unwrap().corners()[0];
|
||||
assert!(tl.distance(Point::new(60.0, 0.0)) < 1e-9, "{tl:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_top_object_corner_tie_goes_to_the_first_anchor() {
|
||||
// Both chamfer anchors lie 30 from the box corner: the first one along the outline, in
|
||||
|
||||
@@ -354,7 +354,10 @@ const CORNER_END_SNAP: f64 = 0.005;
|
||||
/// Is the anchor at `a`, reached by handle `h_in` and left by handle `h_out` on an outline that
|
||||
/// runs clockwise on screen, a corner of a top object? A handle of [`SHORT_HANDLE`] or shorter
|
||||
/// makes it one. Otherwise its tangent directions must differ by [`SMOOTH_TURN`] or more and turn
|
||||
/// clockwise, so it points out of the outline.
|
||||
/// clockwise, so it points out of the outline. A straight segment's handles here are the ones
|
||||
/// [`Coons::from_top_object`] gives it, a third of the way along, so an anchor between two
|
||||
/// straight segments longer than three times [`SHORT_HANDLE`] is a corner only when it turns out
|
||||
/// of the outline.
|
||||
fn top_object_corner_anchor(h_in: Point, a: Point, h_out: Point) -> bool {
|
||||
let (vin, vout) = (a - h_in, h_out - a);
|
||||
let (len_in, len_out) = (vin.hypot(), vout.hypot());
|
||||
|
||||
+3
-1
@@ -6619,7 +6619,9 @@ arcLower, arcUpper, arch, bulge, shellLower, shellUpper, flag, wave, fish, rise,
|
||||
A top object's outline is split into four sides at four corners. Each corner is the anchor nearest a corner of the
|
||||
outline's bounding box among the anchors within 47.5% of the box's width and height from that box corner that count as
|
||||
corners: an anchor with a handle 0.01 pt long or shorter, or one whose tangent unit vectors differ by 0.01 or more in
|
||||
x or y and turn out of the outline. On a tie, the anchor met first along the outline in the order it was drawn wins.
|
||||
x or y and turn out of the outline. In this test a straight segment counts as having its handles a third of the way
|
||||
along it, so an anchor between two straight segments longer than 0.03 pt is a corner only when it turns out of the
|
||||
outline. On a tie, the anchor met first along the outline in the order it was drawn wins.
|
||||
Without such an anchor, the corner is the outline's point nearest the box corner, moved onto the anchor at the end of
|
||||
its segment when within 0.5% of the segment's parameter. Each piece of a side between anchors and corners takes a
|
||||
share of the content's width or height in proportion to the length of its control polygon, spread along the piece by
|
||||
|
||||
Reference in New Issue
Block a user