@@ -2,7 +2,7 @@ mod attributes;
22mod indexed;
33mod modification;
44
5- use super :: misc:: point_to_dvec2;
5+ use super :: misc:: { dvec2_to_point , point_to_dvec2} ;
66use super :: style:: { PathStyle , Stroke } ;
77use crate :: instances:: Instances ;
88use crate :: { AlphaBlending , Color , GraphicGroupTable } ;
@@ -12,6 +12,7 @@ use core::borrow::Borrow;
1212use dyn_any:: DynAny ;
1313use glam:: { DAffine2 , DVec2 } ;
1414pub use indexed:: VectorDataIndex ;
15+ use kurbo:: { Affine , Shape } ;
1516pub use modification:: * ;
1617use std:: collections:: HashMap ;
1718
@@ -193,6 +194,23 @@ impl VectorData {
193194 vector_data
194195 }
195196
197+ pub fn close_subpaths ( & mut self ) {
198+ let segments_to_add: Vec < _ > = self
199+ . stroke_bezier_paths ( )
200+ . filter ( |subpath| !subpath. closed )
201+ . filter_map ( |subpath| {
202+ let ( first, last) = subpath. manipulator_groups ( ) . first ( ) . zip ( subpath. manipulator_groups ( ) . last ( ) ) ?;
203+ let ( start, end) = self . point_domain . resolve_id ( first. id ) . zip ( self . point_domain . resolve_id ( last. id ) ) ?;
204+ Some ( ( start, end) )
205+ } )
206+ . collect ( ) ;
207+
208+ for ( start, end) in segments_to_add {
209+ let segment_id = self . segment_domain . next_id ( ) . next_id ( ) ;
210+ self . segment_domain . push ( segment_id, start, end, bezier_rs:: BezierHandles :: Linear , StrokeId :: ZERO ) ;
211+ }
212+ }
213+
196214 /// Compute the bounding boxes of the subpaths without any transform
197215 pub fn bounding_box ( & self ) -> Option < [ DVec2 ; 2 ] > {
198216 self . bounding_box_with_transform ( DAffine2 :: IDENTITY )
@@ -316,6 +334,34 @@ impl VectorData {
316334 self . point_domain . resolve_id ( point) . map_or ( 0 , |point| self . segment_domain . connected_count ( point) )
317335 }
318336
337+ pub fn check_point_inside_shape ( & self , vector_data_transform : DAffine2 , point : DVec2 ) -> bool {
338+ let bez_paths: Vec < _ > = self
339+ . stroke_bezpath_iter ( )
340+ . map ( |mut bezpath| {
341+ // TODO: apply transform to points instead of modifying the paths
342+ bezpath. apply_affine ( Affine :: new ( vector_data_transform. to_cols_array ( ) ) ) ;
343+ bezpath. close_path ( ) ;
344+ let bbox = bezpath. bounding_box ( ) ;
345+ ( bezpath, bbox)
346+ } )
347+ . collect ( ) ;
348+
349+ // Check against all paths the point is contained in to compute the correct winding number
350+ let mut number = 0 ;
351+
352+ for ( shape, bbox) in bez_paths {
353+ if bbox. x0 > point. x || bbox. y0 > point. y || bbox. x1 < point. x || bbox. y1 < point. y {
354+ continue ;
355+ }
356+
357+ let winding = shape. winding ( dvec2_to_point ( point) ) ;
358+ number += winding;
359+ }
360+
361+ // Non-zero fill rule
362+ number != 0
363+ }
364+
319365 /// Points that can be extended from.
320366 ///
321367 /// This is usually only points with exactly one connection unless vector meshes are enabled.
0 commit comments