Skip to main content

use_polyhedron/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use use_vector::Vector3;
5
6/// A polyhedron vertex.
7#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct Vertex {
9    position: Vector3,
10}
11
12impl Vertex {
13    /// Creates a vertex.
14    #[must_use]
15    pub const fn new(position: Vector3) -> Self {
16        Self { position }
17    }
18
19    /// Returns the vertex position.
20    #[must_use]
21    pub const fn position(self) -> Vector3 {
22        self.position
23    }
24}
25
26/// A polyhedron edge represented by vertex indices.
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub struct Edge {
29    start: usize,
30    end: usize,
31}
32
33impl Edge {
34    /// Creates an edge between two vertex indices.
35    #[must_use]
36    pub const fn new(start: usize, end: usize) -> Self {
37        Self { start, end }
38    }
39
40    /// Returns the edge endpoints.
41    #[must_use]
42    pub const fn endpoints(self) -> (usize, usize) {
43        (self.start, self.end)
44    }
45}
46
47/// A polyhedron face record represented by vertex indices.
48#[derive(Debug, Clone, PartialEq, Eq)]
49pub struct PolyhedronFace {
50    vertices: Vec<usize>,
51}
52
53impl PolyhedronFace {
54    /// Creates a face record.
55    #[must_use]
56    pub const fn new(vertices: Vec<usize>) -> Self {
57        Self { vertices }
58    }
59
60    /// Returns the face vertex indices.
61    #[must_use]
62    pub fn vertices(&self) -> &[usize] {
63        &self.vertices
64    }
65}
66
67/// A polyhedron count summary.
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub struct Polyhedron {
70    vertex_count: usize,
71    edge_count: usize,
72    face_count: usize,
73}
74
75impl Polyhedron {
76    /// Creates a polyhedron from positive vertex, edge, and face counts.
77    #[must_use]
78    pub const fn from_counts(
79        vertex_count: usize,
80        edge_count: usize,
81        face_count: usize,
82    ) -> Option<Self> {
83        if vertex_count > 0 && edge_count > 0 && face_count > 0 {
84            Some(Self {
85                vertex_count,
86                edge_count,
87                face_count,
88            })
89        } else {
90            None
91        }
92    }
93
94    /// Returns the vertex count.
95    #[must_use]
96    pub const fn vertex_count(self) -> usize {
97        self.vertex_count
98    }
99
100    /// Returns the edge count.
101    #[must_use]
102    pub const fn edge_count(self) -> usize {
103        self.edge_count
104    }
105
106    /// Returns the face count.
107    #[must_use]
108    pub const fn face_count(self) -> usize {
109        self.face_count
110    }
111
112    /// Returns `V - E + F`.
113    #[must_use]
114    pub const fn euler_characteristic(self) -> isize {
115        self.vertex_count as isize - self.edge_count as isize + self.face_count as isize
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::{Edge, Polyhedron, PolyhedronFace, Vertex};
122    use use_vector::Vector3;
123
124    #[test]
125    fn stores_polyhedron_records() {
126        let vertex = Vertex::new(Vector3::new(1.0, 2.0, 3.0));
127        let edge = Edge::new(0, 1);
128        let face = PolyhedronFace::new(vec![0, 1, 2]);
129        let polyhedron = Polyhedron::from_counts(8, 12, 6).expect("valid counts");
130
131        assert_eq!(vertex.position(), Vector3::new(1.0, 2.0, 3.0));
132        assert_eq!(edge.endpoints(), (0, 1));
133        assert_eq!(face.vertices(), &[0, 1, 2]);
134        assert_eq!(polyhedron.euler_characteristic(), 2);
135    }
136}