math_utils/geometry/mesh/
edge_triangle.rs1use std::collections::{BTreeMap, BTreeSet};
7#[cfg(feature = "derive_serdes")]
8use serde::{Deserialize, Serialize};
9
10#[derive(Clone, Debug, Default, Eq, PartialEq)]
11#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
12pub struct VertexEdgeTriangleMesh {
13 et_mesh : EdgeTriangleMesh,
14 vertices : BTreeMap <u32, Vertex>
15}
16
17#[derive(Clone, Debug, Default, Eq, PartialEq)]
18#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
19pub struct EdgeTriangleMesh {
20 pub(crate) edges : BTreeMap <EdgeKey, Edge>,
21 pub(crate) triangles : BTreeMap <TriangleKey, Triangle>,
22}
23
24#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
26#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
27pub struct EdgeKey (u32, u32);
28#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
29#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
30pub struct TriangleKey (u32, u32, u32);
31
32#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
33#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
34pub struct Vertex {
35 index : u32,
36 adjacent_vertices : BTreeSet <u32>,
37 adjacent_edges : BTreeSet <EdgeKey>,
38 adjacent_triangles : BTreeSet <TriangleKey>
39}
40
41#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
42#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
43pub struct Edge {
44 vertices : [u32; 2],
45 triangles : [Option <TriangleKey>; 2]
46}
47
48#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
49#[cfg_attr(feature = "derive_serdes", derive(Serialize, Deserialize))]
50pub struct Triangle {
51 vertices : [u32; 3],
53 edges : [Option <EdgeKey>; 3],
54 adjacent_triangles : [Option <TriangleKey>; 3],
56}
57
58impl EdgeTriangleMesh {
59 #[inline]
60 pub fn get_edge (&self, key : &EdgeKey) -> Option <&Edge> {
61 self.edges.get (key)
62 }
63 #[inline]
64 pub fn get_triangle (&self, key : &TriangleKey) -> Option <&Triangle> {
65 self.triangles.get (key)
66 }
67 #[inline]
68 pub const fn edges (&self) -> &BTreeMap <EdgeKey, Edge> {
69 &self.edges
70 }
71 #[inline]
72 pub const fn triangles (&self) -> &BTreeMap <TriangleKey, Triangle> {
73 &self.triangles
74 }
75
76 pub fn insert (&mut self, v0 : u32, v1 : u32, v2 : u32) -> Option <Triangle> {
78 self.insert_ (v0, v1, v2).map (|inserted| inserted.1)
79 }
80 fn insert_ (&mut self, v0 : u32, v1 : u32, v2 : u32)
81 -> Option <(TriangleKey, Triangle)>
82 {
83 let triangle_key = TriangleKey (v0, v1, v2);
84 if self.triangles.contains_key (&triangle_key) {
85 return None
86 }
87 let mut triangle = Triangle::new (v0, v1, v2);
88 let mut i0 = 2;
89 let mut i1 = 0;
90 while i1 < 3 {
91 let edge_key = EdgeKey::new (triangle.vertices[i0], triangle.vertices[i1]);
92 if let Some (mut edge) = self.edges.get (&edge_key).copied() {
93 if edge.triangles[1].is_some() {
95 return None
96 }
97 edge.triangles[1] = Some (triangle_key);
98 let adjacent_key = edge.triangles[0].unwrap();
99 let adjacent = self.triangles.get_mut (&adjacent_key).unwrap();
100 for (i, e_key) in adjacent.edges.iter().enumerate() {
101 if e_key == &Some (edge_key) {
102 adjacent.adjacent_triangles[i] = Some (triangle_key);
103 break
104 }
105 }
106 triangle.edges[i0] = Some (edge_key);
107 triangle.adjacent_triangles[i0] = Some (adjacent_key);
108 *self.edges.get_mut (&edge_key).unwrap() = edge;
109 } else {
110 let mut new_edge = Edge::new (edge_key.0, edge_key.1);
111 new_edge.triangles[0] = Some (triangle_key);
112 triangle.edges[i0] = Some (edge_key);
113 let inserted = self.edges.insert (edge_key, new_edge);
114 debug_assert!(inserted.is_none());
115 }
116 i0 = i1;
118 i1 += 1;
119 }
120 let inserted = self.triangles.insert (triangle_key, triangle);
121 debug_assert!(inserted.is_none());
122 Some ((triangle_key, triangle))
123 }
124
125 #[expect(clippy::missing_panics_doc)]
126 pub fn remove (&mut self, v0 : u32, v1 : u32, v2 : u32) -> bool {
127 let triangle_key = TriangleKey (v0, v1, v2);
128 if let Some (triangle) = self.triangles.remove (&triangle_key) {
129 for (i, edge_key) in triangle.edges.iter().map (|k| k.unwrap()).enumerate() {
130 let edge = self.edges.get_mut (&edge_key).unwrap();
131 if edge.triangles[0] == Some (triangle_key) {
132 edge.triangles[0] = edge.triangles[1];
133 edge.triangles[1] = None;
134 } else if edge.triangles[1] == Some (triangle_key) {
135 edge.triangles[1] = None;
136 } else {
137 unreachable!()
138 }
139 if edge.triangles[0].is_none() && edge.triangles[1].is_none() {
140 self.edges.remove (&edge_key);
141 }
142 if let Some (adjacent_key) = triangle.adjacent_triangles[i] {
143 let adjacent = self.triangles.get_mut (&adjacent_key).unwrap();
144 for key in adjacent.adjacent_triangles.iter_mut() {
145 if key == &Some (triangle_key) {
146 *key = None;
147 break
148 }
149 }
150 }
151 }
152 true
153 } else {
154 false
155 }
156 }
157
158 }
160
161impl VertexEdgeTriangleMesh {
162 #[inline]
163 pub fn with_vertex (vertex : Vertex) -> Self {
164 let mut mesh = VertexEdgeTriangleMesh::default();
165 mesh.vertices.insert (vertex.index, vertex);
166 mesh
167 }
168 #[inline]
169 pub fn with_edge (edge : Edge) -> Self {
170 let mut mesh = VertexEdgeTriangleMesh::default();
171 let edge_key = EdgeKey::new (edge.vertices[0], edge.vertices[1]);
172 let v0 = Vertex {
173 index: edge_key.0,
174 adjacent_vertices: BTreeSet::from_iter ([edge_key.1]),
175 adjacent_edges: BTreeSet::from_iter ([edge_key]),
176 adjacent_triangles: BTreeSet::new()
177 };
178 let v1 = Vertex {
179 index: edge_key.1,
180 adjacent_vertices: BTreeSet::from_iter ([edge_key.0]),
181 adjacent_edges: BTreeSet::from_iter ([edge_key]),
182 adjacent_triangles: BTreeSet::new()
183 };
184 mesh.vertices.insert (v0.index, v0);
185 mesh.vertices.insert (v1.index, v1);
186 mesh.et_mesh.edges.insert (edge_key, edge);
187 mesh
188 }
189 #[inline]
190 pub fn get_vertex (&self, index : u32) -> Option <&Vertex> {
191 self.vertices.get (&index)
192 }
193
194 #[inline]
195 pub const fn edges (&self) -> &BTreeMap <EdgeKey, Edge> {
196 self.et_mesh.edges()
197 }
198
199 #[inline]
200 pub const fn triangles (&self) -> &BTreeMap <TriangleKey, Triangle> {
201 self.et_mesh.triangles()
202 }
203
204 #[inline]
205 pub const fn vertices (&self) -> &BTreeMap <u32, Vertex> {
206 &self.vertices
207 }
208
209 #[expect(clippy::missing_panics_doc)]
211 pub fn insert (&mut self, v0 : u32, v1 : u32, v2 : u32) -> Option <Triangle> {
212 let (triangle_key, triangle) = self.et_mesh.insert_ (v0, v1, v2)?;
213 for index in triangle.vertices.iter() {
214 let vertex = self.vertices.entry (*index).or_insert_with (|| Vertex::new (*index));
215 vertex.adjacent_triangles.insert (triangle_key);
216 for edge_key in triangle.edges.iter().map (|k| k.unwrap()) {
217 let edge = self.et_mesh.edges.get (&edge_key).unwrap();
218 if edge.vertices[0] == *index {
219 vertex.adjacent_vertices.insert (edge.vertices[1]);
220 vertex.adjacent_edges.insert (edge_key);
221 } else if edge.vertices[1] == *index {
222 vertex.adjacent_vertices.insert (edge.vertices[0]);
223 vertex.adjacent_edges.insert (edge_key);
224 }
225 }
226 }
227 Some (triangle)
228 }
229
230 #[expect(clippy::missing_panics_doc)]
231 pub fn remove (&mut self, v0 : u32, v1 : u32, v2 : u32) -> bool {
232 let triangle_key = TriangleKey (v0, v1, v2);
233 if let Some (triangle) = self.et_mesh.triangles.get (&triangle_key) {
234 for index in triangle.vertices.iter() {
235 let vertex = self.vertices.get_mut (index).unwrap();
236 for edge_key in triangle.edges.iter().map (|k| k.unwrap()) {
237 let edge = self.et_mesh.edges.get (&edge_key).unwrap();
238 if edge.triangles[0].is_some() && edge.triangles[1].is_none() {
239 if edge.vertices[0] == *index {
240 vertex.adjacent_vertices.remove (&edge.vertices[1]);
241 vertex.adjacent_edges.remove (&edge_key);
242 } else if edge.vertices[1] == *index {
243 vertex.adjacent_vertices.remove (&edge.vertices[0]);
244 vertex.adjacent_edges.remove (&edge_key);
245 }
246 }
247 }
248 vertex.adjacent_triangles.remove (&triangle_key);
249 if vertex.adjacent_triangles.is_empty() {
250 self.vertices.remove (index);
251 }
252 }
253 self.et_mesh.remove (v0, v1, v2)
254 } else {
255 false
256 }
257 }
258
259 pub fn reindex (&mut self) {
261 #[expect(clippy::cast_possible_truncation)]
262 self.vertices.values_mut().enumerate().for_each (|(i, v)| v.index = i as u32);
263 self.et_mesh.edges.values_mut().for_each (|edge|
264 edge.vertices.iter_mut().for_each (|v| *v = self.vertices[v].index));
265 self.et_mesh.triangles.values_mut().for_each (|triangle|
266 triangle.vertices.iter_mut().for_each (|v| *v = self.vertices[v].index));
267 #[expect(clippy::needless_collect)] for i in self.vertices.keys().copied().collect::<Vec<_>>() {
269 self.vertices.get_mut (&i).unwrap().adjacent_vertices = self.vertices[&i]
270 .adjacent_vertices.iter().map (|i| self.vertices[i].index).collect();
271 }
272 self.vertices = {
273 #[expect(clippy::cast_possible_truncation)]
274 self.vertices.values().cloned().enumerate().map (|(i, v)| (i as u32, v)).collect()
275 };
276 }
277
278 }
280
281impl std::ops::Deref for VertexEdgeTriangleMesh {
282 type Target = EdgeTriangleMesh;
283 fn deref (&self) -> &EdgeTriangleMesh {
284 &self.et_mesh
285 }
286}
287
288impl Vertex {
289 pub const fn new (index : u32) -> Self {
290 Self {
291 index,
292 adjacent_vertices: BTreeSet::new(),
293 adjacent_edges: BTreeSet::new(),
294 adjacent_triangles: BTreeSet::new()
295 }
296 }
297 pub const fn index (&self) -> u32 {
298 self.index
299 }
300 pub const fn adjacent_vertices (&self) -> &BTreeSet <u32> {
301 &self.adjacent_vertices
302 }
303 pub const fn adjacent_edges (&self) -> &BTreeSet <EdgeKey> {
304 &self.adjacent_edges
305 }
306 pub const fn adjacent_triangles (&self) -> &BTreeSet <TriangleKey> {
307 &self.adjacent_triangles
308 }
309}
310
311impl Edge {
312 pub const fn new (v0 : u32, v1 : u32) -> Self {
313 Edge {
314 vertices: [v0, v1],
315 triangles: [None, None],
316 }
317 }
318 #[inline]
319 pub const fn vertices (&self) -> &[u32; 2] {
320 &self.vertices
321 }
322 #[inline]
323 pub const fn triangles (&self) -> &[Option <TriangleKey>; 2] {
324 &self.triangles
325 }
326}
327
328impl Triangle {
329 pub const fn new (v0 : u32, v1 : u32, v2 : u32) -> Self {
330 Triangle {
331 vertices: [v0, v1, v2],
332 edges: [None, None, None],
333 adjacent_triangles: [None, None, None]
334 }
335 }
336
337 #[inline]
338 pub const fn vertices (&self) -> [u32; 3] {
339 self.vertices
340 }
341 #[inline]
342 pub const fn edges (&self) -> [Option <EdgeKey>; 3] {
343 self.edges
344 }
345 #[inline]
346 pub const fn adjacent_triangles (&self) -> [Option <TriangleKey>; 3] {
347 self.adjacent_triangles
348 }
349}
350
351impl EdgeKey {
352 pub const fn new (a : u32, b : u32) -> Self {
353 if a < b {
354 EdgeKey (a, b)
355 } else {
356 EdgeKey (b, a)
357 }
358 }
359}