tri_mesh/mesh/
append.rs

1use crate::mesh::*;
2use std::collections::HashMap;
3
4impl Mesh {
5    /// Appends the `other` mesh to this mesh without creating a connection between them.
6    /// Use `merge_with` if merging of overlapping primitives is desired, thereby creating a connection.
7    /// All the primitives of the `other` mesh are copied to the current mesh and the `other` mesh is therefore not changed.
8    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}