Skip to main content

mesh_graph/ops/cleanup/
mod.rs

1mod edge_boundary;
2mod vertex_neighborhood;
3
4use tracing::instrument;
5
6use crate::{FaceId, HalfedgeId, MeshGraph, VertexId, error_none};
7
8impl MeshGraph {
9    /// Test if two faces have at least one halfedge in common.
10    #[inline]
11    #[instrument(skip(self))]
12    pub fn faces_share_edge(&self, face_id1: FaceId, face_id2: FaceId) -> bool {
13        self.faces_share_edge_inner(face_id1, face_id2).is_some()
14    }
15
16    fn faces_share_edge_inner(&self, face_id1: FaceId, face_id2: FaceId) -> Option<()> {
17        let face1 = self
18            .faces
19            .get(face_id1)
20            .or_else(error_none!("Face 1 not found"))?;
21        let face2 = self
22            .faces
23            .get(face_id2)
24            .or_else(error_none!("Face 2 not found"))?;
25
26        for edge_id1 in face1.halfedges(self) {
27            let edge1 = self
28                .halfedges
29                .get(edge_id1)
30                .or_else(error_none!("Halfedge 1 not found"))?;
31
32            let start_pos1 = self
33                .positions
34                .get(edge1.start_vertex(self)?)
35                .or_else(error_none!("Position of start vertex 1 not found"))?;
36            let end_pos1 = self
37                .positions
38                .get(edge1.end_vertex)
39                .or_else(error_none!("Position of end vertex 1 not found"))?;
40
41            for edge_id2 in face2.halfedges(self) {
42                let edge2 = self
43                    .halfedges
44                    .get(edge_id2)
45                    .or_else(error_none!("Halfedge 2 not found"))?;
46
47                let start_pos2 = self
48                    .positions
49                    .get(edge2.start_vertex(self)?)
50                    .or_else(error_none!("Position of start vertex 2 not found"))?;
51                let end_pos2 = self
52                    .positions
53                    .get(edge2.end_vertex)
54                    .or_else(error_none!("Position of end vertex 2 not found"))?;
55
56                if start_pos1 == start_pos2 && end_pos1 == end_pos2 {
57                    return Some(());
58                }
59            }
60        }
61
62        None
63    }
64
65    /// Test if two faces share all vertices.
66    #[inline]
67    #[instrument(skip(self))]
68    pub fn faces_share_all_vertices(&self, face_id1: FaceId, face_id2: FaceId) -> bool {
69        self.faces_share_all_vertices_inner(face_id1, face_id2)
70            .is_some()
71    }
72
73    fn faces_share_all_vertices_inner(&self, face_id1: FaceId, face_id2: FaceId) -> Option<()> {
74        let face1 = self
75            .faces
76            .get(face_id1)
77            .or_else(error_none!("Face 1 not found"))?;
78        let face2 = self
79            .faces
80            .get(face_id2)
81            .or_else(error_none!("Face 2 not found"))?;
82
83        'outer: for vertex_id1 in face1.vertices(self) {
84            let pos1 = self
85                .positions
86                .get(vertex_id1)
87                .or_else(error_none!("Position of vertex 1 not found"))?;
88
89            for vertex_id2 in face2.vertices(self) {
90                let pos2 = self
91                    .positions
92                    .get(vertex_id2)
93                    .or_else(error_none!("Position of vertex 2 not found"))?;
94
95                if pos1 == pos2 {
96                    continue 'outer;
97                }
98            }
99
100            return None;
101        }
102
103        Some(())
104    }
105
106    /// Test if two halfedges share all vertices.
107    #[inline]
108    #[instrument(skip(self))]
109    pub fn halfedges_share_all_vertices(
110        &self,
111        halfedge_id1: HalfedgeId,
112        halfedge_id2: HalfedgeId,
113    ) -> bool {
114        self.halfedges_share_all_vertices_inner(halfedge_id1, halfedge_id2)
115            .is_some()
116    }
117
118    fn halfedges_share_all_vertices_inner(
119        &self,
120        halfedge_id1: HalfedgeId,
121        halfedge_id2: HalfedgeId,
122    ) -> Option<()> {
123        let he1 = self
124            .halfedges
125            .get(halfedge_id1)
126            .or_else(error_none!("Halfedge 1 not found"))?;
127        let he2 = self
128            .halfedges
129            .get(halfedge_id2)
130            .or_else(error_none!("Halfedge 2 not found"))?;
131
132        let start_id1 = he1.start_vertex(self)?;
133
134        let start_id2 = he2.start_vertex(self)?;
135
136        (start_id1 == start_id2 && he1.end_vertex == he2.end_vertex).then_some(())
137    }
138
139    /// Test if two vertices have the exact same position.
140    #[inline]
141    #[instrument(skip(self))]
142    pub fn vertices_share_position(&self, vertex_id1: VertexId, vertex_id2: VertexId) -> bool {
143        self.vertices_share_position_inner(vertex_id1, vertex_id2)
144            .is_some()
145    }
146
147    fn vertices_share_position_inner(
148        &self,
149        vertex_id1: VertexId,
150        vertex_id2: VertexId,
151    ) -> Option<()> {
152        (self
153            .positions
154            .get(vertex_id1)
155            .or_else(error_none!("Position of vertex 1 not found"))?
156            == self
157                .positions
158                .get(vertex_id2)
159                .or_else(error_none!("Position of vertex 2 not found"))?)
160        .then_some(())
161    }
162}