From 72ebaeea800a736430a7aa55690c0bc9e867ba8d Mon Sep 17 00:00:00 2001 From: Adam Getchell Date: Wed, 18 Sep 2024 21:19:08 -0700 Subject: [PATCH] fix: update algorithm --- src/delaunay_core/cell.rs | 17 ++- src/delaunay_core/facet.rs | 2 +- .../triangulation_data_structure.rs | 113 +++++++----------- 3 files changed, 57 insertions(+), 75 deletions(-) diff --git a/src/delaunay_core/cell.rs b/src/delaunay_core/cell.rs index 59a8739..7baa05b 100644 --- a/src/delaunay_core/cell.rs +++ b/src/delaunay_core/cell.rs @@ -115,7 +115,7 @@ where /// let new_cell = Cell::from_facet_and_vertex(facet, vertex5).unwrap(); /// assert!(new_cell.vertices.contains(&vertex5)); pub fn from_facet_and_vertex( - mut facet: Facet, + facet: Facet, vertex: Vertex, ) -> Result { let mut vertices = facet.vertices(); @@ -257,7 +257,7 @@ where /// Using the approach from: /// /// Lévy, Bruno, and Yang Liu. - /// “Lp Centroidal Voronoi Tessellation and Its Applications.” + /// "Lp Centroidal Voronoi Tessellation and Its Applications." /// ACM Transactions on Graphics 29, no. 4 (July 26, 2010): 119:1-119:11. /// . /// @@ -428,6 +428,19 @@ where facets } + + /// The function `contains_facet` checks if a given facet is contained in the cell. + /// + /// # Arguments: + /// + /// * `facet`: The facet to check. + /// + /// # Returns: + /// + /// Returns `true` if the given facet is contained in the cell, and `false` otherwise. + pub fn contains_facet(&self, facet: &Facet) -> bool { + self.vertices.iter().all(|v| facet.vertices().contains(v)) + } } /// Equality of cells is based on equality of sorted vector of vertices. diff --git a/src/delaunay_core/facet.rs b/src/delaunay_core/facet.rs index 07da793..e584ed8 100644 --- a/src/delaunay_core/facet.rs +++ b/src/delaunay_core/facet.rs @@ -87,7 +87,7 @@ where /// The `vertices` method in the [Facet] returns a container of /// [Vertex] objects that are in the [Facet]. - pub fn vertices(&mut self) -> Vec> { + pub fn vertices(&self) -> Vec> { let mut vertices = self.cell.clone().vertices; vertices.retain(|v| *v != self.vertex); diff --git a/src/delaunay_core/triangulation_data_structure.rs b/src/delaunay_core/triangulation_data_structure.rs index 9e0c6fb..d637aa1 100644 --- a/src/delaunay_core/triangulation_data_structure.rs +++ b/src/delaunay_core/triangulation_data_structure.rs @@ -4,7 +4,7 @@ //! [CGAL Triangulation](https://doc.cgal.org/latest/Triangulation/index.html). use super::{ - cell::Cell, cell::CellBuilder, facet::Facet, point::Point, utilities::find_extreme_coordinates, + cell::Cell, cell::CellBuilder, point::Point, utilities::find_extreme_coordinates, vertex::Vertex, }; use na::{ComplexField, Const, OPoint}; @@ -252,93 +252,60 @@ where /// /// # Returns: /// - /// A [Result] containing a [Vec] of [Cell] objects representing the triangulation, or an error message. - fn bowyer_watson(&mut self) -> Result>, anyhow::Error> + /// A [Result] containing the updated [Tds] with the Delaunay triangulation, or an error message. + pub fn bowyer_watson(&mut self) -> Result where OPoint>: From<[f64; D]>, [f64; D]: Default + DeserializeOwned + Serialize + Sized, { - let mut triangulation: Vec> = Vec::new(); - // Create super-cell that contains all vertices let supercell = self.supercell()?; - triangulation.push(supercell.clone()); + self.cells.insert(supercell.uuid, supercell.clone()); // Iterate over vertices - for vertex in self.vertices.values() { - // Find cells that contain the vertex - let mut bad_cells: Vec> = Vec::new(); - - for cell in &triangulation { - if cell.circumsphere_contains(*vertex)? { - bad_cells.push((*cell).clone()); + for vertex in self.vertices.values().cloned().collect::>() { + let mut bad_cells = Vec::new(); + let mut boundary_facets = Vec::new(); + + // Find cells whose circumsphere contains the vertex + for (cell_id, cell) in self.cells.iter() { + if cell.circumsphere_contains(vertex)? { + bad_cells.push(*cell_id); } } - // Find the boundary of the hole left by the bad cells - let mut boundary_facets: Vec> = Vec::new(); - for bad_cell in &bad_cells { - for facet in bad_cell.facets() { - if !bad_cells.iter().any(|c| c.facets().contains(&facet)) { - boundary_facets.push(facet); + // Collect boundary facets + for &bad_cell_id in &bad_cells { + if let Some(bad_cell) = self.cells.get(&bad_cell_id) { + for facet in bad_cell.facets() { + if !bad_cells.iter().any(|&id| { + self.cells + .get(&id) + .map_or(false, |c| c.contains_facet(&facet)) + }) { + boundary_facets.push(facet); + } } } } - // Remove bad cells from triangulation - triangulation.retain(|cell| !bad_cells.contains(cell)); + // Remove bad cells + for bad_cell_id in bad_cells { + self.cells.remove(&bad_cell_id); + } - // Create new cells from the boundary facets and new vertex + // Create new cells using the boundary facets and the new vertex for facet in boundary_facets { - let new_cell = Cell::from_facet_and_vertex(facet, *vertex)?; - triangulation.push(new_cell); + let new_cell = Cell::from_facet_and_vertex(facet, vertex)?; + self.cells.insert(new_cell.uuid, new_cell); } } - // // Find the boundary of the polygonal hole - // let mut polygonal_hole: Vec> = Vec::new(); - // for cell in bad_cells.iter() { - // // Create Facets from the Cell - // for vertex in cell.vertices.iter() { - // let facet = Facet::new(cell.clone(), *vertex)?; - // polygonal_hole.push(facet); - // } - - // // for vertex in cell.vertices.iter() { - // // if bad_cells.iter().any(|c| c.contains_vertex(vertex)) { - // // polygonal_hole.push(vertex.clone()); - // // } - // // } - // } - - // // Remove duplicate facets - // polygonal_hole.sort_by(|a, b| a.partial_cmp(b).unwrap()); - // polygonal_hole.dedup(); - - // // Remove bad cells from the triangulation - // for cell in bad_cells.iter() { - // triangulation.remove(triangulation.iter().position(|c| c == cell).unwrap()); - // } - - // // Re-triangulate the polygonal hole - // for mut facet in polygonal_hole.iter().cloned() { - // let mut new_cell_vertices: Vec> = Vec::new(); - // for facet_vertex in facet.vertices().iter() { - // new_cell_vertices.push(*facet_vertex); - // } - // new_cell_vertices.push(*vertex); - // triangulation.push(Cell::new(new_cell_vertices)?); - // } - // } - - // // Remove all cells containing vertices from the supercell - // triangulation - // .retain(|c| !c.contains_vertex(supercell.vertices.clone().into_iter().next().unwrap())); - - // Remove any cells that contain a vertex of the supercell - triangulation.retain(|cell| !cell.contains_vertex_of(supercell.clone())); - - Ok(triangulation) + // Remove cells that contain vertices of the supercell + self.cells + .retain(|_, cell| !cell.contains_vertex_of(supercell.clone())); + + Ok(self.clone()) } fn assign_neighbors(&mut self, _cells: Vec>) -> Result<(), &'static str> { @@ -493,13 +460,15 @@ mod tests { Point::new([0.0, 0.0, 1.0]), ]; let mut tds: Tds = Tds::new(points); - let cells = tds.bowyer_watson(); - let unwrapped_cells = cells.unwrap_or_else(|err| panic!("Error creating cells: {:?}", err)); + let result = tds.bowyer_watson().unwrap_or_else(|err| { + panic!("Error creating triangulation: {:?}", err); + }); - assert_eq!(unwrapped_cells.len(), 1); + assert_eq!(result.number_of_vertices(), 4); + assert_eq!(result.number_of_cells(), 2); // Human readable output for cargo test -- --nocapture - println!("{:?}", unwrapped_cells); + println!("{:?}", result); } #[test]