Prep gcore splitup 2: Vector extension traits (#2759)

* extension trait for `MergeByDistance::merge_by_distance_*`

* extension trait for `VectorData::append_bezpath`

* extension trait for `HandleId::set_relative_position`

* remove unreferenced rust files
This commit is contained in:
Firestar99 2025-06-27 12:30:12 +02:00 committed by GitHub
parent 2ddae98bcf
commit d581319ee8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 46 additions and 123 deletions

View file

@ -9,8 +9,8 @@ use crate::messages::tool::common_functionality::shape_editor::ShapeState;
use crate::messages::tool::utility_types::ToolType;
use glam::{DAffine2, DMat2, DVec2};
use graphene_std::renderer::Quad;
use graphene_std::vector::ManipulatorPointId;
use graphene_std::vector::VectorModificationType;
use graphene_std::vector::{HandleExt, ManipulatorPointId};
use graphene_std::vector::{HandleId, PointId};
use std::collections::{HashMap, VecDeque};
use std::f64::consts::PI;

View file

@ -12,7 +12,7 @@ use crate::messages::tool::common_functionality::utility_functions::is_visible_p
use crate::messages::tool::tool_messages::path_tool::{PathOverlayMode, PointSelectState};
use bezier_rs::{Bezier, BezierHandles, Subpath, TValue};
use glam::{DAffine2, DVec2};
use graphene_std::vector::{HandleId, SegmentId};
use graphene_std::vector::{HandleExt, HandleId, SegmentId};
use graphene_std::vector::{ManipulatorPointId, PointId, VectorData, VectorModificationType};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]

View file

@ -12,7 +12,7 @@ use bezier_rs::Bezier;
use glam::{DAffine2, DVec2};
use graphene_std::renderer::Quad;
use graphene_std::text::{FontCache, load_face};
use graphene_std::vector::{HandleId, ManipulatorPointId, PointId, SegmentId, VectorData, VectorModificationType};
use graphene_std::vector::{HandleExt, HandleId, ManipulatorPointId, PointId, SegmentId, VectorData, VectorModificationType};
/// 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(

View file

@ -18,7 +18,7 @@ use crate::messages::tool::common_functionality::snapping::{SnapCache, SnapCandi
use crate::messages::tool::common_functionality::utility_functions::{calculate_segment_angle, find_two_param_best_approximate};
use bezier_rs::{Bezier, TValue};
use graphene_std::renderer::Quad;
use graphene_std::vector::{HandleId, NoHashBuilder, SegmentId, VectorData};
use graphene_std::vector::{HandleExt, HandleId, NoHashBuilder, SegmentId, VectorData};
use graphene_std::vector::{ManipulatorPointId, PointId, VectorModificationType};
use std::vec;

View file

@ -3,9 +3,14 @@ use glam::{DAffine2, DVec2};
use petgraph::prelude::UnGraphMap;
use rustc_hash::FxHashSet;
impl VectorData {
pub trait MergeByDistanceExt {
/// Collapse all points with edges shorter than the specified distance
pub fn merge_by_distance_topological(&mut self, distance: f64) {
fn merge_by_distance_topological(&mut self, distance: f64);
fn merge_by_distance_spatial(&mut self, transform: DAffine2, distance: f64);
}
impl MergeByDistanceExt for VectorData {
fn merge_by_distance_topological(&mut self, distance: f64) {
// Treat self as an undirected graph
let indices = VectorDataIndex::build_from(self);
@ -95,7 +100,7 @@ impl VectorData {
self.point_domain.retain(&mut self.segment_domain, |id| !points_to_delete.contains(id));
}
pub fn merge_by_distance_spatial(&mut self, transform: DAffine2, distance: f64) {
fn merge_by_distance_spatial(&mut self, transform: DAffine2, distance: f64) {
let point_count = self.point_domain.positions().len();
// Find min x and y for grid cell normalization

View file

@ -1,6 +1,6 @@
pub mod bezpath_algorithms;
mod instance;
mod merge_by_distance;
pub mod instance;
pub mod merge_by_distance;
pub mod offset_subpath;
mod poisson_disk;
pub mod poisson_disk;
pub mod spline;

View file

@ -1,4 +1,4 @@
mod algorithms;
pub mod algorithms;
pub mod brush_stroke;
pub mod click_target;
pub mod generator_nodes;

View file

@ -186,11 +186,6 @@ impl VectorData {
self.point_domain.push(id, point.position);
}
/// Appends a Kurbo BezPath to the vector data.
pub fn append_bezpath(&mut self, bezpath: kurbo::BezPath) {
AppendBezpath::append_bezpath(self, bezpath);
}
/// Construct some new vector data from a single subpath with an identity transform and black fill.
pub fn from_subpath(subpath: impl Borrow<bezier_rs::Subpath<PointId>>) -> Self {
Self::from_subpaths([subpath], false)
@ -637,16 +632,6 @@ impl HandleId {
handle_position.map(|pos| (pos - anchor_position).length()).unwrap_or(f64::MAX)
}
/// Set the handle's position relative to the anchor which is the start anchor for the primary handle and end anchor for the end handle.
#[must_use]
pub fn set_relative_position(self, relative_position: DVec2) -> VectorModificationType {
let Self { ty, segment } = self;
match ty {
HandleType::Primary => VectorModificationType::SetPrimaryHandle { segment, relative_position },
HandleType::End => VectorModificationType::SetEndHandle { segment, relative_position },
}
}
/// Convert an end handle to the primary handle and a primary handle to an end handle. Note that the new handle may not exist (e.g. for a quadratic bézier).
#[must_use]
pub fn opposite(self) -> Self {

View file

@ -634,6 +634,33 @@ impl<'a> AppendBezpath<'a> {
}
}
pub trait VectorDataExt {
/// Appends a Kurbo BezPath to the vector data.
fn append_bezpath(&mut self, bezpath: BezPath);
}
impl VectorDataExt for VectorData {
fn append_bezpath(&mut self, bezpath: BezPath) {
AppendBezpath::append_bezpath(self, bezpath);
}
}
pub trait HandleExt {
/// Set the handle's position relative to the anchor which is the start anchor for the primary handle and end anchor for the end handle.
#[must_use]
fn set_relative_position(self, relative_position: DVec2) -> VectorModificationType;
}
impl HandleExt for HandleId {
fn set_relative_position(self, relative_position: DVec2) -> VectorModificationType {
let Self { ty, segment } = self;
match ty {
HandleType::Primary => VectorModificationType::SetPrimaryHandle { segment, relative_position },
HandleType::End => VectorModificationType::SetEndHandle { segment, relative_position },
}
}
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -3,12 +3,13 @@ use super::algorithms::offset_subpath::offset_subpath;
use super::algorithms::spline::{solve_spline_first_handle_closed, solve_spline_first_handle_open};
use super::misc::{CentroidType, point_to_dvec2};
use super::style::{Fill, Gradient, GradientStops, Stroke};
use super::{PointId, SegmentDomain, SegmentId, StrokeId, VectorData, VectorDataTable};
use super::{PointId, SegmentDomain, SegmentId, StrokeId, VectorData, VectorDataExt, VectorDataTable};
use crate::instances::{Instance, InstanceMut, Instances};
use crate::raster_types::{CPU, GPU, RasterDataTable};
use crate::registry::types::{Angle, Fraction, IntegerCount, Length, Multiplier, Percentage, PixelLength, PixelSize, SeedValue};
use crate::renderer::GraphicElementRendered;
use crate::transform::{Footprint, ReferencePoint, Transform};
use crate::vector::algorithms::merge_by_distance::MergeByDistanceExt;
use crate::vector::misc::{MergeByDistanceAlgorithm, PointSpacingType};
use crate::vector::style::{PaintOrder, StrokeAlign, StrokeCap, StrokeJoin};
use crate::vector::{FillId, PointDomain, RegionId};

View file

@ -1,51 +0,0 @@
use parking_lot::RawRwLock;
use std::any::Any;
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::iter::{self, Sum};
use std::marker::PhantomData;
use storage_map::{StorageMap, StorageMapGuard};
/// Caches the output of a given Node and acts as a proxy
/// Automatically resets if it receives different input
pub struct SmartCacheNode<'n, 'c, NODE: Node + 'c> {
node: &'n NODE,
map: StorageMap<RawRwLock, HashMap<u64, CacheNode<'n, 'c, NODE>>>,
}
impl<'n: 'c, 'c, NODE: Node + 'c> Node for SmartCacheNode<'n, 'c, NODE>
where
for<'a> NODE::Input<'a>: Hash,
{
type Input<'a>
= NODE::Input<'a>
where
Self: 'a,
'c: 'a;
type Output<'a>
= StorageMapGuard<'a, RawRwLock, CacheNode<'n, 'c, NODE>>
where
Self: 'a,
'c: 'a;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
let mut hasher = DefaultHasher::new();
input.borrow().hash(&mut hasher);
let hash = hasher.finish();
self.map.get_or_create_with(&hash, || {
trace!("Creating new cache node");
CacheNode::new(self.node)
})
}
}
impl<'n, 'c, NODE: Node> SmartCacheNode<'n, 'c, NODE> {
pub fn clear(&'n mut self) {
self.map = StorageMap::default();
}
pub fn new(node: &'n NODE) -> SmartCacheNode<'n, 'c, NODE> {
SmartCacheNode { node, map: StorageMap::default() }
}
}

View file

@ -1,45 +0,0 @@
use core::marker::PhantomData;
pub use graphene_core::value::*;
use graphene_core::Node;
use dyn_any::DynAny;
pub struct AnyRefNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>);
impl<'n, N: Node<'n, Output = &'n O>, O: DynAny<'n> + 'n> Node<'n> for AnyRefNode<'n, N> {
fn eval(&'n self) -> &'n (dyn DynAny<'n>) {
let value: &O = self.0.eval();
value
}
}
impl<'n, N: Node<'n, Output = &'n O>, O: 'n + ?Sized> AnyRefNode<'n, N> {
pub fn new(n: N) -> AnyRefNode<'n, N> {
AnyRefNode(n, PhantomData)
}
}
pub struct StorageNode<'n>(&'n dyn Node<'n, Output = &'n dyn DynAny<'n>>);
impl<'n> Node<'n> for StorageNode<'n> {
fn eval(&'n self) -> &'n (dyn DynAny<'n>) {
self.0.eval()
}
}
impl<'n> StorageNode<'n> {
pub fn new<N: Node<'n, Output = &'n dyn DynAny<'n>>>(n: &'n N) -> StorageNode<'n> {
StorageNode(n)
}
}
#[derive(Default)]
pub struct AnyValueNode<'n, T>(T, PhantomData<&'n ()>);
impl<'n, T: 'n + DynAny<'n>> Node<'n> for AnyValueNode<'n, T> {
fn eval(&'n self) -> &'n dyn DynAny<'n> {
&self.0
}
}
impl<'n, T> AnyValueNode<'n, T> {
pub const fn new(value: T) -> AnyValueNode<'n, T> {
AnyValueNode(value, PhantomData)
}
}

View file

@ -1,6 +1,7 @@
use bezier_rs::{ManipulatorGroup, Subpath};
use glam::{DAffine2, DVec2};
use graphene_core::instances::{Instance, InstanceRef};
use graphene_core::vector::algorithms::merge_by_distance::MergeByDistanceExt;
use graphene_core::vector::misc::BooleanOperation;
use graphene_core::vector::style::Fill;
pub use graphene_core::vector::*;