Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions node-graph/gcore/src/vector/algorithms/bezpath_algorithms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,8 +608,9 @@ pub fn round_line_join(bezpath1: &BezPath, bezpath2: &BezPath, center: DVec2) ->
}

/// Returns `true` if the `bezpath1` is completely inside the `bezpath2`.
/// NOTE: `bezpath2` must be a closed path to get correct results.
pub fn bezpath_is_inside_bezpath(bezpath1: &BezPath, bezpath2: &BezPath, accuracy: Option<f64>, minimum_separation: Option<f64>) -> bool {
// Eliminate any possibility of one being inside the other, if either of them is empty
// Eliminate any possibility of one being inside the other, if either of them are empty
if bezpath1.is_empty() || bezpath2.is_empty() {
return false;
}
Expand All @@ -621,12 +622,12 @@ pub fn bezpath_is_inside_bezpath(bezpath1: &BezPath, bezpath2: &BezPath, accurac
// Reasoning:
// If the inner bezpath bounding box is larger than the outer bezpath bounding box in any direction
// then the inner bezpath is intersecting with or outside the outer bezpath.
if !outer_bbox.contains_rect(inner_bbox) {
if !outer_bbox.contains_rect(inner_bbox) && outer_bbox.intersect(inner_bbox).is_zero_area() {
return false;
}

// Eliminate bezpath1 if any of its anchor points are outside the bezpath2.
if !bezpath1.elements().iter().filter_map(|el| el.end_point()).all(|point| bezpath2.contains(point)) {
if !bezpath1.elements().iter().filter_map(|elm| elm.end_point()).all(|point| bezpath2.contains(point)) {
return false;
}

Expand Down
10 changes: 6 additions & 4 deletions node-graph/gcore/src/vector/click_target.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use super::algorithms::intersection::filtered_segment_intersections;
use super::algorithms::{bezpath_algorithms::bezpath_is_inside_bezpath, intersection::filtered_segment_intersections};
use super::misc::dvec2_to_point;
use crate::math::math_ext::QuadExt;
use crate::math::quad::Quad;
use crate::subpath::Subpath;
use crate::vector::PointId;
use crate::vector::misc::point_to_dvec2;
use glam::{DAffine2, DMat2, DVec2};
use kurbo::{Affine, ParamCurve, PathSeg, Point, Shape};
use kurbo::{Affine, BezPath, ParamCurve, PathSeg, Shape};

#[derive(Copy, Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct FreePoint {
Expand Down Expand Up @@ -125,9 +125,11 @@ impl ClickTarget {
return true;
}

let mut selection = BezPath::from_path_segments(bezier_iter());
selection.close_path();

// Check if shape is entirely within selection
let any_point_from_subpath = subpath.manipulator_groups().first().map(|manipulators| manipulators.anchor);
any_point_from_subpath.is_some_and(|shape_point| bezier_iter().map(|bezier| bezier.winding(Point::new(shape_point.x, shape_point.y))).sum::<i32>() != 0)
bezpath_is_inside_bezpath(&subpath.to_bezpath(), &selection, None, None)
}
ClickTargetType::FreePoint(point) => bezier_iter().map(|bezier: PathSeg| bezier.winding(dvec2_to_point(point.position))).sum::<i32>() != 0,
}
Expand Down
Loading