Skip to content

Commit

Permalink
Implement PartialEq, Eq, and PartialOrd on Vertex
Browse files Browse the repository at this point in the history
Following:

https://www.philipdaniels.com/blog/2019/rust-equality-and-ordering/

Implemented my own based strictly on the point contained in the vertex. Two vertices should be equal if their points are equal, even if their Uuids are different (this should be an error).

Because I have f64, I cannot implement Hash or Ord without further work.

All this because I'm getting extra Facets which should be filtered out but I suspect are not because default Eq is allowing dupes.
  • Loading branch information
acgetchell committed Jan 18, 2024
1 parent d55df6f commit 1430ce1
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 39 deletions.
13 changes: 7 additions & 6 deletions src/delaunay_core/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ use uuid::Uuid;
/// `i-th`` vertex.
/// * `data`: The `data` property is an optional field that can hold a value of
/// type `V`. It allows storage of additional data associated with the `Cell`.
pub struct Cell<T: Clone + Copy + Default, U, V, const D: usize>
pub struct Cell<T, U, V, const D: usize>
where
[T; D]: Default + DeserializeOwned + Serialize + Sized,
T: Clone + Copy + Default + PartialEq + PartialOrd,
U: Clone + Copy + PartialEq,
V: Clone + Copy + PartialEq,
[T; D]: Default + DeserializeOwned + Serialize + Sized,
{
/// The vertices of the cell.
pub vertices: Vec<Vertex<T, U, D>>,
Expand All @@ -41,14 +42,14 @@ where
pub data: Option<V>,
}

impl<T: Clone + ComplexField<RealField = T> + Copy + Default + Sum, U, V, const D: usize>
Cell<T, U, V, D>
impl<T, U, V, const D: usize> Cell<T, U, V, D>
where
T: Clone + ComplexField<RealField = T> + Copy + Default + PartialOrd + Sum,
U: Clone + Copy + PartialEq,
V: Clone + Copy + PartialEq,
for<'a> &'a T: Div<f64>,
f64: From<T>,
[T; D]: Default + DeserializeOwned + Serialize + Sized,
U: Clone + Copy + PartialEq,
V: Clone + Copy + PartialEq,
{
/// The function `new` creates a new `Cell`` object with the given
/// vertices. A D-dimensional cell has D + 1 vertices, so the number of
Expand Down
9 changes: 5 additions & 4 deletions src/delaunay_core/facet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
///
/// Note that `D` is the dimensionality of the `Cell` and `Vertex`;
/// the `Facet` is one dimension less than the `Cell` (co-dimension 1).
pub struct Facet<T: Clone + Copy + Default, U, V, const D: usize>
pub struct Facet<T, U, V, const D: usize>
where
[T; D]: Default + DeserializeOwned + Serialize + Sized,
T: Clone + Copy + Default + PartialEq + PartialOrd,
U: Clone + Copy + PartialEq,
V: Clone + Copy + PartialEq,
[T; D]: Default + DeserializeOwned + Serialize + Sized,
{
/// The `Cell` that contains this facet.
pub cell: Cell<T, U, V, D>,
Expand All @@ -36,10 +37,10 @@ where

impl<T, U, V, const D: usize> Facet<T, U, V, D>
where
T: Copy + Default + PartialEq,
[T; D]: Default + DeserializeOwned + Serialize + Sized,
T: Clone + Copy + Default + PartialEq + PartialOrd,
U: Clone + Copy + PartialEq,
V: Clone + Copy + PartialEq,
[T; D]: Default + DeserializeOwned + Serialize + Sized,
{
/// The `new` function is a constructor for the `Facet` struct. It takes
/// in a `Cell` and a `Vertex` as arguments and returns a `Result`
Expand Down
14 changes: 8 additions & 6 deletions src/delaunay_core/point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use serde::{de::DeserializeOwned, Deserialize, Serialize};

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PartialOrd)]
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, PartialOrd, Serialize)]
/// The `Point` struct represents a point in a D-dimensional space, where the
/// coordinates are of type `T`.
///
Expand All @@ -12,19 +12,20 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
/// type `T` with a length of `D`. The type `T` is a generic type parameter,
/// which means it can be any type. The length `D` is a constant unsigned
/// integer, which means it cannot be changed and is known at compile time.
pub struct Point<T: Clone + Copy + Default, const D: usize>
pub struct Point<T, const D: usize>
where
[T; D]: Default + DeserializeOwned + Serialize + Sized,
T: PartialOrd,
[T; D]: Copy + Default + DeserializeOwned + PartialEq + Serialize + Sized,
{
/// The coordinates of the point.
pub coords: [T; D],
}

impl<T, const D: usize> From<[T; D]> for Point<f64, D>
where
T: Into<f64>,
[T; D]: Default + DeserializeOwned + Serialize + Sized,
[f64; D]: Default + DeserializeOwned + Serialize + Sized,
T: Into<f64>,
{
fn from(coords: [T; D]) -> Self {
// Convert the `coords` array to `[f64; D]`
Expand All @@ -33,8 +34,9 @@ where
}
}

impl<T: Clone + Copy + Default, const D: usize> Point<T, D>
impl<T, const D: usize> Point<T, D>
where
T: Clone + Copy + Default + PartialEq + PartialOrd,
[T; D]: Default + DeserializeOwned + Serialize + Sized,
{
/// The function `new` creates a new instance of a `Point` with the given
Expand Down Expand Up @@ -93,7 +95,7 @@ where
/// ```
pub fn origin() -> Self
where
T: num_traits::Zero + Copy, // Add the Copy trait bound
T: num_traits::Zero + Copy,
{
Self::new([T::zero(); D])
}
Expand Down
32 changes: 15 additions & 17 deletions src/delaunay_core/triangulation_data_structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ use uuid::Uuid;
///
/// In general, vertices are embedded into D-dimensional Euclidean space,
/// and so the `Tds` is a finite simplicial complex.
pub struct Tds<T: Clone + Copy + Default, U, V, const D: usize>
pub struct Tds<T, U, V, const D: usize>
where
[T; D]: Default + DeserializeOwned + Serialize + Sized,
T: Clone + Copy + Default + PartialEq + PartialOrd,
U: Clone + Copy + PartialEq,
V: Clone + Copy + PartialEq,
[T; D]: Default + DeserializeOwned + Serialize + Sized,
{
/// A `HashMap` that stores vertices with their corresponding `Uuid`s as
/// keys. Each `Vertex` has a `Point` of type T, vertex data of type U,
Expand All @@ -62,24 +63,21 @@ where
pub cells: HashMap<Uuid, Cell<T, U, V, D>>,
}

impl<
T: AddAssign<f64>
+ Clone
+ Copy
+ ComplexField<RealField = T>
+ Default
+ SubAssign<f64>
+ Sum,
U,
V,
const D: usize,
> Tds<T, U, V, D>
impl<T, U, V, const D: usize> Tds<T, U, V, D>
where
T: AddAssign<f64>
+ Clone
+ Copy
+ ComplexField<RealField = T>
+ Default
+ PartialOrd
+ SubAssign<f64>
+ Sum,
U: Clone + Copy + PartialEq,
V: Clone + Copy + PartialEq,
f64: From<T>,
for<'a> &'a T: Div<f64>,
[T; D]: Default + DeserializeOwned + Serialize + Sized,
U: Clone + Copy + PartialEq,
V: Clone + Copy + PartialEq,
{
/// The function creates a new instance of a triangulation data structure
/// with given points, initializing the vertices and cells.
Expand Down Expand Up @@ -449,7 +447,7 @@ mod tests {
#[test]
fn tds_bowyer_watson() {
let points = vec![
Point::new([1.0, 1.0, 1.0]),
Point::new([0.0, 0.0, 0.0]),
Point::new([1.0, 0.0, 0.0]),
Point::new([0.0, 1.0, 0.0]),
Point::new([0.0, 0.0, 1.0]),
Expand Down
2 changes: 1 addition & 1 deletion src/delaunay_core/utilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ pub fn find_extreme_coordinates<T, U, const D: usize>(
) -> [T; D]
where
T: Clone + Copy + Default + PartialOrd,
[T; D]: Default + DeserializeOwned + Serialize + Sized,
U: Clone + Copy + PartialEq,
[T; D]: Default + DeserializeOwned + Serialize + Sized,
{
let mut min_coords = [Default::default(); D];

Expand Down
59 changes: 54 additions & 5 deletions src/delaunay_core/vertex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::{collections::HashMap, option::Option};
use uuid::Uuid;

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PartialOrd)]
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Serialize)]
/// The `Vertex` struct represents a vertex in a triangulation with a `Point`,
/// a unique identifier, an optional incident cell identifier, and optional
/// data.
Expand All @@ -22,10 +22,11 @@ use uuid::Uuid;
/// calculated by the `delaunay_core::triangulation_data_structure::Tds`.
/// * `data`: The `data` property is an optional field that can hold any
/// type `U`. It is used to store additional data associated with the vertex.
pub struct Vertex<T: Clone + Copy + Default, U, const D: usize>
pub struct Vertex<T, U, const D: usize>
where
[T; D]: Default + DeserializeOwned + Serialize + Sized,
T: Clone + Copy + Default + PartialEq + PartialOrd,
U: Clone + Copy + PartialEq,
[T; D]: Copy + Default + DeserializeOwned + Serialize + Sized,
{
/// The coordinates of the vertex in a D-dimensional space.
pub point: Point<T, D>,
Expand All @@ -37,10 +38,11 @@ where
pub data: Option<U>,
}

impl<T: Clone + Copy + Default, U, const D: usize> Vertex<T, U, D>
impl<T, U, const D: usize> Vertex<T, U, D>
where
[T; D]: Default + DeserializeOwned + Serialize + Sized,
T: Clone + Copy + Default + PartialEq + PartialOrd,
U: Clone + Copy + PartialEq,
[T; D]: Copy + Default + DeserializeOwned + Serialize + Sized,
{
/// The function creates a new instance of a `Vertex`.
///
Expand Down Expand Up @@ -173,6 +175,34 @@ where
todo!("Implement is_valid for Vertex")
}
}

impl<T, U, const D: usize> PartialEq for Vertex<T, U, D>
where
T: Clone + Copy + Default + PartialEq + PartialOrd,
U: Clone + Copy + PartialEq,
[T; D]: Copy + Default + DeserializeOwned + Serialize + Sized,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.point == other.point
// && self.uuid == other.uuid
// && self.incident_cell == other.incident_cell
// && self.data == other.data
}
}

impl<T, U, const D: usize> PartialOrd for Vertex<T, U, D>
where
T: Clone + Copy + Default + PartialEq + PartialOrd,
U: Clone + Copy + PartialEq,
[T; D]: Copy + Default + DeserializeOwned + Serialize + Sized,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.point.partial_cmp(&other.point)
}
}

#[cfg(test)]
mod tests {

Expand Down Expand Up @@ -277,4 +307,23 @@ mod tests {
// Human readable output for cargo test -- --nocapture
println!("Serialized: {:?}", serialized);
}

#[test]
fn vertex_partial_eq() {
let vertex1: Vertex<f64, Option<()>, 3> = Vertex::new(Point::new([1.0, 2.0, 3.0]));
let vertex2: Vertex<f64, Option<()>, 3> = Vertex::new(Point::new([1.0, 2.0, 3.0]));
let vertex3: Vertex<f64, Option<()>, 3> = Vertex::new(Point::new([1.0, 2.0, 4.0]));

assert_eq!(vertex1, vertex2);
assert_ne!(vertex1, vertex3);
}

#[test]
fn vertex_partial_ord() {
let vertex1: Vertex<f64, Option<()>, 3> = Vertex::new(Point::new([1.0, 2.0, 3.0]));
let vertex2: Vertex<f64, Option<()>, 3> = Vertex::new(Point::new([1.0, 2.0, 4.0]));

assert!(vertex1 < vertex2);
assert!(vertex2 > vertex1);
}
}

0 comments on commit 1430ce1

Please sign in to comment.