tri_mesh/operations/
connectivity.rs1use crate::mesh::*;
4
5impl Mesh {
7 pub fn is_closed(&self) -> bool {
9 for halfedge_id in self.edge_iter() {
10 if self.is_edge_on_boundary(halfedge_id) {
11 return false;
12 }
13 }
14 true
15 }
16 pub fn connecting_edge(
23 &self,
24 vertex_id1: VertexID,
25 vertex_id2: VertexID,
26 ) -> Option<HalfEdgeID> {
27 for halfedge_id in self.vertex_halfedge_iter(vertex_id1) {
28 if self.walker_from_halfedge(halfedge_id).vertex_id().unwrap() == vertex_id2 {
29 return Some(halfedge_id);
30 }
31 }
32 None
33 }
34
35 pub fn is_vertex_on_boundary(&self, vertex_id: VertexID) -> bool {
37 for halfedge_id in self.vertex_halfedge_iter(vertex_id) {
38 let mut walker = self.walker_from_halfedge(halfedge_id);
39 if walker.face_id().is_none() || walker.as_twin().face_id().is_none() {
40 return true;
41 }
42 }
43 false
44 }
45
46 pub fn is_edge_on_boundary(&self, halfedge_id: HalfEdgeID) -> bool {
48 let mut walker = self.walker_from_halfedge(halfedge_id);
49 walker.face_id().is_none() || walker.as_twin().face_id().is_none()
50 }
51
52 pub fn edge_vertices(&self, halfedge_id: HalfEdgeID) -> (VertexID, VertexID) {
54 let mut walker = self.walker_from_halfedge(halfedge_id);
55 let v1 = walker.vertex_id().unwrap();
56 let v2 = walker.as_twin().vertex_id().unwrap();
57 (v1, v2)
58 }
59
60 pub fn ordered_edge_vertices(&self, halfedge_id: HalfEdgeID) -> (VertexID, VertexID) {
63 let mut walker = self.walker_from_halfedge(halfedge_id);
64 let v1 = walker.vertex_id().unwrap();
65 let v2 = walker.as_twin().vertex_id().unwrap();
66 if v1 < v2 {
67 (v1, v2)
68 } else {
69 (v2, v1)
70 }
71 }
72
73 pub fn face_vertices(&self, face_id: FaceID) -> (VertexID, VertexID, VertexID) {
75 let mut walker = self.walker_from_face(face_id);
76 let v1 = walker.vertex_id().unwrap();
77 walker.as_next();
78 let v2 = walker.vertex_id().unwrap();
79 walker.as_next();
80 let v3 = walker.vertex_id().unwrap();
81 (v1, v2, v3)
82 }
83
84 pub fn ordered_face_vertices(&self, face_id: FaceID) -> (VertexID, VertexID, VertexID) {
87 let mut walker = self.walker_from_face(face_id);
88 let v1 = walker.vertex_id().unwrap();
89 walker.as_next();
90 let v2 = walker.vertex_id().unwrap();
91 walker.as_next();
92 let v3 = walker.vertex_id().unwrap();
93 if v1 < v2 {
94 if v2 < v3 {
95 (v1, v2, v3)
96 } else {
97 if v1 < v3 {
98 (v1, v3, v2)
99 } else {
100 (v3, v1, v2)
101 }
102 }
103 } else {
104 if v1 < v3 {
105 (v2, v1, v3)
106 } else {
107 if v2 < v3 {
108 (v2, v3, v1)
109 } else {
110 (v3, v2, v1)
111 }
112 }
113 }
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use three_d_asset::TriMesh;
121 #[test]
122 fn test_is_closed_when_not_closed() {
123 let mesh = crate::test_utility::subdivided_triangle();
124 assert!(!mesh.is_closed());
125 }
126
127 #[test]
128 fn test_is_closed_when_closed() {
129 let mesh: Mesh = TriMesh::sphere(4).into();
130 assert!(mesh.is_closed());
131 }
132}