Add path-bool library (#1952)

* Add path-bool library

* Cleanup code

* Cargo format

* Integrate boolean ops into graphite

* Add test for editor crash

* Fix edge sort floating point instability

* Add unit test for red-dress failure

* Backport tests and aux functions

* Use curvature based sorting

* Convert linear cubic splines to line segments

* Deduplicate reversed path segments

* Fix epsilon for empty segments

* Remove parameter based intersection pruning

* Add support for reversed paths

* Add benchmark infrastructure

* Add intersection benchmark

* Add recursion bound

* Implement support for overlapping path segments

* Remove rouge prinln

* Fix sorting for bezier segments with one control point at the start of the segment

* Cleanup log statements

* Directly translate graphite paths to Path segments

* Round data before passing it to path_bool

* Fix flag_faces traversal order

* Add test for white dots in bottom right of painted dreams

* Make rounding configurable

* Update demo artwork to remove manual path modifications

* Convert from path segments to manipulator groups directly

* Remove dead code

* Fix clippy lints

* Replace functions in path segment with methods and add documentation

* Add more documentation

* Close subpaths

* Reorganize files and add README.md

* Add license information

* Code review

* Fix license info

* Adopt new node macro and fix demo artwork

* Close subpaths with Z

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2024-09-21 02:06:43 -07:00
committed by GitHub
co-authored by Keavon Chambers
parent 2febbfd698
commit 3eb98c6d6d
165 changed files with 5990 additions and 78 deletions
@@ -0,0 +1,33 @@
use glam::DVec2;
pub type LineSegment = [DVec2; 2];
const COLLINEAR_EPS: f64 = f64::EPSILON * 64.0;
#[inline(never)]
pub fn line_segment_intersection([p1, p2]: LineSegment, [p3, p4]: LineSegment, eps: f64) -> Option<(f64, f64)> {
// https://en.wikipedia.org/wiki/Intersection_(geometry)#Two_line_segments
let a = p2 - p1;
let b = p3 - p4;
let c = p3 - p1;
let denom = a.x * b.y - a.y * b.x;
if denom.abs() < COLLINEAR_EPS {
return None;
}
let s = (c.x * b.y - c.y * b.x) / denom;
let t = (a.x * c.y - a.y * c.x) / denom;
if (-eps..=1.0 + eps).contains(&s) && (-eps..=1.0 + eps).contains(&t) {
Some((s, t))
} else {
None
}
}
pub fn line_segments_intersect(seg1: LineSegment, seg2: LineSegment, eps: f64) -> bool {
line_segment_intersection(seg1, seg2, eps).is_some()
}