diff --git a/iOverlay/Cargo.toml b/iOverlay/Cargo.toml index eb563da..06b9a2f 100644 --- a/iOverlay/Cargo.toml +++ b/iOverlay/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "i_overlay" -version = "5.0.0" +version = "6.0.0" authors = ["Nail Sharipov "] edition = "2024" rust-version = "1.88" @@ -12,8 +12,8 @@ readme = "README.md" categories = ["algorithms", "graphics", "science::geo", "mathematics", "no-std"] [dependencies] -i_float = { version = "~1.16.0" } -i_shape = { version = "~1.18.0" } +i_float = { version = "^2.0.0" } +i_shape = { version = "^2.0.0" } i_tree = { version = "^0.18.0" } i_key_sort = { version = "^0.10.1" } @@ -38,5 +38,5 @@ serde_json = "^1.0" rand = { version = "~0.10", features = ["alloc"] } #i_float = { path = "../../iFloat", features = ["serde"] } #i_shape = { path = "../../iShape", features = ["serde"] } -i_float = { version = "~1.16.0", features = ["serde"] } -i_shape = { version = "~1.18.0", features = ["serde"] } +i_float = { version = "^2.0.0", features = ["serde"] } +i_shape = { version = "~2.0.0", features = ["serde"] } diff --git a/iOverlay/src/float/clip.rs b/iOverlay/src/float/clip.rs index e0c8ab0..9f83a6d 100644 --- a/iOverlay/src/float/clip.rs +++ b/iOverlay/src/float/clip.rs @@ -4,15 +4,13 @@ use crate::float::scale::FixedScaleOverlayError; use crate::float::string_overlay::FloatStringOverlay; use crate::string::clip::ClipRule; use i_float::float::compatible::FloatPointCompatible; -use i_float::float::number::FloatNumber; use i_shape::base::data::Paths; use i_shape::source::resource::ShapeResource; -pub trait FloatClip +pub trait FloatClip where - R: ShapeResource, - P: FloatPointCompatible, - T: FloatNumber, + R: ShapeResource

, + P: FloatPointCompatible, { /// Clips paths according to the specified build and clip rules. /// - `resource`: A clipping shape. @@ -44,7 +42,7 @@ where source: &R, fill_rule: FillRule, clip_rule: ClipRule, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError>; /// Clips paths according to the specified build and clip rules. @@ -86,7 +84,7 @@ where fill_rule: FillRule, clip_rule: ClipRule, solver: Solver, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError>; } @@ -146,12 +144,11 @@ mod tests { } } -impl FloatClip for R1 +impl FloatClip for R1 where - R0: ShapeResource, - R1: ShapeResource, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

, + R1: ShapeResource

, + P: FloatPointCompatible, { #[inline] fn clip_by(&self, resource: &R0, fill_rule: FillRule, clip_rule: ClipRule) -> Paths

{ @@ -176,7 +173,7 @@ where resource: &R0, fill_rule: FillRule, clip_rule: ClipRule, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError> { self.clip_by_fixed_scale_with_solver(resource, fill_rule, clip_rule, Default::default(), scale) } @@ -188,7 +185,7 @@ where fill_rule: FillRule, clip_rule: ClipRule, solver: Solver, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError> { Ok( FloatStringOverlay::with_shape_and_string_fixed_scale(resource, self, scale)? diff --git a/iOverlay/src/float/graph.rs b/iOverlay/src/float/graph.rs index 85d7965..a0209db 100644 --- a/iOverlay/src/float/graph.rs +++ b/iOverlay/src/float/graph.rs @@ -7,7 +7,6 @@ use crate::core::graph::OverlayGraph; use crate::core::overlay_rule::OverlayRule; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; -use i_float::float::number::FloatNumber; use i_shape::base::data::Shapes; use i_shape::float::adapter::ShapesToFloat; use i_shape::float::despike::DeSpikeContour; @@ -16,15 +15,15 @@ use i_shape::float::simple::SimplifyContour; /// The `FloatOverlayGraph` struct represents an overlay graph with floating point precision, /// providing methods to extract geometric shapes from the graph after applying boolean operations. /// [More information](https://ishape-rust.github.io/iShape-js/overlay/overlay_graph/overlay_graph.html) about Overlay Graph. -pub struct FloatOverlayGraph<'a, P: FloatPointCompatible, T: FloatNumber> { +pub struct FloatOverlayGraph<'a, P: FloatPointCompatible> { pub graph: OverlayGraph<'a>, - pub adapter: FloatPointAdapter, + pub adapter: FloatPointAdapter

, clean_result: bool, } -impl<'a, P: FloatPointCompatible, T: FloatNumber> FloatOverlayGraph<'a, P, T> { +impl<'a, P: FloatPointCompatible> FloatOverlayGraph<'a, P> { #[inline] - pub(crate) fn new(graph: OverlayGraph<'a>, adapter: FloatPointAdapter, clean_result: bool) -> Self { + pub(crate) fn new(graph: OverlayGraph<'a>, adapter: FloatPointAdapter

, clean_result: bool) -> Self { Self { graph, adapter, diff --git a/iOverlay/src/float/overlay.rs b/iOverlay/src/float/overlay.rs index cd1f67b..cf383e6 100644 --- a/iOverlay/src/float/overlay.rs +++ b/iOverlay/src/float/overlay.rs @@ -42,13 +42,13 @@ pub struct OverlayOptions { } /// This struct is essential for describing and uploading the geometry or shapes required to construct an `FloatOverlay`. It prepares the necessary data for boolean operations. -pub struct FloatOverlay, T: FloatNumber> { +pub struct FloatOverlay { pub(super) overlay: Overlay, pub(super) clean_result: bool, - pub(super) adapter: FloatPointAdapter, + pub(super) adapter: FloatPointAdapter

, } -impl, T: FloatNumber> FloatOverlay { +impl FloatOverlay

{ /// Constructs a new `FloatOverlay`, a builder for overlaying geometric shapes /// by converting float-based geometry to integer space, using a pre-configured adapter. /// @@ -57,7 +57,7 @@ impl, T: FloatNumber> FloatOverlay { /// - `capacity`: Initial capacity for storing segments, ideally matching the total number of /// segments for efficient memory allocation. #[inline] - pub fn with_adapter(adapter: FloatPointAdapter, capacity: usize) -> Self { + pub fn with_adapter(adapter: FloatPointAdapter

, capacity: usize) -> Self { Self::new_custom(adapter, Default::default(), Default::default(), capacity) } @@ -72,8 +72,8 @@ impl, T: FloatNumber> FloatOverlay { /// segments for efficient memory allocation. #[inline] pub fn new_custom( - adapter: FloatPointAdapter, - options: OverlayOptions, + adapter: FloatPointAdapter

, + options: OverlayOptions, solver: Solver, capacity: usize, ) -> Self { @@ -93,7 +93,7 @@ impl, T: FloatNumber> FloatOverlay { /// - `capacity`: Initial capacity for storing segments, ideally matching the total number of /// segments for efficient memory allocation. #[inline] - pub fn new_empty(options: OverlayOptions, solver: Solver, capacity: usize) -> Self { + pub fn new_empty(options: OverlayOptions, solver: Solver, capacity: usize) -> Self { let clean_result = options.clean_result; let adapter = FloatPointAdapter::new(FloatRect::zero()); let overlay = Overlay::new_custom(capacity, options.int_default(), solver); @@ -113,10 +113,8 @@ impl, T: FloatNumber> FloatOverlay { /// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours. pub fn with_subj_and_clip(subj: &R0, clip: &R1) -> Self where - R0: ShapeResource + ?Sized, - R1: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

+ ?Sized, + R1: ShapeResource

+ ?Sized, { let iter = subj.iter_paths().chain(clip.iter_paths()).flatten(); let adapter = FloatPointAdapter::with_iter(iter); @@ -140,14 +138,12 @@ impl, T: FloatNumber> FloatOverlay { pub fn with_subj_and_clip_custom( subj: &R0, clip: &R1, - options: OverlayOptions, + options: OverlayOptions, solver: Solver, ) -> Self where - R0: ShapeResource + ?Sized, - R1: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

+ ?Sized, + R1: ShapeResource

+ ?Sized, { let iter = subj.iter_paths().chain(clip.iter_paths()).flatten(); let adapter = FloatPointAdapter::with_iter(iter); @@ -167,9 +163,7 @@ impl, T: FloatNumber> FloatOverlay { /// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours. pub fn with_subj(subj: &R) -> Self where - R: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R: ShapeResource

+ ?Sized, { let iter = subj.iter_paths().flatten(); let adapter = FloatPointAdapter::with_iter(iter); @@ -186,11 +180,9 @@ impl, T: FloatNumber> FloatOverlay { /// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours. /// - `options`: Adjust custom behavior. /// - `solver`: Type of solver to use. - pub fn with_subj_custom(subj: &R, options: OverlayOptions, solver: Solver) -> Self + pub fn with_subj_custom(subj: &R, options: OverlayOptions, solver: Solver) -> Self where - R: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R: ShapeResource

+ ?Sized, { let iter = subj.iter_paths().flatten(); let adapter = FloatPointAdapter::with_iter(iter); @@ -207,7 +199,7 @@ impl, T: FloatNumber> FloatOverlay { /// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours. /// - `shape_type`: Specifies the role of the added paths in the overlay operation, either as `Subject` or `Clip`. #[inline] - pub fn unsafe_add_source + ?Sized>( + pub fn unsafe_add_source + ?Sized>( mut self, resource: &R, shape_type: ShapeType, @@ -233,7 +225,7 @@ impl, T: FloatNumber> FloatOverlay { } #[inline] - fn add_source + ?Sized>(&mut self, resource: &R, shape_type: ShapeType) { + fn add_source + ?Sized>(&mut self, resource: &R, shape_type: ShapeType) { for contour in resource.iter_paths() { self.overlay .add_path_iter(contour.iter().map(|p| self.adapter.float_to_int(p)), shape_type); @@ -249,10 +241,8 @@ impl, T: FloatNumber> FloatOverlay { /// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours. pub fn reinit_with_subj_and_clip(&mut self, subj: &R0, clip: &R1) where - R0: ShapeResource + ?Sized, - R1: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

+ ?Sized, + R1: ShapeResource

+ ?Sized, { self.clear(); @@ -270,9 +260,7 @@ impl, T: FloatNumber> FloatOverlay { /// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours. pub fn reinit_with_subj(&mut self, subj: &R) where - R: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R: ShapeResource

+ ?Sized, { self.clear(); @@ -284,7 +272,7 @@ impl, T: FloatNumber> FloatOverlay { /// Convert into `FloatOverlayGraph` from the added paths or shapes using the specified build rule. This graph is the foundation for executing boolean operations, allowing for the analysis and manipulation of the geometric data. The `OverlayGraph` created by this method represents a preprocessed state of the input shapes, optimized for the application of boolean operations based on the provided build rule. /// - `fill_rule`: Specifies the rule for determining filled areas within the shapes, influencing how the resulting graph represents intersections and unions. #[inline] - pub fn build_graph_view(&mut self, fill_rule: FillRule) -> Option> { + pub fn build_graph_view(&mut self, fill_rule: FillRule) -> Option> { let graph = self.overlay.build_graph_view(fill_rule)?; Some(FloatOverlayGraph::new( graph, @@ -396,9 +384,9 @@ impl Default for OverlayOptions { } impl OverlayOptions { - pub(crate) fn int_with_adapter>( + pub(crate) fn int_with_adapter>( &self, - adapter: &FloatPointAdapter, + adapter: &FloatPointAdapter

, ) -> IntOverlayOptions { IntOverlayOptions { preserve_input_collinear: self.preserve_input_collinear, diff --git a/iOverlay/src/float/relate.rs b/iOverlay/src/float/relate.rs index 7e5727f..1e360f3 100644 --- a/iOverlay/src/float/relate.rs +++ b/iOverlay/src/float/relate.rs @@ -4,7 +4,6 @@ use crate::core::relate::PredicateOverlay; use crate::core::solver::Solver; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; -use i_float::float::number::FloatNumber; use i_shape::source::resource::ShapeResource; /// Float-coordinate wrapper for spatial predicate evaluation. @@ -27,12 +26,12 @@ use i_shape::source::resource::ShapeResource; /// /// For a more ergonomic API, see the [`FloatRelate`] trait which provides /// methods directly on shape types. -pub struct FloatPredicateOverlay, T: FloatNumber> { +pub struct FloatPredicateOverlay { pub(crate) overlay: PredicateOverlay, - pub(crate) adapter: FloatPointAdapter, + pub(crate) adapter: FloatPointAdapter

, } -impl, T: FloatNumber> FloatPredicateOverlay { +impl FloatPredicateOverlay

{ /// Creates a new predicate overlay with a pre-configured adapter. /// /// Use this when you need fixed-scale precision via `FloatPointAdapter::with_scale()`. @@ -41,7 +40,7 @@ impl, T: FloatNumber> FloatPredicateOverlay { /// * `adapter` - A `FloatPointAdapter` instance for coordinate conversion. /// * `capacity` - Initial capacity for storing segments. #[inline] - pub fn with_adapter(adapter: FloatPointAdapter, capacity: usize) -> Self { + pub fn with_adapter(adapter: FloatPointAdapter

, capacity: usize) -> Self { Self { overlay: PredicateOverlay::new(capacity), adapter, @@ -59,7 +58,7 @@ impl, T: FloatNumber> FloatPredicateOverlay { /// * `capacity` - Initial capacity for storing segments. #[inline] pub fn with_adapter_custom( - adapter: FloatPointAdapter, + adapter: FloatPointAdapter

, fill_rule: FillRule, solver: Solver, capacity: usize, @@ -73,8 +72,8 @@ impl, T: FloatNumber> FloatPredicateOverlay { /// Creates a new predicate overlay from subject and clip shapes. pub fn with_subj_and_clip(subj: &R0, clip: &R1) -> Self where - R0: ShapeResource + ?Sized, - R1: ShapeResource + ?Sized, + R0: ShapeResource

+ ?Sized, + R1: ShapeResource

+ ?Sized, { let iter = subj.iter_paths().chain(clip.iter_paths()).flatten(); let adapter = FloatPointAdapter::with_iter(iter); @@ -98,8 +97,8 @@ impl, T: FloatNumber> FloatPredicateOverlay { solver: Solver, ) -> Self where - R0: ShapeResource + ?Sized, - R1: ShapeResource + ?Sized, + R0: ShapeResource

+ ?Sized, + R1: ShapeResource

+ ?Sized, { let iter = subj.iter_paths().chain(clip.iter_paths()).flatten(); let adapter = FloatPointAdapter::with_iter(iter); @@ -121,7 +120,7 @@ impl, T: FloatNumber> FloatPredicateOverlay { /// # Arguments /// * `resource` - A `ShapeResource` specifying the geometry to add. /// * `shape_type` - Whether to add as `Subject` or `Clip`. - pub fn add_source + ?Sized>(&mut self, resource: &R, shape_type: ShapeType) { + pub fn add_source + ?Sized>(&mut self, resource: &R, shape_type: ShapeType) { for contour in resource.iter_paths() { self.overlay .add_path_iter(contour.iter().map(|p| self.adapter.float_to_int(p)), shape_type); @@ -200,11 +199,10 @@ impl, T: FloatNumber> FloatPredicateOverlay { /// - `Vec<[f64; 2]>` - single contour /// - `Vec>` - multiple contours (shape with holes) /// - `Vec>>` - multiple shapes -pub trait FloatRelate +pub trait FloatRelate where - R1: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R1: ShapeResource

+ ?Sized, + P: FloatPointCompatible, { /// Returns `true` if this shape intersects with another (shares any point). /// @@ -247,12 +245,11 @@ where fn covers(&self, other: &R1) -> bool; } -impl FloatRelate for R0 +impl FloatRelate for R0 where - R0: ShapeResource + ?Sized, - R1: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

+ ?Sized, + R1: ShapeResource

+ ?Sized, + P: FloatPointCompatible, { #[inline] fn intersects(&self, other: &R1) -> bool { diff --git a/iOverlay/src/float/scale.rs b/iOverlay/src/float/scale.rs index 6e7d562..e2012e4 100644 --- a/iOverlay/src/float/scale.rs +++ b/iOverlay/src/float/scale.rs @@ -40,12 +40,11 @@ impl FixedScaleOverlayError { /// The `scale` parameter defines the float-to-integer conversion: /// `x_int = (x_float - offset_x) * scale`. /// Larger `scale` gives higher precision but must fit within the safe integer bounds. -pub trait FixedScaleFloatOverlay +pub trait FixedScaleFloatOverlay where - R0: ShapeResource, - R1: ShapeResource, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

, + R1: ShapeResource

, + P: FloatPointCompatible, { /// General overlay method that takes an `ShapeResource` to determine the input type. /// @@ -63,16 +62,15 @@ where source: &R1, overlay_rule: OverlayRule, fill_rule: FillRule, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError>; } -impl FixedScaleFloatOverlay for R0 +impl FixedScaleFloatOverlay for R0 where - R0: ShapeResource, - R1: ShapeResource, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

, + R1: ShapeResource

, + P: FloatPointCompatible, { #[inline] fn overlay_with_fixed_scale( @@ -80,14 +78,14 @@ where source: &R1, overlay_rule: OverlayRule, fill_rule: FillRule, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError> { Ok(FloatOverlay::with_subj_and_clip_fixed_scale(self, source, scale)? .overlay(overlay_rule, fill_rule)) } } -impl, T: FloatNumber> FloatOverlay { +impl FloatOverlay

{ /// Creates a new `FloatOverlay` instance and initializes it with subject and clip shapes. /// /// This variant uses a fixed float-to-integer scale instead of auto-scaling. @@ -103,13 +101,11 @@ impl, T: FloatNumber> FloatOverlay { pub fn with_subj_and_clip_fixed_scale( subj: &R0, clip: &R1, - scale: T, + scale: P::Scalar, ) -> Result where - R0: ShapeResource + ?Sized, - R1: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

+ ?Sized, + R1: ShapeResource

+ ?Sized, { let s = FixedScaleOverlayError::validate_scale(scale)?; @@ -120,7 +116,7 @@ impl, T: FloatNumber> FloatOverlay { } adapter.dir_scale = scale; - adapter.inv_scale = T::from_float(1.0 / s); + adapter.inv_scale = P::Scalar::from_float(1.0 / s); let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len()); let clip_capacity = clip.iter_paths().fold(0, |s, c| s + c.len()); @@ -147,15 +143,13 @@ impl, T: FloatNumber> FloatOverlay { pub fn with_subj_and_clip_fixed_scale_custom( subj: &R0, clip: &R1, - options: OverlayOptions, + options: OverlayOptions, solver: Solver, - scale: T, + scale: P::Scalar, ) -> Result where - R0: ShapeResource + ?Sized, - R1: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

+ ?Sized, + R1: ShapeResource

+ ?Sized, { let s = FixedScaleOverlayError::validate_scale(scale)?; @@ -166,7 +160,7 @@ impl, T: FloatNumber> FloatOverlay { } adapter.dir_scale = scale; - adapter.inv_scale = T::from_float(1.0 / s); + adapter.inv_scale = P::Scalar::from_float(1.0 / s); let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len()); let clip_capacity = clip.iter_paths().fold(0, |s, c| s + c.len()); @@ -179,7 +173,7 @@ impl, T: FloatNumber> FloatOverlay { } } -impl, T: FloatNumber> FloatPredicateOverlay { +impl FloatPredicateOverlay

{ /// Creates a new predicate overlay with subject and clip shapes using fixed-scale precision. /// /// This variant uses a fixed float-to-integer scale instead of auto-scaling. @@ -194,11 +188,11 @@ impl, T: FloatNumber> FloatPredicateOverlay { pub fn with_subj_and_clip_fixed_scale( subj: &R0, clip: &R1, - scale: T, + scale: P::Scalar, ) -> Result where - R0: ShapeResource + ?Sized, - R1: ShapeResource + ?Sized, + R0: ShapeResource

+ ?Sized, + R1: ShapeResource

+ ?Sized, { let s = FixedScaleOverlayError::validate_scale(scale)?; @@ -209,7 +203,7 @@ impl, T: FloatNumber> FloatPredicateOverlay { } adapter.dir_scale = scale; - adapter.inv_scale = T::from_float(1.0 / s); + adapter.inv_scale = P::Scalar::from_float(1.0 / s); let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len()); let clip_capacity = clip.iter_paths().fold(0, |s, c| s + c.len()); @@ -234,11 +228,11 @@ impl, T: FloatNumber> FloatPredicateOverlay { clip: &R1, fill_rule: FillRule, solver: Solver, - scale: T, + scale: P::Scalar, ) -> Result where - R0: ShapeResource + ?Sized, - R1: ShapeResource + ?Sized, + R0: ShapeResource

+ ?Sized, + R1: ShapeResource

+ ?Sized, { let s = FixedScaleOverlayError::validate_scale(scale)?; @@ -249,7 +243,7 @@ impl, T: FloatNumber> FloatPredicateOverlay { } adapter.dir_scale = scale; - adapter.inv_scale = T::from_float(1.0 / s); + adapter.inv_scale = P::Scalar::from_float(1.0 / s); let subj_capacity = subj.iter_paths().fold(0, |s, c| s + c.len()); let clip_capacity = clip.iter_paths().fold(0, |s, c| s + c.len()); @@ -279,44 +273,51 @@ impl, T: FloatNumber> FloatPredicateOverlay { /// let result = square.intersects_with_fixed_scale(&other, 1000.0); /// assert!(result.unwrap()); /// ``` -pub trait FixedScaleFloatRelate +pub trait FixedScaleFloatRelate where - R1: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R1: ShapeResource

+ ?Sized, + P: FloatPointCompatible, { /// Returns `true` if shapes intersect, using fixed-scale precision. - fn intersects_with_fixed_scale(&self, other: &R1, scale: T) -> Result; + fn intersects_with_fixed_scale( + &self, + other: &R1, + scale: P::Scalar, + ) -> Result; /// Returns `true` if interiors of shapes overlap, using fixed-scale precision. fn interiors_intersect_with_fixed_scale( &self, other: &R1, - scale: T, + scale: P::Scalar, ) -> Result; /// Returns `true` if shapes touch (boundaries intersect but interiors don't), using fixed-scale precision. - fn touches_with_fixed_scale(&self, other: &R1, scale: T) -> Result; + fn touches_with_fixed_scale(&self, other: &R1, scale: P::Scalar) -> Result; /// Returns `true` if this shape is completely within another, using fixed-scale precision. - fn within_with_fixed_scale(&self, other: &R1, scale: T) -> Result; + fn within_with_fixed_scale(&self, other: &R1, scale: P::Scalar) -> Result; /// Returns `true` if shapes do not intersect, using fixed-scale precision. - fn disjoint_with_fixed_scale(&self, other: &R1, scale: T) -> Result; + fn disjoint_with_fixed_scale(&self, other: &R1, scale: P::Scalar) + -> Result; /// Returns `true` if this shape completely covers another, using fixed-scale precision. - fn covers_with_fixed_scale(&self, other: &R1, scale: T) -> Result; + fn covers_with_fixed_scale(&self, other: &R1, scale: P::Scalar) -> Result; } -impl FixedScaleFloatRelate for R0 +impl FixedScaleFloatRelate for R0 where - R0: ShapeResource + ?Sized, - R1: ShapeResource + ?Sized, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

+ ?Sized, + R1: ShapeResource

+ ?Sized, + P: FloatPointCompatible, { #[inline] - fn intersects_with_fixed_scale(&self, other: &R1, scale: T) -> Result { + fn intersects_with_fixed_scale( + &self, + other: &R1, + scale: P::Scalar, + ) -> Result { Ok(FloatPredicateOverlay::with_subj_and_clip_fixed_scale(self, other, scale)?.intersects()) } @@ -324,28 +325,32 @@ where fn interiors_intersect_with_fixed_scale( &self, other: &R1, - scale: T, + scale: P::Scalar, ) -> Result { Ok(FloatPredicateOverlay::with_subj_and_clip_fixed_scale(self, other, scale)?.interiors_intersect()) } #[inline] - fn touches_with_fixed_scale(&self, other: &R1, scale: T) -> Result { + fn touches_with_fixed_scale(&self, other: &R1, scale: P::Scalar) -> Result { Ok(FloatPredicateOverlay::with_subj_and_clip_fixed_scale(self, other, scale)?.touches()) } #[inline] - fn within_with_fixed_scale(&self, other: &R1, scale: T) -> Result { + fn within_with_fixed_scale(&self, other: &R1, scale: P::Scalar) -> Result { Ok(FloatPredicateOverlay::with_subj_and_clip_fixed_scale(self, other, scale)?.within()) } #[inline] - fn disjoint_with_fixed_scale(&self, other: &R1, scale: T) -> Result { + fn disjoint_with_fixed_scale( + &self, + other: &R1, + scale: P::Scalar, + ) -> Result { Ok(!FloatPredicateOverlay::with_subj_and_clip_fixed_scale(self, other, scale)?.intersects()) } #[inline] - fn covers_with_fixed_scale(&self, other: &R1, scale: T) -> Result { + fn covers_with_fixed_scale(&self, other: &R1, scale: P::Scalar) -> Result { Ok(FloatPredicateOverlay::with_subj_and_clip_fixed_scale(other, self, scale)?.within()) } } diff --git a/iOverlay/src/float/simplify.rs b/iOverlay/src/float/simplify.rs index 65b067d..74053bc 100644 --- a/iOverlay/src/float/simplify.rs +++ b/iOverlay/src/float/simplify.rs @@ -3,14 +3,13 @@ use crate::core::overlay_rule::OverlayRule; use crate::core::solver::Solver; use crate::float::overlay::{FloatOverlay, OverlayOptions}; use i_float::float::compatible::FloatPointCompatible; -use i_float::float::number::FloatNumber; use i_shape::base::data::Shapes; use i_shape::source::resource::ShapeResource; /// Trait `Simplify` provides a method to simplify geometric shapes by reducing the number of points in contours or shapes /// while preserving overall shape and topology. The method applies a minimum area threshold and a build rule to /// determine which areas should be retained or excluded. -pub trait SimplifyShape { +pub trait SimplifyShape { /// Simplifies the shape or collection of points, contours, or shapes, based on a specified minimum area threshold. /// /// - Returns: A collection of `Shapes

` that represents the simplified geometry. @@ -27,16 +26,15 @@ pub trait SimplifyShape { fn simplify_shape_custom( &self, fill_rule: FillRule, - options: OverlayOptions, + options: OverlayOptions, solver: Solver, ) -> Shapes

; } -impl SimplifyShape for S +impl SimplifyShape

for S where - S: ShapeResource, - P: FloatPointCompatible, - T: FloatNumber, + S: ShapeResource

, + P: FloatPointCompatible, { #[inline] fn simplify_shape(&self, fill_rule: FillRule) -> Shapes

{ @@ -48,7 +46,7 @@ where fn simplify_shape_custom( &self, fill_rule: FillRule, - options: OverlayOptions, + options: OverlayOptions, solver: Solver, ) -> Shapes

{ FloatOverlay::with_subj_custom(self, options, solver).overlay(OverlayRule::Subject, fill_rule) diff --git a/iOverlay/src/float/single.rs b/iOverlay/src/float/single.rs index 984d7f0..19d7197 100644 --- a/iOverlay/src/float/single.rs +++ b/iOverlay/src/float/single.rs @@ -2,18 +2,16 @@ use crate::core::fill_rule::FillRule; use crate::core::overlay_rule::OverlayRule; use crate::float::overlay::FloatOverlay; use i_float::float::compatible::FloatPointCompatible; -use i_float::float::number::FloatNumber; use i_shape::base::data::Shapes; use i_shape::source::resource::ShapeResource; /// Trait `SingleFloatOverlay` provides methods for overlay operations between various geometric entities. /// This trait supports boolean operations on contours, shapes, and collections of shapes, using customizable overlay and build rules. -pub trait SingleFloatOverlay +pub trait SingleFloatOverlay where - R0: ShapeResource, - R1: ShapeResource, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

, + R1: ShapeResource

, + P: FloatPointCompatible, { /// General overlay method that takes an `ShapeResource` to determine the input type. /// @@ -28,12 +26,11 @@ where fn overlay(&self, source: &R1, overlay_rule: OverlayRule, fill_rule: FillRule) -> Shapes

; } -impl SingleFloatOverlay for R0 +impl SingleFloatOverlay for R0 where - R0: ShapeResource, - R1: ShapeResource, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

, + R1: ShapeResource

, + P: FloatPointCompatible, { #[inline] fn overlay(&self, resource: &R1, overlay_rule: OverlayRule, fill_rule: FillRule) -> Shapes

{ diff --git a/iOverlay/src/float/slice.rs b/iOverlay/src/float/slice.rs index 760bbce..d434de7 100644 --- a/iOverlay/src/float/slice.rs +++ b/iOverlay/src/float/slice.rs @@ -5,17 +5,15 @@ use crate::float::scale::FixedScaleOverlayError; use crate::float::string_overlay::FloatStringOverlay; use crate::string::rule::StringRule; use i_float::float::compatible::FloatPointCompatible; -use i_float::float::number::FloatNumber; use i_shape::base::data::Shapes; use i_shape::source::resource::ShapeResource; /// The `FloatSlice` trait provides methods to slice geometric shapes using a given path or set of paths, /// allowing for boolean operations based on the specified build rule. -pub trait FloatSlice +pub trait FloatSlice where - R: ShapeResource, - P: FloatPointCompatible, - T: FloatNumber, + R: ShapeResource

, + P: FloatPointCompatible, { /// Slices the current shapes by string lines. /// @@ -48,7 +46,7 @@ where &self, resource: &R, fill_rule: FillRule, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError>; /// Slices the current shapes by string lines. @@ -68,7 +66,7 @@ where &self, resource: &R, fill_rule: FillRule, - options: OverlayOptions, + options: OverlayOptions, solver: Solver, ) -> Shapes

; @@ -90,18 +88,17 @@ where &self, resource: &R, fill_rule: FillRule, - options: OverlayOptions, + options: OverlayOptions, solver: Solver, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError>; } -impl FloatSlice for R1 +impl FloatSlice for R1 where - R0: ShapeResource, - R1: ShapeResource, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

, + R1: ShapeResource

, + P: FloatPointCompatible, { #[inline] fn slice_by(&self, resource: &R0, fill_rule: FillRule) -> Shapes

{ @@ -116,7 +113,7 @@ where &self, resource: &R0, fill_rule: FillRule, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError> { Ok( FloatStringOverlay::with_shape_and_string_fixed_scale(self, resource, scale)? @@ -131,7 +128,7 @@ where &self, resource: &R0, fill_rule: FillRule, - options: OverlayOptions, + options: OverlayOptions, solver: Solver, ) -> Shapes

{ FloatStringOverlay::with_shape_and_string(self, resource) @@ -145,9 +142,9 @@ where &self, resource: &R0, fill_rule: FillRule, - options: OverlayOptions, + options: OverlayOptions, solver: Solver, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError> { Ok( FloatStringOverlay::with_shape_and_string_fixed_scale(self, resource, scale)? diff --git a/iOverlay/src/float/string_graph.rs b/iOverlay/src/float/string_graph.rs index 44363df..592a6bb 100644 --- a/iOverlay/src/float/string_graph.rs +++ b/iOverlay/src/float/string_graph.rs @@ -3,7 +3,6 @@ use crate::string::graph::StringGraph; use crate::string::rule::StringRule; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; -use i_float::float::number::FloatNumber; use i_shape::base::data::Shapes; use i_shape::float::adapter::ShapesToFloat; use i_shape::float::despike::DeSpikeContour; @@ -11,12 +10,12 @@ use i_shape::float::simple::SimplifyContour; /// The `FloatStringGraph` struct represents a graph structure with floating-point precision, /// providing methods to extract geometric shapes from the graph after applying string-based operations. -pub struct FloatStringGraph<'a, P: FloatPointCompatible, T: FloatNumber> { +pub struct FloatStringGraph<'a, P: FloatPointCompatible> { pub graph: StringGraph<'a>, - pub adapter: FloatPointAdapter, + pub adapter: FloatPointAdapter

, } -impl, T: FloatNumber> FloatStringGraph<'_, P, T> { +impl FloatStringGraph<'_, P> { /// Extracts shapes from the overlay graph based on the specified string rule. /// This method is used to retrieve the final geometric shapes after boolean operations have been applied. /// It's suitable for most use cases where the minimum area of shapes is not a concern. @@ -57,7 +56,11 @@ impl, T: FloatNumber> FloatStringGraph<'_, P, T> { /// /// Note: Outer boundary paths have a **main_direction** order, and holes have an opposite to **main_direction** order. #[inline] - pub fn extract_shapes_custom(&self, string_rule: StringRule, options: OverlayOptions) -> Shapes

{ + pub fn extract_shapes_custom( + &self, + string_rule: StringRule, + options: OverlayOptions, + ) -> Shapes

{ let shapes = self .graph .extract_shapes_custom(string_rule, options.int_with_adapter(&self.adapter)); diff --git a/iOverlay/src/float/string_overlay.rs b/iOverlay/src/float/string_overlay.rs index 7509b4d..5fc42d2 100644 --- a/iOverlay/src/float/string_overlay.rs +++ b/iOverlay/src/float/string_overlay.rs @@ -17,12 +17,12 @@ use i_shape::source::resource::ShapeResource; /// /// The float-to-integer conversion is controlled by the `FloatPointAdapter` scale: /// `x_int = (x_float - offset_x) * scale`. Use a fixed scale if you need predictable precision. -pub struct FloatStringOverlay, T: FloatNumber> { +pub struct FloatStringOverlay { pub(super) overlay: StringOverlay, - pub(super) adapter: FloatPointAdapter, + pub(super) adapter: FloatPointAdapter

, } -impl, T: FloatNumber> FloatStringOverlay { +impl FloatStringOverlay

{ /// Constructs a new `FloatStringOverlay`, a builder for overlaying geometric shapes /// by converting float-based geometry to integer space, using a pre-configured adapter. /// @@ -33,7 +33,7 @@ impl, T: FloatNumber> FloatStringOverlay { /// - `capacity`: Initial capacity for storing segments, ideally matching the total number of /// segments for efficient memory allocation. #[inline] - pub fn with_adapter(adapter: FloatPointAdapter, capacity: usize) -> Self { + pub fn with_adapter(adapter: FloatPointAdapter

, capacity: usize) -> Self { Self { overlay: StringOverlay::new(capacity), adapter, @@ -55,10 +55,8 @@ impl, T: FloatNumber> FloatStringOverlay { /// - `Vec`: A collection of grouped paths, where each group may consist of multiple paths. pub fn with_shape_and_string(shape: &R0, string: &R1) -> Self where - R0: ShapeResource, - R1: ShapeResource, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

, + R1: ShapeResource

, { let iter = shape.iter_paths().chain(string.iter_paths()).flatten(); let adapter = FloatPointAdapter::with_iter(iter); @@ -77,13 +75,11 @@ impl, T: FloatNumber> FloatStringOverlay { pub fn with_shape_and_string_fixed_scale( shape: &R0, string: &R1, - scale: T, + scale: P::Scalar, ) -> Result where - R0: ShapeResource, - R1: ShapeResource, - P: FloatPointCompatible, - T: FloatNumber, + R0: ShapeResource

, + R1: ShapeResource

, { let s = FixedScaleOverlayError::validate_scale(scale)?; @@ -94,7 +90,7 @@ impl, T: FloatNumber> FloatStringOverlay { } adapter.dir_scale = scale; - adapter.inv_scale = T::from_float(1.0 / s); + adapter.inv_scale = P::Scalar::from_float(1.0 / s); let shape_capacity = shape.iter_paths().fold(0, |s, c| s + c.len()); let string_capacity = string.iter_paths().fold(0, |s, c| s + c.len()); @@ -112,7 +108,7 @@ impl, T: FloatNumber> FloatStringOverlay { /// - `Shapes`: A collection of shapes, where each shape may consist of multiple contours. /// - `shape_type`: Specifies the role of the added paths in the overlay operation, either as `Subject` or `Clip`. #[inline] - pub fn unsafe_add_shapes>(mut self, source: &S) -> Self { + pub fn unsafe_add_shapes>(mut self, source: &S) -> Self { for contour in source.iter_paths() { self = self.unsafe_add_shape_contour(contour); } @@ -126,7 +122,7 @@ impl, T: FloatNumber> FloatStringOverlay { /// - `Paths`: A collection of paths, each representing a string line. /// - `Vec`: A collection of grouped paths, where each group may consist of multiple paths. #[inline] - pub fn unsafe_add_string_lines>(mut self, resource: &S) -> Self { + pub fn unsafe_add_string_lines>(mut self, resource: &S) -> Self { for path in resource.iter_paths() { self = self.unsafe_add_string_line(path); } @@ -162,7 +158,7 @@ impl, T: FloatNumber> FloatStringOverlay { /// - `fill_rule`: Fill rule to determine filled areas (non-zero, even-odd, positive, negative). /// - Returns: A `FloatStringGraph` containing the graph representation of the overlay's geometry. #[inline] - pub fn build_graph_view(&mut self, fill_rule: FillRule) -> Option> { + pub fn build_graph_view(&mut self, fill_rule: FillRule) -> Option> { self.build_graph_view_with_solver(fill_rule, Default::default()) } @@ -176,7 +172,7 @@ impl, T: FloatNumber> FloatStringOverlay { &mut self, fill_rule: FillRule, solver: Solver, - ) -> Option> { + ) -> Option> { let graph = self.overlay.build_graph_view_with_solver(fill_rule, solver)?; Some(FloatStringGraph { graph, diff --git a/iOverlay/src/lib.rs b/iOverlay/src/lib.rs index 16db78a..f7fd8ea 100644 --- a/iOverlay/src/lib.rs +++ b/iOverlay/src/lib.rs @@ -99,7 +99,9 @@ //! } //! //! // Implement the `FloatPointCompatible` trait for CustomPoint -//! impl FloatPointCompatible for CustomPoint { +//! impl FloatPointCompatible for CustomPoint { +//! type Scalar = f32; +//! //! fn from_xy(x: f32, y: f32) -> Self { //! Self { x, y } //! } diff --git a/iOverlay/src/mesh/math.rs b/iOverlay/src/mesh/math.rs index b81f3a7..f32475b 100644 --- a/iOverlay/src/mesh/math.rs +++ b/iOverlay/src/mesh/math.rs @@ -1,11 +1,10 @@ use i_float::float::compatible::FloatPointCompatible; -use i_float::float::number::FloatNumber; use i_float::float::vector::FloatPointMath; -pub(crate) struct Math { - _phantom: core::marker::PhantomData<(T, P)>, +pub(crate) struct Math

{ + _phantom: core::marker::PhantomData

, } -impl> Math { +impl Math

{ #[inline(always)] pub(crate) fn normal(a: &P, b: &P) -> P { let c = FloatPointMath::sub(a, b); @@ -13,7 +12,7 @@ impl> Math { } #[inline(always)] - pub(crate) fn ortho_and_scale(p: &P, s: T) -> P { + pub(crate) fn ortho_and_scale(p: &P, s: P::Scalar) -> P { let t = P::from_xy(-p.y(), p.x()); FloatPointMath::scale(&t, s) } diff --git a/iOverlay/src/mesh/miter.rs b/iOverlay/src/mesh/miter.rs index c01c287..504d910 100644 --- a/iOverlay/src/mesh/miter.rs +++ b/iOverlay/src/mesh/miter.rs @@ -13,12 +13,12 @@ pub(super) enum SharpMiter { impl Miter { #[inline] - pub(super) fn sharp>( + pub(super) fn sharp( pa: P, pb: P, va: P, vb: P, - adapter: &FloatPointAdapter, + adapter: &FloatPointAdapter

, ) -> SharpMiter { let ia = adapter.float_to_int(&pa); let ib = adapter.float_to_int(&pb); @@ -39,7 +39,7 @@ impl Miter { } #[inline] - pub(super) fn peak>(pa: P, pb: P, va: P, vb: P) -> P { + pub(super) fn peak(pa: P, pb: P, va: P, vb: P) -> P { let pax = pa.x(); let pay = pa.y(); let pbx = pb.x(); diff --git a/iOverlay/src/mesh/outline/builder.rs b/iOverlay/src/mesh/outline/builder.rs index 94a9f0a..5dbe2a1 100644 --- a/iOverlay/src/mesh/outline/builder.rs +++ b/iOverlay/src/mesh/outline/builder.rs @@ -14,33 +14,33 @@ use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; use i_float::float::vector::FloatPointMath; -trait OutlineBuild, T: FloatNumber> { +trait OutlineBuild { fn build( &self, path: &[P], - adapter: &FloatPointAdapter, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ); fn capacity(&self, points_count: usize) -> usize; - fn additional_offset(&self, radius: T) -> T; + fn additional_offset(&self, radius: P::Scalar) -> P::Scalar; } -pub(super) struct OutlineBuilder, T: FloatNumber> { - builder: Box>, +pub(super) struct OutlineBuilder { + builder: Box>, } -struct Builder, P: FloatPointCompatible, T: FloatNumber> { +struct Builder, P: FloatPointCompatible> { extend: bool, - radius: T, + radius: P::Scalar, join_builder: J, _phantom: PhantomData

, } -impl + 'static, T: FloatNumber + 'static> OutlineBuilder { - pub(super) fn new(radius: T, join: &LineJoin) -> OutlineBuilder { - let extend = radius > T::from_float(0.0); - let builder: Box> = { +impl OutlineBuilder

{ + pub(super) fn new(radius: P::Scalar, join: &LineJoin) -> OutlineBuilder

{ + let extend = radius > P::Scalar::from_float(0.0); + let builder: Box> = { match join { LineJoin::Miter(ratio) => Box::new(Builder { extend, @@ -70,7 +70,7 @@ impl + 'static, T: FloatNumber + 'static> OutlineBuil pub(super) fn build( &self, path: &[P], - adapter: &FloatPointAdapter, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { self.builder.build(path, adapter, segments); @@ -82,19 +82,17 @@ impl + 'static, T: FloatNumber + 'static> OutlineBuil } #[inline] - pub(super) fn additional_offset(&self, radius: T) -> T { + pub(super) fn additional_offset(&self, radius: P::Scalar) -> P::Scalar { self.builder.additional_offset(radius) } } -impl, P: FloatPointCompatible, T: FloatNumber> OutlineBuild - for Builder -{ +impl, P: FloatPointCompatible> OutlineBuild

for Builder { #[inline] fn build( &self, path: &[P], - adapter: &FloatPointAdapter, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { if path.len() < 2 { @@ -110,16 +108,16 @@ impl, P: FloatPointCompatible, T: FloatNumber> OutlineBu } #[inline] - fn additional_offset(&self, radius: T) -> T { + fn additional_offset(&self, radius: P::Scalar) -> P::Scalar { self.join_builder.additional_offset(radius) } } -impl, P: FloatPointCompatible, T: FloatNumber> Builder { +impl, P: FloatPointCompatible> Builder { fn build( &self, path: &[P], - adapter: &FloatPointAdapter, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { let iter = path.iter().map(|p| adapter.float_to_int(p)); @@ -152,9 +150,9 @@ impl, P: FloatPointCompatible, T: FloatNumber> Builder, - s1: &OffsetSection, - adapter: &FloatPointAdapter, + s0: &OffsetSection

, + s1: &OffsetSection

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { let vi = s1.b - s1.a; @@ -175,13 +173,9 @@ impl, P: FloatPointCompatible, T: FloatNumber> Builder, T: FloatNumber> OffsetSection { +impl OffsetSection

{ #[inline] - fn new(radius: T, s: &UniqueSegment, adapter: &FloatPointAdapter) -> Self - where - P: FloatPointCompatible, - T: FloatNumber, - { + fn new(radius: P::Scalar, s: &UniqueSegment, adapter: &FloatPointAdapter

) -> Self { let a = adapter.int_to_float(&s.a); let b = adapter.int_to_float(&s.b); let ab = FloatPointMath::sub(&b, &a); @@ -199,7 +193,6 @@ impl, T: FloatNumber> OffsetSection { a_top, b_top, dir, - _phantom: Default::default(), } } } diff --git a/iOverlay/src/mesh/outline/builder_join.rs b/iOverlay/src/mesh/outline/builder_join.rs index 1a99902..5eabce4 100644 --- a/iOverlay/src/mesh/outline/builder_join.rs +++ b/iOverlay/src/mesh/outline/builder_join.rs @@ -10,26 +10,26 @@ use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; use i_float::float::vector::FloatPointMath; -pub(super) trait JoinBuilder, T: FloatNumber> { +pub(super) trait JoinBuilder { fn add_join( &self, - s0: &OffsetSection, - s1: &OffsetSection, - adapter: &FloatPointAdapter, + s0: &OffsetSection

, + s1: &OffsetSection

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ); fn capacity(&self) -> usize; - fn additional_offset(&self, radius: T) -> T; + fn additional_offset(&self, radius: P::Scalar) -> P::Scalar; } pub(super) struct BevelJoinBuilder; impl BevelJoinBuilder { #[inline] - fn join>( - s0: &OffsetSection, - s1: &OffsetSection, - _adapter: &FloatPointAdapter, + fn join( + s0: &OffsetSection

, + s1: &OffsetSection

, + _adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { debug_assert_ne!(s0.b_top, s1.a_top, "must be validated before"); @@ -37,13 +37,13 @@ impl BevelJoinBuilder { } } -impl> JoinBuilder for BevelJoinBuilder { +impl JoinBuilder

for BevelJoinBuilder { #[inline] fn add_join( &self, - s0: &OffsetSection, - s1: &OffsetSection, - adapter: &FloatPointAdapter, + s0: &OffsetSection

, + s1: &OffsetSection

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { Self::join(s0, s1, adapter, segments); @@ -55,9 +55,9 @@ impl> JoinBuilder for BevelJoin } #[inline] - fn additional_offset(&self, radius: T) -> T { + fn additional_offset(&self, radius: P::Scalar) -> P::Scalar { // add extra 10% to avoid problems with floating point precision. - T::from_float(1.1) * radius + P::Scalar::from_float(1.1) * radius } } @@ -91,12 +91,12 @@ impl MiterJoinBuilder { } } -impl> JoinBuilder for MiterJoinBuilder { +impl JoinBuilder

for MiterJoinBuilder { fn add_join( &self, - s0: &OffsetSection, - s1: &OffsetSection, - adapter: &FloatPointAdapter, + s0: &OffsetSection

, + s1: &OffsetSection

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { let ia = s0.b_top; @@ -157,7 +157,7 @@ impl> JoinBuilder for MiterJoin } #[inline] - fn additional_offset(&self, _radius: T) -> T { + fn additional_offset(&self, _radius: P::Scalar) -> P::Scalar { self.max_offset } } @@ -191,12 +191,12 @@ impl RoundJoinBuilder { } } } -impl> JoinBuilder for RoundJoinBuilder { +impl JoinBuilder

for RoundJoinBuilder { fn add_join( &self, - s0: &OffsetSection, - s1: &OffsetSection, - adapter: &FloatPointAdapter, + s0: &OffsetSection

, + s1: &OffsetSection

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { let dot_product = FloatPointMath::dot_product(&s0.dir, &s1.dir); @@ -207,14 +207,14 @@ impl> JoinBuilder for RoundJoin let angle = dot_product.acos(); let n = (angle * self.inv_ratio).to_usize(); - let delta_angle = angle / T::from_usize(n); + let delta_angle = angle / P::Scalar::from_usize(n); let start = s0.b_top; let end = s1.a_top; let dir = P::from_xy(-s0.dir.y(), s0.dir.x()); - let rotator = Rotator::::with_angle(self.rot_dir * delta_angle); + let rotator = Rotator::::with_angle(self.rot_dir * delta_angle); let center = adapter.int_to_float(&s0.b); let mut v = dir; @@ -241,8 +241,8 @@ impl> JoinBuilder for RoundJoin } #[inline] - fn additional_offset(&self, radius: T) -> T { + fn additional_offset(&self, radius: P::Scalar) -> P::Scalar { // add extra 10% to avoid problems with floating point precision. - T::from_float(1.1) * radius + P::Scalar::from_float(1.1) * radius } } diff --git a/iOverlay/src/mesh/outline/offset.rs b/iOverlay/src/mesh/outline/offset.rs index 0614cc0..e8215e3 100644 --- a/iOverlay/src/mesh/outline/offset.rs +++ b/iOverlay/src/mesh/outline/offset.rs @@ -22,7 +22,7 @@ use i_shape::float::int_area::IntArea; use i_shape::float::simple::SimplifyContour; use i_shape::source::resource::ShapeResource; -pub trait OutlineOffset, T: FloatNumber> { +pub trait OutlineOffset { /// Generates an outline shapes for contours, or shapes. /// /// - `style`: Defines the outline properties, including offset, and joins. @@ -30,13 +30,13 @@ pub trait OutlineOffset, T: FloatNumber> { /// # Returns /// A collection of `Shapes

` representing the outline geometry. /// Note: Outer boundary paths have a counterclockwise order, and holes have a clockwise order. - fn outline(&self, style: &OutlineStyle) -> Shapes

; + fn outline(&self, style: &OutlineStyle) -> Shapes

; /// Generates outline contours directly into a flat buffer. /// /// - `style`: Defines the outline properties, including offset, and joins. /// - `output`: Destination buffer that receives resulting contours. Existing contents are replaced. - fn outline_into(&self, style: &OutlineStyle, output: &mut FloatFlatContoursBuffer

); + fn outline_into(&self, style: &OutlineStyle, output: &mut FloatFlatContoursBuffer

); /// Generates an outline shapes for contours, or shapes with optional filtering. /// @@ -46,7 +46,11 @@ pub trait OutlineOffset, T: FloatNumber> { /// # Returns /// A collection of `Shapes

` representing the outline geometry. /// Note: Outer boundary paths have a **main_direction** order, and holes have an opposite to **main_direction** order. - fn outline_custom(&self, style: &OutlineStyle, options: OverlayOptions) -> Shapes

; + fn outline_custom( + &self, + style: &OutlineStyle, + options: OverlayOptions, + ) -> Shapes

; /// Generates outline contours directly into a flat buffer with optional filtering. /// @@ -55,8 +59,8 @@ pub trait OutlineOffset, T: FloatNumber> { /// - `output`: Destination buffer that receives resulting contours. Existing contents are replaced. fn outline_custom_into( &self, - style: &OutlineStyle, - options: OverlayOptions, + style: &OutlineStyle, + options: OverlayOptions, output: &mut FloatFlatContoursBuffer

, ); @@ -70,8 +74,8 @@ pub trait OutlineOffset, T: FloatNumber> { /// Note: Outer boundary paths have a counterclockwise order, and holes have a clockwise order. fn outline_fixed_scale( &self, - style: &OutlineStyle, - scale: T, + style: &OutlineStyle, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError>; /// Generates outline contours directly into a flat buffer with fixed float-to-integer scale. @@ -81,8 +85,8 @@ pub trait OutlineOffset, T: FloatNumber> { /// - `output`: Destination buffer that receives resulting contours. Existing contents are replaced on success. fn outline_fixed_scale_into( &self, - style: &OutlineStyle, - scale: T, + style: &OutlineStyle, + scale: P::Scalar, output: &mut FloatFlatContoursBuffer

, ) -> Result<(), FixedScaleOverlayError>; @@ -97,9 +101,9 @@ pub trait OutlineOffset, T: FloatNumber> { /// Note: Outer boundary paths have a **main_direction** order, and holes have an opposite to **main_direction** order. fn outline_custom_fixed_scale( &self, - style: &OutlineStyle, - options: OverlayOptions, - scale: T, + style: &OutlineStyle, + options: OverlayOptions, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError>; /// Generates outline contours directly into a flat buffer with optional filtering and fixed scaling. @@ -110,28 +114,31 @@ pub trait OutlineOffset, T: FloatNumber> { /// - `output`: Destination buffer that receives resulting contours. Existing contents are replaced on success. fn outline_custom_fixed_scale_into( &self, - style: &OutlineStyle, - options: OverlayOptions, - scale: T, + style: &OutlineStyle, + options: OverlayOptions, + scale: P::Scalar, output: &mut FloatFlatContoursBuffer

, ) -> Result<(), FixedScaleOverlayError>; } -impl OutlineOffset for S +impl OutlineOffset

for S where - S: ShapeResource, - P: FloatPointCompatible + 'static, - T: FloatNumber + 'static, + S: ShapeResource

, + P: FloatPointCompatible + 'static, { - fn outline(&self, style: &OutlineStyle) -> Shapes

{ + fn outline(&self, style: &OutlineStyle) -> Shapes

{ self.outline_custom(style, Default::default()) } - fn outline_into(&self, style: &OutlineStyle, output: &mut FloatFlatContoursBuffer

) { + fn outline_into(&self, style: &OutlineStyle, output: &mut FloatFlatContoursBuffer

) { self.outline_custom_into(style, Default::default(), output) } - fn outline_custom(&self, style: &OutlineStyle, options: OverlayOptions) -> Shapes

{ + fn outline_custom( + &self, + style: &OutlineStyle, + options: OverlayOptions, + ) -> Shapes

{ match OutlineSolver::prepare(self, style) { Some(solver) => solver.build(self, options), None => vec![], @@ -140,8 +147,8 @@ where fn outline_custom_into( &self, - style: &OutlineStyle, - options: OverlayOptions, + style: &OutlineStyle, + options: OverlayOptions, output: &mut FloatFlatContoursBuffer

, ) { match OutlineSolver::prepare(self, style) { @@ -152,16 +159,16 @@ where fn outline_fixed_scale( &self, - style: &OutlineStyle, - scale: T, + style: &OutlineStyle, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError> { self.outline_custom_fixed_scale(style, Default::default(), scale) } fn outline_fixed_scale_into( &self, - style: &OutlineStyle, - scale: T, + style: &OutlineStyle, + scale: P::Scalar, output: &mut FloatFlatContoursBuffer

, ) -> Result<(), FixedScaleOverlayError> { self.outline_custom_fixed_scale_into(style, Default::default(), scale, output) @@ -169,9 +176,9 @@ where fn outline_custom_fixed_scale( &self, - style: &OutlineStyle, - options: OverlayOptions, - scale: T, + style: &OutlineStyle, + options: OverlayOptions, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError> { let s = FixedScaleOverlayError::validate_scale(scale)?; let mut solver = match OutlineSolver::prepare(self, style) { @@ -184,9 +191,9 @@ where fn outline_custom_fixed_scale_into( &self, - style: &OutlineStyle, - options: OverlayOptions, - scale: T, + style: &OutlineStyle, + options: OverlayOptions, + scale: P::Scalar, output: &mut FloatFlatContoursBuffer

, ) -> Result<(), FixedScaleOverlayError> { let s = FixedScaleOverlayError::validate_scale(scale)?; @@ -203,15 +210,15 @@ where } } -struct OutlineSolver, T: FloatNumber> { - outer_builder: OutlineBuilder, - inner_builder: OutlineBuilder, - adapter: FloatPointAdapter, +struct OutlineSolver { + outer_builder: OutlineBuilder

, + inner_builder: OutlineBuilder

, + adapter: FloatPointAdapter

, points_count: usize, } -impl + 'static, T: FloatNumber + 'static> OutlineSolver { - fn prepare>(source: &S, style: &OutlineStyle) -> Option { +impl OutlineSolver

{ + fn prepare>(source: &S, style: &OutlineStyle) -> Option { let (points_count, paths_count) = { let mut points_count = 0; let mut paths_count = 0; @@ -227,8 +234,8 @@ impl + 'static, T: FloatNumber + 'static> OutlineSolv } let join = style.join.clone().normalize(); - let outer_builder = OutlineBuilder::new(-style.outer_offset, &join); - let inner_builder = OutlineBuilder::new(-style.inner_offset, &join); + let outer_builder: OutlineBuilder

= OutlineBuilder::new(-style.outer_offset, &join); + let inner_builder: OutlineBuilder

= OutlineBuilder::new(-style.inner_offset, &join); let outer_radius = style.outer_offset; let inner_radius = style.inner_offset; @@ -252,18 +259,18 @@ impl + 'static, T: FloatNumber + 'static> OutlineSolv } fn apply_scale(&mut self, scale: f64) -> Result<(), FixedScaleOverlayError> { - let s = T::from_float(scale); + let s = P::Scalar::from_float(scale); if self.adapter.dir_scale < s { return Err(FixedScaleOverlayError::ScaleTooLarge); } self.adapter.dir_scale = s; - self.adapter.inv_scale = T::from_float(1.0 / scale); + self.adapter.inv_scale = P::Scalar::from_float(1.0 / scale); Ok(()) } - fn build_overlay>(&self, source: &S, options: OverlayOptions) -> Overlay { + fn build_overlay>(&self, source: &S, options: OverlayOptions) -> Overlay { let total_capacity = self.outer_builder.capacity(self.points_count); let mut overlay = Overlay::new_custom( total_capacity, @@ -313,7 +320,7 @@ impl + 'static, T: FloatNumber + 'static> OutlineSolv overlay } - fn build>(self, source: &S, options: OverlayOptions) -> Shapes

{ + fn build>(self, source: &S, options: OverlayOptions) -> Shapes

{ let preserve_output_collinear = options.preserve_output_collinear; let clean_result = options.clean_result; let mut overlay = self.build_overlay(source, options); @@ -332,10 +339,10 @@ impl + 'static, T: FloatNumber + 'static> OutlineSolv } } - fn build_into>( + fn build_into>( self, source: &S, - options: OverlayOptions, + options: OverlayOptions, output: &mut FloatFlatContoursBuffer

, ) { let preserve_output_collinear = options.preserve_output_collinear; diff --git a/iOverlay/src/mesh/outline/section.rs b/iOverlay/src/mesh/outline/section.rs index e00a7c5..3f36e99 100644 --- a/iOverlay/src/mesh/outline/section.rs +++ b/iOverlay/src/mesh/outline/section.rs @@ -1,21 +1,18 @@ use crate::segm::boolean::ShapeCountBoolean; use crate::segm::segment::Segment; -use core::marker::PhantomData; use i_float::float::compatible::FloatPointCompatible; -use i_float::float::number::FloatNumber; use i_float::int::point::IntPoint; #[derive(Debug, Clone)] -pub(super) struct OffsetSection, T: FloatNumber> { +pub(super) struct OffsetSection { pub(super) a: IntPoint, pub(super) b: IntPoint, pub(super) a_top: IntPoint, pub(super) b_top: IntPoint, pub(super) dir: P, - pub(super) _phantom: PhantomData, } -impl, T: FloatNumber> OffsetSection { +impl OffsetSection

{ #[inline] pub(super) fn top_segment(&self) -> Option> { if self.a_top != self.b_top { diff --git a/iOverlay/src/mesh/rotator.rs b/iOverlay/src/mesh/rotator.rs index 5ab4e93..8e660ab 100644 --- a/iOverlay/src/mesh/rotator.rs +++ b/iOverlay/src/mesh/rotator.rs @@ -26,12 +26,12 @@ impl Rotator { } #[inline] - pub(crate) fn with_vector>(v: &P) -> Self { + pub(crate) fn with_vector>(v: &P) -> Self { Self::new(v.x(), v.y()) } #[inline] - pub(crate) fn rotate>(&self, v: &P) -> P { + pub(crate) fn rotate>(&self, v: &P) -> P { let v_x = v.x(); let v_y = v.y(); let x = self.a_x * v_x + self.b_x * v_y; diff --git a/iOverlay/src/mesh/stroke/builder.rs b/iOverlay/src/mesh/stroke/builder.rs index 8d6425a..5489573 100644 --- a/iOverlay/src/mesh/stroke/builder.rs +++ b/iOverlay/src/mesh/stroke/builder.rs @@ -10,38 +10,38 @@ use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; -trait StrokeBuild, T: FloatNumber> { +trait StrokeBuild { fn build( &self, path: &[P], is_closed_path: bool, - adapter: &FloatPointAdapter, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ); fn capacity(&self, paths_count: usize, points_count: usize, is_closed_path: bool) -> usize; - fn additional_offset(&self, radius: T) -> T; + fn additional_offset(&self, radius: P::Scalar) -> P::Scalar; } -pub(super) struct StrokeBuilder, T: FloatNumber> { - builder: Box>, +pub(super) struct StrokeBuilder { + builder: Box>, } -struct Builder, P: FloatPointCompatible, T: FloatNumber> { - radius: T, +struct Builder, P: FloatPointCompatible> { + radius: P::Scalar, join_builder: J, - start_cap_builder: CapBuilder, - end_cap_builder: CapBuilder, + start_cap_builder: CapBuilder

, + end_cap_builder: CapBuilder

, } -impl + 'static, T: FloatNumber + 'static> StrokeBuilder { - pub(super) fn new(style: StrokeStyle) -> StrokeBuilder { - let radius = T::from_float(0.5 * style.width.to_f64().max(0.0)); +impl StrokeBuilder

{ + pub(super) fn new(style: StrokeStyle

) -> StrokeBuilder

{ + let radius = P::Scalar::from_float(0.5 * style.width.to_f64().max(0.0)); let start_cap_builder = CapBuilder::new(style.start_cap.normalize(), radius); let end_cap_builder = CapBuilder::new(style.end_cap.normalize(), radius); - let builder: Box> = match style.join.normalize() { + let builder: Box> = match style.join.normalize() { LineJoin::Miter(ratio) => Box::new(Builder { radius, join_builder: MiterJoinBuilder::new(ratio, radius), @@ -70,7 +70,7 @@ impl + 'static, T: FloatNumber + 'static> StrokeBuild &self, path: &[P], is_closed_path: bool, - adapter: &FloatPointAdapter, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { self.builder.build(path, is_closed_path, adapter, segments); @@ -82,20 +82,18 @@ impl + 'static, T: FloatNumber + 'static> StrokeBuild } #[inline] - pub(super) fn additional_offset(&self, radius: T) -> T { + pub(super) fn additional_offset(&self, radius: P::Scalar) -> P::Scalar { self.builder.additional_offset(radius) } } -impl, P: FloatPointCompatible, T: FloatNumber> StrokeBuild - for Builder -{ +impl, P: FloatPointCompatible> StrokeBuild

for Builder { #[inline] fn build( &self, path: &[P], is_closed_path: bool, - adapter: &FloatPointAdapter, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { if is_closed_path { @@ -116,7 +114,7 @@ impl, P: FloatPointCompatible, T: FloatNumber> StrokeBui } #[inline] - fn additional_offset(&self, radius: T) -> T { + fn additional_offset(&self, radius: P::Scalar) -> P::Scalar { let start_cap = self.start_cap_builder.additional_offset(); let end_cap = self.end_cap_builder.additional_offset(); let join = self.join_builder.additional_offset(radius); @@ -124,11 +122,11 @@ impl, P: FloatPointCompatible, T: FloatNumber> StrokeBui } } -impl, P: FloatPointCompatible, T: FloatNumber> Builder { +impl, P: FloatPointCompatible> Builder { fn open_segments( &self, path: &[P], - adapter: &FloatPointAdapter, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { // build segments only from points which are not equal in int space @@ -181,7 +179,7 @@ impl, P: FloatPointCompatible, T: FloatNumber> Builder, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { if path.len() < 2 { @@ -214,7 +212,7 @@ impl, P: FloatPointCompatible, T: FloatNumber> Builder) -> usize { + fn next_unique_point(start: usize, index: usize, path: &[P], adapter: &FloatPointAdapter

) -> usize { let a = adapter.float_to_int(&path[start]); for (j, p) in path.iter().enumerate().skip(index) { let b = adapter.float_to_int(p); diff --git a/iOverlay/src/mesh/stroke/builder_cap.rs b/iOverlay/src/mesh/stroke/builder_cap.rs index a001300..12a6732 100644 --- a/iOverlay/src/mesh/stroke/builder_cap.rs +++ b/iOverlay/src/mesh/stroke/builder_cap.rs @@ -6,7 +6,6 @@ use crate::segm::segment::Segment; use alloc::vec; use alloc::vec::Vec; use core::f64::consts::PI; -use core::marker::PhantomData; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; @@ -14,13 +13,12 @@ use i_float::float::rect::FloatRect; use i_float::float::vector::FloatPointMath; #[derive(Debug, Clone)] -pub(super) struct CapBuilder { +pub(super) struct CapBuilder

{ points: Option>, - _phantom: PhantomData, } -impl> CapBuilder { - pub(super) fn new(cap: LineCap, radius: T) -> Self { +impl CapBuilder

{ + pub(super) fn new(cap: LineCap

, radius: P::Scalar) -> Self { let points = match cap { LineCap::Butt => None, LineCap::Round(ratio) => Some(Self::round_points(ratio, radius)), @@ -28,13 +26,10 @@ impl> CapBuilder { LineCap::Custom(points) => Some(Self::custom_points(points.to_vec(), radius)), }; - Self { - points, - _phantom: Default::default(), - } + Self { points } } - pub(super) fn round_points(angle: T, r: T) -> Vec

{ + pub(super) fn round_points(angle: P::Scalar, r: P::Scalar) -> Vec

{ let angle_f64 = angle.to_f64(); let n = if angle_f64 > 0.0 { let count = PI / angle_f64; @@ -43,9 +38,9 @@ impl> CapBuilder { 1024 }; - let fix_angle = T::from_float(PI / n as f64); + let fix_angle = P::Scalar::from_float(PI / n as f64); let rotator = Rotator::with_angle(fix_angle); - let mut v = P::from_xy(T::from_float(0.0), T::from_float(-1.0)); + let mut v = P::from_xy(P::Scalar::from_float(0.0), P::Scalar::from_float(-1.0)); let mut points = Vec::with_capacity(n); for _ in 1..n { v = rotator.rotate(&v); @@ -56,11 +51,11 @@ impl> CapBuilder { points } - pub(super) fn square_points(r: T) -> Vec

{ + pub(super) fn square_points(r: P::Scalar) -> Vec

{ vec![P::from_xy(r, -r), P::from_xy(r, r)] } - pub(super) fn custom_points(points: Vec

, r: T) -> Vec

{ + pub(super) fn custom_points(points: Vec

, r: P::Scalar) -> Vec

{ let mut scaled = points; let mut i = 0; while i < scaled.len() { @@ -73,8 +68,8 @@ impl> CapBuilder { pub(super) fn add_to_start( &self, - section: &Section, - adapter: &FloatPointAdapter, + section: &Section

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { let mut a = adapter.float_to_int(§ion.a_top); @@ -95,8 +90,8 @@ impl> CapBuilder { pub(super) fn add_to_end( &self, - section: &Section, - adapter: &FloatPointAdapter, + section: &Section

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { let mut a = adapter.float_to_int(§ion.b_bot); @@ -124,15 +119,15 @@ impl> CapBuilder { } #[inline] - pub(super) fn additional_offset(&self) -> T { + pub(super) fn additional_offset(&self) -> P::Scalar { if let Some(points) = &self.points { if let Some(rect) = FloatRect::with_iter(points.iter()) { rect.width() + rect.height() } else { - T::from_float(0.0) + P::Scalar::from_float(0.0) } } else { - T::from_float(0.0) + P::Scalar::from_float(0.0) } } } diff --git a/iOverlay/src/mesh/stroke/builder_join.rs b/iOverlay/src/mesh/stroke/builder_join.rs index 651428b..b3e0961 100644 --- a/iOverlay/src/mesh/stroke/builder_join.rs +++ b/iOverlay/src/mesh/stroke/builder_join.rs @@ -10,46 +10,46 @@ use i_float::float::compatible::FloatPointCompatible; use i_float::float::number::FloatNumber; use i_float::float::vector::FloatPointMath; -pub(super) trait JoinBuilder, T: FloatNumber> { +pub(super) trait JoinBuilder { fn add_join( &self, - s0: &Section, - s1: &Section, - adapter: &FloatPointAdapter, + s0: &Section

, + s1: &Section

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ); fn capacity(&self) -> usize; - fn additional_offset(&self, radius: T) -> T; + fn additional_offset(&self, radius: P::Scalar) -> P::Scalar; } pub(super) struct BevelJoinBuilder; impl BevelJoinBuilder { #[inline] - fn join_top>( - s0: &Section, - s1: &Section, - adapter: &FloatPointAdapter, + fn join_top( + s0: &Section

, + s1: &Section

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { Self::add_segment(&s0.b_top, &s1.a_top, adapter, segments); } #[inline] - fn join_bot>( - s0: &Section, - s1: &Section, - adapter: &FloatPointAdapter, + fn join_bot( + s0: &Section

, + s1: &Section

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { Self::add_segment(&s1.a_bot, &s0.b_bot, adapter, segments); } #[inline] - fn add_segment>( + fn add_segment( a: &P, b: &P, - adapter: &FloatPointAdapter, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { let ia = adapter.float_to_int(a); @@ -60,13 +60,13 @@ impl BevelJoinBuilder { } } -impl> JoinBuilder for BevelJoinBuilder { +impl JoinBuilder

for BevelJoinBuilder { #[inline] fn add_join( &self, - s0: &Section, - s1: &Section, - adapter: &FloatPointAdapter, + s0: &Section

, + s1: &Section

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { Self::join_top(s0, s1, adapter, segments); @@ -79,9 +79,9 @@ impl> JoinBuilder for BevelJoin } #[inline] - fn additional_offset(&self, radius: T) -> T { + fn additional_offset(&self, radius: P::Scalar) -> P::Scalar { // add extra 10% to avoid problems with floating point precision. - T::from_float(1.1) * radius + P::Scalar::from_float(1.1) * radius } } @@ -117,22 +117,22 @@ impl MiterJoinBuilder { } } -impl> JoinBuilder for MiterJoinBuilder { +impl JoinBuilder

for MiterJoinBuilder { fn add_join( &self, - s0: &Section, - s1: &Section, - adapter: &FloatPointAdapter, + s0: &Section

, + s1: &Section

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { let cross_product = FloatPointMath::cross_product(&s0.dir, &s1.dir); - if cross_product.abs() < T::from_float(0.0001) { + if cross_product.abs() < P::Scalar::from_float(0.0001) { BevelJoinBuilder::join_top(s0, s1, adapter, segments); BevelJoinBuilder::join_bot(s0, s1, adapter, segments); return; } - let turn = cross_product > T::from_float(0.0); + let turn = cross_product > P::Scalar::from_float(0.0); let dot_product = FloatPointMath::dot_product(&s0.dir, &s1.dir); @@ -211,7 +211,7 @@ impl> JoinBuilder for MiterJoin } #[inline] - fn additional_offset(&self, _radius: T) -> T { + fn additional_offset(&self, _radius: P::Scalar) -> P::Scalar { self.max_offset } } @@ -237,12 +237,12 @@ impl RoundJoinBuilder { } } } -impl> JoinBuilder for RoundJoinBuilder { +impl JoinBuilder

for RoundJoinBuilder { fn add_join( &self, - s0: &Section, - s1: &Section, - adapter: &FloatPointAdapter, + s0: &Section

, + s1: &Section

, + adapter: &FloatPointAdapter

, segments: &mut Vec>, ) { let dot_product = FloatPointMath::dot_product(&s0.dir, &s1.dir); @@ -254,10 +254,10 @@ impl> JoinBuilder for RoundJoin let angle = dot_product.acos(); let n = (angle * self.inv_ratio).to_usize(); - let delta_angle = angle / T::from_usize(n); + let delta_angle = angle / P::Scalar::from_usize(n); let cross_product = FloatPointMath::cross_product(&s0.dir, &s1.dir); - let (start, end, dir) = if cross_product > T::from_float(0.0) { + let (start, end, dir) = if cross_product > P::Scalar::from_float(0.0) { BevelJoinBuilder::join_top(s0, s1, adapter, segments); let ortho = P::from_xy(s1.dir.y(), -s1.dir.x()); (s1.a_bot, s0.b_bot, ortho) @@ -266,7 +266,7 @@ impl> JoinBuilder for RoundJoin let ortho = P::from_xy(-s0.dir.y(), s0.dir.x()); (s0.b_top, s1.a_top, ortho) }; - let rotator = Rotator::::with_angle(-delta_angle); + let rotator = Rotator::::with_angle(-delta_angle); let center = s0.b; let mut v = dir; @@ -294,8 +294,8 @@ impl> JoinBuilder for RoundJoin } #[inline] - fn additional_offset(&self, radius: T) -> T { + fn additional_offset(&self, radius: P::Scalar) -> P::Scalar { // add extra 10% to avoid problems with floating point precision. - T::from_float(1.1) * radius + P::Scalar::from_float(1.1) * radius } } diff --git a/iOverlay/src/mesh/stroke/offset.rs b/iOverlay/src/mesh/stroke/offset.rs index f66bcec..768e9f7 100644 --- a/iOverlay/src/mesh/stroke/offset.rs +++ b/iOverlay/src/mesh/stroke/offset.rs @@ -19,7 +19,7 @@ use i_shape::float::adapter::ShapesToFloat; use i_shape::float::despike::DeSpikeContour; use i_shape::float::simple::SimplifyContour; -pub trait StrokeOffset, T: FloatNumber> { +pub trait StrokeOffset { /// Generates a stroke shapes for paths, contours, or shapes. /// /// - `style`: Defines the stroke properties, including width, line caps, and joins. @@ -29,7 +29,7 @@ pub trait StrokeOffset, T: FloatNumber> { /// A collection of `Shapes

` representing the stroke geometry. /// /// Note: Outer boundary paths have a counterclockwise order, and holes have a clockwise order. - fn stroke(&self, style: StrokeStyle, is_closed_path: bool) -> Shapes

; + fn stroke(&self, style: StrokeStyle

, is_closed_path: bool) -> Shapes

; /// Generates stroke contours directly into a flat buffer. /// @@ -38,7 +38,7 @@ pub trait StrokeOffset, T: FloatNumber> { /// - `output`: Destination buffer that receives resulting contours. Existing contents are replaced. fn stroke_into( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, output: &mut FloatFlatContoursBuffer

, ); @@ -55,9 +55,9 @@ pub trait StrokeOffset, T: FloatNumber> { /// Note: Outer boundary paths have a **main_direction** order, and holes have an opposite to **main_direction** order. fn stroke_custom( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - options: OverlayOptions, + options: OverlayOptions, ) -> Shapes

; /// Generates stroke contours directly into a flat buffer with custom overlay options. @@ -68,9 +68,9 @@ pub trait StrokeOffset, T: FloatNumber> { /// - `output`: Destination buffer that receives resulting contours. Existing contents are replaced. fn stroke_custom_into( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - options: OverlayOptions, + options: OverlayOptions, output: &mut FloatFlatContoursBuffer

, ); @@ -86,9 +86,9 @@ pub trait StrokeOffset, T: FloatNumber> { /// Note: Outer boundary paths have a counterclockwise order, and holes have a clockwise order. fn stroke_fixed_scale( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError>; /// Generates stroke contours directly into a flat buffer with a fixed float-to-integer scale. @@ -99,9 +99,9 @@ pub trait StrokeOffset, T: FloatNumber> { /// - `output`: Destination buffer that receives resulting contours. Existing contents are replaced on success. fn stroke_fixed_scale_into( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - scale: T, + scale: P::Scalar, output: &mut FloatFlatContoursBuffer

, ) -> Result<(), FixedScaleOverlayError>; @@ -118,10 +118,10 @@ pub trait StrokeOffset, T: FloatNumber> { /// Note: Outer boundary paths have a **main_direction** order, and holes have an opposite to **main_direction** order. fn stroke_custom_fixed_scale( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - options: OverlayOptions, - scale: T, + options: OverlayOptions, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError>; /// Generates stroke contours directly into a flat buffer with custom options and fixed scaling. @@ -133,27 +133,26 @@ pub trait StrokeOffset, T: FloatNumber> { /// - `output`: Destination buffer that receives resulting contours. Existing contents are replaced on success. fn stroke_custom_fixed_scale_into( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - options: OverlayOptions, - scale: T, + options: OverlayOptions, + scale: P::Scalar, output: &mut FloatFlatContoursBuffer

, ) -> Result<(), FixedScaleOverlayError>; } -impl StrokeOffset for S +impl StrokeOffset

for S where - S: ShapeResource, - P: FloatPointCompatible + 'static, - T: FloatNumber + 'static, + S: ShapeResource

, + P: FloatPointCompatible + 'static, { - fn stroke(&self, style: StrokeStyle, is_closed_path: bool) -> Shapes

{ + fn stroke(&self, style: StrokeStyle

, is_closed_path: bool) -> Shapes

{ self.stroke_custom(style, is_closed_path, Default::default()) } fn stroke_into( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, output: &mut FloatFlatContoursBuffer

, ) { @@ -162,18 +161,18 @@ where fn stroke_fixed_scale( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - scale: T, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError> { self.stroke_custom_fixed_scale(style, is_closed_path, Default::default(), scale) } fn stroke_fixed_scale_into( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - scale: T, + scale: P::Scalar, output: &mut FloatFlatContoursBuffer

, ) -> Result<(), FixedScaleOverlayError> { self.stroke_custom_fixed_scale_into(style, is_closed_path, Default::default(), scale, output) @@ -181,9 +180,9 @@ where fn stroke_custom( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - options: OverlayOptions, + options: OverlayOptions, ) -> Shapes

{ match StrokeSolver::prepare(self, style) { Some(solver) => solver.build(self, is_closed_path, options), @@ -193,9 +192,9 @@ where fn stroke_custom_into( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - options: OverlayOptions, + options: OverlayOptions, output: &mut FloatFlatContoursBuffer

, ) { match StrokeSolver::prepare(self, style) { @@ -206,10 +205,10 @@ where fn stroke_custom_fixed_scale( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - options: OverlayOptions, - scale: T, + options: OverlayOptions, + scale: P::Scalar, ) -> Result, FixedScaleOverlayError> { let mut solver = match StrokeSolver::prepare(self, style) { Some(solver) => solver, @@ -221,10 +220,10 @@ where fn stroke_custom_fixed_scale_into( &self, - style: StrokeStyle, + style: StrokeStyle

, is_closed_path: bool, - options: OverlayOptions, - scale: T, + options: OverlayOptions, + scale: P::Scalar, output: &mut FloatFlatContoursBuffer

, ) -> Result<(), FixedScaleOverlayError> { let mut solver = match StrokeSolver::prepare(self, style) { @@ -240,16 +239,16 @@ where } } -struct StrokeSolver, T: FloatNumber> { - r: T, - builder: StrokeBuilder, - adapter: FloatPointAdapter, +struct StrokeSolver { + r: P::Scalar, + builder: StrokeBuilder

, + adapter: FloatPointAdapter

, paths_count: usize, points_count: usize, } -impl, T: 'static + FloatNumber> StrokeSolver { - fn prepare>(source: &S, style: StrokeStyle) -> Option { +impl StrokeSolver

{ + fn prepare>(source: &S, style: StrokeStyle

) -> Option { let mut paths_count = 0; let mut points_count = 0; for path in source.iter_paths() { @@ -261,7 +260,7 @@ impl, T: 'static + FloatNumber> StrokeSolve return None; } - let r = T::from_float(0.5 * style.width.to_f64()); + let r = P::Scalar::from_float(0.5 * style.width.to_f64()); let builder = StrokeBuilder::new(style); let a = builder.additional_offset(r); @@ -278,23 +277,23 @@ impl, T: 'static + FloatNumber> StrokeSolve }) } - fn apply_scale(&mut self, scale: T) -> Result<(), FixedScaleOverlayError> { + fn apply_scale(&mut self, scale: P::Scalar) -> Result<(), FixedScaleOverlayError> { let s = FixedScaleOverlayError::validate_scale(scale)?; if self.adapter.dir_scale < scale { return Err(FixedScaleOverlayError::ScaleTooLarge); } self.adapter.dir_scale = scale; - self.adapter.inv_scale = T::from_float(1.0 / s); + self.adapter.inv_scale = P::Scalar::from_float(1.0 / s); Ok(()) } - fn build>( + fn build>( self, source: &S, is_closed_path: bool, - options: OverlayOptions, + options: OverlayOptions, ) -> Shapes

{ let ir = self.adapter.len_float_to_int(self.r).abs(); if ir <= 1 { @@ -330,11 +329,11 @@ impl, T: 'static + FloatNumber> StrokeSolve float } - fn build_into>( + fn build_into>( self, source: &S, is_closed_path: bool, - options: OverlayOptions, + options: OverlayOptions, output: &mut FloatFlatContoursBuffer

, ) { let ir = self.adapter.len_float_to_int(self.r).abs(); diff --git a/iOverlay/src/mesh/stroke/section.rs b/iOverlay/src/mesh/stroke/section.rs index 9be4caf..2fcbdf2 100644 --- a/iOverlay/src/mesh/stroke/section.rs +++ b/iOverlay/src/mesh/stroke/section.rs @@ -2,14 +2,12 @@ use crate::mesh::math::Math; use crate::segm::boolean::ShapeCountBoolean; use crate::segm::segment::Segment; use alloc::vec::Vec; -use core::marker::PhantomData; use i_float::adapter::FloatPointAdapter; use i_float::float::compatible::FloatPointCompatible; -use i_float::float::number::FloatNumber; use i_float::float::vector::FloatPointMath; #[derive(Debug, Clone)] -pub(super) struct Section, T: FloatNumber> { +pub(super) struct Section { pub(super) a: P, pub(super) b: P, pub(super) a_top: P, @@ -17,11 +15,10 @@ pub(super) struct Section, T: FloatNumber> { pub(super) a_bot: P, pub(super) b_bot: P, pub(super) dir: P, - _phantom: PhantomData, } -impl> Section { - pub(crate) fn new(radius: T, a: &P, b: &P) -> Self { +impl Section

{ + pub(crate) fn new(radius: P::Scalar, a: &P, b: &P) -> Self { let dir = Math::normal(b, a); let t = Math::ortho_and_scale(&dir, radius); @@ -39,17 +36,16 @@ impl> Section { a_bot, b_bot, dir, - _phantom: Default::default(), } } } -pub(crate) trait SectionToSegment> { - fn add_section(&mut self, section: &Section, adapter: &FloatPointAdapter); +pub(crate) trait SectionToSegment { + fn add_section(&mut self, section: &Section

, adapter: &FloatPointAdapter

); } -impl> SectionToSegment for Vec> { - fn add_section(&mut self, section: &Section, adapter: &FloatPointAdapter) { +impl SectionToSegment

for Vec> { + fn add_section(&mut self, section: &Section

, adapter: &FloatPointAdapter

) { let a_top = adapter.float_to_int(§ion.a_top); let b_top = adapter.float_to_int(§ion.b_top); let a_bot = adapter.float_to_int(§ion.a_bot); diff --git a/iOverlay/src/mesh/style.rs b/iOverlay/src/mesh/style.rs index 5ddbf45..5d0d4c6 100644 --- a/iOverlay/src/mesh/style.rs +++ b/iOverlay/src/mesh/style.rs @@ -5,12 +5,12 @@ use i_float::float::number::FloatNumber; /// The endpoint style of a line. #[derive(Debug, Clone)] -pub enum LineCap, T: FloatNumber> { +pub enum LineCap { /// A line with a squared-off end. This is the default. Butt, /// A line with a rounded end. The line ends with a semicircular arc with a radius of 1/2 the line’s width, centered on the endpoint. /// Takes a parameter `Angle` in radians. - Round(T), + Round(P::Scalar), /// A line with a squared-off end. An extended distance equal to half the line width. Square, /// Set a custom end with template points. @@ -34,15 +34,15 @@ pub enum LineJoin { /// Defines the stroke style for outlining paths. #[derive(Debug, Clone)] -pub struct StrokeStyle, T: FloatNumber> { +pub struct StrokeStyle { /// The width of the stroke. - pub width: T, + pub width: P::Scalar, /// The cap style at the start of the stroke. - pub start_cap: LineCap, + pub start_cap: LineCap

, /// The cap style at the end of the stroke. - pub end_cap: LineCap, + pub end_cap: LineCap

, /// The join style where two lines meet. - pub join: LineJoin, + pub join: LineJoin, } /// Defines the outline style for offsetting shapes. @@ -53,11 +53,11 @@ pub struct OutlineStyle { pub join: LineJoin, } -impl, T: FloatNumber> LineCap { +impl LineCap

{ pub(crate) fn normalize(self) -> Self { if let LineCap::Round(angle) = self { let a = angle.to_f64().clamp(0.01 * PI, 0.25 * PI); - LineCap::Round(T::from_float(a)) + LineCap::Round(P::Scalar::from_float(a)) } else { self } @@ -80,9 +80,9 @@ impl LineJoin { } } -impl, T: FloatNumber> StrokeStyle { +impl StrokeStyle

{ /// Creates a new `StrokeStyle` with the specified width. - pub fn new(width: T) -> Self { + pub fn new(width: P::Scalar) -> Self { Self { width, ..Default::default() @@ -90,34 +90,34 @@ impl, T: FloatNumber> StrokeStyle { } /// Sets the stroke width. - pub fn width(mut self, width: T) -> Self { - self.width = T::from_float(width.to_f64().max(0.0)); + pub fn width(mut self, width: P::Scalar) -> Self { + self.width = P::Scalar::from_float(width.to_f64().max(0.0)); self } /// Sets the cap style at the start of the stroke. - pub fn start_cap(mut self, cap: LineCap) -> Self { + pub fn start_cap(mut self, cap: LineCap

) -> Self { self.start_cap = cap.normalize(); self } /// Sets the cap style at the end of the stroke. - pub fn end_cap(mut self, cap: LineCap) -> Self { + pub fn end_cap(mut self, cap: LineCap

) -> Self { self.end_cap = cap.normalize(); self } /// Sets the line join style. - pub fn line_join(mut self, join: LineJoin) -> Self { + pub fn line_join(mut self, join: LineJoin) -> Self { self.join = join.normalize(); self } } -impl, T: FloatNumber> Default for StrokeStyle { +impl Default for StrokeStyle

{ fn default() -> Self { Self { - width: T::from_float(1.0), + width: P::Scalar::from_float(1.0), start_cap: LineCap::Butt, end_cap: LineCap::Butt, join: LineJoin::Bevel, diff --git a/iOverlay/tests/doc_tests.rs b/iOverlay/tests/doc_tests.rs index 40e09da..0a07eae 100644 --- a/iOverlay/tests/doc_tests.rs +++ b/iOverlay/tests/doc_tests.rs @@ -50,7 +50,9 @@ mod tests { y: f32, } - impl FloatPointCompatible for CustomPoint { + impl FloatPointCompatible for CustomPoint { + type Scalar = f32; + fn from_xy(x: f32, y: f32) -> Self { Self { x, y } } diff --git a/iOverlay/tests/float_overlay_tests.rs b/iOverlay/tests/float_overlay_tests.rs index 41d4ad9..d51606f 100644 --- a/iOverlay/tests/float_overlay_tests.rs +++ b/iOverlay/tests/float_overlay_tests.rs @@ -23,7 +23,9 @@ mod tests { } } - impl FloatPointCompatible for FPoint { + impl FloatPointCompatible for FPoint { + type Scalar = f32; + fn from_xy(x: f32, y: f32) -> Self { Self { x, y } }