Developer Documentation

unittests_trimesh_collapse.cc
1 #include <gtest/gtest.h>
2 #include <Unittests/unittests_common.hh>
3
4 #include <iostream>
5
6 namespace {
7
8 class OpenMeshCollapse : public OpenMeshBase {
9
10 protected:
11
12 // This function is called before each test is run
13 virtual void SetUp() {
14 }
15
16 // This function is called after all tests are through
17 virtual void TearDown() {
18
19 // Do some final stuff with the member data here...
20 }
21
22 // Member already defined in OpenMeshBase
23 //Mesh mesh_;
24 };
25
26 /*
27 * ====================================================================
28 * Define tests below
29 * ====================================================================
30 */
31
32
33 /*
34 * Collapsing a quad splitted with center vertex
35 */
36 TEST_F(OpenMeshCollapse, CollapseQuadWithCenter) {
37
38 mesh_.clear();
39
40
41 // 0--------1
42 // |\ /|
43 // | \ / |
44 // | \ / |
45 // | 2 |
46 // | / \ |
47 // | / \ |
48 // 3--------4
49
50 // Add some vertices
51 Mesh::VertexHandle vhandle[5];
52
53 vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
54 vhandle[1] = mesh_.add_vertex(Mesh::Point(2, 0, 0));
55 vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
56 vhandle[3] = mesh_.add_vertex(Mesh::Point(0, 2, 0));
57 vhandle[4] = mesh_.add_vertex(Mesh::Point(2, 2, 0));
58
59 // Add four faces
60 std::vector<Mesh::VertexHandle> face_vhandles;
61
62 face_vhandles.push_back(vhandle[0]);
63 face_vhandles.push_back(vhandle[2]);
64 face_vhandles.push_back(vhandle[1]);
65 mesh_.add_face(face_vhandles);
66
67 face_vhandles.clear();
68
69 face_vhandles.push_back(vhandle[0]);
70 face_vhandles.push_back(vhandle[3]);
71 face_vhandles.push_back(vhandle[2]);
72 mesh_.add_face(face_vhandles);
73
74 face_vhandles.clear();
75
76 face_vhandles.push_back(vhandle[4]);
77 face_vhandles.push_back(vhandle[2]);
78 face_vhandles.push_back(vhandle[3]);
79 mesh_.add_face(face_vhandles);
80
81 face_vhandles.clear();
82
83 face_vhandles.push_back(vhandle[4]);
84 face_vhandles.push_back(vhandle[1]);
85 face_vhandles.push_back(vhandle[2]);
86 mesh_.add_face(face_vhandles);
87
88 mesh_.request_vertex_status();
89 mesh_.request_edge_status();
90 mesh_.request_face_status();
91
92
93 // Get the halfedge
94 Mesh::HalfedgeHandle v2v1 = mesh_.find_halfedge(vhandle[2], vhandle[1]);
95
96 EXPECT_TRUE( v2v1.is_valid() ) << "Invalid halfedge returned although it shoud exist";
97 EXPECT_TRUE( mesh_.is_collapse_ok(v2v1) ) << "Collapse retuned illegal althoug legal";
98
99 // Execute it as a crash test
100 mesh_.collapse(v2v1);
101 }
102
103
104
105
106 /*
107 * Collapsing a tetrahedron
108 */
109 TEST_F(OpenMeshCollapse, CollapseTetrahedronComplex) {
110
111 mesh_.clear();
112
113 // Add some vertices
114 Mesh::VertexHandle vhandle[4];
115
116 vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
117 vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
118 vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
119 vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
120
121 // Add four faces
122 std::vector<Mesh::VertexHandle> face_vhandles;
123
124 face_vhandles.push_back(vhandle[0]);
125 face_vhandles.push_back(vhandle[1]);
126 face_vhandles.push_back(vhandle[2]);
127 mesh_.add_face(face_vhandles);
128
129 face_vhandles.clear();
130
131 face_vhandles.push_back(vhandle[0]);
132 face_vhandles.push_back(vhandle[2]);
133 face_vhandles.push_back(vhandle[3]);
134 mesh_.add_face(face_vhandles);
135
136 face_vhandles.clear();
137
138 face_vhandles.push_back(vhandle[2]);
139 face_vhandles.push_back(vhandle[1]);
140 face_vhandles.push_back(vhandle[3]);
141 mesh_.add_face(face_vhandles);
142
143 face_vhandles.clear();
144
145 face_vhandles.push_back(vhandle[3]);
146 face_vhandles.push_back(vhandle[1]);
147 face_vhandles.push_back(vhandle[0]);
148 mesh_.add_face(face_vhandles);
149
150 mesh_.request_vertex_status();
151 mesh_.request_edge_status();
152 mesh_.request_face_status();
153
154 Mesh::HalfedgeHandle v0v1 = mesh_.halfedge_handle(0);
155 Mesh::HalfedgeHandle v1v0 = mesh_.opposite_halfedge_handle(v0v1);
156
157 Mesh::HalfedgeHandle v1vL = mesh_.next_halfedge_handle(v0v1);
158 Mesh::HalfedgeHandle vLv1 = mesh_.opposite_halfedge_handle(v1vL);
159 Mesh::HalfedgeHandle vLv0 = mesh_.next_halfedge_handle(v1vL);
160 Mesh::HalfedgeHandle v0vL = mesh_.opposite_halfedge_handle(vLv0);
161
162 Mesh::HalfedgeHandle vLvR = mesh_.next_halfedge_handle(v0vL);
163 Mesh::HalfedgeHandle vRvL = mesh_.opposite_halfedge_handle(vLvR);
164
165 Mesh::HalfedgeHandle v0vR = mesh_.next_halfedge_handle(v1v0);
166 Mesh::HalfedgeHandle vRv0 = mesh_.opposite_halfedge_handle(v0vR);
167 Mesh::HalfedgeHandle vRv1 = mesh_.next_halfedge_handle(v0vR);
168 Mesh::HalfedgeHandle v1vR = mesh_.opposite_halfedge_handle(vRv1);
169
170
171
172 Mesh::VertexHandle v0 = mesh_.from_vertex_handle(v0v1);
173 Mesh::VertexHandle v1 = mesh_.to_vertex_handle(v0v1);
174 Mesh::VertexHandle vL = mesh_.to_vertex_handle(mesh_.next_halfedge_handle(v0v1));
175 Mesh::VertexHandle vR = mesh_.to_vertex_handle(mesh_.next_halfedge_handle(v1v0));
176
177 // ===================================================================
178 // Check preconditions
179 // ===================================================================
180
181 EXPECT_TRUE( mesh_.is_collapse_ok(v0v1) ) << "Collapse not ok for halfedge 0";
182 EXPECT_TRUE( mesh_.is_collapse_ok(v1v0) ) << "Collapse not ok for opposite of halfedge 0";
183
184 // Test the Vertex indices
185 EXPECT_EQ(0, v0.idx() ) << "Index wrong for from vertex of collapse halfedge";
186 EXPECT_EQ(1, v1.idx() ) << "Index wrong for to vertex of collapse halfedge";
187 EXPECT_EQ(2, vL.idx() ) << "Index wrong for left vertex of collapse halfedge";
188 EXPECT_EQ(3, vR.idx() ) << "Index wrong for right vertex of collapse halfedge";
189
190 // Check the halfedges
191 EXPECT_EQ(0, v0v1.idx() ) << "Index wrong for collapse halfedge";
192 EXPECT_EQ(1, v1v0.idx() ) << "Index wrong for opposite collapse halfedge";
193
194 EXPECT_EQ(2 , v1vL.idx() ) << "Index wrong for v1vL halfedge";
195 EXPECT_EQ(3 , vLv1.idx() ) << "Index wrong for vLv1 halfedge";
196 EXPECT_EQ(4 , vLv0.idx() ) << "Index wrong for vLv0 halfedge";
197 EXPECT_EQ(5 , v0vL.idx() ) << "Index wrong for v0vL halfedge";
198
199 EXPECT_EQ(6 , vLvR.idx() ) << "Index wrong for vLvR halfedge";
200 EXPECT_EQ(7 , vRvL.idx() ) << "Index wrong for vRvL halfedge";
201
202 EXPECT_EQ(8 , vRv0.idx() ) << "Index wrong for vRv0 halfedge";
203 EXPECT_EQ(9 , v0vR.idx() ) << "Index wrong for v0vR halfedge";
204
205 EXPECT_EQ(10 , v1vR.idx() ) << "Index wrong for v1vR halfedge";
206 EXPECT_EQ(11 , vRv1.idx() ) << "Index wrong for vRv1 halfedge";
207
208 // ===================================================================
209 // Execute collapse
210 // ===================================================================
211
212 mesh_.collapse(v0v1);
213
214 // ===================================================================
215 // Check configuration afterwards
216 // ===================================================================
217
233 EXPECT_EQ(4u , mesh_.n_faces() ) << "Wrong number of faces (garbage collection not executed!)";
234
235 // Check if the right vertices got deleted
236 EXPECT_TRUE( mesh_.status(mesh_.face_handle(0)).deleted() ) << "Face 0 not deleted";
237 EXPECT_FALSE( mesh_.status(mesh_.face_handle(1)).deleted() ) << "Face 1 deleted";
238 EXPECT_FALSE( mesh_.status(mesh_.face_handle(2)).deleted() ) << "Face 2 deleted";
239 EXPECT_TRUE( mesh_.status(mesh_.face_handle(3)).deleted() ) << "Face 3 not deleted";
240
241 // Check the vertices of the two remaining faces
242 Mesh::FaceHandle fh_1 = mesh_.face_handle(1);
243 Mesh::FaceHandle fh_2 = mesh_.face_handle(2);
244
245 Mesh::FaceVertexIter fv_it = mesh_.fv_begin(fh_1);
246
247 EXPECT_EQ(1 , fv_it->idx() ) << "Index wrong for Vertex 1 of face 1";
248 ++fv_it;
249 EXPECT_EQ(2 , fv_it->idx() ) << "Index wrong for Vertex 2 of face 1";
250 ++fv_it;
251 EXPECT_EQ(3 , fv_it->idx() ) << "Index wrong for Vertex 3 of face 1";
252
253 fv_it = mesh_.fv_begin(fh_2);
254 EXPECT_EQ(2 , fv_it->idx() ) << "Index wrong for Vertex 1 of face 2";
255 ++fv_it;
256 EXPECT_EQ(1 , fv_it->idx() ) << "Index wrong for Vertex 2 of face 2";
257 ++fv_it;
258 EXPECT_EQ(3 , fv_it->idx() ) << "Index wrong for Vertex 3 of face 2";
259
260 // Get the first halfedge of face 1
261 Mesh::HalfedgeHandle fh_1_he = mesh_.halfedge_handle(fh_1);
262
263 EXPECT_EQ(11 , fh_1_he.idx() ) << "Index wrong for first halfedge of face 1";
264 EXPECT_EQ(1 , mesh_.to_vertex_handle(fh_1_he).idx() ) << "First halfedge inside face 1 pointing to wrong vertex";
265
266 Mesh::HalfedgeHandle next = mesh_.next_halfedge_handle(fh_1_he);
267 EXPECT_EQ(2 , next.idx() ) << "Index wrong for second halfedge inside face 1 ";
268 EXPECT_EQ(2 , mesh_.to_vertex_handle(next).idx() ) << "second halfedge inside face 1 pointing to wrong vertex ";
269
270 next = mesh_.next_halfedge_handle(next);
271 EXPECT_EQ(6 , next.idx() ) << "Index wrong for third halfedge inside face 1 ";
272 EXPECT_EQ(3 , mesh_.to_vertex_handle(next).idx() ) << "Third halfedge inside face 1 pointing to wrong vertex ";
273
274 // Get the first halfedge of face 2
275 Mesh::HalfedgeHandle fh_2_he = mesh_.halfedge_handle(fh_2);
276
277 EXPECT_EQ(7 , fh_2_he.idx() ) << "Index wrong for first halfedge of face 2";
278 EXPECT_EQ(2 , mesh_.to_vertex_handle(fh_2_he).idx() ) << "First halfedge inside face 2 pointing to wrong vertex";
279
280 next = mesh_.next_halfedge_handle(fh_2_he);
281 EXPECT_EQ(3 , next.idx() ) << "Index wrong for second halfedge inside face 2";
282 EXPECT_EQ(1 , mesh_.to_vertex_handle(next).idx() ) << "second halfedge inside face 2 pointing to wrong vertex ";
283
284 next = mesh_.next_halfedge_handle(next);
285 EXPECT_EQ(10 , next.idx() ) << "Index wrong for third halfedge inside face 2";
286 EXPECT_EQ(3 , mesh_.to_vertex_handle(next).idx() ) << "Third halfedge inside face 2 pointing to wrong vertex ";
287
288 // Vertex 1 outgoing
289 Mesh::VertexOHalfedgeIter voh_it = mesh_.voh_begin(mesh_.vertex_handle(1));
290 EXPECT_EQ(10 , voh_it->idx() ) << "Index wrong for first outgoing halfedge of vertex 1";
291 ++voh_it;
292 EXPECT_EQ(2 , voh_it->idx() ) << "Index wrong for second outgoing halfedge of vertex 1";
293 ++voh_it;
294 EXPECT_EQ(10 , voh_it->idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 1";
295
296 // Vertex 2 outgoing
297 voh_it = mesh_.voh_begin(mesh_.vertex_handle(2));
298 EXPECT_EQ(3 , voh_it->idx() ) << "Index wrong for first outgoing halfedge of vertex 2";
299 ++voh_it;
300 EXPECT_EQ(6 , voh_it->idx() ) << "Index wrong for second outgoing halfedge of vertex 2";
301 ++voh_it;
302 EXPECT_EQ(3 , voh_it->idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 2";
303
304 // Vertex 3 outgoing
305 voh_it = mesh_.voh_begin(mesh_.vertex_handle(3));
306 EXPECT_EQ(11 , voh_it->idx() ) << "Index wrong for first outgoing halfedge of vertex 3";
307 ++voh_it;
308 EXPECT_EQ(7 , voh_it->idx() ) << "Index wrong for second outgoing halfedge of vertex 3";
309 ++voh_it;
310 EXPECT_EQ(11 , voh_it->idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 3";
311
312 // ===================================================================
313 // Cleanup
314 // ===================================================================
315 mesh_.garbage_collection();
316
317 // ===================================================================
318 // Check configuration afterwards
319 // ===================================================================
320
335 EXPECT_EQ(2u , mesh_.n_faces() ) << "Wrong number of faces (garbage collection executed!)";
336
337 // Check the vertices of the two remaining faces
338 Mesh::FaceHandle fh_0 = mesh_.face_handle(0);
339 fh_1 = mesh_.face_handle(1);
340
341 fv_it = mesh_.fv_begin(fh_0);
342
343 EXPECT_EQ(2 , fv_it->idx() ) << "Index wrong for Vertex 1 of face 0 after garbage collection";
344 ++fv_it;
345 EXPECT_EQ(1 , fv_it->idx() ) << "Index wrong for Vertex 2 of face 0 after garbage collection";
346 ++fv_it;
347 EXPECT_EQ(0 , fv_it->idx() ) << "Index wrong for Vertex 3 of face 0 after garbage collection";
348
349 fv_it = mesh_.fv_begin(fh_1);
350 EXPECT_EQ(1 , fv_it->idx() ) << "Index wrong for Vertex 1 of face 1 after garbage collection";
351 ++fv_it;
352 EXPECT_EQ(2 , fv_it->idx() ) << "Index wrong for Vertex 2 of face 1 after garbage collection";
353 ++fv_it;
354 EXPECT_EQ(0 , fv_it->idx() ) << "Index wrong for Vertex 3 of face 1 after garbage collection";
355
356 // Get the first halfedge of face 1
357 Mesh::HalfedgeHandle fh_0_he = mesh_.halfedge_handle(fh_0);
358
359 EXPECT_EQ(5 , fh_0_he.idx() ) << "Index wrong for first halfedge of face 0";
360 EXPECT_EQ(2 , mesh_.to_vertex_handle(fh_0_he).idx() ) << "First halfedge inside face 0 pointing to wrong vertex";
361
362 next = mesh_.next_halfedge_handle(fh_0_he);
363 EXPECT_EQ(3 , next.idx() ) << "Index wrong for second halfedge inside face 0 ";
364 EXPECT_EQ(1 , mesh_.to_vertex_handle(next).idx() ) << "second halfedge inside face 0 pointing to wrong vertex ";
365
366 next = mesh_.next_halfedge_handle(next);
367 EXPECT_EQ(0 , next.idx() ) << "Index wrong for third halfedge inside face 0 ";
368 EXPECT_EQ(0 , mesh_.to_vertex_handle(next).idx() ) << "Third halfedge inside face 0 pointing to wrong vertex ";
369
370 // Get the first halfedge of face 1
371 fh_1_he = mesh_.halfedge_handle(fh_1);
372
373 EXPECT_EQ(1 , fh_1_he.idx() ) << "Index wrong for first halfedge of face 1";
374 EXPECT_EQ(1 , mesh_.to_vertex_handle(fh_1_he).idx() ) << "First halfedge inside face 1 pointing to wrong vertex";
375
376 next = mesh_.next_halfedge_handle(fh_1_he);
377 EXPECT_EQ(2 , next.idx() ) << "Index wrong for second halfedge inside face 1 ";
378 EXPECT_EQ(2 , mesh_.to_vertex_handle(next).idx() ) << "second halfedge inside face 1 pointing to wrong vertex ";
379
380 next = mesh_.next_halfedge_handle(next);
381 EXPECT_EQ(4 , next.idx() ) << "Index wrong for third halfedge inside face 1 ";
382 EXPECT_EQ(0 , mesh_.to_vertex_handle(next).idx() ) << "Third halfedge inside face 1 pointing to wrong vertex ";
383
384
385 // Vertex 0 outgoing
386 voh_it = mesh_.voh_begin(mesh_.vertex_handle(0));
387 EXPECT_EQ(1 , voh_it->idx() ) << "Index wrong for first outgoing halfedge of vertex 0";
388 ++voh_it;
389 EXPECT_EQ(5 , voh_it->idx() ) << "Index wrong for second outgoing halfedge of vertex 0";
390 ++voh_it;
391 EXPECT_EQ(1 , voh_it->idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 0";
392
393 // Vertex 1 outgoing
394 voh_it = mesh_.voh_begin(mesh_.vertex_handle(1));
395 EXPECT_EQ(0 , voh_it->idx() ) << "Index wrong for first outgoing halfedge of vertex 1";
396 ++voh_it;
397 EXPECT_EQ(2 , voh_it->idx() ) << "Index wrong for second outgoing halfedge of vertex 1";
398 ++voh_it;
399 EXPECT_EQ(0 , voh_it->idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 1";
400
401 // Vertex 2 outgoing
402 voh_it = mesh_.voh_begin(mesh_.vertex_handle(2));
403 EXPECT_EQ(3 , voh_it->idx() ) << "Index wrong for first outgoing halfedge of vertex 2";
404 ++voh_it;
405 EXPECT_EQ(4 , voh_it->idx() ) << "Index wrong for second outgoing halfedge of vertex 2";
406 ++voh_it;
407 EXPECT_EQ(3 , voh_it->idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 2";
408
409 EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(0)) ) << "Collapse should be not ok for halfedge 0";
410 EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(1)) ) << "Collapse should be not ok for halfedge 1";
411 EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(2)) ) << "Collapse should be not ok for halfedge 2";
412 EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(3)) ) << "Collapse should be not ok for halfedge 3";
413 EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(4)) ) << "Collapse should be not ok for halfedge 4";
414 EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(5)) ) << "Collapse should be not ok for halfedge 5";
415 }
416
417 /*
418 * Collapsing a tetrahedron
419 */
420 TEST_F(OpenMeshCollapse, CollapseTetrahedron) {
421
422 mesh_.clear();
423
424 // Add some vertices
425 Mesh::VertexHandle vhandle[5];
426
427 // Setup a pyramid
428 vhandle[0] = mesh_.add_vertex(Mesh::Point(0 , 0, 0));
429 vhandle[1] = mesh_.add_vertex(Mesh::Point(1 , 0, 0));
430 vhandle[2] = mesh_.add_vertex(Mesh::Point(0 ,-1, 0));
431 vhandle[3] = mesh_.add_vertex(Mesh::Point(0 , 1, 0));
432 vhandle[4] = mesh_.add_vertex(Mesh::Point(-1, 0, 0));
433
434 // Add six faces
435 std::vector<Mesh::VertexHandle> face_vhandles;
436
437 face_vhandles.push_back(vhandle[0]);
438 face_vhandles.push_back(vhandle[4]);
439 face_vhandles.push_back(vhandle[2]);
440 mesh_.add_face(face_vhandles);
441
442 face_vhandles.clear();
443
444 face_vhandles.push_back(vhandle[3]);
445 face_vhandles.push_back(vhandle[4]);
446 face_vhandles.push_back(vhandle[0]);
447 mesh_.add_face(face_vhandles);
448
449 face_vhandles.clear();
450
451 face_vhandles.push_back(vhandle[2]);
452 face_vhandles.push_back(vhandle[4]);
453 face_vhandles.push_back(vhandle[3]);
454 mesh_.add_face(face_vhandles);
455
456 face_vhandles.clear();
457
458 face_vhandles.push_back(vhandle[2]);
459 face_vhandles.push_back(vhandle[1]);
460 face_vhandles.push_back(vhandle[0]);
461 mesh_.add_face(face_vhandles);
462
463 face_vhandles.clear();
464
465 face_vhandles.push_back(vhandle[0]);
466 face_vhandles.push_back(vhandle[1]);
467 face_vhandles.push_back(vhandle[3]);
468 mesh_.add_face(face_vhandles);
469
470 mesh_.request_vertex_status();
471 mesh_.request_edge_status();
472 mesh_.request_face_status();
473
474
475 // =============================================
476 // Collapse halfedge from 0 to 4
477 // =============================================
478
479 Mesh::HalfedgeHandle heh_collapse1 = mesh_.halfedge_handle(0);
480
481 EXPECT_EQ(4, mesh_.to_vertex_handle(heh_collapse1).idx() ) << "To vertex of collapse halfedge 1 is wrong";
482 EXPECT_EQ(0, mesh_.from_vertex_handle(heh_collapse1).idx() ) << "from vertex of collapse halfedge 1 is wrong";
483
484 EXPECT_TRUE( mesh_.is_collapse_ok(heh_collapse1) ) << "Collapse not ok for collapse first halfedge (0)";
485 mesh_.collapse(heh_collapse1);
486
487 Mesh::HalfedgeHandle heh_collapse2 = mesh_.halfedge_handle(2);
488
489 EXPECT_EQ(2, mesh_.to_vertex_handle(heh_collapse2).idx() ) << "To vertex of collapse halfedge 2 is wrong";
490 EXPECT_EQ(4, mesh_.from_vertex_handle(heh_collapse2).idx() ) << "from vertex of collapse halfedge 2 is wrong";
491
492 EXPECT_TRUE( mesh_.is_collapse_ok(heh_collapse2) ) << "Collapse not ok for collapse second halfedge (2)";
493 mesh_.collapse(heh_collapse2);
494
495 Mesh::HalfedgeHandle heh_collapse3 = mesh_.halfedge_handle(6);
496
497 EXPECT_EQ(2, mesh_.to_vertex_handle(heh_collapse3).idx() ) << "To vertex of collapse halfedge 3 is wrong";
498 EXPECT_EQ(3, mesh_.from_vertex_handle(heh_collapse3).idx() ) << "from vertex of collapse halfedge 3 is wrong";
499
500 EXPECT_FALSE( mesh_.is_collapse_ok(heh_collapse3) ) << "Collapse not ok for collapse third halfedge (6)";
501
502
503 }
504
505 /*
506 * Test collapsing an halfedge in a triangle mesh
507 *
508 */
509 TEST_F(OpenMeshCollapse, LargeCollapseHalfEdge) {
510
511 mesh_.clear();
512
513 // Add some vertices
514 Mesh::VertexHandle vhandle[7];
515
516 vhandle[0] = mesh_.add_vertex(Mesh::Point( 0, 1, 0));
517 vhandle[1] = mesh_.add_vertex(Mesh::Point( 1, 0, 0));
518 vhandle[2] = mesh_.add_vertex(Mesh::Point( 2, 1, 0));
519 vhandle[3] = mesh_.add_vertex(Mesh::Point( 0,-1, 0));
520 vhandle[4] = mesh_.add_vertex(Mesh::Point( 2,-1, 0));
521 vhandle[5] = mesh_.add_vertex(Mesh::Point(-1, 0, 0));
522 vhandle[6] = mesh_.add_vertex(Mesh::Point( 3, 0, 0));
523
524 // Add two faces
525 std::vector<Mesh::VertexHandle> face_vhandles;
526
527 face_vhandles.push_back(vhandle[0]);
528 face_vhandles.push_back(vhandle[5]);
529 face_vhandles.push_back(vhandle[1]);
530 mesh_.add_face(face_vhandles);
531
532 face_vhandles.clear();
533
534 face_vhandles.push_back(vhandle[1]);
535 face_vhandles.push_back(vhandle[5]);
536 face_vhandles.push_back(vhandle[3]);
537 mesh_.add_face(face_vhandles);
538
539 face_vhandles.clear();
540
541 face_vhandles.push_back(vhandle[0]);
542 face_vhandles.push_back(vhandle[1]);
543 face_vhandles.push_back(vhandle[2]);
544 mesh_.add_face(face_vhandles);
545
546 face_vhandles.clear();
547
548 face_vhandles.push_back(vhandle[1]);
549 face_vhandles.push_back(vhandle[3]);
550 face_vhandles.push_back(vhandle[4]);
551 mesh_.add_face(face_vhandles);
552
553 face_vhandles.clear();
554
555 face_vhandles.push_back(vhandle[2]);
556 face_vhandles.push_back(vhandle[1]);
557 face_vhandles.push_back(vhandle[4]);
558 mesh_.add_face(face_vhandles);
559
560 face_vhandles.clear();
561
562 face_vhandles.push_back(vhandle[2]);
563 face_vhandles.push_back(vhandle[4]);
564 face_vhandles.push_back(vhandle[6]);
565 mesh_.add_face(face_vhandles);
566
567 /* Test setup:
568 0 ==== 2
569 / \ /|\
570 / \ / | \
571 5 --- 1 | 6
572 \ / \ | /
573 \ / \|/
574 3 ==== 4 */
575
576 // Request the status bits
577 mesh_.request_vertex_status();
578 mesh_.request_edge_status();
579 mesh_.request_face_status();
580
581 // =============================================
582 // Collapse halfedge from 1 to 4
583 // =============================================
584
585 Mesh::HalfedgeHandle heh_collapse;
586
587 // Iterate over all halfedges to find the correct one
588 for ( Mesh::HalfedgeIter he_it = mesh_.halfedges_begin() ; he_it != mesh_.halfedges_end() ; ++he_it ) {
589 if ( mesh_.from_vertex_handle(*he_it).idx() == 1 && mesh_.to_vertex_handle(*he_it).idx() == 4 )
590 heh_collapse = *he_it;
591 }
592
593 // Check our halfedge
594 EXPECT_EQ(4, mesh_.to_vertex_handle(heh_collapse).idx() ) << "To vertex of collapse halfedge is wrong";
595 EXPECT_EQ(1, mesh_.from_vertex_handle(heh_collapse).idx() ) << "from vertex of collapse halfedge is wrong";
596 EXPECT_TRUE( mesh_.is_collapse_ok(heh_collapse) ) << "Collapse not ok for collapse first halfedge (0)";
597
598 // Remember the end vertices
599 Mesh::VertexHandle vh_from = mesh_.from_vertex_handle(heh_collapse);
600 Mesh::VertexHandle vh_to = mesh_.to_vertex_handle(heh_collapse);
601
602 // Collapse it
603 mesh_.collapse(heh_collapse);
604
605 EXPECT_TRUE( mesh_.status(vh_from).deleted() ) << "From vertex not deleted";
606 EXPECT_FALSE( mesh_.status(vh_to).deleted() ) << "To Vertex deleted";
607
608 }
609
610
611 /*
612 * Test collapsing an halfedge in a triangle mesh
613 *
614 */
615 TEST_F(OpenMeshCollapse, DeletedStatus) {
616
617 mesh_.clear();
618
619 // Add some vertices
620 Mesh::VertexHandle vhandle[6];
621
622 vhandle[0] = mesh_.add_vertex(Mesh::Point(-1, 0, 0));
623 vhandle[1] = mesh_.add_vertex(Mesh::Point( 0, 2, 0));
624 vhandle[2] = mesh_.add_vertex(Mesh::Point( 0, 1, 0));
625 vhandle[3] = mesh_.add_vertex(Mesh::Point( 0,-1, 0));
626 vhandle[4] = mesh_.add_vertex(Mesh::Point( 0,-2, 0));
627 vhandle[5] = mesh_.add_vertex(Mesh::Point( 1, 0, 0));
628
629 // Add two faces
630 std::vector<Mesh::VertexHandle> face_vhandles;
631
632 face_vhandles.push_back(vhandle[0]);
633 face_vhandles.push_back(vhandle[2]);
634 face_vhandles.push_back(vhandle[1]);
635 mesh_.add_face(face_vhandles);
636
637 face_vhandles.clear();
638
639 face_vhandles.push_back(vhandle[0]);
640 face_vhandles.push_back(vhandle[3]);
641 face_vhandles.push_back(vhandle[2]);
642 mesh_.add_face(face_vhandles);
643
644 face_vhandles.clear();
645
646 face_vhandles.push_back(vhandle[0]);
647 face_vhandles.push_back(vhandle[4]);
648 face_vhandles.push_back(vhandle[3]);
649 mesh_.add_face(face_vhandles);
650
651 face_vhandles.clear();
652
653 face_vhandles.push_back(vhandle[5]);
654 face_vhandles.push_back(vhandle[1]);
655 face_vhandles.push_back(vhandle[2]);
656 mesh_.add_face(face_vhandles);
657
658 face_vhandles.clear();
659
660 face_vhandles.push_back(vhandle[5]);
661 face_vhandles.push_back(vhandle[2]);
662 face_vhandles.push_back(vhandle[3]);
663 mesh_.add_face(face_vhandles);
664
665 face_vhandles.clear();
666
667 face_vhandles.push_back(vhandle[5]);
668 face_vhandles.push_back(vhandle[3]);
669 face_vhandles.push_back(vhandle[4]);
670 mesh_.add_face(face_vhandles);
671
672 /* Test setup:
673 * 1
674 * /|\
675 * / | \
676 * / _2_ \
677 * /_/ | \_\
678 * 0__ | __5
679 * \ \_3_/ /
680 * \ | /
681 * \ | /
682 * \|/
683 * 4
684 */
685
686 EXPECT_EQ(mesh_.n_faces(), 6u) << "Could not add all faces";
687
688 // Request the status bits
689 mesh_.request_vertex_status();
690 mesh_.request_edge_status();
691 mesh_.request_halfedge_status();
692 mesh_.request_face_status();
693
694 // =============================================
695 // Collapse halfedge from 3 to 2
696 // =============================================
697
698 Mesh::HalfedgeHandle heh_collapse = mesh_.find_halfedge(Mesh::VertexHandle(2), Mesh::VertexHandle(3));
699
700 EXPECT_TRUE(heh_collapse.is_valid()) << "Could not find halfedge from vertex 2 to vetex 3";
701 EXPECT_TRUE(mesh_.is_collapse_ok(heh_collapse)) << "Collapse is not ok for halfedge from vertex 2 to vertex 3";
702
703 Mesh::HalfedgeHandle top_left = mesh_.find_halfedge(Mesh::VertexHandle(2), Mesh::VertexHandle(0));
704 Mesh::HalfedgeHandle top_right = mesh_.find_halfedge(Mesh::VertexHandle(5), Mesh::VertexHandle(2));
705 Mesh::HalfedgeHandle bottom_left = mesh_.find_halfedge(Mesh::VertexHandle(0), Mesh::VertexHandle(3));
706 Mesh::HalfedgeHandle bottom_right = mesh_.find_halfedge(Mesh::VertexHandle(3), Mesh::VertexHandle(5));
707
708 EXPECT_TRUE(top_left.is_valid()) << "Could not find halfedge from vertex 2 to vetex 0";
709 EXPECT_TRUE(top_right.is_valid()) << "Could not find halfedge from vertex 5 to vetex 2";
710 EXPECT_TRUE(bottom_left.is_valid()) << "Could not find halfedge from vertex 0 to vetex 3";
711 EXPECT_TRUE(bottom_right.is_valid()) << "Could not find halfedge from vertex 3 to vetex 5";
712
713 Mesh::FaceHandle left = mesh_.face_handle(top_left);
714 Mesh::FaceHandle right = mesh_.face_handle(top_right);
715 EXPECT_TRUE(left.is_valid()) << "Could not find left face";
716 EXPECT_TRUE(right.is_valid()) << "Could not find right";
717
718 mesh_.collapse(heh_collapse);
719
720 EXPECT_TRUE(mesh_.status(Mesh::VertexHandle(2)).deleted()) << "Collapsed vertex is not deleted.";
721
722 EXPECT_TRUE(mesh_.status(left).deleted()) << "Left face is not deleted.";
723 EXPECT_TRUE(mesh_.status(right).deleted()) << "Right face is not deleted.";
724
725 EXPECT_TRUE(mesh_.status(mesh_.edge_handle(heh_collapse)).deleted()) << "Collapsed edge is not deleted.";
726 EXPECT_TRUE(mesh_.status(mesh_.edge_handle(top_left)).deleted()) << "Top left edge is not deleted.";
727 EXPECT_TRUE(mesh_.status(mesh_.edge_handle(top_right)).deleted()) << "Top right edge is not deleted.";
728 EXPECT_FALSE(mesh_.status(mesh_.edge_handle(bottom_left)).deleted()) << "Bottom left edge is deleted.";
729 EXPECT_FALSE(mesh_.status(mesh_.edge_handle(bottom_right)).deleted()) << "Bottom right edge is deleted.";
730
731 EXPECT_TRUE(mesh_.status(heh_collapse).deleted()) << "Collapsed halfedge is not deleted.";
732 EXPECT_TRUE(mesh_.status(mesh_.opposite_halfedge_handle(heh_collapse)).deleted()) << "Opposite of collapsed halfedge is not deleted.";
733
734 EXPECT_TRUE(mesh_.status(top_left).deleted()) << "Halfedge from vertex 0 to vertex 2 is not deleted";
735 EXPECT_TRUE(mesh_.status(mesh_.opposite_halfedge_handle(top_left)).deleted()) << "Halfedge from vertex 2 to vertex 0 is not deleted";
736 EXPECT_TRUE(mesh_.status(top_right).deleted()) << "Halfedge from vertex 5 to vertex 2 is not deleted";
737 EXPECT_TRUE(mesh_.status(mesh_.opposite_halfedge_handle(top_right)).deleted()) << "Halfedge from vertex 2 to vertex 5 is not deleted";
738 EXPECT_FALSE(mesh_.status(bottom_left).deleted()) << "Halfedge from vertex 0 to vertex 3 is deleted";
739 EXPECT_FALSE(mesh_.status(mesh_.opposite_halfedge_handle(bottom_left)).deleted()) << "Halfedge from vertex 3 to vertex 0 is deleted";
740 EXPECT_FALSE(mesh_.status(bottom_right).deleted()) << "Halfedge from vertex 3 to vertex 5 is deleted";
741 EXPECT_FALSE(mesh_.status(mesh_.opposite_halfedge_handle(bottom_right)).deleted()) << "Halfedge from vertex 5 to vertex 3 is deleted";
742 }
743
744 }
OpenMesh::PolyMeshT::FaceVertexIter
Kernel::FaceVertexIter FaceVertexIter
Circulator.
Definition: PolyMeshT.hh:167
OpenMesh::PolyMeshT::Point
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
OpenMesh::PolyMeshT::VertexOHalfedgeIter
Kernel::VertexOHalfedgeIter VertexOHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:163
OpenMesh::PolyMeshT::add_vertex
SmartVertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:235
OpenMeshBase
Definition: unittests_common.hh:29
OpenMesh::PolyMeshT::VertexHandle
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136