update doc + apply changes to the constrained version

This commit is contained in:
Sébastien Loriot 2025-11-06 19:40:48 +01:00
parent 25005a97d8
commit 3c7d507530
1 changed files with 41 additions and 28 deletions

View File

@ -1543,10 +1543,10 @@ does_satisfy_link_condition(typename boost::graph_traits<Graph>::edge_descriptor
* *
* After the collapse of edge `e` the following holds: * After the collapse of edge `e` the following holds:
* - The edge `e` is no longer in `g`. * - 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`. * - `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 `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 not a border halfedge, `p_o_h` is no longer in `g` and is replaced by `o_n_o_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. * - 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`. * - No other incidence information is changed in `g`.
* *
@ -1658,7 +1658,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor e,
* collapses an edge in a graph having non-collapsable edges. * 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`. * 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`, * and guarantees that an edge `e2`, for which `get(edge_is_constrained_map, e2)==true`,
* is not removed after the collapse. * is not removed after the collapse.
* *
@ -1668,14 +1668,14 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor e,
* *
* \returns vertex `v1`. * \returns vertex `v1`.
* \pre This function requires `g` to be an oriented 2-manifold with or without boundaries. * \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. * 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, v0v1)==false`. * \pre `get(edge_is_constrained_map, e)==false`.
* \pre `v0` and `v1` are not both incident to a constrained edge. * \pre `v0` and `v1` are not both incident to a constrained edge.
*/ */
template<typename Graph, typename EdgeIsConstrainedMap> template<typename Graph, typename EdgeIsConstrainedMap>
typename boost::graph_traits<Graph>::vertex_descriptor typename boost::graph_traits<Graph>::vertex_descriptor
collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1, collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor e,
Graph& g, Graph& g,
EdgeIsConstrainedMap Edge_is_constrained_map) EdgeIsConstrainedMap Edge_is_constrained_map)
{ {
@ -1683,11 +1683,11 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
typedef typename Traits::vertex_descriptor vertex_descriptor; typedef typename Traits::vertex_descriptor vertex_descriptor;
typedef typename Traits::halfedge_descriptor halfedge_descriptor; typedef typename Traits::halfedge_descriptor halfedge_descriptor;
CGAL_precondition(is_valid_edge_descriptor(v0v1, g)); CGAL_precondition(is_valid_edge_descriptor(e, g));
CGAL_precondition(does_satisfy_link_condition(v0v1,g)); CGAL_precondition(does_satisfy_link_condition(e,g));
CGAL_precondition(!get(Edge_is_constrained_map, v0v1)); 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 qp = opposite(pq,g);
halfedge_descriptor pt = opposite(prev(pq,g),g); halfedge_descriptor pt = opposite(prev(pq,g),g);
@ -1697,6 +1697,8 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
bool lTopFaceExists = ! is_border(pq,g) ; bool lTopFaceExists = ! is_border(pq,g) ;
bool lBottomFaceExists = ! is_border(qp,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 q = target(pq,g);
vertex_descriptor p = source(pq,g); vertex_descriptor p = source(pq,g);
@ -1707,7 +1709,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
// If the top facet exists, we need to choose one out of the two edges which one disappears: // 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 // p-t if it is not constrained and t-q otherwise
if ( lTopFaceExists ) if ( lTopIsTriangle )
{ {
if ( !get(Edge_is_constrained_map,edge(pt,g)) ) if ( !get(Edge_is_constrained_map,edge(pt,g)) )
{ {
@ -1721,7 +1723,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
// If the bottom facet exists, we need to choose one out of the two edges which one disappears: // 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 // q-b if it is not constrained and b-p otherwise
if ( lBottomFaceExists ) if ( lBottomIsTriangle )
{ {
if ( !get(Edge_is_constrained_map,edge(qb,g)) ) if ( !get(Edge_is_constrained_map,edge(qb,g)) )
{ {
@ -1732,7 +1734,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
} }
} }
if (lTopFaceExists && lBottomFaceExists) if (lTopIsTriangle && lBottomIsTriangle)
{ {
if ( face(edges_to_erase[0],g) == face(edges_to_erase[1],g) if ( face(edges_to_erase[0],g) == face(edges_to_erase[1],g)
&& (! is_border(edges_to_erase[0],g)) ) && (! is_border(edges_to_erase[0],g)) )
@ -1779,7 +1781,7 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
} }
else else
{ {
if (lTopFaceExists) if (lTopIsTriangle)
{ {
if (!(is_border(edges_to_erase[0],g))){ if (!(is_border(edges_to_erase[0],g))){
join_face(edges_to_erase[0],g); join_face(edges_to_erase[0],g);
@ -1794,12 +1796,16 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
remove_face(opposite(edges_to_erase[0],g),g); remove_face(opposite(edges_to_erase[0],g),g);
return q; return q;
} }
else
{
if (lBottomIsTriangle)
{
if (! (is_border(edges_to_erase[0],g))){ if (! (is_border(edges_to_erase[0],g))){
// q will be removed, swap it with p // q will be removed, swap it with p
internal::swap_vertices(p, q, g); internal::swap_vertices(p, q, g);
join_face(edges_to_erase[0],g); join_face(edges_to_erase[0],g);
join_vertex(qp,g); join_vertex(qp,g);
CGAL_assertion(source(qp,g)==p);
return q; return q;
} }
if(!is_border(opposite(next(qp,g),g),g)) if(!is_border(opposite(next(qp,g),g),g))
@ -1810,6 +1816,13 @@ collapse_edge(typename boost::graph_traits<Graph>::edge_descriptor v0v1,
remove_face(opposite(edges_to_erase[0],g),g); remove_face(opposite(edges_to_erase[0],g),g);
return q; return q;
} }
else
{
join_vertex(pq,g);
return q;
}
}
}
} }
/// performs an edge flip, rotating the edge pointed by /// performs an edge flip, rotating the edge pointed by