Skip to content

Commit a70c48f

Browse files
authored
Use lyon_geom for intersection calculation of bezier segments (#3071)
* Add lyon_geom for cubic cubic intersections in he path bool crate * Remove cubic line intersection for now
1 parent e70862b commit a70c48f

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libraries/path-bool/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ default = ["parsing"]
2727
glam = "0.29.0"
2828
regex = "1.10.6"
2929
slotmap = "1.0.7"
30+
lyon_geom = "1.0"
3031

3132
[dev-dependencies]
3233
glob = "0.3"

libraries/path-bool/src/path/intersection_path_segment.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ use crate::line_segment_aabb::line_segment_aabb_intersect;
55
use crate::math::lerp;
66
use crate::path_segment::PathSegment;
77
use glam::DVec2;
8+
use lyon_geom::{CubicBezierSegment, Point};
9+
10+
/// Convert PathSegment::Cubic to lyon_geom::CubicBezierSegment
11+
fn path_segment_cubic_to_lyon(start: DVec2, ctrl1: DVec2, ctrl2: DVec2, end: DVec2) -> CubicBezierSegment<f64> {
12+
CubicBezierSegment {
13+
from: Point::new(start.x, start.y),
14+
ctrl1: Point::new(ctrl1.x, ctrl1.y),
15+
ctrl2: Point::new(ctrl2.x, ctrl2.y),
16+
to: Point::new(end.x, end.y),
17+
}
18+
}
819

920
#[derive(Clone)]
1021
struct IntersectionSegment {
@@ -87,13 +98,24 @@ pub fn segments_equal(seg0: &PathSegment, seg1: &PathSegment, point_epsilon: f64
8798
}
8899

89100
pub fn path_segment_intersection(seg0: &PathSegment, seg1: &PathSegment, endpoints: bool, eps: &Epsilons) -> Vec<[f64; 2]> {
90-
if let (PathSegment::Line(start0, end0), PathSegment::Line(start1, end1)) = (seg0, seg1) {
91-
if let Some(st) = line_segment_intersection([*start0, *end0], [*start1, *end1], eps.param) {
92-
if !endpoints && (st.0 < eps.param || st.0 > 1. - eps.param) && (st.1 < eps.param || st.1 > 1. - eps.param) {
93-
return vec![];
101+
match (seg0, seg1) {
102+
(PathSegment::Line(start0, end0), PathSegment::Line(start1, end1)) => {
103+
if let Some(st) = line_segment_intersection([*start0, *end0], [*start1, *end1], eps.param) {
104+
if !endpoints && (st.0 < eps.param || st.0 > 1. - eps.param) && (st.1 < eps.param || st.1 > 1. - eps.param) {
105+
return vec![];
106+
}
107+
return vec![st.into()];
94108
}
95-
return vec![st.into()];
96109
}
110+
(PathSegment::Cubic(s1, c11, c21, e1), PathSegment::Cubic(s2, c12, c22, e2)) => {
111+
let path1 = path_segment_cubic_to_lyon(*s1, *c11, *c21, *e1);
112+
let path2 = path_segment_cubic_to_lyon(*s2, *c12, *c22, *e2);
113+
114+
let intersections = path1.cubic_intersections_t(&path2);
115+
let intersections: Vec<_> = intersections.into_iter().map(|(s, t)| [s, t]).collect();
116+
return intersections;
117+
}
118+
_ => (),
97119
}
98120

99121
// https://math.stackexchange.com/questions/20321/how-can-i-tell-when-two-cubic-b%C3%A9zier-curves-intersect

0 commit comments

Comments
 (0)