diff --git a/editor/src/draw/path.rs b/editor/src/draw/path.rs index 964f3a4..544552d 100644 --- a/editor/src/draw/path.rs +++ b/editor/src/draw/path.rs @@ -1,7 +1,7 @@ use i_mesh::path::butt::ButtStrokeBuilder; use i_mesh::path::style::StrokeStyle; -use i_triangle::float::builder::TriangulationBuilder; -use i_triangle::float::triangulation::Triangulation; +use i_triangle::generic::builder::TriangulationBuilder; +use i_triangle::generic::triangulation::Triangulation; use i_triangle::i_overlay::i_float::float::point::FloatPoint; use i_triangle::i_overlay::i_float::int::point::IntPoint; use i_triangle::i_overlay::i_shape::int::path::{IntPath, IntPaths}; diff --git a/editor/src/mesh/path_builder.rs b/editor/src/mesh/path_builder.rs index bef8d9b..88f90bf 100644 --- a/editor/src/mesh/path_builder.rs +++ b/editor/src/mesh/path_builder.rs @@ -1,6 +1,6 @@ use i_mesh::path::butt::ButtStrokeBuilder; use i_mesh::path::style::StrokeStyle; -use i_triangle::float::builder::TriangulationBuilder; +use i_triangle::generic::builder::TriangulationBuilder; use i_triangle::i_overlay::i_float::float::point::FloatPoint; use i_triangle::i_overlay::i_float::int::point::IntPoint; use iced::{Color, Rectangle, Transformation}; diff --git a/iTriangle/README.md b/iTriangle/README.md index cc14cb8..32797e5 100644 --- a/iTriangle/README.md +++ b/iTriangle/README.md @@ -50,7 +50,8 @@ iTriangle is a high-performance 2D polygon triangulation library for Rust. It tu iTriangle is designed around a deterministic integer core: -- Floating-point APIs accept `f32` and `f64` compatible point types, then map them into integer coordinates before triangulation. +- Generic API accepts `f32` and `f64` compatible point types, then maps them into integer coordinates before triangulation. +- You can also pass `i16`, `i32`, or `i64` coordinates to the generic API - it applies an identity map on them. - Integer APIs work directly with `i16`, `i32`, or `i64` coordinates when your geometry is already quantized. - `i32` is the default integer coordinate type for floating-point input. - `i64` is useful for larger coordinate ranges or finer fixed precision. @@ -72,7 +73,7 @@ i_triangle = "0.45" Minimal example: ```rust -use i_triangle::float::triangulatable::Triangulatable; +use i_triangle::generic::triangulatable::Triangulatable; let contour = vec![ [0.0, 0.0], @@ -90,8 +91,8 @@ coordinates. If your geometry needs a different integer precision, choose it explicitly: ```rust -use i_triangle::float::triangulatable::Triangulatable; -use i_triangle::float::triangulator::Triangulator; +use i_triangle::generic::triangulatable::TriangulatableAs; +use i_triangle::generic::triangulator::Triangulator; let shape = vec![vec![ [0.0, 0.0], @@ -121,8 +122,8 @@ let mesh = triangulator.triangulate(&shape); ```rust -use i_triangle::float::triangulatable::Triangulatable; -use i_triangle::float::triangulation::Triangulation; +use i_triangle::generic::triangulatable::Triangulatable; +use i_triangle::generic::triangulation::Triangulation; let shape = vec![ vec![ @@ -199,8 +200,8 @@ println!("centroids: {:?}", centroids); If you need to triangulate many shapes, it is more efficient to use `Triangulator`. ```rust -use i_triangle::float::triangulation::Triangulation; -use i_triangle::float::triangulator::Triangulator; +use i_triangle::generic::triangulation::Triangulation; +use i_triangle::generic::triangulator::Triangulator; let contours = vec![ vec![[0.0, 0.0], [4.0, 0.0], [4.0, 4.0], [0.0, 4.0]], diff --git a/iTriangle/src/float/centroid_net.rs b/iTriangle/src/float/centroid_net.rs deleted file mode 100644 index 92c3191..0000000 --- a/iTriangle/src/float/centroid_net.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::float::delaunay::Delaunay; -use alloc::vec::Vec; -use i_overlay::i_float::float::compatible::FloatPointCompatible; -use i_overlay::i_float::int::number::int::IntNumber; -use i_overlay::i_float::int::number::wide_int::WideIntNumber; -use i_overlay::i_shape::base::data::Contour; -use i_overlay::i_shape::float::adapter::ShapeToFloat; - -impl Delaunay { - #[inline] - pub fn to_centroid_net(&self, min_area: P::Scalar) -> Vec> { - let int_area = self.adapter.round_sqr_len_to_int(min_area); - self.delaunay - .centroid_net(int_area.to_uint()) - .to_float(&self.adapter) - } -} diff --git a/iTriangle/src/float/circumcenter.rs b/iTriangle/src/float/circumcenter.rs deleted file mode 100644 index ea62256..0000000 --- a/iTriangle/src/float/circumcenter.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::float::delaunay::Delaunay; -use i_overlay::i_float::float::compatible::FloatPointCompatible; -use i_overlay::i_float::int::number::int::IntNumber; -use i_overlay::i_float::int::number::wide_int::WideIntNumber; - -impl Delaunay { - #[inline] - pub fn refine_with_circumcenters(mut self, min_area: P::Scalar) -> Self { - self.refine_with_circumcenters_mut(min_area); - self - } - - #[inline] - pub fn refine_with_circumcenters_by_obtuse_angle(mut self, min_area: P::Scalar) -> Self { - self.refine_with_circumcenters_by_obtuse_angle_mut(min_area); - self - } - - #[inline] - pub fn refine_with_circumcenters_mut(&mut self, min_area: P::Scalar) { - let int_area = self.adapter.round_sqr_len_to_int(min_area); - self.delaunay - .refine_with_circumcenters_mut(int_area.to_uint()); - } - - #[inline] - pub fn refine_with_circumcenters_by_obtuse_angle_mut(&mut self, min_area: P::Scalar) { - let int_area = self.adapter.round_sqr_len_to_int(min_area); - self.delaunay - .refine_with_circumcenters_by_obtuse_angle_mut(int_area.to_uint()); - } -} diff --git a/iTriangle/src/float/convex.rs b/iTriangle/src/float/convex.rs deleted file mode 100644 index 4fd3ac1..0000000 --- a/iTriangle/src/float/convex.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::float::delaunay::Delaunay; -use alloc::vec::Vec; -use i_overlay::i_float::float::compatible::FloatPointCompatible; -use i_overlay::i_float::int::number::int::IntNumber; -use i_overlay::i_shape::base::data::Contour; -use i_overlay::i_shape::float::adapter::ShapeToFloat; - -impl Delaunay { - /// Groups triangles into non-overlapping convex polygons in counter-clockwise order. - /// - /// Returns a list of float-based [`Contour

`]s. - #[inline] - pub fn to_convex_polygons(&self) -> Vec> { - self.delaunay.to_convex_polygons().to_float(&self.adapter) - } -} diff --git a/iTriangle/src/float/custom.rs b/iTriangle/src/float/custom.rs deleted file mode 100644 index 3925327..0000000 --- a/iTriangle/src/float/custom.rs +++ /dev/null @@ -1,178 +0,0 @@ -use crate::float::triangulation::RawTriangulation; -use crate::int::custom::IntCustomTriangulatable; -use crate::int::triangulation::RawIntTriangulation; -use crate::int::validation::Validation; -use i_key_sort::sort::key::SortKey; -use i_overlay::i_float::adapter::FloatPointAdapter; -use i_overlay::i_float::float::compatible::FloatPointCompatible; -use i_overlay::i_float::float::rect::FloatRect; -use i_overlay::i_float::int::number::int::IntNumber; -use i_overlay::i_shape::base::data::{Contour, Shape}; -use i_overlay::i_shape::float::adapter::{PathToInt, ShapeToInt, ShapesToInt}; -use i_overlay::i_shape::float::rect::RectInit; -use i_tree::{Expiration, LayoutNumber}; - -/// A trait for triangulating float geometry with user-defined validation rules. -/// -/// Accepts a custom [`Validation`] object for tuning fill rule, min area, etc. -pub trait CustomTriangulatable { - /// Performs triangulation using the specified [`Validation`] settings. - fn custom_triangulate(&self, validation: Validation) -> RawTriangulation

{ - self.custom_triangulate_as(validation) - } - - /// Performs triangulation using the requested integer coordinate type. - fn custom_triangulate_as(&self, validation: Validation) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey; - - /// Performs triangulation with Steiner points and a custom [`Validation`] config. - fn custom_triangulate_with_steiner_points( - &self, - points: &[P], - validation: Validation, - ) -> RawTriangulation

{ - self.custom_triangulate_with_steiner_points_as(points, validation) - } - - /// Performs triangulation with Steiner points using the requested integer coordinate type. - fn custom_triangulate_with_steiner_points_as( - &self, - points: &[P], - validation: Validation, - ) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey; -} - -impl

CustomTriangulatable

for Contour

-where - P: FloatPointCompatible, -{ - fn custom_triangulate_as(&self, validation: Validation) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_path(self) { - let adapter = FloatPointAdapter::::new(rect); - let raw = self.to_int(&adapter).custom_triangulate(validation); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } - - fn custom_triangulate_with_steiner_points_as( - &self, - points: &[P], - validation: Validation, - ) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_path(self) { - let adapter = FloatPointAdapter::::new(rect); - let float_points = points.to_int(&adapter); - let raw = self - .to_int(&adapter) - .custom_triangulate_with_steiner_points(&float_points, validation); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } -} - -impl

CustomTriangulatable

for [Contour

] -where - P: FloatPointCompatible, -{ - fn custom_triangulate_as(&self, validation: Validation) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let raw = self.to_int(&adapter).custom_triangulate(validation); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } - - fn custom_triangulate_with_steiner_points_as( - &self, - points: &[P], - validation: Validation, - ) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let float_points = points.to_int(&adapter); - let raw = self - .to_int(&adapter) - .custom_triangulate_with_steiner_points(&float_points, validation); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } -} - -impl

CustomTriangulatable

for [Shape

] -where - P: FloatPointCompatible, -{ - fn custom_triangulate_as(&self, validation: Validation) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_list_of_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let raw = self.to_int(&adapter).custom_triangulate(validation); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } - - fn custom_triangulate_with_steiner_points_as( - &self, - points: &[P], - validation: Validation, - ) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_list_of_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let float_points = points.to_int(&adapter); - let raw = self - .to_int(&adapter) - .custom_triangulate_with_steiner_points(&float_points, validation); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } -} diff --git a/iTriangle/src/float/triangulatable.rs b/iTriangle/src/float/triangulatable.rs deleted file mode 100644 index 32c057f..0000000 --- a/iTriangle/src/float/triangulatable.rs +++ /dev/null @@ -1,167 +0,0 @@ -use crate::float::triangulation::RawTriangulation; -use crate::int::triangulatable::IntTriangulatable; -use crate::int::triangulation::RawIntTriangulation; -use i_key_sort::sort::key::SortKey; -use i_overlay::i_float::adapter::FloatPointAdapter; -use i_overlay::i_float::float::compatible::FloatPointCompatible; -use i_overlay::i_float::float::rect::FloatRect; -use i_overlay::i_float::int::number::int::IntNumber; -use i_overlay::i_shape::base::data::{Contour, Shape}; -use i_overlay::i_shape::float::adapter::{PathToInt, ShapeToInt, ShapesToInt}; -use i_overlay::i_shape::float::rect::RectInit; -use i_tree::{Expiration, LayoutNumber}; - -/// A trait for triangulating float-based geometry with default validation. -/// -/// Automatically converts the input to integer space, applies validation, -/// and returns a float-mapped result. -/// -/// # Implemented For -/// - `Contour

` -/// - `[Contour

]` -/// - `[Shape

]` -pub trait Triangulatable { - /// Triangulates the shape(s) using the default [`Triangulator`] configuration. - /// - /// Validation includes contour simplification, direction correction, and area filtering. - fn triangulate(&self) -> RawTriangulation

{ - self.triangulate_as::() - } - - /// Triangulates the shape(s) using the requested integer coordinate type. - fn triangulate_as(&self) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey; - - /// Triangulates the shape(s) and inserts the given Steiner points. - /// - /// Points must lie strictly within the interior of the geometry. - fn triangulate_with_steiner_points(&self, points: &[P]) -> RawTriangulation

{ - self.triangulate_with_steiner_points_as::(points) - } - - /// Triangulates the shape(s) with Steiner points using the requested integer coordinate type. - fn triangulate_with_steiner_points_as(&self, points: &[P]) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey; -} - -impl

Triangulatable

for [P] -where - P: FloatPointCompatible, -{ - fn triangulate_as(&self) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_path(self) { - let adapter = FloatPointAdapter::::new(rect); - let raw = self.to_int(&adapter).triangulate(); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } - - fn triangulate_with_steiner_points_as(&self, points: &[P]) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_path(self) { - let adapter = FloatPointAdapter::::new(rect); - let float_points = points.to_int(&adapter); - let raw = self - .to_int(&adapter) - .triangulate_with_steiner_points(&float_points); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } -} - -impl

Triangulatable

for [Contour

] -where - P: FloatPointCompatible, -{ - fn triangulate_as(&self) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let raw = self.to_int(&adapter).triangulate(); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } - - fn triangulate_with_steiner_points_as(&self, points: &[P]) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let float_points = points.to_int(&adapter); - let raw = self - .to_int(&adapter) - .triangulate_with_steiner_points(&float_points); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } -} - -impl

Triangulatable

for [Shape

] -where - P: FloatPointCompatible, -{ - fn triangulate_as(&self) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_list_of_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let raw = self.to_int(&adapter).triangulate(); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } - - fn triangulate_with_steiner_points_as(&self, points: &[P]) -> RawTriangulation - where - I: IntNumber + Expiration + LayoutNumber + SortKey, - { - if let Some(rect) = FloatRect::with_list_of_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let float_points = points.to_int(&adapter); - let raw = self - .to_int(&adapter) - .triangulate_with_steiner_points(&float_points); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } -} diff --git a/iTriangle/src/float/unchecked.rs b/iTriangle/src/float/unchecked.rs deleted file mode 100644 index 4356aaa..0000000 --- a/iTriangle/src/float/unchecked.rs +++ /dev/null @@ -1,174 +0,0 @@ -use crate::float::triangulation::RawTriangulation; -use crate::int::triangulation::RawIntTriangulation; -use crate::int::unchecked::IntUncheckedTriangulatable; -use i_key_sort::sort::key::SortKey; -use i_overlay::i_float::adapter::FloatPointAdapter; -use i_overlay::i_float::float::compatible::FloatPointCompatible; -use i_overlay::i_float::float::rect::FloatRect; -use i_overlay::i_float::int::number::int::IntNumber; -use i_overlay::i_shape::base::data::{Contour, Shape}; -use i_overlay::i_shape::float::adapter::{PathToInt, ShapeToInt, ShapesToInt}; -use i_overlay::i_shape::float::rect::RectInit; -use i_tree::Expiration; - -/// A trait for triangulating already valid float-based geometry. -/// -/// Skips all validation for performance. Ideal when input is generated programmatically. -/// -/// # Safety Requirements -/// - Outer contours must be counter-clockwise -/// - Holes must be clockwise -/// - Steiner points must lie strictly within the shape -pub trait UncheckedTriangulatable { - /// Triangulates float geometry without validation or simplification. - fn unchecked_triangulate(&self) -> RawTriangulation

{ - self.unchecked_triangulate_as::() - } - - /// Triangulates float geometry without validation using the requested integer coordinate type. - fn unchecked_triangulate_as(&self) -> RawTriangulation - where - I: IntNumber + Expiration + SortKey; - - /// Same as `unchecked_triangulate`, but inserts user-defined Steiner points. - fn unchecked_triangulate_with_steiner_points(&self, points: &[P]) -> RawTriangulation

{ - self.unchecked_triangulate_with_steiner_points_as::(points) - } - - /// Same as `unchecked_triangulate_as`, but inserts user-defined Steiner points. - fn unchecked_triangulate_with_steiner_points_as( - &self, - points: &[P], - ) -> RawTriangulation - where - I: IntNumber + Expiration + SortKey; -} - -impl

UncheckedTriangulatable

for [P] -where - P: FloatPointCompatible, -{ - fn unchecked_triangulate_as(&self) -> RawTriangulation - where - I: IntNumber + Expiration + SortKey, - { - if let Some(rect) = FloatRect::with_path(self) { - let adapter = FloatPointAdapter::::new(rect); - let raw = self.to_int(&adapter).uncheck_triangulate(); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } - - fn unchecked_triangulate_with_steiner_points_as( - &self, - points: &[P], - ) -> RawTriangulation - where - I: IntNumber + Expiration + SortKey, - { - if let Some(rect) = FloatRect::with_path(self) { - let adapter = FloatPointAdapter::::new(rect); - let float_points = points.to_int(&adapter); - let raw = self - .to_int(&adapter) - .uncheck_triangulate_with_steiner_points(&float_points); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } -} - -impl

UncheckedTriangulatable

for [Contour

] -where - P: FloatPointCompatible, -{ - fn unchecked_triangulate_as(&self) -> RawTriangulation - where - I: IntNumber + Expiration + SortKey, - { - if let Some(rect) = FloatRect::with_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let raw = self.to_int(&adapter).uncheck_triangulate(); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } - - fn unchecked_triangulate_with_steiner_points_as( - &self, - points: &[P], - ) -> RawTriangulation - where - I: IntNumber + Expiration + SortKey, - { - if let Some(rect) = FloatRect::with_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let float_points = points.to_int(&adapter); - let raw = self - .to_int(&adapter) - .uncheck_triangulate_with_steiner_points(&float_points); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } -} - -impl

UncheckedTriangulatable

for [Shape

] -where - P: FloatPointCompatible, -{ - fn unchecked_triangulate_as(&self) -> RawTriangulation - where - I: IntNumber + Expiration + SortKey, - { - if let Some(rect) = FloatRect::with_list_of_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let raw = self.to_int(&adapter).uncheck_triangulate(); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } - - fn unchecked_triangulate_with_steiner_points_as( - &self, - points: &[P], - ) -> RawTriangulation - where - I: IntNumber + Expiration + SortKey, - { - if let Some(rect) = FloatRect::with_list_of_paths(self) { - let adapter = FloatPointAdapter::::new(rect); - let float_points = points.to_int(&adapter); - let raw = self - .to_int(&adapter) - .uncheck_triangulate_with_steiner_points(&float_points); - RawTriangulation { raw, adapter } - } else { - RawTriangulation { - raw: RawIntTriangulation::default(), - adapter: FloatPointAdapter::::new(FloatRect::zero()), - } - } - } -} diff --git a/iTriangle/src/generic/adapter.rs b/iTriangle/src/generic/adapter.rs new file mode 100644 index 0000000..4f7db5c --- /dev/null +++ b/iTriangle/src/generic/adapter.rs @@ -0,0 +1,88 @@ +use alloc::vec::Vec; +use core::marker::PhantomData; +use i_overlay::i_float::adapter::FloatPointAdapter; +use i_overlay::i_float::float::compatible::FloatPointCompatible; +use i_overlay::i_float::int::number::int::IntNumber; +use i_overlay::i_float::int::number::wide_int::WideIntNumber; +use i_overlay::i_float::int::point::IntPoint; + +pub trait PointAdapter: Clone { + type Point: Clone; + type Int: IntNumber; + type Measure: Copy; + + fn to_int_point(&self, point: &Self::Point) -> IntPoint; + fn from_int_point(&self, point: &IntPoint) -> Self::Point; + + fn measure_to_int_area(&self, measure: Self::Measure) -> ::WideUInt; + + #[inline] + fn points_to_int(&self, points: &[Self::Point]) -> Vec> { + points.iter().map(|p| self.to_int_point(p)).collect() + } + + #[inline] + fn points_from_int(&self, points: &[IntPoint]) -> Vec { + points.iter().map(|p| self.from_int_point(p)).collect() + } +} + +#[derive(Debug, Clone, Copy, Default)] +pub struct IntPointAdapter { + marker: PhantomData, +} + +impl IntPointAdapter { + #[inline] + pub const fn new() -> Self { + Self { + marker: PhantomData, + } + } +} + +impl PointAdapter for IntPointAdapter { + type Point = IntPoint; + type Int = I; + type Measure = I::WideUInt; + + #[inline] + fn to_int_point(&self, point: &Self::Point) -> IntPoint { + *point + } + + #[inline] + fn from_int_point(&self, point: &IntPoint) -> Self::Point { + *point + } + + #[inline] + fn measure_to_int_area(&self, measure: Self::Measure) -> I::WideUInt { + measure + } +} + +impl PointAdapter for FloatPointAdapter +where + P: FloatPointCompatible, + I: IntNumber, +{ + type Point = P; + type Int = I; + type Measure = P::Scalar; + + #[inline] + fn to_int_point(&self, point: &P) -> IntPoint { + self.float_to_int(point) + } + + #[inline] + fn from_int_point(&self, point: &IntPoint) -> P { + self.int_to_float(point) + } + + #[inline] + fn measure_to_int_area(&self, measure: P::Scalar) -> I::WideUInt { + self.round_sqr_len_to_int(measure).to_uint() + } +} diff --git a/iTriangle/src/float/builder.rs b/iTriangle/src/generic/builder.rs similarity index 96% rename from iTriangle/src/float/builder.rs rename to iTriangle/src/generic/builder.rs index 68814f3..54491a3 100644 --- a/iTriangle/src/float/builder.rs +++ b/iTriangle/src/generic/builder.rs @@ -1,4 +1,4 @@ -use crate::float::triangulation::Triangulation; +use crate::generic::triangulation::Triangulation; use crate::int::triangulation::IndexType; use alloc::vec::Vec; diff --git a/iTriangle/src/generic/centroid_net.rs b/iTriangle/src/generic/centroid_net.rs new file mode 100644 index 0000000..d911bab --- /dev/null +++ b/iTriangle/src/generic/centroid_net.rs @@ -0,0 +1,16 @@ +use crate::generic::adapter::PointAdapter; +use crate::generic::delaunay::Delaunay; +use alloc::vec::Vec; +use i_overlay::i_shape::base::data::Contour; + +impl Delaunay { + #[inline] + pub fn to_centroid_net(&self, min_area: A::Measure) -> Vec> { + let int_area = self.adapter.measure_to_int_area(min_area); + self.delaunay + .centroid_net(int_area) + .into_iter() + .map(|contour| self.adapter.points_from_int(&contour)) + .collect() + } +} diff --git a/iTriangle/src/generic/circumcenter.rs b/iTriangle/src/generic/circumcenter.rs new file mode 100644 index 0000000..966829d --- /dev/null +++ b/iTriangle/src/generic/circumcenter.rs @@ -0,0 +1,29 @@ +use crate::generic::adapter::PointAdapter; +use crate::generic::delaunay::Delaunay; + +impl Delaunay { + #[inline] + pub fn refine_with_circumcenters(mut self, min_area: A::Measure) -> Self { + self.refine_with_circumcenters_mut(min_area); + self + } + + #[inline] + pub fn refine_with_circumcenters_by_obtuse_angle(mut self, min_area: A::Measure) -> Self { + self.refine_with_circumcenters_by_obtuse_angle_mut(min_area); + self + } + + #[inline] + pub fn refine_with_circumcenters_mut(&mut self, min_area: A::Measure) { + let int_area = self.adapter.measure_to_int_area(min_area); + self.delaunay.refine_with_circumcenters_mut(int_area); + } + + #[inline] + pub fn refine_with_circumcenters_by_obtuse_angle_mut(&mut self, min_area: A::Measure) { + let int_area = self.adapter.measure_to_int_area(min_area); + self.delaunay + .refine_with_circumcenters_by_obtuse_angle_mut(int_area); + } +} diff --git a/iTriangle/src/generic/convex.rs b/iTriangle/src/generic/convex.rs new file mode 100644 index 0000000..bc49a1d --- /dev/null +++ b/iTriangle/src/generic/convex.rs @@ -0,0 +1,18 @@ +use crate::generic::adapter::PointAdapter; +use crate::generic::delaunay::Delaunay; +use alloc::vec::Vec; +use i_overlay::i_shape::base::data::Contour; + +impl Delaunay { + /// Groups triangles into non-overlapping convex polygons in counter-clockwise order. + /// + /// Returns a list of adapter-mapped [`Contour`]s. + #[inline] + pub fn to_convex_polygons(&self) -> Vec> { + self.delaunay + .to_convex_polygons() + .into_iter() + .map(|contour| self.adapter.points_from_int(&contour)) + .collect() + } +} diff --git a/iTriangle/src/generic/custom.rs b/iTriangle/src/generic/custom.rs new file mode 100644 index 0000000..d862c16 --- /dev/null +++ b/iTriangle/src/generic/custom.rs @@ -0,0 +1,365 @@ +use crate::generic::adapter::{IntPointAdapter, PointAdapter}; +use crate::generic::triangulation::RawTriangulation; +use crate::int::custom::IntCustomTriangulatable; +use crate::int::triangulation::RawIntTriangulation; +use crate::int::validation::Validation; +use i_key_sort::sort::key::SortKey; +use i_overlay::i_float::adapter::FloatPointAdapter; +use i_overlay::i_float::float::compatible::FloatPointCompatible; +use i_overlay::i_float::float::rect::FloatRect; +use i_overlay::i_float::int::number::int::IntNumber; +use i_overlay::i_float::int::point::IntPoint; +use i_overlay::i_shape::base::data::{Contour, Shape}; +use i_overlay::i_shape::float::rect::RectInit; +use i_overlay::i_shape::int::shape::{IntContour, IntShape, IntShapes}; +use i_tree::{Expiration, LayoutNumber}; + +/// A trait for triangulating geometry with user-defined validation rules. +/// +/// Accepts a custom [`Validation`] object for tuning fill rule, min area, etc. +pub trait CustomTriangulatable

{ + type Adapter: PointAdapter; + + /// Performs triangulation using the specified [`Validation`] settings. + fn custom_triangulate( + &self, + validation: Validation<::Int>, + ) -> RawTriangulation; + + /// Performs triangulation with Steiner points and a custom [`Validation`] config. + fn custom_triangulate_with_steiner_points( + &self, + points: &[P], + validation: Validation<::Int>, + ) -> RawTriangulation; +} + +/// Float-only. You can choose the integer coordinate type to be used internally +/// by the triangulator. +pub trait CustomTriangulatableAs: CustomTriangulatable

{ + /// Performs triangulation using the requested integer coordinate type. + fn custom_triangulate_as( + &self, + validation: Validation, + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey; + + /// Performs triangulation with Steiner points using the requested integer coordinate type. + fn custom_triangulate_with_steiner_points_as( + &self, + points: &[P], + validation: Validation, + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey; +} + +impl

CustomTriangulatable

for [P] +where + P: FloatPointCompatible, +{ + type Adapter = FloatPointAdapter; + + #[inline] + fn custom_triangulate(&self, validation: Validation) -> RawTriangulation { + self.custom_triangulate_as(validation) + } + + #[inline] + fn custom_triangulate_with_steiner_points( + &self, + points: &[P], + validation: Validation, + ) -> RawTriangulation { + self.custom_triangulate_with_steiner_points_as(points, validation) + } +} + +impl

CustomTriangulatableAs

for [P] +where + P: FloatPointCompatible, +{ + fn custom_triangulate_as( + &self, + validation: Validation, + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_path(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_contour: IntContour = adapter.points_to_int(self); + let raw = IntCustomTriangulatable::custom_triangulate(&int_contour, validation); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } + + fn custom_triangulate_with_steiner_points_as( + &self, + points: &[P], + validation: Validation, + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_path(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_points = adapter.points_to_int(points); + let int_contour: IntContour = adapter.points_to_int(self); + let raw = IntCustomTriangulatable::custom_triangulate_with_steiner_points( + &int_contour, + &int_points, + validation, + ); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } +} + +impl

CustomTriangulatable

for [Contour

] +where + P: FloatPointCompatible, +{ + type Adapter = FloatPointAdapter; + + #[inline] + fn custom_triangulate(&self, validation: Validation) -> RawTriangulation { + self.custom_triangulate_as(validation) + } + + #[inline] + fn custom_triangulate_with_steiner_points( + &self, + points: &[P], + validation: Validation, + ) -> RawTriangulation { + self.custom_triangulate_with_steiner_points_as(points, validation) + } +} + +impl

CustomTriangulatableAs

for [Contour

] +where + P: FloatPointCompatible, +{ + fn custom_triangulate_as( + &self, + validation: Validation, + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_shape: IntShape = self.iter().map(|c| adapter.points_to_int(c)).collect(); + let raw = IntCustomTriangulatable::custom_triangulate(&int_shape, validation); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } + + fn custom_triangulate_with_steiner_points_as( + &self, + points: &[P], + validation: Validation, + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_points = adapter.points_to_int(points); + let int_shape: IntShape = self.iter().map(|c| adapter.points_to_int(c)).collect(); + let raw = IntCustomTriangulatable::custom_triangulate_with_steiner_points( + &int_shape, + &int_points, + validation, + ); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } +} + +impl

CustomTriangulatable

for [Shape

] +where + P: FloatPointCompatible, +{ + type Adapter = FloatPointAdapter; + + #[inline] + fn custom_triangulate(&self, validation: Validation) -> RawTriangulation { + self.custom_triangulate_as(validation) + } + + #[inline] + fn custom_triangulate_with_steiner_points( + &self, + points: &[P], + validation: Validation, + ) -> RawTriangulation { + self.custom_triangulate_with_steiner_points_as(points, validation) + } +} + +impl

CustomTriangulatableAs

for [Shape

] +where + P: FloatPointCompatible, +{ + fn custom_triangulate_as( + &self, + validation: Validation, + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_list_of_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_shapes: IntShapes = self + .iter() + .map(|shape| shape.iter().map(|c| adapter.points_to_int(c)).collect()) + .collect(); + let raw = IntCustomTriangulatable::custom_triangulate(&int_shapes, validation); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } + + fn custom_triangulate_with_steiner_points_as( + &self, + points: &[P], + validation: Validation, + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_list_of_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_points = adapter.points_to_int(points); + let int_shapes: IntShapes = self + .iter() + .map(|shape| shape.iter().map(|c| adapter.points_to_int(c)).collect()) + .collect(); + let raw = IntCustomTriangulatable::custom_triangulate_with_steiner_points( + &int_shapes, + &int_points, + validation, + ); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } +} + +impl CustomTriangulatable> for IntContour +where + I: IntNumber + Expiration + LayoutNumber + SortKey, +{ + type Adapter = IntPointAdapter; + + #[inline] + fn custom_triangulate(&self, validation: Validation) -> RawTriangulation { + RawTriangulation::new( + IntCustomTriangulatable::custom_triangulate(self, validation), + IntPointAdapter::new(), + ) + } + + #[inline] + fn custom_triangulate_with_steiner_points( + &self, + points: &[IntPoint], + validation: Validation, + ) -> RawTriangulation { + RawTriangulation::new( + IntCustomTriangulatable::custom_triangulate_with_steiner_points( + self, points, validation, + ), + IntPointAdapter::new(), + ) + } +} + +impl CustomTriangulatable> for IntShape +where + I: IntNumber + Expiration + LayoutNumber + SortKey, +{ + type Adapter = IntPointAdapter; + + #[inline] + fn custom_triangulate(&self, validation: Validation) -> RawTriangulation { + RawTriangulation::new( + IntCustomTriangulatable::custom_triangulate(self, validation), + IntPointAdapter::new(), + ) + } + + #[inline] + fn custom_triangulate_with_steiner_points( + &self, + points: &[IntPoint], + validation: Validation, + ) -> RawTriangulation { + RawTriangulation::new( + IntCustomTriangulatable::custom_triangulate_with_steiner_points( + self, points, validation, + ), + IntPointAdapter::new(), + ) + } +} + +impl CustomTriangulatable> for IntShapes +where + I: IntNumber + Expiration + LayoutNumber + SortKey, +{ + type Adapter = IntPointAdapter; + + #[inline] + fn custom_triangulate(&self, validation: Validation) -> RawTriangulation { + RawTriangulation::new( + IntCustomTriangulatable::custom_triangulate(self, validation), + IntPointAdapter::new(), + ) + } + + #[inline] + fn custom_triangulate_with_steiner_points( + &self, + points: &[IntPoint], + validation: Validation, + ) -> RawTriangulation { + RawTriangulation::new( + IntCustomTriangulatable::custom_triangulate_with_steiner_points( + self, points, validation, + ), + IntPointAdapter::new(), + ) + } +} diff --git a/iTriangle/src/float/delaunay.rs b/iTriangle/src/generic/delaunay.rs similarity index 52% rename from iTriangle/src/float/delaunay.rs rename to iTriangle/src/generic/delaunay.rs index 6a31a62..bb5a205 100644 --- a/iTriangle/src/float/delaunay.rs +++ b/iTriangle/src/generic/delaunay.rs @@ -1,31 +1,28 @@ use crate::advanced::buffer::DelaunayBuffer; use crate::advanced::delaunay::IntDelaunay; -use crate::float::triangulation::{RawTriangulation, Triangulation}; +use crate::generic::adapter::PointAdapter; +use crate::generic::triangulation::{RawTriangulation, Triangulation}; use crate::int::triangulation::IndexType; use alloc::vec::Vec; -use i_overlay::i_float::adapter::FloatPointAdapter; -use i_overlay::i_float::float::compatible::FloatPointCompatible; -use i_overlay::i_float::int::number::int::IntNumber; -use i_overlay::i_shape::float::adapter::PathToFloat; -/// A Delaunay-refined triangle mesh with float-mapped geometry. +/// A Delaunay-refined triangle mesh with adapter-mapped geometry. /// -/// Produced from [`Triangulation::into_delaunay`] by applying edge flips +/// Produced from [`RawTriangulation::into_delaunay`] by applying edge flips /// to satisfy the Delaunay condition. -pub struct Delaunay { - pub(super) delaunay: IntDelaunay, - pub(super) adapter: FloatPointAdapter, +pub struct Delaunay { + pub(super) delaunay: IntDelaunay, + pub(super) adapter: A, } -impl RawTriangulation { +impl RawTriangulation { #[inline] - pub fn into_delaunay(self) -> Delaunay { + pub fn into_delaunay(self) -> Delaunay { let mut buffer = DelaunayBuffer::new(); self.into_delaunay_with_buffer(&mut buffer) } #[inline] - pub fn into_delaunay_with_buffer(self, buffer: &mut DelaunayBuffer) -> Delaunay { + pub fn into_delaunay_with_buffer(self, buffer: &mut DelaunayBuffer) -> Delaunay { Delaunay { delaunay: self.raw.into_delaunay_with_buffer(buffer), adapter: self.adapter, @@ -33,11 +30,11 @@ impl RawTriangulation { } } -impl Delaunay { - /// Returns the float-mapped vertex positions in the triangulation. +impl Delaunay { + /// Returns the adapter-mapped vertex positions in the triangulation. #[inline] - pub fn points(&self) -> Vec

{ - self.delaunay.points.to_float(&self.adapter) + pub fn points(&self) -> Vec { + self.adapter.points_from_int(&self.delaunay.points) } /// Returns indices forming counter-clockwise triangles. @@ -52,9 +49,9 @@ impl Delaunay { self.delaunay.triangle_neighbors() } - /// Converts this refined mesh into a flat float [`Triangulation`]. + /// Converts this refined mesh into a flat [`Triangulation`]. #[inline] - pub fn to_triangulation(&self) -> Triangulation { + pub fn to_triangulation(&self) -> Triangulation { Triangulation { indices: self.triangle_indices(), points: self.points(), diff --git a/iTriangle/src/float/locator.rs b/iTriangle/src/generic/locator.rs similarity index 87% rename from iTriangle/src/float/locator.rs rename to iTriangle/src/generic/locator.rs index dc3012f..9f88588 100644 --- a/iTriangle/src/float/locator.rs +++ b/iTriangle/src/generic/locator.rs @@ -3,11 +3,12 @@ use i_key_sort::sort::key::SortKey; use i_overlay::i_float::float::compatible::FloatPointCompatible; use i_overlay::i_float::float::number::FloatNumber; use i_overlay::i_float::int::number::int::IntNumber; -use i_overlay::{i_float::adapter::FloatPointAdapter, i_shape::float::adapter::PathToInt}; +use i_overlay::i_float::adapter::FloatPointAdapter; +use crate::generic::adapter::PointAdapter; use crate::int::locator::IntPointInTriangulationLocator; use crate::{ - float::triangulation::Triangulation, int::triangulation::IndexType, + generic::triangulation::Triangulation, int::triangulation::IndexType, location::PointLocationInTriangulation, }; @@ -29,12 +30,12 @@ impl Triangulation { { let adapter = FloatPointAdapter::::with_iter(self.points.iter().chain(points.iter())); - let int_points = points.to_int(&adapter); + let int_points = adapter.points_to_int(points); let triangles = self.indices.chunks_exact(3).map(|triangle| { - let a = adapter.float_to_int(&self.points[triangle[0].into_usize()]); - let b = adapter.float_to_int(&self.points[triangle[1].into_usize()]); - let c = adapter.float_to_int(&self.points[triangle[2].into_usize()]); + let a = adapter.to_int_point(&self.points[triangle[0].into_usize()]); + let b = adapter.to_int_point(&self.points[triangle[1].into_usize()]); + let c = adapter.to_int_point(&self.points[triangle[2].into_usize()]); [a, b, c] }); @@ -60,7 +61,7 @@ mod tests { use alloc::vec; use crate::{ - float::triangulation::Triangulation, + generic::triangulation::Triangulation, location::{PointLocationInTriangulation, TriangleIndex}, }; diff --git a/iTriangle/src/float/mod.rs b/iTriangle/src/generic/mod.rs similarity index 92% rename from iTriangle/src/float/mod.rs rename to iTriangle/src/generic/mod.rs index b601b5a..20483f4 100644 --- a/iTriangle/src/float/mod.rs +++ b/iTriangle/src/generic/mod.rs @@ -1,3 +1,4 @@ +pub mod adapter; pub mod builder; pub mod centroid_net; pub mod circumcenter; diff --git a/iTriangle/src/generic/triangulatable.rs b/iTriangle/src/generic/triangulatable.rs new file mode 100644 index 0000000..5f7dcb5 --- /dev/null +++ b/iTriangle/src/generic/triangulatable.rs @@ -0,0 +1,308 @@ +use crate::generic::adapter::{IntPointAdapter, PointAdapter}; +use crate::generic::triangulation::RawTriangulation; +use crate::int::triangulatable::IntTriangulatable; +use crate::int::triangulation::RawIntTriangulation; +use i_key_sort::sort::key::SortKey; +use i_overlay::i_float::adapter::FloatPointAdapter; +use i_overlay::i_float::float::compatible::FloatPointCompatible; +use i_overlay::i_float::float::rect::FloatRect; +use i_overlay::i_float::int::number::int::IntNumber; +use i_overlay::i_float::int::point::IntPoint; +use i_overlay::i_shape::base::data::{Contour, Shape}; +use i_overlay::i_shape::float::rect::RectInit; +use i_overlay::i_shape::int::shape::{IntContour, IntShape, IntShapes}; +use i_tree::{Expiration, LayoutNumber}; + +/// A trait for triangulating geometry with default validation. +/// +/// Automatically converts the input to integer space when needed, applies validation, +/// and returns an adapter-mapped result. +/// +/// # Implemented For +/// - `[P]` / `[Contour

]` / `[Shape

]` (float) +/// - [`IntContour`] / [`IntShape`] / [`IntShapes`] (integer, [`IntPointAdapter`]) +pub trait Triangulatable

{ + type Adapter: PointAdapter; + + /// Triangulates the shape(s) using the default [`Triangulator`] configuration. + /// + /// Validation includes contour simplification, direction correction, and area filtering. + fn triangulate(&self) -> RawTriangulation; + + /// Triangulates the shape(s) and inserts the given Steiner points. + /// + /// Points must lie strictly within the interior of the geometry. + fn triangulate_with_steiner_points(&self, points: &[P]) -> RawTriangulation; +} + +/// Float-only. You can choose the integer coordinate type to be used internally +/// by the triangulator. +pub trait TriangulatableAs: Triangulatable

{ + /// Triangulates the shape(s) using the requested integer coordinate type. + fn triangulate_as(&self) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey; + + /// Triangulates the shape(s) with Steiner points using the requested integer coordinate type. + fn triangulate_with_steiner_points_as( + &self, + points: &[P], + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey; +} + +impl

Triangulatable

for [P] +where + P: FloatPointCompatible, +{ + type Adapter = FloatPointAdapter; + + #[inline] + fn triangulate(&self) -> RawTriangulation { + self.triangulate_as::() + } + + #[inline] + fn triangulate_with_steiner_points(&self, points: &[P]) -> RawTriangulation { + self.triangulate_with_steiner_points_as::(points) + } +} + +impl

TriangulatableAs

for [P] +where + P: FloatPointCompatible, +{ + fn triangulate_as(&self) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_path(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_contour: IntContour = adapter.points_to_int(self); + let raw = IntTriangulatable::triangulate(&int_contour); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } + + fn triangulate_with_steiner_points_as( + &self, + points: &[P], + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_path(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_points = adapter.points_to_int(points); + let int_contour: IntContour = adapter.points_to_int(self); + let raw = IntTriangulatable::triangulate_with_steiner_points(&int_contour, &int_points); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } +} + +impl

Triangulatable

for [Contour

] +where + P: FloatPointCompatible, +{ + type Adapter = FloatPointAdapter; + + #[inline] + fn triangulate(&self) -> RawTriangulation { + self.triangulate_as::() + } + + #[inline] + fn triangulate_with_steiner_points(&self, points: &[P]) -> RawTriangulation { + self.triangulate_with_steiner_points_as::(points) + } +} + +impl

TriangulatableAs

for [Contour

] +where + P: FloatPointCompatible, +{ + fn triangulate_as(&self) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_shape: IntShape = self.iter().map(|c| adapter.points_to_int(c)).collect(); + let raw = IntTriangulatable::triangulate(&int_shape); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } + + fn triangulate_with_steiner_points_as( + &self, + points: &[P], + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_points = adapter.points_to_int(points); + let int_shape: IntShape = self.iter().map(|c| adapter.points_to_int(c)).collect(); + let raw = IntTriangulatable::triangulate_with_steiner_points(&int_shape, &int_points); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } +} + +impl

Triangulatable

for [Shape

] +where + P: FloatPointCompatible, +{ + type Adapter = FloatPointAdapter; + + #[inline] + fn triangulate(&self) -> RawTriangulation { + self.triangulate_as::() + } + + #[inline] + fn triangulate_with_steiner_points(&self, points: &[P]) -> RawTriangulation { + self.triangulate_with_steiner_points_as::(points) + } +} + +impl

TriangulatableAs

for [Shape

] +where + P: FloatPointCompatible, +{ + fn triangulate_as(&self) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_list_of_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_shapes: IntShapes = self + .iter() + .map(|shape| shape.iter().map(|c| adapter.points_to_int(c)).collect()) + .collect(); + let raw = IntTriangulatable::triangulate(&int_shapes); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } + + fn triangulate_with_steiner_points_as( + &self, + points: &[P], + ) -> RawTriangulation> + where + I: IntNumber + Expiration + LayoutNumber + SortKey, + { + if let Some(rect) = FloatRect::with_list_of_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_points = adapter.points_to_int(points); + let int_shapes: IntShapes = self + .iter() + .map(|shape| shape.iter().map(|c| adapter.points_to_int(c)).collect()) + .collect(); + let raw = IntTriangulatable::triangulate_with_steiner_points(&int_shapes, &int_points); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } +} + +impl Triangulatable> for IntContour +where + I: IntNumber + Expiration + LayoutNumber + SortKey, +{ + type Adapter = IntPointAdapter; + + #[inline] + fn triangulate(&self) -> RawTriangulation { + RawTriangulation::new(IntTriangulatable::triangulate(self), IntPointAdapter::new()) + } + + #[inline] + fn triangulate_with_steiner_points( + &self, + points: &[IntPoint], + ) -> RawTriangulation { + RawTriangulation::new( + IntTriangulatable::triangulate_with_steiner_points(self, points), + IntPointAdapter::new(), + ) + } +} + +impl Triangulatable> for IntShape +where + I: IntNumber + Expiration + LayoutNumber + SortKey, +{ + type Adapter = IntPointAdapter; + + #[inline] + fn triangulate(&self) -> RawTriangulation { + RawTriangulation::new(IntTriangulatable::triangulate(self), IntPointAdapter::new()) + } + + #[inline] + fn triangulate_with_steiner_points( + &self, + points: &[IntPoint], + ) -> RawTriangulation { + RawTriangulation::new( + IntTriangulatable::triangulate_with_steiner_points(self, points), + IntPointAdapter::new(), + ) + } +} + +impl Triangulatable> for IntShapes +where + I: IntNumber + Expiration + LayoutNumber + SortKey, +{ + type Adapter = IntPointAdapter; + + #[inline] + fn triangulate(&self) -> RawTriangulation { + RawTriangulation::new(IntTriangulatable::triangulate(self), IntPointAdapter::new()) + } + + #[inline] + fn triangulate_with_steiner_points( + &self, + points: &[IntPoint], + ) -> RawTriangulation { + RawTriangulation::new( + IntTriangulatable::triangulate_with_steiner_points(self, points), + IntPointAdapter::new(), + ) + } +} diff --git a/iTriangle/src/float/triangulation.rs b/iTriangle/src/generic/triangulation.rs similarity index 73% rename from iTriangle/src/float/triangulation.rs rename to iTriangle/src/generic/triangulation.rs index 822eba7..7f6ae93 100644 --- a/iTriangle/src/float/triangulation.rs +++ b/iTriangle/src/generic/triangulation.rs @@ -1,27 +1,27 @@ +use crate::generic::adapter::PointAdapter; use crate::int::triangulation::{IndexType, IntTriangulation, RawIntTriangulation}; use alloc::vec::Vec; -use i_overlay::i_float::adapter::FloatPointAdapter; use i_overlay::i_float::float::compatible::FloatPointCompatible; use i_overlay::i_float::float::number::FloatNumber; use i_overlay::i_float::int::number::int::IntNumber; -use i_overlay::i_shape::float::adapter::PathToFloat; use i_overlay::i_shape::util::reserve::Reserve; -/// A triangulation result based on integer computation, with float mapping. +/// A triangulation result based on integer computation, with point mapping. /// -/// Internally uses an [`Triangulation`] for performance and robustness, -/// and maps results back to user-provided float types via a [`FloatPointAdapter`]. +/// Internally uses a [`RawIntTriangulation`] for performance and robustness, +/// and maps results back to user-provided point types via a [`PointAdapter`]. /// /// # Parameters -/// - `P`: Float point type (e.g., `Vec2`, `[f32; 2]`, etc.) -pub struct RawTriangulation { - pub raw: RawIntTriangulation, - pub adapter: FloatPointAdapter, +/// - `A`: Point adapter (e.g. [`i_overlay::i_float::adapter::FloatPointAdapter`] +/// or [`crate::generic::adapter::IntPointAdapter`]) +pub struct RawTriangulation { + pub raw: RawIntTriangulation, + pub adapter: A, } -/// A flat triangulation result consisting of float points and triangle indices. +/// A flat triangulation result consisting of points and triangle indices. /// -/// Useful for rendering, exporting, or post-processing the mesh in float space. +/// Useful for rendering, exporting, or post-processing the mesh. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, Clone)] pub struct Triangulation { @@ -29,13 +29,18 @@ pub struct Triangulation { pub indices: Vec, } -impl RawTriangulation { - /// Returns the float-mapped points used in the triangulation. +impl RawTriangulation { + #[inline] + pub fn new(raw: RawIntTriangulation, adapter: A) -> Self { + Self { raw, adapter } + } + + /// Returns the adapter-mapped points used in the triangulation. /// /// The points are guaranteed to match the input shape geometry within adapter precision. #[inline] - pub fn points(&self) -> Vec

{ - self.raw.points.to_float(&self.adapter) + pub fn points(&self) -> Vec { + self.adapter.points_from_int(&self.raw.points) } /// Returns the triangle indices for the mesh, ordered counter-clockwise. @@ -46,7 +51,7 @@ impl RawTriangulation { /// Converts this flat triangulation into a flat [`Triangulation`] (points + indices). #[inline] - pub fn to_triangulation(&self) -> Triangulation { + pub fn to_triangulation(&self) -> Triangulation { Triangulation { indices: self.triangle_indices(), points: self.points(), @@ -64,18 +69,16 @@ impl Triangulation { } #[inline] - pub fn set_with_int( + pub fn set_with_int>( &mut self, - triangulation: &IntTriangulation, - adapter: &FloatPointAdapter, - ) where - P: FloatPointCompatible, - { + triangulation: &IntTriangulation, + adapter: &A, + ) { self.points.clear(); self.points .reserve_capacity(triangulation.points.capacity()); self.points - .extend(triangulation.points.iter().map(|p| adapter.int_to_float(p))); + .extend(triangulation.points.iter().map(|p| adapter.from_int_point(p))); self.indices.clear(); self.indices.extend_from_slice(&triangulation.indices); @@ -84,14 +87,11 @@ impl Triangulation { impl IntTriangulation { #[inline] - pub fn into_float( - self, - adapter: &FloatPointAdapter, - ) -> Triangulation { + pub fn into_adapted>(self, adapter: &A) -> Triangulation { let points = self .points .iter() - .map(|p| adapter.int_to_float(p)) + .map(|p| adapter.from_int_point(p)) .collect(); Triangulation { points, @@ -100,14 +100,11 @@ impl IntTriangulation { } #[inline] - pub fn to_float( - &self, - adapter: &FloatPointAdapter, - ) -> Triangulation { + pub fn to_adapted>(&self, adapter: &A) -> Triangulation { let points = self .points .iter() - .map(|p| adapter.int_to_float(p)) + .map(|p| adapter.from_int_point(p)) .collect(); Triangulation { points, @@ -175,7 +172,7 @@ impl Triangulation { #[cfg(test)] mod tests { - use crate::float::triangulator::Triangulator; + use crate::generic::triangulator::Triangulator; #[test] fn test_0() { diff --git a/iTriangle/src/float/triangulator.rs b/iTriangle/src/generic/triangulator.rs similarity index 86% rename from iTriangle/src/float/triangulator.rs rename to iTriangle/src/generic/triangulator.rs index c6def4d..94b15f4 100644 --- a/iTriangle/src/float/triangulator.rs +++ b/iTriangle/src/generic/triangulator.rs @@ -1,4 +1,4 @@ -use crate::float::triangulation::Triangulation; +use crate::generic::triangulation::Triangulation; use crate::int::triangulation::{IndexType, IntTriangulation}; use crate::int::triangulator::IntTriangulator; use crate::int::validation::Validation; @@ -6,11 +6,13 @@ use i_key_sort::sort::key::SortKey; use i_overlay::core::solver::Solver; use i_overlay::i_float::float::compatible::FloatPointCompatible; use i_overlay::i_float::int::number::int::IntNumber; +use i_overlay::i_float::int::point::IntPoint; use i_overlay::i_shape::flat::buffer::FlatContoursBuffer; +use i_overlay::i_shape::int::shape::{IntContour, IntShape, IntShapes}; use i_overlay::i_shape::source::resource::ShapeResource; use i_tree::{Expiration, LayoutNumber}; -/// A reusable triangulator that converts float-based shapes into triangle meshes. +/// A reusable triangulator that converts shapes into triangle meshes. pub struct Triangulator where I: IntNumber + Expiration + LayoutNumber + SortKey, @@ -110,7 +112,7 @@ where self.int_triangulator .triangulate_flat_into(&mut flat_buffer, &mut int_buffer); - let triangulation = int_buffer.to_float(&adapter); + let triangulation = int_buffer.to_adapted(&adapter); self.flat_buffer = Some(flat_buffer); self.int_buffer = Some(int_buffer); @@ -175,7 +177,7 @@ where self.int_triangulator .uncheck_triangulate_flat_into(&flat_buffer, &mut int_buffer); - let triangulation = int_buffer.to_float(&adapter); + let triangulation = int_buffer.to_adapted(&adapter); self.flat_buffer = Some(flat_buffer); self.int_buffer = Some(int_buffer); @@ -219,4 +221,34 @@ where self.flat_buffer = Some(flat_buffer); self.int_buffer = Some(int_buffer); } + + /// Triangulates an integer contour and returns points as [`IntPoint`]s. + #[inline] + pub fn triangulate_contour(&mut self, contour: &IntContour) -> Triangulation, N> { + let t = self.int_triangulator.triangulate_contour(contour); + Triangulation { + points: t.points, + indices: t.indices, + } + } + + /// Triangulates an integer shape and returns points as [`IntPoint`]s. + #[inline] + pub fn triangulate_shape(&mut self, shape: &IntShape) -> Triangulation, N> { + let t = self.int_triangulator.triangulate_shape(shape); + Triangulation { + points: t.points, + indices: t.indices, + } + } + + /// Triangulates integer shapes and returns points as [`IntPoint`]s. + #[inline] + pub fn triangulate_shapes(&mut self, shapes: &IntShapes) -> Triangulation, N> { + let t = self.int_triangulator.triangulate_shapes(shapes); + Triangulation { + points: t.points, + indices: t.indices, + } + } } diff --git a/iTriangle/src/generic/unchecked.rs b/iTriangle/src/generic/unchecked.rs new file mode 100644 index 0000000..9b359c4 --- /dev/null +++ b/iTriangle/src/generic/unchecked.rs @@ -0,0 +1,334 @@ +use crate::generic::adapter::{IntPointAdapter, PointAdapter}; +use crate::generic::triangulation::RawTriangulation; +use crate::int::triangulation::RawIntTriangulation; +use crate::int::unchecked::IntUncheckedTriangulatable; +use i_key_sort::sort::key::SortKey; +use i_overlay::i_float::adapter::FloatPointAdapter; +use i_overlay::i_float::float::compatible::FloatPointCompatible; +use i_overlay::i_float::float::rect::FloatRect; +use i_overlay::i_float::int::number::int::IntNumber; +use i_overlay::i_float::int::point::IntPoint; +use i_overlay::i_shape::base::data::{Contour, Shape}; +use i_overlay::i_shape::float::rect::RectInit; +use i_overlay::i_shape::int::shape::{IntContour, IntShape, IntShapes}; +use i_tree::Expiration; + +/// A trait for triangulating already valid geometry. +/// +/// Skips all validation for performance. Ideal when input is generated programmatically. +/// +/// # Safety Requirements +/// - Outer contours must be counter-clockwise +/// - Holes must be clockwise +/// - Steiner points must lie strictly within the shape +pub trait UncheckedTriangulatable

{ + type Adapter: PointAdapter; + + /// Triangulates geometry without validation or simplification. + fn unchecked_triangulate(&self) -> RawTriangulation; + + /// Same as `unchecked_triangulate`, but inserts user-defined Steiner points. + fn unchecked_triangulate_with_steiner_points( + &self, + points: &[P], + ) -> RawTriangulation; +} + +/// Float-only. You can choose the integer coordinate type to be used internally +/// by the triangulator. +pub trait UncheckedTriangulatableAs: UncheckedTriangulatable

{ + /// Triangulates without validation using the requested integer coordinate type. + fn unchecked_triangulate_as(&self) -> RawTriangulation> + where + I: IntNumber + Expiration + SortKey; + + /// Same as `unchecked_triangulate_as`, but inserts user-defined Steiner points. + fn unchecked_triangulate_with_steiner_points_as( + &self, + points: &[P], + ) -> RawTriangulation> + where + I: IntNumber + Expiration + SortKey; +} + +impl

UncheckedTriangulatable

for [P] +where + P: FloatPointCompatible, +{ + type Adapter = FloatPointAdapter; + + #[inline] + fn unchecked_triangulate(&self) -> RawTriangulation { + self.unchecked_triangulate_as::() + } + + #[inline] + fn unchecked_triangulate_with_steiner_points( + &self, + points: &[P], + ) -> RawTriangulation { + self.unchecked_triangulate_with_steiner_points_as::(points) + } +} + +impl

UncheckedTriangulatableAs

for [P] +where + P: FloatPointCompatible, +{ + fn unchecked_triangulate_as(&self) -> RawTriangulation> + where + I: IntNumber + Expiration + SortKey, + { + if let Some(rect) = FloatRect::with_path(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_contour: IntContour = adapter.points_to_int(self); + let raw = IntUncheckedTriangulatable::uncheck_triangulate(&int_contour); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } + + fn unchecked_triangulate_with_steiner_points_as( + &self, + points: &[P], + ) -> RawTriangulation> + where + I: IntNumber + Expiration + SortKey, + { + if let Some(rect) = FloatRect::with_path(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_points = adapter.points_to_int(points); + let int_contour: IntContour = adapter.points_to_int(self); + let raw = IntUncheckedTriangulatable::uncheck_triangulate_with_steiner_points( + &int_contour, + &int_points, + ); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } +} + +impl

UncheckedTriangulatable

for [Contour

] +where + P: FloatPointCompatible, +{ + type Adapter = FloatPointAdapter; + + #[inline] + fn unchecked_triangulate(&self) -> RawTriangulation { + self.unchecked_triangulate_as::() + } + + #[inline] + fn unchecked_triangulate_with_steiner_points( + &self, + points: &[P], + ) -> RawTriangulation { + self.unchecked_triangulate_with_steiner_points_as::(points) + } +} + +impl

UncheckedTriangulatableAs

for [Contour

] +where + P: FloatPointCompatible, +{ + fn unchecked_triangulate_as(&self) -> RawTriangulation> + where + I: IntNumber + Expiration + SortKey, + { + if let Some(rect) = FloatRect::with_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_shape: IntShape = self.iter().map(|c| adapter.points_to_int(c)).collect(); + let raw = IntUncheckedTriangulatable::uncheck_triangulate(&int_shape); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } + + fn unchecked_triangulate_with_steiner_points_as( + &self, + points: &[P], + ) -> RawTriangulation> + where + I: IntNumber + Expiration + SortKey, + { + if let Some(rect) = FloatRect::with_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_points = adapter.points_to_int(points); + let int_shape: IntShape = self.iter().map(|c| adapter.points_to_int(c)).collect(); + let raw = IntUncheckedTriangulatable::uncheck_triangulate_with_steiner_points( + &int_shape, + &int_points, + ); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } +} + +impl

UncheckedTriangulatable

for [Shape

] +where + P: FloatPointCompatible, +{ + type Adapter = FloatPointAdapter; + + #[inline] + fn unchecked_triangulate(&self) -> RawTriangulation { + self.unchecked_triangulate_as::() + } + + #[inline] + fn unchecked_triangulate_with_steiner_points( + &self, + points: &[P], + ) -> RawTriangulation { + self.unchecked_triangulate_with_steiner_points_as::(points) + } +} + +impl

UncheckedTriangulatableAs

for [Shape

] +where + P: FloatPointCompatible, +{ + fn unchecked_triangulate_as(&self) -> RawTriangulation> + where + I: IntNumber + Expiration + SortKey, + { + if let Some(rect) = FloatRect::with_list_of_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_shapes: IntShapes = self + .iter() + .map(|shape| shape.iter().map(|c| adapter.points_to_int(c)).collect()) + .collect(); + let raw = IntUncheckedTriangulatable::uncheck_triangulate(&int_shapes); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } + + fn unchecked_triangulate_with_steiner_points_as( + &self, + points: &[P], + ) -> RawTriangulation> + where + I: IntNumber + Expiration + SortKey, + { + if let Some(rect) = FloatRect::with_list_of_paths(self) { + let adapter = FloatPointAdapter::::new(rect); + let int_points = adapter.points_to_int(points); + let int_shapes: IntShapes = self + .iter() + .map(|shape| shape.iter().map(|c| adapter.points_to_int(c)).collect()) + .collect(); + let raw = IntUncheckedTriangulatable::uncheck_triangulate_with_steiner_points( + &int_shapes, + &int_points, + ); + RawTriangulation { raw, adapter } + } else { + RawTriangulation { + raw: RawIntTriangulation::default(), + adapter: FloatPointAdapter::::new(FloatRect::zero()), + } + } + } +} + +impl UncheckedTriangulatable> for IntContour +where + I: IntNumber + SortKey, +{ + type Adapter = IntPointAdapter; + + #[inline] + fn unchecked_triangulate(&self) -> RawTriangulation { + RawTriangulation::new( + IntUncheckedTriangulatable::uncheck_triangulate(self), + IntPointAdapter::new(), + ) + } + + #[inline] + fn unchecked_triangulate_with_steiner_points( + &self, + points: &[IntPoint], + ) -> RawTriangulation { + RawTriangulation::new( + IntUncheckedTriangulatable::uncheck_triangulate_with_steiner_points(self, points), + IntPointAdapter::new(), + ) + } +} + +impl UncheckedTriangulatable> for IntShape +where + I: IntNumber + SortKey, +{ + type Adapter = IntPointAdapter; + + #[inline] + fn unchecked_triangulate(&self) -> RawTriangulation { + RawTriangulation::new( + IntUncheckedTriangulatable::uncheck_triangulate(self), + IntPointAdapter::new(), + ) + } + + #[inline] + fn unchecked_triangulate_with_steiner_points( + &self, + points: &[IntPoint], + ) -> RawTriangulation { + RawTriangulation::new( + IntUncheckedTriangulatable::uncheck_triangulate_with_steiner_points(self, points), + IntPointAdapter::new(), + ) + } +} + +impl UncheckedTriangulatable> for IntShapes +where + I: IntNumber + Expiration + SortKey, +{ + type Adapter = IntPointAdapter; + + #[inline] + fn unchecked_triangulate(&self) -> RawTriangulation { + RawTriangulation::new( + IntUncheckedTriangulatable::uncheck_triangulate(self), + IntPointAdapter::new(), + ) + } + + #[inline] + fn unchecked_triangulate_with_steiner_points( + &self, + points: &[IntPoint], + ) -> RawTriangulation { + RawTriangulation::new( + IntUncheckedTriangulatable::uncheck_triangulate_with_steiner_points(self, points), + IntPointAdapter::new(), + ) + } +} diff --git a/iTriangle/src/lib.rs b/iTriangle/src/lib.rs index 8bb0e90..e8f5af6 100644 --- a/iTriangle/src/lib.rs +++ b/iTriangle/src/lib.rs @@ -2,7 +2,7 @@ extern crate alloc; pub mod advanced; -pub mod float; +pub mod generic; pub mod geom; mod index; pub mod int; diff --git a/iTriangle/tests/doc_tests.rs b/iTriangle/tests/doc_tests.rs index 727c9f8..8ad432c 100644 --- a/iTriangle/tests/doc_tests.rs +++ b/iTriangle/tests/doc_tests.rs @@ -1,9 +1,9 @@ #[cfg(test)] mod tests { use i_overlay::i_shape::base::data::Contour; - use i_triangle::float::triangulatable::Triangulatable; - use i_triangle::float::triangulation::Triangulation; - use i_triangle::float::triangulator::Triangulator; + use i_triangle::generic::triangulatable::Triangulatable; + use i_triangle::generic::triangulation::Triangulation; + use i_triangle::generic::triangulator::Triangulator; use rand::RngExt; #[test] diff --git a/iTriangle/tests/float_tests.rs b/iTriangle/tests/float_tests.rs index 9d372e6..f1d7c74 100644 --- a/iTriangle/tests/float_tests.rs +++ b/iTriangle/tests/float_tests.rs @@ -7,9 +7,9 @@ mod tests { use i_overlay::i_shape::base::data::Contour; use i_overlay::i_shape::float::area::Area; use i_tree::{Expiration, LayoutNumber}; - use i_triangle::float::triangulatable::Triangulatable; - use i_triangle::float::triangulation::Triangulation; - use i_triangle::float::triangulator::Triangulator; + use i_triangle::generic::triangulatable::TriangulatableAs; + use i_triangle::generic::triangulation::Triangulation; + use i_triangle::generic::triangulator::Triangulator; use rand::RngExt; trait TestInt: IntNumber + Expiration + LayoutNumber + SortKey {} diff --git a/performance/rust_app/src/test/runner.rs b/performance/rust_app/src/test/runner.rs index ed3e8be..965c02e 100644 --- a/performance/rust_app/src/test/runner.rs +++ b/performance/rust_app/src/test/runner.rs @@ -1,7 +1,7 @@ use std::hint::black_box; use std::time::Instant; -use i_triangle::float::triangulation::Triangulation; -use i_triangle::float::triangulator::Triangulator; +use i_triangle::generic::triangulation::Triangulation; +use i_triangle::generic::triangulator::Triangulator; use i_triangle::i_overlay::i_float::float::compatible::FloatPointCompatible; use i_triangle::i_overlay::i_float::float::number::FloatNumber; use i_triangle::i_overlay::i_shape::source::resource::ShapeResource;