1use crate::mesh::*;
2use std::collections::HashMap;
3
4impl Mesh {
5 pub fn append(&mut self, other: &Self) {
9 let mut mapping: HashMap<VertexID, VertexID> = HashMap::new();
10 let mut get_or_create_vertex = |mesh: &mut Mesh, vertex_id| -> VertexID {
11 if let Some(vid) = mapping.get(&vertex_id) {
12 return *vid;
13 }
14 let p = other.vertex_position(vertex_id);
15 let vid = mesh.add_vertex(p.clone());
16 mapping.insert(vertex_id, vid);
17 vid
18 };
19
20 let mut face_mapping: HashMap<FaceID, FaceID> = HashMap::new();
21 for other_face_id in other.face_iter() {
22 let vertex_ids = other.face_vertices(other_face_id);
23
24 let vertex_id0 = get_or_create_vertex(self, vertex_ids.0);
25 let vertex_id1 = get_or_create_vertex(self, vertex_ids.1);
26 let vertex_id2 = get_or_create_vertex(self, vertex_ids.2);
27 let new_face_id = self
28 .connectivity_info
29 .create_face(vertex_id0, vertex_id1, vertex_id2);
30
31 for halfedge_id in other.face_halfedge_iter(other_face_id) {
32 if let Some(fid) = other.walker_from_halfedge(halfedge_id).as_twin().face_id() {
33 if let Some(self_face_id) = face_mapping.get(&fid) {
34 for halfedge_id1 in self.face_halfedge_iter(*self_face_id) {
35 let mut walker1 = self.walker_from_halfedge(halfedge_id1);
36 let source_vertex_id = walker1.vertex_id().unwrap();
37 let sink_vertex_id = walker1.as_next().vertex_id().unwrap();
38
39 for halfedge_id2 in self.face_halfedge_iter(new_face_id) {
40 let mut walker2 = self.walker_from_halfedge(halfedge_id2);
41 if sink_vertex_id == walker2.vertex_id().unwrap()
42 && source_vertex_id == walker2.as_next().vertex_id().unwrap()
43 {
44 self.connectivity_info.set_halfedge_twin(
45 walker1.halfedge_id().unwrap(),
46 walker2.halfedge_id().unwrap(),
47 );
48 }
49 }
50 }
51 }
52 }
53 }
54
55 face_mapping.insert(other_face_id, new_face_id);
56 }
57
58 self.create_boundary_edges();
59 }
60
61 fn create_boundary_edges(&mut self) {
62 let mut walker = self.walker();
63 for halfedge_id in self.halfedge_iter() {
64 walker.as_halfedge_walker(halfedge_id);
65 if walker.twin_id().is_none() {
66 let boundary_halfedge_id = self.connectivity_info.new_halfedge(
67 walker.as_previous().vertex_id(),
68 None,
69 None,
70 );
71 self.connectivity_info
72 .set_halfedge_twin(halfedge_id, boundary_halfedge_id);
73 }
74 }
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use three_d_asset::TriMesh;
82
83 #[test]
84 fn test_sphere_sphere_append() {
85 let mut mesh1: Mesh = TriMesh::sphere(4).into();
86 let mut mesh2: Mesh = TriMesh::sphere(3).into();
87 mesh2.translate(vec3(0.5, 0.5, 0.5));
88
89 let prev_no_vertices = mesh1.no_vertices();
90 let prev_no_halfedges = mesh1.no_halfedges();
91 let prev_no_faces = mesh1.no_faces();
92
93 mesh1.append(&mesh2);
94
95 mesh1.is_valid().unwrap();
96 mesh2.is_valid().unwrap();
97
98 assert_eq!(mesh1.no_vertices(), mesh2.no_vertices() + prev_no_vertices);
99 assert_eq!(
100 mesh1.no_halfedges(),
101 mesh2.no_halfedges() + prev_no_halfedges
102 );
103 assert_eq!(mesh1.no_faces(), mesh2.no_faces() + prev_no_faces);
104
105 for pos in mesh2.vertex_iter().map(|v| mesh2.vertex_position(v)) {
106 assert!(mesh1
107 .vertex_iter()
108 .find(|v| mesh1.vertex_position(*v) == pos)
109 .is_some());
110 }
111 }
112}