1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use use_vector::Vector3;
5
6#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct Vertex {
9 position: Vector3,
10}
11
12impl Vertex {
13 #[must_use]
15 pub const fn new(position: Vector3) -> Self {
16 Self { position }
17 }
18
19 #[must_use]
21 pub const fn position(self) -> Vector3 {
22 self.position
23 }
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub struct Edge {
29 start: usize,
30 end: usize,
31}
32
33impl Edge {
34 #[must_use]
36 pub const fn new(start: usize, end: usize) -> Self {
37 Self { start, end }
38 }
39
40 #[must_use]
42 pub const fn endpoints(self) -> (usize, usize) {
43 (self.start, self.end)
44 }
45}
46
47#[derive(Debug, Clone, PartialEq, Eq)]
49pub struct PolyhedronFace {
50 vertices: Vec<usize>,
51}
52
53impl PolyhedronFace {
54 #[must_use]
56 pub const fn new(vertices: Vec<usize>) -> Self {
57 Self { vertices }
58 }
59
60 #[must_use]
62 pub fn vertices(&self) -> &[usize] {
63 &self.vertices
64 }
65}
66
67#[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 #[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 #[must_use]
96 pub const fn vertex_count(self) -> usize {
97 self.vertex_count
98 }
99
100 #[must_use]
102 pub const fn edge_count(self) -> usize {
103 self.edge_count
104 }
105
106 #[must_use]
108 pub const fn face_count(self) -> usize {
109 self.face_count
110 }
111
112 #[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}