From 20af96c1d9ff15d6f7e363191b0db7724b8ea364 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Tue, 18 Aug 2026 12:34:34 -0700 Subject: [PATCH] Remove remnant dead code across the Subpath, Vector, and editor geometry API surfaces (#4454) --- .../document/document_message_handler.rs | 8 +- .../graph_operation_message.rs | 9 +- .../graph_operation_message_handler.rs | 7 -- .../graph_modification_utils.rs | 10 -- .../shapes/shape_utility.rs | 8 +- .../common_functionality/utility_functions.rs | 48 +------- node-graph/graph-craft/src/document/value.rs | 2 - .../libraries/core-types/src/math/rect.rs | 7 -- node-graph/libraries/vector-types/src/lib.rs | 2 +- .../libraries/vector-types/src/math/mod.rs | 19 ---- .../vector-types/src/subpath/core.rs | 103 ++---------------- .../vector-types/src/subpath/lookup.rs | 2 +- .../vector-types/src/subpath/manipulators.rs | 26 ----- .../libraries/vector-types/src/subpath/mod.rs | 19 +--- .../vector-types/src/subpath/structs.rs | 35 ------ .../vector-types/src/subpath/transform.rs | 52 +-------- .../vector/algorithms/bezpath_algorithms.rs | 14 --- .../src/vector/algorithms/util.rs | 6 - .../src/vector/vector_attributes.rs | 101 ----------------- .../src/vector/vector_modification.rs | 13 +-- .../vector-types/src/vector/vector_types.rs | 60 +++------- node-graph/nodes/gstd/src/lib.rs | 2 +- node-graph/nodes/repeat/src/repeat_nodes.rs | 16 +-- .../nodes/vector/src/generator_nodes.rs | 6 +- node-graph/nodes/vector/src/vector_nodes.rs | 16 +-- 25 files changed, 58 insertions(+), 533 deletions(-) diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index bd76c26bbe..aa1e4c1e93 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -1836,7 +1836,8 @@ impl DocumentMessageHandler { let document_to_viewport = self.navigation_handler.calculate_offset_transform(viewport.center_in_viewport_space().into(), &self.document_ptz); viewport_polygon.apply_transform(document_to_viewport.inverse()); - ClickXRayIter::new(&self.network_interface, XRayTarget::Polygon(viewport_polygon)) + let polygon = BezPath::from_path_segments(viewport_polygon.iter_closed()); + ClickXRayIter::new(&self.network_interface, XRayTarget::Path(polygon)) } /// Runs an intersection test with all layers and a viewport space subpath; ignoring artboards @@ -3791,7 +3792,6 @@ enum XRayTarget { Point(DVec2), Quad(Quad), Path(BezPath), - Polygon(Subpath), } /// The result for the [`ClickXRayIter`] on the layer @@ -3891,10 +3891,6 @@ impl<'a> ClickXRayIter<'a> { } XRayTarget::Quad(quad) => self.check_layer_area_target(click_targets, clip, layer, quad_to_kurbo(*quad), transform), XRayTarget::Path(path) => self.check_layer_area_target(click_targets, clip, layer, path.clone(), transform), - XRayTarget::Polygon(polygon) => { - let polygon = BezPath::from_path_segments(polygon.iter_closed()); - self.check_layer_area_target(click_targets, clip, layer, polygon, transform) - } } } } diff --git a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs index ae83a96c0f..c82922e424 100644 --- a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs +++ b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message.rs @@ -8,10 +8,9 @@ use graphene_std::Color; use graphene_std::brush::brush_stroke::BrushStroke; use graphene_std::raster::BlendMode; use graphene_std::raster_types::Image; -use graphene_std::subpath::Subpath; use graphene_std::text::{Font, TypesettingConfig}; use graphene_std::vector::style::{GradientForm, GradientHueDirection, GradientInterpolation, GradientSettings, GradientSpace, GradientSpread, PaintOrder, Stroke}; -use graphene_std::vector::{Gradient, PointId, VectorModificationType}; +use graphene_std::vector::{Gradient, VectorModificationType}; #[impl_message(Message, DocumentMessage, GraphOperation)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] @@ -162,12 +161,6 @@ pub enum GraphOperationMessage { parent: LayerNodeIdentifier, insert_index: usize, }, - NewVectorLayer { - id: NodeId, - subpaths: Vec>, - parent: LayerNodeIdentifier, - insert_index: usize, - }, NewTextLayer { id: NodeId, text: String, diff --git a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs index 0aa20e1d4e..108ddb1b91 100644 --- a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs +++ b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs @@ -363,13 +363,6 @@ impl MessageHandler> for network_interface.move_layer_to_stack(layer, parent, insert_index, &[]); responses.add(NodeGraphMessage::RunDocumentGraph); } - GraphOperationMessage::NewVectorLayer { id, subpaths, parent, insert_index } => { - let mut modify_inputs = ModifyInputsContext::new(network_interface, responses); - let layer = modify_inputs.create_layer(id); - modify_inputs.insert_vector(subpaths, layer, true, true, true); - network_interface.move_layer_to_stack(layer, parent, insert_index, &[]); - responses.add(NodeGraphMessage::RunDocumentGraph); - } GraphOperationMessage::NewTextLayer { id, text, diff --git a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs index e66ef4f783..598e493935 100644 --- a/editor/src/messages/tool/common_functionality/graph_modification_utils.rs +++ b/editor/src/messages/tool/common_functionality/graph_modification_utils.rs @@ -10,7 +10,6 @@ use graph_craft::document::{DocumentNode, NodeId, NodeInput}; use graphene_std::Color; use graphene_std::raster::BlendMode; use graphene_std::raster_types::Image; -use graphene_std::subpath::Subpath; use graphene_std::text::{Font, TypesettingConfig}; use graphene_std::vector::misc::ManipulatorPointId; use graphene_std::vector::style::{FillChoice, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, initial_gradient_transform_for_bounding_box}; @@ -207,15 +206,6 @@ pub fn merge_points(document: &DocumentMessageHandler, layer: LayerNodeIdentifie responses.add(GraphOperationMessage::Vector { layer, modification_type }); } -/// Create a new vector layer. -pub fn new_vector_layer(subpaths: Vec>, id: NodeId, parent: LayerNodeIdentifier, responses: &mut VecDeque) -> LayerNodeIdentifier { - let insert_index = 0; - responses.add(GraphOperationMessage::NewVectorLayer { id, subpaths, parent, insert_index }); - responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![id] }); - - LayerNodeIdentifier::new_unchecked(id) -} - /// Create a new bitmap layer. pub fn new_image_layer(image: Image, id: NodeId, parent: LayerNodeIdentifier, responses: &mut VecDeque) -> LayerNodeIdentifier { let insert_index = 0; diff --git a/editor/src/messages/tool/common_functionality/shapes/shape_utility.rs b/editor/src/messages/tool/common_functionality/shapes/shape_utility.rs index c2413ef35d..c1c2bd4525 100644 --- a/editor/src/messages/tool/common_functionality/shapes/shape_utility.rs +++ b/editor/src/messages/tool/common_functionality/shapes/shape_utility.rs @@ -16,7 +16,7 @@ use crate::messages::tool::utility_types::*; use glam::{DAffine2, DMat2, DVec2}; use graph_craft::document::NodeInput; use graph_craft::document::value::TaggedValue; -use graphene_std::subpath::{self, Subpath}; +use graphene_std::subpath::Subpath; use graphene_std::vector::click_target::ClickTargetType; use graphene_std::vector::misc::{ArcType, GridType, SpiralType, dvec2_to_point}; use kurbo::{BezPath, PathEl, Shape}; @@ -479,11 +479,7 @@ pub fn arc_outline(layer: Option, document: &DocumentMessag radius, start_angle / 360. * std::f64::consts::TAU, sweep_angle / 360. * std::f64::consts::TAU, - match arc_type { - ArcType::Open => subpath::ArcType::Open, - ArcType::Closed => subpath::ArcType::Closed, - ArcType::PieSlice => subpath::ArcType::PieSlice, - }, + arc_type, ))]; let viewport = document.metadata().transform_to_viewport(layer); diff --git a/editor/src/messages/tool/common_functionality/utility_functions.rs b/editor/src/messages/tool/common_functionality/utility_functions.rs index 8deeb60218..a4ea05db1d 100644 --- a/editor/src/messages/tool/common_functionality/utility_functions.rs +++ b/editor/src/messages/tool/common_functionality/utility_functions.rs @@ -13,11 +13,10 @@ use crate::messages::tool::utility_types::ToolType; use glam::{DAffine2, DVec2}; use graph_craft::document::value::TaggedValue; use graphene_std::renderer::Quad; -use graphene_std::subpath::{Bezier, BezierHandles}; use graphene_std::vector::algorithms::bezpath_algorithms::pathseg_compute_lookup_table; use graphene_std::vector::misc::{HandleId, ManipulatorPointId, dvec2_to_point}; use graphene_std::vector::{HandleExt, PointId, SegmentId, Vector, VectorModification, VectorModificationType}; -use kurbo::{CubicBez, DEFAULT_ACCURACY, Line, ParamCurve, PathSeg, Point, QuadBez, Shape}; +use kurbo::{CubicBez, DEFAULT_ACCURACY, ParamCurve, PathSeg, Point, Shape}; /// Determines if a path should be extended. Goal in viewport space. Returns the path and if it is extending from the start, if applicable. pub fn should_extend(document: &DocumentMessageHandler, goal: DVec2, tolerance: f64, layers: impl Iterator) -> Option<(LayerNodeIdentifier, PointId, DVec2)> { @@ -196,51 +195,6 @@ pub fn is_visible_point( } } -pub fn is_intersecting(bezier: Bezier, quad: [DVec2; 2], transform: DAffine2) -> bool { - let to_layerspace = transform.inverse(); - let quad = [to_layerspace.transform_point2(quad[0]), to_layerspace.transform_point2(quad[1])]; - let start = Point::new(bezier.start.x, bezier.start.y); - let end = Point::new(bezier.end.x, bezier.end.y); - let segment = match bezier.handles { - BezierHandles::Cubic { handle_start, handle_end } => { - let p1 = Point::new(handle_start.x, handle_start.y); - let p2 = Point::new(handle_end.x, handle_end.y); - PathSeg::Cubic(CubicBez::new(start, p1, p2, end)) - } - BezierHandles::Quadratic { handle } => { - let p1 = Point::new(handle.x, handle.y); - PathSeg::Quad(QuadBez::new(start, p1, end)) - } - BezierHandles::Linear => PathSeg::Line(Line::new(start, end)), - }; - - // Create a list of all the sides - let sides = [ - Line::new((quad[0].x, quad[0].y), (quad[1].x, quad[0].y)), - Line::new((quad[0].x, quad[0].y), (quad[0].x, quad[1].y)), - Line::new((quad[1].x, quad[1].y), (quad[1].x, quad[0].y)), - Line::new((quad[1].x, quad[1].y), (quad[0].x, quad[1].y)), - ]; - - let mut is_intersecting = false; - for line in sides { - let intersections = segment.intersect_line(line); - let mut intersects = false; - for intersection in intersections { - if intersection.line_t <= 1. && intersection.line_t >= 0. && intersection.segment_t <= 1. && intersection.segment_t >= 0. { - // There is a valid intersection point - intersects = true; - break; - } - } - if intersects { - is_intersecting = true; - break; - } - } - is_intersecting -} - #[allow(clippy::too_many_arguments)] pub fn resize_bounds( document: &DocumentMessageHandler, diff --git a/node-graph/graph-craft/src/document/value.rs b/node-graph/graph-craft/src/document/value.rs index 2d526123ba..d717a2f3ff 100644 --- a/node-graph/graph-craft/src/document/value.rs +++ b/node-graph/graph-craft/src/document/value.rs @@ -390,7 +390,6 @@ macro_rules! tagged_value { Type::Generic(_) => None, Type::Concrete(concrete_type) => { let name = concrete_type.name.as_ref(); - // TODO: Add default implementations for types such as TaggedValue::Subpaths, and use the defaults here and in document_node_types // Tries using the default for the tagged value type. If it not implemented, then uses the default used in document_node_types. If it is not used there, then TaggedValue::None is returned. if name == std::any::type_name::<()>() { return Some(TaggedValue::None) } if name == std::any::type_name::() { return Some(TaggedValue::GradientRamp(GradientRamp::default())) } @@ -671,7 +670,6 @@ impl TaggedValue { Type::Concrete(concrete_type) => { let ty = concrete_type.id?; use std::any::TypeId; - // TODO: Add default implementations for types such as TaggedValue::Subpaths, and use the defaults here and in document_node_types // Tries using the default for the tagged value type. If it not implemented, then uses the default used in document_node_types. If it is not used there, then TaggedValue::None is returned. let ty = match () { () if ty == TypeId::of::<()>() => TaggedValue::None, diff --git a/node-graph/libraries/core-types/src/math/rect.rs b/node-graph/libraries/core-types/src/math/rect.rs index 4998eddb3a..d4ff900528 100644 --- a/node-graph/libraries/core-types/src/math/rect.rs +++ b/node-graph/libraries/core-types/src/math/rect.rs @@ -36,13 +36,6 @@ impl Rect { bounds } - /// Get all the edges in the rect. - #[must_use] - pub fn edges(&self) -> [[DVec2; 2]; 4] { - let corners = [self[0], DVec2::new(self[0].x, self[1].y), self[1], DVec2::new(self[1].y, self[0].x)]; - [[corners[0], corners[1]], [corners[1], corners[2]], [corners[2], corners[3]], [corners[3], corners[0]]] - } - /// Gets the center of a rect #[must_use] pub fn center(&self) -> DVec2 { diff --git a/node-graph/libraries/vector-types/src/lib.rs b/node-graph/libraries/vector-types/src/lib.rs index d15d4b6a73..14e04184f4 100644 --- a/node-graph/libraries/vector-types/src/lib.rs +++ b/node-graph/libraries/vector-types/src/lib.rs @@ -9,7 +9,7 @@ pub mod vector; // Re-export commonly used types at the crate root pub use core_types as gcore; pub use gradient::{Gradient, GradientForm, GradientHueDirection, GradientInterpolation, GradientRamp, GradientSettings, GradientSpace, GradientSpread, GradientStop}; -pub use math::{QuadExt, RectExt}; +pub use math::QuadExt; pub use subpath::Subpath; pub use vector::Vector; pub use vector::reference_point::ReferencePoint; diff --git a/node-graph/libraries/vector-types/src/math/mod.rs b/node-graph/libraries/vector-types/src/math/mod.rs index 3919c71f81..7b1b1dc4c5 100644 --- a/node-graph/libraries/vector-types/src/math/mod.rs +++ b/node-graph/libraries/vector-types/src/math/mod.rs @@ -1,32 +1,13 @@ -use crate::subpath::Bezier; use crate::vector::misc::dvec2_to_point; use core_types::math::quad::Quad; -use core_types::math::rect::Rect; use kurbo::{Line, PathSeg}; pub trait QuadExt { - /// Get all the edges in the rect as linear bezier curves - fn bezier_lines(&self) -> impl Iterator + '_; fn to_lines(&self) -> impl Iterator; } impl QuadExt for Quad { - fn bezier_lines(&self) -> impl Iterator + '_ { - self.all_edges().into_iter().map(|[start, end]| Bezier::from_linear_dvec2(start, end)) - } - fn to_lines(&self) -> impl Iterator { self.all_edges().into_iter().map(|[start, end]| PathSeg::Line(Line::new(dvec2_to_point(start), dvec2_to_point(end)))) } } - -pub trait RectExt { - /// Get all the edges in the quad as linear bezier curves - fn bezier_lines(&self) -> impl Iterator + '_; -} - -impl RectExt for Rect { - fn bezier_lines(&self) -> impl Iterator + '_ { - self.edges().into_iter().map(|[start, end]| Bezier::from_linear_dvec2(start, end)) - } -} diff --git a/node-graph/libraries/vector-types/src/subpath/core.rs b/node-graph/libraries/vector-types/src/subpath/core.rs index 1a5a12caa0..cf81481ed7 100644 --- a/node-graph/libraries/vector-types/src/subpath/core.rs +++ b/node-graph/libraries/vector-types/src/subpath/core.rs @@ -1,6 +1,5 @@ -use super::consts::*; use super::*; -use crate::vector::misc::{SpiralType, point_to_dvec2}; +use crate::vector::misc::{ArcType, SpiralType, point_to_dvec2}; use glam::DVec2; use kurbo::PathSeg; use std::f64::consts::TAU; @@ -36,55 +35,6 @@ impl Subpath { Self { manipulator_groups, closed } } - /// Create a `Subpath` consisting of 2 manipulator groups from a `Bezier`. - pub fn from_bezier(segment: PathSeg) -> Self { - let PathSegPoints { p0, p1, p2, p3 } = pathseg_points(segment); - Subpath::new(vec![ManipulatorGroup::new(p0, None, p1), ManipulatorGroup::new(p3, p2, None)], false) - } - - /// Creates a subpath from a slice of [Bezier]. When two consecutive Beziers do not share an end and start point, this function - /// resolves the discrepancy by simply taking the start-point of the second Bezier as the anchor of the Manipulator Group. - pub fn from_beziers(beziers: &[PathSeg], closed: bool) -> Self { - assert!(!closed || beziers.len() > 1, "A closed Subpath must contain at least 1 Bezier."); - if beziers.is_empty() { - return Subpath::new(vec![], closed); - } - - let beziers: Vec<_> = beziers.iter().map(|b| pathseg_points(*b)).collect(); - - let first = beziers.first().unwrap(); - let mut manipulator_groups = vec![ManipulatorGroup { - anchor: first.p0, - in_handle: None, - out_handle: first.p1, - id: PointId::new(), - }]; - let mut inner_groups: Vec> = beziers - .windows(2) - .map(|bezier_pair| ManipulatorGroup { - anchor: bezier_pair[1].p0, - in_handle: bezier_pair[0].p2, - out_handle: bezier_pair[1].p1, - id: PointId::new(), - }) - .collect::>>(); - manipulator_groups.append(&mut inner_groups); - - let last = beziers.last().unwrap(); - if !closed { - manipulator_groups.push(ManipulatorGroup { - anchor: last.p3, - in_handle: last.p2, - out_handle: None, - id: PointId::new(), - }); - return Subpath::new(manipulator_groups, false); - } - - manipulator_groups[0].in_handle = last.p2; - Subpath::new(manipulator_groups, true) - } - /// Returns true if the `Subpath` contains no [ManipulatorGroup]. pub fn is_empty(&self) -> bool { self.manipulator_groups.is_empty() @@ -95,23 +45,6 @@ impl Subpath { self.manipulator_groups.len() } - /// Returns the number of segments contained within the `Subpath`. - pub fn len_segments(&self) -> usize { - let mut number_of_curves = self.len(); - if !self.closed && number_of_curves > 0 { - number_of_curves -= 1 - } - number_of_curves - } - - /// Returns a copy of the bezier segment at the given segment index, if this segment exists. - pub fn get_segment(&self, segment_index: usize) -> Option { - if segment_index >= self.len_segments() { - return None; - } - Some(self[segment_index].to_bezier(&self[(segment_index + 1) % self.len()])) - } - /// Returns an iterator of the [Bezier]s along the `Subpath`. pub fn iter(&self) -> SubpathIter<'_, PointId> { SubpathIter { @@ -140,22 +73,6 @@ impl Subpath { &mut self.manipulator_groups } - /// Returns a vector of all the anchors (DVec2) for this `Subpath`. - pub fn anchors(&self) -> Vec { - self.manipulator_groups().iter().map(|group| group.anchor).collect() - } - - /// Returns if the Subpath is equivalent to a single point. - pub fn is_point(&self) -> bool { - if self.is_empty() { - return false; - } - let point = self.manipulator_groups[0].anchor; - self.manipulator_groups - .iter() - .all(|manipulator_group| manipulator_group.anchor.abs_diff_eq(point, MAX_ABSOLUTE_DIFFERENCE)) - } - pub fn from_anchors(anchor_positions: impl IntoIterator, closed: bool) -> Self { Self::new(anchor_positions.into_iter().map(|anchor| ManipulatorGroup::new_anchor(anchor)).collect(), closed) } @@ -406,7 +323,7 @@ pub fn spiral_point(theta: f64, a: f64, b: f64, spiral_type: SpiralType) -> DVec } /// Returns the tangent direction at angle `theta` for the given spiral type. -pub fn spiral_tangent(theta: f64, a: f64, b: f64, spiral_type: SpiralType) -> DVec2 { +fn spiral_tangent(theta: f64, a: f64, b: f64, spiral_type: SpiralType) -> DVec2 { match spiral_type { SpiralType::Archimedean => archimedean_spiral_tangent(theta, a, b), SpiralType::Logarithmic => log_spiral_tangent(theta, a, b), @@ -414,7 +331,7 @@ pub fn spiral_tangent(theta: f64, a: f64, b: f64, spiral_type: SpiralType) -> DV } /// Computes arc length between two angles for the given spiral type. -pub fn spiral_arc_length(theta_start: f64, theta_end: f64, a: f64, b: f64, spiral_type: SpiralType) -> f64 { +fn spiral_arc_length(theta_start: f64, theta_end: f64, a: f64, b: f64, spiral_type: SpiralType) -> f64 { match spiral_type { SpiralType::Archimedean => archimedean_spiral_arc_length(theta_start, theta_end, a, b), SpiralType::Logarithmic => log_spiral_arc_length(theta_start, theta_end, a, b), @@ -422,19 +339,19 @@ pub fn spiral_arc_length(theta_start: f64, theta_end: f64, a: f64, b: f64, spira } /// Returns a point on a logarithmic spiral at angle `theta`. -pub fn log_spiral_point(theta: f64, a: f64, b: f64) -> DVec2 { +fn log_spiral_point(theta: f64, a: f64, b: f64) -> DVec2 { let r = a * (b * theta).exp(); // a * e^(bθ) DVec2::new(r * theta.cos(), -r * theta.sin()) } /// Computes arc length along a logarithmic spiral between two angles. -pub fn log_spiral_arc_length(theta_start: f64, theta_end: f64, a: f64, b: f64) -> f64 { +fn log_spiral_arc_length(theta_start: f64, theta_end: f64, a: f64, b: f64) -> f64 { let factor = (1. + b * b).sqrt(); (a / b) * factor * ((b * theta_end).exp() - (b * theta_start).exp()) } /// Returns the tangent direction of a logarithmic spiral at angle `theta`. -pub fn log_spiral_tangent(theta: f64, a: f64, b: f64) -> DVec2 { +fn log_spiral_tangent(theta: f64, a: f64, b: f64) -> DVec2 { let r = a * (b * theta).exp(); let dx = r * (b * theta.cos() - theta.sin()); let dy = r * (b * theta.sin() + theta.cos()); @@ -443,13 +360,13 @@ pub fn log_spiral_tangent(theta: f64, a: f64, b: f64) -> DVec2 { } /// Returns a point on an Archimedean spiral at angle `theta`. -pub fn archimedean_spiral_point(theta: f64, a: f64, b: f64) -> DVec2 { +fn archimedean_spiral_point(theta: f64, a: f64, b: f64) -> DVec2 { let r = a + b * theta; DVec2::new(r * theta.cos(), -r * theta.sin()) } /// Returns the tangent direction of an Archimedean spiral at angle `theta`. -pub fn archimedean_spiral_tangent(theta: f64, a: f64, b: f64) -> DVec2 { +fn archimedean_spiral_tangent(theta: f64, a: f64, b: f64) -> DVec2 { let r = a + b * theta; let dx = b * theta.cos() - r * theta.sin(); let dy = b * theta.sin() + r * theta.cos(); @@ -457,12 +374,12 @@ pub fn archimedean_spiral_tangent(theta: f64, a: f64, b: f64) -> DVec2 { } /// Computes arc length along an Archimedean spiral between two angles. -pub fn archimedean_spiral_arc_length(theta_start: f64, theta_end: f64, a: f64, b: f64) -> f64 { +fn archimedean_spiral_arc_length(theta_start: f64, theta_end: f64, a: f64, b: f64) -> f64 { archimedean_spiral_arc_length_origin(theta_end, a, b) - archimedean_spiral_arc_length_origin(theta_start, a, b) } /// Computes arc length from origin to a point on Archimedean spiral at angle `theta`. -pub fn archimedean_spiral_arc_length_origin(theta: f64, a: f64, b: f64) -> f64 { +fn archimedean_spiral_arc_length_origin(theta: f64, a: f64, b: f64) -> f64 { let r = a + b * theta; let sqrt_term = (r * r + b * b).sqrt(); (r * sqrt_term + b * b * ((r + sqrt_term).ln())) / (2. * b) diff --git a/node-graph/libraries/vector-types/src/subpath/lookup.rs b/node-graph/libraries/vector-types/src/subpath/lookup.rs index b3dc49e222..c9ea7c9a69 100644 --- a/node-graph/libraries/vector-types/src/subpath/lookup.rs +++ b/node-graph/libraries/vector-types/src/subpath/lookup.rs @@ -14,7 +14,7 @@ impl Subpath { /// If the comparison condition is not satisfied, the function takes the larger `t`-value of the two /// /// **NOTE**: if an intersection were to occur within an `error` distance away from an anchor point, the algorithm will filter that intersection out. - pub fn all_self_intersections(&self, accuracy: Option, minimum_separation: Option) -> Vec<(usize, f64)> { + fn all_self_intersections(&self, accuracy: Option, minimum_separation: Option) -> Vec<(usize, f64)> { let mut intersections_vec = Vec::new(); let err = accuracy.unwrap_or(MAX_ABSOLUTE_DIFFERENCE); let num_curves = self.len(); diff --git a/node-graph/libraries/vector-types/src/subpath/manipulators.rs b/node-graph/libraries/vector-types/src/subpath/manipulators.rs index 6dad21d6d1..94ef54e55c 100644 --- a/node-graph/libraries/vector-types/src/subpath/manipulators.rs +++ b/node-graph/libraries/vector-types/src/subpath/manipulators.rs @@ -13,27 +13,6 @@ impl Subpath { self.closed = new_closed; } - /// Access a [ManipulatorGroup] from a PointId. - pub fn manipulator_from_id(&self, id: PointId) -> Option<&ManipulatorGroup> { - self.manipulator_groups.iter().find(|manipulator_group| manipulator_group.id == id) - } - - /// Access a mutable [ManipulatorGroup] from a PointId. - pub fn manipulator_mut_from_id(&mut self, id: PointId) -> Option<&mut ManipulatorGroup> { - self.manipulator_groups.iter_mut().find(|manipulator_group| manipulator_group.id == id) - } - - /// Access the index of a [ManipulatorGroup] from a PointId. - pub fn manipulator_index_from_id(&self, id: PointId) -> Option { - self.manipulator_groups.iter().position(|manipulator_group| manipulator_group.id == id) - } - - /// Insert a manipulator group at an index. - pub fn insert_manipulator_group(&mut self, index: usize, group: ManipulatorGroup) { - assert!(group.is_finite(), "Inserting non finite manipulator group"); - self.manipulator_groups.insert(index, group) - } - /// Push a manipulator group to the end. pub fn push_manipulator_group(&mut self, group: ManipulatorGroup) { assert!(group.is_finite(), "Pushing non finite manipulator group"); @@ -44,9 +23,4 @@ impl Subpath { pub fn last_manipulator_group_mut(&mut self) -> Option<&mut ManipulatorGroup> { self.manipulator_groups.last_mut() } - - /// Remove a manipulator group at an index. - pub fn remove_manipulator_group(&mut self, index: usize) -> ManipulatorGroup { - self.manipulator_groups.remove(index) - } } diff --git a/node-graph/libraries/vector-types/src/subpath/mod.rs b/node-graph/libraries/vector-types/src/subpath/mod.rs index 80ea7cd241..2ca1010483 100644 --- a/node-graph/libraries/vector-types/src/subpath/mod.rs +++ b/node-graph/libraries/vector-types/src/subpath/mod.rs @@ -9,7 +9,6 @@ mod transform; pub use core::*; use kurbo::PathSeg; use std::fmt::{Debug, Formatter, Result}; -use std::ops::{Index, IndexMut}; pub use structs::*; /// Structure used to represent a path composed of [Bezier] curves. @@ -27,22 +26,6 @@ pub struct SubpathIter<'a, PointId: Identifier> { is_always_closed: bool, } -impl Index for Subpath { - type Output = ManipulatorGroup; - - fn index(&self, index: usize) -> &Self::Output { - assert!(index < self.len(), "Index out of bounds in trait Index of SubPath."); - &self.manipulator_groups[index] - } -} - -impl IndexMut for Subpath { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - assert!(index < self.len(), "Index out of bounds in trait IndexMut of SubPath."); - &mut self.manipulator_groups[index] - } -} - impl Iterator for SubpathIter<'_, PointId> { type Item = PathSeg; @@ -60,7 +43,7 @@ impl Iterator for SubpathIter<'_, PointId> { let end_index = (self.index + 1) % self.subpath.len(); self.index += 1; - Some(self.subpath[start_index].to_bezier(&self.subpath[end_index])) + Some(self.subpath.manipulator_groups[start_index].to_bezier(&self.subpath.manipulator_groups[end_index])) } } diff --git a/node-graph/libraries/vector-types/src/subpath/structs.rs b/node-graph/libraries/vector-types/src/subpath/structs.rs index 11d72b0e2b..d3c99e147a 100644 --- a/node-graph/libraries/vector-types/src/subpath/structs.rs +++ b/node-graph/libraries/vector-types/src/subpath/structs.rs @@ -77,37 +77,6 @@ impl ManipulatorGroup { pub fn is_finite(&self) -> bool { self.anchor.is_finite() && self.in_handle.is_none_or(|handle| handle.is_finite()) && self.out_handle.is_none_or(|handle| handle.is_finite()) } - - /// Reverse directions of handles - pub fn flip(mut self) -> Self { - std::mem::swap(&mut self.in_handle, &mut self.out_handle); - self - } - - pub fn has_in_handle(&self) -> bool { - self.in_handle.map(|handle| Self::has_handle(self.anchor, handle)).unwrap_or(false) - } - - pub fn has_out_handle(&self) -> bool { - self.out_handle.map(|handle| Self::has_handle(self.anchor, handle)).unwrap_or(false) - } - - fn has_handle(anchor: DVec2, handle: DVec2) -> bool { - !((handle.x - anchor.x).abs() < f64::EPSILON && (handle.y - anchor.y).abs() < f64::EPSILON) - } -} - -#[derive(Copy, Clone)] -pub enum AppendType { - IgnoreStart, - SmoothJoin(f64), -} - -#[derive(Copy, Clone, Eq, PartialEq, Hash, graphene_hash::CacheHash)] -pub enum ArcType { - Open, - Closed, - PieSlice, } /// Representation of the handle point(s) in a bezier segment. @@ -130,10 +99,6 @@ pub enum BezierHandles { } impl BezierHandles { - pub fn is_cubic(&self) -> bool { - matches!(self, Self::Cubic { .. }) - } - pub fn is_finite(&self) -> bool { match self { BezierHandles::Linear => true, diff --git a/node-graph/libraries/vector-types/src/subpath/transform.rs b/node-graph/libraries/vector-types/src/subpath/transform.rs index c4476a7388..2e839e70e0 100644 --- a/node-graph/libraries/vector-types/src/subpath/transform.rs +++ b/node-graph/libraries/vector-types/src/subpath/transform.rs @@ -1,62 +1,12 @@ use super::structs::Identifier; use super::*; -use glam::{DAffine2, DVec2}; +use glam::DAffine2; -/// Functionality that transforms Subpaths, such as split, reduce, offset, etc. impl Subpath { - /// Returns [ManipulatorGroup]s with a reversed winding order. - fn reverse_manipulator_groups(manipulator_groups: &[ManipulatorGroup]) -> Vec> { - manipulator_groups - .iter() - .rev() - .map(|group| ManipulatorGroup { - anchor: group.anchor, - in_handle: group.out_handle, - out_handle: group.in_handle, - id: PointId::new(), - }) - .collect::>>() - } - - /// Returns a [Subpath] with a reversed winding order. - /// Note that a reversed closed subpath will start on the same manipulator group and simply wind the other direction - pub fn reverse(&self) -> Subpath { - let mut reversed = Subpath::reverse_manipulator_groups(self.manipulator_groups()); - if self.closed { - reversed.rotate_right(1); - }; - Subpath { - manipulator_groups: reversed, - closed: self.closed, - } - } - /// Apply a transformation to all of the [ManipulatorGroup]s in the [Subpath]. pub fn apply_transform(&mut self, affine_transform: DAffine2) { for manipulator_group in &mut self.manipulator_groups { manipulator_group.apply_transform(affine_transform); } } - - /// Returns a subpath that results from rotating this subpath around the origin by the given angle (in radians). - pub fn rotate(&self, angle: f64) -> Subpath { - let mut rotated_subpath = self.clone(); - - let affine_transform: DAffine2 = DAffine2::from_angle(angle); - rotated_subpath.apply_transform(affine_transform); - - rotated_subpath - } - - /// Returns a subpath that results from rotating this subpath around the provided point by the given angle (in radians). - pub fn rotate_about_point(&self, angle: f64, pivot: DVec2) -> Subpath { - // Translate before and after the rotation to account for the pivot - let translate: DAffine2 = DAffine2::from_translation(pivot); - let rotate: DAffine2 = DAffine2::from_angle(angle); - let translate_inverse = translate.inverse(); - - let mut rotated_subpath = self.clone(); - rotated_subpath.apply_transform(translate * rotate * translate_inverse); - rotated_subpath - } } diff --git a/node-graph/libraries/vector-types/src/vector/algorithms/bezpath_algorithms.rs b/node-graph/libraries/vector-types/src/vector/algorithms/bezpath_algorithms.rs index b09fe4ea52..0b7eed83c4 100644 --- a/node-graph/libraries/vector-types/src/vector/algorithms/bezpath_algorithms.rs +++ b/node-graph/libraries/vector-types/src/vector/algorithms/bezpath_algorithms.rs @@ -1,7 +1,6 @@ use super::intersection::bezpath_intersections; use super::poisson_disk::poisson_disk_sample; use super::util::pathseg_tangent; -use crate::vector::algorithms::offset_subpath::MAX_ABSOLUTE_DIFFERENCE; use crate::vector::misc::{PointSpacingType, dvec2_to_point, point_to_dvec2}; use core_types::math::polynomial::pathseg_to_parametric_polynomial; use glam::{DMat2, DVec2}; @@ -415,19 +414,6 @@ pub fn poisson_disk_points(bezpath_index: usize, bezpaths: &[(BezPath, Rect)], s poisson_disk_sample(offset, width, height, separation_disk_diameter, point_in_shape_checker, line_intersect_shape_checker, rng) } -/// Returns true if the Bezier curve is equivalent to a line. -/// -/// **NOTE**: This is different from simply checking if the segment is [`PathSeg::Line`] or [`PathSeg::Quad`] or [`PathSeg::Cubic`]. Bezier curve can also be a line if the control points are colinear to the start and end points. Therefore if the handles exceed the start and end point, it will still be considered as a line. -pub fn is_linear(segment: &PathSeg) -> bool { - let is_colinear = |a: Point, b: Point, c: Point| -> bool { ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)).abs() < MAX_ABSOLUTE_DIFFERENCE }; - - match *segment { - PathSeg::Line(_) => true, - PathSeg::Quad(QuadBez { p0, p1, p2 }) => is_colinear(p0, p1, p2), - PathSeg::Cubic(CubicBez { p0, p1, p2, p3 }) => is_colinear(p0, p1, p3) && is_colinear(p0, p2, p3), - } -} - // TODO: If a segment curls back on itself tightly enough it could intersect again at the portion that should be trimmed. This could cause the Subpaths to be clipped // TODO: at the incorrect location. This can be avoided by first trimming the two Subpaths at any extrema, effectively ignoring loopbacks. /// Helper function to clip overlap of two intersecting open BezPaths. Returns an Option because intersections may not exist for certain arrangements and distances. diff --git a/node-graph/libraries/vector-types/src/vector/algorithms/util.rs b/node-graph/libraries/vector-types/src/vector/algorithms/util.rs index 0c2eacf7ce..67d754c0c2 100644 --- a/node-graph/libraries/vector-types/src/vector/algorithms/util.rs +++ b/node-graph/libraries/vector-types/src/vector/algorithms/util.rs @@ -14,12 +14,6 @@ pub fn pathseg_tangent(segment: PathSeg, t: f64) -> DVec2 { DVec2::new(tangent.x, tangent.y) } -// Compare two f64s with some maximum absolute difference to account for floating point errors -#[cfg(test)] -pub fn compare_f64s(f1: f64, f2: f64) -> bool { - (f1 - f2).abs() < super::contants::MAX_ABSOLUTE_DIFFERENCE -} - /// Compare points by allowing some maximum absolute difference to account for floating point errors #[cfg(test)] pub fn compare_points(p1: kurbo::Point, p2: kurbo::Point) -> bool { diff --git a/node-graph/libraries/vector-types/src/vector/vector_attributes.rs b/node-graph/libraries/vector-types/src/vector/vector_attributes.rs index 63f9b87650..8ffa23b0b5 100644 --- a/node-graph/libraries/vector-types/src/vector/vector_attributes.rs +++ b/node-graph/libraries/vector-types/src/vector/vector_attributes.rs @@ -93,11 +93,6 @@ impl PointDomain { Self { id: Vec::new(), position: Vec::new() } } - pub fn clear(&mut self) { - self.id.clear(); - self.position.clear(); - } - #[inline(always)] pub fn reserve(&mut self, additional: usize) { self.id.reserve(additional); @@ -229,14 +224,6 @@ impl SegmentDomain { } } - pub fn clear(&mut self) { - self.id.clear(); - self.start_point.clear(); - self.end_point.clear(); - self.handles.clear(); - self.stroke.clear(); - } - #[inline(always)] pub fn reserve(&mut self, additional: usize) { self.id.reserve(additional); @@ -401,16 +388,6 @@ impl SegmentDomain { self.id.iter().position(|&check_id| check_id == id) } - fn resolve_range(&self, range: &std::ops::RangeInclusive) -> Option> { - match (self.id_to_index(*range.start()), self.id_to_index(*range.end())) { - (Some(start), Some(end)) if start.max(end) < self.handles.len().min(self.id.len()).min(self.start_point.len()).min(self.end_point.len()) => Some(start..=end), - _ => { - warn!("Resolving range with invalid id"); - None - } - } - } - pub fn concat(&mut self, other: &Self, transform: DAffine2, id_map: &IdMap) { self.id.extend(other.id.iter().map(|id| *id_map.segment_map.get(id).unwrap_or(id))); self.start_point.extend(other.start_point.iter().map(|&index| id_map.point_offset + index)); @@ -609,12 +586,6 @@ impl RegionDomain { } } - pub fn clear(&mut self) { - self.id.clear(); - self.segment_range.clear(); - self.fill.clear(); - } - #[inline(always)] pub fn reserve(&mut self, additional: usize) { self.id.reserve(additional); @@ -759,10 +730,6 @@ pub struct FoundSubpath { } impl FoundSubpath { - pub fn new(segments: Vec) -> Self { - Self { edges: segments } - } - pub fn endpoints(&self) -> Option<(&HalfEdge, &HalfEdge)> { match (self.edges.first(), self.edges.last()) { (Some(first), Some(last)) => Some((first, last)), @@ -774,21 +741,6 @@ impl FoundSubpath { self.edges.push(segment); } - pub fn insert(&mut self, index: usize, segment: HalfEdge) { - self.edges.insert(index, segment); - } - - pub fn extend(&mut self, segments: impl IntoIterator) { - self.edges.extend(segments); - } - - pub fn splice(&mut self, range: std::ops::Range, replace_with: I) - where - I: IntoIterator, - { - self.edges.splice(range, replace_with); - } - pub fn is_closed(&self) -> bool { match (self.edges.first(), self.edges.last()) { (Some(first), Some(last)) => first.start == last.end, @@ -1088,49 +1040,6 @@ impl Vector { Some(Subpath::new(manipulators_list, closed)) } - /// Construct a [`Bezier`] curve for each region, skipping invalid regions. - pub fn region_manipulator_groups(&self) -> impl Iterator>)> + '_ { - self.region_domain - .id - .iter() - .zip(&self.region_domain.segment_range) - .filter_map(|(&id, segment_range)| self.segment_domain.resolve_range(segment_range).map(|range| (id, range))) - .filter_map(|(id, range)| { - let segments_iter = self - .segment_domain - .handles - .get(range.clone())? - .iter() - .zip(self.segment_domain.start_point.get(range.clone())?) - .zip(self.segment_domain.end_point.get(range)?) - .map(|((&handles, &start), &end)| (handles, start, end)); - - let mut manipulator_groups = Vec::new(); - let mut in_handle = None; - - for segment in segments_iter { - let (handles, start_point_index, _end_point_index) = segment; - let start_point_id = self.point_domain.id[start_point_index]; - let start_point = self.point_domain.position[start_point_index]; - - let (manipulator_group, next_in_handle) = match handles { - BezierHandles::Linear => (ManipulatorGroup::new_with_id(start_point, in_handle, None, start_point_id), None), - BezierHandles::Quadratic { handle } => (ManipulatorGroup::new_with_id(start_point, in_handle, Some(handle), start_point_id), None), - BezierHandles::Cubic { handle_start, handle_end } => (ManipulatorGroup::new_with_id(start_point, in_handle, Some(handle_start), start_point_id), Some(handle_end)), - }; - - in_handle = next_in_handle; - manipulator_groups.push(manipulator_group); - } - - if let Some(first) = manipulator_groups.first_mut() { - first.in_handle = in_handle; - } - - Some((id, manipulator_groups)) - }) - } - pub fn build_stroke_path_iter(&self) -> StrokePathIter<'_> { let mut points = vec![StrokePathIterPointMetadata::default(); self.point_domain.ids().len()]; for (segment_index, (&start, &end)) in self.segment_domain.start_point.iter().zip(&self.segment_domain.end_point).enumerate() { @@ -1190,16 +1099,6 @@ impl Vector { }) } - /// Construct an iterator [`ManipulatorGroup`] for stroke. - pub fn manipulator_groups(&self) -> impl Iterator> + '_ { - self.stroke_bezier_paths().flat_map(|mut path| std::mem::take(path.manipulator_groups_mut())) - } - - pub fn manipulator_group_id(&self, id: impl Into) -> Option> { - let id = id.into(); - self.manipulator_groups().find(|manipulators| manipulators.id == id) - } - pub fn transform(&mut self, transform: DAffine2) { self.point_domain.transform(transform); self.segment_domain.transform(transform); diff --git a/node-graph/libraries/vector-types/src/vector/vector_modification.rs b/node-graph/libraries/vector-types/src/vector/vector_modification.rs index eb67bc1368..ce7a1110d9 100644 --- a/node-graph/libraries/vector-types/src/vector/vector_modification.rs +++ b/node-graph/libraries/vector-types/src/vector/vector_modification.rs @@ -806,11 +806,9 @@ impl HandleExt for HandleId { #[cfg(test)] mod tests { - use kurbo::{PathSeg, QuadBez}; - use super::*; - use crate::subpath::{Bezier, Subpath}; + use crate::subpath::{Bezier, ManipulatorGroup, Subpath}; #[test] fn modify_new() { @@ -828,10 +826,11 @@ mod tests { let subpaths = [ Subpath::new_ellipse(DVec2::ZERO, DVec2::ONE), Subpath::new_rectangle(DVec2::NEG_ONE, DVec2::ZERO), - Subpath::from_beziers( - &[ - PathSeg::Quad(QuadBez::new(Point::new(0., 0.), Point::new(5., 10.), Point::new(10., 0.))), - PathSeg::Quad(QuadBez::new(Point::new(10., 0.), Point::new(15., 10.), Point::new(20., 0.))), + Subpath::new( + vec![ + ManipulatorGroup::new(DVec2::new(0., 0.), None, None), + ManipulatorGroup::new(DVec2::new(10., 0.), Some(DVec2::new(5., 10.)), None), + ManipulatorGroup::new(DVec2::new(20., 0.), Some(DVec2::new(15., 10.)), None), ], false, ), diff --git a/node-graph/libraries/vector-types/src/vector/vector_types.rs b/node-graph/libraries/vector-types/src/vector/vector_types.rs index 196199a996..73fe19f614 100644 --- a/node-graph/libraries/vector-types/src/vector/vector_types.rs +++ b/node-graph/libraries/vector-types/src/vector/vector_types.rs @@ -2,7 +2,6 @@ use super::misc::dvec2_to_point; use super::style::{Stroke, StrokeAlign, StrokeCap, StrokeJoin}; pub use super::vector_attributes::*; use crate::subpath::{BezierHandles, ManipulatorGroup, Subpath}; -use crate::vector::click_target::{ClickTargetType, FreePoint}; use crate::vector::misc::{HandleId, ManipulatorPointId}; use crate::vector::vector_modification::VectorExt; use core::borrow::Borrow; @@ -135,18 +134,6 @@ impl Vector { } } - pub fn append_free_point(&mut self, point: &FreePoint, preserve_id: bool) { - let mut point_id = self.point_domain.next_id(); - - // Use the current point ID if it's not already in the domain, otherwise generate a new one - let id = if preserve_id && !self.point_domain.ids().contains(&point.id) { - point.id - } else { - point_id.next_id() - }; - self.point_domain.push(id, point.position); - } - /// Construct some new vector path from a single subpath with an identity transform and black fill. pub fn from_subpath(subpath: impl Borrow>) -> Self { Self::from_subpaths([subpath], false) @@ -170,24 +157,6 @@ impl Vector { vector } - pub fn from_target_types(target_types: impl IntoIterator>, preserve_id: bool) -> Self { - let mut vector = Self::default(); - - for target_type in target_types.into_iter() { - match target_type.borrow() { - ClickTargetType::Subpath(subpath) => vector.append_subpath(subpath, preserve_id), - ClickTargetType::FreePoint(point) => vector.append_free_point(point, preserve_id), - ClickTargetType::CompoundPath(subpaths) => { - for subpath in subpaths { - vector.append_subpath(subpath, preserve_id); - } - } - } - } - - vector - } - /// Compute the bounding boxes of the bezpaths without any transform pub fn bounding_box_rect(&self) -> Option { self.bounding_box_with_transform_rect(DAffine2::IDENTITY) @@ -321,13 +290,6 @@ impl Vector { [bounds_min, bounds_max] } - /// Compute the pivot of the layer in layerspace (the coordinates of the subpaths) - pub fn layerspace_pivot(&self, normalized_pivot: DVec2) -> DVec2 { - let [bounds_min, bounds_max] = self.nonzero_bounding_box(); - let bounds_size = bounds_max - bounds_min; - bounds_min + bounds_size * normalized_pivot - } - pub fn start_point(&self) -> impl Iterator + '_ { self.segment_domain.start_point().iter().map(|&index| self.point_domain.ids()[index]) } @@ -362,11 +324,6 @@ impl Vector { self.segment_domain.segment_end_from_id(segment).map(|index| self.point_domain.ids()[index]) } - /// Returns an array for the start and end points of a segment. - pub fn points_from_id(&self, segment: SegmentId) -> Option<[PointId; 2]> { - self.segment_domain.points_from_id(segment).map(|val| val.map(|index| self.point_domain.ids()[index])) - } - /// Attempts to find another point in the segment that is not the one passed in. pub fn other_point(&self, segment: SegmentId, current: PointId) -> Option { let index = self.point_domain.resolve_id(current); @@ -595,7 +552,13 @@ mod tests { #[test] fn construct_open_subpath() { let bezier = PathSeg::Cubic(CubicBez::new(Point::ZERO, Point::new(-1., -1.), Point::new(1., 1.), Point::new(1., 0.))); - let subpath = Subpath::from_bezier(bezier); + let subpath = Subpath::new( + vec![ + ManipulatorGroup::new(DVec2::ZERO, None, Some(DVec2::new(-1., -1.))), + ManipulatorGroup::new(DVec2::new(1., 0.), Some(DVec2::new(1., 1.)), None), + ], + false, + ); let vector: Vector = Vector::from_subpath(&subpath); assert_eq!(vector.point_domain.ids().len(), 2); let bezier_paths = vector.segment_iter().map(|(_, bezier, _, _)| bezier).collect::>(); @@ -607,8 +570,13 @@ mod tests { #[test] fn construct_many_subpath() { - let curve = PathSeg::Cubic(CubicBez::new(Point::ZERO, Point::new(-1., -1.), Point::new(1., 1.), Point::new(1., 0.))); - let curve = Subpath::from_bezier(curve); + let curve = Subpath::new( + vec![ + ManipulatorGroup::new(DVec2::ZERO, None, Some(DVec2::new(-1., -1.))), + ManipulatorGroup::new(DVec2::new(1., 0.), Some(DVec2::new(1., 1.)), None), + ], + false, + ); let circle = Subpath::new_ellipse(DVec2::NEG_ONE, DVec2::ONE); let vector: Vector = Vector::from_subpaths([&curve, &circle], false); diff --git a/node-graph/nodes/gstd/src/lib.rs b/node-graph/nodes/gstd/src/lib.rs index 3761fef610..adeefb23b2 100644 --- a/node-graph/nodes/gstd/src/lib.rs +++ b/node-graph/nodes/gstd/src/lib.rs @@ -74,7 +74,7 @@ pub mod math { pub use core_types::math::quad; pub mod math_ext { - pub use vector_types::{QuadExt, RectExt}; + pub use vector_types::QuadExt; } } diff --git a/node-graph/nodes/repeat/src/repeat_nodes.rs b/node-graph/nodes/repeat/src/repeat_nodes.rs index c3b87556de..d7de1fa62c 100644 --- a/node-graph/nodes/repeat/src/repeat_nodes.rs +++ b/node-graph/nodes/repeat/src/repeat_nodes.rs @@ -323,8 +323,8 @@ mod test { .await; let vector_list = List::new_from_item(vector_nodes::combine_paths(Footprint::default(), List::new_from_element(Graphic::VectorList(repeated))).await); let vector = vector_list.element(0).unwrap(); - assert_eq!(vector.region_manipulator_groups().count(), 3); - for (index, (_, manipulator_groups)) in vector.region_manipulator_groups().enumerate() { + assert_eq!(vector.stroke_manipulator_groups().count(), 3); + for (index, (manipulator_groups, _)) in vector.stroke_manipulator_groups().enumerate() { assert!((manipulator_groups[0].anchor - direction * index as f64 / (count - 1) as f64).length() < 1e-5); } } @@ -342,9 +342,9 @@ mod test { .await; let vector_list = List::new_from_item(vector_nodes::combine_paths(Footprint::default(), List::new_from_element(Graphic::VectorList(repeated))).await); let vector = vector_list.element(0).unwrap(); - assert_eq!(vector.region_manipulator_groups().count(), 1); + assert_eq!(vector.stroke_manipulator_groups().count(), 1); - let (_, manipulator_groups) = vector.region_manipulator_groups().next().unwrap(); + let (manipulator_groups, _) = vector.stroke_manipulator_groups().next().unwrap(); let anchor = manipulator_groups[0].anchor; assert!(anchor.length() < 1e-5, "Expected the single copy to be untransformed, found anchor {anchor}"); } @@ -364,8 +364,8 @@ mod test { .await; let vector_list = List::new_from_item(vector_nodes::combine_paths(Footprint::default(), List::new_from_element(Graphic::VectorList(repeated))).await); let vector = vector_list.element(0).unwrap(); - assert_eq!(vector.region_manipulator_groups().count(), 8); - for (index, (_, manipulator_groups)) in vector.region_manipulator_groups().enumerate() { + assert_eq!(vector.stroke_manipulator_groups().count(), 8); + for (index, (manipulator_groups, _)) in vector.stroke_manipulator_groups().enumerate() { assert!((manipulator_groups[0].anchor - direction * index as f64 / (count - 1) as f64).length() < 1e-5); } } @@ -383,9 +383,9 @@ mod test { .await; let vector_list = List::new_from_item(vector_nodes::combine_paths(Footprint::default(), List::new_from_element(Graphic::VectorList(repeated))).await); let vector = vector_list.element(0).unwrap(); - assert_eq!(vector.region_manipulator_groups().count(), 8); + assert_eq!(vector.stroke_manipulator_groups().count(), 8); - for (index, (_, manipulator_groups)) in vector.region_manipulator_groups().enumerate() { + for (index, (manipulator_groups, _)) in vector.stroke_manipulator_groups().enumerate() { let expected_angle = (index as f64 + 1.) * 45.; let center = (manipulator_groups[0].anchor + manipulator_groups[2].anchor) / 2.; diff --git a/node-graph/nodes/vector/src/generator_nodes.rs b/node-graph/nodes/vector/src/generator_nodes.rs index c0fa20ba97..3099521252 100644 --- a/node-graph/nodes/vector/src/generator_nodes.rs +++ b/node-graph/nodes/vector/src/generator_nodes.rs @@ -42,11 +42,7 @@ fn arc( radius, start_angle / 360. * std::f64::consts::TAU, sweep_angle / 360. * std::f64::consts::TAU, - match arc_type { - ArcType::Open => subpath::ArcType::Open, - ArcType::Closed => subpath::ArcType::Closed, - ArcType::PieSlice => subpath::ArcType::PieSlice, - }, + arc_type, ))) } diff --git a/node-graph/nodes/vector/src/vector_nodes.rs b/node-graph/nodes/vector/src/vector_nodes.rs index 06f9516440..bbc65de14e 100644 --- a/node-graph/nodes/vector/src/vector_nodes.rs +++ b/node-graph/nodes/vector/src/vector_nodes.rs @@ -3776,12 +3776,12 @@ mod test { async fn bounding_box() { let bounding_box = super::bounding_box((), Item::new_from_element(Vector::from_bezpath(Rect::new(-1., -1., 1., 1.).to_path(DEFAULT_ACCURACY)))).await; let bounding_box = bounding_box.element(); - assert_eq!(bounding_box.region_manipulator_groups().count(), 1); + assert_eq!(bounding_box.stroke_manipulator_groups().count(), 1); let manipulator_groups_anchors = bounding_box - .region_manipulator_groups() + .stroke_manipulator_groups() .next() .unwrap() - .1 + .0 .iter() .map(|manipulators| manipulators.anchor) .collect::>(); @@ -3794,12 +3794,12 @@ mod test { square.with_attribute_mut_or_default(ATTR_TRANSFORM, 0, |t: &mut DAffine2| *t *= DAffine2::from_angle(std::f64::consts::FRAC_PI_4)); let bounding_box = BoundingBoxNodeMapped { content: FutureWrapperNode(square) }.eval(Footprint::default()).await; let bounding_box = bounding_box.element(0).unwrap(); - assert_eq!(bounding_box.region_manipulator_groups().count(), 1); + assert_eq!(bounding_box.stroke_manipulator_groups().count(), 1); let manipulator_groups_anchors = bounding_box - .region_manipulator_groups() + .stroke_manipulator_groups() .next() .unwrap() - .1 + .0 .iter() .map(|manipulators| manipulators.anchor) .collect::>(); @@ -3831,9 +3831,9 @@ mod test { let combined = List::new_from_item(super::combine_paths(Footprint::default(), List::new_from_element(Graphic::VectorList(copy_to_points))).await); let combined_copy_to_points = combined.element(0).unwrap(); - assert_eq!(combined_copy_to_points.region_manipulator_groups().count(), expected_points.len()); + assert_eq!(combined_copy_to_points.stroke_manipulator_groups().count(), expected_points.len()); - for (index, (_, manipulator_groups)) in combined_copy_to_points.region_manipulator_groups().enumerate() { + for (index, (manipulator_groups, _)) in combined_copy_to_points.stroke_manipulator_groups().enumerate() { let offset = expected_points[index]; let manipulator_groups_anchors = manipulator_groups.iter().map(|manipulators| manipulators.anchor).collect::>(); assert_eq!(