Various fixes

This commit is contained in:
Fernando Cacciola 2006-06-29 17:08:41 +00:00
parent d8829ca42d
commit b272b3d6fa
10 changed files with 425 additions and 233 deletions

View File

@ -31,6 +31,13 @@
CGAL_BEGIN_NAMESPACE
template<class Gt, class I, CGAL_HDS_PARAM_, class A>
typename boost::graph_traits< Polyhedron_3<Gt,I,HDS,A> const>::edges_size_type
num_undirected_edges(const Polyhedron_3<Gt,I,HDS,A>& p)
{
return p.size_of_halfedges() / 2 ;
}
//
// Const versions
//

View File

@ -323,7 +323,7 @@ void LindstromTurkImpl<CD>::Extract_triangles_and_link( Triangles& rTriangles, L
if ( v2 != mQ )
{
if ( std::find(rLink.begin(),rLink.end(),v2) == rLink.end() )
CGAL_expensive_assertion ( std::find(rLink.begin(),rLink.end(),v2) == rLink.end() ) ;
rLink.push_back(v2) ;
}
@ -670,6 +670,8 @@ void LindstromTurkImpl<CD>::Constrians::Add_from_gradient ( Matrix const& H, Vec
case 0: Q0 = Vector(- A0.z()/A0.x(),0 ,1 ); break;
case 1: Q0 = Vector(0 ,- A0.z()/A0.y(),1 ); break;
case 2: Q0 = Vector(1 ,0 ,- A0.x()/A0.z()); break;
default : Q0 = NULL_VECTOR ; // This should never happen ;
}
Vector Q1 = cross_product(A0,Q0);

View File

@ -67,6 +67,17 @@ public:
public :
LindstromTurk_collapse_data ( vertex_descriptor const& aP
, vertex_descriptor const& aQ
, bool aIsPFixed
, bool aIsQFixed
, edge_descriptor const& aEdge
, TSM& aSurface
)
:
Base(aP,aQ,aIsPFixed,aIsQFixed,aEdge,aSurface)
{}
LindstromTurk_collapse_data ( vertex_descriptor const& aP
, vertex_descriptor const& aQ
, bool aIsPFixed

View File

@ -149,16 +149,6 @@ CGAL_END_NAMESPACE
# define CGAL_TSMS_TRACE(l,m)
#endif
#ifdef CGAL_SURFACE_SIMPLIFICATION_ENABLE_AUDIT
# define CGAL_TSMS_AUDIT(p,q,e,c,v) CGAL_TSMS_audit(p,q,e,c,v)
#else
# define CGAL_TSMS_AUDIT(p,q,e,c,v)
#endif
#undef CGAL_TSMS_ENABLE_TRACE
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_TSMS_COMMON_H //

View File

@ -46,6 +46,7 @@ template<class TSM_
,class GetCost_
,class GetNewVertexPoint_
,class ShouldStop_
,class VisitorT_
>
class VertexPairCollapse
{
@ -56,6 +57,7 @@ public:
typedef GetCost_ GetCost ;
typedef GetNewVertexPoint_ GetNewVertexPoint ;
typedef ShouldStop_ ShouldStop ;
typedef VisitorT_ VisitorT ;
typedef VertexPairCollapse Self ;
@ -144,6 +146,16 @@ public:
void reset_data( Collapse_data_ptr const& aData ) { mData = aData ; mCostStored = false ; }
void reset_data( vertex_descriptor const& new_p
, vertex_descriptor const& new_q
, bool is_new_p_fixed
, bool is_new_q_fixed
, edge_descriptor const& edge
)
{
reset_data( Collapse_data_ptr( new Collapse_data(new_p,new_q,is_new_p_fixed,is_new_q_fixed,edge,surface()) ) );
}
Collapse_data_ptr data () const { return mData ; }
vertex_descriptor const& p () const { return mData->p() ; }
vertex_descriptor const& q () const { return mData->q() ; }
@ -152,6 +164,8 @@ public:
edge_descriptor const& edge () const { return mData->edge() ; }
TSM& surface () const { return mData->surface() ; }
bool is_edge_fixed() const { return is_p_fixed() && is_q_fixed() ; }
bool is_edge() const
{
edge_descriptor null ;
@ -169,6 +183,7 @@ public:
void reset_PQ_handle() { mPQHandle = null_PQ_handle() ; }
friend bool operator< ( shared_ptr<vertex_pair> const& a, shared_ptr<vertex_pair> const& b )
{
// NOTE: cost() is an optional<> value.
@ -195,10 +210,11 @@ public:
if ( vp.is_p_in_surface() )
out << "V" << vp.p()->ID << " (" << vp.p()->point().x() << "," << vp.p()->point().y() << "," << vp.p()->point().z() << ")" ;
else out << "##p() has been erased## " ;
out << "->" ;
out << ( vp.is_p_fixed() ? "[FIXED] " : "" ) << "->" ;
if ( vp.is_q_in_surface() )
out << " V" << vp.q()->ID << "(" << vp.q()->point().x() << "," << vp.q()->point().y() << "," << vp.q()->point().z() << ")" ;
else out << "##q() has been erased## " ;
out << ( vp.is_q_fixed() ? "[FIXED] " : "" );
if ( vp.is_edge_in_surface() )
out << " E" << vp.edge()->ID ;
else out << "##e() has been erased## " ;
@ -259,6 +275,7 @@ public:
, GetCost const& aGetCost
, GetNewVertexPoint const& aGetVertexPoint
, ShouldStop const& aShouldStop
, VisitorT* aVisitor
, bool aIncludeNonEdgePairs
) ;
@ -270,7 +287,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 const& aPair ) ;
void Update_neighbors( vertex_descriptor const& v ) ;
void Update_neighbors( vertex_pair_ptr const& aCollapsingPair ) ;
vertex_pair_ptr get_pair ( edge_descriptor const& e )
{
@ -337,25 +354,6 @@ private:
return get(is_vertex_fixed,mSurface,v) ;
}
void GetVerticesIsFixedFlags( vertex_descriptor const& p
, vertex_descriptor const& q
, edge_descriptor const& p_q
, bool& aIsPFixed
, bool& aIsQFixed
)
{
if (Is_collapsable(p,q,p_q))
{
aIsPFixed = is_vertex_fixed(p);
aIsQFixed = is_vertex_fixed(q);
}
else
{
aIsPFixed = true ;
aIsQFixed = true ;
}
}
private:
TSM& mSurface ;
@ -365,6 +363,7 @@ private:
GetCost const& Get_cost ;
GetNewVertexPoint const& Get_new_vertex_point ;
ShouldStop const& Should_stop ;
VisitorT* Visitor ;
bool mIncludeNonEdgePairs;

View File

@ -23,13 +23,14 @@ CGAL_BEGIN_NAMESPACE
namespace Triangulated_surface_mesh { namespace Simplification
{
template<class M,class D,class C,class V,class S>
VertexPairCollapse<M,D,C,V,S>::VertexPairCollapse( TSM& aSurface
template<class M,class D,class C,class V,class S, class I>
VertexPairCollapse<M,D,C,V,S,I>::VertexPairCollapse( TSM& aSurface
, GetCollapseData const& aGet_collapse_data
, ParamsToGetCollapseData const* aParamsToGetCollapseData
, GetCost const& aGet_cost
, GetNewVertexPoint const& aGet_new_vertex_point
, ShouldStop const& aShould_stop
, VisitorT* aVisitor
, bool aIncludeNonEdgePairs
)
:
@ -40,15 +41,19 @@ VertexPairCollapse<M,D,C,V,S>::VertexPairCollapse( TSM&
,Get_cost (aGet_cost)
,Get_new_vertex_point(aGet_new_vertex_point)
,Should_stop (aShould_stop)
,Visitor (aVisitor)
,mIncludeNonEdgePairs(aIncludeNonEdgePairs)
{
CGAL_TSMS_TRACE(0,"VertexPairCollapse of TSM with " << num_edges(aSurface)/2 << " edges" );
CGAL_TSMS_TRACE(0,"VertexPairCollapse of TSM with " << num_undirected_edges(aSurface) << " edges" );
}
template<class M,class D,class C,class V,class S>
int VertexPairCollapse<M,D,C,V,S>::run()
template<class M,class D,class C,class V,class S, class I>
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
@ -61,20 +66,35 @@ int VertexPairCollapse<M,D,C,V,S>::run()
}
else
{
mInitialPairCount = mCurrentPairCount = num_edges(mSurface) / 2 ;
if ( Visitor )
Visitor->OnThetrahedronReached(mSurface);
mInitialPairCount = mCurrentPairCount = num_undirected_edges(mSurface) ;
CGAL_TSMS_TRACE(0,"A thetrahedron cannot be simplified any further.");
}
return (int)(mInitialPairCount - mCurrentPairCount) ;
int r = (int)(mInitialPairCount - mCurrentPairCount) ;
if ( Visitor )
Visitor->OnFinished(mSurface);
return r ;
}
template<class M,class D,class C,class V,class S>
void VertexPairCollapse<M,D,C,V,S>::Collect()
template<class M,class D,class C,class V,class S, class I>
void VertexPairCollapse<M,D,C,V,S,I>::Collect()
{
CGAL_TSMS_TRACE(0,"Collecting vertex-pairs...");
// Loop over all the edges in the surface putting the accepted vertex-pairs in the PQ
//
// NOTE: This algorithm requires ALL directed edges to be mapped the corresponding vertex-pair.
// This must be true whether the pair is in the PQ or not
//
//
// Loop over all the edges in the surface putting the corresponding vertex-pairs in the PQ
//
Equal_3 equal_points = Kernel().equal_3_object();
@ -88,13 +108,13 @@ void VertexPairCollapse<M,D,C,V,S>::Collect()
vertex_descriptor s = source(edge,mSurface);
vertex_descriptor t = target(edge,mSurface);
Point_3 sp = get_point(s) ;
Point_3 tp = get_point(t) ;
bool is_s_fixed = is_vertex_fixed(s) ;
bool is_t_fixed = is_vertex_fixed(t) ;
if ( ! equal_points(sp,tp) )
{
bool is_s_fixed, is_t_fixed ;
GetVerticesIsFixedFlags(s,t,edge,is_s_fixed,is_t_fixed);
// All directed edges must be mapped to vertex-pair whether they are put in the PQ or not.
// Thus, degenerate edges are marked as fixed.
if ( s == t || equal_points( get_point(s), get_point(t)) )
is_s_fixed = is_t_fixed = true ;
// The collapse always keeps the vertex 't' and removes vertex 's'.
// If the 's' is fixed (but not t) then swap the pair to keep (the original) 's' correctly fixed.
@ -109,12 +129,14 @@ void VertexPairCollapse<M,D,C,V,S>::Collect()
Collapse_data_ptr lData = Get_collapse_data(s,t,is_s_fixed,is_t_fixed,edge,mSurface,mParamsToGetCollapseData) ;
vertex_pair_ptr lPair( new vertex_pair(lID++,lData,Get_cost) ) ;
set_pair(edge,lPair);
if ( !lPair->is_edge_fixed() )
insert_in_PQ(lPair);
CGAL_TSMS_TRACE(3, (lPair->cost(),*lPair) << " accepted." );
CGAL_TSMS_AUDIT(s,t,edge,lPair->cost(),Get_new_vertex_point(*lPair->data()));
}
}
if ( Visitor )
Visitor->OnCollected(mSurface,s,t,is_s_fixed,is_t_fixed,edge,lPair->cost(),Get_new_vertex_point(*lPair->data()));
CGAL_TSMS_TRACE(3, (lPair->cost(),*lPair) );
}
// TODO: Collect non-edge pairs if requested
@ -123,8 +145,8 @@ void VertexPairCollapse<M,D,C,V,S>::Collect()
CGAL_TSMS_TRACE(0,"Initial pair count: " << mInitialPairCount ) ;
}
template<class M,class D,class C,class V,class S>
void VertexPairCollapse<M,D,C,V,S>::Loop()
template<class M,class D,class C,class V,class S, class I>
void VertexPairCollapse<M,D,C,V,S,I>::Loop()
{
CGAL_TSMS_TRACE(0,"Removing pairs...") ;
@ -135,16 +157,22 @@ void VertexPairCollapse<M,D,C,V,S>::Loop()
{
CGAL_TSMS_TRACE(3,"Poped " << *lPair ) ;
bool lIsCollapsable = false ;
if ( lPair->cost() != none )
{
if ( num_vertices(mSurface) <= 4 )
{
if ( Visitor )
Visitor->OnThetrahedronReached(mSurface);
CGAL_TSMS_TRACE(0,"Thetrahedron reached.");
break ;
}
if ( Should_stop(*lPair->cost(),*lPair->data(),mInitialPairCount,mCurrentPairCount) )
{
if ( Visitor )
Visitor->OnStopConditionReached(mSurface);
CGAL_TSMS_TRACE(0,"Stop condition reached with InitialCount=" << mInitialPairCount
<< " CurrentPairCount=" << mCurrentPairCount
<< " CurrentPair: " << *lPair
@ -152,16 +180,41 @@ void VertexPairCollapse<M,D,C,V,S>::Loop()
break ;
}
lIsCollapsable = Is_collapsable(lPair->p(),lPair->q(),lPair->edge()) ;
if ( !lPair->is_edge_fixed() && lIsCollapsable )
{
Collapse(lPair);
}
else
{
CGAL_TSMS_TRACE(1,*lPair << " NOT Collapsable" );
}
}
else
{
CGAL_TSMS_TRACE(1,*lPair << " uncomputable cost." );
}
if ( Visitor )
Visitor->OnProcessed(mSurface
,lPair->p()
,lPair->q()
,lPair->is_p_fixed()
,lPair->is_q_fixed()
,lPair->edge()
,lPair->cost()
,Get_new_vertex_point(*lPair->data())
,lIsCollapsable
);
}
}
// Some edges are NOT collapsable: doing so would break the topological consistency of the mesh.
// This function returns true if a edge 'p->q' can be collapsed.
//
template<class M,class D,class C,class V,class S>
bool VertexPairCollapse<M,D,C,V,S>::Is_collapsable( vertex_descriptor const& p, vertex_descriptor const& q, edge_descriptor const& p_q )
template<class M,class D,class C,class V,class S, class I>
bool VertexPairCollapse<M,D,C,V,S,I>::Is_collapsable( vertex_descriptor const& p, vertex_descriptor const& q, edge_descriptor const& p_q )
{
bool rR = true ;
@ -172,6 +225,16 @@ bool VertexPairCollapse<M,D,C,V,S>::Is_collapsable( vertex_descriptor const& p,
edge_descriptor q_t = next_edge_cw (q_p,mSurface);
edge_descriptor q_b = next_edge_ccw(q_p,mSurface);
CGAL_TSMS_TRACE(5, "Testing link condition:"
<< "\np_q: V" << source(p_q,mSurface)->id() << "->V" << target(p_q,mSurface)->id()
<< "\nq_p: V" << source(q_p,mSurface)->id() << "->V" << target(q_p,mSurface)->id()
<< "\np_t: V" << source(p_t,mSurface)->id() << "->V" << target(p_t,mSurface)->id()
<< "\np_b: V" << source(p_b,mSurface)->id() << "->V" << target(p_b,mSurface)->id()
<< "\nq_t: V" << source(q_t,mSurface)->id() << "->V" << target(q_t,mSurface)->id()
<< "\nq_n: V" << source(q_b,mSurface)->id() << "->V" << target(q_b,mSurface)->id()
);
// degree(p) and degree(q) >= 3
if ( target(p_t,mSurface) != q
&& target(p_b,mSurface) != q
@ -196,6 +259,12 @@ bool VertexPairCollapse<M,D,C,V,S>::Is_collapsable( vertex_descriptor const& p,
q_tn = next_edge_cw (q_tn,mSurface);
q_bn = next_edge_ccw(q_bn,mSurface);
CGAL_TSMS_TRACE(5, "\n p_tn: V" << source(p_tn,mSurface)->id() << "->V" << target(p_tn,mSurface)->id()
<< "\n q_tn: V" << source(q_tn,mSurface)->id() << "->V" << target(q_tn,mSurface)->id()
<< "\n p_bn: V" << source(p_bn,mSurface)->id() << "->V" << target(p_bn,mSurface)->id()
<< "\n q_bn: V" << source(q_bn,mSurface)->id() << "->V" << target(q_bn,mSurface)->id()
);
if ( target(p_tn,mSurface) == target(q_tn,mSurface)
|| target(p_bn,mSurface) == target(q_bn,mSurface)
)
@ -206,15 +275,23 @@ bool VertexPairCollapse<M,D,C,V,S>::Is_collapsable( vertex_descriptor const& p,
}
while ( p_tn != p_bn && q_tn != q_bn ) ;
}
else rR = false ;
else
{
CGAL_TSMS_TRACE(5, "t and b vertices not shared by p and q");
rR = false ;
}
}
else
{
CGAL_TSMS_TRACE(5, "degree(p) or degree(q) < 3");
rR = false ;
}
else rR = false ;
return rR ;
}
template<class M,class D,class C,class V,class S>
void VertexPairCollapse<M,D,C,V,S>::Collapse( vertex_pair_ptr const& aPair )
template<class M,class D,class C,class V,class S, class I>
void VertexPairCollapse<M,D,C,V,S,I>::Collapse( vertex_pair_ptr const& aPair )
{
CGAL_TSMS_TRACE(1,"Collapsig " << *aPair ) ;
@ -223,7 +300,7 @@ void VertexPairCollapse<M,D,C,V,S>::Collapse( vertex_pair_ptr const& aPair )
CGAL_assertion( lP != lQ );
// This external function is allowed to return an absent point if there is no way to place the vertex
// The external function Get_new_vertex_point() is allowed to return an absent point if there is no way to place the vertex
// satisfying its constrians. In that case the vertex-pair is simply not removed.
Optional_vertex_point_type lNewVertexPoint = Get_new_vertex_point(*aPair->data());
if ( lNewVertexPoint )
@ -242,74 +319,24 @@ void VertexPairCollapse<M,D,C,V,S>::Collapse( vertex_pair_ptr const& aPair )
edge_descriptor lEdgeQB = next_edge_ccw(lEdgeQP,mSurface);
CGAL_TSMS_TRACE(3,"EdgePQ E" << lEdgePQ->ID << " Opposite EdgePQ E" << lEdgePQ->opposite()->ID
<< " V" << lEdgePQ->opposite()->vertex()->ID << "->V" << lEdgePQ->vertex()->ID ) ;
<< " V" << lEdgePQ->opposite()->vertex()->ID << "->V" << lEdgePQ->vertex()->ID
) ;
CGAL_TSMS_TRACE(3,"EdgePT E" << lEdgePT->ID << " Opposite EdgePT E" << lEdgePT->opposite()->ID
<< " V" << lEdgePT->opposite()->vertex()->ID << "->V" << lEdgePT->vertex()->ID ) ;
<< " V" << lEdgePT->opposite()->vertex()->ID << "->V" << lEdgePT->vertex()->ID
) ;
vertex_pair_vector lUpdated ;
// Since vertex P will be removed during the collapse, all cached pairs linked to 'P' (either from or to)
// are updated to link to 'Q' instead.
out_edge_iterator eb, ee ;
for ( boost::tie(eb,ee) = boost::out_edges(lP,mSurface) ; eb != ee ; ++ eb )
{
edge_descriptor outedge = *eb ;
CGAL_TSMS_TRACE(4,"Outedge around V" << lP->ID << " E" << outedge->ID << " Opposite E" << outedge->opposite()->ID
<< " V" << outedge->opposite()->vertex()->ID << "->V" << outedge->vertex()->ID ) ;
if ( outedge != lEdgePQ && outedge != lEdgePT )
{
vertex_pair_ptr lPair = get_pair(outedge);
CGAL_TSMS_TRACE(4,"Updating vertex P in " << *lPair) ;
CGAL_assertion( lPair->p() == lP || lPair->q() == lP );
bool is_v0_fixed, is_v1_fixed ;
vertex_descriptor v0, v1 ;
edge_descriptor edge ;
if ( lPair->p() == lP )
{
v0 = lQ ;
v1 = lPair->q() ;
is_v0_fixed = aPair->is_q_fixed() ;
is_v1_fixed = lPair->is_q_fixed() ;
edge = outedge ;
}
else
{
v0 = lPair->p() ;
v1 = lQ ;
is_v0_fixed = lPair->is_p_fixed() ;
is_v1_fixed = aPair->is_q_fixed() ;
edge = opposite_edge(outedge,mSurface);
}
if ( !Is_collapsable(v0,v1,edge) )
is_v0_fixed = is_v1_fixed = true ;
Collapse_data_ptr lNewData = Get_collapse_data(v0,v1,is_v0_fixed,is_v1_fixed,edge,mSurface,mParamsToGetCollapseData);
lPair->reset_data(lNewData);
lPair->mark() = 1 ;
lUpdated.push_back(lPair);
CGAL_TSMS_TRACE(4,"...after update: " << *lPair ) ;
}
}
// The collapse will remove the following edges from the surface so the corresponding pairs won't be valid anymore.
vertex_pair_ptr lPairPT = get_pair(lEdgePT) ;
// 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 ( lPairPT->is_in_PQ() )
{
CGAL_TSMS_TRACE(2,"Removing from PQ VP" << lPairPT->id() ) ;
CGAL_TSMS_TRACE(2,"Removing VP" << lPairPT->id() << " from PQ" ) ;
remove_from_PQ(lPairPT) ;
}
if ( lPairQB->is_in_PQ() )
{
CGAL_TSMS_TRACE(2,"Removing from PQ VP" << lPairQB->id() ) ;
CGAL_TSMS_TRACE(2,"Removing VP" << lPairQB->id() << " from PQ") ;
remove_from_PQ(lPairQB) ;
}
@ -319,18 +346,22 @@ void VertexPairCollapse<M,D,C,V,S>::Collapse( vertex_pair_ptr const& aPair )
<< " E" << lEdgeQB->ID
);
if ( Visitor )
Visitor->OnCollapsed(mSurface,lP,lEdgePQ,lEdgePT,lEdgeQB);
//
// 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);
// Reset the point of placement of Q (the vertex that "replaces" the collapsed edge)
vertex_point_t vertex_point ;
put(vertex_point,mSurface,lQ,*lNewVertexPoint) ;
// Updates the cost of all pairs in the PQ
Update_neighbors(lQ);
for ( vertex_pair_vector_iterator it = lUpdated.begin(), eit = lUpdated.end() ; it != eit ; ++ it )
(*it)->mark() = 0 ;
Update_neighbors(aPair);
mCurrentPairCount -= 3 ;
}
@ -340,56 +371,70 @@ void VertexPairCollapse<M,D,C,V,S>::Collapse( vertex_pair_ptr const& aPair )
}
}
template<class M,class D,class C,class V,class S>
void VertexPairCollapse<M,D,C,V,S>::Update_neighbors( vertex_descriptor const& v )
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 const& aCollapsingPair )
{
CGAL_TSMS_TRACE(3,"Updating cost of neighboring edges..." ) ;
//
// (A) Collect all pairs to update its cost: all those around each vertex adjacent to v
// (A) Collect all pairs to update its cost: all those around each vertex adjacent to q
//
vertex_pair_vector lToUpdate ;
// (A.1) Loop around all vertices adjacent to v
// (A.1) Loop around all vertices adjacent to q
in_edge_iterator eb1, ee1 ;
for ( tie(eb1,ee1) = in_edges(v,mSurface) ; eb1 != ee1 ; ++ eb1 )
for ( tie(eb1,ee1) = in_edges(aCollapsingPair->q(),mSurface) ; eb1 != ee1 ; ++ eb1 )
{
edge_descriptor edge1 = *eb1 ;
vertex_pair_ptr lPair1 = get_pair(edge1) ;
CGAL_TSMS_TRACE(4,"Inedge around V" << v->ID << " E" << edge1->ID << " Opposite E" << edge1->opposite()->ID
<< " V" << edge1->opposite()->vertex()->ID << "->V" << edge1->vertex()->ID
<< "\n" << *lPair1
) ;
vertex_descriptor adj_v = source(edge1,mSurface);
vertex_descriptor adj_q = 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_v,mSurface) ; eb2 != ee2 ; ++ eb2 )
for ( tie(eb2,ee2) = in_edges(adj_q,mSurface) ; eb2 != ee2 ; ++ eb2 )
{
edge_descriptor edge2 = *eb2 ;
vertex_pair_ptr lPair2 = get_pair(edge2);
vertex_pair_ptr lPair = get_pair(edge2);
CGAL_TSMS_TRACE(4,"Inedge around V" << adj_v->ID << " E" << edge2->ID << " Opposite E" << edge2->opposite()->ID
if ( lPair->p() == aCollapsingPair->p() )
{
CGAL_TSMS_TRACE(4,"Replacing lPair->p() with Q" ) ;
lPair->reset_data(aCollapsingPair->q()
,lPair ->q()
,aCollapsingPair->is_q_fixed()
,lPair ->is_q_fixed()
,source(edge2,mSurface) == aCollapsingPair->q() ? edge2 : opposite_edge(edge2,mSurface)
);
}
else if ( lPair->q() == aCollapsingPair->p() )
{
CGAL_TSMS_TRACE(4,"Replacing lPair->q() with Q" ) ;
lPair->reset_data(lPair ->p()
,aCollapsingPair->q()
,lPair ->is_p_fixed()
,aCollapsingPair->is_q_fixed()
,target(edge2,mSurface) == aCollapsingPair->q() ? edge2 : opposite_edge(edge2,mSurface)
);
}
CGAL_TSMS_TRACE(4,"Inedge around V" << adj_q->ID << " E" << edge2->ID << " Opposite E" << edge2->opposite()->ID
<< " V" << edge2->opposite()->vertex()->ID << "->V" << edge2->vertex()->ID
<< "\n" << *lPair2
<< "\nPair:" << *lPair
) ;
// Only those pairs still in the PQ are update.
// The mark is used because in the way we loop here the same pair is found many times.
if ( lPair2->is_in_PQ() && lPair2->mark() == 0 )
if ( lPair->is_in_PQ() && lPair->mark() == 0 )
{
CGAL_TSMS_TRACE(4,"Pair registered for updating.") ;
lPair2->mark() = 1 ;
lToUpdate.push_back(lPair2);
lPair->mark() = 1 ;
lToUpdate.push_back(lPair);
}
}
}
@ -421,6 +466,7 @@ void VertexPairCollapse<M,D,C,V,S>::Update_neighbors( vertex_descriptor const& v
}
} } // namespace Triangulated_surface_mesh::Simplification
CGAL_END_NAMESPACE

View File

@ -57,25 +57,27 @@ namespace Triangulated_surface_mesh { namespace Simplification
// This global function returns the number of vertex-pairs removed or -1 if there was an error
// (like the surface not being a valid triangulated surface mesh)
//
template<class TSM,class GetCollapseData,class ParamsToGetCollapseData,class GetCost,class GetNewVertexPoint,class ShouldStop>
template<class TSM,class GetCollapseData,class ParamsToGetCollapseData,class GetCost,class GetNewVertexPoint,class ShouldStop, class Visitor>
int vertex_pair_collapse ( TSM& aSurface
, GetCollapseData const& aGet_collapse_data
, ParamsToGetCollapseData const* aParamsToGetCollapseData // Can be NULL
, GetCost const& aGet_cost
, GetNewVertexPoint const& aGet_new_vertex_point
, ShouldStop const& aShould_stop
, Visitor* aVisitor = 0
, bool aIncludeNonEdgePairs = false
)
{
if ( is_valid_triangulated_surface_mesh(aSurface) )
{
typedef VertexPairCollapse<TSM,GetCollapseData,GetCost,GetNewVertexPoint,ShouldStop> Algorithm ;
typedef VertexPairCollapse<TSM,GetCollapseData,GetCost,GetNewVertexPoint,ShouldStop,Visitor> Algorithm ;
Algorithm algorithm(aSurface
,aGet_collapse_data
,aParamsToGetCollapseData
,aGet_cost
,aGet_new_vertex_point
,aShould_stop
,aVisitor
,aIncludeNonEdgePairs
) ;
return algorithm.run();

View File

@ -24,9 +24,10 @@
#include <fstream>
#include <boost/tokenizer.hpp>
#define CGAL_CHECK_EXPENSIVE
//#define CGAL_CHECK_EXPENSIVE
#include <CGAL/Simple_homogeneous.h>
#include <CGAL/Real_timer.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Polyhedron_BGL.h>
#include <CGAL/Polyhedron_extended_BGL.h>
@ -35,8 +36,10 @@
#include <CGAL/IO/Polyhedron_iostream.h>
//#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_LT_TRACE 4
//#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE 3
#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_AUDIT
//#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE 1
#define STATS
//#define AUDIT
void Surface_simplification_external_trace( std::string s )
{
@ -59,7 +62,6 @@ using namespace std ;
using namespace boost ;
using namespace CGAL ;
//typedef Simple_homogeneous<int> Kernel;
typedef Simple_cartesian<double> Kernel;
typedef Kernel::Vector_3 Vector;
typedef Kernel::Point_3 Point;
@ -143,6 +145,9 @@ struct External_polyhedron_get_is_vertex_fixed<Polyhedron>
CGAL_END_NAMESPACE
#ifdef AUDIT
double sCostMatchThreshold = 1e-2 ;
double sVertexMatchThreshold = 1e-2 ;
@ -273,7 +278,7 @@ string to_string( optional<Point> const& p )
else return "NONE" ;
}
void CGAL_TSMS_audit( Vertex_handle const& p
void register_collected_edge( Vertex_handle const& p
, Vertex_handle const& q
, Halfedge_handle const& e
, optional<double> const& cost
@ -312,6 +317,101 @@ void CGAL_TSMS_audit( Vertex_handle const& p
sAuditReport.insert( make_pair(e->ID,lReport) ) ;
}
#endif
#ifdef STATS
int sInitial ;
int sCollected ;
int sProcessed ;
int sCollapsed ;
int sNonCollapsable ;
int sCostUncomputable ;
int sFixed ;
int sRemoved ;
#endif
struct Visitor
{
void OnStarted( Polyhedron& aSurface )
{
#ifdef STATS
sInitial = aSurface.size_of_halfedges() / 2 ;
#endif
}
void OnFinished ( Polyhedron& aSurface )
{
#ifdef STATS
printf("\n");
#endif
}
void OnThetrahedronReached ( Polyhedron& aSurface ) {}
void OnStopConditionReached( Polyhedron& aSurface ) {}
void OnCollected( Polyhedron& aSurface
, Vertex_handle const& aP
, Vertex_handle const& aQ
, bool aIsPFixed
, bool aIsQFixed
, Halfedge_handle const& aEdge
, optional<double> aCost
, optional<Point> aNewVertexPoint
)
{
#ifdef AUDIT
register_collected_edge(aP,aQ,aEdge,aCost,aNewVertexPoint);
#endif
#ifdef STATS
++sCollected ;
printf("\rEdges collected %d",sCollected);
#endif
}
void OnProcessed( Polyhedron& aSurface
, Vertex_handle const& aP
, Vertex_handle const& aQ
, bool aIsPFixed
, bool aIsQFixed
, Halfedge_handle const& aEdge
, optional<double> aCost
, optional<Point> aNewVertexPoint
, bool aIsCollapsable
)
{
#ifdef STATS
if ( sProcessed == 0 )
printf("\n");
++ sProcessed ;
if ( aIsPFixed && aIsQFixed )
++ sFixed ;
else if ( !aIsCollapsable )
{
if ( !aCost )
++ sCostUncomputable ;
else ++ sNonCollapsable ;
}
else
++ sCollapsed;
#endif
}
void OnCollapsed( Polyhedron& aSurface
, Vertex_handle const& aP
, Halfedge_handle const& aPQ
, Halfedge_handle const& aPT
, Halfedge_handle const& aQB
)
{
#ifdef STATS
sRemoved += 3 ;
printf("\r%d%%",((int)(100.0*((double)sRemoved/(double)sInitial))));
#endif
}
} ;
// This is here only to allow a breakpoint to be placed so I can trace back the problem.
void error_handler ( char const* what, char const* expr, char const* file, int line, char const* msg )
@ -331,7 +431,7 @@ char const* matched_alpha ( bool matched )
return matched ? "matched" : "UNMATCHED" ;
}
bool Test ( string name )
bool Test ( int aStop, string name )
{
bool rSucceeded = false ;
@ -339,14 +439,16 @@ bool Test ( string name )
string audit_name = name+string(".audit");
string result_name = name+string(".out.off");
cout << "Testing simplification of surface " << off_name << endl ;
ifstream off_is(off_name.c_str());
if ( off_is )
{
Polyhedron lP;
off_is >> lP ;
scan_OFF(off_is,lP,true);
cout << "Testing Lindstrom Turk simplification of surace with " << (lP.size_of_halfedges()/2) << " edges..." << endl ;
cout << (lP.size_of_halfedges()/2) << " edges..." << endl ;
cout << setprecision(19) ;
@ -362,33 +464,52 @@ bool Test ( string name )
for ( Polyhedron::Facet_iterator fi = lP.facets_begin(); fi != lP.facets_end() ; ++ fi )
fi->ID = lFacetID ++ ;
#ifdef AUDIT
sAuditData .clear();
//ParseAudit(audit_name);
sAuditReport.clear();
ParseAudit(audit_name);
cout << "Audit data loaded." << endl ;
#endif
typedef LindstromTurk_collapse_data<Polyhedron> Collapse_data ;
Construct_LindstromTurk_collapse_data<Collapse_data> Construct_collapse_data ;
LindstromTurk_cost <Collapse_data> Get_cost ;
LindstromTurk_vertex_placement <Collapse_data> Get_vertex_point ;
Count_stop_condition <Collapse_data> Should_stop(0);
Count_stop_condition <Collapse_data> Should_stop(aStop);
Collapse_data::Params lParams;
sAuditReport.clear();
int r = vertex_pair_collapse(lP,Construct_collapse_data,&lParams,Get_cost,Get_vertex_point,Should_stop);
Visitor lVisitor ;
Real_timer t ; t.start();
int r = vertex_pair_collapse(lP,Construct_collapse_data,&lParams,Get_cost,Get_vertex_point,Should_stop,&lVisitor);
t.stop();
ofstream off_out(result_name.c_str(),ios::trunc);
off_out << lP ;
cout << "Finished...\n"
cout << "\nFinished...\n"
<< "Ellapsed time: " << t.time() << " seconds.\n"
<< r << " edges removed.\n"
<< lP.size_of_vertices() << " vertices.\n"
<< (lP.size_of_halfedges()/2) << " edges.\n"
<< lP.size_of_facets() << " triangles.\n"
<< endl
<< lP.size_of_vertices() << " final vertices.\n"
<< (lP.size_of_halfedges()/2) << " final edges.\n"
<< lP.size_of_facets() << " final triangles.\n"
<< ( lP.is_valid() ? " valid\n" : " INVALID!!\n" ) ;
#ifdef STATS
cout << "\n------------STATS--------------\n"
<< sProcessed << " edges processed.\n"
<< sCollapsed << " edges collapsed.\n"
<< sNonCollapsable << " non-collapsable edges.\n"
<< sCostUncomputable << " non-computable edges.\n"
<< sFixed << " fixed edges.\n"
<< sRemoved << " edges removed.\n"
<< (sRemoved/3) << " vertices removed." ;
#endif
#ifdef AUDIT
unsigned lMatches = 0 ;
cout << "Audit report:\n" ;
@ -417,6 +538,10 @@ bool Test ( string name )
}
rSucceeded = ( lMatches == sAuditReport.size() ) ;
#else
rSucceeded = true ;
#endif
}
else
{
@ -431,18 +556,22 @@ int main( int argc, char** argv )
set_error_handler (error_handler);
set_warning_handler(error_handler);
if ( argc > 3 )
{
vector<string> cases ;
for ( int i = 1 ; i < argc ; ++i )
cases.push_back( string(argv[i]) ) ;
int lStop = atoi(argv[1]);
if ( cases.size() == 0 )
cases.push_back( string("data/sample5") ) ;
string lFolder(argv[2]);
lFolder += "/" ;
for ( int i = 3 ; i < argc ; ++i )
cases.push_back( string(argv[i]) ) ;
unsigned lOK = 0 ;
for ( vector<string>::const_iterator it = cases.begin(); it != cases.end() ; ++ it )
{
if ( Test(*it) )
if ( Test( lStop, lFolder + *it) )
++ lOK ;
}
@ -452,5 +581,12 @@ int main( int argc, char** argv )
return lOK == cases.size() ? 0 : 1 ;
}
else
{
cout << "USAGE: LT_edge_collapse_test final_edge_count folder file0 file1 file2 ..." << endl ;
return 1 ;
}
}
// EOF //

View File

@ -9,14 +9,14 @@
<ignoreparts/>
<projectdirectory>.</projectdirectory>
<absoluteprojectpath>false</absoluteprojectpath>
<description></description>
<description/>
</general>
<kdevcustomproject>
<run>
<mainprogram>LT_edge_collapse_test</mainprogram>
<directoryradio>executable</directoryradio>
<directoryradio>build</directoryradio>
<customdirectory>/</customdirectory>
<programargs>data/sample5</programargs>
<programargs>data/elk</programargs>
<terminal>false</terminal>
<autocompile>true</autocompile>
<envvars/>
@ -26,8 +26,8 @@
<numberofjobs>1</numberofjobs>
<prio>0</prio>
<dontact>false</dontact>
<makebin></makebin>
<defaulttarget></defaulttarget>
<makebin/>
<defaulttarget/>
<makeoptions>CGAL_MAKEFILE=/home/fcacciola/Programming/CGAL/make/makefile_i686_Linux-2.6_g++-4.0.2 DEBUGGING=yes</makeoptions>
<selectedenvironment>default</selectedenvironment>
<environments>
@ -36,17 +36,17 @@
</make>
<build>
<buildtool>make</buildtool>
<builddir></builddir>
<builddir/>
</build>
</kdevcustomproject>
<kdevdebugger>
<general>
<dbgshell></dbgshell>
<programargs></programargs>
<gdbpath></gdbpath>
<configGdbScript></configGdbScript>
<runShellScript></runShellScript>
<runGdbScript></runGdbScript>
<dbgshell/>
<programargs>data/hedra</programargs>
<gdbpath/>
<configGdbScript/>
<runShellScript/>
<runGdbScript/>
<breakonloadinglibs>true</breakonloadinglibs>
<separatetty>false</separatetty>
<floatingtoolbar>false</floatingtoolbar>
@ -126,7 +126,7 @@
<headerCompletionDelay>250</headerCompletionDelay>
</codecompletion>
<creategettersetter>
<prefixGet></prefixGet>
<prefixGet/>
<prefixSet>set</prefixSet>
<prefixVariable>m_,_</prefixVariable>
<parameterName>theValue</parameterName>
@ -152,8 +152,8 @@
</cppsupportpart>
<kdevvisualadvance>
<emulator>VisualBoyAdvance</emulator>
<binary></binary>
<addOptions></addOptions>
<binary/>
<addOptions/>
<terminal>false</terminal>
<fullscreen>false</fullscreen>
<graphicFilter>-f0</graphicFilter>

View File

@ -16,8 +16,7 @@ include $(CGAL_MAKEFILE)
CXXFLAGS = -I../../include/\
$(TESTSUITE_CXXFLAGS) \
$(EXTRA_FLAGS) \
$(CGAL_CXXFLAGS) \
$(DEBUG_OPT)
$(CGAL_CXXFLAGS)
#---------------------------------------------------------------------#
# linker flags