Skip to content

Commit 7d86bf4

Browse files
committed
New node: Jitter Points
1 parent 4c9ab2d commit 7d86bf4

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

node-graph/gcore/src/vector/vector_nodes.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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))]
9791041
async fn morph<F: 'n + Send + Copy>(
9801042
#[implementations(

0 commit comments

Comments
 (0)