OpenMesh
Unittests/unittests_trimesh_collapse.hh
00001 #ifndef INCLUDE_UNITTESTS_TRIMESH_COLLAPSE_HH
00002 #define INCLUDE_UNITTESTS_TRIMESH_COLLAPSE_HH
00003 
00004 #include <gtest/gtest.h>
00005 #include <Unittests/unittests_common.hh>
00006 
00007 #include <iostream>
00008 
00009 class OpenMeshCollapse : public OpenMeshBase {
00010 
00011     protected:
00012 
00013         // This function is called before each test is run
00014         virtual void SetUp() {
00015         }
00016 
00017         // This function is called after all tests are through
00018         virtual void TearDown() {
00019 
00020             // Do some final stuff with the member data here...
00021         }
00022 
00023     // Member already defined in OpenMeshBase
00024     //Mesh mesh_;  
00025 };
00026 
00027 /*
00028  * ====================================================================
00029  * Define tests below
00030  * ====================================================================
00031  */
00032 
00033 /*
00034  * Collapsing a tetrahedron
00035  */
00036 TEST_F(OpenMeshCollapse, CollapseTetrahedron) {
00037 
00038   mesh_.clear();
00039 
00040   // Add some vertices
00041   Mesh::VertexHandle vhandle[4];
00042 
00043   vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0));
00044   vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0));
00045   vhandle[2] = mesh_.add_vertex(Mesh::Point(1, 1, 0));
00046   vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0));
00047 
00048   // Add four faces
00049   std::vector<Mesh::VertexHandle> face_vhandles;
00050 
00051   face_vhandles.push_back(vhandle[0]);
00052   face_vhandles.push_back(vhandle[1]);
00053   face_vhandles.push_back(vhandle[2]);
00054   mesh_.add_face(face_vhandles);
00055 
00056   face_vhandles.clear();
00057 
00058   face_vhandles.push_back(vhandle[0]);
00059   face_vhandles.push_back(vhandle[2]);
00060   face_vhandles.push_back(vhandle[3]);
00061   mesh_.add_face(face_vhandles);
00062 
00063   face_vhandles.clear();
00064 
00065   face_vhandles.push_back(vhandle[2]);
00066   face_vhandles.push_back(vhandle[1]);
00067   face_vhandles.push_back(vhandle[3]);
00068   mesh_.add_face(face_vhandles);
00069 
00070   face_vhandles.clear();
00071 
00072   face_vhandles.push_back(vhandle[3]);
00073   face_vhandles.push_back(vhandle[1]);
00074   face_vhandles.push_back(vhandle[0]);
00075   mesh_.add_face(face_vhandles);
00076 
00077   mesh_.request_vertex_status();
00078   mesh_.request_edge_status();
00079   mesh_.request_face_status();
00080 
00081   Mesh::HalfedgeHandle v0v1 = mesh_.halfedge_handle(0);
00082   Mesh::HalfedgeHandle v1v0 = mesh_.opposite_halfedge_handle(v0v1);
00083 
00084   Mesh::HalfedgeHandle v1vL = mesh_.next_halfedge_handle(v0v1);
00085   Mesh::HalfedgeHandle vLv1 = mesh_.opposite_halfedge_handle(v1vL);
00086   Mesh::HalfedgeHandle vLv0 = mesh_.next_halfedge_handle(v1vL);
00087   Mesh::HalfedgeHandle v0vL = mesh_.opposite_halfedge_handle(vLv0);
00088 
00089   Mesh::HalfedgeHandle vLvR = mesh_.next_halfedge_handle(v0vL);
00090   Mesh::HalfedgeHandle vRvL = mesh_.opposite_halfedge_handle(vLvR);
00091 
00092   Mesh::HalfedgeHandle v0vR = mesh_.next_halfedge_handle(v1v0);
00093   Mesh::HalfedgeHandle vRv0 = mesh_.opposite_halfedge_handle(v0vR);
00094   Mesh::HalfedgeHandle vRv1 = mesh_.next_halfedge_handle(v0vR);
00095   Mesh::HalfedgeHandle v1vR = mesh_.opposite_halfedge_handle(vRv1);
00096 
00097 
00098 
00099   Mesh::VertexHandle v0     = mesh_.from_vertex_handle(v0v1);
00100   Mesh::VertexHandle v1     = mesh_.to_vertex_handle(v0v1);
00101   Mesh::VertexHandle vL     = mesh_.to_vertex_handle(mesh_.next_halfedge_handle(v0v1));
00102   Mesh::VertexHandle vR     = mesh_.to_vertex_handle(mesh_.next_halfedge_handle(v1v0));
00103 
00104   // ===================================================================
00105   // Check preconditions
00106   // ===================================================================
00107 
00108   EXPECT_TRUE( mesh_.is_collapse_ok(v0v1) ) << "Collapse not ok for halfedge 0";
00109   EXPECT_TRUE( mesh_.is_collapse_ok(v1v0) ) << "Collapse not ok for opposite of halfedge 0";
00110 
00111   // Test the Vertex indices
00112   EXPECT_EQ(0, v0.idx() ) << "Index wrong for from vertex of collapse halfedge";
00113   EXPECT_EQ(1, v1.idx() ) << "Index wrong for to vertex of collapse halfedge";
00114   EXPECT_EQ(2, vL.idx() ) << "Index wrong for left vertex of collapse halfedge";
00115   EXPECT_EQ(3, vR.idx() ) << "Index wrong for right vertex of collapse halfedge";
00116 
00117   // Check the halfedges
00118   EXPECT_EQ(0, v0v1.idx() ) << "Index wrong for collapse halfedge";
00119   EXPECT_EQ(1, v1v0.idx() ) << "Index wrong for opposite collapse halfedge";
00120 
00121   EXPECT_EQ(2  , v1vL.idx() ) << "Index wrong for v1vL halfedge";
00122   EXPECT_EQ(3  , vLv1.idx() ) << "Index wrong for vLv1 halfedge";
00123   EXPECT_EQ(4  , vLv0.idx() ) << "Index wrong for vLv0 halfedge";
00124   EXPECT_EQ(5  , v0vL.idx() ) << "Index wrong for v0vL halfedge";
00125 
00126   EXPECT_EQ(6  , vLvR.idx() ) << "Index wrong for vLvR halfedge";
00127   EXPECT_EQ(7  , vRvL.idx() ) << "Index wrong for vRvL halfedge";
00128 
00129   EXPECT_EQ(8  , vRv0.idx() ) << "Index wrong for vRv0 halfedge";
00130   EXPECT_EQ(9  , v0vR.idx() ) << "Index wrong for v0vR halfedge";
00131 
00132   EXPECT_EQ(10 , v1vR.idx() ) << "Index wrong for v1vR halfedge";
00133   EXPECT_EQ(11 , vRv1.idx() ) << "Index wrong for vRv1 halfedge";
00134 
00135   // ===================================================================
00136   // Execute collapse
00137   // ===================================================================
00138 
00139   mesh_.collapse(v0v1);
00140 
00141   // ===================================================================
00142   // Check configuration afterwards
00143   // ===================================================================
00144 
00160   EXPECT_EQ(4 , mesh_.n_faces() ) << "Wrong number of faces (garbage collection not executed!)";
00161 
00162   // Check if the right vertices got deleted
00163   EXPECT_TRUE( mesh_.status(mesh_.face_handle(0)).deleted() ) << "Face 0 not deleted";
00164   EXPECT_FALSE( mesh_.status(mesh_.face_handle(1)).deleted() ) << "Face 1 deleted";
00165   EXPECT_FALSE( mesh_.status(mesh_.face_handle(2)).deleted() ) << "Face 2 deleted";
00166   EXPECT_TRUE( mesh_.status(mesh_.face_handle(3)).deleted() ) << "Face 3 not deleted";
00167 
00168   // Check the vertices of the two remaining faces
00169   Mesh::FaceHandle fh_1 = mesh_.face_handle(1);
00170   Mesh::FaceHandle fh_2 = mesh_.face_handle(2);
00171 
00172   Mesh::FaceVertexIter fv_it =  mesh_.fv_begin(fh_1);
00173 
00174   EXPECT_EQ(1 , fv_it.handle().idx() ) << "Index wrong for Vertex 1 of face 1";
00175   ++fv_it;
00176   EXPECT_EQ(2 , fv_it.handle().idx() ) << "Index wrong for Vertex 2 of face 1";
00177   ++fv_it;
00178   EXPECT_EQ(3 , fv_it.handle().idx() ) << "Index wrong for Vertex 3 of face 1";
00179 
00180   fv_it =  mesh_.fv_begin(fh_2);
00181   EXPECT_EQ(2 , fv_it.handle().idx() ) << "Index wrong for Vertex 1 of face 2";
00182   ++fv_it;
00183   EXPECT_EQ(1 , fv_it.handle().idx() ) << "Index wrong for Vertex 2 of face 2";
00184   ++fv_it;
00185   EXPECT_EQ(3 , fv_it.handle().idx() ) << "Index wrong for Vertex 3 of face 2";
00186 
00187   // Get the first halfedge of face 1
00188   Mesh::HalfedgeHandle fh_1_he = mesh_.halfedge_handle(fh_1);
00189 
00190   EXPECT_EQ(11 , fh_1_he.idx() ) << "Index wrong for first halfedge of face 1";
00191   EXPECT_EQ(1  , mesh_.to_vertex_handle(fh_1_he).idx() ) << "First halfedge inside face 1 pointing to wrong vertex";
00192 
00193   Mesh::HalfedgeHandle next = mesh_.next_halfedge_handle(fh_1_he);
00194   EXPECT_EQ(2 , next.idx() ) << "Index wrong for second halfedge inside face 1 ";
00195   EXPECT_EQ(2 , mesh_.to_vertex_handle(next).idx() ) << "second halfedge inside face 1 pointing to wrong vertex ";
00196 
00197   next = mesh_.next_halfedge_handle(next);
00198   EXPECT_EQ(6 , next.idx() ) << "Index wrong for third halfedge inside face 1 ";
00199   EXPECT_EQ(3 , mesh_.to_vertex_handle(next).idx() ) << "Third halfedge inside face 1 pointing to wrong vertex ";
00200 
00201   // Get the first halfedge of face 2
00202   Mesh::HalfedgeHandle fh_2_he = mesh_.halfedge_handle(fh_2);
00203 
00204   EXPECT_EQ(7 , fh_2_he.idx() ) << "Index wrong for first halfedge of face 2";
00205   EXPECT_EQ(2  , mesh_.to_vertex_handle(fh_2_he).idx() ) << "First halfedge inside face 2 pointing to wrong vertex";
00206 
00207   next = mesh_.next_halfedge_handle(fh_2_he);
00208   EXPECT_EQ(3 , next.idx() ) << "Index wrong for second halfedge inside face 2";
00209   EXPECT_EQ(1 , mesh_.to_vertex_handle(next).idx() ) << "second halfedge inside face 2 pointing to wrong vertex ";
00210 
00211   next = mesh_.next_halfedge_handle(next);
00212   EXPECT_EQ(10 , next.idx() ) << "Index wrong for third halfedge inside face 2";
00213   EXPECT_EQ(3 , mesh_.to_vertex_handle(next).idx() ) << "Third halfedge inside face 2 pointing to wrong vertex ";
00214 
00215   // Vertex 1 outgoing
00216   Mesh::VertexOHalfedgeIter voh_it = mesh_.voh_begin(mesh_.vertex_handle(1));
00217   EXPECT_EQ(10 , voh_it.handle().idx() ) << "Index wrong for first outgoing halfedge of vertex 1";
00218   ++voh_it;
00219   EXPECT_EQ(2  , voh_it.handle().idx() ) << "Index wrong for second outgoing halfedge of vertex 1";
00220   ++voh_it;
00221   EXPECT_EQ(10 , voh_it.handle().idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 1";
00222 
00223   // Vertex 2 outgoing
00224   voh_it = mesh_.voh_begin(mesh_.vertex_handle(2));
00225   EXPECT_EQ(3 , voh_it.handle().idx() ) << "Index wrong for first outgoing halfedge of vertex 2";
00226   ++voh_it;
00227   EXPECT_EQ(6 , voh_it.handle().idx() ) << "Index wrong for second outgoing halfedge of vertex 2";
00228   ++voh_it;
00229   EXPECT_EQ(3 , voh_it.handle().idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 2";
00230 
00231   // Vertex 3 outgoing
00232   voh_it = mesh_.voh_begin(mesh_.vertex_handle(3));
00233   EXPECT_EQ(11 , voh_it.handle().idx() ) << "Index wrong for first outgoing halfedge of vertex 3";
00234   ++voh_it;
00235   EXPECT_EQ(7  , voh_it.handle().idx() ) << "Index wrong for second outgoing halfedge of vertex 3";
00236   ++voh_it;
00237   EXPECT_EQ(11 , voh_it.handle().idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 3";
00238 
00239   // ===================================================================
00240   // Cleanup
00241   // ===================================================================
00242   mesh_.garbage_collection();
00243 
00244   // ===================================================================
00245   // Check configuration afterwards
00246   // ===================================================================
00247 
00262   EXPECT_EQ(2 , mesh_.n_faces() ) << "Wrong number of faces (garbage collection executed!)";
00263 
00264   // Check the vertices of the two remaining faces
00265   Mesh::FaceHandle fh_0 = mesh_.face_handle(0);
00266   fh_1 = mesh_.face_handle(1);
00267 
00268   fv_it =  mesh_.fv_begin(fh_0);
00269 
00270   EXPECT_EQ(2 , fv_it.handle().idx() ) << "Index wrong for Vertex 1 of face 0 after garbage collection";
00271   ++fv_it;
00272   EXPECT_EQ(1 , fv_it.handle().idx() ) << "Index wrong for Vertex 2 of face 0 after garbage collection";
00273   ++fv_it;
00274   EXPECT_EQ(0 , fv_it.handle().idx() ) << "Index wrong for Vertex 3 of face 0 after garbage collection";
00275 
00276   fv_it =  mesh_.fv_begin(fh_1);
00277   EXPECT_EQ(1 , fv_it.handle().idx() ) << "Index wrong for Vertex 1 of face 1 after garbage collection";
00278   ++fv_it;
00279   EXPECT_EQ(2 , fv_it.handle().idx() ) << "Index wrong for Vertex 2 of face 1 after garbage collection";
00280   ++fv_it;
00281   EXPECT_EQ(0 , fv_it.handle().idx() ) << "Index wrong for Vertex 3 of face 1 after garbage collection";
00282 
00283   // Get the first halfedge of face 1
00284   Mesh::HalfedgeHandle fh_0_he = mesh_.halfedge_handle(fh_0);
00285 
00286   EXPECT_EQ(5 , fh_0_he.idx() ) << "Index wrong for first halfedge of face 0";
00287   EXPECT_EQ(2  , mesh_.to_vertex_handle(fh_0_he).idx() ) << "First halfedge inside face 0 pointing to wrong vertex";
00288 
00289   next = mesh_.next_halfedge_handle(fh_0_he);
00290   EXPECT_EQ(3 , next.idx() ) << "Index wrong for second halfedge inside face 0 ";
00291   EXPECT_EQ(1 , mesh_.to_vertex_handle(next).idx() ) << "second halfedge inside face 0 pointing to wrong vertex ";
00292 
00293   next = mesh_.next_halfedge_handle(next);
00294   EXPECT_EQ(0 , next.idx() ) << "Index wrong for third halfedge inside face 0 ";
00295   EXPECT_EQ(0 , mesh_.to_vertex_handle(next).idx() ) << "Third halfedge inside face 0 pointing to wrong vertex ";
00296 
00297   // Get the first halfedge of face 1
00298   fh_1_he = mesh_.halfedge_handle(fh_1);
00299 
00300   EXPECT_EQ(1 , fh_1_he.idx() ) << "Index wrong for first halfedge of face 1";
00301   EXPECT_EQ(1  , mesh_.to_vertex_handle(fh_1_he).idx() ) << "First halfedge inside face 1 pointing to wrong vertex";
00302 
00303   next = mesh_.next_halfedge_handle(fh_1_he);
00304   EXPECT_EQ(2 , next.idx() ) << "Index wrong for second halfedge inside face 1 ";
00305   EXPECT_EQ(2 , mesh_.to_vertex_handle(next).idx() ) << "second halfedge inside face 1 pointing to wrong vertex ";
00306 
00307   next = mesh_.next_halfedge_handle(next);
00308   EXPECT_EQ(4 , next.idx() ) << "Index wrong for third halfedge inside face 1 ";
00309   EXPECT_EQ(0 , mesh_.to_vertex_handle(next).idx() ) << "Third halfedge inside face 1 pointing to wrong vertex ";
00310 
00311 
00312   // Vertex 0 outgoing
00313   voh_it = mesh_.voh_begin(mesh_.vertex_handle(0));
00314   EXPECT_EQ(1 , voh_it.handle().idx() ) << "Index wrong for first outgoing halfedge of vertex 0";
00315   ++voh_it;
00316   EXPECT_EQ(5 , voh_it.handle().idx() ) << "Index wrong for second outgoing halfedge of vertex 0";
00317   ++voh_it;
00318   EXPECT_EQ(1 , voh_it.handle().idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 0";
00319 
00320   // Vertex 1 outgoing
00321   voh_it = mesh_.voh_begin(mesh_.vertex_handle(1));
00322   EXPECT_EQ(0 , voh_it.handle().idx() ) << "Index wrong for first outgoing halfedge of vertex 1";
00323   ++voh_it;
00324   EXPECT_EQ(2 , voh_it.handle().idx() ) << "Index wrong for second outgoing halfedge of vertex 1";
00325   ++voh_it;
00326   EXPECT_EQ(0 , voh_it.handle().idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 1";
00327 
00328   // Vertex 2 outgoing
00329   voh_it = mesh_.voh_begin(mesh_.vertex_handle(2));
00330   EXPECT_EQ(3 , voh_it.handle().idx() ) << "Index wrong for first outgoing halfedge of vertex 2";
00331   ++voh_it;
00332   EXPECT_EQ(4 , voh_it.handle().idx() ) << "Index wrong for second outgoing halfedge of vertex 2";
00333   ++voh_it;
00334   EXPECT_EQ(3 , voh_it.handle().idx() ) << "Index wrong for third(one lap) outgoing halfedge of vertex 2";
00335 
00336   EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(0)) ) << "Collapse should be not ok for halfedge 0";
00337   EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(1)) ) << "Collapse should be not ok for halfedge 1";
00338   EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(2)) ) << "Collapse should be not ok for halfedge 2";
00339   EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(3)) ) << "Collapse should be not ok for halfedge 3";
00340   EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(4)) ) << "Collapse should be not ok for halfedge 4";
00341   EXPECT_FALSE( mesh_.is_collapse_ok(mesh_.halfedge_handle(5)) ) << "Collapse should be not ok for halfedge 5";
00342 }
00343 
00344 /*
00345  * Collapsing a tetrahedron
00346  */
00347 TEST_F(OpenMeshCollapse, CollapseComplex) {
00348 
00349   mesh_.clear();
00350 
00351   // Add some vertices
00352   Mesh::VertexHandle vhandle[5];
00353 
00354   // Setup a pyramid
00355   vhandle[0] = mesh_.add_vertex(Mesh::Point(0 , 0, 0));
00356   vhandle[1] = mesh_.add_vertex(Mesh::Point(1 , 0, 0));
00357   vhandle[2] = mesh_.add_vertex(Mesh::Point(0 ,-1, 0));
00358   vhandle[3] = mesh_.add_vertex(Mesh::Point(0 , 1, 0));
00359   vhandle[4] = mesh_.add_vertex(Mesh::Point(-1, 0, 0));
00360 
00361   // Add six faces
00362   std::vector<Mesh::VertexHandle> face_vhandles;
00363 
00364   face_vhandles.push_back(vhandle[0]);
00365   face_vhandles.push_back(vhandle[4]);
00366   face_vhandles.push_back(vhandle[2]);
00367   mesh_.add_face(face_vhandles);
00368 
00369   face_vhandles.clear();
00370 
00371   face_vhandles.push_back(vhandle[3]);
00372   face_vhandles.push_back(vhandle[4]);
00373   face_vhandles.push_back(vhandle[0]);
00374   mesh_.add_face(face_vhandles);
00375 
00376   face_vhandles.clear();
00377 
00378   face_vhandles.push_back(vhandle[2]);
00379   face_vhandles.push_back(vhandle[4]);
00380   face_vhandles.push_back(vhandle[3]);
00381   mesh_.add_face(face_vhandles);
00382 
00383   face_vhandles.clear();
00384 
00385   face_vhandles.push_back(vhandle[2]);
00386   face_vhandles.push_back(vhandle[1]);
00387   face_vhandles.push_back(vhandle[0]);
00388   mesh_.add_face(face_vhandles);
00389 
00390   face_vhandles.clear();
00391 
00392   face_vhandles.push_back(vhandle[0]);
00393   face_vhandles.push_back(vhandle[1]);
00394   face_vhandles.push_back(vhandle[3]);
00395   mesh_.add_face(face_vhandles);
00396 
00397   mesh_.request_vertex_status();
00398   mesh_.request_edge_status();
00399   mesh_.request_face_status();
00400 
00401 
00402   // =============================================
00403   // Collapse halfedge from 0 to 4
00404   // =============================================
00405 
00406   Mesh::HalfedgeHandle heh_collapse1 = mesh_.halfedge_handle(0);
00407 
00408   EXPECT_EQ(4, mesh_.to_vertex_handle(heh_collapse1).idx()   ) << "To   vertex of collapse halfedge 1 is wrong";
00409   EXPECT_EQ(0, mesh_.from_vertex_handle(heh_collapse1).idx() ) << "from vertex of collapse halfedge 1 is wrong";
00410 
00411   EXPECT_TRUE( mesh_.is_collapse_ok(heh_collapse1) ) << "Collapse not ok for collapse first halfedge (0)";
00412   mesh_.collapse(heh_collapse1);
00413 
00414   Mesh::HalfedgeHandle heh_collapse2 = mesh_.halfedge_handle(2);
00415 
00416   EXPECT_EQ(2, mesh_.to_vertex_handle(heh_collapse2).idx()   ) << "To   vertex of collapse halfedge 2 is wrong";
00417   EXPECT_EQ(4, mesh_.from_vertex_handle(heh_collapse2).idx() ) << "from vertex of collapse halfedge 2 is wrong";
00418 
00419   EXPECT_TRUE( mesh_.is_collapse_ok(heh_collapse2) ) << "Collapse not ok for collapse second halfedge (2)";
00420   mesh_.collapse(heh_collapse2);
00421 
00422   Mesh::HalfedgeHandle heh_collapse3 = mesh_.halfedge_handle(6);
00423 
00424   EXPECT_EQ(2, mesh_.to_vertex_handle(heh_collapse3).idx()   ) << "To   vertex of collapse halfedge 3 is wrong";
00425   EXPECT_EQ(3, mesh_.from_vertex_handle(heh_collapse3).idx() ) << "from vertex of collapse halfedge 3 is wrong";
00426 
00427   EXPECT_FALSE( mesh_.is_collapse_ok(heh_collapse3) ) << "Collapse not ok for collapse third halfedge (6)";
00428 
00429 
00430 }
00431 
00432 
00433 #endif // INCLUDE GUARD
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines