mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-04 13:30:48 +00:00
Always close subpaths before applying boolean ops (#2014)
* Always close subpaths before applying boolean ops * Roundtrip boolean path through svg string * Reverse closing path segment * Sort result of boolean ops * Make face visiting order deterministic * Remove debugging code * Remove unused post processing * Clippy lint --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
d2f791cfb3
commit
b26dfbcd7c
3 changed files with 56 additions and 7 deletions
|
@ -5,10 +5,11 @@ use graphene_core::transform::Transform;
|
|||
use graphene_core::vector::misc::BooleanOperation;
|
||||
pub use graphene_core::vector::*;
|
||||
use graphene_core::{Color, GraphicElement, GraphicGroup};
|
||||
use path_bool::FillRule;
|
||||
use path_bool::PathBooleanOperation;
|
||||
|
||||
use glam::{DAffine2, DVec2};
|
||||
use path_bool::PathBooleanOperation;
|
||||
use std::ops::{Div, Mul};
|
||||
use std::ops::Mul;
|
||||
|
||||
#[node_macro::node(category(""))]
|
||||
async fn boolean_operation<F: 'n + Send>(
|
||||
|
@ -205,11 +206,17 @@ fn to_path(vector: &VectorData, transform: DAffine2) -> Vec<path_bool::PathSegme
|
|||
|
||||
fn to_path_segments(path: &mut Vec<path_bool::PathSegment>, subpath: &bezier_rs::Subpath<PointId>, transform: DAffine2) {
|
||||
use path_bool::PathSegment;
|
||||
let mut global_start = None;
|
||||
let mut global_end = DVec2::ZERO;
|
||||
for bezier in subpath.iter() {
|
||||
const EPS: f64 = 1e-8;
|
||||
let transformed = bezier.apply_transformation(|pos| transform.transform_point2(pos).mul(EPS.recip()).round().div(EPS.recip()));
|
||||
let transformed = bezier.apply_transformation(|pos| transform.transform_point2(pos).mul(EPS.recip()).round().mul(EPS));
|
||||
let start = transformed.start;
|
||||
let end = transformed.end;
|
||||
if global_start.is_none() {
|
||||
global_start = Some(start);
|
||||
}
|
||||
global_end = end;
|
||||
let segment = match transformed.handles {
|
||||
bezier_rs::BezierHandles::Linear => PathSegment::Line(start, end),
|
||||
bezier_rs::BezierHandles::Quadratic { handle } => PathSegment::Quadratic(start, handle, end),
|
||||
|
@ -217,6 +224,9 @@ fn to_path_segments(path: &mut Vec<path_bool::PathSegment>, subpath: &bezier_rs:
|
|||
};
|
||||
path.push(segment);
|
||||
}
|
||||
if let Some(start) = global_start {
|
||||
path.push(PathSegment::Line(global_end, start));
|
||||
}
|
||||
}
|
||||
|
||||
fn from_path(path_data: &[Path]) -> VectorData {
|
||||
|
@ -317,7 +327,6 @@ fn boolean_union(a: Path, b: Path) -> Vec<Path> {
|
|||
}
|
||||
|
||||
fn path_bool(a: Path, b: Path, op: PathBooleanOperation) -> Vec<Path> {
|
||||
use path_bool::FillRule;
|
||||
match path_bool::path_boolean(&a, FillRule::NonZero, &b, FillRule::NonZero, op) {
|
||||
Ok(results) => results,
|
||||
Err(e) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue