diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index eb63b9dc6df..11dd34b1922 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -1329,38 +1329,37 @@ flip_edge(typename boost::graph_traits::halfedge_descriptor h, /** * \returns `true` if `e` satisfies the *link condition* \cgalCite{degn-tpec-98}, which guarantees that the surface is also 2-manifold after the edge collapse. */ - template +template bool - does_satisfy_link_condition(typename boost::graph_traits::edge_descriptor e, - Graph& g) +does_satisfy_link_condition(typename boost::graph_traits::edge_descriptor e, + Graph& g) { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef CGAL::Halfedge_around_source_iterator out_edge_iterator; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef CGAL::Halfedge_around_source_iterator out_edge_iterator; - halfedge_descriptor v0_v1 = halfedge(e,g); - halfedge_descriptor v1_v0 = opposite(v0_v1,g); - - vertex_descriptor v0 = target(v1_v0,g), v1 = target(v0_v1,g); + halfedge_descriptor v0_v1 = halfedge(e,g); + halfedge_descriptor v1_v0 = opposite(v0_v1,g); - vertex_descriptor vL = target(next(v0_v1,g),g); - vertex_descriptor vR = target(next(v1_v0,g),g); + vertex_descriptor v0 = target(v1_v0,g), v1 = target(v0_v1,g); - out_edge_iterator eb1, ee1 ; - out_edge_iterator eb2, ee2 ; + vertex_descriptor vL = target(next(v0_v1,g),g); + vertex_descriptor vR = target(next(v1_v0,g),g); + out_edge_iterator eb1, ee1 ; + out_edge_iterator eb2, ee2 ; // The following loop checks the link condition for v0_v1. // Specifically, that for every vertex 'k' adjacent to both 'p and 'q', 'pkq' is a face of the mesh. - // + // for ( boost::tie(eb1,ee1) = halfedges_around_source(v0,g) ; eb1 != ee1 ; ++ eb1 ) { halfedge_descriptor v0_k = *eb1; - + if ( v0_k != v0_v1 ) { vertex_descriptor k = target(v0_k,g); - + for ( boost::tie(eb2,ee2) = halfedges_around_source(k,g) ; eb2 != ee2 ; ++ eb2 ) { halfedge_descriptor k_v1 = *eb2; @@ -1377,66 +1376,53 @@ bool // If k is either t or b then p-q-k *might* be a face of the mesh. It won't be if k==t but p->q is border // or k==b but q->b is a border (because in that case even though there exists triangles p->q->t (or q->p->b) // they are holes, not faces) - // - + // + bool lIsFace = ( vL == k && (! is_border(v0_v1,g)) ) || ( vR == k && (! is_border(v1_v0,g)) ) ; - - if ( !lIsFace ) { // CGAL_ECMS_TRACE(3," k=V" << get(Vertex_index_map,k) << " IS NOT in a face with p-q. NON-COLLAPSABLE edge." ) ; return false ; - } - else + } + else { //CGAL_ECMS_TRACE(4," k=V" << get(Vertex_index_map,k) << " is in a face with p-q") ; } } - } - } - } - - - if ( is_border(v0_v1,g) ) - { - if ( next(next(next(v0_v1,g),g),g) == v0_v1 ) - { - //CGAL_ECMS_TRACE(3," p-q belongs to an open triangle. NON-COLLAPSABLE edge." ) ; - return false ; } } - else if ( is_border(v1_v0,g) ) + } + + // detect isolated triangle (or triangle attached to a mesh with non-manifold vertices) + if (!is_border(v0_v1,g) && is_border(opposite(next(v0_v1,g), g), g) + && is_border(opposite(prev(v0_v1,g), g), g) ) return false; + if (!is_border(v1_v0,g) && is_border(opposite(next(v1_v0,g), g), g) + && is_border(opposite(prev(v1_v0,g), g), g) ) return false; + + if ( !is_border(v0_v1,g) && !is_border(v1_v0,g) ) + { + if ( is_border(v0,g) && is_border(v1,g) ) { - if ( next(next(next(v1_v0,g),g),g) == v1_v0 ) - { - //CGAL_ECMS_TRACE(3," p-q belongs to an open triangle. NON-COLLAPSABLE edge." ) ; - return false ; - } + //CGAL_ECMS_TRACE(3," both p and q are boundary vertices but p-q is not. NON-COLLAPSABLE edge." ) ; + return false ; } else { - if ( is_border(v0,g) && is_border(v1,g) ) + if ( is_tetrahedron(v0_v1,g) ) { - //CGAL_ECMS_TRACE(3," both p and q are boundary vertices but p-q is not. NON-COLLAPSABLE edge." ) ; + //CGAL_ECMS_TRACE(3," p-q belongs to a tetrahedron. NON-COLLAPSABLE edge." ) ; return false ; - } - else + } + if ( next(v0_v1, g) == opposite(prev(v1_v0, g), g) && + prev(v0_v1, g) == opposite(next(v1_v0, g), g) ) { - if ( is_tetrahedron(v0_v1,g) ) - { - //CGAL_ECMS_TRACE(3," p-q belongs to a tetrahedron. NON-COLLAPSABLE edge." ) ; - return false ; - } - if ( next(v0_v1, g) == opposite(prev(v1_v0, g), g) && - prev(v0_v1, g) == opposite(next(v1_v0, g), g) ) - { - //CGAL_ECMS_TRACE(3," degenerate volume." ) ; - return false ; - } + //CGAL_ECMS_TRACE(3," degenerate volume." ) ; + return false ; } } + } return true ; }