OpenMesh
|
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