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 }
Kernel::FaceVertexIter FaceVertexIter
Circulator.
Definition: PolyMeshT.hh:170
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:139
VertexHandle add_vertex(const Point &_p)
Alias for new_vertex(const Point&).
Definition: PolyMeshT.hh:236
Kernel::VertexOHalfedgeIter VertexOHalfedgeIter
Circulator.
Definition: PolyMeshT.hh:166
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:115