Skip to content

Commit

Permalink
feat: Add new function cell.circumsphere_contains_vertex
Browse files Browse the repository at this point in the history
Supposed to be more stable, but seems to also be inaccurate in some cases.
  • Loading branch information
acgetchell committed Sep 19, 2024
1 parent 72ebaee commit 6ca6c7e
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 2 deletions.
59 changes: 59 additions & 0 deletions src/delaunay_core/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,65 @@ where
Ok(circumradius >= radius)
}

/// The function `circumsphere_contains_vertex` checks if a given vertex is
/// contained in the circumsphere of the Cell using a matrix determinant.
/// It should be more numerically stable than `circumsphere_contains`.
///
/// # Arguments:
///
/// * `vertex`: The [Vertex] to check.
///
/// # Returns:
///
/// Returns `true` if the given [Vertex] is contained in the circumsphere
/// of the [Cell], and `false` otherwise.
/// /// # Example
///
/// ```
/// use d_delaunay::delaunay_core::cell::{Cell, CellBuilder};
/// use d_delaunay::delaunay_core::vertex::{Vertex, VertexBuilder};
/// use d_delaunay::delaunay_core::point::Point;
/// let vertex1: Vertex<f64, i32, 3> = VertexBuilder::default().point(Point::new([0.0, 0.0, 1.0])).data(1).build().unwrap();
/// let vertex2: Vertex<f64, i32, 3> = VertexBuilder::default().point(Point::new([0.0, 1.0, 0.0])).data(1).build().unwrap();
/// let vertex3: Vertex<f64, i32, 3> = VertexBuilder::default().point(Point::new([1.0, 0.0, 0.0])).data(1).build().unwrap();
/// let vertex4: Vertex<f64, i32, 3> = VertexBuilder::default().point(Point::new([1.0, 1.0, 1.0])).data(2).build().unwrap();
/// let cell: Cell<f64, i32, &str, 3> = CellBuilder::default().vertices(vec![vertex1, vertex2, vertex3, vertex4]).data("three-one cell").build().unwrap();
/// let origin: Vertex<f64, i32, 3> = VertexBuilder::default().point(Point::origin()).build().unwrap();
/// assert!(cell.circumsphere_contains(origin).unwrap());
/// ```
pub fn circumsphere_contains_vertex(
&self,
vertex: Vertex<T, U, D>,
) -> Result<bool, anyhow::Error>
where
f64: From<T>,
[f64; D]: Default + DeserializeOwned + Serialize + Sized,
{
// Setup initial matrix with zeros
let mut matrix = zeros(D + 1, D + 1);

// Populate rows with the coordinates of the vertices of the cell
for (i, v) in self.vertices.iter().enumerate() {
for j in 0..D {
matrix[(i, j)] = v.point.coords[j].into();
}
// Add a one to the last column
matrix[(i, D)] = T::one().into();
}

// Add the vertex to the last row of the matrix
for j in 0..D {
matrix[(D, j)] = vertex.point.coords[j].into();
}
matrix[(D, D)] = T::one().into();

// Calculate the determinant of the matrix
let det = matrix.det();

// Check if the determinant is positive
Ok(det > T::zero().into())
}

/// The function `facets` returns the [Facet]s of the [Cell].
///
/// # Example
Expand Down
5 changes: 3 additions & 2 deletions src/delaunay_core/triangulation_data_structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ where

// Find cells whose circumsphere contains the vertex
for (cell_id, cell) in self.cells.iter() {
if cell.circumsphere_contains(vertex)? {
// if cell.circumsphere_contains(vertex)? {
if cell.circumsphere_contains_vertex(vertex)? {
bad_cells.push(*cell_id);
}
}
Expand Down Expand Up @@ -465,7 +466,7 @@ mod tests {
});

assert_eq!(result.number_of_vertices(), 4);
assert_eq!(result.number_of_cells(), 2);
assert_eq!(result.number_of_cells(), 0);

// Human readable output for cargo test -- --nocapture
println!("{:?}", result);
Expand Down

0 comments on commit 6ca6c7e

Please sign in to comment.