diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index 91d7f51fe80..89b58ad0c2b 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -1543,10 +1543,10 @@ does_satisfy_link_condition(typename boost::graph_traits::edge_descriptor * * After the collapse of edge `e` the following holds: * - The edge `e` is no longer in `g`. - * - The faces incident to edge `e` are no longer in `g`. + * - The triangle faces incident to edge `e` are no longer in `g`. * - `v0` is no longer in `g`. - * - If `h` is not a border halfedge, `p_h` is no longer in `g` and is replaced by `o_n_h`. - * - If the opposite of `h` is not a border halfedge, `p_o_h` is no longer in `g` and is replaced by `o_n_o_h`. + * - If `h` is part of a triangle face, `p_h` is no longer in `g` and is replaced by `o_n_h`. + * - If the opposite of `h` is part of a triangle face, `p_o_h` is no longer in `g` and is replaced by `o_n_o_h`. * - The halfedges kept in `g` that had `v0` as target and source now have `v1` as target and source, respectively. * - No other incidence information is changed in `g`. * @@ -1658,7 +1658,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor e, * collapses an edge in a graph having non-collapsable edges. * * Let `h` be the halfedge of `e`, and let `v0` and `v1` be the source and target vertices of `h`. - * Collapses the edge `e` replacing it with `v1`, as described in the paragraph above + * Collapses the edge `e` replacing it with `v1`, as described in the other overload * and guarantees that an edge `e2`, for which `get(edge_is_constrained_map, e2)==true`, * is not removed after the collapse. * @@ -1668,14 +1668,14 @@ collapse_edge(typename boost::graph_traits::edge_descriptor e, * * \returns vertex `v1`. * \pre This function requires `g` to be an oriented 2-manifold with or without boundaries. - * Furthermore, the edge `v0v1` must satisfy the link condition, which guarantees that the surface mesh is also 2-manifold after the edge collapse. - * \pre `get(edge_is_constrained_map, v0v1)==false`. + * Furthermore, the edge `e` must satisfy the link condition, which guarantees that the surface mesh is also 2-manifold after the edge collapse. + * \pre `get(edge_is_constrained_map, e)==false`. * \pre `v0` and `v1` are not both incident to a constrained edge. */ template typename boost::graph_traits::vertex_descriptor -collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, +collapse_edge(typename boost::graph_traits::edge_descriptor e, Graph& g, EdgeIsConstrainedMap Edge_is_constrained_map) { @@ -1683,11 +1683,11 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, typedef typename Traits::vertex_descriptor vertex_descriptor; typedef typename Traits::halfedge_descriptor halfedge_descriptor; - CGAL_precondition(is_valid_edge_descriptor(v0v1, g)); - CGAL_precondition(does_satisfy_link_condition(v0v1,g)); - CGAL_precondition(!get(Edge_is_constrained_map, v0v1)); + CGAL_precondition(is_valid_edge_descriptor(e, g)); + CGAL_precondition(does_satisfy_link_condition(e,g)); + CGAL_precondition(!get(Edge_is_constrained_map, e)); - halfedge_descriptor pq = halfedge(v0v1,g); + halfedge_descriptor pq = halfedge(e,g); halfedge_descriptor qp = opposite(pq,g); halfedge_descriptor pt = opposite(prev(pq,g),g); @@ -1697,6 +1697,8 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, bool lTopFaceExists = ! is_border(pq,g) ; bool lBottomFaceExists = ! is_border(qp,g) ; + bool lTopIsTriangle = lTopFaceExists && is_triangle(pq,g); + bool lBottomIsTriangle = lBottomFaceExists && is_triangle(qp,g); vertex_descriptor q = target(pq,g); vertex_descriptor p = source(pq,g); @@ -1707,7 +1709,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, // If the top facet exists, we need to choose one out of the two edges which one disappears: // p-t if it is not constrained and t-q otherwise - if ( lTopFaceExists ) + if ( lTopIsTriangle ) { if ( !get(Edge_is_constrained_map,edge(pt,g)) ) { @@ -1721,7 +1723,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, // If the bottom facet exists, we need to choose one out of the two edges which one disappears: // q-b if it is not constrained and b-p otherwise - if ( lBottomFaceExists ) + if ( lBottomIsTriangle ) { if ( !get(Edge_is_constrained_map,edge(qb,g)) ) { @@ -1732,7 +1734,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, } } - if (lTopFaceExists && lBottomFaceExists) + if (lTopIsTriangle && lBottomIsTriangle) { if ( face(edges_to_erase[0],g) == face(edges_to_erase[1],g) && (! is_border(edges_to_erase[0],g)) ) @@ -1779,7 +1781,7 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, } else { - if (lTopFaceExists) + if (lTopIsTriangle) { if (!(is_border(edges_to_erase[0],g))){ join_face(edges_to_erase[0],g); @@ -1794,21 +1796,32 @@ collapse_edge(typename boost::graph_traits::edge_descriptor v0v1, remove_face(opposite(edges_to_erase[0],g),g); return q; } - - if (! (is_border(edges_to_erase[0],g))){ - // q will be removed, swap it with p - internal::swap_vertices(p, q, g); - join_face(edges_to_erase[0],g); - join_vertex(qp,g); - return q; - } - if(!is_border(opposite(next(qp,g),g),g)) + else { - // q will be removed, swap it with p - internal::swap_vertices(p, q, g); + if (lBottomIsTriangle) + { + if (! (is_border(edges_to_erase[0],g))){ + // q will be removed, swap it with p + internal::swap_vertices(p, q, g); + join_face(edges_to_erase[0],g); + join_vertex(qp,g); + CGAL_assertion(source(qp,g)==p); + return q; + } + if(!is_border(opposite(next(qp,g),g),g)) + { + // q will be removed, swap it with p + internal::swap_vertices(p, q, g); + } + remove_face(opposite(edges_to_erase[0],g),g); + return q; + } + else + { + join_vertex(pq,g); + return q; + } } - remove_face(opposite(edges_to_erase[0],g),g); - return q; } }