Fixed various bugs in the handling of boundaries

This commit is contained in:
Fernando Cacciola 2006-08-17 17:29:20 +00:00
parent 2ed5292c1e
commit 7fdc391f75
10 changed files with 469 additions and 280 deletions

View File

@ -1,6 +1,7 @@
17 August 2006 Fernando Cacciola
- Fixed various bugs in the handling of boundaries
20 June 2006 Fernando Cacciola
- Bug fixes
- Vertex-evetns replaced by Speudo-split events .
31 March 2006 Fernando Cacciola
- Start

View File

@ -75,6 +75,39 @@ public:
}
};
template<class Gt, class I, CGAL_HDS_PARAM_, class A>
class Polyhedron_vertex_is_border_map : public put_get_helper<bool, Polyhedron_vertex_is_border_map<Gt, I, HDS, A> >
{
private:
typedef CGAL::Polyhedron_3<Gt,I,HDS,A> Polyhedron ;
public:
typedef readable_property_map_tag category;
typedef bool value_type;
typedef bool reference;
typedef typename graph_traits<Polyhedron const>::vertex_descriptor key_type;
Polyhedron_vertex_is_border_map( Polyhedron const& p_) {}
reference operator[](key_type const& v) const
{
typedef typename Polyhedron::Halfedge_around_vertex_const_circulator Halfedge_around_vertex_const_circulator ;
Halfedge_around_vertex_const_circulator cb = v->vertex_begin();
Halfedge_around_vertex_const_circulator c = cb ;
do
{
if ( c->is_border() || c->opposite()->is_border() )
return true ;
++ c ;
}
while ( c != cb ) ;
return false ;
}
};
template<class Gt, class I, CGAL_HDS_PARAM_, class A>
class Polyhedron_vertex_point_map : public put_get_helper< typename Gt::Point_3&, Polyhedron_vertex_point_map<Gt, I, HDS, A> >
{
@ -125,8 +158,9 @@ public:
}
};
struct edge_is_border_t {} ;
struct vertex_point_t {} ;
struct edge_is_border_t {} ;
struct vertex_is_border_t {} ;
struct vertex_point_t {} ;
template<class Gt, class I, CGAL_HDS_PARAM_, class A>
inline
@ -144,6 +178,14 @@ Polyhedron_edge_is_border_map<Gt,I,HDS,A> get(edge_is_border_t, CGAL::Polyhedron
return m;
}
template<class Gt, class I, CGAL_HDS_PARAM_, class A>
inline
Polyhedron_vertex_is_border_map<Gt,I,HDS,A> get(vertex_is_border_t, CGAL::Polyhedron_3<Gt,I,HDS,A> const& p)
{
Polyhedron_vertex_is_border_map<Gt,I,HDS,A> m(p);
return m;
}
template<class Gt, class I, CGAL_HDS_PARAM_, class A>
inline
Polyhedron_vertex_point_map<Gt,I,HDS,A> get(vertex_point_t, CGAL::Polyhedron_3<Gt,I,HDS,A>& p)
@ -185,6 +227,17 @@ struct Polyhedron_property_map<edge_is_border_t>
};
};
template <>
struct Polyhedron_property_map<vertex_is_border_t>
{
template<class Gt, class I, CGAL_HDS_PARAM_, class A>
struct bind_
{
typedef Polyhedron_vertex_is_border_map<Gt,I,HDS,A> type;
typedef Polyhedron_vertex_is_border_map<Gt,I,HDS,A> const_type;
};
};
template <>
struct Polyhedron_property_map<vertex_point_t>
{

View File

@ -27,79 +27,141 @@ namespace Triangulated_surface_mesh { namespace Simplification
//
// collapse_triangulation_edge euler operator (topological operation only).
//
// This operator removes from a triangulation 'aDS' 2 facets, 1 vertex and 3 edges, as follows:
// This operator collapses the edge p-q replacing it with one single vertex connected to the link of p-q.
//
// Consider 2 vertices 'p', 'q', 't' and 'b', such that the edge 'p-q' is shared by two facets
// 'p-q-t' and 'q-p-b', called top and bottom facets resp. (their orientation is unimportant)
// The net effect of the operator is equivalent to removing one of the vertices and re-triangulating the resulting hole.
//
// Consider additional vertices 'l' and 'r' such that
// 'p-t-l' and 'q-r-t' are the other 2 facets adjacent to the top facet, called the top-left and top-right facets, resp.,
// and
// 'l-b-p' and 'b-r-q' are the other 2 facets adjacent to the bottom facet, called the bottom-left and bottom-right facets, resp.
// The actual collapse operation only removes up to 2 faces, 3 edges and 1 vertex, as follows.
//
// In such a triangulated path there is a cycle of vertices around 'p' and 'q' called the "link" of the edge 'p-q'.
// In the minimal case, the link is the unordered cycle of vertices: l-b-r-t. It could also be that 'l' and 'r' are really a
// sequence of vertices instead of just 1 vertex.
// As the link has at least 4 vertices there are at least 6 facets inside the link:
// bottom-left (l-b-p)
// bottom (q-p-b)
// bottom-right (q-b-r)
// top-right (q-r-t)
// top (p-q-t)
// top-left (l-p-t)
// (the vertices are enumerated in an arbiraty order as that is unimportant here)
// The top face, p-q-t, to the left of p->q, if any, is removed.
// The bottom face, q-p-b, to the left of q->p (right of p->q), if any, is removed.
//
// If there is a top-left face, that is, if the edge p->t is NOT a border edge, the top face is removed by joining it
// with the top-left face (this creates a 4 sided face: p-q-t-l).
// If p->t IS a border edge then the top face is simply erased.
//
// If there is a bottom-right face, that is, if the edge q->b is NOT a border edge, the bottom face is removed by joining it
// with the bottom-right face (this creates a 4 sided face: q-p-b-r)
// If q->b IS a border edge then the bottom face is simply erased.
//
// If there is a top face edge p->t is removed.
// If there is a bottom face edge q->b is removed.
//
// The operator is passed 3 DIRECTED edges: 'p-q', 'p-t' and 'q-b' as proceeds with the following 3 steps:
// One of the vertices (p or q) is removed.
// If there is no top-left face so the top face is directly erased AND there is no bottom face,
// that face erasure automatically removes vertex p. Likewise, if there is no bottom-right face
// so the bottom face is directly erased AND there is no top face, that erasure automatically
// removes vertex q.
// Directly erasing the top/bottom faces when the opposite face exists does not removes any vertex
// automatically, in which case vertex p is removed by joining p->q
//
// (1) Merges the top facet with the top-left facet keeping the top-left facet; that is,
// removes the top-facet 'q-p-t', the edge 'p-t' and
// redefines the top-left facet to be 'l-p-q-t' instead of 'l-p-t'.
// NOTES:
//
// (2) Merges the bottom facet with the bottom-right facet keeping the bottom-right facet; that is,
// removes the botton-facet 'q-p-t', the edge 'q-b' and
// redefines the bottom-right facet to be 'r-q-p-b' instead of 'r-q-b'.
// This operator can only be called by collapsable edges (which satisfy the link condition), hence,
// there must exist at least the top face or a bottom face, and, if there is no top-left face there is a top-right face
// and likewise, if there is no bottom-right face there is a bottom-left face. (IOW vertices t/b must have degree >=3
// unless the top/bottom faces do not exists)
//
// (3) Joins the vertices 'p' and 'q' keeping the vertex 'q'; that is
// removes the edge 'p-q' and the vertex 'p' redefining the top-left facet to be 'l-q-t' instead of 'l-p-q-t'
// and the bottom-right facet to be 'r-q-b' instead of 'r-q-p-b'
// The operator doesn't join the top face with the top-left face and the bottom-face with the bottom-left face
// (or both to the right) because if the top-left and bottom-left (or both right) faces are themselve adjacent,
// the first joint would introduce a degree 2 vertex.
// That is why the operator alternates left and right to join the top and bottom faces.
//
// The net result is a valid triangulation but the intermediate results from steps 1 and 2 are not as the top-left
// and bottom-right facets are temporarily 4-sided until 'p' and 'q' is joint.
// PARAMETERS:
// pq : the edge to collapse
// pt : the edge shared between the top face and the top-left face (if any). If there is no top face this parameter is a null handle.
// qb : the edge shared between the bottom face and the bottom-right face. If there is no bottom face this parameter is a null handle.
//
// The operator merges the bottom facets with the bottom-right facet instead of the bottom-left facet becasue in the
// minimal link case (that is, just 'l-b-r-t'), the top-left and bottom-left facets are adjacent, so merging one of
// them prevents the other to be merged becuase doing so would introduce degree-2 vertex (which is illegal in most DS)
//
// The operator is required to erase from the aDS the following: vertex 'p', edges 'pq', 'pt' and 'qb', and
// facets 'pqt' and 'qpb'. It is also required NOT to erase anything else.
//
// The code in this primary template simply forwards the operations to the DS.
// Thus, the DS must support the join_facet(edge) and join_vertex(edge) operations. If not, an specialization is required.
// RETURN VALUE: A handle to the vertex that IS NOT removed.
//
template<class DS_>
struct Collapse_triangulation_edge
{
typedef DS_ DS ;
typedef typename boost::graph_traits<DS>::edge_descriptor edge_descriptor ;
typedef typename boost::graph_traits<DS>::edge_descriptor edge_descriptor ;
typedef typename boost::graph_traits<DS>::vertex_descriptor vertex_descriptor ;
void operator() ( edge_descriptor const& pq
, edge_descriptor const& pt
, edge_descriptor const& qb
, DS& aDS
) const
vertex_descriptor operator() ( edge_descriptor const& pq
, edge_descriptor const& pt
, edge_descriptor const& qb
, DS& aDS
) const
{
CGAL_precondition( pt->vertex()->vertex_degree() >= 3 || qb->vertex()->vertex_degree() >= 3 ) ;
if ( pt->vertex()->vertex_degree() >= 3 )
aDS.join_facet (pt);
edge_descriptor null ;
if ( qb->vertex()->vertex_degree() >= 3 )
aDS.join_facet (qb);
bool lTopFaceExists = pt != null ;
bool lBottomFaceExists = qb != null ;
bool lTopLeftFaceExists = lTopFaceExists && !pt->is_border() ;
bool lBottomRightFaceExists = lBottomFaceExists && !qb->is_border() ;
aDS.join_vertex(pq);
CGAL_precondition( !lTopFaceExists || (lTopFaceExists && ( pt->vertex()->vertex_degree() > 2 ) ) ) ;
CGAL_precondition( !lBottomFaceExists || (lBottomFaceExists && ( qb->vertex()->vertex_degree() > 2 ) ) ) ;
vertex_descriptor q = pq->vertex();
vertex_descriptor p = pq->opposite()->vertex();
CGAL_TSMS_TRACE(3, "Collapsing p-q E" << pq->ID << " (V" << p->ID << "->V" << q->ID << ")" ) ;
bool lP_Erased = false, lQ_Erased = false ;
if ( lTopFaceExists )
{
CGAL_precondition( !pt->opposite()->is_border() ) ; // p-q-t is a face of the mesh
if ( lTopLeftFaceExists )
{
CGAL_TSMS_TRACE(3, "Removing p-t E" << pt->ID << " (V" << p->ID << "->V" << pt->vertex()->ID << ") by joining top-left face" ) ;
aDS.join_facet (pt);
}
else
{
CGAL_TSMS_TRACE(3, "Removing p-t E" << pt->ID << " (V" << p->ID << "->V" << pt->vertex()->ID << ") by erasing top face" ) ;
aDS.erase_facet(pt->opposite());
if ( !lBottomFaceExists )
{
CGAL_TSMS_TRACE(3, "Bottom face doesn't exist so vertex P already removed" ) ;
lP_Erased = true ;
}
}
}
if ( lBottomFaceExists )
{
CGAL_precondition( !qb->opposite()->is_border() ) ; // p-q-b is a face of the mesh
if ( lBottomRightFaceExists )
{
CGAL_TSMS_TRACE(3, "Removing q-b E" << qb->ID << " (V" << q->ID << "->V" << qb->vertex()->ID << ") by joining bottom-right face" ) ;
aDS.join_facet (qb);
}
else
{
CGAL_TSMS_TRACE(3, "Removing q-b E" << qb->ID << " (V" << q->ID << "->V" << qb->vertex()->ID << ") by erasing bottom face" ) ;
aDS.erase_facet(qb->opposite());
if ( !lTopFaceExists )
{
CGAL_TSMS_TRACE(3, "Top face doesn't exist so vertex Q already removed" ) ;
lQ_Erased = true ;
}
}
}
CGAL_assertion( !lP_Erased || !lQ_Erased ) ;
if ( !lP_Erased && !lQ_Erased )
{
CGAL_TSMS_TRACE(3, "Removing vertex P by joining pQ" ) ;
aDS.join_vertex(pq);
lP_Erased = true ;
}
CGAL_expensive_postcondition(aDS.is_valid());
return lP_Erased ? q : p ;
}
} ;

View File

@ -18,7 +18,8 @@
#ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_LINDSTROM_TURK_CORE_H
#define CGAL_SURFACE_MESH_SIMPLIFICATION_LINDSTROM_TURK_CORE_H 1
#include <CGAL/Simple_cartesian.h>
#include <vector>
#include <CGAL/Surface_mesh_simplification/TSMS_common.h>
#include <CGAL/Surface_mesh_simplification/Policies/LindstromTurk_collapse_data.h>
@ -48,6 +49,10 @@ public:
typedef typename Collapse_data::edge_descriptor edge_descriptor ;
typedef typename Collapse_data::Params Params ;
typedef boost::graph_traits<TSM> GraphTraits ;
typedef typename GraphTraits::in_edge_iterator in_edge_iterator ;
typedef typename Surface_geometric_traits<TSM>::Kernel Kernel ;
typedef typename Kernel::Point_3 Point ;
@ -88,23 +93,16 @@ private :
typedef std::vector<Triangle> Triangles ;
typedef std::vector<vertex_descriptor> Link ;
struct Boundary
typedef std::vector<edge_descriptor> edge_descriptor_vector ;
struct BoundaryEdge
{
Boundary ( Vector const& op_
, Vector const& opN_
, Vector const& pq_
, Vector const& pqN_
, Vector const& qr_
, Vector const& qrN_
)
:
op(op_), opN(opN_), pq(pq_), pqN(pqN_), qr(qr_), qrN(qrN_)
{}
Vector op, opN, pq, pqN, qr, qrN ;
BoundaryEdge ( Point s_, Point t_, Vector const& v_, Vector const& n_ ) : s(s_), t(t_), v(v_), n(n_) {}
Point s, t ;
Vector v, n ;
} ;
typedef optional<Boundary> OptionalBoundary ;
typedef std::vector<BoundaryEdge> BoundaryEdges ;
class Constrians
{
@ -129,12 +127,12 @@ private :
private :
void Add_boundary_preservation_constrians( Boundary const& aBdry ) ;
void Add_boundary_preservation_constrians( BoundaryEdges const& aBdry ) ;
void Add_volume_preservation_constrians( Triangles const& aTriangles );
void Add_boundary_and_volume_optimization_constrians( OptionalBoundary const& aBdry, Triangles const& aTriangles ) ;
void Add_boundary_and_volume_optimization_constrians( BoundaryEdges const& aBdry, Triangles const& aTriangles ) ;
void Add_shape_optimization_constrians( Link const& aLink ) ;
FT Compute_boundary_cost( Vector const& v, Boundary const& aBdry ) ;
FT Compute_boundary_cost( Vector const& v, BoundaryEdges const& aBdry ) ;
FT Compute_volume_cost ( Vector const& v, Triangles const& aTriangles ) ;
FT Compute_shape_cost ( Point const& p, Link const& aLink ) ;
@ -195,8 +193,14 @@ private :
void Extract_triangles_and_link( Triangles& rTriangles, Link& rLink );
OptionalBoundary Extract_boundary() ;
void Extract_boundary_edge ( edge_descriptor edge, BoundaryEdges& rBdry ) ;
void Extract_boundary_edges( vertex_descriptor const& v
, edge_descriptor_vector& rCollected
, BoundaryEdges& rBdry
) ;
void Extract_boundary_edges( BoundaryEdges& rBdry ) ;
private:
Params const& mParams ;

View File

@ -20,19 +20,6 @@
CGAL_BEGIN_NAMESPACE
struct G
{
~G()
{
std::cout << "PFixed=" << PFixed << " QFixed=" << QFixed << " Boundary=" << Boundary << std::endl ;
}
int PFixed ;
int QFixed ;
int Boundary ;
} ;
G g ;
//
// Implementation of the strategy from:
//
@ -94,11 +81,9 @@ void LindstromTurkCore<CD>::compute( Collapse_data& rData )
CGAL_TSMS_LT_TRACE(3,"Link: " << s );
#endif
// If the collapsing edge is a boundary edge, the "local boundary" is cached in a Boundary object.
OptionalBoundary lBdry ;
BoundaryEdges lBdry ;
if ( is_undirected_edge_a_border(mP_Q) )
lBdry = Extract_boundary();
Extract_boundary_edges(lBdry);
Point const& lP = get_point(mP) ;
Point const& lQ = get_point(mQ) ;
@ -138,8 +123,8 @@ void LindstromTurkCore<CD>::compute( Collapse_data& rData )
//
// A constrian (Ai,bi) must be alpha-compatible with the previously added constrians (see Paper); if it's not, is discarded.
//
if ( lBdry)
Add_boundary_preservation_constrians(*lBdry);
if ( lBdry.size() > 0 )
Add_boundary_preservation_constrians(lBdry);
if ( mConstrians.n < 3 )
Add_volume_preservation_constrians(lTriangles);
@ -181,13 +166,9 @@ void LindstromTurkCore<CD>::compute( Collapse_data& rData )
CGAL_TSMS_LT_TRACE(1,"Squared edge length: " << lSquaredLength ) ;
FT lBdryCost = 0;
if ( lBdry )
lBdryCost = Compute_boundary_cost(*lOptionalV,*lBdry);
FT lVolumeCost = Compute_volume_cost(*lOptionalV,lTriangles);
FT lShapeCost = Compute_shape_cost(*lOptionalP,lLink);
FT lBdryCost = Compute_boundary_cost(*lOptionalV,lBdry);
FT lVolumeCost = Compute_volume_cost (*lOptionalV,lTriangles);
FT lShapeCost = Compute_shape_cost (*lOptionalP,lLink);
FT lTotalCost = mParams.VolumeWeight * lVolumeCost
+ mParams.BoundaryWeight * lBdryCost * lSquaredLength
@ -201,6 +182,7 @@ void LindstromTurkCore<CD>::compute( Collapse_data& rData )
<< "\nBoundary cost: " << lBdryCost
<< "\nVolume cost: " << lVolumeCost
<< "\nShape cost: " << lShapeCost
<< "\nTOTAL COST: " << lTotalCost
);
}
@ -212,52 +194,58 @@ void LindstromTurkCore<CD>::compute( Collapse_data& rData )
rData = Collapse_data(mP,mQ,mIsPFixed,mIsQFixed,mP_Q,mSurface,lOptionalCost,lOptionalP) ;
}
//
// Caches the "local boundary", that is, the sequence of 3 border edges: o->p, p->q, q->e
//
template<class CD>
typename LindstromTurkCore<CD>::OptionalBoundary LindstromTurkCore<CD>::Extract_boundary()
void LindstromTurkCore<CD>::Extract_boundary_edge( edge_descriptor edge, BoundaryEdges& rBdry )
{
// Since p_q is a boundary edge, one of the previous edges (ccw or cw) is the previous boundary edge
// Likewise, one of the next edges (ccw or cw) is the next boundary edge.
edge_descriptor p_pt = next_edge_ccw(mP_Q,mSurface);
edge_descriptor p_pb = next_edge_cw (mP_Q,mSurface);
edge_descriptor q_qt = next_edge_cw (mQ_P,mSurface);
edge_descriptor q_qb = next_edge_ccw(mQ_P,mSurface);
edge_descriptor face_edge = is_border(edge) ? opposite_edge(edge,mSurface) : edge ;
vertex_descriptor sv = source(face_edge,mSurface);
vertex_descriptor tv = target(face_edge,mSurface);
edge_descriptor border_1 = mP_Q;
edge_descriptor border_0 = is_undirected_edge_a_border(p_pt) ? p_pt : p_pb ;
edge_descriptor border_2 = is_undirected_edge_a_border(q_qt) ? q_qt : q_qb ;
Point const& sp = get_point(sv);
Point const& tp = get_point(tv);
CGAL_assertion(is_undirected_edge_a_border(border_0));
CGAL_assertion(is_undirected_edge_a_border(border_2));
Vector v = tp - sp ;
Vector n = Point_cross_product(tp,sp) ;
CGAL_TSMS_LT_TRACE(3,"Boundary edge. S:" << xyz_to_string(sp) << " T:" << xyz_to_string(tp)
<< " V:" << xyz_to_string(v) << " N:" << xyz_to_string(n)
) ;
rBdry.push_back( BoundaryEdge(sp,tp,v,n) ) ;
}
// opposite(border0)->border1->border2 is the local boundary
vertex_descriptor ov = target(border_0,mSurface);
vertex_descriptor rv = target(border_2,mSurface);
// o->p->q->r is the local boundary
Point const& o = get_point(ov);
Point const& p = get_point(mP);
Point const& q = get_point(mQ);
Point const& r = get_point(rv);
//
// The "Boundary" object caches the boundary as displacement vectors since the code uses that.
//
Vector op = p - o ;
Vector opN = Point_cross_product(p,o);
Vector pq = q - p ;
Vector pqN = Point_cross_product(q,p);
Vector qr = r - q ;
Vector qrN = Point_cross_product(r,q);
return OptionalBoundary(Boundary(op,opN,pq,pqN,qr,qrN)) ;
template<class CD>
void LindstromTurkCore<CD>::Extract_boundary_edges( vertex_descriptor const& v
, edge_descriptor_vector& rCollected
, BoundaryEdges& rBdry
)
{
in_edge_iterator eb, ee ;
for ( tie(eb,ee) = in_edges(v,mSurface) ; eb != ee ; ++ eb )
{
edge_descriptor edge = *eb ;
if ( is_undirected_edge_a_border(edge) && std::find(rCollected.begin(),rCollected.end(),edge) == rCollected.end() )
{
Extract_boundary_edge(edge,rBdry);
rCollected.push_back(edge);
rCollected.push_back(opposite_edge(edge,mSurface));
}
}
}
template<class CD>
void LindstromTurkCore<CD>::Extract_boundary_edges( BoundaryEdges& rBdry )
{
edge_descriptor_vector lCollected ;
Extract_boundary_edges(mP,lCollected,rBdry);
Extract_boundary_edges(mQ,lCollected,rBdry);
}
//
@ -269,8 +257,6 @@ typename LindstromTurkCore<CD>::Triangle LindstromTurkCore<CD>::Get_triangle( ve
, vertex_descriptor const& v2
)
{
CGAL_TSMS_LT_TRACE(3,"Extracting triangle v" << v0->ID << "->v" << v1->ID << "->v" << v2->ID );
Point const& p0 = get_point(v0);
Point const& p1 = get_point(v1);
Point const& p2 = get_point(v2);
@ -282,6 +268,10 @@ typename LindstromTurkCore<CD>::Triangle LindstromTurkCore<CD>::Get_triangle( ve
FT lNormalL = Point_cross_product(p0,p1) * (p2-ORIGIN);
CGAL_TSMS_LT_TRACE(3,"Extracting triangle v" << v0->ID << "->v" << v1->ID << "->v" << v2->ID
<< " N:" << xyz_to_string(lNormalV) << " L:" << lNormalL
);
return Triangle(lNormalV,lNormalL);
}
@ -360,7 +350,11 @@ void LindstromTurkCore<CD>::Extract_triangles_and_link( Triangles& rTriangles, L
e02 = next_edge_ccw(mQ_P,mSurface);
v1 = target(e02,mSurface); // This was added to the link while circulating around mP
v1 = target(e02,mSurface);
// This could have been added to the link while circulating around mP
if ( v1 != mP && std::find(rLink.begin(),rLink.end(),v1) == rLink.end() )
rLink.push_back(v1) ;
e02 = next_edge_ccw(e02,mSurface);
@ -369,7 +363,7 @@ void LindstromTurkCore<CD>::Extract_triangles_and_link( Triangles& rTriangles, L
vertex_descriptor v2 = target(e02,mSurface);
// Any of the vertices found around mP can be reached again around mQ, but we can't duplicate them here.
if ( std::find(rLink.begin(),rLink.end(),v2) == rLink.end() )
if ( v2 != mP && std::find(rLink.begin(),rLink.end(),v2) == rLink.end() )
rLink.push_back(v2) ;
Extract_triangle(v0,v1,v2,e02,rTriangles);
@ -383,18 +377,28 @@ void LindstromTurkCore<CD>::Extract_triangles_and_link( Triangles& rTriangles, L
}
template<class CD>
void LindstromTurkCore<CD>::Add_boundary_preservation_constrians( Boundary const& aBdry )
void LindstromTurkCore<CD>::Add_boundary_preservation_constrians( BoundaryEdges const& aBdry )
{
CGAL_TSMS_LT_TRACE(2,"Adding boundary preservation constrians. ");
Vector e1 = aBdry.op + aBdry.pq + aBdry.qr ;
Vector e3 = aBdry.opN + aBdry.pqN + aBdry.qrN ;
Matrix H = LT_product(e1);
if ( aBdry.size() > 0 )
{
Vector e1 = NULL_VECTOR ;
Vector e2 = NULL_VECTOR ;
for ( typename BoundaryEdges::const_iterator it = aBdry.begin() ; it != aBdry.end() ; ++ it )
{
e1 = e1 + it->v ;
e2 = e2 + it->n ;
}
Vector c = cross_product(e1,e3);
mConstrians.Add_from_gradient(H,c);
CGAL_TSMS_LT_TRACE(2,"Adding boundary preservation constrians. SumV=" << xyz_to_string(e1) << " SumN=" << xyz_to_string(e2) );
Matrix H = LT_product(e1);
Vector c = cross_product(e1,e2);
mConstrians.Add_from_gradient(H,c);
}
}
template<class CD>
@ -407,19 +411,16 @@ void LindstromTurkCore<CD>::Add_volume_preservation_constrians( Triangles const&
for( typename Triangles::const_iterator it = aTriangles.begin(), eit = aTriangles.end() ; it != eit ; ++it )
{
CGAL_TSMS_LT_TRACE(2,"V:" << xyz_to_string(it->NormalV) << ", L:" << it->NormalL);
lSumV = lSumV + it->NormalV ;
lSumL = lSumL + it->NormalL ;
}
mConstrians.Add_if_alpha_compatible(lSumV,lSumL);
}
template<class CD>
void LindstromTurkCore<CD>::Add_boundary_and_volume_optimization_constrians( OptionalBoundary const& aBdry, Triangles const& aTriangles )
void LindstromTurkCore<CD>::Add_boundary_and_volume_optimization_constrians( BoundaryEdges const& aBdry, Triangles const& aTriangles )
{
CGAL_TSMS_LT_TRACE(2,"Adding boundary and volume optimization constrians. ");
@ -438,26 +439,40 @@ void LindstromTurkCore<CD>::Add_boundary_and_volume_optimization_constrians( Opt
c = c - ( lTri.NormalL * lTri.NormalV ) ;
}
CGAL_TSMS_LT_TRACE(3,"Hv:" << matrix_to_string(H) << "\n cv:" << xyz_to_string(c) ) ;
if ( aBdry )
if ( aBdry.size() > 0 )
{
//
// Boundary optimization
//
Matrix Hb = LT_product(aBdry->op) + LT_product(aBdry->pq) + LT_product(aBdry->qr) ;
Matrix Hb = NULL_MATRIX ;
Vector cb = NULL_VECTOR ;
Vector cb = cross_product(aBdry->op,aBdry->opN) + cross_product(aBdry->pq,aBdry->pqN) + cross_product(aBdry->qr,aBdry->qrN);
for ( typename BoundaryEdges::const_iterator it = aBdry.begin() ; it != aBdry.end() ; ++ it )
{
Matrix H = LT_product(it->v);
Vector c = cross_product(it->v,it->n);
Hb += H ;
cb = cb + c ;
}
CGAL_TSMS_LT_TRACE(3,"Hb:" << matrix_to_string(Hb) << "\n cb:" << xyz_to_string(cb) ) ;
//
// Weighted average
//
FT lBoundaryWeight = ( FT(9) * mParams.BoundaryWeight * squared_distance ( get_point(mP), get_point(mQ) ) ) / FT(10) ;
FT lScaledBoundaryWeight = FT(9) * mParams.BoundaryWeight * squared_distance ( get_point(mP), get_point(mQ) ) ;
H *= mParams.VolumeWeight ;
c = c * mParams.VolumeWeight ;
H += lBoundaryWeight * Hb ;
c = c + ( lBoundaryWeight * cb ) ;
H += lScaledBoundaryWeight * Hb ;
c = c + ( lScaledBoundaryWeight * cb ) ;
CGAL_TSMS_LT_TRACE(3,"VolW=" << mParams.VolumeWeight << " BdryW=" << mParams.BoundaryWeight << " ScaledBdryW=" << lScaledBoundaryWeight ) ;
}
@ -467,8 +482,6 @@ void LindstromTurkCore<CD>::Add_boundary_and_volume_optimization_constrians( Opt
template<class CD>
void LindstromTurkCore<CD>::Add_shape_optimization_constrians( Link const& aLink )
{
CGAL_TSMS_LT_TRACE(2,"Add shape optimization constrians. ");
FT s(aLink.size());
Matrix H (s,0,0
@ -481,15 +494,23 @@ void LindstromTurkCore<CD>::Add_shape_optimization_constrians( Link const& aLink
for( typename Link::const_iterator it = aLink.begin(), eit = aLink.end() ; it != eit ; ++it )
c = c + (ORIGIN - get_point(*it)) ;
CGAL_TSMS_LT_TRACE(2,"Adding shape optimization constrians: Shape vector: " << xyz_to_string(c) );
mConstrians.Add_from_gradient(H,c);
}
template<class CD>
typename LindstromTurkCore<CD>::FT
LindstromTurkCore<CD>::Compute_boundary_cost( Vector const& v, Boundary const& aBdry )
LindstromTurkCore<CD>::Compute_boundary_cost( Vector const& v, BoundaryEdges const& aBdry )
{
FT rCost(0);
return rCost ;
for ( typename BoundaryEdges::const_iterator it = aBdry.begin() ; it != aBdry.end() ; ++ it )
{
Vector u = (it->t - ORIGIN ) - v ;
Vector c = cross_product(it->v,u);
rCost += c*c;
}
return rCost / FT(4) ;
}
template<class CD>
@ -632,11 +653,10 @@ void LindstromTurkCore<CD>::Constrians::Add_if_alpha_compatible( Vector const& A
break ;
}
++ n ;
CGAL_TSMS_LT_TRACE(1,"Constrains.A:" << matrix_to_string(A) << "\nConstrains.b:" << xyz_to_string(b) ) ;
}
}
CGAL_TSMS_LT_TRACE(1,"Constrains.A:" << matrix_to_string(A) << "\nConstrains.b:" << xyz_to_string(b) ) ;
}
template<class V>

View File

@ -50,6 +50,7 @@ using boost::in_edges ;
using boost::source ;
using boost::target ;
using boost::edge_is_border_t ;
using boost::vertex_is_border_t ;
using boost::vertex_point_t ;
using boost::cgal_tsms_is_vertex_fixed_t ;
using boost::cgal_tsms_edge_cached_pointer_t ;
@ -146,14 +147,16 @@ CGAL_END_NAMESPACE
#endif
#ifdef CGAL_SURFACE_SIMPLIFICATION_ENABLE_LT_TRACE
# define CGAL_TSMS_LT_TRACE(l,m) if ( l <= CGAL_SURFACE_SIMPLIFICATION_ENABLE_LT_TRACE ) CGAL_TSMS_TRACE_IMPL(m)
# define CGAL_TSMS_LT_TRACE(l,m) if ( (l) <= CGAL_SURFACE_SIMPLIFICATION_ENABLE_LT_TRACE ) CGAL_TSMS_TRACE_IMPL(m)
#else
# define CGAL_TSMS_LT_TRACE(l,m)
#endif
#ifdef CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE
# define CGAL_TSMS_TRACE(l,m) if ( l <= CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE ) CGAL_TSMS_TRACE_IMPL(m)
# define CGAL_TSMS_TRACE_IF(c,l,m) if ( (c) && ( (l) <= CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE) ) CGAL_TSMS_TRACE_IMPL(m)
# define CGAL_TSMS_TRACE(l,m) if ( (l) <= CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE ) CGAL_TSMS_TRACE_IMPL(m)
#else
# define CGAL_TSMS_TRACE_IF(c,l,m)
# define CGAL_TSMS_TRACE(l,m)
#endif

View File

@ -242,7 +242,7 @@ private:
void Loop();
bool Is_collapsable( vertex_descriptor const& p, vertex_descriptor const& q, edge_descriptor const& p_q ) ;
void Collapse( vertex_pair_ptr aPair ) ;
void Update_neighbors( vertex_pair_ptr aCollapsingPair ) ;
void Update_neighbors( vertex_descriptor aRemovedV, vertex_descriptor aKeptV, bool aIsKeptVFixed ) ;
vertex_pair_ptr get_pair ( edge_descriptor const& e )
{
@ -304,10 +304,16 @@ private:
return get(is_vertex_fixed,mSurface,v) ;
}
bool is_border ( vertex_descriptor const& v ) const
{
vertex_is_border_t is_border_vertex_property ;
return get(is_border_vertex_property,mSurface,v) ;
}
bool is_border ( edge_descriptor const& edge ) const
{
edge_is_border_t is_border_property ;
return get(is_border_property,mSurface,edge) ;
edge_is_border_t is_border_edge_property ;
return get(is_border_edge_property,mSurface,edge) ;
}
bool is_undirected_edge_a_border ( edge_descriptor const& edge ) const

View File

@ -48,6 +48,16 @@ VertexPairCollapse<M,D,C,V,S,I>::VertexPairCollapse( TSM&
CGAL_TSMS_TRACE(0,"VertexPairCollapse of TSM with " << num_undirected_edges(aSurface) << " edges" );
CGAL_TSMS_DEBUG_CODE ( mStep = 0 ; )
#ifdef CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE
vertex_iterator vb, ve ;
for ( tie(vb,ve) = vertices(mSurface) ; vb != ve ; ++ vb )
CGAL_TSMS_TRACE(2,"V" << (*vb)->ID << xyz_to_string((*vb)->point()) ) ;
undirected_edge_iterator eb, ee ;
for ( tie(eb,ee) = undirected_edges(mSurface); eb!=ee; ++eb )
CGAL_TSMS_TRACE(2,"E" << (*eb)->ID << " (V" << source((*eb),mSurface)->ID << "-V" << target((*eb),mSurface)->ID << ")" ) ;
#endif
}
template<class M,class D,class C,class V,class S, class I>
@ -55,26 +65,14 @@ int VertexPairCollapse<M,D,C,V,S,I>::run()
{
if ( Visitor )
Visitor->OnStarted(mSurface);
if ( num_vertices(mSurface) > 4 )
{
// First collect all candidate edges in a PQ
Collect();
// Then proceed to collapse each edge in turn
Loop();
// First collect all candidate edges in a PQ
Collect();
CGAL_TSMS_TRACE(0,"Finished: " << (mInitialPairCount - mCurrentPairCount) << " pairs removed." ) ;
}
else
{
if ( Visitor )
Visitor->OnThetrahedronReached(mSurface);
mInitialPairCount = mCurrentPairCount = num_undirected_edges(mSurface) ;
CGAL_TSMS_TRACE(0,"A thetrahedron cannot be simplified any further.");
}
// Then proceed to collapse each edge in turn
Loop();
CGAL_TSMS_TRACE(0,"Finished: " << (mInitialPairCount - mCurrentPairCount) << " pairs removed." ) ;
int r = (int)(mInitialPairCount - mCurrentPairCount) ;
@ -235,11 +233,15 @@ bool VertexPairCollapse<M,D,C,V,S,I>::Is_collapsable( vertex_descriptor const& p
{
bool rR = true ;
std::cout << "testing collapsabilty of p_q=V" << p->ID << "->V" << q->ID << std::endl ;
std::cout << "is p_q border:" << is_border(p_q) << std::endl ;
std::cout << "is q_q border:" << is_border(opposite_edge(p_q,mSurface)) << std::endl ;
std::size_t min = is_undirected_edge_a_border(p_q) ? 3 : 4 ;
CGAL_TSMS_TRACE(3,"Testing collapsabilty of p_q=V" << p->ID << "(%" << p->vertex_degree() << ")"
<< "->V" << q->ID << "(%" << q->vertex_degree() << ")"
);
CGAL_TSMS_TRACE(4, "is p_q border:" << is_border(p_q) );
CGAL_TSMS_TRACE(4, "is q_q border:" << is_border(opposite_edge(p_q,mSurface)) ) ;
bool is_boundary = is_undirected_edge_a_border(p_q) ;
std::size_t min = is_boundary ? 3 : 4 ;
if ( num_vertices(mSurface) > min )
{
out_edge_iterator eb1, ee1 ;
@ -250,8 +252,8 @@ std::cout << "is q_q border:" << is_border(opposite_edge(p_q,mSurface)) << std::
vertex_descriptor t = target(next_edge(p_q,mSurface),mSurface);
vertex_descriptor b = target(next_edge(q_p,mSurface),mSurface);
std::cout << " t=V" << t->ID << std::endl ;
std::cout << " b=V" << b->ID << std::endl ;
CGAL_TSMS_TRACE(4," t=V" << t->ID << "(%" << t->vertex_degree() << ")" );
CGAL_TSMS_TRACE(4," b=V" << b->ID << "(%" << b->vertex_degree() << ")" );
// The following loop checks the link condition for p_q.
// Specifically, that every vertex 'k' adjacent to both 'p and 'q' is a face of the mesh.
@ -270,7 +272,6 @@ std::cout << " b=V" << b->ID << std::endl ;
if ( target(k_l,mSurface) == q )
{
std::cout << " k=V" << k->ID << std::endl ;
// At this point we know p-q-k are connected and we need to determine if this triangle is a face of the mesh.
//
// Since the mesh is known to be triangular there are at most two faces sharing the edge p-q.
@ -286,14 +287,34 @@ std::cout << " k=V" << k->ID << std::endl ;
|| ( b == k && !is_border(q_p) ) ;
if ( !is_face )
{
CGAL_TSMS_TRACE(3," k=V" << k->ID << " IS NOT in a face with p-q. NON-COLLAPSABLE edge." ) ;
rR = false ;
}
else
{
CGAL_TSMS_TRACE(4," k=V" << k->ID << " is in a face with p-q") ;
}
}
}
}
}
}
else rR = false ;
else
{
rR = false ;
CGAL_TSMS_TRACE(3," Surface is irreducible. NON-COLLAPSABLE edge." ) ;
}
if ( rR && !is_boundary )
{
if ( is_border(p) && is_border(q) )
{
rR = false ;
CGAL_TSMS_TRACE(3," both p and q are boundary vertices but p-q is not. NON-COLLAPSABLE edge." ) ;
}
}
return rR ;
}
@ -313,71 +334,94 @@ void VertexPairCollapse<M,D,C,V,S,I>::Collapse( vertex_pair_ptr aPair )
if ( lNewVertexPoint )
{
CGAL_TSMS_TRACE(2,"New vertex point: " << xyz_to_string(*lNewVertexPoint) ) ;
-- mCurrentPairCount ;
// The actual collapse of edge PQ merges the top and bottom facets with its left and right adjacents resp, then
// joins P and Q.
edge_descriptor lEdgePQ = aPair->edge();
edge_descriptor lEdgeQP = opposite_edge(lEdgePQ,mSurface);
//edge_descriptor lEdgePT = next_edge_ccw(lEdgePQ,mSurface);
edge_descriptor lEdgePT = opposite_edge(prev_edge(lEdgePQ,mSurface),mSurface);
// The collapse of P-Q removes the top and bottom facets, if any.
// Edges P-T and P-Q, which are in the top and bottom facets (if they exist), are used by the collapse operator to remove them.
edge_descriptor lEdgeQB = opposite_edge(prev_edge(lEdgeQP,mSurface),mSurface);
// Edges P-T and P-Q are defined only if the top/bottom facets exists
edge_descriptor lEdgePT, lEdgeQB ;
if ( !is_border(lEdgePQ) ) // Exists top facet
lEdgePT = opposite_edge(prev_edge(lEdgePQ,mSurface),mSurface);
if ( !is_border(lEdgeQP) ) // Exists bottom facet
lEdgeQB = opposite_edge(prev_edge(lEdgeQP,mSurface),mSurface);
CGAL_TSMS_TRACE(3,"EdgePQ E" << lEdgePQ->ID
<< "(V" << lEdgePQ->vertex()->ID << "->V" << lEdgePQ->opposite()->vertex()->ID
<< ") EdgeQP E" << lEdgePQ->opposite()->ID
) ;
CGAL_TSMS_TRACE(3,"EdgePT E" << lEdgePT->ID
<< "(V" << lEdgePT->vertex()->ID << "->V" << lEdgePT->opposite()->vertex()->ID
<< ") EdgeTP E" << lEdgePT->opposite()->ID
) ;
CGAL_TSMS_TRACE(3,"EdgeQB E" << lEdgeQB->ID
<< "(V" << lEdgeQB->vertex()->ID << "->V" << lEdgeQB->opposite()->vertex()->ID
<< ") EdgeBQ E" << lEdgeQB->opposite()->ID
<< "(V" << lEdgePQ->vertex()->ID << "->V" << lEdgePQ->opposite()->vertex()->ID
<< ") EdgeQP E" << lEdgePQ->opposite()->ID
) ;
// The collapse will also remove QB so it must be pop off the PQ as well
vertex_pair_ptr lPairQB = get_pair(lEdgeQB) ;
vertex_pair_ptr lPairPT = get_pair(lEdgePT) ;
// If the top/bottom facets exists, they are removed and the edges P-T and Q-B along with them.
// In that case their corresponding pairs must be pop off the queue
if ( lPairPT->is_in_PQ() )
if ( handle_assigned(lEdgePT) )
{
CGAL_TSMS_TRACE(2,"Removing VP" << lPairPT->id() << " from PQ" ) ;
remove_from_PQ(lPairPT) ;
}
if ( lPairQB->is_in_PQ() )
{
CGAL_TSMS_TRACE(2,"Removing VP" << lPairQB->id() << " from PQ") ;
remove_from_PQ(lPairQB) ;
CGAL_TSMS_TRACE(3,"EdgePT E" << lEdgePT->ID
<< "(V" << lEdgePT->vertex()->ID << "->V" << lEdgePT->opposite()->vertex()->ID
<< ") EdgeTP E" << lEdgePT->opposite()->ID
) ;
vertex_pair_ptr lPairPT = get_pair(lEdgePT) ;
if ( lPairPT->is_in_PQ() )
{
CGAL_TSMS_TRACE(2,"Removing VP" << lPairPT->id() << " from PQ" ) ;
remove_from_PQ(lPairPT) ;
-- mCurrentPairCount ;
}
}
CGAL_TSMS_TRACE(1,"Removing from surface V" << lP->ID
<< " E" << lEdgePQ->ID << "(PQ=V" << lP->ID << "->V" << lQ->ID << ")"
<< " E" << lEdgePT->ID << "(PT=V" << lP->ID << "->V" << target(lEdgePT,mSurface)->ID << ")"
<< " E" << lEdgeQB->ID << "(QB=V" << lQ->ID << "->V" << target(lEdgeQB,mSurface)->ID << ")"
);
if ( handle_assigned(lEdgeQB) )
{
CGAL_TSMS_TRACE(3,"EdgeQB E" << lEdgeQB->ID
<< "(V" << lEdgeQB->vertex()->ID << "->V" << lEdgeQB->opposite()->vertex()->ID
<< ") EdgeBQ E" << lEdgeQB->opposite()->ID
) ;
vertex_pair_ptr lPairQB = get_pair(lEdgeQB) ;
if ( lPairQB->is_in_PQ() )
{
CGAL_TSMS_TRACE(2,"Removing VP" << lPairQB->id() << " from PQ") ;
remove_from_PQ(lPairQB) ;
-- mCurrentPairCount ;
}
}
if ( Visitor )
Visitor->OnCollapsed(mSurface,lP,lEdgePQ,lEdgePT,lEdgeQB);
//
CGAL_TSMS_TRACE(1,"Removing:\n P-Q: E" << lEdgePQ->ID << "(V" << lP->ID << "->V" << lQ->ID << ")" );
CGAL_TSMS_TRACE_IF(handle_assigned(lEdgePT),1," P-T: E" << lEdgePT->ID << "(V" << lP->ID << "->V" << target(lEdgePT,mSurface)->ID << ")" ) ;
CGAL_TSMS_TRACE_IF(handle_assigned(lEdgeQB),1," Q-B: E" << lEdgeQB->ID << "(V" << lQ->ID << "->V" << target(lEdgeQB,mSurface)->ID << ")" ) ;
// Perform the actuall collapse.
// This is an external function.
// It's REQUIRED to remove ONLY vertex P and edges PQ,PT and QB, keeping all other edges and
// to relink all directed edges incident to P with Q.
// The algorithm is based on the stability of the remaining edges.
Collapse_triangulation_edge(lEdgePQ,lEdgePT,lEdgeQB,mSurface);
// It's REQUIRED to remove ONLY 1 vertex (P or Q) and edges PQ,PT and QB (PT and QB are removed if they are not null).
// All other edges must be kept.
// All directed edges incident to vertex removed are relink to the vertex kept.
vertex_descriptor lKeptV = Collapse_triangulation_edge(lEdgePQ,lEdgePT,lEdgeQB,mSurface);
// Reset the point of placement of Q (the vertex that "replaces" the collapsed edge)
vertex_descriptor lRemovedV = ( lKeptV == lP ? lQ : lP ) ;
CGAL_TSMS_TRACE(1,"V" << lKeptV->ID << " kept." ) ;
#ifdef CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE
out_edge_iterator eb1, ee1 ;
for ( tie(eb1,ee1) = out_edges(lKeptV,mSurface) ; eb1 != ee1 ; ++ eb1 )
CGAL_TSMS_TRACE(2," E" << (*eb1)->ID << " V" << lKeptV->ID << "->V" << target(*eb1,mSurface)->ID ) ;
#endif
// Reset the point of placement of the kept vertex.
vertex_point_t vertex_point ;
put(vertex_point,mSurface,lQ,*lNewVertexPoint) ;
put(vertex_point,mSurface,lKeptV,*lNewVertexPoint) ;
Update_neighbors(aPair);
mCurrentPairCount -= 3 ;
Update_neighbors(lRemovedV,lKeptV, ( lKeptV == lP ? aPair->is_p_fixed() : aPair->is_q_fixed() ) ) ;
}
else
{
@ -388,66 +432,67 @@ void VertexPairCollapse<M,D,C,V,S,I>::Collapse( vertex_pair_ptr aPair )
}
template<class M,class D,class C,class V,class S, class I>
void VertexPairCollapse<M,D,C,V,S,I>::Update_neighbors( vertex_pair_ptr aCollapsingPair )
void VertexPairCollapse<M,D,C,V,S,I>::Update_neighbors( vertex_descriptor aRemovedV
, vertex_descriptor aKeptV
, bool aIsKeptVFixed
)
{
CGAL_TSMS_TRACE(3,"Updating cost of neighboring edges..." ) ;
//
// (A) Collect all pairs to update its cost: all those around each vertex adjacent to q
// (A) Collect all pairs to update its cost: all those around each vertex adjacent to the vertex kept
//
typedef std::set<vertex_pair_ptr> vertex_pair_set ;
vertex_pair_set lToUpdate ;
// (A.1) Loop around all vertices adjacent to q
// (A.1) Loop around all vertices adjacent to the vertex kept
in_edge_iterator eb1, ee1 ;
for ( tie(eb1,ee1) = in_edges(aCollapsingPair->q(),mSurface) ; eb1 != ee1 ; ++ eb1 )
for ( tie(eb1,ee1) = in_edges(aKeptV,mSurface) ; eb1 != ee1 ; ++ eb1 )
{
edge_descriptor edge1 = *eb1 ;
vertex_descriptor adj_q = source(edge1,mSurface);
vertex_descriptor adj_k = source(edge1,mSurface);
// (A.2) Loop around all edges incident on each adjacent vertex
in_edge_iterator eb2, ee2 ;
for ( tie(eb2,ee2) = in_edges(adj_q,mSurface) ; eb2 != ee2 ; ++ eb2 )
for ( tie(eb2,ee2) = in_edges(adj_k,mSurface) ; eb2 != ee2 ; ++ eb2 )
{
edge_descriptor edge2 = *eb2 ;
vertex_pair_ptr lPair = get_pair(edge2);
if ( lPair->p() == aCollapsingPair->p() )
if ( lPair->p() == aRemovedV )
{
CGAL_TSMS_TRACE(4,"Replacing lPair->p() with V" << aCollapsingPair->q()->id() << "(Q)" ) ;
CGAL_TSMS_TRACE(4,"Replacing lPair->p() with V" << aKeptV->id() << "(Q)" ) ;
CGAL_assertion( aCollapsingPair->q() != lPair->q() ) ;
CGAL_assertion( aKeptV != lPair->q() ) ;
lPair->data().set(aCollapsingPair->q()
,lPair ->q()
,aCollapsingPair->is_q_fixed()
,lPair ->is_q_fixed()
,source(edge2,mSurface) == aCollapsingPair->q() ? edge2 : opposite_edge(edge2,mSurface)
lPair->data().set(aKeptV
,lPair->q()
,aIsKeptVFixed
,lPair->is_q_fixed()
,source(edge2,mSurface) == aKeptV ? edge2 : opposite_edge(edge2,mSurface)
,mSurface
);
}
else if ( lPair->q() == aCollapsingPair->p() )
else if ( lPair->q() == aRemovedV )
{
CGAL_TSMS_TRACE(4,"Replacing lPair->q() with V" << aCollapsingPair->q()->id() << " (Q)" ) ;
CGAL_TSMS_TRACE(4,"Replacing lPair->q() with V" << aKeptV->id() << " (Q)" ) ;
CGAL_assertion( aCollapsingPair->q() != lPair->p() ) ;
CGAL_assertion( aKeptV != lPair->p() ) ;
lPair->data().set(lPair ->p()
,aCollapsingPair->q()
,lPair ->is_p_fixed()
,aCollapsingPair->is_q_fixed()
,target(edge2,mSurface) == aCollapsingPair->q() ? edge2 : opposite_edge(edge2,mSurface)
lPair->data().set(lPair->p()
,aKeptV
,lPair->is_p_fixed()
,aIsKeptVFixed
,target(edge2,mSurface) == aKeptV ? edge2 : opposite_edge(edge2,mSurface)
,mSurface
);
}
CGAL_TSMS_TRACE(4,"Inedge around V" << adj_q->ID << " E" << edge2->ID << " Opposite E" << edge2->opposite()->ID
CGAL_TSMS_TRACE(4,"Inedge around V" << adj_k->ID << " E" << edge2->ID << " Opposite E" << edge2->opposite()->ID
<< " V" << edge2->opposite()->vertex()->ID << "->V" << edge2->vertex()->ID
<< "\nPair:" << *lPair
) ;
@ -471,16 +516,11 @@ void VertexPairCollapse<M,D,C,V,S,I>::Update_neighbors( vertex_pair_ptr aCollaps
{
vertex_pair_ptr lPair = *it ;
//bool lIsPFixed = lPair->p() == aCollapsingPair->q() ? true : lPair->is_p_fixed() ;
//bool lIsQFixed = lPair->q() == aCollapsingPair->q() ? true : lPair->is_q_fixed() ;
bool lIsPFixed = lPair->is_p_fixed() ;
bool lIsQFixed = lPair->is_q_fixed() ;
Set_collapse_data(lPair->data()
,lPair->p()
,lPair->q()
,lIsPFixed
,lIsQFixed
,lPair->is_p_fixed()
,lPair->is_q_fixed()
,lPair->edge()
,lPair->surface()
,mParamsToSetCollapseData

View File

@ -32,7 +32,7 @@
<selectedenvironment>default</selectedenvironment>
<environments>
<default>
<envvar value="-g" name="EXTRA_FLAGS" />
<envvar value="-O2" name="EXTRA_FLAGS" />
</default>
</environments>
</make>

View File

@ -36,9 +36,9 @@
#include <CGAL/Constrained_triangulation_2.h>
//#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_LT_TRACE 4
#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE 1
//#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE 4
//#define STATS
#define STATS
//#define AUDIT
void Surface_simplification_external_trace( std::string s )