@@ -12,11 +12,11 @@ use crate::vector::PointDomain;
1212use crate :: vector:: misc:: dvec2_to_point;
1313use crate :: vector:: style:: { LineCap , LineJoin } ;
1414use crate :: { CloneVarArgs , Color , Context , Ctx , ExtractAll , GraphicElement , GraphicGroupTable , OwnedContextImpl } ;
15- use bezier_rs:: { Join , ManipulatorGroup , Subpath , SubpathTValue } ;
15+ use bezier_rs:: { Join , ManipulatorGroup , Subpath } ;
1616use core:: f64:: consts:: PI ;
1717use core:: hash:: { Hash , Hasher } ;
1818use glam:: { DAffine2 , DVec2 } ;
19- use kurbo:: { Affine , BezPath , DEFAULT_ACCURACY , Shape } ;
19+ use kurbo:: { Affine , BezPath , DEFAULT_ACCURACY , ParamCurve , PathEl , PathSeg , Point , Shape } ;
2020use rand:: { Rng , SeedableRng } ;
2121use std:: collections:: hash_map:: DefaultHasher ;
2222use std:: f64:: consts:: TAU ;
@@ -1526,6 +1526,46 @@ async fn jitter_points(_: impl Ctx, vector_data: VectorDataTable, #[default(5.)]
15261526
15271527#[ node_macro:: node( category( "Vector" ) , path( graphene_core:: vector) ) ]
15281528async fn morph ( _: impl Ctx , source : VectorDataTable , #[ expose] target : VectorDataTable , #[ default( 0.5 ) ] time : Fraction ) -> VectorDataTable {
1529+ /// Subdivides the last segment of the bezpath to until it appends 'count' number of segments.
1530+ fn make_new_segments ( bezpath : & mut BezPath , count : usize ) {
1531+ let bezpath_segment_count = bezpath. segments ( ) . count ( ) ;
1532+
1533+ if count == 0 || bezpath_segment_count == 0 {
1534+ return ;
1535+ }
1536+
1537+ // Initially push the last segment of the bezpath
1538+ let mut new_segments = vec ! [ bezpath. get_seg( bezpath_segment_count) . unwrap( ) ] ;
1539+
1540+ // Generate new segments by subdividing last segment
1541+ for _ in 0 ..count {
1542+ let last = new_segments. pop ( ) . unwrap ( ) ;
1543+ let ( first, second) = last. subdivide ( ) ;
1544+ new_segments. push ( first) ;
1545+ new_segments. push ( second) ;
1546+ }
1547+
1548+ // Append the new segments.
1549+ if count != 0 {
1550+ // Remove the last segment as it is already appended to the new_segments.
1551+ let mut is_closed = false ;
1552+ if let Some ( last_element) = bezpath. pop ( ) {
1553+ if last_element == PathEl :: ClosePath {
1554+ is_closed = true ;
1555+ _ = bezpath. pop ( ) ;
1556+ }
1557+ }
1558+
1559+ for segment in new_segments {
1560+ bezpath. push ( segment. as_path_el ( ) ) ;
1561+ }
1562+
1563+ if is_closed {
1564+ bezpath. close_path ( ) ;
1565+ }
1566+ }
1567+ }
1568+
15291569 let time = time. clamp ( 0. , 1. ) ;
15301570
15311571 let mut result_table = VectorDataTable :: default ( ) ;
@@ -1542,65 +1582,99 @@ async fn morph(_: impl Ctx, source: VectorDataTable, #[expose] target: VectorDat
15421582 let target_transform = target_instance. transform ;
15431583
15441584 // Before and after paths
1545- let source_paths = source_instance. instance . stroke_bezier_paths ( ) ;
1546- let target_paths = target_instance. instance . stroke_bezier_paths ( ) ;
1547- for ( mut source_path, mut target_path) in source_paths. zip ( target_paths) {
1548- source_path. apply_transform ( source_transform) ;
1549- target_path. apply_transform ( target_transform) ;
1550-
1551- // Align point counts by inserting mid‐segment points until their counts match
1552- while source_path. manipulator_groups ( ) . len ( ) < target_path. manipulator_groups ( ) . len ( ) {
1553- let last = source_path. len ( ) - 1 ;
1554- source_path. insert ( SubpathTValue :: Parametric { segment_index : last, t : 0.5 } ) ;
1555- }
1556- while target_path. manipulator_groups ( ) . len ( ) < source_path. manipulator_groups ( ) . len ( ) {
1557- let last = target_path. len ( ) - 1 ;
1558- target_path. insert ( SubpathTValue :: Parametric { segment_index : last, t : 0.5 } ) ;
1585+ let source_bezpaths = source_instance. instance . stroke_bezpath_iter ( ) ;
1586+ let target_bezpaths = target_instance. instance . stroke_bezpath_iter ( ) ;
1587+
1588+ for ( mut source_bezpath, mut target_bezpath) in source_bezpaths. zip ( target_bezpaths) {
1589+ if source_bezpath. elements ( ) . is_empty ( ) || target_bezpath. elements ( ) . is_empty ( ) {
1590+ continue ;
15591591 }
15601592
1593+ source_bezpath. apply_affine ( Affine :: new ( source_transform. to_cols_array ( ) ) ) ;
1594+ target_bezpath. apply_affine ( Affine :: new ( target_transform. to_cols_array ( ) ) ) ;
1595+
1596+ let target_segment_len = target_bezpath. segments ( ) . count ( ) ;
1597+ let source_segment_len = source_bezpath. segments ( ) . count ( ) ;
1598+
1599+ // Insert new segments to align the number of segments in sorce_bezpath and target_bezpath.
1600+ make_new_segments ( & mut source_bezpath, target_segment_len. max ( source_segment_len) - source_segment_len) ;
1601+ make_new_segments ( & mut target_bezpath, source_segment_len. max ( target_segment_len) - target_segment_len) ;
1602+
1603+ let source_segments = source_bezpath. segments ( ) . collect :: < Vec < PathSeg > > ( ) ;
1604+ let target_segments = target_bezpath. segments ( ) . collect :: < Vec < PathSeg > > ( ) ;
1605+
15611606 // Interpolate anchors and handles
1562- for ( source_manipulators, target_manipulators) in source_path. manipulator_groups_mut ( ) . iter_mut ( ) . zip ( target_path. manipulator_groups ( ) ) {
1563- let source_anchor = source_manipulators. anchor ;
1564- let target_anchor = target_manipulators. anchor ;
1565- source_manipulators. anchor = source_anchor. lerp ( target_anchor, time) ;
1566-
1567- let source_in_handle = source_manipulators. in_handle . unwrap_or ( source_anchor) ;
1568- let target_in_handle = target_manipulators. in_handle . unwrap_or ( target_anchor) ;
1569- source_manipulators. in_handle = Some ( source_in_handle. lerp ( target_in_handle, time) ) ;
1570-
1571- let source_out_handle = source_manipulators. out_handle . unwrap_or ( source_anchor) ;
1572- let target_out_handle = target_manipulators. out_handle . unwrap_or ( target_anchor) ;
1573- source_manipulators. out_handle = Some ( source_out_handle. lerp ( target_out_handle, time) ) ;
1607+ for ( i, ( source_element, target_element) ) in source_bezpath. elements_mut ( ) . iter_mut ( ) . zip ( target_bezpath. elements_mut ( ) . iter_mut ( ) ) . enumerate ( ) {
1608+ match source_element {
1609+ PathEl :: MoveTo ( point) => * point = point. lerp ( target_element. end_point ( ) . unwrap ( ) , time) ,
1610+ PathEl :: ClosePath => { }
1611+ elm => {
1612+ let mut source_segment = source_segments. get ( i - 1 ) . unwrap ( ) . to_cubic ( ) ;
1613+ let target_segment = target_segments. get ( i - 1 ) . unwrap ( ) . to_cubic ( ) ;
1614+ source_segment. p0 = source_segment. p0 . lerp ( target_segment. p0 , time) ;
1615+ source_segment. p1 = source_segment. p1 . lerp ( target_segment. p1 , time) ;
1616+ source_segment. p2 = source_segment. p2 . lerp ( target_segment. p2 , time) ;
1617+ source_segment. p3 = source_segment. p3 . lerp ( target_segment. p3 , time) ;
1618+ * elm = PathSeg :: Cubic ( source_segment) . as_path_el ( ) ;
1619+ }
1620+ }
15741621 }
15751622
1576- vector_data_instance. append_subpath ( source_path . clone ( ) , true ) ;
1623+ vector_data_instance. append_bezpath ( source_bezpath . clone ( ) ) ;
15771624 }
15781625
15791626 // Deal with unmatched extra paths by collapsing them
1580- let source_paths_count = source_instance. instance . stroke_bezier_paths ( ) . count ( ) ;
1581- let target_paths_count = target_instance. instance . stroke_bezier_paths ( ) . count ( ) ;
1582- let source_paths = source_instance. instance . stroke_bezier_paths ( ) . skip ( target_paths_count) ;
1583- let target_paths = target_instance. instance . stroke_bezier_paths ( ) . skip ( source_paths_count) ;
1627+ let source_paths_count = source_instance. instance . stroke_bezpath_iter ( ) . count ( ) ;
1628+ let target_paths_count = target_instance. instance . stroke_bezpath_iter ( ) . count ( ) ;
1629+ let source_paths = source_instance. instance . stroke_bezpath_iter ( ) . skip ( target_paths_count) ;
1630+ let target_paths = target_instance. instance . stroke_bezpath_iter ( ) . skip ( source_paths_count) ;
15841631
15851632 for mut source_path in source_paths {
1586- source_path. apply_transform ( source_transform) ;
1587- let end = source_path. manipulator_groups ( ) . last ( ) . map ( |group| group. anchor ) . unwrap_or_default ( ) ;
1588- for group in source_path. manipulator_groups_mut ( ) {
1589- group. anchor = group. anchor . lerp ( end, time) ;
1590- group. in_handle = group. in_handle . map ( |handle| handle. lerp ( end, time) ) ;
1591- group. out_handle = group. out_handle . map ( |handle| handle. lerp ( end, time) ) ;
1633+ source_path. apply_affine ( Affine :: new ( source_transform. to_cols_array ( ) ) ) ;
1634+
1635+ let end: Point = source_path. elements ( ) . last ( ) . and_then ( |element| element. end_point ( ) ) . unwrap_or_default ( ) ;
1636+
1637+ for element in source_path. elements_mut ( ) {
1638+ match element {
1639+ PathEl :: MoveTo ( point) => * point = point. lerp ( end, time) ,
1640+ PathEl :: LineTo ( point) => * point = point. lerp ( end, time) ,
1641+ PathEl :: QuadTo ( point, point1) => {
1642+ * point = point. lerp ( end, time) ;
1643+ * point1 = point1. lerp ( end, time) ;
1644+ }
1645+ PathEl :: CurveTo ( point, point1, point2) => {
1646+ * point = point. lerp ( end, time) ;
1647+ * point1 = point1. lerp ( end, time) ;
1648+ * point2 = point2. lerp ( end, time) ;
1649+ }
1650+ PathEl :: ClosePath => { }
1651+ }
15921652 }
1593- vector_data_instance. append_subpath ( source_path, true ) ;
1653+ vector_data_instance. append_bezpath ( source_path) ;
15941654 }
1655+
15951656 for mut target_path in target_paths {
1596- target_path. apply_transform ( target_transform) ;
1597- let start = target_path. manipulator_groups ( ) . first ( ) . map ( |group| group. anchor ) . unwrap_or_default ( ) ;
1598- for group in target_path. manipulator_groups_mut ( ) {
1599- group. anchor = start. lerp ( group. anchor , time) ;
1600- group. in_handle = group. in_handle . map ( |handle| start. lerp ( handle, time) ) ;
1601- group. out_handle = group. out_handle . map ( |handle| start. lerp ( handle, time) ) ;
1657+ target_path. apply_affine ( Affine :: new ( source_transform. to_cols_array ( ) ) ) ;
1658+
1659+ let end: Point = target_path. elements ( ) . last ( ) . and_then ( |element| element. end_point ( ) ) . unwrap_or_default ( ) ;
1660+
1661+ for element in target_path. elements_mut ( ) {
1662+ match element {
1663+ PathEl :: MoveTo ( point) => * point = point. lerp ( end, time) ,
1664+ PathEl :: LineTo ( point) => * point = point. lerp ( end, time) ,
1665+ PathEl :: QuadTo ( point, point1) => {
1666+ * point = point. lerp ( end, time) ;
1667+ * point1 = point1. lerp ( end, time) ;
1668+ }
1669+ PathEl :: CurveTo ( point, point1, point2) => {
1670+ * point = point. lerp ( end, time) ;
1671+ * point1 = point1. lerp ( end, time) ;
1672+ * point2 = point2. lerp ( end, time) ;
1673+ }
1674+ PathEl :: ClosePath => { }
1675+ }
16021676 }
1603- vector_data_instance. append_subpath ( target_path, true ) ;
1677+ vector_data_instance. append_bezpath ( target_path) ;
16041678 }
16051679
16061680 result_table. push ( Instance {
0 commit comments