baby_shark/mesh/corner_table/
edit.rs

1use super::{traversal::collect_corners_around_vertex, *};
2use crate::helpers::aliases::Vec3;
3
4// Topology editing operations
5impl<S: RealNumber> CornerTable<S> {
6    pub fn collapse_edge(&mut self, edge: EdgeId, at: &Vec3<S>) {
7        if self[edge.corner()].is_deleted() {
8            return;
9        }
10
11        let mut walker = CornerWalker::from_corner(self, edge.corner());
12
13        // Collect corners of faces that is going to be removed,
14        // vertices of collapsed edge and corners that going to be opposite after collapse
15        let c24_idx = walker.corner_id();
16        let v7_idx = walker.corner().vertex();
17
18        let c25_idx = walker.move_to_next().corner_id();
19        let v8_idx = walker.corner().vertex();
20        let c21_idx = walker.corner().opposite_corner();
21
22        let c26_idx = walker.move_to_next().corner_id();
23        let c28_idx = walker.corner().opposite_corner();
24        let v9_idx = walker.corner().vertex();
25
26        walker.move_to_next();
27
28        let mut c6_idx = None;
29        let mut c13_idx = None;
30
31        let is_boundary_edge = walker.corner().opposite_corner().is_none();
32
33        if !is_boundary_edge {
34            let c9_idx = walker.move_to_opposite().corner_id();
35            let v3_idx = walker.corner().vertex();
36
37            let c10_idx = walker.move_to_next().corner_id();
38            c6_idx = walker.corner().opposite_corner();
39
40            let c11_idx = walker.move_to_next().corner_id();
41            c13_idx = walker.corner().opposite_corner();
42
43            // Update vertex for corners around removed one
44            for corner_index in collect_corners_around_vertex(self, v9_idx) {
45                self[corner_index].set_vertex(v8_idx);
46            }
47
48            // Make sure vertices are not referencing deleted corners
49            self.set_corner_for_wing_vertex(v3_idx, c13_idx, c6_idx);
50
51            // Delete face
52            self[c9_idx].set_deleted(true);
53            self[c10_idx].set_deleted(true);
54            self[c11_idx].set_deleted(true);
55        } else {
56            // Update vertex for corners around removed one
57            for corner_id in collect_corners_around_vertex(self, v9_idx) {
58                self[corner_id].set_vertex(v8_idx);
59            }
60        }
61
62        // Make sure vertices are not referencing deleted corners
63        self.set_corner_for_wing_vertex(v7_idx, c28_idx, c21_idx);
64
65        // Delete face
66        self[c24_idx].set_deleted(true);
67        self[c25_idx].set_deleted(true);
68        self[c26_idx].set_deleted(true);
69
70        // Remove vertex on edge end
71        self[v9_idx].set_deleted(true);
72
73        // Shift vertex on other side of edge
74        self[v8_idx].set_position(*at);
75        self.set_corner_for_wing_vertex(v8_idx, c6_idx.or(c21_idx), c28_idx.or(c13_idx));
76
77        // Setup new opposites
78        self.make_corners_opposite(c28_idx, c21_idx);
79        self.make_corners_opposite(c6_idx, c13_idx);
80    }
81
82    pub fn flip_edge(&mut self, edge: EdgeId) {
83        if self[edge.corner()].is_deleted() {
84            return;
85        }
86
87        let mut walker = CornerWalker::from_corner(self, edge.corner());
88
89        // Face 1
90        let c1_idx = walker.corner_id();
91        let v1_idx = walker.corner().vertex();
92
93        let c2_idx = walker.move_to_next().corner_id();
94        let c2 = walker.corner();
95        let v2_idx = c2.vertex();
96        let c2_opp = c2.opposite_corner();
97
98        let c0_idx = walker.move_to_next().corner_id();
99        let c0 = walker.corner();
100        let v0_idx = c0.vertex();
101        let c0_opp = c0.opposite_corner();
102
103        // Face 2
104        let c4_idx = walker.move_to_next().move_to_opposite().corner_id();
105        let v3_idx = walker.corner().vertex();
106
107        let c5_idx = walker.move_to_next().corner_id();
108        let c5_opp = walker.corner().opposite_corner();
109
110        let c3_idx = walker.move_to_next().corner_id();
111        let c3_opp = walker.corner().opposite_corner();
112
113        // Update corners
114        self[c0_idx].set_vertex(v1_idx);
115        self.make_corners_opposite(Some(c0_idx), c5_opp);
116        self[c1_idx].set_vertex(v2_idx);
117        self.make_corners_opposite(Some(c1_idx), Some(c4_idx));
118        self[c2_idx].set_vertex(v3_idx);
119        self.make_corners_opposite(Some(c2_idx), c0_opp);
120
121        self[c3_idx].set_vertex(v3_idx);
122        self.make_corners_opposite(Some(c3_idx), c2_opp);
123        self[c4_idx].set_vertex(v0_idx);
124        self[c5_idx].set_vertex(v1_idx);
125        self.make_corners_opposite(Some(c5_idx), c3_opp);
126
127        // Make sure vertices are referencing correct corners
128        self[v0_idx].set_corner(c4_idx);
129        self[v1_idx].set_corner(c0_idx);
130        self[v2_idx].set_corner(c1_idx);
131        self[v3_idx].set_corner(c2_idx);
132    }
133
134    pub fn split_edge(&mut self, edge: EdgeId, at: &Vec3<S>) {
135        if self[edge.corner()].is_deleted() {
136            return;
137        }
138
139        let corner_id = edge.corner();
140        let corner = &self[corner_id];
141
142        match corner.opposite_corner() {
143            Some(_) => self.split_inner_edge(corner_id, at),
144            None => self.split_boundary_edge(corner_id, at),
145        }
146    }
147
148    pub fn split_face(&mut self, face: FaceId, point: Vec3<S>) {
149        if self[face.corner()].is_deleted() {
150            return;
151        }
152
153        let mut walker = CornerWalker::from_corner(self, face.corner());
154
155        // Splitted face
156        let c0_idx = walker.corner_id();
157        let v0_idx = walker.corner().vertex();
158        let c0_opp = walker.corner().opposite_corner();
159
160        let c1_idx = walker.move_to_next().corner_id();
161        let v1_idx = walker.corner().vertex();
162        let c1_opp = walker.corner().opposite_corner();
163
164        let c2_idx = walker.move_to_next().corner_id();
165        let v2_idx = walker.corner().vertex();
166
167        // Create new vertex at split point
168        let new_vertex_id = self.create_vertex(Some(c2_idx), point);
169
170        // New faces required for split
171        let (c3_idx, c4_idx, c5_idx) =
172            self.create_isolated_face_from_vertices(v1_idx, v2_idx, new_vertex_id);
173        let (c6_idx, c7_idx, c8_idx) =
174            self.create_isolated_face_from_vertices(v2_idx, v0_idx, new_vertex_id);
175
176        // Corners relationship between internal faces
177        self.set_opposite_relationship(c0_idx, c4_idx);
178        self.set_opposite_relationship(c3_idx, c7_idx);
179        self.set_opposite_relationship(c6_idx, c1_idx);
180
181        // Corners relationship with external faces
182        self.make_corners_opposite(Some(c8_idx), c1_opp);
183        self.make_corners_opposite(Some(c5_idx), c0_opp);
184
185        self[c2_idx].set_vertex(new_vertex_id);
186        self[v2_idx].set_corner(c4_idx);
187    }
188}
189
190// Helper functions
191impl<S: RealNumber> CornerTable<S> {
192    /// Splits inner edge opposite to corner at given position
193    fn split_inner_edge(&mut self, corner_id: CornerId, at: &Vec3<S>) {
194        // Existing corners and vertices that needs to be updated
195        let mut walker = CornerWalker::from_corner(self, corner_id);
196        let c0_idx = walker.previous_corner_id();
197        let v1_idx = walker.corner().vertex();
198        let c2_idx = walker.move_to_next().corner_id();
199        let v2_idx = walker.corner().vertex();
200        let c3_idx = walker.swing_right().corner_id();
201        let v3_idx = walker.move_to_next().corner().vertex();
202        let c5_idx = walker.move_to_next().corner_id();
203
204        // Shift existing vertex
205        let old_vertex_position = *walker.move_to_next().vertex().position();
206        self[v2_idx].set_position(*at);
207        self[v2_idx].set_corner(c2_idx);
208
209        // New vertex, instead of shifted
210        let new_vertex_id = self.create_vertex(None, old_vertex_position);
211
212        // Create new faces
213        let (c6_idx, c7_idx, c8_idx) =
214            self.create_isolated_face_from_vertices(v1_idx, new_vertex_id, v2_idx);
215        let (c9_idx, c10_idx, c11_idx) =
216            self.create_isolated_face_from_vertices(new_vertex_id, v3_idx, v2_idx);
217        self[new_vertex_id].set_corner(c7_idx);
218
219        // Update vertex index of existing corners
220        for corner_index in collect_corners_around_vertex(self, v2_idx) {
221            if corner_index != c3_idx && corner_index != c2_idx {
222                self[corner_index].set_vertex(new_vertex_id);
223            }
224        }
225
226        // Update opposites
227        if let Some(c0_opposite_idx) = self[c0_idx].opposite_corner() {
228            self.set_opposite_relationship(c0_opposite_idx, c8_idx);
229        }
230
231        if let Some(c5_opposite_idx) = self[c5_idx].opposite_corner() {
232            self.set_opposite_relationship(c5_opposite_idx, c11_idx);
233        }
234
235        self.set_opposite_relationship(c0_idx, c7_idx);
236        self.set_opposite_relationship(c5_idx, c9_idx);
237        self.set_opposite_relationship(c6_idx, c10_idx);
238    }
239
240    /// Splits boundary edge opposite to corner at given position
241    fn split_boundary_edge(&mut self, corner_id: CornerId, at: &Vec3<S>) {
242        // Existing corners and vertices that needs to be updated
243        let mut walker = CornerWalker::from_corner(self, corner_id);
244        let c0_idx = walker.previous_corner_id();
245        let v1_idx = walker.corner().vertex();
246        let c2_idx = walker.move_to_next().corner_id();
247        let v2_idx = walker.corner().vertex();
248
249        // Shift existing vertex
250        let old_vertex_position = *walker.vertex().position();
251        self[v2_idx].set_position(*at);
252        self[v2_idx].set_corner(c2_idx);
253
254        // New vertex, instead of shifted
255        let new_vertex_id = self.create_vertex(None, old_vertex_position);
256
257        // Create new face
258        let (c3_idx, c4_idx, c5_idx) =
259            self.create_isolated_face_from_vertices(v1_idx, new_vertex_id, v2_idx);
260        self[new_vertex_id].set_corner(c4_idx);
261
262        // Update vertex index of existing corners
263        for corner_id in collect_corners_around_vertex(self, v2_idx) {
264            if corner_id != c3_idx && corner_id != c2_idx {
265                self[corner_id].set_vertex(new_vertex_id);
266            }
267        }
268
269        // Update opposites
270        if let Some(c0_opposite) = self[c0_idx].opposite_corner() {
271            self.set_opposite_relationship(c0_opposite, c5_idx);
272        }
273
274        self.set_opposite_relationship(c0_idx, c4_idx);
275    }
276
277    /// Makes give corners opposite to each other
278    #[inline]
279    fn set_opposite_relationship(&mut self, corner1_id: CornerId, corner2_id: CornerId) {
280        self[corner1_id].set_opposite_corner(Some(corner2_id));
281        self[corner2_id].set_opposite_corner(Some(corner1_id));
282    }
283
284    /// Set corner for wing vertex of collapsed edge
285    #[inline]
286    fn set_corner_for_wing_vertex(
287        &mut self,
288        vertex_id: VertexId,
289        opposite_corner_left: Option<CornerId>,
290        opposite_corner_right: Option<CornerId>,
291    ) {
292        if let Some(corner) = opposite_corner_left {
293            self[vertex_id].set_corner(corner.previous());
294        } else if let Some(corner) = opposite_corner_right {
295            self[vertex_id].set_corner(corner.next());
296        }
297    }
298
299    /// Make corners opposite to each other
300    #[inline]
301    fn make_corners_opposite(&mut self, c1: Option<CornerId>, c2: Option<CornerId>) {
302        if let Some(c1) = c1 {
303            debug_assert!(!self[c1].is_deleted());
304            self[c1].set_opposite_corner(c2);
305        }
306
307        if let Some(c2) = c2 {
308            debug_assert!(!self[c2].is_deleted());
309            self[c2].set_opposite_corner(c1);
310        }
311    }
312
313    fn create_isolated_face_from_vertices(
314        &mut self,
315        v1: VertexId,
316        v2: VertexId,
317        v3: VertexId,
318    ) -> (CornerId, CornerId, CornerId) {
319        let (c1, _) = self.create_corner(v1);
320        let (c2, _) = self.create_corner(v2);
321        let (c3, _) = self.create_corner(v3);
322        (c1, c2, c3)
323    }
324}
325
326#[cfg(test)]
327mod tests {
328    use super::*;
329    use crate::{
330        helpers::aliases::Vec3f,
331        mesh::corner_table::test_helpers::*,
332    };
333
334    #[test]
335    fn split_inner_edge1() {
336        let mut mesh = create_unit_square_mesh();
337
338        let expected_vertices = vec![
339            Vertex::new(CornerId::new(5), Vec3f::new(0.0, 1.0, 0.0)), // 0
340            Vertex::new(CornerId::new(1), Vec3f::new(0.0, 0.0, 0.0)), // 1
341            Vertex::new(CornerId::new(2), Vec3f::new(0.5, 0.5, 0.0)), // 2
342            Vertex::new(CornerId::new(4), Vec3f::new(1.0, 1.0, 0.0)), // 3
343            Vertex::new(CornerId::new(7), Vec3f::new(1.0, 0.0, 0.0)), // 4
344        ];
345
346        let expected_corners = vec![
347            // next, opposite, vertex, index, flags
348            Corner::new(Some(CornerId::new(7)), VertexId::new(0)), // 0
349            Corner::new(Some(CornerId::new(4)), VertexId::new(1)), // 1
350            Corner::new(None, VertexId::new(2)),                   // 2
351            Corner::new(None, VertexId::new(2)),                   // 3
352            Corner::new(Some(CornerId::new(1)), VertexId::new(3)), // 4
353            Corner::new(Some(CornerId::new(9)), VertexId::new(0)), // 5
354            Corner::new(Some(CornerId::new(10)), VertexId::new(1)), // 6
355            Corner::new(Some(CornerId::new(0)), VertexId::new(4)), // 7
356            Corner::new(None, VertexId::new(2)),                   // 8
357            Corner::new(Some(CornerId::new(5)), VertexId::new(4)), // 9
358            Corner::new(Some(CornerId::new(6)), VertexId::new(3)), // 10
359            Corner::new(None, VertexId::new(2)),                   // 11
360        ];
361
362        mesh.split_edge(EdgeId::new(CornerId::new(1)), &Vec3f::new(0.5, 0.5, 0.0));
363
364        assert_mesh_eq(&mesh, &expected_corners, &expected_vertices);
365    }
366
367    #[test]
368    fn split_inner_edge2() {
369        let mut mesh = create_unit_cross_square_mesh();
370
371        let expected_vertices = vec![
372            Vertex::new(CornerId::new(10), Vec3f::new(0.0, 1.0, 0.0)), // 0
373            Vertex::new(CornerId::new(3), Vec3f::new(0.0, 0.0, 0.0)),  // 1
374            Vertex::new(CornerId::new(6), Vec3f::new(1.0, 0.0, 0.0)),  // 2
375            Vertex::new(CornerId::new(7), Vec3f::new(0.75, 0.75, 0.0)), // 3
376            Vertex::new(CornerId::new(11), Vec3f::new(0.5, 0.5, 0.0)), // 4
377            Vertex::new(CornerId::new(13), Vec3f::new(1.0, 1.0, 0.0)), // 5
378        ];
379
380        let expected_corners = vec![
381            // opposite, vertex, flags
382            Corner::new(Some(CornerId::new(4)), VertexId::new(0)), // 0
383            Corner::new(Some(CornerId::new(9)), VertexId::new(1)), // 1
384            Corner::new(None, VertexId::new(4)),                   // 2
385            Corner::new(Some(CornerId::new(7)), VertexId::new(1)), // 3
386            Corner::new(Some(CornerId::new(0)), VertexId::new(2)), // 4
387            Corner::new(None, VertexId::new(4)),                   // 5
388            Corner::new(Some(CornerId::new(10)), VertexId::new(2)), // 6
389            Corner::new(Some(CornerId::new(3)), VertexId::new(3)), // 7
390            Corner::new(Some(CornerId::new(13)), VertexId::new(4)), // 8
391            Corner::new(Some(CornerId::new(1)), VertexId::new(3)), // 9
392            Corner::new(Some(CornerId::new(6)), VertexId::new(0)), // 10
393            Corner::new(Some(CornerId::new(15)), VertexId::new(4)), // 11
394            Corner::new(Some(CornerId::new(16)), VertexId::new(2)), // 12
395            Corner::new(Some(CornerId::new(8)), VertexId::new(5)), // 13
396            Corner::new(None, VertexId::new(3)),                   // 14
397            Corner::new(Some(CornerId::new(11)), VertexId::new(5)), // 15
398            Corner::new(Some(CornerId::new(12)), VertexId::new(0)), // 16
399            Corner::new(None, VertexId::new(3)),                   // 17
400        ];
401
402        mesh.split_edge(EdgeId::new(CornerId::new(6)), &Vec3f::new(0.75, 0.75, 0.0));
403
404        assert_mesh_eq(&mesh, &expected_corners, &expected_vertices);
405    }
406
407    #[test]
408    fn split_boundary_edge() {
409        let mut mesh = create_single_face_mesh();
410
411        let expected_vertices = vec![
412            Vertex::new(CornerId::new(0), Vec3f::new(0.0, 1.0, 0.0)), // 0
413            Vertex::new(CornerId::new(1), Vec3f::new(0.0, 0.0, 0.0)), // 1
414            Vertex::new(CornerId::new(2), Vec3f::new(0.5, 0.5, 0.0)), // 2
415            Vertex::new(CornerId::new(4), Vec3f::new(1.0, 0.0, 0.0)), // 3
416        ];
417
418        let expected_corners = vec![
419            // opposite, vertex, flags
420            Corner::new(Some(CornerId::new(4)), VertexId::new(0)), // 0
421            Corner::new(None, VertexId::new(1)),                   // 1
422            Corner::new(None, VertexId::new(2)),                   // 2
423            Corner::new(None, VertexId::new(1)),                   // 3
424            Corner::new(Some(CornerId::new(0)), VertexId::new(3)), // 4
425            Corner::new(None, VertexId::new(2)),                   // 5
426        ];
427
428        mesh.split_edge(EdgeId::new(CornerId::new(1)), &Vec3f::new(0.5, 0.5, 0.0));
429
430        assert_mesh_eq(&mesh, &expected_corners, &expected_vertices);
431    }
432
433    #[test]
434    fn collapse_edge() {
435        let mut mesh = create_collapse_edge_sample_mesh1();
436
437        let expected_vertices = vec![
438            Vertex::new(CornerId::new(28), Vec3f::new(0.0, 1.0, 0.0)), // 0
439            Vertex::new(CornerId::new(3), Vec3f::new(0.0, 0.5, 0.0)),  // 1
440            Vertex::new(CornerId::new(6), Vec3f::new(0.0, 0.0, 0.0)),  // 2
441            Vertex::new(CornerId::new(12), Vec3f::new(0.5, 0.0, 0.0)), // 3
442            Vertex::new(CornerId::new(15), Vec3f::new(1.0, 0.0, 0.0)), // 4
443            Vertex::new(CornerId::new(18), Vec3f::new(1.0, 0.5, 0.0)), // 5
444            Vertex::new(CornerId::new(21), Vec3f::new(1.0, 1.0, 0.0)), // 6
445            Vertex::new(CornerId::new(27), Vec3f::new(0.5, 1.0, 0.0)), // 7
446            Vertex::new(CornerId::new(29), Vec3f::new(0.25, 0.5, 0.0)), // 8
447            Vertex::new(CornerId::new(23), Vec3f::new(0.5, 0.5, 0.0)), // 9
448        ];
449
450        let expected_corners = vec![
451            // opposite, vertex, flags
452            Corner::new(Some(CornerId::new(4)), VertexId::new(0)), // 0
453            Corner::new(Some(CornerId::new(27)), VertexId::new(1)), // 1
454            Corner::new(None, VertexId::new(9)),                   // 2
455            Corner::new(Some(CornerId::new(7)), VertexId::new(1)), // 3
456            Corner::new(Some(CornerId::new(0)), VertexId::new(2)), // 4
457            Corner::new(None, VertexId::new(9)),                   // 5
458            Corner::new(Some(CornerId::new(13)), VertexId::new(2)), // 6
459            Corner::new(Some(CornerId::new(3)), VertexId::new(3)), // 7
460            Corner::new(None, VertexId::new(9)),                   // 8
461            Corner::new(Some(CornerId::new(24)), VertexId::new(3)), // 9
462            Corner::new(Some(CornerId::new(6)), VertexId::new(9)), // 10
463            Corner::new(Some(CornerId::new(13)), VertexId::new(9)), // 11
464            Corner::new(Some(CornerId::new(16)), VertexId::new(3)), // 12
465            Corner::new(Some(CornerId::new(6)), VertexId::new(4)), // 13
466            Corner::new(None, VertexId::new(9)),                   // 14
467            Corner::new(Some(CornerId::new(19)), VertexId::new(4)), // 15
468            Corner::new(Some(CornerId::new(12)), VertexId::new(5)), // 16
469            Corner::new(None, VertexId::new(9)),                   // 17
470            Corner::new(Some(CornerId::new(22)), VertexId::new(5)), // 18
471            Corner::new(Some(CornerId::new(15)), VertexId::new(6)), // 19
472            Corner::new(None, VertexId::new(9)),                   // 20
473            Corner::new(Some(CornerId::new(28)), VertexId::new(6)), // 21
474            Corner::new(Some(CornerId::new(18)), VertexId::new(7)), // 22
475            Corner::new(None, VertexId::new(9)),                   // 23
476            Corner::new(Some(CornerId::new(9)), VertexId::new(7)), // 24
477            Corner::new(Some(CornerId::new(21)), VertexId::new(9)), // 25
478            Corner::new(Some(CornerId::new(28)), VertexId::new(9)), // 26
479            Corner::new(Some(CornerId::new(1)), VertexId::new(7)), // 27
480            Corner::new(Some(CornerId::new(21)), VertexId::new(0)), // 28
481            Corner::new(None, VertexId::new(9)),                   // 29
482        ];
483
484        mesh.collapse_edge(EdgeId::new(CornerId::new(9)), &Vec3f::new(0.5, 0.5, 0.0));
485
486        assert_mesh_eq(&mesh, &expected_corners, &expected_vertices);
487    }
488
489    #[test]
490    fn collapse_edge_with_one_vertex_on_boundary() {
491        let mut mesh = create_collapse_edge_sample_mesh2();
492
493        let expected_vertices = vec![
494            Vertex::new(CornerId::new(0), Vec3f::new(0.5, 0.0, 0.0)), // 0
495            Vertex::new(CornerId::new(3), Vec3f::new(1.0, 0.0, 0.0)), // 1
496            Vertex::new(CornerId::new(6), Vec3f::new(1.0, 0.5, 0.0)), // 2
497            Vertex::new(CornerId::new(9), Vec3f::new(1.0, 1.0, 0.0)), // 3
498            Vertex::new(CornerId::new(10), Vec3f::new(0.5, 1.0, 0.0)), // 4
499            Vertex::new(CornerId::new(11), Vec3f::new(0.5, 0.5, 0.0)), // 5
500            Vertex::new(CornerId::new(17), Vec3f::new(0.75, 0.5, 0.0)), // 6
501        ];
502
503        let expected_corners = vec![
504            // opposite, vertex, flags
505            Corner::new(Some(CornerId::new(4)), VertexId::new(0)), // 0
506            Corner::new(None, VertexId::new(1)),                   // 1
507            Corner::new(None, VertexId::new(5)),                   // 2
508            Corner::new(Some(CornerId::new(7)), VertexId::new(1)), // 3
509            Corner::new(Some(CornerId::new(0)), VertexId::new(2)), // 4
510            Corner::new(None, VertexId::new(5)),                   // 5
511            Corner::new(Some(CornerId::new(10)), VertexId::new(2)), // 6
512            Corner::new(Some(CornerId::new(3)), VertexId::new(3)), // 7
513            Corner::new(None, VertexId::new(5)),                   // 8
514            Corner::new(None, VertexId::new(3)),                   // 9
515            Corner::new(Some(CornerId::new(6)), VertexId::new(4)), // 10
516            Corner::new(None, VertexId::new(5)),                   // 11
517            Corner::new(Some(CornerId::new(16)), VertexId::new(4)), // 12
518            Corner::new(Some(CornerId::new(9)), VertexId::new(5)), // 13
519            Corner::new(None, VertexId::new(5)),                   // 14
520            Corner::new(Some(CornerId::new(1)), VertexId::new(5)), // 15
521            Corner::new(Some(CornerId::new(12)), VertexId::new(0)), // 16
522            Corner::new(None, VertexId::new(5)),                   // 17
523        ];
524
525        mesh.collapse_edge(EdgeId::new(CornerId::new(12)), &Vec3f::new(0.5, 0.5, 0.0));
526
527        assert_mesh_eq(&mesh, &expected_corners, &expected_vertices);
528    }
529
530    #[test]
531    fn collapse_boundary_edge() {
532        let mut mesh = create_collapse_edge_sample_mesh3();
533
534        let expected_vertices = vec![
535            Vertex::new(CornerId::new(0), Vec3f::new(0.0, 1.0, 0.0)), // 0
536            Vertex::new(CornerId::new(6), Vec3f::new(2.0, 0.0, 0.0)), // 1
537            Vertex::new(CornerId::new(6), Vec3f::new(3.0, 0.0, 0.0)), // 2
538            Vertex::new(CornerId::new(7), Vec3f::new(4.0, 1.0, 0.0)), // 3
539            Vertex::new(CornerId::new(2), Vec3f::new(2.0, 1.0, 0.0)), // 4
540        ];
541
542        let expected_corners = vec![
543            // opposite, vertex, flags
544            Corner::new(Some(CornerId::new(7)), VertexId::new(0)), // 0
545            Corner::new(None, VertexId::new(1)),                   // 1
546            Corner::new(None, VertexId::new(4)),                   // 2
547            Corner::new(Some(CornerId::new(7)), VertexId::new(1)), // 3
548            Corner::new(Some(CornerId::new(0)), VertexId::new(1)), // 4
549            Corner::new(None, VertexId::new(4)),                   // 5
550            Corner::new(None, VertexId::new(1)),                   // 6
551            Corner::new(Some(CornerId::new(0)), VertexId::new(3)), // 7
552            Corner::new(None, VertexId::new(4)),                   // 8
553        ];
554
555        mesh.collapse_edge(EdgeId::new(CornerId::new(5)), &Vec3f::new(2.0, 0.0, 0.0));
556
557        assert_mesh_eq(&mesh, &expected_corners, &expected_vertices);
558    }
559
560    #[test]
561    fn flip_edge() {
562        let mut mesh = create_flip_edge_sample_mesh();
563
564        let expected_vertices = vec![
565            Vertex::new(CornerId::new(4), Vec3f::new(0.5, 1.0, 0.0)), // 0
566            Vertex::new(CornerId::new(0), Vec3f::new(0.0, 0.5, 0.0)), // 1
567            Vertex::new(CornerId::new(1), Vec3f::new(0.5, 0.0, 0.0)), // 2
568            Vertex::new(CornerId::new(2), Vec3f::new(1.0, 0.5, 0.0)), // 3
569            Vertex::new(CornerId::new(13), Vec3f::new(1.0, 1.0, 0.0)), // 4
570            Vertex::new(CornerId::new(16), Vec3f::new(0.0, 1.0, 0.0)), // 5
571            Vertex::new(CornerId::new(7), Vec3f::new(0.0, 0.0, 0.0)), // 6
572            Vertex::new(CornerId::new(10), Vec3f::new(1.0, 0.0, 0.0)), // 7
573        ];
574
575        let expected_corners = vec![
576            // opposite, vertex, flags
577            Corner::new(Some(CornerId::new(10)), VertexId::new(1)), // 0
578            Corner::new(Some(CornerId::new(4)), VertexId::new(2)),  // 1
579            Corner::new(Some(CornerId::new(7)), VertexId::new(3)),  // 2
580            Corner::new(Some(CornerId::new(16)), VertexId::new(3)), // 3
581            Corner::new(Some(CornerId::new(1)), VertexId::new(0)),  // 4
582            Corner::new(Some(CornerId::new(13)), VertexId::new(1)), // 5
583            Corner::new(None, VertexId::new(1)),                    // 6
584            Corner::new(Some(CornerId::new(2)), VertexId::new(6)),  // 7
585            Corner::new(None, VertexId::new(2)),                    // 8
586            Corner::new(None, VertexId::new(2)),                    // 9
587            Corner::new(Some(CornerId::new(0)), VertexId::new(7)),  // 10
588            Corner::new(None, VertexId::new(3)),                    // 11
589            Corner::new(None, VertexId::new(3)),                    // 12
590            Corner::new(Some(CornerId::new(5)), VertexId::new(4)),  // 13
591            Corner::new(None, VertexId::new(0)),                    // 14
592            Corner::new(None, VertexId::new(0)),                    // 15
593            Corner::new(Some(CornerId::new(3)), VertexId::new(5)),  // 16
594            Corner::new(None, VertexId::new(1)),                    // 17
595        ];
596
597        mesh.flip_edge(EdgeId::new(CornerId::new(1)));
598
599        assert_mesh_eq(&mesh, &expected_corners, &expected_vertices);
600    }
601
602    #[test]
603    fn split_face() {
604        let mut mesh = create_unit_square_mesh();
605
606        let expected_vertices = vec![
607            Vertex::new(CornerId::new(5), Vec3f::new(0.0, 1.0, 0.0)), // 0
608            Vertex::new(CornerId::new(1), Vec3f::new(0.0, 0.0, 0.0)), // 1
609            Vertex::new(CornerId::new(7), Vec3f::new(1.0, 0.0, 0.0)), // 2
610            Vertex::new(CornerId::new(4), Vec3f::new(1.0, 1.0, 0.0)), // 3
611            Vertex::new(CornerId::new(2), Vec3f::new(0.5, 0.5, 0.0)), // 4
612        ];
613
614        let expected_corners = vec![
615            // opposite, vertex, flags
616            Corner::new(Some(CornerId::new(7)), VertexId::new(0)), // 0
617            Corner::new(Some(CornerId::new(9)), VertexId::new(1)), // 1
618            Corner::new(None, VertexId::new(4)),                   // 2
619            Corner::new(None, VertexId::new(2)),                   // 3
620            Corner::new(Some(CornerId::new(11)), VertexId::new(3)), // 4
621            Corner::new(None, VertexId::new(0)),                   // 5
622            Corner::new(Some(CornerId::new(10)), VertexId::new(1)), // 6
623            Corner::new(Some(CornerId::new(0)), VertexId::new(2)), // 7
624            Corner::new(None, VertexId::new(4)),                   // 8
625            Corner::new(Some(CornerId::new(1)), VertexId::new(2)), // 9
626            Corner::new(Some(CornerId::new(6)), VertexId::new(0)), // 10
627            Corner::new(Some(CornerId::new(4)), VertexId::new(4)), // 11
628        ];
629
630        mesh.split_face(FaceId::new(0), Vec3f::new(0.5, 0.5, 0.0));
631
632        assert_mesh_eq(&mesh, &expected_corners, &expected_vertices);
633    }
634}