Skip to content

Commit

Permalink
Added Serialization via serde
Browse files Browse the repository at this point in the history
  • Loading branch information
acgetchell committed Jan 3, 2024
1 parent ba20c84 commit a89ff48
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 45 deletions.
70 changes: 63 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ edition = "2021"
[dependencies]
nalgebra = "0.32.3"
num-traits = "0.2.17"
uuid = { version = "1.6.1", features = ["v4", "fast-rng", "macro-diagnostics"] }
serde = { version = "1.0.194", features = ["derive"] }
serde_json = "1.0.110"
serde_test = "1.0.176"
uuid = { version = "1.6.1", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] }

[lints.rust]
unsafe_code = "forbid"
Expand Down
42 changes: 31 additions & 11 deletions src/delaunay_core/cell.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
//! Data and operations on d-dimensional cells or [simplices](https://en.wikipedia.org/wiki/Simplex).
use std::{fmt::Debug, ops::Div};

use uuid::Uuid;

use super::{point::Point, utilities::make_uuid, vertex::Vertex};

use nalgebra as na;

use na::{Const, OPoint};

use crate::delaunay_core;
use na::{Const, OPoint};
use nalgebra as na;
use serde::Serialize;
use std::{fmt::Debug, ops::Div};
use uuid::Uuid;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize)]
/// The `Cell` struct represents a d-dimensional [simplex](https://en.wikipedia.org/wiki/Simplex)
/// with vertices, a unique identifier, optional neighbors, and optional data.
///
Expand All @@ -27,7 +23,10 @@ use crate::delaunay_core;
/// neighbor is opposite the `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: std::default::Default + std::marker::Copy, U, V, const D: usize> {
pub struct Cell<T: std::default::Default + std::marker::Copy, U, V, const D: usize>
where
[T; D]: Serialize,
{
/// The vertices of the cell.
pub vertices: Vec<Vertex<T, U, D>>,
/// The unique identifier of the cell.
Expand All @@ -50,6 +49,7 @@ impl<
where
for<'a> &'a T: Div<f64>,
f64: From<T>,
[T; D]: Serialize,
{
/// The function `new` creates a new `Cell`` object with the given vertices.
/// A D-dimensional cell has D + 1 vertices, so the number of vertices must be less than or equal to D + 1.
Expand Down Expand Up @@ -248,6 +248,8 @@ where
fn circumcenter(&self) -> Result<Point<f64, D>, &'static str>
where
T: Clone + Copy + PartialEq + Debug + 'static,
[T; D]: Serialize,
[f64; D]: Sized + Serialize,
{
let dim = self.dim();
if self.vertices[0].dim() != dim {
Expand Down Expand Up @@ -301,6 +303,7 @@ where
where
T: Copy,
OPoint<T, Const<D>>: From<[f64; D]>,
[f64; D]: Serialize,
{
let circumcenter = self.circumcenter()?;
// Change the type of vertex to match circumcenter
Expand Down Expand Up @@ -338,6 +341,7 @@ where
where
T: Copy + PartialOrd, // Add the PartialOrd trait bound
OPoint<T, Const<D>>: From<[f64; D]>,
[f64; D]: Serialize,
{
let circumradius = self.circumradius()?;
let radius = na::distance(
Expand Down Expand Up @@ -589,4 +593,20 @@ mod tests {
// Human readable output for cargo test -- --nocapture
println!("Cell: {:?}", cell);
}

#[test]
fn cell_serialization() {
let vertex1 = Vertex::new(Point::new([0.0, 0.0, 1.0]));
let vertex2 = Vertex::new(Point::new([0.0, 1.0, 0.0]));
let vertex3 = Vertex::new(Point::new([1.0, 0.0, 0.0]));
let vertex4 = Vertex::new(Point::new([1.0, 1.0, 1.0]));
let cell: Cell<f64, Option<()>, Option<()>, 3> =
Cell::new(vec![vertex1, vertex2, vertex3, vertex4]).unwrap();

let serialized = serde_json::to_string(&cell).unwrap();
assert!(serialized.contains("[0.0,0.0,1.0]"));
assert!(serialized.contains("[0.0,1.0,0.0]"));
assert!(serialized.contains("[1.0,0.0,0.0]"));
assert!(serialized.contains("[1.0,1.0,1.0]"));
}
}
53 changes: 47 additions & 6 deletions src/delaunay_core/point.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Data and operations on d-dimensional points.
#[derive(Debug, Clone, PartialEq, Copy)]
use serde::Serialize;

#[derive(Debug, Clone, PartialEq, Copy, Serialize)]
/// The `Point` struct represents a point in a D-dimensional space, where the coordinates are of type
/// `T`.
///
Expand All @@ -9,12 +11,18 @@
/// * `coords`: `coords` is a public property of the `Point`. It is an array of 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, const D: usize> {
pub struct Point<T, const D: usize>
where
[T; D]: Serialize,
{
/// The coordinates of the point.
pub coords: [T; D],
}

impl<T: std::default::Default + Copy, const D: usize> Default for Point<T, D> {
impl<T: std::default::Default + Copy, const D: usize> Default for Point<T, D>
where
[T; D]: Serialize,
{
fn default() -> Self {
Self {
coords: [Default::default(); D],
Expand All @@ -24,8 +32,8 @@ impl<T: std::default::Default + Copy, const D: usize> Default for Point<T, D> {

impl<T, const D: usize> From<[T; D]> for Point<f64, D>
where
[T; D]: Sized,
[f64; D]: Sized,
[T; D]: Sized + Serialize,
[f64; D]: Sized + Serialize,
T: Into<f64>,
{
fn from(coords: [T; D]) -> Self {
Expand All @@ -35,7 +43,10 @@ where
}
}

impl<T: Clone + std::default::Default + Copy, const D: usize> Point<T, D> {
impl<T: Clone + std::default::Default + Copy, const D: usize> Point<T, D>
where
[T; D]: Serialize,
{
/// The function `new` creates a new instance of a `Point` with the given coordinates.
///
/// # Arguments:
Expand Down Expand Up @@ -143,4 +154,34 @@ mod tests {
// Human readable output for cargo test -- --nocapture
println!("Default: {:?} is {}-D", point, point.dim());
}

#[test]
fn point_serialization() {
use serde_test::{assert_ser_tokens, Token};

let point2: Point<f64, 3> = Point::new([1.0, 2.0, 3.0]);
assert_ser_tokens(
&point2,
&[
Token::Struct {
name: "Point",
len: 1,
},
Token::Str("coords"),
Token::Tuple { len: 3 },
Token::F64(1.0),
Token::F64(2.0),
Token::F64(3.0),
Token::TupleEnd,
Token::StructEnd,
],
);

let point: Point<f64, 4> = Default::default();
let serialized = serde_json::to_string(&point).unwrap();
assert_eq!(serialized, "{\"coords\":[0.0,0.0,0.0,0.0]}");

// Human readable output for cargo test -- --nocapture
println!("Serialized: {:?}", serialized);
}
}
10 changes: 8 additions & 2 deletions src/delaunay_core/triangulation_data_structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ use super::utilities::find_extreme_coordinates;
use super::{cell::Cell, point::Point, vertex::Vertex};
use na::{Const, OPoint};
use nalgebra as na;
use serde::Serialize;
use std::cmp::{Ordering, PartialEq};
use std::ops::Div;
use std::{cmp::min, collections::HashMap};
use uuid::Uuid;

#[derive(Debug, Default, Clone)]
#[derive(Debug, Default, Clone, Serialize)]
/// The `Tds` struct represents a triangulation data structure with vertices and cells, where the vertices
/// and cells are identified by UUIDs.
///
Expand All @@ -34,7 +35,10 @@ use uuid::Uuid;
/// A similar pattern holds for higher dimensions.
///
/// In general, vertices are embedded into D-dimensional Euclidean space, and so the `Tds` is a finite simplicial complex.
pub struct Tds<T: std::default::Default + std::marker::Copy, U, V, const D: usize> {
pub struct Tds<T: std::default::Default + std::marker::Copy, U, V, const D: usize>
where
[T; D]: Serialize,
{
/// A HashMap that stores vertices with their corresponding UUIDs as keys.
/// Each `Vertex` has a `Point` of type T, vertex data of type U, and a constant D representing the dimension.
pub vertices: HashMap<Uuid, Vertex<T, U, D>>,
Expand All @@ -60,6 +64,7 @@ impl<
where
f64: From<T>,
for<'a> &'a T: Div<f64>,
[T; D]: Serialize,
{
/// The function creates a new instance of a triangulation data structure with given points, initializing the vertices and
/// cells.
Expand Down Expand Up @@ -230,6 +235,7 @@ where
T: Copy + Default + PartialOrd,
Vertex<T, U, D>: Clone, // Add the Clone trait bound for Vertex
OPoint<T, Const<D>>: From<[f64; D]>,
[f64; D]: Serialize,
{
let mut cells: Vec<Cell<T, U, V, D>> = Vec::new();

Expand Down
9 changes: 4 additions & 5 deletions src/delaunay_core/utilities.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
//! Utility functions
use std::collections::HashMap;

use uuid::Uuid;

use super::vertex::Vertex;

use serde::Serialize;
use std::cmp::Ordering;
use std::collections::HashMap;
use uuid::Uuid;

/// The function `make_uuid` generates a version 4 UUID in Rust.
///
Expand Down Expand Up @@ -65,6 +63,7 @@ pub fn find_extreme_coordinates<T, U, const D: usize>(
) -> [T; D]
where
T: Copy + Default + PartialOrd,
[T; D]: Sized + Serialize,
{
let mut min_coords = [Default::default(); D];

Expand Down
Loading

0 comments on commit a89ff48

Please sign in to comment.