Sample Points node: employ caching and deduplication (#1546)

Sample Points node: split out expensive computation so it can be deduped
This commit is contained in:
Keavon Chambers
2024-01-06 16:07:45 -08:00
committed by GitHub
parent 93aa10a76f
commit 121c1d2b9d
5 changed files with 75 additions and 9 deletions

View File

@@ -19,7 +19,7 @@ where
for<'a> <CachedNode as Node<'a, ()>>::Output: core::future::Future<Output = T> + 'a,
{
// TODO: This should return a reference to the cached cached_value
// but that requires a lot of lifetime magic <- This was suggested by copilot but is pretty acurate xD
// but that requires a lot of lifetime magic <- This was suggested by copilot but is pretty accurate xD
type Output = Pin<Box<dyn Future<Output = T> + 'i>>;
fn eval(&'i self, input: ()) -> Pin<Box<dyn Future<Output = T> + 'i>> {
Box::pin(async move {

View File

@@ -203,27 +203,39 @@ async fn copy_to_points<I: GraphicElementRendered + Default + ConcatElement + Tr
}
#[derive(Debug, Clone, Copy)]
pub struct SamplePoints<Spacing, StartOffset, StopOffset, AdaptiveSpacing> {
pub struct SamplePoints<VectorData, Spacing, StartOffset, StopOffset, AdaptiveSpacing, LengthsOfSegmentsOfSubpaths> {
vector_data: VectorData,
spacing: Spacing,
start_offset: StartOffset,
stop_offset: StopOffset,
adaptive_spacing: AdaptiveSpacing,
lengths_of_segments_of_subpaths: LengthsOfSegmentsOfSubpaths,
}
#[node_macro::node_fn(SamplePoints)]
fn sample_points(mut vector_data: VectorData, spacing: f32, start_offset: f32, stop_offset: f32, adaptive_spacing: bool) -> VectorData {
async fn sample_points<FV: Future<Output = VectorData>, FL: Future<Output = Vec<Vec<f64>>>>(
footprint: Footprint,
mut vector_data: impl Node<Footprint, Output = FV>,
spacing: f32,
start_offset: f32,
stop_offset: f32,
adaptive_spacing: bool,
lengths_of_segments_of_subpaths: impl Node<Footprint, Output = FL>,
) -> VectorData {
let mut vector_data = self.vector_data.eval(footprint).await;
let lengths_of_segments_of_subpaths = self.lengths_of_segments_of_subpaths.eval(footprint).await;
let spacing = spacing as f64;
let start_offset = start_offset as f64;
let stop_offset = stop_offset as f64;
for subpath in &mut vector_data.subpaths {
for (index, subpath) in &mut vector_data.subpaths.iter_mut().enumerate() {
if subpath.is_empty() || !spacing.is_finite() || spacing <= 0. {
continue;
}
subpath.apply_transform(vector_data.transform);
let segment_lengths = subpath.iter().map(|bezier| bezier.length(None)).collect::<Vec<f64>>();
let segment_lengths = &lengths_of_segments_of_subpaths[index];
let total_length: f64 = segment_lengths.iter().sum();
let mut used_length = total_length - start_offset - stop_offset;
@@ -265,7 +277,22 @@ fn sample_points(mut vector_data: VectorData, spacing: f32, start_offset: f32, s
}
#[derive(Debug, Clone, Copy)]
pub struct SplinesFromPointsNode {}
pub struct LengthsOfSegmentsOfSubpaths;
#[node_macro::node_fn(LengthsOfSegmentsOfSubpaths)]
fn lengths_of_segments_of_subpaths(mut vector_data: VectorData) -> Vec<Vec<f64>> {
vector_data
.subpaths
.iter_mut()
.map(|subpath| {
subpath.apply_transform(vector_data.transform);
subpath.iter().map(|bezier| bezier.length(None)).collect()
})
.collect()
}
#[derive(Debug, Clone, Copy)]
pub struct SplinesFromPointsNode;
#[node_macro::node_fn(SplinesFromPointsNode)]
fn splines_from_points(mut vector_data: VectorData) -> VectorData {

View File

@@ -734,7 +734,8 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
register_node!(graphene_std::raster::MandelbrotNode, input: Footprint, params: []),
async_node!(graphene_core::vector::CopyToPoints<_, _>, input: Footprint, output: VectorData, fn_params: [Footprint => VectorData, Footprint => VectorData]),
async_node!(graphene_core::vector::CopyToPoints<_, _>, input: Footprint, output: GraphicGroup, fn_params: [Footprint => VectorData, Footprint => GraphicGroup]),
register_node!(graphene_core::vector::SamplePoints<_, _, _, _>, input: VectorData, params: [f32, f32, f32, bool]),
async_node!(graphene_core::vector::SamplePoints<_, _, _, _, _, _>, input: Footprint, output: VectorData, fn_params: [Footprint => VectorData, () => f32, () => f32, () => f32, () => bool, Footprint => Vec<Vec<f64>>]),
register_node!(graphene_core::vector::LengthsOfSegmentsOfSubpaths, input: VectorData, params: []),
register_node!(graphene_core::vector::SplinesFromPointsNode, input: VectorData, params: []),
register_node!(graphene_core::vector::generator_nodes::CircleGenerator<_>, input: (), params: [f32]),
register_node!(graphene_core::vector::generator_nodes::EllipseGenerator<_, _>, input: (), params: [f32, f32]),