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
This commit is contained in:
Dennis Kobert 2025-08-20 13:59:11 +02:00 committed by GitHub
parent e70862b399
commit a70c48f69a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 29 additions and 5 deletions

1
Cargo.lock generated
View File

@ -3809,6 +3809,7 @@ dependencies = [
"glam", "glam",
"glob", "glob",
"image", "image",
"lyon_geom",
"regex", "regex",
"resvg", "resvg",
"slotmap", "slotmap",

View File

@ -27,6 +27,7 @@ default = ["parsing"]
glam = "0.29.0" glam = "0.29.0"
regex = "1.10.6" regex = "1.10.6"
slotmap = "1.0.7" slotmap = "1.0.7"
lyon_geom = "1.0"
[dev-dependencies] [dev-dependencies]
glob = "0.3" glob = "0.3"

View File

@ -5,6 +5,17 @@ use crate::line_segment_aabb::line_segment_aabb_intersect;
use crate::math::lerp; use crate::math::lerp;
use crate::path_segment::PathSegment; use crate::path_segment::PathSegment;
use glam::DVec2; use glam::DVec2;
use lyon_geom::{CubicBezierSegment, Point};
/// Convert PathSegment::Cubic to lyon_geom::CubicBezierSegment
fn path_segment_cubic_to_lyon(start: DVec2, ctrl1: DVec2, ctrl2: DVec2, end: DVec2) -> CubicBezierSegment<f64> {
CubicBezierSegment {
from: Point::new(start.x, start.y),
ctrl1: Point::new(ctrl1.x, ctrl1.y),
ctrl2: Point::new(ctrl2.x, ctrl2.y),
to: Point::new(end.x, end.y),
}
}
#[derive(Clone)] #[derive(Clone)]
struct IntersectionSegment { struct IntersectionSegment {
@ -87,13 +98,24 @@ pub fn segments_equal(seg0: &PathSegment, seg1: &PathSegment, point_epsilon: f64
} }
pub fn path_segment_intersection(seg0: &PathSegment, seg1: &PathSegment, endpoints: bool, eps: &Epsilons) -> Vec<[f64; 2]> { pub fn path_segment_intersection(seg0: &PathSegment, seg1: &PathSegment, endpoints: bool, eps: &Epsilons) -> Vec<[f64; 2]> {
if let (PathSegment::Line(start0, end0), PathSegment::Line(start1, end1)) = (seg0, seg1) { match (seg0, seg1) {
if let Some(st) = line_segment_intersection([*start0, *end0], [*start1, *end1], eps.param) { (PathSegment::Line(start0, end0), PathSegment::Line(start1, end1)) => {
if !endpoints && (st.0 < eps.param || st.0 > 1. - eps.param) && (st.1 < eps.param || st.1 > 1. - eps.param) { if let Some(st) = line_segment_intersection([*start0, *end0], [*start1, *end1], eps.param) {
return vec![]; if !endpoints && (st.0 < eps.param || st.0 > 1. - eps.param) && (st.1 < eps.param || st.1 > 1. - eps.param) {
return vec![];
}
return vec![st.into()];
} }
return vec![st.into()];
} }
(PathSegment::Cubic(s1, c11, c21, e1), PathSegment::Cubic(s2, c12, c22, e2)) => {
let path1 = path_segment_cubic_to_lyon(*s1, *c11, *c21, *e1);
let path2 = path_segment_cubic_to_lyon(*s2, *c12, *c22, *e2);
let intersections = path1.cubic_intersections_t(&path2);
let intersections: Vec<_> = intersections.into_iter().map(|(s, t)| [s, t]).collect();
return intersections;
}
_ => (),
} }
// https://math.stackexchange.com/questions/20321/how-can-i-tell-when-two-cubic-b%C3%A9zier-curves-intersect // https://math.stackexchange.com/questions/20321/how-can-i-tell-when-two-cubic-b%C3%A9zier-curves-intersect