New nodes: Resample Points, Spline from Points (#1226)

* Create node (no implementation)

* Resampling - WIP

* use bezier::from_linear_dvec2

* Use from anchors instead of Bezier

* Tidy up anchor collection & subpath creation

* Add Spline from Points node (not implemented)

* Add spline from points node implementation

* Update resampling

* Update minimum density 0.01 -> 1.0

* Add a way to create a custom vector network

* Add spline from points node to spline tool

* Fix crash when no points

* Add anchor method to subpath

* Exact start and end point

* Fix compile errors from rebase

* Fix spline tool

* Rename 'Density' to 'Spacing'

* Fix transforms

* Only close subpaths with >1 anchor

* Fix compile

* Fix compile error

* Fix from points with many subpaths

* Fix new_cubic_spline crash with one point

* Rename to resample as polyline

* Fix div zero

* Fix missing file

* Fix resample

* Rename to resample points

---------

Co-authored-by: hypercube <0hypercube@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Chase 2023-08-30 20:21:39 +08:00 committed by GitHub
parent 3419e739af
commit 5acb2cff06
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 94 additions and 3 deletions

View file

@ -2,9 +2,9 @@ use super::style::{Fill, FillType, Gradient, GradientType, Stroke};
use super::VectorData;
use crate::{Color, Node};
use bezier_rs::Subpath;
use bezier_rs::{Subpath, SubpathTValue};
use glam::{DAffine2, DVec2};
use num_traits::Zero;
#[derive(Debug, Clone, Copy)]
pub struct SetFillNode<FillType, SolidColor, GradientType, Start, End, Transform, Positions> {
@ -147,3 +147,41 @@ fn generate_bounding_box(vector_data: VectorData) -> VectorData {
vector_data.transform.transform_point2(bounding_box[1]),
)])
}
#[derive(Debug, Clone, Copy)]
pub struct ResamplePoints<Spacing> {
spacing: Spacing,
}
#[node_macro::node_fn(ResamplePoints)]
fn resample_points(mut vector_data: VectorData, spacing: f64) -> VectorData {
for subpath in &mut vector_data.subpaths {
if subpath.is_empty() || spacing.is_zero() || !spacing.is_finite() {
continue;
}
subpath.apply_transform(vector_data.transform);
let length = subpath.length(None);
let rounded_count = (length / spacing).round();
if rounded_count >= 1. {
let new_anchors = (0..=rounded_count as usize).map(|c| subpath.evaluate(SubpathTValue::GlobalEuclidean(c as f64 / rounded_count)));
*subpath = Subpath::from_anchors(new_anchors, subpath.closed() && rounded_count as usize > 1);
}
subpath.apply_transform(vector_data.transform.inverse());
}
vector_data
}
#[derive(Debug, Clone, Copy)]
pub struct SplineFromPointsNode {}
#[node_macro::node_fn(SplineFromPointsNode)]
fn spline_from_points(mut vector_data: VectorData) -> VectorData {
for subpath in &mut vector_data.subpaths {
*subpath = Subpath::new_cubic_spline(subpath.anchors());
}
vector_data
}

View file

@ -634,6 +634,8 @@ fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstruct
register_node!(graphene_core::vector::RepeatNode<_, _>, input: VectorData, params: [DVec2, u32]),
register_node!(graphene_core::vector::BoundingBoxNode, input: VectorData, params: []),
register_node!(graphene_core::vector::CircularRepeatNode<_, _, _>, input: VectorData, params: [f32, f32, u32]),
register_node!(graphene_core::vector::ResamplePoints<_>, input: VectorData, params: [f64]),
register_node!(graphene_core::vector::SplineFromPointsNode, 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]),
register_node!(graphene_core::vector::generator_nodes::RectangleGenerator<_, _>, input: (), params: [f32, f32]),