handle triangles attached by non-manifold vertices

This commit is contained in:
Sébastien Loriot 2019-01-16 15:24:57 +01:00
parent e0184766d2
commit c697c2086f
1 changed files with 41 additions and 55 deletions

View File

@ -1329,38 +1329,37 @@ flip_edge(typename boost::graph_traits<Graph>::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. * \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<typename Graph> template<typename Graph>
bool bool
does_satisfy_link_condition(typename boost::graph_traits<Graph>::edge_descriptor e, does_satisfy_link_condition(typename boost::graph_traits<Graph>::edge_descriptor e,
Graph& g) Graph& g)
{ {
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
typedef CGAL::Halfedge_around_source_iterator<Graph> out_edge_iterator; typedef CGAL::Halfedge_around_source_iterator<Graph> out_edge_iterator;
halfedge_descriptor v0_v1 = halfedge(e,g); halfedge_descriptor v0_v1 = halfedge(e,g);
halfedge_descriptor v1_v0 = opposite(v0_v1,g); halfedge_descriptor v1_v0 = opposite(v0_v1,g);
vertex_descriptor v0 = target(v1_v0,g), v1 = target(v0_v1,g);
vertex_descriptor vL = target(next(v0_v1,g),g); vertex_descriptor v0 = target(v1_v0,g), v1 = target(v0_v1,g);
vertex_descriptor vR = target(next(v1_v0,g),g);
out_edge_iterator eb1, ee1 ; vertex_descriptor vL = target(next(v0_v1,g),g);
out_edge_iterator eb2, ee2 ; 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. // 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. // 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 ) for ( boost::tie(eb1,ee1) = halfedges_around_source(v0,g) ; eb1 != ee1 ; ++ eb1 )
{ {
halfedge_descriptor v0_k = *eb1; halfedge_descriptor v0_k = *eb1;
if ( v0_k != v0_v1 ) if ( v0_k != v0_v1 )
{ {
vertex_descriptor k = target(v0_k,g); vertex_descriptor k = target(v0_k,g);
for ( boost::tie(eb2,ee2) = halfedges_around_source(k,g) ; eb2 != ee2 ; ++ eb2 ) for ( boost::tie(eb2,ee2) = halfedges_around_source(k,g) ; eb2 != ee2 ; ++ eb2 )
{ {
halfedge_descriptor k_v1 = *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 // 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) // 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) // they are holes, not faces)
// //
bool lIsFace = ( vL == k && (! is_border(v0_v1,g)) ) bool lIsFace = ( vL == k && (! is_border(v0_v1,g)) )
|| ( vR == k && (! is_border(v1_v0,g)) ) ; || ( vR == k && (! is_border(v1_v0,g)) ) ;
if ( !lIsFace ) if ( !lIsFace )
{ {
// CGAL_ECMS_TRACE(3," k=V" << get(Vertex_index_map,k) << " IS NOT in a face with p-q. NON-COLLAPSABLE edge." ) ; // CGAL_ECMS_TRACE(3," k=V" << get(Vertex_index_map,k) << " IS NOT in a face with p-q. NON-COLLAPSABLE edge." ) ;
return false ; return false ;
} }
else else
{ {
//CGAL_ECMS_TRACE(4," k=V" << get(Vertex_index_map,k) << " is in a face with p-q") ; //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," both p and q are boundary vertices but p-q is not. NON-COLLAPSABLE edge." ) ;
{ return false ;
//CGAL_ECMS_TRACE(3," p-q belongs to an open triangle. NON-COLLAPSABLE edge." ) ;
return false ;
}
} }
else 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 ; 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," degenerate volume." ) ;
{ return false ;
//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 ;
}
} }
} }
}
return true ; return true ;
} }