diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/LoopT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/LoopT.hh index 0fb5d353..f7253c1d 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/LoopT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/LoopT.hh @@ -321,7 +321,7 @@ private: // topological modifiers typename mesh_t::VertexHandle vh1(_m.to_vertex_handle(heh)); typename mesh_t::Point midP(_m.point(_m.to_vertex_handle(heh))); midP += _m.point(_m.to_vertex_handle(opp_heh)); - midP *= 0.5; + midP *= static_cast(0.5); // new vertex vh = _m.new_vertex( midP ); @@ -393,7 +393,7 @@ private: // geometry helper // boundary edge: just average vertex positions if (_m.is_boundary(_eh) ) { - pos *= 0.5; + pos *= static_cast(0.5); } else // inner edge: add neighbouring Vertices to sum { diff --git a/src/OpenMesh/Tools/Subdivider/Uniform/ModifiedButterFlyT.hh b/src/OpenMesh/Tools/Subdivider/Uniform/ModifiedButterFlyT.hh index 96a8f868..61ac23b9 100644 --- a/src/OpenMesh/Tools/Subdivider/Uniform/ModifiedButterFlyT.hh +++ b/src/OpenMesh/Tools/Subdivider/Uniform/ModifiedButterFlyT.hh @@ -356,7 +356,11 @@ private: // topological modifiers _m.set_face_handle( new_heh, _m.face_handle(heh) ); _m.set_halfedge_handle( vh, new_heh); - _m.set_halfedge_handle( _m.face_handle(heh), heh ); + + // We cant reconnect a non existing face, so we skip this here if necessary + if ( !_m.is_boundary(heh) ) + _m.set_halfedge_handle( _m.face_handle(heh), heh ); + _m.set_halfedge_handle( vh1, opp_new_heh ); // Never forget this, when playing with the topology @@ -383,7 +387,7 @@ private: // geometry helper { pos = _m.point(a_0); pos += _m.point(a_1); - pos *= static_cast(9.0/16.0); + pos *= static_cast(9.0/16.0); typename mesh_t::Point tpos; if(_m.is_boundary(heh)) { @@ -396,7 +400,7 @@ private: // geometry helper tpos = _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(opp_heh))); tpos += _m.point(_m.to_vertex_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(opp_heh)))); } - tpos *= static_cast(-1.0/16.0); + tpos *= static_cast(-1.0/16.0); pos += tpos; } else @@ -499,7 +503,7 @@ private: // geometry helper } else //at least one endpoint is [irregular and not in boundary] { - typename mesh_t::Point::value_type normFactor = static_cast(0.0); + RealType normFactor = static_cast(0.0); if(valence_a_0!=6 && !_m.is_boundary(a_0)) { diff --git a/src/Unittests/unittests_subdivider_uniform.cc b/src/Unittests/unittests_subdivider_uniform.cc index 4b21df47..52a0cabc 100644 --- a/src/Unittests/unittests_subdivider_uniform.cc +++ b/src/Unittests/unittests_subdivider_uniform.cc @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -550,4 +551,226 @@ TEST_F(OpenMeshSubdividerUniform_Poly, Midpoint) { EXPECT_EQ(26u, mesh_.n_faces()) << "Wrong number of faces"; } + + +TEST_F(OpenMeshSubdividerUniform_Triangle, Modified_Butterfly) { + mesh_.clear(); + + // 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 + + // Initialize subdivider + OpenMesh::Subdivider::Uniform::ModifiedButterflyT butter; + + // 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 + butter.attach(mesh_); + butter( 3 ); + butter.detach(); + + // Check setup + EXPECT_EQ(289u, mesh_.n_vertices() ) << "Wrong number of vertices after subdivision with loop"; + EXPECT_EQ(512u, mesh_.n_faces() ) << "Wrong number of faces after subdivision with loop"; +} + + + +TEST_F(OpenMeshSubdividerUniform_Triangle, Modified_Butterfly_delete_vertex) { + 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]); + mesh_.garbage_collection(); + + // 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(); + + // 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"; +} + + + + }