Skip to content

Commit 0170d8f

Browse files
committed
move sampling points code into a separate function
1 parent 5ef41ba commit 0170d8f

File tree

2 files changed

+54
-46
lines changed

2 files changed

+54
-46
lines changed

node-graph/gcore/src/vector/algorithms/bezpath_algorithms.rs

+50
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,56 @@ pub fn tangent_on_bezpath(bezpath: &BezPath, t: f64, euclidian: bool, segments_l
2020
}
2121
}
2222

23+
pub fn sample_points_on_bezpath(bezpath: BezPath, spacing: f64, start_offset: f64, stop_offset: f64, adaptive_spacing: bool, segments_length: &[f64]) -> Option<BezPath> {
24+
let mut sample_bezpath = BezPath::new();
25+
26+
// Calculate the total length of the collected segments.
27+
let total_length: f64 = segments_length.iter().sum();
28+
29+
// Adjust the usable length by subtracting start and stop offsets.
30+
let mut used_length = total_length - start_offset - stop_offset;
31+
32+
if used_length <= 0. {
33+
return None;
34+
}
35+
36+
// Determine the number of points to generate along the path.
37+
let count = if adaptive_spacing {
38+
// Calculate point count to evenly distribute points while covering the entire path.
39+
// With adaptive spacing, we widen or narrow the points as necessary to ensure the last point is always at the end of the path.
40+
(used_length / spacing).round()
41+
} else {
42+
// Calculate point count based on exact spacing, which may not cover the entire path.
43+
44+
// Without adaptive spacing, we just evenly space the points at the exact specified spacing, usually falling short before the end of the path.
45+
let count = (used_length / spacing + f64::EPSILON).floor();
46+
used_length -= used_length % spacing;
47+
count
48+
};
49+
50+
// Skip if there are no points to generate.
51+
if count < 1. {
52+
return None;
53+
}
54+
// Generate points along the path based on calculated intervals.
55+
let max_c = count as usize;
56+
57+
for c in 0..=max_c {
58+
let fraction = c as f64 / count;
59+
let current_length = fraction * used_length + start_offset;
60+
let t = current_length / total_length;
61+
let point = position_on_bezpath(&bezpath, t, true, Some(segments_length));
62+
63+
if sample_bezpath.elements().is_empty() {
64+
sample_bezpath.move_to(point)
65+
} else {
66+
sample_bezpath.line_to(point)
67+
}
68+
}
69+
70+
Some(sample_bezpath)
71+
}
72+
2373
pub fn t_value_to_parametric(bezpath: &BezPath, t: f64, euclidian: bool, segments_length: Option<&[f64]>) -> (usize, f64) {
2474
if euclidian {
2575
let (segment_index, t) = bezpath_t_value_to_parametric(bezpath, BezPathTValue::GlobalEuclidean(t), segments_length);

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

+4-46
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::algorithms::bezpath_algorithms::{PERIMETER_ACCURACY, position_on_bezpath, tangent_on_bezpath};
1+
use super::algorithms::bezpath_algorithms::{PERIMETER_ACCURACY, position_on_bezpath, sample_points_on_bezpath, tangent_on_bezpath};
22
use super::algorithms::offset_subpath::offset_subpath;
33
use super::misc::{CentroidType, point_to_dvec2};
44
use super::style::{Fill, Gradient, GradientStops, Stroke};
@@ -15,7 +15,7 @@ use bezier_rs::{Join, ManipulatorGroup, Subpath, SubpathTValue};
1515
use core::f64::consts::PI;
1616
use core::hash::{Hash, Hasher};
1717
use glam::{DAffine2, DVec2};
18-
use kurbo::{Affine, BezPath, Shape};
18+
use kurbo::{Affine, Shape};
1919
use rand::{Rng, SeedableRng};
2020
use std::collections::hash_map::DefaultHasher;
2121

@@ -1161,63 +1161,21 @@ async fn sample_points(_: impl Ctx, vector_data: VectorDataTable, spacing: f64,
11611161
let mut next_segment_index = 0;
11621162

11631163
for mut bezpath in bezpaths {
1164-
let mut sample_bezpath = BezPath::new();
1165-
11661164
// Apply the tranformation to the current bezpath to calculate points after transformation.
11671165
bezpath.apply_affine(Affine::new(vector_data_transform.to_cols_array()));
11681166

11691167
let segment_count = bezpath.segments().count();
11701168

11711169
// For the current bezpath we get its segment's length by calculating the start index and end index.
1172-
let lengths = &subpath_segment_lengths[next_segment_index..next_segment_index + segment_count];
1170+
let current_bezpath_segments_length = &subpath_segment_lengths[next_segment_index..next_segment_index + segment_count];
11731171

11741172
// Increment the segment index by the number of segments in the current bezpath to calculate the next bezpath segment's length.
11751173
next_segment_index += segment_count;
11761174

1177-
// Calculate the total length of the collected segments.
1178-
let total_length: f64 = lengths.iter().sum();
1179-
1180-
// Adjust the usable length by subtracting start and stop offsets.
1181-
let mut used_length = total_length - start_offset - stop_offset;
1182-
1183-
if used_length <= 0. {
1175+
let Some(mut sample_bezpath) = sample_points_on_bezpath(bezpath, spacing, start_offset, stop_offset, adaptive_spacing, current_bezpath_segments_length) else {
11841176
continue;
1185-
}
1186-
1187-
// Determine the number of points to generate along the path.
1188-
let count = if adaptive_spacing {
1189-
// Calculate point count to evenly distribute points while covering the entire path.
1190-
// With adaptive spacing, we widen or narrow the points as necessary to ensure the last point is always at the end of the path.
1191-
(used_length / spacing).round()
1192-
} else {
1193-
// Calculate point count based on exact spacing, which may not cover the entire path.
1194-
1195-
// Without adaptive spacing, we just evenly space the points at the exact specified spacing, usually falling short before the end of the path.
1196-
let count = (used_length / spacing + f64::EPSILON).floor();
1197-
used_length -= used_length % spacing;
1198-
count
11991177
};
12001178

1201-
// Skip if there are no points to generate.
1202-
if count < 1. {
1203-
continue;
1204-
}
1205-
// Generate points along the path based on calculated intervals.
1206-
let max_c = count as usize;
1207-
1208-
for c in 0..=max_c {
1209-
let fraction = c as f64 / count;
1210-
let current_length = fraction * used_length + start_offset;
1211-
let t = current_length / total_length;
1212-
let point = position_on_bezpath(&bezpath, t, true, Some(lengths));
1213-
1214-
if sample_bezpath.elements().is_empty() {
1215-
sample_bezpath.move_to(point)
1216-
} else {
1217-
sample_bezpath.line_to(point)
1218-
}
1219-
}
1220-
12211179
// Reverse the transformation applied to the bezpath as the `result` already has the transformation set.
12221180
sample_bezpath.apply_affine(Affine::new(vector_data_transform.to_cols_array()).inverse());
12231181

0 commit comments

Comments
 (0)