diff --git a/src/OpenMesh/Core/Mesh/PolyConnectivity.cc b/src/OpenMesh/Core/Mesh/PolyConnectivity.cc index 70fb8eca..abf2f9f3 100644 --- a/src/OpenMesh/Core/Mesh/PolyConnectivity.cc +++ b/src/OpenMesh/Core/Mesh/PolyConnectivity.cc @@ -464,6 +464,18 @@ void PolyConnectivity::delete_edge(EdgeHandle _eh, bool _delete_isolated_vertice if (fh0.is_valid()) delete_face(fh0, _delete_isolated_vertices); if (fh1.is_valid()) delete_face(fh1, _delete_isolated_vertices); + + // mark edge deleted if the mesh has a edge status + if ( has_edge_status() ) + status(_eh).set_deleted(true); + + // mark corresponding halfedges as deleted + // As the deleted edge is boundary, + // all corresponding halfedges will also be deleted. + if ( has_halfedge_status() ) { + status(halfedge_handle(_eh, 0)).set_deleted(true); + status(halfedge_handle(_eh, 1)).set_deleted(true); + } } //----------------------------------------------------------------------------- diff --git a/src/Unittests/unittests_trimesh_iterators.hh b/src/Unittests/unittests_trimesh_iterators.hh index 936fb15a..aa5f54e0 100644 --- a/src/Unittests/unittests_trimesh_iterators.hh +++ b/src/Unittests/unittests_trimesh_iterators.hh @@ -427,6 +427,267 @@ TEST_F(OpenMeshIterators, HalfedgeIterSkipping) { EXPECT_TRUE( ok_5 ) << "Non-skipping iterator missed deleted halfedge 5"; } +/* Adds a cube to a trimesh and runs over all halfedges + */ +TEST_F(OpenMeshIterators, HalfedgeIterSkippingLowLevel) { + + mesh_.clear(); + + // Add some vertices + Mesh::VertexHandle vhandle[8]; + vhandle[0] = mesh_.add_vertex(Mesh::Point(-1, -1, 1)); + vhandle[1] = mesh_.add_vertex(Mesh::Point( 1, -1, 1)); + vhandle[2] = mesh_.add_vertex(Mesh::Point( 1, 1, 1)); + vhandle[3] = mesh_.add_vertex(Mesh::Point(-1, 1, 1)); + vhandle[4] = mesh_.add_vertex(Mesh::Point(-1, -1, -1)); + vhandle[5] = mesh_.add_vertex(Mesh::Point( 1, -1, -1)); + vhandle[6] = mesh_.add_vertex(Mesh::Point( 1, 1, -1)); + vhandle[7] = mesh_.add_vertex(Mesh::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[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[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]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + face_vhandles.push_back(vhandle[7]); + 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]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + face_vhandles.push_back(vhandle[1]); + 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]); + 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[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]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + face_vhandles.push_back(vhandle[3]); + 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]); + mesh_.add_face(face_vhandles); + + face_vhandles.clear(); + face_vhandles.push_back(vhandle[0]); + 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(18u, mesh_.n_edges() ) << "Wrong number of Edges"; + EXPECT_EQ(36u, mesh_.n_halfedges() ) << "Wrong number of HalfEdges"; + EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices"; + EXPECT_EQ(12u, mesh_.n_faces() ) << "Wrong number of faces"; + + + // Run over all halfedges + unsigned int heCounter = 0; + + mesh_.request_face_status(); + mesh_.request_vertex_status(); + mesh_.request_halfedge_status(); + + // Get second edge + Mesh::EdgeHandle eh = mesh_.edge_handle(2); + + // Check setup ( No garbage collection, so nothing should change!) + EXPECT_EQ(18u, mesh_.n_edges() ) << "Wrong number of Edges after delete"; + EXPECT_EQ(36u, mesh_.n_halfedges() ) << "Wrong number of HalfEdges after delete"; + EXPECT_EQ(8u, mesh_.n_vertices() ) << "Wrong number of vertices after delete"; + EXPECT_EQ(12u, mesh_.n_faces() ) << "Wrong number of faces after delete"; + + Mesh::HalfedgeIter he_it = mesh_.halfedges_sbegin(); + Mesh::HalfedgeIter he_end = mesh_.halfedges_end(); + + EXPECT_EQ(0, he_it.handle().idx()) << "Wrong start index in halfedge iterator"; + EXPECT_EQ(36, he_end.handle().idx()) << "Wrong end index in halfedge iterator"; + + // ===================================================== + // Try to add low level edge with invalid incidents and + // check skipping iterator + // ===================================================== + + // Add a low level edge without handles + Mesh::EdgeHandle eh_test = mesh_.edge_handle(mesh_.new_edge(Mesh::VertexHandle(),Mesh::VertexHandle())); + + he_it = mesh_.halfedges_sbegin(); + he_end = mesh_.halfedges_end(); + + unsigned int count = 0; + bool found_36 = false; + bool found_37 = false; + + while (he_it != he_end) { + if ( he_it.handle().idx() == 36 ) + found_36 = true; + + if ( he_it.handle().idx() == 37 ) + found_37 = true; + + ++he_it; + ++count; + } + + EXPECT_EQ(38u,count) << "Skipping iterator count error"; + EXPECT_TRUE( found_36 ) << "Skipping iterator missed halfedge 36"; + EXPECT_TRUE( found_37 ) << "Skipping iterator missed halfedge 37"; + + // ===================================================== + // Try to delete one edge with valid incidents and + // check skipping iterator + // ===================================================== + + // delete one edge and recheck (Halfedges 4 and 5) + mesh_.delete_edge(eh); + + he_it = mesh_.halfedges_sbegin(); + he_end = mesh_.halfedges_end(); + + count = 0; + bool found_4 = false; + bool found_5 = false; + found_36 = false; + found_37 = false; + + while (he_it != he_end) { + + if ( he_it.handle().idx() == 4 ) + found_4 = true; + + if ( he_it.handle().idx() == 5 ) + found_5 = true; + + if ( he_it.handle().idx() == 36 ) + found_36 = true; + + if ( he_it.handle().idx() == 37 ) + found_37 = true; + + ++he_it; + ++count; + } + + EXPECT_EQ(36u,count) << "Deleted valid: Skipping iterator count error"; + EXPECT_FALSE( found_4 ) << "Deleted valid: Skipping iterator hit deleted halfedge 4"; + EXPECT_FALSE( found_5 ) << "Deleted valid: Skipping iterator hit deleted halfedge 5"; + EXPECT_TRUE( found_36 ) << "Deleted valid: Skipping iterator missed halfedge 36"; + EXPECT_TRUE( found_37 ) << "Deleted valid: Skipping iterator missed halfedge 37"; + + // ===================================================== + // Try to delete one edge with invalid incidents and + // check skipping iterator + // ===================================================== + + // delete one edge and recheck (Halfedges 4 and 5) + mesh_.delete_edge(eh_test); + + he_it = mesh_.halfedges_sbegin(); + he_end = mesh_.halfedges_end(); + + count = 0; + found_4 = false; + found_5 = false; + found_36 = false; + found_37 = false; + + while (he_it != he_end) { + + if ( he_it.handle().idx() == 4 ) + found_4 = true; + + if ( he_it.handle().idx() == 5 ) + found_5 = true; + + if ( he_it.handle().idx() == 36 ) + found_36 = true; + + if ( he_it.handle().idx() == 37 ) + found_37 = true; + + ++he_it; + ++count; + } + + EXPECT_EQ(34u,count) << "Deleted invalid: Skipping iterator count error"; + EXPECT_FALSE( found_4 ) << "Deleted invalid: Skipping iterator hit deleted halfedge 4"; + EXPECT_FALSE( found_5 ) << "Deleted invalid: Skipping iterator hit deleted halfedge 5"; + EXPECT_FALSE( found_36 ) << "Deleted invalid: Skipping iterator hit deleted halfedge 36"; + EXPECT_FALSE( found_37 ) << "Deleted invalid: Skipping iterator hit deleted halfedge 37"; + +} + /* * Test with a mesh with one deleted face */