1use hashbrown::HashSet;
2use tracing::instrument;
3
4use crate::{FaceId, HalfedgeId, MeshGraph, VertexId, error_none, utils::unwrap_or_return};
5
6impl MeshGraph {
7 #[instrument(skip(self))]
14 pub fn delete_face(&mut self, face_id: FaceId) -> (Vec<VertexId>, Vec<HalfedgeId>) {
15 let face = unwrap_or_return!(self.faces.get(face_id), "Face not found", (vec![], vec![]));
16
17 let vertices = face.vertices(self).collect::<Vec<_>>();
18 let halfedges = face.halfedges(self).collect::<Vec<_>>();
19
20 let mut deleted_halfedges = HashSet::with_capacity(4);
21
22 for he_id in halfedges {
23 let he = unwrap_or_return!(
24 self.halfedges.get(he_id),
25 "Halfedge not found",
26 (vec![], vec![])
27 );
28 let twin_id = unwrap_or_return!(he.twin, "Twin not found", (vec![], vec![]));
29
30 if unwrap_or_return!(
31 self.halfedges.get(twin_id),
32 "Twin halfedge not found",
33 (vec![], vec![])
34 )
35 .is_boundary()
36 {
37 deleted_halfedges.insert(he_id);
38 deleted_halfedges.insert(twin_id);
39 } else {
40 self.halfedges[he_id].face = None;
42 self.halfedges[he_id].next = None;
43 }
44 }
45
46 #[cfg(feature = "rerun")]
47 self.log_hes_rerun(
48 "deleted_by_face_deletion",
49 &deleted_halfedges.iter().copied().collect::<Vec<_>>(),
50 );
51
52 let mut deleted_vertices = Vec::with_capacity(3);
53
54 for &vertex_id in &vertices {
55 let mut all_deleted = true;
56 for he_id in unwrap_or_return!(
57 self.vertices.get(vertex_id),
58 "Vertex not found",
59 (vec![], vec![])
60 )
61 .outgoing_halfedges(self)
62 {
63 if !deleted_halfedges.contains(&he_id) {
64 all_deleted = false;
65 break;
66 }
67 }
68
69 if all_deleted {
70 self.positions.remove(vertex_id);
71 if let Some(normals) = &mut self.vertex_normals {
72 normals.remove(vertex_id);
73 }
74 self.vertices.remove(vertex_id);
75
76 deleted_vertices.push(vertex_id);
77 }
78 }
79
80 for &he_id in &deleted_halfedges {
82 let start_v_id = unwrap_or_return!(
84 self.halfedges[he_id].start_vertex(self),
85 "Start vertex not found",
86 (vec![], vec![])
87 );
88 if let Some(v) = self.vertices.get(start_v_id) {
89 self.vertices[start_v_id].outgoing_halfedge = v
90 .outgoing_halfedges(self)
91 .into_iter()
92 .find(|id| !deleted_halfedges.contains(id))
93 .or_else(error_none!("No new outgoing halfedge found"));
94 }
95 }
96
97 for &he_id in &deleted_halfedges {
98 self.halfedges.remove(he_id);
99 }
100
101 self.bvh.remove(self.faces[face_id].index);
103 self.faces.remove(face_id);
104
105 (deleted_vertices, Vec::from_iter(deleted_halfedges))
106 }
107}