demo updated

This commit is contained in:
Fernando Cacciola 2006-10-17 16:47:30 +00:00
parent 0e5d766ca3
commit ddd88bdfd3
9 changed files with 475 additions and 494 deletions

7
.gitattributes vendored
View File

@ -2056,6 +2056,7 @@ Surface_mesh_parameterization/test/Surface_mesh_parameterization/data/cube.off -
Surface_mesh_parameterization/test/Surface_mesh_parameterization/data/high_genus.off -text svneol=unset#application/octet-stream
Surface_mesh_parameterization/test/Surface_mesh_parameterization/data/knot2.off -text svneol=unset#application/octet-stream
Surface_mesh_parameterization/test/Surface_mesh_parameterization/data/oni.off -text svneol=unset#application/octet-stream
Surface_mesh_simplification/demo/Surface_mesh_simplification/edge_collapse_demo.cpp -text
Surface_mesh_simplification/doc_tex/Surface_mesh_simplification.tex -text
Surface_mesh_simplification/doc_tex/Surface_mesh_simplification/PkgDescription.tex -text
Surface_mesh_simplification/doc_tex/Surface_mesh_simplification/Surface_mesh_simplification.tex -text
@ -2142,12 +2143,12 @@ Surface_mesh_simplification/test/Surface_mesh_simplification/data/cube_MP.audit
Surface_mesh_simplification/test/Surface_mesh_simplification/data/cube_open.off -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/cube_open_LT.audit -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/cube_open_MP.audit -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/eight.off -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/eight_LT.audit -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/eight_MP.audit -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/genus1.off -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/genus1_LT.audit -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/genus1_MP.audit -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/genus2.off -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/genus2_LT.audit -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/genus2_MP.audit -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/head_open_with_holes.off -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/head_open_with_holes_LT.audit -text
Surface_mesh_simplification/test/Surface_mesh_simplification/data/head_open_with_holes_MP.audit -text

View File

@ -1,7 +1,7 @@
demo/Surface_simplification/README
----------------------------------
simplification_demo.C
edge_collapse_demo.cpp
Fernando Cacciola

View File

@ -1,162 +0,0 @@
<?xml version = '1.0'?>
<kdevelop>
<general>
<author>fcacciola</author>
<email>fernando.cacciola@gmail.com</email>
<version>$VERSION$</version>
<projectmanagement>KDevCustomProject</projectmanagement>
<primarylanguage>C++</primarylanguage>
<ignoreparts/>
<projectdirectory>.</projectdirectory>
<absoluteprojectpath>false</absoluteprojectpath>
<description/>
</general>
<kdevcustomproject>
<run>
<mainprogram>simplification_demo</mainprogram>
<directoryradio>build</directoryradio>
<customdirectory>/</customdirectory>
<programargs>./data/Sample0.off 1000</programargs>
<terminal>false</terminal>
<autocompile>true</autocompile>
<envvars/>
</run>
<build>
<buildtool>make</buildtool>
<builddir/>
</build>
<make>
<abortonerror>false</abortonerror>
<numberofjobs>1</numberofjobs>
<prio>0</prio>
<dontact>false</dontact>
<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>
<default/>
</environments>
</make>
</kdevcustomproject>
<kdevdebugger>
<general>
<dbgshell/>
<programargs/>
<gdbpath/>
<configGdbScript/>
<runShellScript/>
<runGdbScript/>
<breakonloadinglibs>true</breakonloadinglibs>
<separatetty>false</separatetty>
<floatingtoolbar>false</floatingtoolbar>
</general>
<display>
<staticmembers>false</staticmembers>
<demanglenames>true</demanglenames>
<outputradix>10</outputradix>
</display>
</kdevdebugger>
<kdevdoctreeview>
<ignoretocs>
<toc>ada</toc>
<toc>ada_bugs_gcc</toc>
<toc>bash</toc>
<toc>bash_bugs</toc>
<toc>clanlib</toc>
<toc>fortran_bugs_gcc</toc>
<toc>gnome1</toc>
<toc>gnustep</toc>
<toc>gtk</toc>
<toc>gtk_bugs</toc>
<toc>haskell</toc>
<toc>haskell_bugs_ghc</toc>
<toc>java_bugs_gcc</toc>
<toc>java_bugs_sun</toc>
<toc>kde2book</toc>
<toc>opengl</toc>
<toc>pascal_bugs_fp</toc>
<toc>php</toc>
<toc>php_bugs</toc>
<toc>perl</toc>
<toc>perl_bugs</toc>
<toc>python</toc>
<toc>python_bugs</toc>
<toc>qt-kdev3</toc>
<toc>ruby</toc>
<toc>ruby_bugs</toc>
<toc>sdl</toc>
<toc>sw</toc>
<toc>w3c-dom-level2-html</toc>
<toc>w3c-svg</toc>
<toc>w3c-uaag10</toc>
<toc>wxwidgets_bugs</toc>
</ignoretocs>
<ignoreqt_xml>
<toc>Guide to the Qt Translation Tools</toc>
<toc>Qt Assistant Manual</toc>
<toc>Qt Designer Manual</toc>
<toc>Qt Reference Documentation</toc>
<toc>qmake User Guide</toc>
</ignoreqt_xml>
<ignoredoxygen>
<toc>KDE Libraries (Doxygen)</toc>
</ignoredoxygen>
</kdevdoctreeview>
<kdevfilecreate>
<filetypes/>
<useglobaltypes>
<type ext="ui" />
<type ext="cpp" />
<type ext="h" />
</useglobaltypes>
</kdevfilecreate>
<kdevcppsupport>
<references/>
<codecompletion>
<includeGlobalFunctions>true</includeGlobalFunctions>
<includeTypes>true</includeTypes>
<includeEnums>true</includeEnums>
<includeTypedefs>false</includeTypedefs>
<automaticCodeCompletion>true</automaticCodeCompletion>
<automaticArgumentsHint>true</automaticArgumentsHint>
<automaticHeaderCompletion>true</automaticHeaderCompletion>
<codeCompletionDelay>250</codeCompletionDelay>
<argumentsHintDelay>400</argumentsHintDelay>
<headerCompletionDelay>250</headerCompletionDelay>
</codecompletion>
<creategettersetter>
<prefixGet/>
<prefixSet>set</prefixSet>
<prefixVariable>m_,_</prefixVariable>
<parameterName>theValue</parameterName>
<inlineGet>true</inlineGet>
<inlineSet>true</inlineSet>
</creategettersetter>
</kdevcppsupport>
<kdevfileview>
<groups>
<hidenonprojectfiles>false</hidenonprojectfiles>
<hidenonlocation>false</hidenonlocation>
</groups>
<tree>
<hidepatterns>*.o,*.lo,CVS</hidepatterns>
<hidenonprojectfiles>false</hidenonprojectfiles>
</tree>
</kdevfileview>
<cppsupportpart>
<filetemplates>
<interfacesuffix>.h</interfacesuffix>
<implementationsuffix>.cpp</implementationsuffix>
</filetemplates>
</cppsupportpart>
<kdevvisualadvance>
<emulator>VisualBoyAdvance</emulator>
<binary/>
<addOptions/>
<terminal>false</terminal>
<fullscreen>false</fullscreen>
<graphicFilter>-f0</graphicFilter>
<scaling>-1</scaling>
</kdevvisualadvance>
</kdevelop>

View File

@ -0,0 +1,463 @@
// 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: svn+ssh://fcacciola@scm.gforge.inria.fr/svn/cgal/trunk/Surface_mesh_simplification/test/Surface_mesh_simplification/LT_edge_collapse_test.cpp $
// $Id: LT_edge_collapse_test.cpp 32177 2006-07-03 11:55:13Z fcacciola $
//
//
// Author(s) : Fernando Cacciola <fernando.cacciola@gmail.com>
#include <iostream>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include <CGAL/Real_timer.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Constrained_triangulation_2.h>
#include <CGAL/Surface_mesh_simplification/HalfedgeGraph_Polyhedron_3.h>
#include <CGAL/Surface_mesh_simplification/edge_collapse.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/LindstromTurk.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Midpoint_and_length.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_collapse/Count_stop_predicate.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/Polyhedron_items_with_id_3.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;
typedef Polyhedron_3<Kernel,Polyhedron_items_with_id_3> 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;
typedef Polyhedron::size_type size_type ;
struct Visitor
{
Visitor ( size_t aRequested ) : mRequested(aRequested), mCollected(0) {}
void OnStarted( Polyhedron& ) {}
void OnFinished ( Polyhedron& )
{
cerr << "\n" << flush ;
}
void OnStopConditionReached( Polyhedron& ) {}
void OnCollected( Halfedge_handle const& aEdge, bool aIsFixed, Polyhedron& )
{
++ mCollected ;
cerr << "\rEdges collected: " << mCollected << flush ;
}
void OnSelected( Halfedge_handle const& aEdge, Polyhedron&, optional<double> const& aCost, size_t aInitial, size_t aCurrent )
{
if ( aCurrent == aInitial )
cerr << "\n" << flush ;
if ( mRequested < aInitial )
{
double n = aInitial - aCurrent ;
double d = aInitial - mRequested ;
cerr << "\r" << aCurrent << " " << ((int)(100.0*(n/d))) << "%" << flush ;
}
}
void OnCollapsing(Halfedge_handle const& aEdge, Polyhedron&, optional<Point> const& aPlacement )
{
}
void OnNonCollapsable(Halfedge_handle const& aEdge, Polyhedron& )
{
}
size_t mRequested ;
size_t mCollected ;
} ;
// 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;
throw std::logic_error("");
}
using namespace CGAL::Surface_mesh_simplification ;
char const* matched_alpha ( bool matched )
{
return matched ? "matched" : "UNMATCHED" ;
}
enum Method { LT, MP } ;
enum Cache { None, Cost, CostPlacement } ;
char const* method_to_string( Method aMethod )
{
switch(aMethod)
{
case LT: return "LindstromTurk" ; break ;
case MP: return "Midpoint" ; break ;
}
return "<unknown>" ;
}
char const* cache_to_string( Cache aCache )
{
switch(aCache)
{
case None : return "None" ; break ;
case Cost : return "Cost" ; break ;
case CostPlacement : return "CostPlacement" ; break ;
}
return "<unknown>" ;
}
typedef Cost_cache <Polyhedron> P_cost_cache ;
typedef Cost_and_placement_cache<Polyhedron> P_cost_and_placement_cache ;
typedef Cached_cost <Polyhedron> P_cached_cost ;
typedef Edge_length_cost <Polyhedron> P_MP_cost ;
typedef LindstromTurk_cost<Polyhedron> P_LT_cost ;
typedef Cached_placement<Polyhedron> P_cached_placement ;
typedef Midpoint_placement<Polyhedron> P_MP_placement ;
typedef LindstromTurk_placement<Polyhedron> P_LT_placement ;
typedef Set_no_cache<Polyhedron> P_set_no_cache ;
typedef Set_cost_cache<Polyhedron,P_MP_cost> P_set_cost_cache_MP ;
typedef LindstromTurk_set_cost_cache<Polyhedron> P_set_cost_cache_LT ;
typedef Set_cost_and_placement_cache<Polyhedron,P_MP_cost,P_MP_placement> P_set_cost_and_placement_cache_MP ;
typedef LindstromTurk_set_cost_and_placement_cache<Polyhedron> P_set_cost_and_placement_cache_LT ;
void Simplify ( int aStopA, int aStopR, bool aJustPrintSurfaceData, string aName, Method aMethod, Cache aCache )
{
string off_name = aName ;
string result_name = aName+string(".out.off");
ifstream off_is(off_name.c_str());
if ( off_is )
{
Polyhedron lP;
scan_OFF(off_is,lP,true);
if ( lP.is_valid() )
{
if ( lP.is_pure_triangle() )
{
if ( !aJustPrintSurfaceData )
{
size_t lRequestedEdgeCount ;
if ( aStopA != -1 )
lRequestedEdgeCount = aStopA ;
else lRequestedEdgeCount = lP.size_of_halfedges() * aStopR / 200 ;
cout << "Testing simplification of surface " << off_name
<< " using " << method_to_string(aMethod) << " method"
<< " with " << cache_to_string(aCache) << " cache." << endl ;
cout << lP.size_of_facets() << " triangles." << endl
<< (lP.size_of_halfedges()/2) << " edges." << endl
<< lP.size_of_vertices() << " vertices." << endl
<< (lP.is_closed() ? "Closed." : "Open." ) << endl
<< "Requested edge count: " << lRequestedEdgeCount << endl ;
cout << setprecision(19) ;
set_halfedgeds_items_id(lP);
P_cached_cost get_cached_cost ;
P_MP_cost get_MP_cost;
P_LT_cost get_LT_cost;
P_cached_placement get_cached_placement ;
P_MP_placement get_MP_placement;
P_LT_placement get_LT_placement;
P_set_no_cache set_no_cache ;
P_set_cost_cache_MP set_cost_cache_MP(get_MP_cost) ;
P_set_cost_cache_LT set_cost_cache_LT ;
P_set_cost_and_placement_cache_MP set_cost_and_placement_cache_MP(get_MP_cost,get_MP_placement) ;
P_set_cost_and_placement_cache_LT set_cost_and_placement_cache_LT ;
Count_stop_predicate<Polyhedron> stop(lRequestedEdgeCount);
Visitor lVisitor(lRequestedEdgeCount) ;
int r = -1 ;
Real_timer t ; t.start();
switch( aMethod )
{
case MP:
switch ( aCache )
{
case None :
r = edge_collapse(lP
,stop
,set_cache(set_no_cache)
.get_cost(get_MP_cost)
.get_placement(get_MP_placement)
.visitor(&lVisitor)
);
break ;
case Cost :
r = edge_collapse(lP
,stop
,set_cache(set_cost_cache_MP)
.get_cost(get_cached_cost)
.get_placement(get_MP_placement)
.visitor(&lVisitor)
);
break ;
case CostPlacement :
r = edge_collapse(lP
,stop
,set_cache(set_cost_and_placement_cache_MP)
.get_cost(get_cached_cost)
.get_placement(get_cached_placement)
.visitor(&lVisitor)
);
break ;
}
break ;
case LT:
switch ( aCache )
{
case None :
r = edge_collapse(lP
,stop
,set_cache(set_no_cache)
.get_cost(get_LT_cost)
.get_placement(get_LT_placement)
.visitor(&lVisitor)
);
break ;
case Cost :
r = edge_collapse(lP
,stop
,set_cache(set_cost_cache_LT)
.get_cost(get_cached_cost)
.get_placement(get_LT_placement)
.visitor(&lVisitor)
);
break ;
case CostPlacement :
r = edge_collapse(lP
,stop
,set_cache(set_cost_and_placement_cache_LT)
.get_cost(get_cached_cost)
.get_placement(get_cached_placement)
.visitor(&lVisitor)
);
break ;
}
break ;
}
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" ) ;
}
else
{
cout << off_name << ": " << lP.size_of_facets() << " triangles, "
<< (lP.size_of_halfedges()/2) << " edges, "
<< lP.size_of_vertices() << " vertices, "
<< (lP.is_closed() ? "Closed." : "Open." ) << endl ;
}
}
else
{
cerr << "Surfaces is not triangulated (has faces with more than 3 sides): " << aName << endl ;
}
}
else
{
cerr << "Invalid surface: " << aName << endl ;
}
}
else
{
cerr << "Unable to open test file " << aName << endl ;
}
}
bool sPrintUsage = false ;
void add_case( string aCase, vector<string>& rCases )
{
bool lAdded = false ;
string::size_type pos = aCase.find_last_of(".") ;
if ( pos != string::npos )
{
string ext = aCase.substr(pos);
if ( ext == ".off" )
{
rCases.push_back(aCase);
lAdded = true ;
}
}
if ( !lAdded )
{
sPrintUsage = true ;
cerr << "Invalid input file. Only .off files are supported: " << aCase << endl ;
}
}
int main( int argc, char** argv )
{
set_error_handler (error_handler);
set_warning_handler(error_handler);
bool lJustPrintSurfaceData = false ;
int lStopA = -1 ;
int lStopR = 20 ;
Method lMethod = LT ;
Cache lCache = CostPlacement ;
string lFolder ="";
vector<string> lCases ;
for ( int i = 1 ; i < argc ; ++i )
{
string opt(argv[i]);
if ( opt[0] == '-' )
{
switch(opt[1])
{
case 'd' : lFolder = opt.substr(2); break ;
case 'a' : lStopA = lexical_cast<int>(opt.substr(2)); break;
case 'r' : lStopR = lexical_cast<int>(opt.substr(2)); break;
case 'n' : lJustPrintSurfaceData = true ; break ;
case 'm' : lMethod = (Method)lexical_cast<int>(opt.substr(2)); break ;
case 'c' : lCache = (Cache)lexical_cast<int>(opt.substr(2)); break ;
default:
cerr << "Invalid option: " << opt << endl ;
sPrintUsage = true ;
}
}
}
for ( int i = 1 ; i < argc ; ++i )
{
string opt(argv[i]);
if ( opt[0] == '@' )
{
string rspname = opt.substr(1) ;
ifstream rsp(rspname.c_str());
if ( rsp )
{
string line ;
while ( getline(rsp,line) )
add_case(lFolder+line,lCases);
}
else
{
cerr << "Cannot open response file: " << rspname << endl ;
sPrintUsage = true ;
}
}
else if ( opt[0] != '-' )
{
add_case(lFolder+opt,lCases);
}
}
if ( lCases.size() == 0 )
sPrintUsage = true ;
if ( sPrintUsage )
{
cout << "edge_collapse_demo <options> file0 file1 ... fileN @response_file" << endl
<< " options: " << endl
<< " -m method method: 0=LindstromTurk[default] 1=Midpoint" << endl
<< " -c data_cache_level level: 0=None 1=Only cost cached 2=Both cost and placement cached[default]" << endl
<< " -d folder Specifies the folder where the files are located. " << endl
<< " -a absolute_max_edge_count Sets the final number of edges as absolute number." << endl
<< " -r relative_max_edge_count Sets the final number of edges as a percentage." << endl
<< " -n Do not simplify but simply report data of surfaces." << endl ;
return 1 ;
}
else
{
for ( vector<string>::const_iterator it = lCases.begin(); it != lCases.end() ; ++ it )
Simplify( lStopA, lStopR, lJustPrintSurfaceData, *it, lMethod, lCache) ;
return 0 ;
}
}
// EOF //

View File

@ -14,10 +14,10 @@ include $(CGAL_MAKEFILE)
#---------------------------------------------------------------------#
CXXFLAGS = -I../../include/\
-I../../../BGL/include\
$(TESTSUITE_CXXFLAGS) \
$(EXTRA_FLAGS) \
$(CGAL_CXXFLAGS) \
$(DEBUG_OPT)
$(CGAL_CXXFLAGS)
#---------------------------------------------------------------------#
# linker flags
@ -29,20 +29,18 @@ LIBPATH = \
LDFLAGS = \
$(TESTSUITE_LDFLAGS) \
$(CGAL_LDFLAGS)
$(CGAL_LDFLAGS)
#---------------------------------------------------------------------#
# target entries
#---------------------------------------------------------------------#
all: \
simplification_demo
all: edge_collapse_demo
simplification_demo$(EXE_EXT): simplification_demo$(OBJ_EXT)
$(CGAL_CXX) $(LIBPATH) $(EXE_OPT)simplification_demo simplification_demo$(OBJ_EXT) $(LDFLAGS)
edge_collapse_demo$(EXE_EXT): edge_collapse_demo$(OBJ_EXT)
$(CGAL_CXX) $(LIBPATH) $(EXE_OPT)edge_collapse_demo edge_collapse_demo$(OBJ_EXT) $(LDFLAGS)
clean: \
simplification_demo.clean
clean: edge_collapse_demo.clean
#---------------------------------------------------------------------#
# suffix rules

View File

@ -1,319 +0,0 @@
// 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
//Borland, Microsoft and Intel compiler are excluded
#if defined(__BORLANDC__) || defined(_MSC_VER)
#include <iostream>
#include <fstream>
int main() {
std::cout << "Geomview doesn't work on Windows, so no demo." << std::endl;
return 0;
}
#else // not windows
#include <iostream>
#include <iomanip>
//#define VISUALIZE
#include <CGAL/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_TRACE 4
void Surface_simplification_external_trace( std::string s )
{
std::cout << s << std::endl ;
}
#include <CGAL/Surface_mesh_simplification_vertex_pair_collapse.h>
#include <CGAL/Surface_mesh_simplification/Policies/Construct_minimal_collapse_data.h>
#include <CGAL/Surface_mesh_simplification/Policies/Edge_length_cost.h>
#include <CGAL/Surface_mesh_simplification/Policies/Midpoint_vertex_placement.h>
#include <CGAL/Surface_mesh_simplification/Policies/LindstromTurk.h>
#include <CGAL/Surface_mesh_simplification/Policies/Count_stop_pred.h>
#include <iostream>
#include <fstream>
template <class Refs, class Traits>
struct My_vertex : public CGAL::HalfedgeDS_vertex_base<Refs,CGAL::Tag_true,typename Traits::Point_3>
{
typedef CGAL::HalfedgeDS_vertex_base<Refs,CGAL::Tag_true,typename Traits::Point_3> Base ;
My_vertex() {}
My_vertex( typename Traits::Point_3 p ) : Base(p) {}
int ID;
} ;
template <class Refs, class Traits>
struct My_halfedge : public CGAL::HalfedgeDS_halfedge_base<Refs>
{
My_halfedge() {}
int ID;
};
template <class Refs, class Traits>
struct My_face : public CGAL::HalfedgeDS_face_base<Refs,CGAL::Tag_true,typename Traits::Plane_3>
{
typedef CGAL::HalfedgeDS_face_base<Refs,CGAL::Tag_true,typename Traits::Plane_3> Base ;
My_face() {}
My_face( typename Traits::Plane_3 plane ) : Base(plane) {}
int ID;
};
struct My_items : public CGAL::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 CGAL::Cartesian<double> Kernel;
typedef Kernel::Vector_3 Vector;
typedef Kernel::Point_3 Point;
typedef CGAL::Polyhedron_3<Kernel,My_items> Polyhedron;
typedef Polyhedron::Vertex Vertex;
typedef Polyhedron::Vertex_iterator Vertex_iterator;
typedef Polyhedron::Halfedge_handle Halfedge_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;
void create_center_vertex( Polyhedron& P, Facet_iterator f) {
Vector vec( 0.0, 0.0, 0.0);
std::size_t order = 0;
HF_circulator h = f->facet_begin();
do {
vec = vec + ( h->vertex()->point() - CGAL::ORIGIN);
++ order;
} while ( ++h != f->facet_begin());
CGAL_assertion( order >= 3); // guaranteed by definition of polyhedron
Point center = CGAL::ORIGIN + (vec / order);
Halfedge_handle new_center = P.create_center_vertex( f->halfedge());
new_center->vertex()->point() = center;
}
struct Smooth_old_vertex {
Point operator()( const Vertex& v) const {
CGAL_precondition((CGAL::circulator_size( v.vertex_begin()) & 1) == 0);
std::size_t degree = CGAL::circulator_size( v.vertex_begin()) / 2;
double alpha = ( 4.0 - 2.0 * std::cos( 2.0 * CGAL_PI / degree)) / 9.0;
Vector vec = (v.point() - CGAL::ORIGIN) * ( 1.0 - alpha);
HV_circulator h = v.vertex_begin();
do {
vec = vec + ( h->opposite()->vertex()->point() - CGAL::ORIGIN)
* alpha / degree;
++ h;
CGAL_assertion( h != v.vertex_begin()); // even degree guaranteed
++ h;
} while ( h != v.vertex_begin());
return (CGAL::ORIGIN + vec);
}
};
void flip_edge( Polyhedron& P, Halfedge_handle e) {
Halfedge_handle h = e->next();
P.join_facet( e);
P.split_facet( h, h->next()->next());
}
void subdiv( Polyhedron& P) {
if ( P.size_of_facets() == 0)
return;
// We use that new vertices/halfedges/facets are appended at the end.
std::size_t nv = P.size_of_vertices();
Vertex_iterator last_v = P.vertices_end();
-- last_v; // the last of the old vertices
Edge_iterator last_e = P.edges_end();
-- last_e; // the last of the old edges
Facet_iterator last_f = P.facets_end();
-- last_f; // the last of the old facets
Facet_iterator f = P.facets_begin(); // create new center vertices
do {
create_center_vertex( P, f);
} while ( f++ != last_f);
std::vector<Point> pts; // smooth the old vertices
pts.reserve( nv); // get intermediate space for the new points
++ last_v; // make it the past-the-end position again
std::transform( P.vertices_begin(), last_v, std::back_inserter( pts),
Smooth_old_vertex());
std::copy( pts.begin(), pts.end(), P.points_begin());
Edge_iterator e = P.edges_begin(); // flip the old edges
++ last_e; // make it the past-the-end position again
while ( e != last_e) {
Halfedge_handle h = e;
++e; // careful, incr. before flip since flip destroys current edge
flip_edge( P, h);
};
CGAL_postcondition( P.is_valid());
}
// 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 )
{
std::cerr << "CGAL error: " << what << " violation!" << std::endl
<< "Expr: " << expr << std::endl
<< "File: " << file << std::endl
<< "Line: " << line << std::endl;
if ( msg != 0)
std::cerr << "Explanation:" << msg << std::endl;
}
using namespace CGAL::Triangulated_surface_mesh::Simplification ;
int Simplify_midpoint ( Polyhedron& aP, int aMax )
{
typedef Minimal_collapse_data<Polyhedron> CollapseData ;
Construct_minimal_collapse_data<Polyhedron> Construct_collapse_data ;
Edge_length_cost <CollapseData> Get_cost ;
Midpoint_vertex_placement<CollapseData> Get_vertex_point ;
Count_stop_condition <CollapseData> Should_stop(aMax);
return vertex_pair_collapse(aP,Construct_collapse_data,(void*)0,Get_cost,Get_vertex_point,Should_stop);
}
int Simplify_LT ( Polyhedron& aP, int aMax )
{
typedef LindstromTurk_collapse_data<Polyhedron> CollapseData ;
Construct_LindstromTurk_collapse_data<Polyhedron> Construct_collapse_data ;
LindstromTurk_cost <Polyhedron> Get_cost ;
LindstromTurk_vertex_placement <Polyhedron> Get_vertex_point ;
Count_stop_condition <CollapseData> Should_stop(aMax);
LindstromTurk_params lParams(1,1,1);
return vertex_pair_collapse(aP,Construct_collapse_data,&lParams,Get_cost,Get_vertex_point,Should_stop);
}
void Simplify ( Polyhedron& aP, int aMax )
{
std::cout << "Simplifying surface with " << (aP.size_of_halfedges()/2) << " edges..." << std::endl ;
#ifdef VISUALIZE
CGAL::Geomview_stream gv;
gv.set_bg_color(CGAL::BLACK);
gv.set_face_color(CGAL::WHITE);
gv.set_edge_color(CGAL::BLUE);
gv.set_vertex_color(CGAL::RED);
#endif
std::cout << std::setprecision(19) ;
int lVertexID = 0 ;
for ( Polyhedron::Vertex_iterator vi = aP.vertices_begin(); vi != aP.vertices_end() ; ++ vi )
vi->ID = lVertexID ++ ;
int lHalfedgeID = 0 ;
for ( Polyhedron::Halfedge_iterator hi = aP.halfedges_begin(); hi != aP.halfedges_end() ; ++ hi )
hi->ID = lHalfedgeID++ ;
int lFacetID = 0 ;
for ( Polyhedron::Facet_iterator fi = aP.facets_begin(); fi != aP.facets_end() ; ++ fi )
fi->ID = lFacetID ++ ;
int r = Simplify_LT(aP,aMax);
std::cout << "Finished...\n"
<< r << " edges removed.\n"
<< aP.size_of_vertices() << " vertices.\n"
<< (aP.size_of_halfedges()/2) << " edges.\n"
<< aP.size_of_facets() << " triangles.\n"
<< ( aP.is_valid() ? " valid" : " INVALID!!" )
<< std::endl ;
#ifdef VISUALIZE
gv << aP ;
std::cout << "Press any key to finish..." << std::endl ;
char k ;
std::cin >> k ;
#endif
}
int main( int argc, char** argv )
{
CGAL::set_error_handler (error_handler);
CGAL::set_warning_handler(error_handler);
Polyhedron lP;
char const* infile = argc > 1 ? argv[1] : "./data/tetra2.off" ; //"./data/Sample0.off" ;
std::ifstream in(infile);
if ( in )
{
in >> lP ;
int lMax = argc > 2 ? std::atoi(argv[2]) : 1 ; // 1000
Simplify(lP,lMax);
char const* of = argc > 3 ? argv[3] : 0 ;
std::string outfile = !of ? std::string(infile) + std::string(".out.off") : of ;
std::ofstream out(outfile.c_str());
if ( out )
{
out << lP ;
}
else
{
std::cerr << "Unable to open out file: " << outfile << std::endl ;
}
}
else
{
std::cerr << "Input file not found: " << infile << std::endl ;
}
return 0;
}
#endif // not windows
// EOF //