mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-24 10:27:00 -06:00
Merge #1230: Honour even-odd fill rule when hit testing vectors (@Silvertree2010)
# Conflicts: # crates/doc/src/tests.rs
This commit is contained in:
@@ -72,7 +72,16 @@ fn hits_node_itself(doc: &Document, id: NodeId, n: &Node, pt: Point, tol: f64, o
|
||||
NodeKind::Frame | NodeKind::Component { .. } | NodeKind::ComponentSet { .. } | NodeKind::Instance { .. } | NodeKind::Section { .. } => {
|
||||
n.local_rect().inflate(tol_l, tol_l).contains(lp)
|
||||
}
|
||||
_ => shape_path(n).is_some_and(|path| hits_path(n, &path, lp, tol_l, !outline && is_closed(n) && path.winding(lp) != 0)),
|
||||
_ => shape_path(n).is_some_and(|path| hits_path(n, &path, lp, tol_l, !outline && is_closed(n) && fills_point(n, &path, lp))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the fill of `n`, drawn as `path`, covers `lp` (vectors follow the rule of
|
||||
/// [`VectorNetwork::fill_contains`](crate::VectorNetwork::fill_contains): even-odd when any region asks for it).
|
||||
fn fills_point(n: &Node, path: &BezPath, lp: Point) -> bool {
|
||||
match &n.kind {
|
||||
NodeKind::Vector { network } => network.fill_contains(lp),
|
||||
_ => path.winding(lp) != 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -499,3 +499,31 @@ fn stale_next_id_never_overwrites_existing_nodes() {
|
||||
assert_eq!(bad.node(p).unwrap().name, snapshot.node(p).unwrap().name);
|
||||
assert!(bad.validate().is_empty(), "{:?}", bad.validate());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hit_test_even_odd_vector_hole_misses() {
|
||||
let ring = |rule| {
|
||||
let sq = |o: f64, s: f64, base: usize| {
|
||||
(
|
||||
[(o, o), (o + s, o), (o + s, o + s), (o, o + s)].map(|(x, y)| Vertex::new(x, y)),
|
||||
[Segment::line(base, base + 1), Segment::line(base + 1, base + 2), Segment::line(base + 2, base + 3), Segment::line(base + 3, base)],
|
||||
)
|
||||
};
|
||||
let (v1, s1) = sq(0.0, 200.0, 0);
|
||||
let (v2, s2) = sq(60.0, 80.0, 4);
|
||||
VectorNetwork {
|
||||
vertices: v1.into_iter().chain(v2).collect(),
|
||||
segments: s1.into_iter().chain(s2).collect(),
|
||||
regions: vec![Region { loops: vec![vec![0, 1, 2, 3], vec![4, 5, 6, 7]], winding: rule }],
|
||||
}
|
||||
};
|
||||
let mut d = Document::new("x");
|
||||
let p = page(&d);
|
||||
let eo = d.create(p, NodeKind::Vector { network: ring(WindingRule::EvenOdd) }, "V", 0.0, 0.0, 200.0, 200.0).unwrap();
|
||||
assert_eq!(d.hit_test(p, Point::new(20.0, 100.0), 0.0, None), Some(eo));
|
||||
assert_eq!(d.hit_test(p, Point::new(100.0, 100.0), 0.0, None), None, "the hole is not filled");
|
||||
let mut d = Document::new("x");
|
||||
let p = page(&d);
|
||||
let nz = d.create(p, NodeKind::Vector { network: ring(WindingRule::NonZero) }, "V", 0.0, 0.0, 200.0, 200.0).unwrap();
|
||||
assert_eq!(d.hit_test(p, Point::new(100.0, 100.0), 0.0, None), Some(nz));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user