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