diff --git a/fj-kernel/src/algorithms/triangulation/delaunay.rs b/fj-kernel/src/algorithms/triangulation/delaunay.rs new file mode 100644 index 000000000..6629990c7 --- /dev/null +++ b/fj-kernel/src/algorithms/triangulation/delaunay.rs @@ -0,0 +1,52 @@ +use fj_math::Scalar; +use parry2d_f64::utils::point_in_triangle::{corner_direction, Orientation}; +use spade::HasPosition; + +use crate::geometry; + +/// Create a Delaunay triangulation of all points +pub fn triangulate( + points: Vec>, +) -> Vec<[geometry::Point<2>; 3]> { + use spade::Triangulation as _; + + let triangulation = spade::DelaunayTriangulation::<_>::bulk_load(points) + .expect("Inserted invalid values into triangulation"); + + let mut triangles = Vec::new(); + for triangle in triangulation.inner_faces() { + let [v0, v1, v2] = triangle.vertices().map(|vertex| *vertex.data()); + let orientation = corner_direction( + &v0.native().to_na(), + &v1.native().to_na(), + &v2.native().to_na(), + ); + + let triangle = match orientation { + Orientation::Ccw => [v0, v1, v2], + Orientation::Cw => [v0, v2, v1], + Orientation::None => { + panic!( + "Triangle returned from triangulation isn't actually a \ + triangle" + ); + } + }; + + triangles.push(triangle); + } + + triangles +} + +// Enables the use of `geometry::Point` in the triangulation. +impl HasPosition for geometry::Point<2> { + type Scalar = Scalar; + + fn position(&self) -> spade::Point2 { + spade::Point2 { + x: self.native().u, + y: self.native().v, + } + } +} diff --git a/fj-kernel/src/algorithms/triangulation/mod.rs b/fj-kernel/src/algorithms/triangulation/mod.rs index 7bf7611f3..992ca94a1 100644 --- a/fj-kernel/src/algorithms/triangulation/mod.rs +++ b/fj-kernel/src/algorithms/triangulation/mod.rs @@ -1,12 +1,11 @@ +mod delaunay; mod polygon; mod ray; use fj_interop::debug::DebugInfo; use fj_math::{Scalar, Triangle}; -use parry2d_f64::utils::point_in_triangle::{corner_direction, Orientation}; -use spade::HasPosition; -use crate::{geometry, shape::Shape, topology::Face}; +use crate::{shape::Shape, topology::Face}; use self::polygon::Polygon; @@ -54,7 +53,7 @@ pub fn triangulate( }, )); - let mut triangles = delaunay(points); + let mut triangles = delaunay::triangulate(points); triangles.retain(|triangle| { face_as_polygon.contains_triangle( triangle.map(|point| point.native()), @@ -74,51 +73,6 @@ pub fn triangulate( } } -/// Create a Delaunay triangulation of all points -fn delaunay(points: Vec>) -> Vec<[geometry::Point<2>; 3]> { - use spade::Triangulation as _; - - let triangulation = spade::DelaunayTriangulation::<_>::bulk_load(points) - .expect("Inserted invalid values into triangulation"); - - let mut triangles = Vec::new(); - for triangle in triangulation.inner_faces() { - let [v0, v1, v2] = triangle.vertices().map(|vertex| *vertex.data()); - let orientation = corner_direction( - &v0.native().to_na(), - &v1.native().to_na(), - &v2.native().to_na(), - ); - - let triangle = match orientation { - Orientation::Ccw => [v0, v1, v2], - Orientation::Cw => [v0, v2, v1], - Orientation::None => { - panic!( - "Triangle returned from triangulation isn't actually a \ - triangle" - ); - } - }; - - triangles.push(triangle); - } - - triangles -} - -// Enables the use of `geometry::Point` in the triangulation. -impl HasPosition for geometry::Point<2> { - type Scalar = Scalar; - - fn position(&self) -> spade::Point2 { - spade::Point2 { - x: self.native().u, - y: self.native().v, - } - } -} - #[cfg(test)] mod tests { use fj_interop::debug::DebugInfo;