Skip to main content

mesh_graph/ops/add/
face.rs

1use glam::Vec3;
2use tracing::{error, instrument};
3
4use crate::{Face, FaceId, HalfedgeId, MeshGraph, VertexId, error_none};
5
6impl MeshGraph {
7    #[instrument(skip(self))]
8    pub fn add_face_from_positions(&mut self, a: Vec3, b: Vec3, c: Vec3) -> AddFace {
9        let a_id = self.add_vertex(a);
10        let b_id = self.add_vertex(b);
11        let c_id = self.add_vertex(c);
12
13        // vertices were just inserted, so this can't fail
14        let inserted_a = self.add_or_get_edge(a_id, b_id).unwrap();
15        let inserted_b = self.add_or_get_edge(b_id, c_id).unwrap();
16        let inserted_c = self.add_or_get_edge(c_id, a_id).unwrap();
17
18        let face_id = self.add_face(
19            inserted_a.start_to_end_he_id,
20            inserted_b.start_to_end_he_id,
21            inserted_c.start_to_end_he_id,
22        );
23
24        let mut halfedge_ids = inserted_a.created_he_ids();
25        halfedge_ids.extend(inserted_b.created_he_ids());
26        halfedge_ids.extend(inserted_c.created_he_ids());
27
28        AddFace {
29            face_id,
30            halfedge_ids,
31            vertex_ids: vec![a_id, b_id, c_id],
32        }
33    }
34
35    /// Returns `None` when an edge already has two faces
36    #[instrument(skip(self))]
37    pub fn add_face_from_halfedge_and_position(
38        &mut self,
39        he_id: HalfedgeId,
40        opposite_vertex_pos: Vec3,
41    ) -> Option<AddFace> {
42        let vertex_id = self.add_vertex(opposite_vertex_pos);
43        self.add_face_from_halfedge_and_vertex(he_id, vertex_id)
44    }
45
46    /// Returns `None` when the edge described by `he_id` already has two faces
47    #[instrument(skip(self))]
48    pub fn add_face_from_halfedge_and_vertex(
49        &mut self,
50        he_id: HalfedgeId,
51        vertex_id: VertexId,
52    ) -> Option<AddFace> {
53        let he_a_id = self.boundary_he(he_id)?;
54
55        let he_a = self.halfedges[he_a_id];
56        let start_vertex_id_he_a = he_a.start_vertex(self)?;
57        let end_vertex_id_he_a = he_a.end_vertex;
58
59        let inserted_b = self.add_or_get_edge(end_vertex_id_he_a, vertex_id)?;
60        let inserted_c = self.add_or_get_edge(vertex_id, start_vertex_id_he_a)?;
61
62        let face_id = self.add_face(
63            he_a_id,
64            inserted_b.start_to_end_he_id,
65            inserted_c.start_to_end_he_id,
66        );
67
68        let mut halfedge_ids = inserted_b.created_he_ids();
69        halfedge_ids.extend(inserted_c.created_he_ids());
70
71        Some(AddFace {
72            face_id,
73            halfedge_ids,
74            vertex_ids: vec![],
75        })
76    }
77
78    /// Creates a face from three vertices.
79    #[instrument(skip(self))]
80    pub fn add_face_from_vertices(
81        &mut self,
82        v_id1: VertexId,
83        v_id2: VertexId,
84        v_id3: VertexId,
85    ) -> Option<AddFace> {
86        let inserted_a = self.add_or_get_edge(v_id1, v_id2)?;
87        let inserted_b = self.add_or_get_edge(v_id2, v_id3)?;
88        let inserted_c = self.add_or_get_edge(v_id3, v_id1)?;
89
90        let face_id = self.add_face(
91            inserted_a.start_to_end_he_id,
92            inserted_b.start_to_end_he_id,
93            inserted_c.start_to_end_he_id,
94        );
95
96        let mut halfedge_ids = inserted_a.created_he_ids();
97        halfedge_ids.extend(inserted_b.created_he_ids());
98        halfedge_ids.extend(inserted_c.created_he_ids());
99
100        Some(AddFace {
101            face_id,
102            halfedge_ids,
103            vertex_ids: vec![],
104        })
105    }
106
107    /// Creates a face from two halfedges.
108    #[instrument(skip(self))]
109    pub fn add_face_from_halfedges(
110        &mut self,
111        he_id1: HalfedgeId,
112        he_id2: HalfedgeId,
113    ) -> Option<AddFace> {
114        let he_id1 = self
115            .boundary_he(he_id1)
116            .or_else(error_none!("Boundary Halfedge 1 {he_id1:?} not found"))?;
117        let he_id2 = self
118            .boundary_he(he_id2)
119            .or_else(error_none!("Boundary Halfedge 2 {he_id2:?} not found"))?;
120
121        let he1 = *self
122            .halfedges
123            .get(he_id1)
124            .or_else(error_none!("Halfedge 1 not found"))?;
125        let he2 = *self
126            .halfedges
127            .get(he_id2)
128            .or_else(error_none!("Halfedge 2 not found"))?;
129
130        let he1_start_vertex = he1
131            .start_vertex(self)
132            .or_else(error_none!("Start vertex should be available"))?;
133
134        let he2_start_vertex = he2
135            .start_vertex(self)
136            .or_else(error_none!("Start vertex should be available"))?;
137
138        if he1_start_vertex == he2.end_vertex {
139            let inserted = self.add_or_get_boundary_edge(he1.end_vertex, he2_start_vertex)?;
140
141            let face_id = self.add_face(inserted.start_to_end_he_id, he_id2, he_id1);
142
143            Some(AddFace {
144                face_id,
145                halfedge_ids: inserted.created_he_ids(),
146                vertex_ids: vec![],
147            })
148        } else if he1_start_vertex == he2_start_vertex {
149            let inserted = self.add_or_get_boundary_edge(he1.end_vertex, he2.end_vertex)?;
150
151            let face_id = self.add_face(
152                inserted.start_to_end_he_id,
153                he2.twin.or_else(error_none!("Twin not set"))?,
154                he_id1,
155            );
156
157            Some(AddFace {
158                face_id,
159                halfedge_ids: inserted.created_he_ids(),
160                vertex_ids: vec![],
161            })
162        } else if he1.end_vertex == he2.end_vertex {
163            let inserted = self.add_or_get_boundary_edge(he2_start_vertex, he1_start_vertex)?;
164
165            let face_id = self.add_face(
166                inserted.start_to_end_he_id,
167                he_id1,
168                he2.twin.or_else(error_none!("Twin not set"))?,
169            );
170
171            Some(AddFace {
172                face_id,
173                halfedge_ids: inserted.created_he_ids(),
174                vertex_ids: vec![],
175            })
176        } else {
177            let inserted = self.add_or_get_boundary_edge(he2.end_vertex, he1_start_vertex)?;
178
179            let face_id = self.add_face(inserted.start_to_end_he_id, he_id1, he_id2);
180
181            Some(AddFace {
182                face_id,
183                halfedge_ids: inserted.created_he_ids(),
184                vertex_ids: vec![],
185            })
186        }
187    }
188
189    /// Inserts a face into the mesh graph. It connects the halfedges to the face and the face to the first halfedge.
190    /// Additionally it connects the halfedges' `next` loop around the face.
191    #[instrument(skip(self))]
192    pub fn add_face(
193        &mut self,
194        he1_id: HalfedgeId,
195        he2_id: HalfedgeId,
196        he3_id: HalfedgeId,
197    ) -> FaceId {
198        let face_id = self.faces.insert_with_key(|id| Face {
199            halfedge: he1_id,
200            index: self.next_index,
201            id,
202        });
203
204        self.index_to_face_id.insert(self.next_index, face_id);
205
206        self.next_index += 1;
207
208        for (he_id, next_he_id) in [(he1_id, he2_id), (he2_id, he3_id), (he3_id, he1_id)] {
209            if let Some(halfedge) = self.halfedges.get_mut(he_id) {
210                halfedge.face = Some(face_id);
211                halfedge.next = Some(next_he_id);
212            } else {
213                error!("Halfedge not found");
214            }
215        }
216
217        let face = self.faces[face_id]; // just inserted above
218        self.bvh
219            .insert_or_update_partially(face.aabb(self), face.index, 0.0);
220
221        face_id
222    }
223}
224
225/// Return value of several `add_face...` methods
226pub struct AddFace {
227    /// Id of the created face
228    pub face_id: FaceId,
229    /// During the process of creating the face all new created halfedges
230    pub halfedge_ids: Vec<HalfedgeId>,
231    /// During the process of creating the face all new created vertices
232    pub vertex_ids: Vec<VertexId>,
233}
234
235#[cfg(test)]
236mod test {
237    use super::*;
238
239    fn add_face(mesh_graph: &mut MeshGraph) -> FaceId {
240        mesh_graph
241            .add_face_from_positions(
242                Vec3::new(0.0, 0.0, 0.0),
243                Vec3::new(1.0, 0.0, 0.0),
244                Vec3::new(0.0, 1.0, 0.0),
245            )
246            .face_id
247    }
248
249    fn add_face_to_edge(
250        mesh_graph: &mut MeshGraph,
251        face_id: FaceId,
252        pos: Vec3,
253        use_twin: bool,
254    ) -> Option<FaceId> {
255        let mut associated_he_id = mesh_graph.faces[face_id]
256            .halfedges(mesh_graph)
257            .nth(1)
258            .unwrap();
259
260        if use_twin {
261            associated_he_id = mesh_graph.halfedges[associated_he_id].twin.unwrap();
262        }
263
264        mesh_graph
265            .add_face_from_halfedge_and_position(associated_he_id, pos)
266            .map(|f| f.face_id)
267    }
268
269    fn fill_face(
270        mesh_graph: &mut MeshGraph,
271        face_id_1: FaceId,
272        face_id_2: FaceId,
273        use_twin: bool,
274    ) -> Option<FaceId> {
275        let mut he_id_1 = mesh_graph.faces[face_id_1]
276            .halfedges(mesh_graph)
277            .next()
278            .unwrap();
279
280        let mut he_id_2 = mesh_graph.faces[face_id_2]
281            .halfedges(mesh_graph)
282            .nth(1)
283            .unwrap();
284
285        if use_twin {
286            he_id_1 = mesh_graph.halfedges[he_id_1].twin.unwrap();
287            he_id_2 = mesh_graph.halfedges[he_id_2].twin.unwrap();
288        }
289
290        mesh_graph
291            .add_face_from_halfedges(he_id_1, he_id_2)
292            .map(|f| f.face_id)
293    }
294
295    macro_rules! init_fill_face {
296        ($f1:ident, $f2:ident, $f3:ident, $mg:ident) => {
297            let $f1 = add_face(&mut $mg);
298
299            let $f2 = add_face_to_edge(&mut $mg, $f1, Vec3::new(1.0, 1.0, 0.0), false);
300            let $f3 = add_face_to_edge(&mut $mg, $f2.unwrap(), Vec3::new(0.5, 0.5, 1.0), false);
301        };
302    }
303
304    macro_rules! log_faces_rerun {
305        ($mg:ident, $($face:expr),*) => {
306            #[cfg(feature = "rerun")]
307            {
308                $(
309                    $mg.log_face_rerun(&format!("{:?}", $face), $face);
310                )*
311            }
312        };
313    }
314
315    fn test_vertices(mesh_graph: &MeshGraph, face: FaceId) {
316        let mut vertices = mesh_graph.faces[face].vertices(mesh_graph);
317
318        let vertex = vertices.next();
319        assert!(vertex.is_some());
320        assert!(
321            mesh_graph.vertices[vertex.unwrap()]
322                .outgoing_halfedge
323                .is_some()
324        );
325
326        let vertex = vertices.next();
327        assert!(vertex.is_some());
328        assert!(
329            mesh_graph.vertices[vertex.unwrap()]
330                .outgoing_halfedge
331                .is_some()
332        );
333
334        let vertex = vertices.next();
335        assert!(vertex.is_some());
336        assert!(
337            mesh_graph.vertices[vertex.unwrap()]
338                .outgoing_halfedge
339                .is_some()
340        );
341
342        assert!(vertices.next().is_none());
343    }
344
345    fn test_halfedges(mesh_graph: &MeshGraph, face: FaceId) {
346        let mut halfedges = mesh_graph.faces[face].halfedges(mesh_graph);
347
348        assert!(halfedges.next().is_some());
349        assert!(halfedges.next().is_some());
350        assert!(halfedges.next().is_some());
351        assert!(halfedges.next().is_none());
352    }
353
354    #[test]
355    fn test_create_face() {
356        let mut mesh_graph = MeshGraph::new();
357        let face1 = add_face(&mut mesh_graph);
358
359        assert_eq!(mesh_graph.vertices.len(), 3);
360        assert_eq!(mesh_graph.positions.len(), 3);
361        assert_eq!(mesh_graph.halfedges.len(), 6);
362        assert_eq!(mesh_graph.faces.len(), 1);
363
364        test_vertices(&mesh_graph, face1);
365        test_halfedges(&mesh_graph, face1);
366
367        log_faces_rerun!(mesh_graph, face1);
368    }
369
370    #[test]
371    fn test_add_face_to_edge() {
372        let mut mesh_graph = MeshGraph::new();
373        let face1 = add_face(&mut mesh_graph);
374
375        let face2 = add_face_to_edge(&mut mesh_graph, face1, Vec3::new(1.0, 1.0, 0.0), false);
376
377        assert!(face2.is_some());
378        assert_eq!(mesh_graph.vertices.len(), 4);
379        assert_eq!(mesh_graph.positions.len(), 4);
380        assert_eq!(mesh_graph.halfedges.len(), 10);
381        assert_eq!(mesh_graph.faces.len(), 2);
382
383        test_vertices(&mesh_graph, face2.unwrap());
384        test_halfedges(&mesh_graph, face2.unwrap());
385
386        log_faces_rerun!(mesh_graph, face1, face2.unwrap());
387    }
388
389    #[test]
390    fn test_add_face_to_twin_edge() {
391        let mut mesh_graph = MeshGraph::new();
392        let face1 = add_face(&mut mesh_graph);
393
394        let face2 = add_face_to_edge(&mut mesh_graph, face1, Vec3::new(1.0, 1.0, 0.0), true);
395
396        assert!(face2.is_some());
397        assert_eq!(mesh_graph.vertices.len(), 4);
398        assert_eq!(mesh_graph.positions.len(), 4);
399        assert_eq!(mesh_graph.halfedges.len(), 10);
400        assert_eq!(mesh_graph.faces.len(), 2);
401
402        test_vertices(&mesh_graph, face2.unwrap());
403        test_halfedges(&mesh_graph, face2.unwrap());
404
405        log_faces_rerun!(mesh_graph, face1, face2.unwrap());
406    }
407
408    #[test]
409    fn test_fill_face() {
410        let mut mesh_graph = MeshGraph::new();
411        init_fill_face!(face1, face2, face3, mesh_graph);
412
413        let face4 = fill_face(&mut mesh_graph, face1, face3.unwrap(), false);
414
415        assert!(face4.is_some());
416        assert_eq!(mesh_graph.vertices.len(), 5);
417        assert_eq!(mesh_graph.positions.len(), 5);
418        assert_eq!(mesh_graph.halfedges.len(), 16);
419        assert_eq!(mesh_graph.faces.len(), 4);
420
421        test_vertices(&mesh_graph, face4.unwrap());
422        test_halfedges(&mesh_graph, face4.unwrap());
423
424        log_faces_rerun!(
425            mesh_graph,
426            face1,
427            face2.unwrap(),
428            face3.unwrap(),
429            face4.unwrap()
430        );
431    }
432
433    #[test]
434    fn test_fill_face_from_twin_edges() {
435        let mut mesh_graph = MeshGraph::new();
436        init_fill_face!(face1, face2, face3, mesh_graph);
437
438        let face4 = fill_face(&mut mesh_graph, face1, face3.unwrap(), true);
439
440        assert!(face4.is_some());
441        assert_eq!(mesh_graph.vertices.len(), 5);
442        assert_eq!(mesh_graph.positions.len(), 5);
443        assert_eq!(mesh_graph.halfedges.len(), 16);
444        assert_eq!(mesh_graph.faces.len(), 4);
445
446        test_vertices(&mesh_graph, face4.unwrap());
447        test_halfedges(&mesh_graph, face4.unwrap());
448
449        log_faces_rerun!(
450            mesh_graph,
451            face1,
452            face2.unwrap(),
453            face3.unwrap(),
454            face4.unwrap()
455        );
456    }
457}