Skip to content

Commit

Permalink
Tds add function and dimensionality constraints
Browse files Browse the repository at this point in the history
Tds::add to add one vertex to the triangulation data structure.

Set the dimensionality of the Tds using CGAL conventions:

-1 if no vertices are present
0 for a single vertex
1 for two vertices (edge)
2 for three vertices (face)
Up to D for D+1 vertices or greater

Where D is the extrinsic dimensionality (i.e. number of coordinates of a point).
  • Loading branch information
acgetchell committed Dec 18, 2023
1 parent 693a1df commit 7645f34
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 6 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ D-dimensional Delaunay triangulations in Rust, inspired by [CGAL].

## Introduction

This library implements d-dimensional Delaunay triangulations and CGAL-like features in Rust. It is inspired by the [CGAL] library, which is a C++ library for computational geometry; and [Spade], a Rust library implementing 2D Delaunay triangulations, Constrained Delaunay triangulations, and Voronoi diagrams. The eventual goal of this library is to provide a lightweight Rust alternative to [CGAL].
This library implements d-dimensional Delaunay triangulations in [Rust]. It is inspired by the [CGAL] library, which is a C++ library for computational geometry; and [Spade], a Rust library implementing 2D Delaunay triangulations, Constrained Delaunay triangulations, and Voronoi diagrams. The eventual goal of this library is to provide a lightweight [Rust] alternative to [CGAL].

At some point I may merge it into another library, such as [Spade], or [delaunay], but for now I am developing this without trying to figure out how to fit into the coding style and standards of another library.
At some point I may merge it into another library, such as [Spade], or [delaunay], but for now I am developing this library without trying to figure out how to fit into other coding styles and standards.

[Rust]: https://rust-lang.org
[CGAL]: https://www.cgal.org/
[Spade]: https://github.com/Stoeoef/spade
[delaunay]: https://crates.io/crates/delaunay
2 changes: 1 addition & 1 deletion src/delaunay_core/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use uuid::Uuid;

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

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Cell<T, U, V, const D: usize> {
pub vertices: Vec<Vertex<T, U, D>>,
pub uuid: Uuid,
Expand Down
95 changes: 92 additions & 3 deletions src/delaunay_core/triangulation_data_structure.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use super::{cell::Cell, point::Point, vertex::Vertex};
use std::collections::HashMap;
use std::cmp::PartialEq;
use std::{cmp::min, collections::HashMap};
use uuid::Uuid;

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Tds<T, U, V, const D: usize> {
pub vertices: HashMap<Uuid, Vertex<T, U, D>>,
pub cells: HashMap<Uuid, Cell<T, U, V, D>>,
Expand All @@ -14,6 +15,34 @@ impl<T, U, V, const D: usize> Tds<T, U, V, D> {
let cells = HashMap::new();
Self { vertices, cells }
}

pub fn add(&mut self, vertex: Vertex<T, U, D>) -> Result<(), &'static str>
where
T: PartialEq,
{
// Don't add if vertex with that point already exists
for val in self.vertices.values() {
if val.point.coords == vertex.point.coords {
return Err("Vertex already exists");
}
}

let result = self.vertices.insert(vertex.uuid, vertex);
match result {
Some(_) => Err("Uuid already exists"),
None => Ok(()),
}
}

pub fn number_of_vertices(&self) -> usize {
self.vertices.len()
}

pub fn dim(&self) -> i32 {
let len = self.vertices.len() as i32;

min(len - 1, D as i32)
}
}

pub fn start() -> i32 {
Expand All @@ -27,7 +56,7 @@ mod tests {
use super::*;

#[test]
fn make_tds() {
fn tds_new() {
let points = vec![
Point::new([1.0, 2.0, 3.0]),
Point::new([4.0, 5.0, 6.0]),
Expand All @@ -39,8 +68,68 @@ mod tests {

assert_eq!(tds.vertices.len(), 4);
assert_eq!(tds.cells.len(), 0);
assert_eq!(tds.dim(), 3);

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

#[test]
fn tds_add_dim() {
let points: Vec<Point<f64, 3>> = Vec::new();

let mut tds: Tds<f64, usize, usize, 3> = Tds::new(points);

assert_eq!(tds.vertices.len(), 0);
assert_eq!(tds.cells.len(), 0);
assert_eq!(tds.dim(), -1);

let new_vertex1: Vertex<f64, usize, 3> = Vertex::new(Point::new([1.0, 2.0, 3.0]));
let _ = tds.add(new_vertex1);
assert_eq!(tds.vertices.len(), 1);
assert_eq!(tds.dim(), 0);

let new_vertex2: Vertex<f64, usize, 3> = Vertex::new(Point::new([4.0, 5.0, 6.0]));
let _ = tds.add(new_vertex2);
assert_eq!(tds.vertices.len(), 2);
assert_eq!(tds.dim(), 1);

let new_vertex3: Vertex<f64, usize, 3> = Vertex::new(Point::new([7.0, 8.0, 9.0]));
let _ = tds.add(new_vertex3);
assert_eq!(tds.vertices.len(), 3);
assert_eq!(tds.dim(), 2);

let new_vertex4: Vertex<f64, usize, 3> = Vertex::new(Point::new([10.0, 11.0, 12.0]));
let _ = tds.add(new_vertex4);
assert_eq!(tds.vertices.len(), 4);
assert_eq!(tds.dim(), 3);

let new_vertex5: Vertex<f64, usize, 3> = Vertex::new(Point::new([13.0, 14.0, 15.0]));
let _ = tds.add(new_vertex5);
assert_eq!(tds.vertices.len(), 5);
assert_eq!(tds.dim(), 3);
}

#[test]
fn tds_no_add() {
let points = vec![
Point::new([1.0, 2.0, 3.0]),
Point::new([4.0, 5.0, 6.0]),
Point::new([7.0, 8.0, 9.0]),
Point::new([10.0, 11.0, 12.0]),
];

let mut tds: Tds<f64, usize, usize, 3> = Tds::new(points);

assert_eq!(tds.vertices.len(), 4);
assert_eq!(tds.cells.len(), 0);
assert_eq!(tds.dim(), 3);

let new_vertex1: Vertex<f64, usize, 3> = Vertex::new(Point::new([1.0, 2.0, 3.0]));
let result = tds.add(new_vertex1);
assert_eq!(tds.vertices.len(), 4);
assert_eq!(tds.dim(), 3);

assert!(result.is_err());
}
}

0 comments on commit 7645f34

Please sign in to comment.