diff --git a/iTriangle/src/advanced/delaunay.rs b/iTriangle/src/advanced/delaunay.rs index f6d64d1..b0d7619 100644 --- a/iTriangle/src/advanced/delaunay.rs +++ b/iTriangle/src/advanced/delaunay.rs @@ -18,6 +18,16 @@ pub struct IntDelaunay { pub points: Vec, } +impl IntDelaunay { + #[inline] + pub(crate) fn into_raw(self) -> RawIntTriangulation { + RawIntTriangulation { + triangles: self.triangles, + points: self.points, + } + } +} + impl RawIntTriangulation { /// Converts an int triangle mesh into a Delaunay triangulation by applying edge flips. /// @@ -28,12 +38,24 @@ impl RawIntTriangulation { /// A new [`IntDelaunay`] structure with updated triangle connectivity. #[inline] pub fn into_delaunay(self) -> IntDelaunay { + let mut buffer = DelaunayBuffer::new(); + self.into_delaunay_with_buffer(&mut buffer) + } + + /// Converts an int triangle mesh into a Delaunay triangulation by applying edge flips. + /// + /// Uses the provided scratch buffer to avoid repeated allocations across calls. + /// + /// # Returns + /// A new [`IntDelaunay`] structure with updated triangle connectivity. + #[inline] + pub fn into_delaunay_with_buffer(self, buffer: &mut DelaunayBuffer) -> IntDelaunay { let mut delaunay = IntDelaunay { triangles: self.triangles, points: self.points, }; - delaunay.triangles.build(); + delaunay.triangles.build_with_buffer(buffer); delaunay } diff --git a/iTriangle/src/float/delaunay.rs b/iTriangle/src/float/delaunay.rs index b79d345..09d1c32 100644 --- a/iTriangle/src/float/delaunay.rs +++ b/iTriangle/src/float/delaunay.rs @@ -1,3 +1,4 @@ +use crate::advanced::buffer::DelaunayBuffer; use crate::advanced::delaunay::IntDelaunay; use crate::float::triangulation::{RawTriangulation, Triangulation}; use crate::int::triangulation::IndexType; @@ -18,8 +19,14 @@ pub struct Delaunay { impl RawTriangulation

{ #[inline] 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

{ Delaunay { - delaunay: self.raw.into_delaunay(), + delaunay: self.raw.into_delaunay_with_buffer(buffer), adapter: self.adapter, } } diff --git a/iTriangle/src/int/triangulation.rs b/iTriangle/src/int/triangulation.rs index a787b1c..9caabb1 100644 --- a/iTriangle/src/int/triangulation.rs +++ b/iTriangle/src/int/triangulation.rs @@ -1,3 +1,4 @@ +use crate::advanced::delaunay::IntDelaunay; use crate::geom::triangle::IntTriangle; use alloc::vec::Vec; use i_overlay::i_float::int::point::IntPoint; @@ -200,6 +201,16 @@ impl IntTriangulation { .triangles .feed_indices(triangulation.points.len(), &mut self.indices); } + + #[inline] + pub fn fill_with_delaunay(&mut self, delaunay: &IntDelaunay) { + self.points.clear(); + self.points.extend_from_slice(&delaunay.points); + + delaunay + .triangles + .feed_indices(delaunay.points.len(), &mut self.indices); + } } pub(crate) trait IndicesBuilder { diff --git a/iTriangle/src/int/triangulator.rs b/iTriangle/src/int/triangulator.rs index 3129d8e..3ef1b6d 100644 --- a/iTriangle/src/int/triangulator.rs +++ b/iTriangle/src/int/triangulator.rs @@ -1,3 +1,4 @@ +use crate::advanced::buffer::DelaunayBuffer; use crate::int::earcut::earcut_64::Earcut64; use crate::int::monotone::triangulator::MonotoneTriangulator; use crate::int::triangulation::{IndexType, IntTriangulation, RawIntTriangulation}; @@ -17,6 +18,7 @@ pub struct IntTriangulator { triangulator: MonotoneTriangulator, shapes_buffer: Option>, raw_buffer: Option, + delaunay_buffer: DelaunayBuffer, } impl IntTriangulator { @@ -30,6 +32,7 @@ impl IntTriangulator { triangulator: MonotoneTriangulator::default(), raw_buffer: None, shapes_buffer: None, + delaunay_buffer: DelaunayBuffer::default(), } } } @@ -137,8 +140,9 @@ impl IntTriangulator { self.triangulator .contour_into_net_triangulation(contour, None, &mut raw); } - triangulation.fill_with_raw(&raw); - self.raw_buffer = Some(raw); + let delaunay = raw.into_delaunay_with_buffer(&mut self.delaunay_buffer); + triangulation.fill_with_delaunay(&delaunay); + self.raw_buffer = Some(delaunay.into_raw()); } else if self.earcut && contour.is_earcut_compatible() { contour.earcut_flat_triangulate_into(triangulation); } else { @@ -169,8 +173,9 @@ impl IntTriangulator { let mut raw = self.raw_buffer.take().unwrap_or_default(); self.triangulator .shape_into_net_triangulation(shape, None, &mut raw); - triangulation.fill_with_raw(&raw); - self.raw_buffer = Some(raw); + let delaunay = raw.into_delaunay_with_buffer(&mut self.delaunay_buffer); + triangulation.fill_with_delaunay(&delaunay); + self.raw_buffer = Some(delaunay.into_raw()); } else { self.triangulator .shape_into_flat_triangulation(shape, triangulation); @@ -236,9 +241,9 @@ impl IntTriangulator { self.triangulator .flat_into_net_triangulation(flat, &mut raw); } - - triangulation.fill_with_raw(&raw); - self.raw_buffer = Some(raw); + let delaunay = raw.into_delaunay_with_buffer(&mut self.delaunay_buffer); + triangulation.fill_with_delaunay(&delaunay); + self.raw_buffer = Some(delaunay.into_raw()); } else if self.earcut && flat.is_earcut_compatible() { flat.as_first_contour() .earcut_flat_triangulate_into(triangulation);