Bug in link-condition fixed

This commit is contained in:
Fernando Cacciola
2006-07-03 17:19:46 +00:00
parent 0e6682573f
commit 7eaa3c8adc
8 changed files with 98 additions and 697 deletions
@@ -20,6 +20,19 @@
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:
//
@@ -44,10 +44,10 @@ public:
typedef Collapse_data_ Collapse_data ;
typedef typename Collapse_data::TSM TSM ;
typedef typename Collapse_data::vertex_descrirptor vertex_descriptor ;
typedef typename Collapse_data::Point_3 Point_3 ;
typedef typename Collapse_data::FT FT ;
typedef typename Collapse_data::TSM TSM ;
typedef typename Collapse_data::vertex_descriptor vertex_descriptor ;
typedef typename Collapse_data::Point_3 Point_3 ;
typedef typename Collapse_data::FT FT ;
public:
@@ -65,7 +65,7 @@ public:
else return result_type();
}
Point_3 const& get_point ( vertex_descriptor const& v, TSM& aSurface )
Point_3 const& get_point ( vertex_descriptor const& v, TSM& aSurface ) const
{
vertex_point_t vertex_point ;
return get(vertex_point,aSurface,v) ;
@@ -44,9 +44,9 @@ public:
typedef Collapse_data_ Collapse_data ;
typedef typename Collapse_data::TSM TSM ;
typedef typename Collapse_data::vertex_descrirptor vertex_descriptor ;
typedef typename Collapse_data::Point_3 Point_3 ;
typedef typename Collapse_data::TSM TSM ;
typedef typename Collapse_data::vertex_descriptor vertex_descriptor ;
typedef typename Collapse_data::Point_3 Point_3 ;
typedef optional<Point_3> result_type ;
@@ -69,7 +69,7 @@ public:
else return result_type();
}
Point_3 const& get_point ( vertex_descriptor const& v, TSM& aSurface )
Point_3 const& get_point ( vertex_descriptor const& v, TSM& aSurface ) const
{
vertex_point_t vertex_point ;
return get(vertex_point,aSurface,v) ;
@@ -39,6 +39,8 @@ public:
typedef typename Surface_geometric_traits<TSM>::Point_3 Point_3 ;
typedef typename Surface_geometric_traits<TSM>::FT FT ;
struct Params{} ;
public :
Minimal_collapse_data()
@@ -236,78 +236,43 @@ void VertexPairCollapse<M,D,C,V,S,I>::Loop()
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 ;
out_edge_iterator eb1, ee1 ;
out_edge_iterator eb2, ee2 ;
edge_descriptor q_p = opposite_edge(p_q,mSurface);
edge_descriptor p_t = next_edge_ccw(p_q,mSurface);
edge_descriptor p_b = next_edge_cw (p_q,mSurface);
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()
);
vertex_descriptor t = target(next_edge_cw (q_p,mSurface),mSurface);
vertex_descriptor b = target(next_edge_ccw(q_p,mSurface),mSurface);
// degree(p) and degree(q) >= 3
if ( target(p_t,mSurface) != q
&& target(p_b,mSurface) != q
&& target(q_t,mSurface) != p
&& target(q_b,mSurface) != p
)
for ( tie(eb1,ee1) = out_edges(p,mSurface) ; eb1 != ee1 ; ++ eb1 )
{
// link('p') .intersection. link('q') == link('p_q') (that is, exactly {'t','b'})
if ( target(p_t,mSurface) == target(q_t,mSurface)
&& target(p_b,mSurface) == target(q_b,mSurface)
)
edge_descriptor p_x = *eb1 ;
if ( p_x != p_q )
{
edge_descriptor p_tn = p_t ;
edge_descriptor p_bn = p_b ;
edge_descriptor q_tn = q_t ;
edge_descriptor q_bn = q_b ;
vertex_descriptor x = target(p_x,mSurface);
do
for ( tie(eb2,ee2) = out_edges(x,mSurface) ; eb2 != ee2 ; ++ eb2 )
{
p_tn = next_edge_ccw(p_tn,mSurface);
p_bn = next_edge_cw (p_bn,mSurface);
q_tn = next_edge_cw (q_tn,mSurface);
q_bn = next_edge_ccw(q_bn,mSurface);
edge_descriptor x_y = *eb2 ;
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)
)
if ( target(x_y,mSurface) == q )
{
rR = false ;
break ;
}
}
while ( p_tn != p_bn && q_tn != q_bn ) ;
}
else
{
CGAL_TSMS_TRACE(5, "t and b vertices not shared by p and q");
rR = false ;
if ( x != t && x != b )
{
CGAL_TSMS_TRACE(0, "Link condition for E" << p_q->id() << " V" << p->id() << "->V" << q->id() << " failed."
<< "\n Non-face triangle found: V" << p->id() << "->V" << x->id() << "->V" << q->id()
<< "\n (top face: V" << p->id() << "->V" << t->id() << "->V" << q->id() << ")"
<< "\n (bottom face: V" << p->id() << "->V" << b->id() << "->V" << q->id() << ")"
);
return false ;
}
}
}
}
}
else
{
CGAL_TSMS_TRACE(5, "degree(p) or degree(q) < 3");
rR = false ;
}
}
return rR ;
return true ;
}
template<class M,class D,class C,class V,class S, class I>
@@ -338,11 +303,17 @@ void VertexPairCollapse<M,D,C,V,S,I>::Collapse( vertex_pair_ptr 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
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 << " Opposite EdgePT E" << lEdgePT->opposite()->ID
<< " V" << lEdgePT->opposite()->vertex()->ID << "->V" << lEdgePT->vertex()->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
) ;
// The collapse will also remove QB so it must be pop off the PQ as well
@@ -424,7 +395,9 @@ void VertexPairCollapse<M,D,C,V,S,I>::Update_neighbors( vertex_pair_ptr aCollaps
if ( lPair->p() == aCollapsingPair->p() )
{
CGAL_TSMS_TRACE(4,"Replacing lPair->p() with Q" ) ;
CGAL_TSMS_TRACE(4,"Replacing lPair->p() with V" << aCollapsingPair->q()->id() << "(Q)" ) ;
CGAL_assertion( aCollapsingPair->q() != lPair->q() ) ;
lPair->data().set(aCollapsingPair->q()
,lPair ->q()
@@ -436,7 +409,9 @@ void VertexPairCollapse<M,D,C,V,S,I>::Update_neighbors( vertex_pair_ptr aCollaps
}
else if ( lPair->q() == aCollapsingPair->p() )
{
CGAL_TSMS_TRACE(4,"Replacing lPair->q() with Q" ) ;
CGAL_TSMS_TRACE(4,"Replacing lPair->q() with V" << aCollapsingPair->q()->id() << " (Q)" ) ;
CGAL_assertion( aCollapsingPair->q() != lPair->p() ) ;
lPair->data().set(lPair ->p()
,aCollapsingPair->q()
@@ -455,13 +430,10 @@ void VertexPairCollapse<M,D,C,V,S,I>::Update_neighbors( vertex_pair_ptr aCollaps
// 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 ( lPair->is_in_PQ() )
if ( lPair->is_in_PQ() && lToUpdate.find(lPair) == lToUpdate.end() )
{
if ( lToUpdate.find(lPair) == lToUpdate.end() )
{
CGAL_TSMS_TRACE(4,"Pair registered for updating.") ;
lToUpdate.insert(lPair) ;
}
CGAL_TSMS_TRACE(4,"Pair registered for updating.") ;
lToUpdate.insert(lPair) ;
}
}
}
@@ -473,21 +445,25 @@ void VertexPairCollapse<M,D,C,V,S,I>::Update_neighbors( vertex_pair_ptr aCollaps
for ( typename vertex_pair_set::iterator it = lToUpdate.begin(), eit = lToUpdate.end() ; it != eit ; ++ it )
{
vertex_pair_ptr lPair = *it ;
CGAL_TSMS_TRACE(3,"Updating cost of " << *lPair) ;
//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() ;
// The cost of a pair can be recalculated by invalidating its cache and updating the PQ.
// The PQ update will reposition the pair in the heap querying its cost(),
// but since the cost was invalidated, it will be computed again
Set_collapse_data(lPair->data()
,lPair->p()
,lPair->q()
,lPair->is_p_fixed()
,lPair->is_q_fixed()
,lIsPFixed
,lIsQFixed
,lPair->edge()
,lPair->surface()
,mParamsToSetCollapseData
) ;
lPair->cost() = Get_cost(lPair->data());
CGAL_TSMS_TRACE(3,"Updated cost of " << *lPair) ;
update_in_PQ(lPair);
}
@@ -1,597 +1,2 @@
// // Copyright (c) 2002 Max Planck Institut fuer Informatik (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Fernando Cacciola <fernando.cacciola@gmail.com>
#include <iostream>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <boost/tokenizer.hpp>
//#define CGAL_CHECK_EXPENSIVE
#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>
#include <CGAL/Polyhedron_BGL_properties.h>
#include <CGAL/IO/Polyhedron_geomview_ostream.h>
#include <CGAL/IO/Polyhedron_iostream.h>
//#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_LT_TRACE 4
//#define CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE 1
#define STATS
//#define AUDIT
void Surface_simplification_external_trace( std::string s )
{
static std::ofstream lout("tsms_log.txt");
lout << s << std::flush << std::endl ;
std::printf("%s\n",s.c_str());
}
int exit_code = 0 ;
#include <CGAL/Surface_mesh_simplification_vertex_pair_collapse.h>
#include <CGAL/Surface_mesh_simplification/Policies/LindstromTurk.h>
#include <CGAL/Surface_mesh_simplification/Policies/Count_stop_pred.h>
#include <CGAL/Surface_mesh_simplification/Polyhedron_is_vertex_fixed_map.h>
#include <CGAL/Surface_mesh_simplification/Polyhedron_edge_cached_pointer_map.h>
using namespace std ;
using namespace boost ;
using namespace CGAL ;
typedef Simple_cartesian<double> Kernel;
typedef Kernel::Vector_3 Vector;
typedef Kernel::Point_3 Point;
template <class Refs, class Traits>
struct My_vertex : public HalfedgeDS_vertex_base<Refs,Tag_true,Point>
{
typedef HalfedgeDS_vertex_base<Refs,Tag_true,Point> Base ;
My_vertex() : ID(-1), IsFixed(false) {}
My_vertex( Point p ) : Base(p), ID(-1), IsFixed(false) {}
int id() const { return ID ; }
int ID;
bool IsFixed ;
} ;
template <class Refs, class Traits>
struct My_halfedge : public HalfedgeDS_halfedge_base<Refs>
{
My_halfedge()
:
ID(-1)
{}
int id() const { return ID ; }
int ID;
void* cached_pointer ;
};
template <class Refs, class Traits>
struct My_face : public HalfedgeDS_face_base<Refs,Tag_true,typename Traits::Plane_3>
{
typedef HalfedgeDS_face_base<Refs,Tag_true,typename Traits::Plane_3> Base ;
My_face() : ID(-1) {}
My_face( typename Traits::Plane_3 plane ) : Base(plane) {}
int id() const { return ID ; }
int ID;
};
struct My_items : public Polyhedron_items_3
{
template < class Refs, class Traits>
struct Vertex_wrapper {
typedef My_vertex<Refs,Traits> Vertex;
};
template < class Refs, class Traits>
struct Halfedge_wrapper {
typedef My_halfedge<Refs,Traits> Halfedge;
};
template < class Refs, class Traits>
struct Face_wrapper {
typedef My_face<Refs,Traits> Face;
};
};
typedef Polyhedron_3<Kernel,My_items> Polyhedron;
typedef Polyhedron::Vertex Vertex;
typedef Polyhedron::Vertex_iterator Vertex_iterator;
typedef Polyhedron::Vertex_handle Vertex_handle;
typedef Polyhedron::Vertex_const_handle Vertex_const_handle;
typedef Polyhedron::Halfedge_handle Halfedge_handle;
typedef Polyhedron::Halfedge_const_handle Halfedge_const_handle;
typedef Polyhedron::Edge_iterator Edge_iterator;
typedef Polyhedron::Facet_iterator Facet_iterator;
typedef Polyhedron::Halfedge_around_vertex_const_circulator HV_circulator;
typedef Polyhedron::Halfedge_around_facet_circulator HF_circulator;
CGAL_BEGIN_NAMESPACE
template<>
struct External_polyhedron_get_is_vertex_fixed<Polyhedron>
{
bool operator() ( Polyhedron const&, Vertex_const_handle v ) const { return v->IsFixed; }
} ;
template<>
struct External_polyhedron_access_edge_cached_pointer<Polyhedron>
{
void*& operator() ( Polyhedron&, Halfedge_handle he ) const { return he->cached_pointer; }
} ;
CGAL_END_NAMESPACE
#ifdef AUDIT
double sCostMatchThreshold = 1e-2 ;
double sVertexMatchThreshold = 1e-2 ;
struct Audit_data
{
Audit_data( Point p, Point q ) : P(p), Q(q) {}
Point P, Q ;
optional<double> Cost ;
optional<Point> NewVertexPoint ;
} ;
typedef shared_ptr<Audit_data> Audit_data_ptr ;
typedef vector<Audit_data_ptr> Audit_data_vector ;
Audit_data_vector sAuditData ;
Audit_data_ptr lookup_audit ( Point p, Point q )
{
for ( Audit_data_vector::iterator it = sAuditData.begin() ; it != sAuditData.end() ; ++ it )
{
Audit_data_ptr data = *it ;
if ( data->P == p && data->Q == q )
return data ;
}
return Audit_data_ptr() ;
}
Audit_data_ptr get_or_create_audit ( Point p, Point q )
{
Audit_data_ptr data = lookup_audit(p,q);
if ( !data )
{
data = Audit_data_ptr(new Audit_data(p,q));
sAuditData.push_back(data);
}
return data ;
}
struct Audit_report
{
Audit_report( int eid )
:
HalfedgeID(eid)
, CostMatched(false)
, OrderMatched(false)
, NewVertexMatched(false)
{}
int HalfedgeID ;
Audit_data_ptr AuditData ;
optional<double> Cost ;
optional<Point> NewVertexPoint ;
bool CostMatched ;
bool OrderMatched ;
bool NewVertexMatched ;
} ;
typedef shared_ptr<Audit_report> Audit_report_ptr ;
typedef map<int,Audit_report_ptr> Audit_report_map ;
Audit_report_map sAuditReport ;
typedef char_separator<char> Separator ;
typedef tokenizer<Separator> Tokenizer ;
Point ParsePoint( vector<string> tokens, int aIdx )
{
double x = atof(tokens[aIdx+0].c_str());
double y = atof(tokens[aIdx+1].c_str());
double z = atof(tokens[aIdx+2].c_str());
return Point(x,y,z);
}
void ParseAuditLine( string s )
{
Tokenizer tk(s,Separator(","));
vector<string> tokens(tk.begin(),tk.end());
if ( tokens.size() >= 7 )
{
Point p = ParsePoint(tokens,0);
Point q = ParsePoint(tokens,3);
Audit_data_ptr lData = get_or_create_audit(p,q);
double cost = atof(tokens[6].c_str()) ;
if ( cost != std::numeric_limits<double>::max() )
lData->Cost = cost ;
if ( tokens.size() == 10 )
lData->NewVertexPoint = ParsePoint(tokens,7);
}
else
cerr << "WARNING: Invalid audit line: [" << s << "]" << endl ;
}
void ParseAudit ( string name )
{
ifstream is(name.c_str());
if ( is )
{
while ( is )
{
string line ;
getline(is,line);
if ( line.length() > 0 )
ParseAuditLine(line);
}
}
else cerr << "Warning: Audit file " << name << " doesn't exist." << endl ;
}
string to_string( optional<double> const& c )
{
if ( c )
return str( format("%1%") % (*c) ) ;
else return "NONE" ;
}
string to_string( optional<Point> const& p )
{
if ( p )
return str( format("(%1%,%2%,%3%)") % p->x() % p->y() % p->z() ) ;
else return "NONE" ;
}
void register_collected_edge( Vertex_handle const& p
, Vertex_handle const& q
, Halfedge_handle const& e
, optional<double> const& cost
, optional<Point> const& newv
)
{
Audit_report_ptr lReport( new Audit_report(e->ID) ) ;
lReport->Cost = cost ;
lReport->NewVertexPoint = newv ;
Audit_data_ptr lData ; //= lookup_audit(p->point(),q->point());
if ( lData )
{
lReport->AuditData = lData ;
if ( !!lData->Cost && !!cost )
{
double d = fabs(*lData->Cost - *cost) ;
if ( d < sCostMatchThreshold )
lReport->CostMatched = true ;
}
else if (!lData->Cost && !cost )
lReport->CostMatched = true ;
if ( !!lData->NewVertexPoint && !!newv )
{
double d = std::sqrt(squared_distance(*lData->NewVertexPoint,*newv));
if ( d < sVertexMatchThreshold )
lReport->NewVertexMatched = true ;
}
else if ( !lData->NewVertexPoint && !newv )
lReport->NewVertexMatched = true ;
}
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 )
{
cerr << "CGAL error: " << what << " violation!" << endl
<< "Expr: " << expr << endl
<< "File: " << file << endl
<< "Line: " << line << endl;
if ( msg != 0)
cerr << "Explanation:" << msg << endl;
}
using namespace CGAL::Triangulated_surface_mesh::Simplification ;
char const* matched_alpha ( bool matched )
{
return matched ? "matched" : "UNMATCHED" ;
}
bool Test ( int aStop, string name )
{
bool rSucceeded = false ;
string off_name = name+string(".off");
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;
scan_OFF(off_is,lP,true);
cout << (lP.size_of_halfedges()/2) << " edges..." << endl ;
cout << setprecision(19) ;
int lVertexID = 0 ;
for ( Polyhedron::Vertex_iterator vi = lP.vertices_begin(); vi != lP.vertices_end() ; ++ vi )
vi->ID = lVertexID ++ ;
int lHalfedgeID = 0 ;
for ( Polyhedron::Halfedge_iterator hi = lP.halfedges_begin(); hi != lP.halfedges_end() ; ++ hi )
hi->ID = lHalfedgeID++ ;
int lFacetID = 0 ;
for ( Polyhedron::Facet_iterator fi = lP.facets_begin(); fi != lP.facets_end() ; ++ fi )
fi->ID = lFacetID ++ ;
#ifdef AUDIT
sAuditData .clear();
sAuditReport.clear();
ParseAudit(audit_name);
cout << "Audit data loaded." << endl ;
#endif
typedef LindstromTurk_collapse_data<Polyhedron> Collapse_data ;
Set_LindstromTurk_collapse_data<Collapse_data> Set_collapse_data ;
LindstromTurk_cost <Collapse_data> Get_cost ;
LindstromTurk_vertex_placement <Collapse_data> Get_vertex_point ;
Count_stop_condition <Collapse_data> Should_stop(aStop);
Collapse_data::Params lParams;
Visitor lVisitor ;
Real_timer t ; t.start();
int r = vertex_pair_collapse(lP,Set_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 << "\nFinished...\n"
<< "Ellapsed time: " << t.time() << " seconds.\n"
<< r << " edges removed.\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" ;
for ( Audit_report_map::const_iterator ri = sAuditReport.begin() ; ri != sAuditReport.end() ; ++ ri )
{
Audit_report_ptr lReport = ri->second ;
if ( lReport->AuditData )
{
if ( lReport->NewVertexMatched )
++ lMatches ;
cout << "Collapsed Halfedge " << lReport->HalfedgeID << endl
<< " Cost: Actual=" << to_string(lReport->Cost) << ", Expected=" << to_string(lReport->AuditData->Cost)
<< ". " << matched_alpha(lReport->CostMatched) << endl
<< " New vertex point: Actual=" << to_string(lReport->NewVertexPoint) << ", Expected="
<< to_string(lReport->AuditData->NewVertexPoint)
<< ". " << matched_alpha(lReport->NewVertexMatched)
<< endl ;
}
else
{
cout << "No audit data for Halfedge " << lReport->HalfedgeID << endl ;
++ lMatches ;
}
}
rSucceeded = ( lMatches == sAuditReport.size() ) ;
#else
rSucceeded = true ;
#endif
}
else
{
cerr << "Unable to open test file " << name << endl ;
}
return rSucceeded ;
}
int main( int argc, char** argv )
{
set_error_handler (error_handler);
set_warning_handler(error_handler);
if ( argc > 3 )
{
vector<string> cases ;
int lStop = atoi(argv[1]);
string lFolder(argv[2]);
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 //
#define TEST_LT
#include "edge_collapse_test.cpp"
@@ -9,7 +9,7 @@
<ignoreparts/>
<projectdirectory>.</projectdirectory>
<absoluteprojectpath>false</absoluteprojectpath>
<description></description>
<description/>
</general>
<kdevcustomproject>
<run>
@@ -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>
@@ -38,17 +38,17 @@
</make>
<build>
<buildtool>make</buildtool>
<builddir></builddir>
<builddir/>
</build>
</kdevcustomproject>
<kdevdebugger>
<general>
<dbgshell></dbgshell>
<dbgshell/>
<programargs>1000 data/ horse.5000</programargs>
<gdbpath></gdbpath>
<configGdbScript></configGdbScript>
<runShellScript></runShellScript>
<runGdbScript></runGdbScript>
<gdbpath/>
<configGdbScript/>
<runShellScript/>
<runGdbScript/>
<breakonloadinglibs>true</breakonloadinglibs>
<separatetty>false</separatetty>
<floatingtoolbar>false</floatingtoolbar>
@@ -128,7 +128,7 @@
<headerCompletionDelay>250</headerCompletionDelay>
</codecompletion>
<creategettersetter>
<prefixGet></prefixGet>
<prefixGet/>
<prefixSet>set</prefixSet>
<prefixVariable>m_,_</prefixVariable>
<parameterName>theValue</parameterName>
@@ -154,8 +154,8 @@
</cppsupportpart>
<kdevvisualadvance>
<emulator>VisualBoyAdvance</emulator>
<binary></binary>
<addOptions></addOptions>
<binary/>
<addOptions/>
<terminal>false</terminal>
<fullscreen>false</fullscreen>
<graphicFilter>-f0</graphicFilter>
@@ -35,12 +35,17 @@ LDFLAGS = \
#---------------------------------------------------------------------#
all: \
Midpoint_edge_collapse_test \
LT_edge_collapse_test
Midpoint_edge_collapse_test$(EXE_EXT): Midpoint_edge_collapse_test$(OBJ_EXT)
$(CGAL_CXX) $(LIBPATH) $(EXE_OPT)Midpoint_edge_collapse_test Midpoint_edge_collapse_test$(OBJ_EXT) $(LDFLAGS)
LT_edge_collapse_test$(EXE_EXT): LT_edge_collapse_test$(OBJ_EXT)
$(CGAL_CXX) $(LIBPATH) $(EXE_OPT)LT_edge_collapse_test LT_edge_collapse_test$(OBJ_EXT) $(LDFLAGS)
clean: \
Midpoint_edge_collapse_test.clean \
LT_edge_collapse_test.clean
#---------------------------------------------------------------------#