Fix n-gon intersection (#342)

* Fix n-gon intersection

* Fix not all layers selected with box selection

* Code golf for TrueDoctor
This commit is contained in:
Paul Kupper
2021-08-11 23:58:10 +02:00
committed by GitHub
parent 01e66bcf79
commit 9cd6d57337
3 changed files with 20 additions and 27 deletions

2
Cargo.lock generated
View File

@@ -168,7 +168,7 @@ dependencies = [
[[package]]
name = "kurbo"
version = "0.8.1"
source = "git+https://github.com/linebender/kurbo#0ef68211223b956942c4a5834d66a2625cb8d575"
source = "git+https://github.com/GraphiteEditor/kurbo.git#feb9ef74f841fcc5890bfe6ae763fbb986c80490"
dependencies = [
"arrayvec",
"serde",

View File

@@ -11,6 +11,8 @@ license = "Apache-2.0"
[dependencies]
log = "0.4"
kurbo = {git="https://github.com/linebender/kurbo", features = ["serde"]}
kurbo = { git = "https://github.com/GraphiteEditor/kurbo.git", features = [
"serde",
] }
serde = { version = "1.0", features = ["derive"] }
glam = { version = "0.17", features = ["serde"] }

View File

@@ -1,7 +1,7 @@
use std::ops::Mul;
use glam::{DAffine2, DVec2};
use kurbo::{BezPath, Line, PathSeg, Point, Shape, Vec2};
use kurbo::{BezPath, Line, PathSeg, Point, Shape};
#[derive(Debug, Clone, Default, Copy)]
pub struct Quad([DVec2; 4]);
@@ -9,7 +9,7 @@ pub struct Quad([DVec2; 4]);
impl Quad {
pub fn from_box(bbox: [DVec2; 2]) -> Self {
let size = bbox[1] - bbox[0];
Self([bbox[0], bbox[0] + size * DVec2::X, bbox[0] + size * DVec2::Y, bbox[1]])
Self([bbox[0], bbox[0] + size * DVec2::X, bbox[1], bbox[0] + size * DVec2::Y])
}
pub fn lines(&self) -> [Line; 4] {
@@ -20,6 +20,16 @@ impl Quad {
Line::new(to_point(self.0[3]), to_point(self.0[0])),
]
}
pub fn path(&self) -> BezPath {
let mut path = kurbo::BezPath::new();
path.move_to(to_point(self.0[0]));
path.line_to(to_point(self.0[1]));
path.line_to(to_point(self.0[2]));
path.line_to(to_point(self.0[3]));
path.close_path();
path
}
}
impl Mul<Quad> for DAffine2 {
@@ -44,31 +54,12 @@ pub fn intersect_quad_bez_path(quad: Quad, shape: &BezPath, closed: bool) -> boo
return true;
}
// check if selection is entirely within the shape
if closed && quad.0.iter().any(|q| shape.contains(to_point(*q))) {
if closed && shape.contains(to_point(quad.0[0])) {
return true;
}
// check if shape is entirely within the selection
if let Some(shape_point) = get_arbitrary_point_on_path(shape) {
let mut pos = 0;
let mut neg = 0;
for line in quad.lines() {
if line.p0 == shape_point {
return true;
};
let line_vec = Vec2::new(line.p1.x - line.p0.x, line.p1.y - line.p0.y);
let point_vec = Vec2::new(line.p1.x - shape_point.x, line.p1.y - shape_point.y);
let cross = line_vec.cross(point_vec);
if cross > 0.0 {
pos += 1;
} else if cross < 0.0 {
neg += 1;
}
if pos > 0 && neg > 0 {
return false;
}
}
}
true
// check if shape is entirely within selection
get_arbitrary_point_on_path(shape).map(|shape_point| quad.path().contains(shape_point)).unwrap_or_default()
}
pub fn get_arbitrary_point_on_path(path: &BezPath) -> Option<Point> {