diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh index 73b1e9f7..bb5965f4 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/MidpointT.hh @@ -13,7 +13,7 @@ namespace Uniform { /** * Midpoint subdivision algorithm. * - * With every step, the set of vertices is replaced with by the midpoints of all + * With every step, the set of vertices is replaced by the midpoints of all * current edges. Then, two sets of faces are created to set up the new * connectivity: From all midpoints of edges surrounding an original face, a new * face is created. Also, for all midpoints of edges surrounding an original @@ -47,6 +47,10 @@ protected: // SubdividerT interface //! @note The _update_points option is ignored bool subdivide(mesh_t& _m, size_t _n, const bool _update_points = true) { + _m.request_halfedge_status(); + _m.request_edge_status(); + _m.request_vertex_status(); + _m.request_face_status(); PropertyManager, mesh_t> edge_midpoint(_m, "edge_midpoint"); PropertyManager, mesh_t> is_original_vertex(_m, "is_original_vertex"); @@ -90,6 +94,7 @@ protected: // SubdividerT interface _m.delete_vertex(vh); } } + _m.garbage_collection(); } return true; } diff --git a/src/Unittests/unittests_subdivider_uniform.cc b/src/Unittests/unittests_subdivider_uniform.cc index d75f0304..b10cc734 100644 --- a/src/Unittests/unittests_subdivider_uniform.cc +++ b/src/Unittests/unittests_subdivider_uniform.cc @@ -3,44 +3,37 @@ #include #include #include +#include namespace { class OpenMeshSubdividerUniform_Poly : public OpenMeshBasePoly { +protected: + // This function is called before each test is run + virtual void SetUp() { + // Do some initial stuff with the member data here... + } - protected: - - // This function is called before each test is run - virtual void SetUp() { - - // Do some initial stuff with the member data here... - } - - // This function is called after all tests are through - virtual void TearDown() { - - // Do some final stuff with the member data here... - } + // This function is called after all tests are through + virtual void TearDown() { + // Do some final stuff with the member data here... + } // Member already defined in OpenMeshBase //Mesh mesh_; }; class OpenMeshSubdividerUniform_Triangle : public OpenMeshBase { +protected: + // This function is called before each test is run + virtual void SetUp() { + // Do some initial stuff with the member data here... + } - protected: - - // This function is called before each test is run - virtual void SetUp() { - - // Do some initial stuff with the member data here... - } - - // This function is called after all tests are through - virtual void TearDown() { - - // Do some final stuff with the member data here... - } + // This function is called after all tests are through + virtual void TearDown() { + // Do some final stuff with the member data here... + } // Member already defined in OpenMeshBase //Mesh mesh_; @@ -52,110 +45,106 @@ class OpenMeshSubdividerUniform_Triangle : public OpenMeshBase { * ==================================================================== */ -/* - */ -TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Loop) { +TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Sqrt3) { + mesh_.clear(); - mesh_.clear(); + // Add some vertices + Mesh::VertexHandle vhandle[9]; - // 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)); - 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; - // 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]); - 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(); - 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]); - 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(); - 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]); - 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(); - 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]); - 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(); - 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]); - 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(); - 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[3]); - face_vhandles.push_back(vhandle[4]); - face_vhandles.push_back(vhandle[7]); + mesh_.add_face(face_vhandles); + face_vhandles.clear(); - 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]); - 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(); - 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[4]); - face_vhandles.push_back(vhandle[5]); - face_vhandles.push_back(vhandle[8]); + mesh_.add_face(face_vhandles); - mesh_.add_face(face_vhandles); + // Test setup: + // 6 === 7 === 8 + // | / | / | + // | / | / | + // | / | / | + // 3 === 4 === 5 + // | / | \ | + // | / | \ | + // | / | \ | + // 0 === 1 === 2 - // Test setup: - // 6 === 7 === 8 - // | / | / | - // | / | / | - // | / | / | - // 3 === 4 === 5 - // | / | \ | - // | / | \ | - // | / | \ | - // 0 === 1 === 2 + // Initialize subdivider + OpenMesh::Subdivider::Uniform::Sqrt3T sqrt3; - // Initialize subdivider - OpenMesh::Subdivider::Uniform::Sqrt3T sqrt3; + // Check setup + EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices"; + EXPECT_EQ(8u, mesh_.n_faces() ) << "Wrong number of faces"; - // Check setup - EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices"; - EXPECT_EQ(8u, mesh_.n_faces() ) << "Wrong number of faces"; - - // Execute 3 subdivision steps - sqrt3.attach(mesh_); - sqrt3( 3 ); - sqrt3.detach(); - - // Check setup - EXPECT_EQ(121u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with sqrt3"; - EXPECT_EQ(216u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with sqrt3"; + // Execute 3 subdivision steps + sqrt3.attach(mesh_); + sqrt3( 3 ); + sqrt3.detach(); + // Check setup + EXPECT_EQ(121u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with sqrt3"; + EXPECT_EQ(216u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with sqrt3"; } /* @@ -167,81 +156,177 @@ TEST_F(OpenMeshSubdividerUniform_Triangle, Subdivider_Loop) { /* */ TEST_F(OpenMeshSubdividerUniform_Poly, Subdivider_CatmullClark) { + mesh_.clear(); - mesh_.clear(); + // Add some vertices + Mesh::VertexHandle vhandle[9]; - // 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)); - 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; - // 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]); - 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(); - 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]); - 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(); - 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]); - 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(); - 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]); - 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); - mesh_.add_face(face_vhandles); + // Test setup: + // 6 === 7 === 8 + // | | | + // | | | + // | | | + // 3 === 4 === 5 + // | | | + // | | | + // | | | + // 0 === 1 === 2 - // Test setup: - // 6 === 7 === 8 - // | | | - // | | | - // | | | - // 3 === 4 === 5 - // | | | - // | | | - // | | | - // 0 === 1 === 2 + // Initialize subdivider + OpenMesh::Subdivider::Uniform::CatmullClarkT catmull; - // Initialize subdivider - OpenMesh::Subdivider::Uniform::CatmullClarkT catmull; + // Check setup + EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices"; + EXPECT_EQ(4u, mesh_.n_faces() ) << "Wrong number of faces"; - // Check setup - EXPECT_EQ(9u, mesh_.n_vertices() ) << "Wrong number of vertices"; - EXPECT_EQ(4u, mesh_.n_faces() ) << "Wrong number of faces"; + // Execute 3 subdivision steps + catmull.attach(mesh_); + catmull( 3 ); + catmull.detach(); - // Execute 3 subdivision steps - catmull.attach(mesh_); - catmull( 3 ); - catmull.detach(); + EXPECT_EQ(289u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with catmull clark"; + EXPECT_EQ(256u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with catmull clark"; +} - EXPECT_EQ(289u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with catmull clark"; - EXPECT_EQ(256u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with catmull clark"; +/* Adds a cube to a polymesh + */ +TEST_F(OpenMeshSubdividerUniform_Poly, Midpoint) { + mesh_.clear(); + + // 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 + // + + // Check setup + 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"; + + // Initialize subdivider + OpenMesh::Subdivider::Uniform::MidpointT midpoint; + + // Execute 2 subdivision steps + midpoint.attach(mesh_); + midpoint(2); + midpoint.detach(); + + // Check Result + EXPECT_EQ(48u, mesh_.n_edges()) << "Wrong number of Edges"; + EXPECT_EQ(96u, mesh_.n_halfedges()) << "Wrong number of HalfEdges"; + EXPECT_EQ(24u, mesh_.n_vertices()) << "Wrong number of vertices"; + EXPECT_EQ(26u, mesh_.n_faces()) << "Wrong number of faces"; +} } -}