From a70c48f69af49a3e79cb00980610f88a94e144f2 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Wed, 20 Aug 2025 13:59:11 +0200 Subject: [PATCH] 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 --- Cargo.lock | 1 + libraries/path-bool/Cargo.toml | 1 + .../src/path/intersection_path_segment.rs | 32 ++++++++++++++++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bdfd2cd..376385d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3809,6 +3809,7 @@ dependencies = [ "glam", "glob", "image", + "lyon_geom", "regex", "resvg", "slotmap", diff --git a/libraries/path-bool/Cargo.toml b/libraries/path-bool/Cargo.toml index d85de28d..0f402b6e 100644 --- a/libraries/path-bool/Cargo.toml +++ b/libraries/path-bool/Cargo.toml @@ -27,6 +27,7 @@ default = ["parsing"] glam = "0.29.0" regex = "1.10.6" slotmap = "1.0.7" +lyon_geom = "1.0" [dev-dependencies] glob = "0.3" diff --git a/libraries/path-bool/src/path/intersection_path_segment.rs b/libraries/path-bool/src/path/intersection_path_segment.rs index 74559fd5..00248208 100644 --- a/libraries/path-bool/src/path/intersection_path_segment.rs +++ b/libraries/path-bool/src/path/intersection_path_segment.rs @@ -5,6 +5,17 @@ use crate::line_segment_aabb::line_segment_aabb_intersect; use crate::math::lerp; use crate::path_segment::PathSegment; 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 { + 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)] 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]> { - if let (PathSegment::Line(start0, end0), PathSegment::Line(start1, end1)) = (seg0, seg1) { - if let Some(st) = line_segment_intersection([*start0, *end0], [*start1, *end1], eps.param) { - if !endpoints && (st.0 < eps.param || st.0 > 1. - eps.param) && (st.1 < eps.param || st.1 > 1. - eps.param) { - return vec![]; + match (seg0, seg1) { + (PathSegment::Line(start0, end0), PathSegment::Line(start1, end1)) => { + if let Some(st) = line_segment_intersection([*start0, *end0], [*start1, *end1], eps.param) { + 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