From 2cb82ec9b9fbb930632e8d1ee516eb74a2915272 Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Mon, 3 Feb 2020 09:51:17 +0100 Subject: [PATCH] add more unittests for subdivision with deleted elements with and without garbage collection --- src/Unittests/unittests_subdivider_uniform.cc | 403 +++++++++++++++++- 1 file changed, 394 insertions(+), 9 deletions(-) diff --git a/src/Unittests/unittests_subdivider_uniform.cc b/src/Unittests/unittests_subdivider_uniform.cc index 52a0cabc..835c89cf 100644 --- a/src/Unittests/unittests_subdivider_uniform.cc +++ b/src/Unittests/unittests_subdivider_uniform.cc @@ -150,6 +150,135 @@ TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Sqrt3) { } +TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Sqrt3_delete_vertex) { + + for (bool collect_garbage : { false, true }) + { + mesh_.clear(); + + // Request status flags to use delete and garbage collection + mesh_.request_vertex_status(); + mesh_.request_halfedge_status(); + mesh_.request_edge_status(); + mesh_.request_face_status(); + + // Add some vertices + Mesh::VertexHandle vhandle[9]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(0, 2, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(1, 1, 0)); + vhandle[5] = mesh_.add_vertex(Mesh::Point(1, 2, 0)); + vhandle[6] = mesh_.add_vertex(Mesh::Point(2, 0, 0)); + vhandle[7] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[8] = mesh_.add_vertex(Mesh::Point(2, 2, 0)); + + // Add eight faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[4]); + face_vhandles.push_back(vhandle[3]); + + mesh_.add_face(face_vhandles); + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + + mesh_.add_face(face_vhandles); + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[4]); + + mesh_.add_face(face_vhandles); + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[4]); + + mesh_.add_face(face_vhandles); + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[7]); + face_vhandles.push_back(vhandle[6]); + + mesh_.add_face(face_vhandles); + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + face_vhandles.push_back(vhandle[7]); + + mesh_.add_face(face_vhandles); + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[4]); + face_vhandles.push_back(vhandle[8]); + face_vhandles.push_back(vhandle[7]); + + mesh_.add_face(face_vhandles); + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[4]); + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[8]); + + mesh_.add_face(face_vhandles); + + // Test setup: + // 6 === 7 === 8 + // | / | / | + // | / | / | + // | / | / | + // 3 === 4 === 5 + // | / | \ | + // | / | \ | + // | / | \ | + // 0 === 1 === 2 + + // Delete one vertex + mesh_.delete_vertex(vhandle[1]); + // Check setup + if (collect_garbage) + { + mesh_.garbage_collection(); + EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices"; + EXPECT_EQ(6u, mesh_.n_faces() ) << "Wrong number of faces"; + } + else + { + EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices"; + EXPECT_EQ(8u, mesh_.n_faces() ) << "Wrong number of faces"; + } + + + // Initialize subdivider + OpenMesh::Subdivider::Uniform::Sqrt3T sqrt3; + + + // Execute 3 subdivision steps + sqrt3.attach(mesh_); + sqrt3( 3 ); + sqrt3.detach(); + + if (!collect_garbage) + mesh_.garbage_collection(); // if we did not collect garbage before, do so now + + // Check setup + EXPECT_EQ(94u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with sqrt3"; + EXPECT_EQ(162u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with sqrt3"; + } +} + + TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Loop) { mesh_.clear(); @@ -255,6 +384,9 @@ TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Loop) { TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Loop_delete_vertex) { + + for (bool collect_garbage : { false, true }) + { mesh_.clear(); // Request status flags to use delete and garbage collection @@ -345,26 +477,39 @@ TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Loop_delete_vertex) { // | / | \ | // 0 === 1 === 2 - // Delete one vertex mesh_.delete_vertex(vhandle[1]); - mesh_.garbage_collection(); + if (collect_garbage) + { + mesh_.garbage_collection(); + // Check setup + EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices"; + EXPECT_EQ(6u, mesh_.n_faces() ) << "Wrong number of faces"; + } + else + { + // Check setup + EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices"; + EXPECT_EQ(8u, mesh_.n_faces() ) << "Wrong number of faces"; + } // Initialize subdivider OpenMesh::Subdivider::Uniform::LoopT loop; - // Check setup - EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices"; - EXPECT_EQ(6u, mesh_.n_faces() ) << "Wrong number of faces"; // Execute 3 subdivision steps loop.attach(mesh_); loop( 3 ); loop.detach(); + if (!collect_garbage) + mesh_.garbage_collection(); // if we did not collect garbage before, do so now + // Check setup EXPECT_EQ(225u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with loop"; EXPECT_EQ(384u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with loop"; + + } } @@ -454,6 +599,108 @@ TEST_F(OpenMeshSubdividerUniform_Poly, Subdivider_CatmullClark) { EXPECT_EQ(256u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with catmull clark"; } + +TEST_F(OpenMeshSubdividerUniform_Poly, Subdivider_CatmullClark_delete_vertex) { + + for (bool collect_garbage : { false, true }) + { + mesh_.clear(); + + // Request status flags to use delete and garbage collection + mesh_.request_vertex_status(); + mesh_.request_halfedge_status(); + mesh_.request_edge_status(); + mesh_.request_face_status(); + + // Add some vertices + Mesh::VertexHandle vhandle[9]; + + vhandle[0] = mesh_.add_vertex(Mesh::Point(0, 0, 0)); + vhandle[1] = mesh_.add_vertex(Mesh::Point(0, 1, 0)); + vhandle[2] = mesh_.add_vertex(Mesh::Point(0, 2, 0)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(1, 0, 0)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(1, 1, 0)); + vhandle[5] = mesh_.add_vertex(Mesh::Point(1, 2, 0)); + vhandle[6] = mesh_.add_vertex(Mesh::Point(2, 0, 0)); + vhandle[7] = mesh_.add_vertex(Mesh::Point(2, 1, 0)); + vhandle[8] = mesh_.add_vertex(Mesh::Point(2, 2, 0)); + + // Add four faces + std::vector face_vhandles; + + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[4]); + face_vhandles.push_back(vhandle[3]); + + mesh_.add_face(face_vhandles); + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[4]); + + mesh_.add_face(face_vhandles); + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[4]); + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[8]); + face_vhandles.push_back(vhandle[7]); + + mesh_.add_face(face_vhandles); + face_vhandles.clear(); + + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[4]); + face_vhandles.push_back(vhandle[7]); + face_vhandles.push_back(vhandle[6]); + + mesh_.add_face(face_vhandles); + + // Test setup: + // 6 === 7 === 8 + // | | | + // | | | + // | | | + // 3 === 4 === 5 + // | | | + // | | | + // | | | + // 0 === 1 === 2 + + + mesh_.delete_vertex(vhandle[1]); + // Check setup + if (collect_garbage) + { + mesh_.garbage_collection(); + EXPECT_EQ(6u, mesh_.n_vertices() ) << "Wrong number of vertices"; + EXPECT_EQ(2u, mesh_.n_faces() ) << "Wrong number of faces"; + } + else + { + EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices"; + EXPECT_EQ(4u, mesh_.n_faces() ) << "Wrong number of faces"; + } + + // Initialize subdivider + OpenMesh::Subdivider::Uniform::CatmullClarkT catmull; + + // Execute 3 subdivision steps + catmull.attach(mesh_); + catmull( 3 ); + catmull.detach(); + + if (!collect_garbage) + mesh_.garbage_collection(); // if we did not collect garbage before, do so now + + EXPECT_EQ(153u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with catmull clark"; + EXPECT_EQ(128u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with catmull clark"; + } +} + /* Adds a cube to a polymesh */ TEST_F(OpenMeshSubdividerUniform_Poly, Midpoint) { @@ -552,6 +799,129 @@ TEST_F(OpenMeshSubdividerUniform_Poly, Midpoint) { } +TEST_F(OpenMeshSubdividerUniform_Poly, Midpoint_delete_vertex) { + + for (bool collect_garbage : { false, true }) + { + mesh_.clear(); + + // Request status flags to use delete and garbage collection + mesh_.request_vertex_status(); + mesh_.request_halfedge_status(); + mesh_.request_edge_status(); + mesh_.request_face_status(); + + // Add some vertices + Mesh::VertexHandle vhandle[8]; + vhandle[0] = mesh_.add_vertex(PolyMesh::Point(-1, -1, 1)); + vhandle[1] = mesh_.add_vertex(PolyMesh::Point( 1, -1, 1)); + vhandle[2] = mesh_.add_vertex(PolyMesh::Point( 1, 1, 1)); + vhandle[3] = mesh_.add_vertex(PolyMesh::Point(-1, 1, 1)); + vhandle[4] = mesh_.add_vertex(PolyMesh::Point(-1, -1, -1)); + vhandle[5] = mesh_.add_vertex(PolyMesh::Point( 1, -1, -1)); + vhandle[6] = mesh_.add_vertex(PolyMesh::Point( 1, 1, -1)); + vhandle[7] = mesh_.add_vertex(PolyMesh::Point(-1, 1, -1)); + + // Add six faces to form a cube + std::vector face_vhandles; + + face_vhandles.clear(); + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[3]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + face_vhandles.push_back(vhandle[7]); + face_vhandles.push_back(vhandle[6]); + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[4]); + face_vhandles.push_back(vhandle[5]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[1]); + face_vhandles.push_back(vhandle[5]); + face_vhandles.push_back(vhandle[6]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[2]); + face_vhandles.push_back(vhandle[6]); + face_vhandles.push_back(vhandle[7]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + face_vhandles.push_back(vhandle[0]); + face_vhandles.push_back(vhandle[3]); + face_vhandles.push_back(vhandle[7]); + face_vhandles.push_back(vhandle[4]); + mesh_.add_face(face_vhandles); + + + // Test setup: + // + // + // 3 ======== 2 + // / /| + // / / | z + // 0 ======== 1 | | + // | | | | y + // | 7 | 6 | / + // | | / | / + // | |/ |/ + // 4 ======== 5 -------> x + // + + mesh_.delete_vertex(vhandle[1]); + // Check setup + if (collect_garbage) + { + mesh_.garbage_collection(); + EXPECT_EQ(9u, mesh_.n_edges()) << "Wrong number of Edges"; + EXPECT_EQ(18u, mesh_.n_halfedges()) << "Wrong number of HalfEdges"; + EXPECT_EQ(7u, mesh_.n_vertices()) << "Wrong number of vertices"; + EXPECT_EQ(3u, mesh_.n_faces()) << "Wrong number of faces"; + } + else + { + EXPECT_EQ(12u, mesh_.n_edges()) << "Wrong number of Edges"; + EXPECT_EQ(24u, mesh_.n_halfedges()) << "Wrong number of HalfEdges"; + EXPECT_EQ(8u, mesh_.n_vertices()) << "Wrong number of vertices"; + EXPECT_EQ(6u, mesh_.n_faces()) << "Wrong number of faces"; + } + + // Check setup + + // Initialize subdivider + OpenMesh::Subdivider::Uniform::MidpointT midpoint; + + // Execute 2 subdivision steps + midpoint.attach(mesh_); + midpoint(2); + midpoint.detach(); + + if (!collect_garbage) + mesh_.garbage_collection(); // if we did not collect garbage before, do so now + + // Check Result + EXPECT_EQ(15u, mesh_.n_edges()) << "Wrong number of Edges"; + EXPECT_EQ(30u, mesh_.n_halfedges()) << "Wrong number of HalfEdges"; + EXPECT_EQ(12u, mesh_.n_vertices()) << "Wrong number of vertices"; + EXPECT_EQ(4u, mesh_.n_faces()) << "Wrong number of faces"; + } +} + + TEST_F(OpenMeshSubdividerUniform_Triangle, Modified_Butterfly) { mesh_.clear(); @@ -658,6 +1028,9 @@ TEST_F(OpenMeshSubdividerUniform_Triangle, Modified_Butterfly) { TEST_F(OpenMeshSubdividerUniform_Triangle, Modified_Butterfly_delete_vertex) { + + for (bool collect_garbage : { false, true }) + { mesh_.clear(); // Request status flags to use delete and garbage collection @@ -751,23 +1124,35 @@ TEST_F(OpenMeshSubdividerUniform_Triangle, Modified_Butterfly_delete_vertex) { // Delete one vertex mesh_.delete_vertex(vhandle[1]); - mesh_.garbage_collection(); + // Check setup + if (collect_garbage) + { + mesh_.garbage_collection(); + EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices"; + EXPECT_EQ(6u, mesh_.n_faces() ) << "Wrong number of faces"; + } + else + { + EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices"; + EXPECT_EQ(8u, mesh_.n_faces() ) << "Wrong number of faces"; + } // Initialize subdivider OpenMesh::Subdivider::Uniform::ModifiedButterflyT butter; - // Check setup - EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices"; - EXPECT_EQ(6u, mesh_.n_faces() ) << "Wrong number of faces"; // Execute 3 subdivision steps butter.attach(mesh_); butter( 3 ); butter.detach(); + if (!collect_garbage) + mesh_.garbage_collection(); // if we did not collect garbage before, do so now + // Check setup EXPECT_EQ(225u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with butter"; EXPECT_EQ(384u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with butter"; + } }