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 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 // Const versions
// //

View File

@ -323,8 +323,8 @@ void LindstromTurkImpl<CD>::Extract_triangles_and_link( Triangles& rTriangles, L
if ( v2 != mQ ) 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) ; rLink.push_back(v2) ;
} }
Extract_triangle(v0,v1,v2,e02,rTriangles); Extract_triangle(v0,v1,v2,e02,rTriangles);
@ -664,12 +664,14 @@ void LindstromTurkImpl<CD>::Constrians::Add_from_gradient ( Matrix const& H, Vec
, A0.z()*A0.z() , A0.z()*A0.z()
); );
Vector Q0 ; Vector Q0;
switch ( index_of_max_component(A02) ) switch ( index_of_max_component(A02) )
{ {
case 0: Q0 = Vector(- A0.z()/A0.x(),0 ,1 ); break; case 0: Q0 = Vector(- A0.z()/A0.x(),0 ,1 ); break;
case 1: Q0 = Vector(0 ,- A0.z()/A0.y(),1 ); break; case 1: Q0 = Vector(0 ,- A0.z()/A0.y(),1 ); break;
case 2: Q0 = Vector(1 ,0 ,- A0.x()/A0.z()); 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); Vector Q1 = cross_product(A0,Q0);

View File

@ -67,6 +67,17 @@ public:
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 LindstromTurk_collapse_data ( vertex_descriptor const& aP
, vertex_descriptor const& aQ , vertex_descriptor const& aQ
, bool aIsPFixed , bool aIsPFixed

View File

@ -149,16 +149,6 @@ CGAL_END_NAMESPACE
# define CGAL_TSMS_TRACE(l,m) # define CGAL_TSMS_TRACE(l,m)
#endif #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 #undef CGAL_TSMS_ENABLE_TRACE
#endif // CGAL_SURFACE_MESH_SIMPLIFICATION_TSMS_COMMON_H // #endif // CGAL_SURFACE_MESH_SIMPLIFICATION_TSMS_COMMON_H //

View File

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

View File

@ -23,15 +23,16 @@ CGAL_BEGIN_NAMESPACE
namespace Triangulated_surface_mesh { namespace Simplification namespace Triangulated_surface_mesh { namespace Simplification
{ {
template<class M,class D,class C,class V,class S> template<class M,class D,class C,class V,class S, class I>
VertexPairCollapse<M,D,C,V,S>::VertexPairCollapse( TSM& aSurface VertexPairCollapse<M,D,C,V,S,I>::VertexPairCollapse( TSM& aSurface
, GetCollapseData const& aGet_collapse_data , GetCollapseData const& aGet_collapse_data
, ParamsToGetCollapseData const* aParamsToGetCollapseData , ParamsToGetCollapseData const* aParamsToGetCollapseData
, GetCost const& aGet_cost , GetCost const& aGet_cost
, GetNewVertexPoint const& aGet_new_vertex_point , GetNewVertexPoint const& aGet_new_vertex_point
, ShouldStop const& aShould_stop , ShouldStop const& aShould_stop
, bool aIncludeNonEdgePairs , VisitorT* aVisitor
) , bool aIncludeNonEdgePairs
)
: :
mSurface (aSurface) mSurface (aSurface)
,mParamsToGetCollapseData(aParamsToGetCollapseData) ,mParamsToGetCollapseData(aParamsToGetCollapseData)
@ -40,15 +41,19 @@ VertexPairCollapse<M,D,C,V,S>::VertexPairCollapse( TSM&
,Get_cost (aGet_cost) ,Get_cost (aGet_cost)
,Get_new_vertex_point(aGet_new_vertex_point) ,Get_new_vertex_point(aGet_new_vertex_point)
,Should_stop (aShould_stop) ,Should_stop (aShould_stop)
,Visitor (aVisitor)
,mIncludeNonEdgePairs(aIncludeNonEdgePairs) ,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> template<class M,class D,class C,class V,class S, class I>
int VertexPairCollapse<M,D,C,V,S>::run() int VertexPairCollapse<M,D,C,V,S,I>::run()
{ {
if ( Visitor )
Visitor->OnStarted(mSurface);
if ( num_vertices(mSurface) > 4 ) if ( num_vertices(mSurface) > 4 )
{ {
// First collect all candidate edges in a PQ // First collect all candidate edges in a PQ
@ -61,20 +66,35 @@ int VertexPairCollapse<M,D,C,V,S>::run()
} }
else 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."); 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> template<class M,class D,class C,class V,class S, class I>
void VertexPairCollapse<M,D,C,V,S>::Collect() void VertexPairCollapse<M,D,C,V,S,I>::Collect()
{ {
CGAL_TSMS_TRACE(0,"Collecting vertex-pairs..."); 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(); Equal_3 equal_points = Kernel().equal_3_object();
@ -88,34 +108,36 @@ void VertexPairCollapse<M,D,C,V,S>::Collect()
vertex_descriptor s = source(edge,mSurface); vertex_descriptor s = source(edge,mSurface);
vertex_descriptor t = target(edge,mSurface); vertex_descriptor t = target(edge,mSurface);
Point_3 sp = get_point(s) ; bool is_s_fixed = is_vertex_fixed(s) ;
Point_3 tp = get_point(t) ; 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);
// The collapse always keeps the vertex 't' and removes vertex 's'. // All directed edges must be mapped to vertex-pair whether they are put in the PQ or not.
// If the 's' is fixed (but not t) then swap the pair to keep (the original) 's' correctly fixed. // Thus, degenerate edges are marked as fixed.
if ( is_s_fixed && !is_t_fixed ) if ( s == t || equal_points( get_point(s), get_point(t)) )
{ is_s_fixed = is_t_fixed = true ;
using std::swap ;
swap(s,t);
swap(is_s_fixed,is_t_fixed);
edge = opposite_edge(edge,mSurface);
}
Collapse_data_ptr lData = Get_collapse_data(s,t,is_s_fixed,is_t_fixed,edge,mSurface,mParamsToGetCollapseData) ; // The collapse always keeps the vertex 't' and removes vertex 's'.
vertex_pair_ptr lPair( new vertex_pair(lID++,lData,Get_cost) ) ; // If the 's' is fixed (but not t) then swap the pair to keep (the original) 's' correctly fixed.
set_pair(edge,lPair); if ( is_s_fixed && !is_t_fixed )
insert_in_PQ(lPair); {
CGAL_TSMS_TRACE(3, (lPair->cost(),*lPair) << " accepted." ); using std::swap ;
CGAL_TSMS_AUDIT(s,t,edge,lPair->cost(),Get_new_vertex_point(*lPair->data())); swap(s,t);
swap(is_s_fixed,is_t_fixed);
edge = opposite_edge(edge,mSurface);
} }
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);
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 // TODO: Collect non-edge pairs if requested
mInitialPairCount = mCurrentPairCount = lID; mInitialPairCount = mCurrentPairCount = lID;
@ -123,8 +145,8 @@ void VertexPairCollapse<M,D,C,V,S>::Collect()
CGAL_TSMS_TRACE(0,"Initial pair count: " << mInitialPairCount ) ; CGAL_TSMS_TRACE(0,"Initial pair count: " << mInitialPairCount ) ;
} }
template<class M,class D,class C,class V,class S> template<class M,class D,class C,class V,class S, class I>
void VertexPairCollapse<M,D,C,V,S>::Loop() void VertexPairCollapse<M,D,C,V,S,I>::Loop()
{ {
CGAL_TSMS_TRACE(0,"Removing pairs...") ; CGAL_TSMS_TRACE(0,"Removing pairs...") ;
@ -135,16 +157,22 @@ void VertexPairCollapse<M,D,C,V,S>::Loop()
{ {
CGAL_TSMS_TRACE(3,"Poped " << *lPair ) ; CGAL_TSMS_TRACE(3,"Poped " << *lPair ) ;
bool lIsCollapsable = false ;
if ( lPair->cost() != none ) if ( lPair->cost() != none )
{ {
if ( num_vertices(mSurface) <= 4 ) if ( num_vertices(mSurface) <= 4 )
{ {
if ( Visitor )
Visitor->OnThetrahedronReached(mSurface);
CGAL_TSMS_TRACE(0,"Thetrahedron reached."); CGAL_TSMS_TRACE(0,"Thetrahedron reached.");
break ; break ;
} }
if ( Should_stop(*lPair->cost(),*lPair->data(),mInitialPairCount,mCurrentPairCount) ) if ( Should_stop(*lPair->cost(),*lPair->data(),mInitialPairCount,mCurrentPairCount) )
{ {
if ( Visitor )
Visitor->OnStopConditionReached(mSurface);
CGAL_TSMS_TRACE(0,"Stop condition reached with InitialCount=" << mInitialPairCount CGAL_TSMS_TRACE(0,"Stop condition reached with InitialCount=" << mInitialPairCount
<< " CurrentPairCount=" << mCurrentPairCount << " CurrentPairCount=" << mCurrentPairCount
<< " CurrentPair: " << *lPair << " CurrentPair: " << *lPair
@ -152,16 +180,41 @@ void VertexPairCollapse<M,D,C,V,S>::Loop()
break ; break ;
} }
Collapse(lPair); 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. // 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. // This function returns true if a edge 'p->q' can be collapsed.
// //
template<class M,class D,class C,class V,class S> template<class M,class D,class C,class V,class S, class I>
bool VertexPairCollapse<M,D,C,V,S>::Is_collapsable( vertex_descriptor const& p, vertex_descriptor const& q, edge_descriptor const& p_q ) 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 ; 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_t = next_edge_cw (q_p,mSurface);
edge_descriptor q_b = next_edge_ccw(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 // degree(p) and degree(q) >= 3
if ( target(p_t,mSurface) != q if ( target(p_t,mSurface) != q
&& target(p_b,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_tn = next_edge_cw (q_tn,mSurface);
q_bn = next_edge_ccw(q_bn,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) if ( target(p_tn,mSurface) == target(q_tn,mSurface)
|| target(p_bn,mSurface) == target(q_bn,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 ) ; 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 rR = false ; else
{
CGAL_TSMS_TRACE(5, "degree(p) or degree(q) < 3");
rR = false ;
}
return rR ; return rR ;
} }
template<class M,class D,class C,class V,class S> template<class M,class D,class C,class V,class S, class I>
void VertexPairCollapse<M,D,C,V,S>::Collapse( vertex_pair_ptr const& aPair ) void VertexPairCollapse<M,D,C,V,S,I>::Collapse( vertex_pair_ptr const& aPair )
{ {
CGAL_TSMS_TRACE(1,"Collapsig " << *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 ); 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. // satisfying its constrians. In that case the vertex-pair is simply not removed.
Optional_vertex_point_type lNewVertexPoint = Get_new_vertex_point(*aPair->data()); Optional_vertex_point_type lNewVertexPoint = Get_new_vertex_point(*aPair->data());
if ( lNewVertexPoint ) 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); edge_descriptor lEdgeQB = next_edge_ccw(lEdgeQP,mSurface);
CGAL_TSMS_TRACE(3,"EdgePQ E" << lEdgePQ->ID << " Opposite EdgePQ E" << lEdgePQ->opposite()->ID 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 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 ; // The collapse will also remove QB so it must be pop off the PQ as well
// 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) ;
vertex_pair_ptr lPairQB = get_pair(lEdgeQB) ; vertex_pair_ptr lPairQB = get_pair(lEdgeQB) ;
vertex_pair_ptr lPairPT = get_pair(lEdgePT) ;
if ( lPairPT->is_in_PQ() ) 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) ; remove_from_PQ(lPairPT) ;
} }
if ( lPairQB->is_in_PQ() ) 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) ; remove_from_PQ(lPairQB) ;
} }
@ -319,19 +346,23 @@ void VertexPairCollapse<M,D,C,V,S>::Collapse( vertex_pair_ptr const& aPair )
<< " E" << lEdgeQB->ID << " 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); Collapse_triangulation_edge(lEdgePQ,lEdgePT,lEdgeQB,mSurface);
// Reset the point of placement of Q (the vertex that "replaces" the collapsed edge) // Reset the point of placement of Q (the vertex that "replaces" the collapsed edge)
vertex_point_t vertex_point ; vertex_point_t vertex_point ;
put(vertex_point,mSurface,lQ,*lNewVertexPoint) ; put(vertex_point,mSurface,lQ,*lNewVertexPoint) ;
// Updates the cost of all pairs in the PQ Update_neighbors(aPair);
Update_neighbors(lQ);
for ( vertex_pair_vector_iterator it = lUpdated.begin(), eit = lUpdated.end() ; it != eit ; ++ it )
(*it)->mark() = 0 ;
mCurrentPairCount -= 3 ; mCurrentPairCount -= 3 ;
} }
else else
@ -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, class I>
template<class M,class D,class C,class V,class S> void VertexPairCollapse<M,D,C,V,S,I>::Update_neighbors( vertex_pair_ptr const& aCollapsingPair )
void VertexPairCollapse<M,D,C,V,S>::Update_neighbors( vertex_descriptor const& v )
{ {
CGAL_TSMS_TRACE(3,"Updating cost of neighboring edges..." ) ; 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 ; 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 ; 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 ; edge_descriptor edge1 = *eb1 ;
vertex_pair_ptr lPair1 = get_pair(edge1) ; vertex_descriptor adj_q = source(edge1,mSurface);
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);
// (A.2) Loop around all edges incident on each adjacent vertex // (A.2) Loop around all edges incident on each adjacent vertex
in_edge_iterator eb2, ee2 ; 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 ; 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 << " V" << edge2->opposite()->vertex()->ID << "->V" << edge2->vertex()->ID
<< "\n" << *lPair2 << "\nPair:" << *lPair
) ; ) ;
// Only those pairs still in the PQ are update. // 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. // 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.") ; CGAL_TSMS_TRACE(4,"Pair registered for updating.") ;
lPair2->mark() = 1 ; lPair->mark() = 1 ;
lToUpdate.push_back(lPair2); 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 } } // namespace Triangulated_surface_mesh::Simplification
CGAL_END_NAMESPACE 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 // 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) // (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 int vertex_pair_collapse ( TSM& aSurface
, GetCollapseData const& aGet_collapse_data , GetCollapseData const& aGet_collapse_data
, ParamsToGetCollapseData const* aParamsToGetCollapseData // Can be NULL , ParamsToGetCollapseData const* aParamsToGetCollapseData // Can be NULL
, GetCost const& aGet_cost , GetCost const& aGet_cost
, GetNewVertexPoint const& aGet_new_vertex_point , GetNewVertexPoint const& aGet_new_vertex_point
, ShouldStop const& aShould_stop , ShouldStop const& aShould_stop
, Visitor* aVisitor = 0
, bool aIncludeNonEdgePairs = false , bool aIncludeNonEdgePairs = false
) )
{ {
if ( is_valid_triangulated_surface_mesh(aSurface) ) 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 Algorithm algorithm(aSurface
,aGet_collapse_data ,aGet_collapse_data
,aParamsToGetCollapseData ,aParamsToGetCollapseData
,aGet_cost ,aGet_cost
,aGet_new_vertex_point ,aGet_new_vertex_point
,aShould_stop ,aShould_stop
,aVisitor
,aIncludeNonEdgePairs ,aIncludeNonEdgePairs
) ; ) ;
return algorithm.run(); return algorithm.run();

View File

@ -24,9 +24,10 @@
#include <fstream> #include <fstream>
#include <boost/tokenizer.hpp> #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_3.h>
#include <CGAL/Polyhedron_BGL.h> #include <CGAL/Polyhedron_BGL.h>
#include <CGAL/Polyhedron_extended_BGL.h> #include <CGAL/Polyhedron_extended_BGL.h>
@ -35,8 +36,10 @@
#include <CGAL/IO/Polyhedron_iostream.h> #include <CGAL/IO/Polyhedron_iostream.h>
//#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_LT_TRACE 4 //#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_LT_TRACE 4
//#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE 3 //#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE 1
#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_AUDIT
#define STATS
//#define AUDIT
void Surface_simplification_external_trace( std::string s ) void Surface_simplification_external_trace( std::string s )
{ {
@ -59,7 +62,6 @@ using namespace std ;
using namespace boost ; using namespace boost ;
using namespace CGAL ; using namespace CGAL ;
//typedef Simple_homogeneous<int> Kernel;
typedef Simple_cartesian<double> Kernel; typedef Simple_cartesian<double> Kernel;
typedef Kernel::Vector_3 Vector; typedef Kernel::Vector_3 Vector;
typedef Kernel::Point_3 Point; typedef Kernel::Point_3 Point;
@ -143,6 +145,9 @@ struct External_polyhedron_get_is_vertex_fixed<Polyhedron>
CGAL_END_NAMESPACE CGAL_END_NAMESPACE
#ifdef AUDIT
double sCostMatchThreshold = 1e-2 ; double sCostMatchThreshold = 1e-2 ;
double sVertexMatchThreshold = 1e-2 ; double sVertexMatchThreshold = 1e-2 ;
@ -273,12 +278,12 @@ string to_string( optional<Point> const& p )
else return "NONE" ; else return "NONE" ;
} }
void CGAL_TSMS_audit( Vertex_handle const& p void register_collected_edge( Vertex_handle const& p
, Vertex_handle const& q , Vertex_handle const& q
, Halfedge_handle const& e , Halfedge_handle const& e
, optional<double> const& cost , optional<double> const& cost
, optional<Point> const& newv , optional<Point> const& newv
) )
{ {
Audit_report_ptr lReport( new Audit_report(e->ID) ) ; Audit_report_ptr lReport( new Audit_report(e->ID) ) ;
@ -312,6 +317,101 @@ void CGAL_TSMS_audit( Vertex_handle const& p
sAuditReport.insert( make_pair(e->ID,lReport) ) ; 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. // 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 ) 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" ; return matched ? "matched" : "UNMATCHED" ;
} }
bool Test ( string name ) bool Test ( int aStop, string name )
{ {
bool rSucceeded = false ; bool rSucceeded = false ;
@ -339,14 +439,16 @@ bool Test ( string name )
string audit_name = name+string(".audit"); string audit_name = name+string(".audit");
string result_name = name+string(".out.off"); string result_name = name+string(".out.off");
cout << "Testing simplification of surface " << off_name << endl ;
ifstream off_is(off_name.c_str()); ifstream off_is(off_name.c_str());
if ( off_is ) if ( off_is )
{ {
Polyhedron lP; 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) ; cout << setprecision(19) ;
@ -362,33 +464,52 @@ bool Test ( string name )
for ( Polyhedron::Facet_iterator fi = lP.facets_begin(); fi != lP.facets_end() ; ++ fi ) for ( Polyhedron::Facet_iterator fi = lP.facets_begin(); fi != lP.facets_end() ; ++ fi )
fi->ID = lFacetID ++ ; fi->ID = lFacetID ++ ;
sAuditData.clear(); #ifdef AUDIT
//ParseAudit(audit_name); sAuditData .clear();
sAuditReport.clear();
ParseAudit(audit_name);
cout << "Audit data loaded." << endl ; cout << "Audit data loaded." << endl ;
#endif
typedef LindstromTurk_collapse_data<Polyhedron> Collapse_data ; typedef LindstromTurk_collapse_data<Polyhedron> Collapse_data ;
Construct_LindstromTurk_collapse_data<Collapse_data> Construct_collapse_data ; Construct_LindstromTurk_collapse_data<Collapse_data> Construct_collapse_data ;
LindstromTurk_cost <Collapse_data> Get_cost ; LindstromTurk_cost <Collapse_data> Get_cost ;
LindstromTurk_vertex_placement <Collapse_data> Get_vertex_point ; 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; Collapse_data::Params lParams;
sAuditReport.clear(); Visitor lVisitor ;
int r = vertex_pair_collapse(lP,Construct_collapse_data,&lParams,Get_cost,Get_vertex_point,Should_stop);
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); ofstream off_out(result_name.c_str(),ios::trunc);
off_out << lP ; off_out << lP ;
cout << "Finished...\n" cout << "\nFinished...\n"
<< "Ellapsed time: " << t.time() << " seconds.\n"
<< r << " edges removed.\n" << r << " edges removed.\n"
<< lP.size_of_vertices() << " vertices.\n" << endl
<< (lP.size_of_halfedges()/2) << " edges.\n" << lP.size_of_vertices() << " final vertices.\n"
<< lP.size_of_facets() << " triangles.\n" << (lP.size_of_halfedges()/2) << " final edges.\n"
<< lP.size_of_facets() << " final triangles.\n"
<< ( lP.is_valid() ? " valid\n" : " INVALID!!\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 ; unsigned lMatches = 0 ;
cout << "Audit report:\n" ; cout << "Audit report:\n" ;
@ -417,6 +538,10 @@ bool Test ( string name )
} }
rSucceeded = ( lMatches == sAuditReport.size() ) ; rSucceeded = ( lMatches == sAuditReport.size() ) ;
#else
rSucceeded = true ;
#endif
} }
else else
{ {
@ -431,26 +556,37 @@ int main( int argc, char** argv )
set_error_handler (error_handler); set_error_handler (error_handler);
set_warning_handler(error_handler); set_warning_handler(error_handler);
vector<string> cases ; if ( argc > 3 )
for ( int i = 1 ; i < argc ; ++i )
cases.push_back( string(argv[i]) ) ;
if ( cases.size() == 0 )
cases.push_back( string("data/sample5") ) ;
unsigned lOK = 0 ;
for ( vector<string>::const_iterator it = cases.begin(); it != cases.end() ; ++ it )
{ {
if ( Test(*it) ) vector<string> cases ;
++ lOK ;
}
cout << endl int lStop = atoi(argv[1]);
<< lOK << " cases succedded." << endl
<< (cases.size() - lOK ) << " cases failed." << endl ; string lFolder(argv[2]);
lFolder += "/" ;
return lOK == cases.size() ? 0 : 1 ;
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( lStop, lFolder + *it) )
++ lOK ;
}
cout << endl
<< lOK << " cases succedded." << endl
<< (cases.size() - lOK ) << " cases failed." << endl ;
return lOK == cases.size() ? 0 : 1 ;
}
else
{
cout << "USAGE: LT_edge_collapse_test final_edge_count folder file0 file1 file2 ..." << endl ;
return 1 ;
}
} }
// EOF // // EOF //

View File

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

View File

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