@@ -975,6 +975,68 @@ async fn splines_from_points<F: 'n + Send>(
975975 vector_data
976976}
977977
978+ #[ node_macro:: node( category( "Vector" ) , path( graphene_core:: vector) ) ]
979+ async fn jitter_points < F : ' n + Send > (
980+ #[ implementations(
981+ ( ) ,
982+ Footprint ,
983+ ) ]
984+ footprint : F ,
985+ #[ implementations(
986+ ( ) -> VectorData ,
987+ Footprint -> VectorData ,
988+ ) ]
989+ vector_data : impl Node < F , Output = VectorData > ,
990+ #[ default( 5. ) ] amount : f64 ,
991+ seed : SeedValue ,
992+ ) -> VectorData {
993+ let mut vector_data = vector_data. eval ( footprint) . await ;
994+
995+ let mut rng = rand:: rngs:: StdRng :: seed_from_u64 ( seed. into ( ) ) ;
996+
997+ let deltas = ( 0 ..vector_data. point_domain . positions ( ) . len ( ) )
998+ . map ( |_| {
999+ let angle = rng. gen :: < f64 > ( ) * std:: f64:: consts:: TAU ;
1000+ DVec2 :: from_angle ( angle) * rng. gen :: < f64 > ( ) * amount
1001+ } )
1002+ . collect :: < Vec < _ > > ( ) ;
1003+ let mut already_applied = vec ! [ false ; vector_data. point_domain. positions( ) . len( ) ] ;
1004+
1005+ for ( handles, start, end) in vector_data. segment_domain . handles_and_points_mut ( ) {
1006+ let start_delta = deltas[ * start] ;
1007+ let end_delta = deltas[ * end] ;
1008+
1009+ if !already_applied[ * start] {
1010+ let start_position = vector_data. point_domain . positions ( ) [ * start] ;
1011+ let start_position = vector_data. transform . transform_point2 ( start_position) ;
1012+ vector_data. point_domain . set_position ( * start, start_position + start_delta) ;
1013+ already_applied[ * start] = true ;
1014+ }
1015+ if !already_applied[ * end] {
1016+ let end_position = vector_data. point_domain . positions ( ) [ * end] ;
1017+ let end_position = vector_data. transform . transform_point2 ( end_position) ;
1018+ vector_data. point_domain . set_position ( * end, end_position + end_delta) ;
1019+ already_applied[ * end] = true ;
1020+ }
1021+
1022+ match handles {
1023+ bezier_rs:: BezierHandles :: Cubic { handle_start, handle_end } => {
1024+ * handle_start = vector_data. transform . transform_point2 ( * handle_start) + start_delta;
1025+ * handle_end += vector_data. transform . transform_point2 ( * handle_end) + end_delta;
1026+ }
1027+ bezier_rs:: BezierHandles :: Quadratic { handle } => {
1028+ * handle += vector_data. transform . transform_point2 ( * handle) + ( start_delta + end_delta) / 2. ;
1029+ }
1030+ bezier_rs:: BezierHandles :: Linear => { }
1031+ }
1032+ }
1033+
1034+ vector_data. transform = DAffine2 :: IDENTITY ;
1035+ vector_data. style . set_stroke_transform ( DAffine2 :: IDENTITY ) ;
1036+
1037+ vector_data
1038+ }
1039+
9781040#[ node_macro:: node( category( "Vector" ) , path( graphene_core:: vector) ) ]
9791041async fn morph < F : ' n + Send + Copy > (
9801042 #[ implementations(
0 commit comments