Documentation for decimater modules, updated decimater, more modules
git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@460 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
@@ -138,16 +138,16 @@ public: // inherited
|
|||||||
|
|
||||||
// to be compatible with gcc 2.95.3
|
// to be compatible with gcc 2.95.3
|
||||||
{
|
{
|
||||||
decimater_o tmp( new decimater_t ( mesh() ) );
|
decimater_o tmp( new decimater_t ( mesh() ) );
|
||||||
decimater_ = tmp;
|
decimater_ = tmp;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
mod_quadric_o tmp( new mod_quadric_t( *decimater_ ) );
|
mod_quadric_o tmp( new mod_quadric_t( *decimater_ ) );
|
||||||
mod_quadric_ = tmp;
|
mod_quadric_ = tmp;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
mod_nf_o tmp( new mod_nf_t ( *decimater_ ) );
|
mod_nf_o tmp( new mod_nf_t ( *decimater_ ) );
|
||||||
mod_nf_ = tmp;
|
mod_nf_ = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
decimater_->initialize();
|
decimater_->initialize();
|
||||||
|
|||||||
@@ -64,6 +64,10 @@
|
|||||||
#include <OpenMesh/Tools/Utils/getopt.h>
|
#include <OpenMesh/Tools/Utils/getopt.h>
|
||||||
#include <OpenMesh/Tools/Utils/Timer.hh>
|
#include <OpenMesh/Tools/Utils/Timer.hh>
|
||||||
#include <OpenMesh/Tools/Decimater/DecimaterT.hh>
|
#include <OpenMesh/Tools/Decimater/DecimaterT.hh>
|
||||||
|
#include <OpenMesh/Tools/Decimater/ModAspectRatioT.hh>
|
||||||
|
#include <OpenMesh/Tools/Decimater/ModEdgeLengthT.hh>
|
||||||
|
#include <OpenMesh/Tools/Decimater/ModHausdorffT.hh>
|
||||||
|
#include <OpenMesh/Tools/Decimater/ModNormalDeviationT.hh>
|
||||||
#include <OpenMesh/Tools/Decimater/ModNormalFlippingT.hh>
|
#include <OpenMesh/Tools/Decimater/ModNormalFlippingT.hh>
|
||||||
#include <OpenMesh/Tools/Decimater/ModQuadricT.hh>
|
#include <OpenMesh/Tools/Decimater/ModQuadricT.hh>
|
||||||
#include <OpenMesh/Tools/Decimater/ModProgMeshT.hh>
|
#include <OpenMesh/Tools/Decimater/ModProgMeshT.hh>
|
||||||
@@ -111,17 +115,21 @@ void usage_and_exit(int xcode);
|
|||||||
struct DecOptions
|
struct DecOptions
|
||||||
{
|
{
|
||||||
DecOptions()
|
DecOptions()
|
||||||
: n_collapses(0)
|
: n_collapses(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
CmdOption<bool> decorate_name;
|
CmdOption<bool> decorate_name;
|
||||||
CmdOption<float> n_collapses;
|
CmdOption<float> n_collapses;
|
||||||
CmdOption<float> Q; // Quadrics
|
|
||||||
CmdOption<float> NF; // Normal Flipping
|
|
||||||
CmdOption<bool> IS; // Independent Sets
|
|
||||||
CmdOption<std::string> PM; // Progressive Mesh
|
|
||||||
CmdOption<float> R; // Roundness
|
|
||||||
|
|
||||||
|
CmdOption<float> AR; // Aspect ratio
|
||||||
|
CmdOption<float> EL; // Edge length
|
||||||
|
CmdOption<float> HD; // Hausdorff distance
|
||||||
|
CmdOption<bool> IS; // Independent Sets
|
||||||
|
CmdOption<float> ND; // Normal deviation
|
||||||
|
CmdOption<float> NF; // Normal flipping
|
||||||
|
CmdOption<std::string> PM; // Progressive Mesh
|
||||||
|
CmdOption<float> Q; // Quadrics
|
||||||
|
CmdOption<float> R; // Roundness
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool init( CmdOption<T>& _o, const std::string& _val )
|
bool init( CmdOption<T>& _o, const std::string& _val )
|
||||||
@@ -135,8 +143,8 @@ struct DecOptions
|
|||||||
T v;
|
T v;
|
||||||
|
|
||||||
if ( (istr >> v).fail() )
|
if ( (istr >> v).fail() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_o = v;
|
_o = v;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -159,28 +167,31 @@ struct DecOptions
|
|||||||
}
|
}
|
||||||
strip(name);
|
strip(name);
|
||||||
strip(value);
|
strip(value);
|
||||||
|
|
||||||
if (name == "Q") return init(Q, value);
|
if (name == "AR") return init(AR, value);
|
||||||
|
if (name == "EL") return init(EL, value);
|
||||||
|
if (name == "HD") return init(HD, value);
|
||||||
|
if (name == "IS") return init(IS, value);
|
||||||
|
if (name == "ND") return init(ND, value);
|
||||||
if (name == "NF") return init(NF, value);
|
if (name == "NF") return init(NF, value);
|
||||||
if (name == "PM") return init(PM, value);
|
if (name == "PM") return init(PM, value);
|
||||||
if (name == "IS") return init(IS, value);
|
if (name == "Q") return init(Q, value);
|
||||||
if (name == "R") return init(R, value);
|
if (name == "R") return init(R, value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string& strip(std::string & line)
|
std::string& strip(std::string & line)
|
||||||
{
|
{
|
||||||
std::string::size_type pos = 0;
|
std::string::size_type pos = 0;
|
||||||
|
|
||||||
pos = line.find_last_not_of(" \t");
|
pos = line.find_last_not_of(" \t");
|
||||||
|
|
||||||
if ( pos!=0 && pos!=std::string::npos )
|
if ( pos!=0 && pos!=std::string::npos )
|
||||||
{
|
{
|
||||||
++pos;
|
++pos;
|
||||||
line.erase( pos, line.length()-pos );
|
line.erase( pos, line.length()-pos );
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = line.find_first_not_of(" \t");
|
pos = line.find_first_not_of(" \t");
|
||||||
if ( pos!=0 && pos!=std::string::npos )
|
if ( pos!=0 && pos!=std::string::npos )
|
||||||
{
|
{
|
||||||
@@ -198,7 +209,7 @@ template <typename Mesh, typename Decimater>
|
|||||||
bool
|
bool
|
||||||
decimate(const std::string &_ifname,
|
decimate(const std::string &_ifname,
|
||||||
const std::string &_ofname,
|
const std::string &_ofname,
|
||||||
DecOptions &_opt)
|
DecOptions &_opt)
|
||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -211,7 +222,7 @@ decimate(const std::string &_ifname,
|
|||||||
if (gverbose)
|
if (gverbose)
|
||||||
clog << "source mesh: ";
|
clog << "source mesh: ";
|
||||||
bool rc;
|
bool rc;
|
||||||
|
|
||||||
if (gverbose)
|
if (gverbose)
|
||||||
clog << _ifname << endl;
|
clog << _ifname << endl;
|
||||||
if ( !(rc = OpenMesh::IO::read_mesh(mesh, _ifname, opt)) )
|
if ( !(rc = OpenMesh::IO::read_mesh(mesh, _ifname, opt)) )
|
||||||
@@ -220,7 +231,7 @@ decimate(const std::string &_ifname,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------- do some decimation
|
// ---------------------------------------- do some decimation
|
||||||
{
|
{
|
||||||
// ---- 0 - For module NormalFlipping one needs face normals
|
// ---- 0 - For module NormalFlipping one needs face normals
|
||||||
@@ -228,50 +239,87 @@ decimate(const std::string &_ifname,
|
|||||||
if ( !opt.check( OpenMesh::IO::Options::FaceNormal ) )
|
if ( !opt.check( OpenMesh::IO::Options::FaceNormal ) )
|
||||||
{
|
{
|
||||||
if ( !mesh.has_face_normals() )
|
if ( !mesh.has_face_normals() )
|
||||||
mesh.request_face_normals();
|
mesh.request_face_normals();
|
||||||
|
|
||||||
if (gverbose)
|
if (gverbose)
|
||||||
clog << " updating face normals" << endl;
|
clog << " updating face normals" << endl;
|
||||||
mesh.update_face_normals();
|
mesh.update_face_normals();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- 1 - create decimater instance
|
// ---- 1 - create decimater instance
|
||||||
Decimater decimater( mesh );
|
Decimater decimater( mesh );
|
||||||
|
|
||||||
// ---- 2 - registrate modules
|
|
||||||
if (gverbose)
|
|
||||||
clog << " registrate modules" << endl;
|
|
||||||
|
|
||||||
|
|
||||||
typename OpenMesh::Decimater::ModQuadricT<Decimater>::Handle modQ;
|
|
||||||
|
|
||||||
if (_opt.Q.is_enabled())
|
// ---- 2 - register modules
|
||||||
|
if (gverbose)
|
||||||
|
clog << " register modules" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typename OpenMesh::Decimater::ModAspectRatioT<Decimater>::Handle modAR;
|
||||||
|
|
||||||
|
if (_opt.AR.is_enabled())
|
||||||
{
|
{
|
||||||
decimater.add(modQ);
|
decimater.add(modAR);
|
||||||
if (_opt.Q.has_value())
|
if (_opt.AR.has_value())
|
||||||
decimater.module( modQ ).set_max_err( _opt.Q );
|
decimater.module( modAR ).set_aspect_ratio( _opt.AR ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename OpenMesh::Decimater::ModEdgeLengthT<Decimater>::Handle modEL;
|
||||||
|
|
||||||
|
if (_opt.EL.is_enabled())
|
||||||
|
{
|
||||||
|
decimater.add(modEL);
|
||||||
|
if (_opt.EL.has_value())
|
||||||
|
decimater.module( modEL ).set_edge_length( _opt.EL ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename OpenMesh::Decimater::ModHausdorffT <Decimater>::Handle modHD;
|
||||||
|
|
||||||
|
if (_opt.HD.is_enabled())
|
||||||
|
{
|
||||||
|
decimater.add(modHD);
|
||||||
|
if (_opt.HD.has_value())
|
||||||
|
decimater.module( modHD ).set_tolerance( _opt.HD ) ;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
typename OpenMesh::Decimater::ModIndependentSetsT<Decimater>::Handle modIS;
|
||||||
|
|
||||||
|
if ( _opt.IS.is_enabled() )
|
||||||
|
decimater.add(modIS);
|
||||||
|
|
||||||
|
typename OpenMesh::Decimater::ModNormalDeviationT<Decimater>::Handle modND;
|
||||||
|
|
||||||
|
if (_opt.ND.is_enabled())
|
||||||
|
{
|
||||||
|
decimater.add(modND);
|
||||||
|
if (_opt.ND.has_value())
|
||||||
|
decimater.module( modND ).set_normal_deviation( _opt.ND );
|
||||||
}
|
}
|
||||||
|
|
||||||
typename OpenMesh::Decimater::ModNormalFlippingT<Decimater>::Handle modNF;
|
typename OpenMesh::Decimater::ModNormalFlippingT<Decimater>::Handle modNF;
|
||||||
|
|
||||||
if (_opt.NF.is_enabled())
|
if (_opt.NF.is_enabled())
|
||||||
{
|
{
|
||||||
decimater.add(modNF);
|
decimater.add(modNF);
|
||||||
if (_opt.NF.has_value())
|
if (_opt.NF.has_value())
|
||||||
decimater.module( modNF ).set_normal_deviation( _opt.NF );
|
decimater.module( modNF ).set_max_normal_deviation( _opt.NF );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typename OpenMesh::Decimater::ModProgMeshT<Decimater>::Handle modPM;
|
typename OpenMesh::Decimater::ModProgMeshT<Decimater>::Handle modPM;
|
||||||
|
|
||||||
if ( _opt.PM.is_enabled() )
|
if ( _opt.PM.is_enabled() )
|
||||||
decimater.add(modPM);
|
decimater.add(modPM);
|
||||||
|
|
||||||
|
typename OpenMesh::Decimater::ModQuadricT<Decimater>::Handle modQ;
|
||||||
|
|
||||||
typename OpenMesh::Decimater::ModIndependentSetsT<Decimater>::Handle modIS;
|
if (_opt.Q.is_enabled())
|
||||||
|
{
|
||||||
if ( _opt.IS.is_enabled() )
|
decimater.add(modQ);
|
||||||
decimater.add(modIS);
|
if (_opt.Q.has_value())
|
||||||
|
decimater.module( modQ ).set_max_err( _opt.Q );
|
||||||
|
}
|
||||||
|
|
||||||
typename OpenMesh::Decimater::ModRoundnessT<Decimater>::Handle modR;
|
typename OpenMesh::Decimater::ModRoundnessT<Decimater>::Handle modR;
|
||||||
|
|
||||||
@@ -279,16 +327,16 @@ decimate(const std::string &_ifname,
|
|||||||
{
|
{
|
||||||
decimater.add( modR );
|
decimater.add( modR );
|
||||||
if ( _opt.R.has_value() )
|
if ( _opt.R.has_value() )
|
||||||
decimater.module( modR ).set_min_angle( _opt.R,
|
decimater.module( modR ).set_min_angle( _opt.R,
|
||||||
!modQ.is_valid() ||
|
!modQ.is_valid() ||
|
||||||
!decimater.module(modQ).is_binary());
|
!decimater.module(modQ).is_binary());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- 3 - initialize decimater
|
// ---- 3 - initialize decimater
|
||||||
|
|
||||||
if (gverbose)
|
if (gverbose)
|
||||||
clog << "initializing mesh" << endl;
|
clog << "initializing mesh" << endl;
|
||||||
|
|
||||||
{
|
{
|
||||||
bool rc;
|
bool rc;
|
||||||
timer.start();
|
timer.start();
|
||||||
@@ -296,8 +344,8 @@ decimate(const std::string &_ifname,
|
|||||||
timer.stop();
|
timer.stop();
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
std::cerr << " initializing failed!" << std::endl;
|
std::cerr << " initializing failed!" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gverbose)
|
if (gverbose)
|
||||||
@@ -325,12 +373,12 @@ decimate(const std::string &_ifname,
|
|||||||
else if (_opt.n_collapses > 0.0f)
|
else if (_opt.n_collapses > 0.0f)
|
||||||
rc = decimater.decimate_to(size_t(mesh.n_vertices()*_opt.n_collapses));
|
rc = decimater.decimate_to(size_t(mesh.n_vertices()*_opt.n_collapses));
|
||||||
timer.stop();
|
timer.stop();
|
||||||
|
|
||||||
// ---- 5 - write progmesh file for progviewer (before garbage collection!)
|
// ---- 5 - write progmesh file for progviewer (before garbage collection!)
|
||||||
|
|
||||||
if ( _opt.PM.has_value() )
|
if ( _opt.PM.has_value() )
|
||||||
decimater.module(modPM).write( _opt.PM );
|
decimater.module(modPM).write( _opt.PM );
|
||||||
|
|
||||||
// ---- 6 - throw away all tagged edges
|
// ---- 6 - throw away all tagged edges
|
||||||
|
|
||||||
mesh.garbage_collection();
|
mesh.garbage_collection();
|
||||||
@@ -339,13 +387,13 @@ decimate(const std::string &_ifname,
|
|||||||
{
|
{
|
||||||
std::clog << " # executed collapses: " << rc << std::endl;
|
std::clog << " # executed collapses: " << rc << std::endl;
|
||||||
std::clog << " # vertices: " << mesh.n_vertices() << ", "
|
std::clog << " # vertices: " << mesh.n_vertices() << ", "
|
||||||
<< ( 100.0*mesh.n_vertices()/nv_before ) << "%\n";
|
<< ( 100.0*mesh.n_vertices()/nv_before ) << "%\n";
|
||||||
std::clog << " Elapsed time: " << timer.as_string() << std::endl;
|
std::clog << " Elapsed time: " << timer.as_string() << std::endl;
|
||||||
std::clog << " collapses/s : " << rc/timer.seconds() << std::endl;
|
std::clog << " collapses/s : " << rc/timer.seconds() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// write resulting mesh
|
// write resulting mesh
|
||||||
if ( ! _ofname.empty() )
|
if ( ! _ofname.empty() )
|
||||||
{
|
{
|
||||||
@@ -373,12 +421,12 @@ decimate(const std::string &_ifname,
|
|||||||
if ( !OpenMesh::IO::write_mesh(mesh, ofname, opt ) )
|
if ( !OpenMesh::IO::write_mesh(mesh, ofname, opt ) )
|
||||||
{
|
{
|
||||||
std::cerr << " Cannot write decimated mesh to file '"
|
std::cerr << " Cannot write decimated mesh to file '"
|
||||||
<< ofname << "'\n";
|
<< ofname << "'\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::clog << " Exported decimated mesh to file '" << ofname << "'\n";
|
std::clog << " Exported decimated mesh to file '" << ofname << "'\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,24 +446,24 @@ int main(int argc, char* argv[])
|
|||||||
//---------------------------------------- parse command line
|
//---------------------------------------- parse command line
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
while ( (c=getopt( argc, argv, "dDhi:M:n:o:v")) != -1 )
|
while ( (c=getopt( argc, argv, "dDhi:M:n:o:v")) != -1 )
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 'D': opt.decorate_name = true; break;
|
case 'D': opt.decorate_name = true; break;
|
||||||
case 'd': gdebug = true; break;
|
case 'd': gdebug = true; break;
|
||||||
case 'h': usage_and_exit(0);
|
case 'h': usage_and_exit(0);
|
||||||
case 'i': ifname = optarg; break;
|
case 'i': ifname = optarg; break;
|
||||||
case 'M': opt.parse_argument( optarg ); break;
|
case 'M': opt.parse_argument( optarg ); break;
|
||||||
case 'n': opt.n_collapses = float(atof(optarg)); break;
|
case 'n': opt.n_collapses = float(atof(optarg)); break;
|
||||||
case 'o': ofname = optarg; break;
|
case 'o': ofname = optarg; break;
|
||||||
case 'v': gverbose = true; break;
|
case 'v': gverbose = true; break;
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
std::cerr << "FATAL: cannot process command line option!"
|
std::cerr << "FATAL: cannot process command line option!"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -467,40 +515,39 @@ int main(int argc, char* argv[])
|
|||||||
void usage_and_exit(int xcode)
|
void usage_and_exit(int xcode)
|
||||||
{
|
{
|
||||||
std::string errmsg;
|
std::string errmsg;
|
||||||
|
|
||||||
switch(xcode)
|
switch(xcode)
|
||||||
{
|
{
|
||||||
case 1: errmsg = "Option not supported!"; break;
|
case 1: errmsg = "Option not supported!"; break;
|
||||||
case 2: errmsg = "Invalid output file format!"; break;
|
case 2: errmsg = "Invalid output file format!"; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
if (xcode)
|
if (xcode) {
|
||||||
{
|
|
||||||
std::cerr << "Error " << xcode << ": " << errmsg << std::endl << std::endl;
|
std::cerr << "Error " << xcode << ": " << errmsg << std::endl << std::endl;
|
||||||
}
|
}
|
||||||
std::cerr << "Usage: decimator [Options] -i input-file -o output-file\n"
|
std::cerr << "Usage: decimator [Options] -i input-file -o output-file\n"
|
||||||
<< " Decimating a mesh using quadrics and normal flipping.\n"
|
<< " Decimating a mesh using quadrics and normal flipping.\n" << std::endl;
|
||||||
<< std::endl;
|
std::cerr << "Options\n" << std::endl;
|
||||||
std::cerr << "Options\n"
|
|
||||||
<< std::endl;
|
|
||||||
std::cerr << " -M \"{Module-Name}[:Value]}\"\n"
|
std::cerr << " -M \"{Module-Name}[:Value]}\"\n"
|
||||||
<< " Use named module with eventually given parameterization\n"
|
<< " Use named module with eventually given parameterization\n" << std::endl;
|
||||||
<< std::endl;
|
|
||||||
std::cerr << " -n <N>\n"
|
std::cerr << " -n <N>\n"
|
||||||
<< " N >= 1: do N halfedge collapses.\n"
|
<< " N >= 1: do N halfedge collapses.\n"
|
||||||
<< " N <=-1: decimate down to |N| vertices.\n"
|
<< " N <=-1: decimate down to |N| vertices.\n"
|
||||||
<< " 0 < N < 1: decimate down to N%.\n"
|
<< " 0 < N < 1: decimate down to N%.\n" << std::endl;
|
||||||
<< std::endl;
|
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
std::cerr << "Modules:\n\n";
|
std::cerr << "Modules:\n\n";
|
||||||
|
std::cerr << " AR[:ratio] - ModAspectRatio\n";
|
||||||
|
std::cerr << " EL[:legth] - ModEdgeLength\n";
|
||||||
|
std::cerr << " HD[:distance] - ModHausdorff\n";
|
||||||
std::cerr << " IS - ModIndependentSets\n";
|
std::cerr << " IS - ModIndependentSets\n";
|
||||||
|
std::cerr << " ND[:angle] - ModNormalDeviation\n";
|
||||||
std::cerr << " NF[:angle] - ModNormalFlipping\n";
|
std::cerr << " NF[:angle] - ModNormalFlipping\n";
|
||||||
std::cerr << " PM[:file name] - ModProgMesh\n";
|
std::cerr << " PM[:file name] - ModProgMesh\n";
|
||||||
std::cerr << " Q[:error] - ModQuadric\n";
|
std::cerr << " Q[:error] - ModQuadric\n";
|
||||||
std::cerr << " R[:angle] - ModRoundness\n";
|
std::cerr << " R[:angle] - ModRoundness\n";
|
||||||
std::cerr << " 0 < angle < 60\n";
|
std::cerr << " 0 < angle < 60\n";
|
||||||
|
|
||||||
exit( xcode );
|
exit( xcode );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,18 +30,18 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision$ *
|
* $Revision$ *
|
||||||
* $Date$ *
|
* $Date$ *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/** \file CollapseInfoT.hh
|
/** \file CollapseInfoT.hh
|
||||||
Provides data class CollapseInfoT for storing all information
|
Provides data class CollapseInfoT for storing all information
|
||||||
about a halfedge collapse.
|
about a halfedge collapse.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@@ -49,129 +49,111 @@
|
|||||||
// STRUCT CollpaseInfoT
|
// STRUCT CollpaseInfoT
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
#ifndef OPENMESH_DECIMATER_COLLAPSEINFOT_HH
|
#ifndef OPENMESH_DECIMATER_COLLAPSEINFOT_HH
|
||||||
#define OPENMESH_DECIMATER_COLLAPSEINFOT_HH
|
#define OPENMESH_DECIMATER_COLLAPSEINFOT_HH
|
||||||
|
|
||||||
|
|
||||||
//== INCLUDES =================================================================
|
//== INCLUDES =================================================================
|
||||||
|
|
||||||
|
|
||||||
//== NAMESPACE ================================================================
|
//== NAMESPACE ================================================================
|
||||||
|
|
||||||
namespace OpenMesh {
|
namespace OpenMesh {
|
||||||
namespace Decimater {
|
namespace Decimater {
|
||||||
|
|
||||||
|
|
||||||
//== CLASS DEFINITION =========================================================
|
//== CLASS DEFINITION =========================================================
|
||||||
|
|
||||||
/** Stores information about a halfedge collapse.
|
/** Stores information about a halfedge collapse.
|
||||||
|
|
||||||
The class stores information about a halfedge collapse. The most
|
The class stores information about a halfedge collapse. The most
|
||||||
important information is \c v0v1, \c v1v0, \c v0, \c v1, \c vl,
|
important information is \c v0v1, \c v1v0, \c v0, \c v1, \c vl,
|
||||||
\c vr, which you can lookup in the following image:
|
\c vr, which you can lookup in the following image:
|
||||||
\image html collapse_info.png
|
\image html collapse_info.png
|
||||||
\see ModProgMeshT::Info
|
\see ModProgMeshT::Info
|
||||||
*/
|
*/
|
||||||
template <class Mesh>
|
template<class Mesh>
|
||||||
struct CollapseInfoT
|
struct CollapseInfoT {
|
||||||
{
|
public:
|
||||||
public:
|
/** Initializing constructor.
|
||||||
/** Initializing constructor.
|
*
|
||||||
*
|
* Given a mesh and a halfedge handle of the halfedge to be collapsed
|
||||||
* Given a mesh and a halfedge handle of the halfedge to be collapsed
|
* all important information of a halfedge collapse will be stored.
|
||||||
* all important information of a halfedge collapse will be stored.
|
* \param _mesh Mesh source
|
||||||
* \param _mesh Mesh source
|
* \param _heh Halfedge to collapse. The direction of the halfedge
|
||||||
* \param _heh Halfedge to collapse. The direction of the halfedge
|
* defines the direction of the collapse, i.e. the from-vertex
|
||||||
* defines the direction of the collapse, i.e. the from-vertex
|
* will be removed and the to-vertex remains.
|
||||||
* will be removed and the to-vertex remains.
|
*/
|
||||||
*/
|
CollapseInfoT(Mesh& _mesh, typename Mesh::HalfedgeHandle _heh);
|
||||||
CollapseInfoT(Mesh& _mesh, typename Mesh::HalfedgeHandle _heh);
|
|
||||||
|
|
||||||
Mesh& mesh;
|
Mesh& mesh;
|
||||||
|
|
||||||
typename Mesh::HalfedgeHandle v0v1; ///< Halfedge to be collapsed
|
typename Mesh::HalfedgeHandle v0v1; ///< Halfedge to be collapsed
|
||||||
typename Mesh::HalfedgeHandle v1v0; ///< Reverse halfedge
|
typename Mesh::HalfedgeHandle v1v0; ///< Reverse halfedge
|
||||||
typename Mesh::VertexHandle v0; ///< Vertex to be removed
|
typename Mesh::VertexHandle v0; ///< Vertex to be removed
|
||||||
typename Mesh::VertexHandle v1; ///< Remaining vertex
|
typename Mesh::VertexHandle v1; ///< Remaining vertex
|
||||||
typename Mesh::Point p0; ///< Position of removed vertex
|
typename Mesh::Point p0; ///< Position of removed vertex
|
||||||
typename Mesh::Point p1; ///< Positions of remaining vertex
|
typename Mesh::Point p1; ///< Positions of remaining vertex
|
||||||
typename Mesh::FaceHandle fl; ///< Left face
|
typename Mesh::FaceHandle fl; ///< Left face
|
||||||
typename Mesh::FaceHandle fr; ///< Right face
|
typename Mesh::FaceHandle fr; ///< Right face
|
||||||
typename Mesh::VertexHandle vl; ///< Left vertex
|
typename Mesh::VertexHandle vl; ///< Left vertex
|
||||||
typename Mesh::VertexHandle vr; ///< Right vertex
|
typename Mesh::VertexHandle vr; ///< Right vertex
|
||||||
//@{
|
//@{
|
||||||
/** Outer remaining halfedge of diamond spanned by \c v0, \c v1,
|
/** Outer remaining halfedge of diamond spanned by \c v0, \c v1,
|
||||||
* \c vl, and \c vr
|
* \c vl, and \c vr
|
||||||
*/
|
*/
|
||||||
typename Mesh::HalfedgeHandle vlv1, v0vl, vrv0, v1vr;
|
typename Mesh::HalfedgeHandle vlv1, v0vl, vrv0, v1vr;
|
||||||
//@}
|
//@}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
// CollapseInfoT::CollapseInfoT( _mesh, _heh )
|
* Local configuration of halfedge collapse to be stored in CollapseInfoT:
|
||||||
//
|
*
|
||||||
// Local configuration of halfedge collapse to be stored in CollapseInfoT:
|
* vl
|
||||||
/*
|
* *
|
||||||
vl
|
* / \
|
||||||
*
|
* / \
|
||||||
/ \
|
* / fl \
|
||||||
/ \
|
* v0 *------>* v1
|
||||||
/ fl \
|
* \ fr /
|
||||||
v0 *------>* v1
|
* \ /
|
||||||
\ fr /
|
* \ /
|
||||||
\ /
|
* *
|
||||||
\ /
|
* vr
|
||||||
*
|
*
|
||||||
vr
|
*
|
||||||
|
* @param _mesh Reference to mesh
|
||||||
|
* @param _heh The halfedge (v0 -> v1) defining the collapse
|
||||||
*/
|
*/
|
||||||
// Parameters:
|
template<class Mesh>
|
||||||
// _mesh Reference to mesh
|
inline CollapseInfoT<Mesh>::CollapseInfoT(Mesh& _mesh,
|
||||||
// _heh The halfedge (v0 -> v1) defining the collapse
|
typename Mesh::HalfedgeHandle _heh) :
|
||||||
//
|
mesh(_mesh), v0v1(_heh), v1v0(_mesh.opposite_halfedge_handle(v0v1)), v0(
|
||||||
template <class Mesh>
|
_mesh.to_vertex_handle(v1v0)), v1(_mesh.to_vertex_handle(v0v1)), p0(
|
||||||
inline
|
_mesh.point(v0)), p1(_mesh.point(v1)), fl(_mesh.face_handle(v0v1)), fr(
|
||||||
CollapseInfoT<Mesh>::
|
_mesh.face_handle(v1v0))
|
||||||
CollapseInfoT(Mesh& _mesh, typename Mesh::HalfedgeHandle _heh) :
|
|
||||||
|
|
||||||
mesh(_mesh),
|
|
||||||
v0v1(_heh),
|
|
||||||
v1v0(_mesh.opposite_halfedge_handle(v0v1)),
|
|
||||||
v0(_mesh.to_vertex_handle(v1v0)),
|
|
||||||
v1(_mesh.to_vertex_handle(v0v1)),
|
|
||||||
p0(_mesh.point(v0)),
|
|
||||||
p1(_mesh.point(v1)),
|
|
||||||
fl(_mesh.face_handle(v0v1)),
|
|
||||||
fr(_mesh.face_handle(v1v0))
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// get vl
|
// get vl
|
||||||
if (fl.is_valid())
|
if (fl.is_valid()) {
|
||||||
{
|
|
||||||
vlv1 = mesh.next_halfedge_handle(v0v1);
|
vlv1 = mesh.next_halfedge_handle(v0v1);
|
||||||
v0vl = mesh.next_halfedge_handle(vlv1);
|
v0vl = mesh.next_halfedge_handle(vlv1);
|
||||||
vl = mesh.to_vertex_handle(vlv1);
|
vl = mesh.to_vertex_handle(vlv1);
|
||||||
vlv1 = mesh.opposite_halfedge_handle(vlv1);
|
vlv1 = mesh.opposite_halfedge_handle(vlv1);
|
||||||
v0vl = mesh.opposite_halfedge_handle(v0vl);
|
v0vl = mesh.opposite_halfedge_handle(v0vl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// get vr
|
// get vr
|
||||||
if (fr.is_valid())
|
if (fr.is_valid()) {
|
||||||
{
|
|
||||||
vrv0 = mesh.next_halfedge_handle(v1v0);
|
vrv0 = mesh.next_halfedge_handle(v1v0);
|
||||||
v1vr = mesh.next_halfedge_handle(vrv0);
|
v1vr = mesh.next_halfedge_handle(vrv0);
|
||||||
vr = mesh.to_vertex_handle(vrv0);
|
vr = mesh.to_vertex_handle(vrv0);
|
||||||
vrv0 = mesh.opposite_halfedge_handle(vrv0);
|
vrv0 = mesh.opposite_halfedge_handle(vrv0);
|
||||||
v1vr = mesh.opposite_halfedge_handle(v1vr);
|
v1vr = mesh.opposite_halfedge_handle(v1vr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
} // END_NS_DECIMATER
|
}// END_NS_DECIMATER
|
||||||
} // END_NS_OPENMESH
|
} // END_NS_OPENMESH
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
#endif // OPENMESH_DECIMATER_COLLAPSEINFOT_HH defined
|
#endif // OPENMESH_DECIMATER_COLLAPSEINFOT_HH defined
|
||||||
|
|||||||
@@ -30,28 +30,25 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision$ *
|
* $Revision$ *
|
||||||
* $Date$ *
|
* $Date$ *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/** \file DecimaterT.cc
|
/** \file DecimaterT.cc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// CLASS DecimaterT - IMPLEMENTATION
|
// CLASS DecimaterT - IMPLEMENTATION
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
#define OPENMESH_DECIMATER_DECIMATERT_CC
|
#define OPENMESH_DECIMATER_DECIMATERT_CC
|
||||||
|
|
||||||
|
|
||||||
//== INCLUDES =================================================================
|
//== INCLUDES =================================================================
|
||||||
|
|
||||||
#include <OpenMesh/Tools/Decimater/DecimaterT.hh>
|
#include <OpenMesh/Tools/Decimater/DecimaterT.hh>
|
||||||
@@ -63,26 +60,16 @@
|
|||||||
# include <cfloat>
|
# include <cfloat>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//== NAMESPACE ===============================================================
|
//== NAMESPACE ===============================================================
|
||||||
|
|
||||||
|
namespace OpenMesh {
|
||||||
namespace OpenMesh {
|
|
||||||
namespace Decimater {
|
namespace Decimater {
|
||||||
|
|
||||||
|
|
||||||
//== IMPLEMENTATION ==========================================================
|
//== IMPLEMENTATION ==========================================================
|
||||||
|
|
||||||
|
template<class Mesh>
|
||||||
|
DecimaterT<Mesh>::DecimaterT(Mesh& _mesh) :
|
||||||
template <class Mesh>
|
mesh_(_mesh), heap_(NULL), cmodule_(NULL), initialized_(false) {
|
||||||
DecimaterT<Mesh>::
|
|
||||||
DecimaterT( Mesh& _mesh )
|
|
||||||
: mesh_(_mesh),
|
|
||||||
heap_(NULL),
|
|
||||||
cmodule_(NULL),
|
|
||||||
initialized_(false)
|
|
||||||
{
|
|
||||||
// default properties
|
// default properties
|
||||||
mesh_.request_vertex_status();
|
mesh_.request_vertex_status();
|
||||||
mesh_.request_edge_status();
|
mesh_.request_edge_status();
|
||||||
@@ -90,19 +77,15 @@ DecimaterT( Mesh& _mesh )
|
|||||||
mesh_.request_face_normals();
|
mesh_.request_face_normals();
|
||||||
|
|
||||||
// private vertex properties
|
// private vertex properties
|
||||||
mesh_.add_property( collapse_target_ );
|
mesh_.add_property(collapse_target_);
|
||||||
mesh_.add_property( priority_ );
|
mesh_.add_property(priority_);
|
||||||
mesh_.add_property( heap_position_ );
|
mesh_.add_property(heap_position_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Mesh>
|
||||||
template <class Mesh>
|
DecimaterT<Mesh>::~DecimaterT() {
|
||||||
DecimaterT<Mesh>::
|
|
||||||
~DecimaterT()
|
|
||||||
{
|
|
||||||
// default properties
|
// default properties
|
||||||
mesh_.release_vertex_status();
|
mesh_.release_vertex_status();
|
||||||
mesh_.release_edge_status();
|
mesh_.release_edge_status();
|
||||||
@@ -118,40 +101,33 @@ DecimaterT<Mesh>::
|
|||||||
{
|
{
|
||||||
set_uninitialized();
|
set_uninitialized();
|
||||||
typename ModuleList::iterator m_it, m_end = all_modules_.end();
|
typename ModuleList::iterator m_it, m_end = all_modules_.end();
|
||||||
for( m_it=all_modules_.begin(); m_it!=m_end; ++m_it)
|
for (m_it = all_modules_.begin(); m_it != m_end; ++m_it)
|
||||||
delete *m_it;
|
delete *m_it;
|
||||||
all_modules_.clear();
|
all_modules_.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Mesh>
|
||||||
template <class Mesh>
|
void DecimaterT<Mesh>::info(std::ostream& _os) {
|
||||||
void
|
if (initialized_) {
|
||||||
DecimaterT<Mesh>::
|
|
||||||
info( std::ostream& _os )
|
|
||||||
{
|
|
||||||
if(initialized_)
|
|
||||||
{
|
|
||||||
_os << "initialized : yes" << std::endl;
|
_os << "initialized : yes" << std::endl;
|
||||||
_os << "binary modules: " << bmodules_.size() << std::endl;
|
_os << "binary modules: " << bmodules_.size() << std::endl;
|
||||||
for( ModuleListIterator m_it=bmodules_.begin(); m_it!=bmodules_.end(); ++m_it)
|
for (ModuleListIterator m_it = bmodules_.begin(); m_it != bmodules_.end();
|
||||||
{
|
++m_it) {
|
||||||
_os << " " << (*m_it)->name() << std::endl;
|
_os << " " << (*m_it)->name() << std::endl;
|
||||||
}
|
}
|
||||||
_os << "priority module: " << cmodule_->name().c_str() << std::endl;
|
_os << "priority module: " << cmodule_->name().c_str() << std::endl;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
_os << "initialized : no" << std::endl;
|
_os << "initialized : no" << std::endl;
|
||||||
_os << "available modules: " << all_modules_.size() << std::endl;
|
_os << "available modules: " << all_modules_.size() << std::endl;
|
||||||
for( ModuleListIterator m_it=all_modules_.begin(); m_it!=all_modules_.end(); ++m_it)
|
for (ModuleListIterator m_it = all_modules_.begin();
|
||||||
{
|
m_it != all_modules_.end(); ++m_it) {
|
||||||
_os << " " << (*m_it)->name() << " : ";
|
_os << " " << (*m_it)->name() << " : ";
|
||||||
if((*m_it)->is_binary()) {
|
if ((*m_it)->is_binary()) {
|
||||||
_os << "binary";
|
_os << "binary";
|
||||||
if((*m_it)->name() == "Quadric") {
|
if ((*m_it)->name() == "Quadric") {
|
||||||
_os << " and priority (special treatment)";
|
_os << " and priority (special treatment)";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -162,17 +138,11 @@ info( std::ostream& _os )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Mesh>
|
||||||
template <class Mesh>
|
bool DecimaterT<Mesh>::initialize() {
|
||||||
bool
|
if (initialized_) {
|
||||||
DecimaterT<Mesh>::
|
|
||||||
initialize()
|
|
||||||
{
|
|
||||||
if(initialized_)
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,17 +157,15 @@ initialize()
|
|||||||
// priority module explicitly.
|
// priority module explicitly.
|
||||||
|
|
||||||
// find the priority module: either the only non-binary module in the list, or "Quadric"
|
// find the priority module: either the only non-binary module in the list, or "Quadric"
|
||||||
Module *quadric=NULL;
|
Module *quadric = NULL;
|
||||||
Module *pmodule=NULL;
|
Module *pmodule = NULL;
|
||||||
for (ModuleListIterator m_it=all_modules_.begin(), m_end=all_modules_.end(); m_it != m_end; ++m_it)
|
for (ModuleListIterator m_it = all_modules_.begin(), m_end =
|
||||||
{
|
all_modules_.end(); m_it != m_end; ++m_it) {
|
||||||
if ( (*m_it)->name() == "Quadric")
|
if ((*m_it)->name() == "Quadric")
|
||||||
quadric = *m_it;
|
quadric = *m_it;
|
||||||
|
|
||||||
if ( !(*m_it)->is_binary() )
|
if (!(*m_it)->is_binary()) {
|
||||||
{
|
if (pmodule) {
|
||||||
if(pmodule)
|
|
||||||
{
|
|
||||||
// only one priority module allowed!
|
// only one priority module allowed!
|
||||||
set_uninitialized();
|
set_uninitialized();
|
||||||
return false;
|
return false;
|
||||||
@@ -207,11 +175,11 @@ initialize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Quadric is used as default priority module (even if it is set to be binary)
|
// Quadric is used as default priority module (even if it is set to be binary)
|
||||||
if(!pmodule && quadric) {
|
if (!pmodule && quadric) {
|
||||||
pmodule = quadric;
|
pmodule = quadric;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!pmodule) {
|
if (!pmodule) {
|
||||||
// At least one priority module required
|
// At least one priority module required
|
||||||
set_uninitialized();
|
set_uninitialized();
|
||||||
return false;
|
return false;
|
||||||
@@ -220,12 +188,12 @@ initialize()
|
|||||||
// set pmodule as the current priority module
|
// set pmodule as the current priority module
|
||||||
cmodule_ = pmodule;
|
cmodule_ = pmodule;
|
||||||
|
|
||||||
for(ModuleListIterator m_it=all_modules_.begin(), m_end=all_modules_.end(); m_it != m_end; ++m_it)
|
for (ModuleListIterator m_it = all_modules_.begin(), m_end =
|
||||||
{
|
all_modules_.end(); m_it != m_end; ++m_it) {
|
||||||
// every module gets initialized
|
// every module gets initialized
|
||||||
(*m_it)->initialize();
|
(*m_it)->initialize();
|
||||||
|
|
||||||
if(*m_it != pmodule) {
|
if (*m_it != pmodule) {
|
||||||
// all other modules are binary, and go into bmodules_ list
|
// all other modules are binary, and go into bmodules_ list
|
||||||
bmodules_.push_back(*m_it);
|
bmodules_.push_back(*m_it);
|
||||||
}
|
}
|
||||||
@@ -234,42 +202,35 @@ initialize()
|
|||||||
return initialized_ = true;
|
return initialized_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <class Mesh>
|
template<class Mesh>
|
||||||
bool
|
bool DecimaterT<Mesh>::is_collapse_legal(const CollapseInfo& _ci) {
|
||||||
DecimaterT<Mesh>::is_collapse_legal(const CollapseInfo& _ci)
|
|
||||||
{
|
|
||||||
// std::clog << "DecimaterT<>::is_collapse_legal()\n";
|
// std::clog << "DecimaterT<>::is_collapse_legal()\n";
|
||||||
|
|
||||||
// locked ? deleted ?
|
// locked ? deleted ?
|
||||||
if (mesh_.status(_ci.v0).locked() ||
|
if (mesh_.status(_ci.v0).locked() || mesh_.status(_ci.v0).deleted())
|
||||||
mesh_.status(_ci.v0).deleted())
|
|
||||||
return false;
|
return false;
|
||||||
/*
|
/*
|
||||||
if (!mesh_.is_collapse_ok(_ci.v0v1))
|
if (!mesh_.is_collapse_ok(_ci.v0v1))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (_ci.vl.is_valid() && _ci.vr.is_valid() &&
|
if (_ci.vl.is_valid() && _ci.vr.is_valid()
|
||||||
mesh_.find_halfedge(_ci.vl, _ci.vr).is_valid() &&
|
&& mesh_.find_halfedge(_ci.vl, _ci.vr).is_valid()
|
||||||
mesh_.valence(_ci.vl) == 3 && mesh_.valence(_ci.vr) == 3)
|
&& mesh_.valence(_ci.vl) == 3 && mesh_.valence(_ci.vr) == 3) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//--- feature test ---
|
//--- feature test ---
|
||||||
|
|
||||||
if (mesh_.status(_ci.v0).feature() &&
|
if (mesh_.status(_ci.v0).feature()
|
||||||
!mesh_.status(mesh_.edge_handle(_ci.v0v1)).feature())
|
&& !mesh_.status(mesh_.edge_handle(_ci.v0v1)).feature())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//--- test one ring intersection ---
|
//--- test one ring intersection ---
|
||||||
|
|
||||||
typename Mesh::VertexVertexIter vv_it;
|
typename Mesh::VertexVertexIter vv_it;
|
||||||
|
|
||||||
for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it)
|
for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it)
|
||||||
mesh_.status(vv_it).set_tagged(false);
|
mesh_.status(vv_it).set_tagged(false);
|
||||||
@@ -278,24 +239,19 @@ DecimaterT<Mesh>::is_collapse_legal(const CollapseInfo& _ci)
|
|||||||
mesh_.status(vv_it).set_tagged(true);
|
mesh_.status(vv_it).set_tagged(true);
|
||||||
|
|
||||||
for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it)
|
for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it)
|
||||||
if (mesh_.status(vv_it).tagged() &&
|
if (mesh_.status(vv_it).tagged() && vv_it.handle() != _ci.vl
|
||||||
vv_it.handle() != _ci.vl &&
|
&& vv_it.handle() != _ci.vr)
|
||||||
vv_it.handle() != _ci.vr)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// if both are invalid OR equal -> fail
|
// if both are invalid OR equal -> fail
|
||||||
if (_ci.vl == _ci.vr) return false;
|
if (_ci.vl == _ci.vr)
|
||||||
|
return false;
|
||||||
|
|
||||||
//--- test boundary cases ---
|
//--- test boundary cases ---
|
||||||
if (mesh_.is_boundary(_ci.v0))
|
if (mesh_.is_boundary(_ci.v0)) {
|
||||||
{
|
if (!mesh_.is_boundary(_ci.v1)) { // don't collapse a boundary vertex to an inner one
|
||||||
if (!mesh_.is_boundary(_ci.v1))
|
|
||||||
{// don't collapse a boundary vertex to an inner one
|
|
||||||
return false;
|
return false;
|
||||||
}
|
} else { // edge between two boundary vertices has to be a boundary edge
|
||||||
else
|
|
||||||
{// edge between two boundary vertices has to be a boundary edge
|
|
||||||
if (!(mesh_.is_boundary(_ci.v0v1) || mesh_.is_boundary(_ci.v1v0)))
|
if (!(mesh_.is_boundary(_ci.v0v1) || mesh_.is_boundary(_ci.v1v0)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -305,108 +261,88 @@ DecimaterT<Mesh>::is_collapse_legal(const CollapseInfo& _ci)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// v0vl and v1vl must not both be boundary edges
|
// v0vl and v1vl must not both be boundary edges
|
||||||
if (_ci.vl.is_valid() &&
|
if (_ci.vl.is_valid() && mesh_.is_boundary(_ci.vlv1)
|
||||||
mesh_.is_boundary(_ci.vlv1) &&
|
&& mesh_.is_boundary(_ci.v0vl))
|
||||||
mesh_.is_boundary(_ci.v0vl))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// v0vr and v1vr must not be both boundary edges
|
// v0vr and v1vr must not be both boundary edges
|
||||||
if (_ci.vr.is_valid() &&
|
if (_ci.vr.is_valid() && mesh_.is_boundary(_ci.vrv0)
|
||||||
mesh_.is_boundary(_ci.vrv0) &&
|
&& mesh_.is_boundary(_ci.v1vr))
|
||||||
mesh_.is_boundary(_ci.v1vr))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// there have to be at least 2 incident faces at v0
|
// there have to be at least 2 incident faces at v0
|
||||||
if (mesh_.cw_rotated_halfedge_handle(
|
if (mesh_.cw_rotated_halfedge_handle(
|
||||||
mesh_.cw_rotated_halfedge_handle(_ci.v0v1)) == _ci.v0v1)
|
mesh_.cw_rotated_halfedge_handle(_ci.v0v1)) == _ci.v0v1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
// collapse passed all tests -> ok
|
// collapse passed all tests -> ok
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Mesh>
|
||||||
template <class Mesh>
|
float DecimaterT<Mesh>::collapse_priority(const CollapseInfo& _ci) {
|
||||||
float
|
|
||||||
DecimaterT<Mesh>::collapse_priority(const CollapseInfo& _ci)
|
|
||||||
{
|
|
||||||
typename ModuleList::iterator m_it, m_end = bmodules_.end();
|
typename ModuleList::iterator m_it, m_end = bmodules_.end();
|
||||||
|
|
||||||
for (m_it = bmodules_.begin(); m_it != m_end; ++m_it)
|
for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) {
|
||||||
{
|
if ((*m_it)->collapse_priority(_ci) < 0.0)
|
||||||
if ( (*m_it)->collapse_priority(_ci) < 0.0)
|
|
||||||
return ModBaseT<DecimaterT<Mesh> >::ILLEGAL_COLLAPSE;
|
return ModBaseT<DecimaterT<Mesh> >::ILLEGAL_COLLAPSE;
|
||||||
}
|
}
|
||||||
return cmodule_->collapse_priority(_ci);
|
return cmodule_->collapse_priority(_ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Mesh>
|
||||||
template <class Mesh>
|
void DecimaterT<Mesh>::heap_vertex(VertexHandle _vh) {
|
||||||
void
|
|
||||||
DecimaterT<Mesh>::heap_vertex(VertexHandle _vh)
|
|
||||||
{
|
|
||||||
// std::clog << "heap_vertex: " << _vh << std::endl;
|
// std::clog << "heap_vertex: " << _vh << std::endl;
|
||||||
|
|
||||||
float prio, best_prio(FLT_MAX);
|
float prio, best_prio(FLT_MAX);
|
||||||
typename Mesh::HalfedgeHandle heh, collapse_target;
|
typename Mesh::HalfedgeHandle heh, collapse_target;
|
||||||
|
|
||||||
|
|
||||||
// find best target in one ring
|
// find best target in one ring
|
||||||
typename Mesh::VertexOHalfedgeIter voh_it(mesh_, _vh);
|
typename Mesh::VertexOHalfedgeIter voh_it(mesh_, _vh);
|
||||||
for (; voh_it; ++voh_it)
|
for (; voh_it; ++voh_it) {
|
||||||
{
|
|
||||||
heh = voh_it.handle();
|
heh = voh_it.handle();
|
||||||
CollapseInfo ci(mesh_, heh);
|
CollapseInfo ci(mesh_, heh);
|
||||||
|
|
||||||
if (is_collapse_legal(ci))
|
if (is_collapse_legal(ci)) {
|
||||||
{
|
|
||||||
prio = collapse_priority(ci);
|
prio = collapse_priority(ci);
|
||||||
if (prio >= 0.0 && prio < best_prio)
|
if (prio >= 0.0 && prio < best_prio) {
|
||||||
{
|
best_prio = prio;
|
||||||
best_prio = prio;
|
collapse_target = heh;
|
||||||
collapse_target = heh;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// target found -> put vertex on heap
|
// target found -> put vertex on heap
|
||||||
if (collapse_target.is_valid())
|
if (collapse_target.is_valid()) {
|
||||||
{
|
|
||||||
// std::clog << " added|updated" << std::endl;
|
// std::clog << " added|updated" << std::endl;
|
||||||
mesh_.property(collapse_target_, _vh) = collapse_target;
|
mesh_.property(collapse_target_, _vh) = collapse_target;
|
||||||
mesh_.property(priority_, _vh) = best_prio;
|
mesh_.property(priority_, _vh) = best_prio;
|
||||||
|
|
||||||
if (heap_->is_stored(_vh)) heap_->update(_vh);
|
if (heap_->is_stored(_vh))
|
||||||
else heap_->insert(_vh);
|
heap_->update(_vh);
|
||||||
|
else
|
||||||
|
heap_->insert(_vh);
|
||||||
}
|
}
|
||||||
|
|
||||||
// not valid -> remove from heap
|
// not valid -> remove from heap
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
// std::clog << " n/a|removed" << std::endl;
|
// std::clog << " n/a|removed" << std::endl;
|
||||||
if (heap_->is_stored(_vh)) heap_->remove(_vh);
|
if (heap_->is_stored(_vh))
|
||||||
|
heap_->remove(_vh);
|
||||||
|
|
||||||
mesh_.property(collapse_target_, _vh) = collapse_target;
|
mesh_.property(collapse_target_, _vh) = collapse_target;
|
||||||
mesh_.property(priority_, _vh) = -1;
|
mesh_.property(priority_, _vh) = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Mesh>
|
||||||
template <class Mesh>
|
void DecimaterT<Mesh>::postprocess_collapse(CollapseInfo& _ci) {
|
||||||
void
|
|
||||||
DecimaterT<Mesh>::
|
|
||||||
postprocess_collapse(CollapseInfo& _ci)
|
|
||||||
{
|
|
||||||
typename ModuleList::iterator m_it, m_end = bmodules_.end();
|
typename ModuleList::iterator m_it, m_end = bmodules_.end();
|
||||||
|
|
||||||
for (m_it = bmodules_.begin(); m_it != m_end; ++m_it)
|
for (m_it = bmodules_.begin(); m_it != m_end; ++m_it)
|
||||||
@@ -415,15 +351,10 @@ postprocess_collapse(CollapseInfo& _ci)
|
|||||||
cmodule_->postprocess_collapse(_ci);
|
cmodule_->postprocess_collapse(_ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Mesh>
|
||||||
template <class Mesh>
|
void DecimaterT<Mesh>::preprocess_collapse(CollapseInfo& _ci) {
|
||||||
void
|
|
||||||
DecimaterT<Mesh>::
|
|
||||||
preprocess_collapse(CollapseInfo& _ci)
|
|
||||||
{
|
|
||||||
typename ModuleList::iterator m_it, m_end = bmodules_.end();
|
typename ModuleList::iterator m_it, m_end = bmodules_.end();
|
||||||
|
|
||||||
for (m_it = bmodules_.begin(); m_it != m_end; ++m_it)
|
for (m_it = bmodules_.begin(); m_it != m_end; ++m_it)
|
||||||
@@ -432,227 +363,182 @@ preprocess_collapse(CollapseInfo& _ci)
|
|||||||
cmodule_->preprocess_collapse(_ci);
|
cmodule_->preprocess_collapse(_ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <class Mesh>
|
template<class Mesh>
|
||||||
size_t
|
size_t DecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
||||||
DecimaterT<Mesh>::decimate( size_t _n_collapses )
|
if (!is_initialized())
|
||||||
{
|
|
||||||
if ( !is_initialized() )
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
|
typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
|
||||||
typename Mesh::VertexHandle vp;
|
typename Mesh::VertexHandle vp;
|
||||||
typename Mesh::HalfedgeHandle v0v1;
|
typename Mesh::HalfedgeHandle v0v1;
|
||||||
typename Mesh::VertexVertexIter vv_it;
|
typename Mesh::VertexVertexIter vv_it;
|
||||||
typename Mesh::VertexFaceIter vf_it;
|
typename Mesh::VertexFaceIter vf_it;
|
||||||
unsigned int n_collapses(0);
|
unsigned int n_collapses(0);
|
||||||
|
|
||||||
typedef std::vector<typename Mesh::VertexHandle> Support;
|
typedef std::vector<typename Mesh::VertexHandle> Support;
|
||||||
typedef typename Support::iterator SupportIterator;
|
typedef typename Support::iterator SupportIterator;
|
||||||
|
|
||||||
Support support(15);
|
|
||||||
SupportIterator s_it, s_end;
|
|
||||||
|
|
||||||
|
Support support(15);
|
||||||
|
SupportIterator s_it, s_end;
|
||||||
|
|
||||||
// check _n_collapses
|
// check _n_collapses
|
||||||
if (!_n_collapses) _n_collapses = mesh_.n_vertices();
|
if (!_n_collapses)
|
||||||
|
_n_collapses = mesh_.n_vertices();
|
||||||
|
|
||||||
// initialize heap
|
// initialize heap
|
||||||
HeapInterface HI(mesh_, priority_, heap_position_);
|
HeapInterface HI(mesh_, priority_, heap_position_);
|
||||||
heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));
|
heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));
|
||||||
heap_->reserve(mesh_.n_vertices());
|
heap_->reserve(mesh_.n_vertices());
|
||||||
|
|
||||||
|
for (v_it = mesh_.vertices_begin(); v_it != v_end; ++v_it) {
|
||||||
for (v_it = mesh_.vertices_begin(); v_it != v_end; ++v_it)
|
heap_->reset_heap_position(v_it.handle());
|
||||||
{
|
|
||||||
heap_->reset_heap_position( v_it.handle() );
|
|
||||||
if (!mesh_.status(v_it).deleted())
|
if (!mesh_.status(v_it).deleted())
|
||||||
heap_vertex( v_it.handle() );
|
heap_vertex(v_it.handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// process heap
|
// process heap
|
||||||
while ((!heap_->empty()) && (n_collapses < _n_collapses))
|
while ((!heap_->empty()) && (n_collapses < _n_collapses)) {
|
||||||
{
|
|
||||||
// get 1st heap entry
|
// get 1st heap entry
|
||||||
vp = heap_->front();
|
vp = heap_->front();
|
||||||
v0v1 = mesh_.property(collapse_target_, vp);
|
v0v1 = mesh_.property(collapse_target_, vp);
|
||||||
heap_->pop_front();
|
heap_->pop_front();
|
||||||
|
|
||||||
|
|
||||||
// setup collapse info
|
// setup collapse info
|
||||||
CollapseInfo ci(mesh_, v0v1);
|
CollapseInfo ci(mesh_, v0v1);
|
||||||
|
|
||||||
|
|
||||||
// check topological correctness AGAIN !
|
// check topological correctness AGAIN !
|
||||||
if (!is_collapse_legal(ci))
|
if (!is_collapse_legal(ci))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
// store support (= one ring of *vp)
|
// store support (= one ring of *vp)
|
||||||
vv_it = mesh_.vv_iter(ci.v0);
|
vv_it = mesh_.vv_iter(ci.v0);
|
||||||
support.clear();
|
support.clear();
|
||||||
for (; vv_it; ++vv_it)
|
for (; vv_it; ++vv_it)
|
||||||
support.push_back(vv_it.handle());
|
support.push_back(vv_it.handle());
|
||||||
|
|
||||||
|
|
||||||
// perform collapse
|
// perform collapse
|
||||||
mesh_.collapse(v0v1);
|
mesh_.collapse(v0v1);
|
||||||
++n_collapses;
|
++n_collapses;
|
||||||
|
|
||||||
|
|
||||||
// update triangle normals
|
// update triangle normals
|
||||||
vf_it = mesh_.vf_iter(ci.v1);
|
vf_it = mesh_.vf_iter(ci.v1);
|
||||||
for (; vf_it; ++vf_it)
|
for (; vf_it; ++vf_it)
|
||||||
if (!mesh_.status(vf_it).deleted())
|
if (!mesh_.status(vf_it).deleted())
|
||||||
mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));
|
mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));
|
||||||
|
|
||||||
|
|
||||||
// post-process collapse
|
// post-process collapse
|
||||||
postprocess_collapse(ci);
|
postprocess_collapse(ci);
|
||||||
|
|
||||||
|
|
||||||
// update heap (former one ring of decimated vertex)
|
// update heap (former one ring of decimated vertex)
|
||||||
for (s_it = support.begin(), s_end = support.end();
|
for (s_it = support.begin(), s_end = support.end(); s_it != s_end; ++s_it) {
|
||||||
s_it != s_end; ++s_it)
|
|
||||||
{
|
|
||||||
assert(!mesh_.status(*s_it).deleted());
|
assert(!mesh_.status(*s_it).deleted());
|
||||||
heap_vertex(*s_it);
|
heap_vertex(*s_it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// delete heap
|
// delete heap
|
||||||
heap_.reset();
|
heap_.reset();
|
||||||
|
|
||||||
|
|
||||||
// DON'T do garbage collection here! It's up to the application.
|
// DON'T do garbage collection here! It's up to the application.
|
||||||
return n_collapses;
|
return n_collapses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Mesh>
|
||||||
template <class Mesh>
|
size_t DecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
||||||
size_t
|
if (!is_initialized())
|
||||||
DecimaterT<Mesh>::
|
|
||||||
decimate_to_faces( size_t _nv, size_t _nf )
|
|
||||||
{
|
|
||||||
if ( !is_initialized() )
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (_nv >= mesh_.n_vertices() || _nf >= mesh_.n_faces())
|
if (_nv >= mesh_.n_vertices() || _nf >= mesh_.n_faces())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
|
typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
|
||||||
typename Mesh::VertexHandle vp;
|
typename Mesh::VertexHandle vp;
|
||||||
typename Mesh::HalfedgeHandle v0v1;
|
typename Mesh::HalfedgeHandle v0v1;
|
||||||
typename Mesh::VertexVertexIter vv_it;
|
typename Mesh::VertexVertexIter vv_it;
|
||||||
typename Mesh::VertexFaceIter vf_it;
|
typename Mesh::VertexFaceIter vf_it;
|
||||||
unsigned int nv = mesh_.n_vertices();
|
unsigned int nv = mesh_.n_vertices();
|
||||||
unsigned int nf = mesh_.n_faces();
|
unsigned int nf = mesh_.n_faces();
|
||||||
unsigned int n_collapses = 0;
|
unsigned int n_collapses = 0;
|
||||||
|
|
||||||
typedef std::vector<typename Mesh::VertexHandle> Support;
|
|
||||||
typedef typename Support::iterator SupportIterator;
|
|
||||||
|
|
||||||
Support support(15);
|
|
||||||
SupportIterator s_it, s_end;
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::vector<typename Mesh::VertexHandle> Support;
|
||||||
|
typedef typename Support::iterator SupportIterator;
|
||||||
|
|
||||||
|
Support support(15);
|
||||||
|
SupportIterator s_it, s_end;
|
||||||
|
|
||||||
// initialize heap
|
// initialize heap
|
||||||
HeapInterface HI(mesh_, priority_, heap_position_);
|
HeapInterface HI(mesh_, priority_, heap_position_);
|
||||||
heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));
|
heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));
|
||||||
heap_->reserve(mesh_.n_vertices());
|
heap_->reserve(mesh_.n_vertices());
|
||||||
|
|
||||||
|
for (v_it = mesh_.vertices_begin(); v_it != v_end; ++v_it) {
|
||||||
for (v_it = mesh_.vertices_begin(); v_it != v_end; ++v_it)
|
heap_->reset_heap_position(v_it.handle());
|
||||||
{
|
|
||||||
heap_->reset_heap_position( v_it.handle() );
|
|
||||||
if (!mesh_.status(v_it).deleted())
|
if (!mesh_.status(v_it).deleted())
|
||||||
heap_vertex( v_it.handle() );
|
heap_vertex(v_it.handle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// process heap
|
// process heap
|
||||||
while ((!heap_->empty()) && (_nv < nv) && (_nf < nf))
|
while ((!heap_->empty()) && (_nv < nv) && (_nf < nf)) {
|
||||||
{
|
|
||||||
// get 1st heap entry
|
// get 1st heap entry
|
||||||
vp = heap_->front();
|
vp = heap_->front();
|
||||||
v0v1 = mesh_.property(collapse_target_, vp);
|
v0v1 = mesh_.property(collapse_target_, vp);
|
||||||
heap_->pop_front();
|
heap_->pop_front();
|
||||||
|
|
||||||
|
|
||||||
// setup collapse info
|
// setup collapse info
|
||||||
CollapseInfo ci(mesh_, v0v1);
|
CollapseInfo ci(mesh_, v0v1);
|
||||||
|
|
||||||
|
|
||||||
// check topological correctness AGAIN !
|
// check topological correctness AGAIN !
|
||||||
if (!is_collapse_legal(ci))
|
if (!is_collapse_legal(ci))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
// store support (= one ring of *vp)
|
// store support (= one ring of *vp)
|
||||||
vv_it = mesh_.vv_iter(ci.v0);
|
vv_it = mesh_.vv_iter(ci.v0);
|
||||||
support.clear();
|
support.clear();
|
||||||
for (; vv_it; ++vv_it)
|
for (; vv_it; ++vv_it)
|
||||||
support.push_back(vv_it.handle());
|
support.push_back(vv_it.handle());
|
||||||
|
|
||||||
|
|
||||||
// adjust complexity in advance (need boundary status)
|
// adjust complexity in advance (need boundary status)
|
||||||
++n_collapses;
|
++n_collapses;
|
||||||
--nv;
|
--nv;
|
||||||
if (mesh_.is_boundary(ci.v0v1) ||
|
if (mesh_.is_boundary(ci.v0v1) || mesh_.is_boundary(ci.v1v0))
|
||||||
mesh_.is_boundary(ci.v1v0))
|
|
||||||
--nf;
|
--nf;
|
||||||
else nf -= 2;
|
else
|
||||||
|
nf -= 2;
|
||||||
|
|
||||||
// pre-processing
|
// pre-processing
|
||||||
preprocess_collapse(ci);
|
preprocess_collapse(ci);
|
||||||
|
|
||||||
|
|
||||||
// perform collapse
|
// perform collapse
|
||||||
mesh_.collapse(v0v1);
|
mesh_.collapse(v0v1);
|
||||||
|
|
||||||
|
|
||||||
// update triangle normals
|
// update triangle normals
|
||||||
vf_it = mesh_.vf_iter(ci.v1);
|
vf_it = mesh_.vf_iter(ci.v1);
|
||||||
for (; vf_it; ++vf_it)
|
for (; vf_it; ++vf_it)
|
||||||
if (!mesh_.status(vf_it).deleted())
|
if (!mesh_.status(vf_it).deleted())
|
||||||
mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));
|
mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));
|
||||||
|
|
||||||
|
|
||||||
// post-process collapse
|
// post-process collapse
|
||||||
postprocess_collapse(ci);
|
postprocess_collapse(ci);
|
||||||
|
|
||||||
|
|
||||||
// update heap (former one ring of decimated vertex)
|
// update heap (former one ring of decimated vertex)
|
||||||
for (s_it = support.begin(), s_end = support.end();
|
for (s_it = support.begin(), s_end = support.end(); s_it != s_end; ++s_it) {
|
||||||
s_it != s_end; ++s_it)
|
|
||||||
{
|
|
||||||
assert(!mesh_.status(*s_it).deleted());
|
assert(!mesh_.status(*s_it).deleted());
|
||||||
heap_vertex(*s_it);
|
heap_vertex(*s_it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// delete heap
|
// delete heap
|
||||||
heap_.reset();
|
heap_.reset();
|
||||||
|
|
||||||
|
|
||||||
// DON'T do garbage collection here! It's up to the application.
|
// DON'T do garbage collection here! It's up to the application.
|
||||||
return n_collapses;
|
return n_collapses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
} // END_NS_DECIMATER
|
}// END_NS_DECIMATER
|
||||||
} // END_NS_OPENMESH
|
} // END_NS_OPENMESH
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -30,59 +30,49 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision: 448 $ *
|
* $Revision: 448 $ *
|
||||||
* $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ *
|
* $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/** \file ModAspectRatioT.cc
|
/** \file ModAspectRatioT.cc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// CLASS ModAspectRatioT - IMPLEMENTATION
|
// CLASS ModAspectRatioT - IMPLEMENTATION
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
#define OPENMESH_DECIMATER_MODASPECTRATIOT_C
|
||||||
#define MB_MODASPECTRATIOT_C
|
|
||||||
|
|
||||||
|
|
||||||
//== INCLUDES =================================================================
|
//== INCLUDES =================================================================
|
||||||
|
|
||||||
#include "ModAspectRatioT.hh"
|
#include "ModAspectRatioT.hh"
|
||||||
|
|
||||||
|
|
||||||
//== NAMESPACES ===============================================================
|
//== NAMESPACES ===============================================================
|
||||||
|
|
||||||
namespace OpenMesh {
|
namespace OpenMesh {
|
||||||
namespace Decimater {
|
namespace Decimater {
|
||||||
|
|
||||||
|
|
||||||
//== IMPLEMENTATION ==========================================================
|
//== IMPLEMENTATION ==========================================================
|
||||||
|
|
||||||
|
template<class DecimaterT>
|
||||||
template <class DecimaterT>
|
typename ModAspectRatioT<DecimaterT>::Scalar ModAspectRatioT<DecimaterT>::aspectRatio(
|
||||||
typename ModAspectRatioT<DecimaterT>::Scalar
|
const Point& _v0, const Point& _v1, const Point& _v2) {
|
||||||
ModAspectRatioT<DecimaterT>::
|
|
||||||
aspectRatio( const Point& _v0,
|
|
||||||
const Point& _v1,
|
|
||||||
const Point& _v2 )
|
|
||||||
{
|
|
||||||
Point d0 = _v0 - _v1;
|
Point d0 = _v0 - _v1;
|
||||||
Point d1 = _v1 - _v2;
|
Point d1 = _v1 - _v2;
|
||||||
|
|
||||||
// finds the max squared edge length
|
// finds the max squared edge length
|
||||||
Scalar l2, maxl2 = d0.sqrnorm();
|
Scalar l2, maxl2 = d0.sqrnorm();
|
||||||
if ((l2=d1.sqrnorm()) > maxl2)
|
if ((l2 = d1.sqrnorm()) > maxl2)
|
||||||
maxl2 = l2;
|
maxl2 = l2;
|
||||||
// keep searching for the max squared edge length
|
// keep searching for the max squared edge length
|
||||||
d1 = _v2 - _v0;
|
d1 = _v2 - _v0;
|
||||||
if ((l2=d1.sqrnorm()) > maxl2)
|
if ((l2 = d1.sqrnorm()) > maxl2)
|
||||||
maxl2 = l2;
|
maxl2 = l2;
|
||||||
|
|
||||||
// squared area of the parallelogram spanned by d0 and d1
|
// squared area of the parallelogram spanned by d0 and d1
|
||||||
@@ -96,116 +86,93 @@ aspectRatio( const Point& _v0,
|
|||||||
|
|
||||||
// returns the length of the longest edge
|
// returns the length of the longest edge
|
||||||
// divided by its corresponding height
|
// divided by its corresponding height
|
||||||
return sqrt( (maxl2 * maxl2) / a2 );
|
return sqrt((maxl2 * maxl2) / a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class DecimaterT>
|
||||||
|
void ModAspectRatioT<DecimaterT>::initialize() {
|
||||||
|
typename Mesh::FaceIter f_it, f_end(mesh_.faces_end());
|
||||||
|
typename Mesh::FVIter fv_it;
|
||||||
|
|
||||||
template <class DecimaterT>
|
for (f_it = mesh_.faces_begin(); f_it != f_end; ++f_it) {
|
||||||
void
|
typename Mesh::Point& p0 = mesh_.point(fv_it = mesh_.fv_iter(f_it));
|
||||||
ModAspectRatioT<DecimaterT>::
|
|
||||||
initialize()
|
|
||||||
{
|
|
||||||
typename Mesh::FaceIter f_it, f_end(mesh_.faces_end());
|
|
||||||
typename Mesh::FVIter fv_it;
|
|
||||||
|
|
||||||
for (f_it=mesh_.faces_begin(); f_it!=f_end; ++f_it)
|
|
||||||
{
|
|
||||||
typename Mesh::Point& p0 = mesh_.point(fv_it=mesh_.fv_iter(f_it));
|
|
||||||
typename Mesh::Point& p1 = mesh_.point(++fv_it);
|
typename Mesh::Point& p1 = mesh_.point(++fv_it);
|
||||||
typename Mesh::Point& p2 = mesh_.point(++fv_it);
|
typename Mesh::Point& p2 = mesh_.point(++fv_it);
|
||||||
|
|
||||||
mesh_.property(roundness_, f_it) =
|
mesh_.property(aspect_, f_it) = 1.0 / aspectRatio(p0, p1, p2);
|
||||||
1.0/aspectRatio(p0, p1, p2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class DecimaterT>
|
||||||
|
void ModAspectRatioT<DecimaterT>::preprocess_collapse(const CollapseInfo& _ci) {
|
||||||
|
typename Mesh::FaceHandle fh;
|
||||||
|
typename Mesh::FVIter fv_it;
|
||||||
|
|
||||||
template <class DecimaterT>
|
for (typename Mesh::VFIter vf_it = mesh_.vf_iter(_ci.v0); vf_it; ++vf_it) {
|
||||||
void
|
|
||||||
ModAspectRatioT<DecimaterT>::
|
|
||||||
preprocess_collapse(const CollapseInfo& _ci)
|
|
||||||
{
|
|
||||||
typename Mesh::FaceHandle fh;
|
|
||||||
typename Mesh::FVIter fv_it;
|
|
||||||
|
|
||||||
for (typename Mesh::VFIter vf_it=mesh_.vf_iter(_ci.v0); vf_it; ++vf_it)
|
|
||||||
{
|
|
||||||
fh = vf_it.handle();
|
fh = vf_it.handle();
|
||||||
if (fh != _ci.fl && fh != _ci.fr)
|
if (fh != _ci.fl && fh != _ci.fr) {
|
||||||
{
|
typename Mesh::Point& p0 = mesh_.point(fv_it = mesh_.fv_iter(fh));
|
||||||
typename Mesh::Point& p0 = mesh_.point(fv_it=mesh_.fv_iter(fh));
|
|
||||||
typename Mesh::Point& p1 = mesh_.point(++fv_it);
|
typename Mesh::Point& p1 = mesh_.point(++fv_it);
|
||||||
typename Mesh::Point& p2 = mesh_.point(++fv_it);
|
typename Mesh::Point& p2 = mesh_.point(++fv_it);
|
||||||
|
|
||||||
mesh_.property(roundness_, fh) =
|
mesh_.property(aspect_, fh) = 1.0 / aspectRatio(p0, p1, p2);
|
||||||
1.0/aspectRatio(p0, p1, p2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class DecimaterT>
|
||||||
template <class DecimaterT>
|
float ModAspectRatioT<DecimaterT>::collapse_priority(const CollapseInfo& _ci) {
|
||||||
float
|
typename Mesh::VertexHandle v2, v3;
|
||||||
ModAspectRatioT<DecimaterT>::
|
typename Mesh::FaceHandle fh;
|
||||||
collapse_priority(const CollapseInfo& _ci)
|
const typename Mesh::Point *p1(&_ci.p1), *p2, *p3;
|
||||||
{
|
typename Mesh::Scalar r0, r1, r0_min(1.0), r1_min(1.0);
|
||||||
typename Mesh::VertexHandle v2, v3;
|
typename Mesh::CVVIter vv_it(mesh_, _ci.v0);
|
||||||
typename Mesh::FaceHandle fh;
|
|
||||||
const typename Mesh::Point *p1(&_ci.p1), *p2, *p3;
|
|
||||||
typename Mesh::Scalar r0, r1, r0_min(1.0), r1_min(1.0);
|
|
||||||
typename Mesh::CVVIter vv_it(mesh_, _ci.v0);
|
|
||||||
|
|
||||||
v3 = vv_it.handle();
|
v3 = vv_it.handle();
|
||||||
p3 = &mesh_.point(v3);
|
p3 = &mesh_.point(v3);
|
||||||
|
|
||||||
while (vv_it)
|
while (vv_it) {
|
||||||
{
|
|
||||||
v2 = v3;
|
v2 = v3;
|
||||||
p2 = p3;
|
p2 = p3;
|
||||||
|
|
||||||
v3 = (++vv_it).handle();
|
v3 = (++vv_it).handle();
|
||||||
p3 = &mesh_.point(v3);
|
p3 = &mesh_.point(v3);
|
||||||
|
|
||||||
fh = mesh_.face_handle(vv_it.current_halfedge_handle());
|
fh = mesh_.face_handle(vv_it.current_halfedge_handle());
|
||||||
|
|
||||||
// if not boundary
|
// if not boundary
|
||||||
if (fh.is_valid())
|
if (fh.is_valid()) {
|
||||||
{
|
// aspect before
|
||||||
// roundness before
|
if ((r0 = mesh_.property(aspect_, fh)) < r0_min)
|
||||||
if ((r0 = mesh_.property(roundness_,fh)) < r0_min)
|
r0_min = r0;
|
||||||
r0_min = r0;
|
|
||||||
|
|
||||||
// roundness after
|
// aspect after
|
||||||
if (!(v2 == _ci.v1 || v3 == _ci.v1))
|
if (!(v2 == _ci.v1 || v3 == _ci.v1))
|
||||||
if ((r1 = 1.0/aspectRatio(*p1, *p2, *p3)) < r1_min)
|
if ((r1 = 1.0 / aspectRatio(*p1, *p2, *p3)) < r1_min)
|
||||||
r1_min = r1;
|
r1_min = r1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Base::is_binary()) {
|
||||||
|
return
|
||||||
|
((r1_min > r0_min) || (r1_min > min_aspect_)) ? Base::LEGAL_COLLAPSE :
|
||||||
|
Base::ILLEGAL_COLLAPSE;
|
||||||
|
|
||||||
if (Base::is_binary())
|
} else {
|
||||||
{
|
|
||||||
return ((r1_min > r0_min) || (r1_min > min_roundness_)) ? 0.0 : -1.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (r1_min > r0_min)
|
if (r1_min > r0_min)
|
||||||
return 1.0 - r1_min;
|
return 1.0 - r1_min;
|
||||||
else
|
else
|
||||||
return (r1_min > min_roundness_) ? 2.0 - r1_min : -1.0;
|
return
|
||||||
|
(r1_min > min_aspect_) ? 2.0 - r1_min : float(Base::ILLEGAL_COLLAPSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,114 +30,117 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision: 448 $ *
|
* $Revision: 448 $ *
|
||||||
* $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ *
|
* $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/** \file ModAspectRatioT.hh
|
/** \file ModAspectRatioT.hh
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// CLASS ModAspectRatioT
|
// CLASS ModAspectRatioT
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
#ifndef OPENMESH_DECIMATER_MODASPECTRATIOT_HH
|
||||||
#ifndef MODASPECTRATIOT_HH
|
#define OPENMESH_DECIMATER_MODASPECTRATIOT_HH
|
||||||
#define MODASPECTRATIOT_HH
|
|
||||||
|
|
||||||
|
|
||||||
//== INCLUDES =================================================================
|
//== INCLUDES =================================================================
|
||||||
|
|
||||||
#include <OpenMesh/Tools/Decimater/ModBaseT.hh>
|
#include <OpenMesh/Tools/Decimater/ModBaseT.hh>
|
||||||
#include <OpenMesh/Core/Utils/Property.hh>
|
#include <OpenMesh/Core/Utils/Property.hh>
|
||||||
|
|
||||||
|
|
||||||
//== NAMESPACES ===============================================================
|
//== NAMESPACES ===============================================================
|
||||||
|
|
||||||
namespace OpenMesh {
|
namespace OpenMesh {
|
||||||
namespace Decimater {
|
namespace Decimater {
|
||||||
|
|
||||||
|
|
||||||
//== CLASS DEFINITION =========================================================
|
//== CLASS DEFINITION =========================================================
|
||||||
|
|
||||||
|
/** \brief Use aspect ratio to control decimation
|
||||||
|
*
|
||||||
|
* This module computes the aspect ratio.
|
||||||
|
*
|
||||||
|
* In binary mode, the collapse is legal if:
|
||||||
|
* - The aspect ratio after the collapse is greater
|
||||||
|
* - The aspect ratio after the collapse is greater than the given minimum
|
||||||
|
*
|
||||||
|
* In continuous mode the collapse is illegal if:
|
||||||
|
* - The aspect ratio after the collapse is smaller than the given minimum
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class DecimaterT>
|
||||||
|
class ModAspectRatioT: public ModBaseT<DecimaterT> {
|
||||||
|
public:
|
||||||
|
|
||||||
template <class DecimaterT>
|
DECIMATING_MODULE( ModAspectRatioT, DecimaterT, Roundness )
|
||||||
class ModAspectRatioT : public ModBaseT<DecimaterT>
|
;
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
DECIMATING_MODULE( ModAspectRatioT, DecimaterT, Roundness );
|
|
||||||
|
|
||||||
typedef typename Mesh::Scalar Scalar;
|
typedef typename Mesh::Scalar Scalar;
|
||||||
typedef typename Mesh::Point Point;
|
typedef typename Mesh::Point Point;
|
||||||
|
|
||||||
// constructor
|
/// constructor
|
||||||
ModAspectRatioT(DecimaterT& _dec,
|
ModAspectRatioT(DecimaterT& _dec, float _min_aspect = 5.0, bool _is_binary =
|
||||||
float _min_roundness = 5.0,
|
true) :
|
||||||
bool _is_binary = true)
|
Base(_dec, _is_binary), mesh_(Base::mesh()), min_aspect_(
|
||||||
: Base(_dec, _is_binary),
|
1.0 / _min_aspect) {
|
||||||
mesh_(Base::mesh()),
|
mesh_.add_property(aspect_);
|
||||||
min_roundness_(1.0/_min_roundness)
|
}
|
||||||
{
|
|
||||||
mesh_.add_property( roundness_ );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// destructor
|
||||||
|
~ModAspectRatioT() {
|
||||||
|
mesh_.remove_property(aspect_);
|
||||||
|
}
|
||||||
|
|
||||||
// destructor
|
/// get aspect ratio
|
||||||
~ModAspectRatioT()
|
float aspect_ratio() const {
|
||||||
{
|
return 1.0 / min_aspect_;
|
||||||
mesh_.remove_property( roundness_ );
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/// set aspect ratio
|
||||||
|
void set_aspect_ratio(float _f) {
|
||||||
|
min_aspect_ = 1.0 / _f;
|
||||||
|
}
|
||||||
|
|
||||||
/// get roundness
|
/// precompute face aspect ratio
|
||||||
float roundness() const { return 1.0/min_roundness_; }
|
void initialize();
|
||||||
/// set roundness
|
|
||||||
void set_roundness(float _f) { min_roundness_ = 1.0/_f; }
|
|
||||||
|
|
||||||
// precompute face roundness
|
|
||||||
void initialize();
|
|
||||||
// blabla
|
|
||||||
float collapse_priority(const CollapseInfo& _ci);
|
|
||||||
// update roundness of one-ring
|
|
||||||
void preprocess_collapse(const CollapseInfo& _ci);
|
|
||||||
|
|
||||||
|
/// Returns the collapse priority
|
||||||
|
float collapse_priority(const CollapseInfo& _ci);
|
||||||
|
|
||||||
private:
|
/// update aspect ratio of one-ring
|
||||||
|
void preprocess_collapse(const CollapseInfo& _ci);
|
||||||
|
|
||||||
/** \brief return aspect ratio (length/height) of triangle
|
private:
|
||||||
*
|
|
||||||
*/
|
|
||||||
Scalar aspectRatio( const Point& _v0,
|
|
||||||
const Point& _v1,
|
|
||||||
const Point& _v2 );
|
|
||||||
|
|
||||||
private:
|
/** \brief return aspect ratio (length/height) of triangle
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Scalar aspectRatio(const Point& _v0, const Point& _v1, const Point& _v2);
|
||||||
|
|
||||||
Mesh& mesh_;
|
private:
|
||||||
float min_roundness_;
|
|
||||||
FPropHandleT<float> roundness_;
|
Mesh& mesh_;
|
||||||
|
float min_aspect_;
|
||||||
|
FPropHandleT<float> aspect_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
} // END_NS_DECIMATER
|
}// END_NS_DECIMATER
|
||||||
} // END_NS_OPENMESH
|
} // END_NS_OPENMESH
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
#if defined(INCLUDE_TEMPLATES) && !defined(MB_MODASPECTRATIOT_C)
|
#if defined(INCLUDE_TEMPLATES) && !defined(OPENMESH_DECIMATER_MODASPECTRATIOT_C)
|
||||||
#define MODASPECTRATIOT_TEMPLATES
|
#define OPENMESH_DECIMATER_MODASPECTRATIOT_TEMPLATES
|
||||||
#include "ModAspectRatioT.cc"
|
#include "ModAspectRatioT.cc"
|
||||||
#endif
|
#endif
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
#endif // MB_MODASPECTRATIOT_HH defined
|
#endif // OPENMESH_DECIMATER_MODASPECTRATIOT_HH defined
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -30,68 +30,52 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision: 448 $ *
|
* $Revision: 448 $ *
|
||||||
* $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ *
|
* $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/** \file ModEdgeLengthT.cc
|
/** \file ModEdgeLengthT.cc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// CLASS ModEdgeLengthT - IMPLEMENTATION
|
// CLASS ModEdgeLengthT - IMPLEMENTATION
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
#define OPENMESH_DECIMATER_MODEDGELENGTHT_C
|
||||||
#define MODEDGELENGTHT_C
|
|
||||||
|
|
||||||
|
|
||||||
//== INCLUDES =================================================================
|
//== INCLUDES =================================================================
|
||||||
|
|
||||||
#include "ModEdgeLengthT.hh"
|
#include "ModEdgeLengthT.hh"
|
||||||
|
|
||||||
|
|
||||||
//== NAMESPACES ===============================================================
|
//== NAMESPACES ===============================================================
|
||||||
|
|
||||||
namespace OpenMesh {
|
namespace OpenMesh {
|
||||||
namespace Decimater {
|
namespace Decimater {
|
||||||
|
|
||||||
|
|
||||||
//== IMPLEMENTATION ==========================================================
|
//== IMPLEMENTATION ==========================================================
|
||||||
|
|
||||||
|
template<class DecimaterT>
|
||||||
template <class DecimaterT>
|
ModEdgeLengthT<DecimaterT>::ModEdgeLengthT(DecimaterT &_dec, float _edge_length,
|
||||||
ModEdgeLengthT<DecimaterT>::
|
bool _is_binary) :
|
||||||
ModEdgeLengthT(DecimaterT &_dec, float _edge_length, bool _is_binary)
|
Base(_dec, _is_binary), mesh_(Base::mesh()) {
|
||||||
: Base(_dec, _is_binary),
|
|
||||||
mesh_(Base::mesh())
|
|
||||||
{
|
|
||||||
set_edge_length(_edge_length);
|
set_edge_length(_edge_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class DecimaterT>
|
||||||
template <class DecimaterT>
|
float ModEdgeLengthT<DecimaterT>::collapse_priority(const CollapseInfo& _ci) {
|
||||||
float
|
|
||||||
ModEdgeLengthT<DecimaterT>::
|
|
||||||
collapse_priority(const CollapseInfo& _ci)
|
|
||||||
{
|
|
||||||
typename Mesh::Scalar sqr_length = (_ci.p0 - _ci.p1).sqrnorm();
|
typename Mesh::Scalar sqr_length = (_ci.p0 - _ci.p1).sqrnorm();
|
||||||
|
|
||||||
return ((sqr_length <= sqr_edge_length_) ?
|
return ( (sqr_length <= sqr_edge_length_) ? sqr_length : float(Base::ILLEGAL_COLLAPSE));
|
||||||
sqr_length :
|
|
||||||
float( Base::ILLEGAL_COLLAPSE ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,14 +30,14 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision: 448 $ *
|
* $Revision: 448 $ *
|
||||||
* $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ *
|
* $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/** \file ModEdgeLengthT.hh
|
/** \file ModEdgeLengthT.hh
|
||||||
*/
|
*/
|
||||||
@@ -47,72 +47,73 @@
|
|||||||
// CLASS ModEdgeLengthT
|
// CLASS ModEdgeLengthT
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
#ifndef OPENMESH_DECIMATER_MODEDGELENGTHT_HH
|
||||||
|
#define OPENMESH_DECIMATER_MODEDGELENGTHT_HH
|
||||||
#ifndef MODEDGELENGTHT_HH
|
|
||||||
#define MODEDGELENGTHT_HH
|
|
||||||
|
|
||||||
|
|
||||||
//== INCLUDES =================================================================
|
//== INCLUDES =================================================================
|
||||||
|
|
||||||
#include <OpenMesh/Tools/Decimater/ModBaseT.hh>
|
#include <OpenMesh/Tools/Decimater/ModBaseT.hh>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
|
|
||||||
//== NAMESPACES ===============================================================
|
//== NAMESPACES ===============================================================
|
||||||
|
|
||||||
namespace OpenMesh {
|
namespace OpenMesh {
|
||||||
namespace Decimater {
|
namespace Decimater {
|
||||||
|
|
||||||
|
|
||||||
//== CLASS DEFINITION =========================================================
|
//== CLASS DEFINITION =========================================================
|
||||||
|
|
||||||
|
/** \brief Use edge length to control decimation
|
||||||
|
*
|
||||||
|
* This module computes the edge length.
|
||||||
|
*
|
||||||
|
* In binary and continuous mode, the collapse is legal if:
|
||||||
|
* - The length after the collapse is lower than the given tolerance
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<class DecimaterT>
|
||||||
|
class ModEdgeLengthT: public ModBaseT<DecimaterT> {
|
||||||
|
public:
|
||||||
|
|
||||||
template <class DecimaterT>
|
DECIMATING_MODULE( ModEdgeLengthT, DecimaterT, EdgeLength )
|
||||||
class ModEdgeLengthT : public ModBaseT<DecimaterT>
|
;
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
DECIMATING_MODULE( ModEdgeLengthT, DecimaterT, EdgeLength );
|
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
ModEdgeLengthT(DecimaterT& _dec,
|
ModEdgeLengthT(DecimaterT& _dec, float _edge_length = FLT_MAX,
|
||||||
float _edge_length = FLT_MAX,
|
bool _is_binary = true);
|
||||||
bool _is_binary = true);
|
|
||||||
|
|
||||||
|
|
||||||
/// get edge_length
|
/// get edge_length
|
||||||
float edge_length() const { return edge_length_; }
|
float edge_length() const {
|
||||||
|
return edge_length_;
|
||||||
|
}
|
||||||
|
|
||||||
/// set edge_length
|
/// set edge_length
|
||||||
void set_edge_length(float _f)
|
void set_edge_length(float _f) {
|
||||||
{ edge_length_ = _f; sqr_edge_length_ = _f*_f; }
|
edge_length_ = _f;
|
||||||
|
sqr_edge_length_ = _f * _f;
|
||||||
|
}
|
||||||
|
|
||||||
/** Compute priority:
|
/** Compute priority:
|
||||||
Binary mode: Don't collapse edges longer then edge_length_
|
Binary mode: Don't collapse edges longer then edge_length_
|
||||||
Cont. mode: Collapse smallest edge first, but
|
Cont. mode: Collapse smallest edge first, but
|
||||||
don't collapse edges longer as edge_length_
|
don't collapse edges longer as edge_length_
|
||||||
*/
|
*/
|
||||||
float collapse_priority(const CollapseInfo& _ci);
|
float collapse_priority(const CollapseInfo& _ci);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
private:
|
Mesh& mesh_;
|
||||||
|
typename Mesh::Scalar edge_length_, sqr_edge_length_;
|
||||||
Mesh& mesh_;
|
|
||||||
typename Mesh::Scalar edge_length_, sqr_edge_length_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
} // END_NS_DECIMATER
|
}// END_NS_DECIMATER
|
||||||
} // END_NS_OPENMESH
|
} // END_NS_OPENMESH
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
#if defined(INCLUDE_TEMPLATES) && !defined(MODEDGELENGTHT_C)
|
#if defined(INCLUDE_TEMPLATES) && !defined(OPENMESH_DECIMATER_MODEDGELENGTHT_C)
|
||||||
#define MODEDGELENGTHT_TEMPLATES
|
#define MODEDGELENGTHT_TEMPLATES
|
||||||
#include "ModEdgeLengthT.cc"
|
#include "ModEdgeLengthT.cc"
|
||||||
#endif
|
#endif
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
#endif // MODEDGELENGTHT_HH defined
|
#endif // OPENMESH_DECIMATER_MODEDGELENGTHT_HH defined
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
#define MODHAUSDORFFT_C
|
#define OPENMESH_DECIMATER_MODHAUSDORFFT_C
|
||||||
|
|
||||||
|
|
||||||
//== INCLUDES =================================================================
|
//== INCLUDES =================================================================
|
||||||
|
|||||||
@@ -30,29 +30,26 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision: 448 $ *
|
* $Revision: 448 $ *
|
||||||
* $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ *
|
* $Date: 2011-11-04 13:59:37 +0100 (Fri, 04 Nov 2011) $ *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/** \file ModHausdorffT.hh
|
/** \file ModHausdorffT.hh
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// CLASS ModHausdorffT
|
// CLASS ModHausdorffT
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
#ifndef OPENMESH_DECIMATER_MODHAUSDORFFT_HH
|
||||||
#ifndef MODHAUSDORFFT_HH
|
#define OPENMESH_DECIMATER_MODHAUSDORFFT_HH
|
||||||
#define MODHAUSDORFFT_HH
|
|
||||||
|
|
||||||
|
|
||||||
//== INCLUDES =================================================================
|
//== INCLUDES =================================================================
|
||||||
|
|
||||||
@@ -61,99 +58,98 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
|
|
||||||
//== NAMESPACES ===============================================================
|
//== NAMESPACES ===============================================================
|
||||||
|
|
||||||
namespace OpenMesh {
|
namespace OpenMesh {
|
||||||
namespace Decimater {
|
namespace Decimater {
|
||||||
|
|
||||||
|
|
||||||
//== CLASS DEFINITION =========================================================
|
//== CLASS DEFINITION =========================================================
|
||||||
|
|
||||||
|
/** \brief Use Hausdorff distance to control decimation
|
||||||
|
*
|
||||||
|
* This module computes the aspect ratio.
|
||||||
|
*
|
||||||
|
* In binary mode, the collapse is legal if:
|
||||||
|
* - The distance after the collapse is lower than the given tolerance
|
||||||
|
*
|
||||||
|
* No continuous mode
|
||||||
|
*/
|
||||||
|
template<class DecimaterT>
|
||||||
|
class ModHausdorffT: public ModBaseT<DecimaterT> {
|
||||||
|
public:
|
||||||
|
|
||||||
template <class DecimaterT>
|
DECIMATING_MODULE( ModHausdorffT, DecimaterT, Roundness );
|
||||||
class ModHausdorffT : public ModBaseT<DecimaterT>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
DECIMATING_MODULE( ModHausdorffT, DecimaterT, Roundness );
|
|
||||||
|
|
||||||
typedef typename Mesh::Scalar Scalar;
|
typedef typename Mesh::Scalar Scalar;
|
||||||
typedef typename Mesh::Point Point;
|
typedef typename Mesh::Point Point;
|
||||||
typedef typename Mesh::FaceHandle FaceHandle;
|
typedef typename Mesh::FaceHandle FaceHandle;
|
||||||
typedef std::vector<Point> Points;
|
typedef std::vector<Point> Points;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
ModHausdorffT(DecimaterT& _dec, Scalar _error_tolerance = FLT_MAX) :
|
||||||
|
Base(_dec, true), mesh_(Base::mesh()), tolerance_(_error_tolerance) {
|
||||||
|
mesh_.add_property(points_);
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructor
|
/// Destructor
|
||||||
ModHausdorffT(DecimaterT& _dec,
|
~ModHausdorffT() {
|
||||||
Scalar _error_tolerance = FLT_MAX)
|
mesh_.remove_property(points_);
|
||||||
: Base(_dec, true),
|
}
|
||||||
mesh_(Base::mesh()),
|
|
||||||
tolerance_(_error_tolerance)
|
|
||||||
{
|
|
||||||
mesh_.add_property(points_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// get max error tolerance
|
||||||
|
Scalar tolerance() const {
|
||||||
|
return tolerance_;
|
||||||
|
}
|
||||||
|
|
||||||
/// Destructor
|
/// set max error tolerance
|
||||||
~ModHausdorffT()
|
void set_tolerance(Scalar _e) {
|
||||||
{
|
tolerance_ = _e;
|
||||||
mesh_.remove_property(points_);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// get max error tolerance
|
/// reset per-face point lists
|
||||||
Scalar tolerance() const { return tolerance_; }
|
virtual void initialize();
|
||||||
|
|
||||||
/// set max error tolerance
|
/** \brief compute Hausdorff error for one-ring
|
||||||
void set_tolerance(Scalar _e) { tolerance_ = _e; }
|
*
|
||||||
|
* This mod only allows collapses if the Hausdorff distance
|
||||||
|
* after a collapse is lower than the given tolerance.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param _ci Collapse info data
|
||||||
|
* @return Binary return, if collapse is legal or illegal
|
||||||
|
*/
|
||||||
|
|
||||||
/// reset per-face point lists
|
virtual float collapse_priority(const CollapseInfo& _ci);
|
||||||
virtual void initialize();
|
|
||||||
|
|
||||||
|
/// re-distribute points
|
||||||
|
virtual void postprocess_collapse(const CollapseInfo& _ci);
|
||||||
|
|
||||||
/// compute Hausdorff error for one-ring
|
private:
|
||||||
virtual float collapse_priority(const CollapseInfo& _ci);
|
|
||||||
|
|
||||||
|
/// squared distance from point _p to triangle (_v0, _v1, _v2)
|
||||||
|
Scalar distPointTriangleSquared(const Point& _p, const Point& _v0,
|
||||||
|
const Point& _v1, const Point& _v2, Point& _nearestPoint);
|
||||||
|
|
||||||
/// re-distribute points
|
/// compute max error for face _fh w.r.t. its point list and _p
|
||||||
virtual void postprocess_collapse(const CollapseInfo& _ci);
|
Scalar compute_sqr_error(FaceHandle _fh, const Point& _p) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Mesh& mesh_;
|
||||||
|
Scalar tolerance_;
|
||||||
|
|
||||||
private:
|
OpenMesh::FPropHandleT<Points> points_;
|
||||||
|
|
||||||
/// squared distance from point _p to triangle (_v0, _v1, _v2)
|
|
||||||
Scalar distPointTriangleSquared( const Point& _p,
|
|
||||||
const Point& _v0,
|
|
||||||
const Point& _v1,
|
|
||||||
const Point& _v2,
|
|
||||||
Point& _nearestPoint );
|
|
||||||
|
|
||||||
|
|
||||||
/// compute max error for face _fh w.r.t. its point list and _p
|
|
||||||
Scalar compute_sqr_error(FaceHandle _fh, const Point& _p) const;
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Mesh& mesh_;
|
|
||||||
Scalar tolerance_;
|
|
||||||
|
|
||||||
OpenMesh::FPropHandleT<Points> points_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
} // END_NS_DECIMATER
|
}// END_NS_DECIMATER
|
||||||
} // END_NS_OPENMESH
|
} // END_NS_OPENMESH
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
#if defined(INCLUDE_TEMPLATES) && !defined(MODHAUSDORFFT_C)
|
#if defined(INCLUDE_TEMPLATES) && !defined(OPENMESH_DECIMATER_MODHAUSDORFFT_C)
|
||||||
#define MODHAUSDORFFT_TEMPLATES
|
#define OPENMESH_DECIMATER_MODHAUSDORFFT_TEMPLATES
|
||||||
#include "ModHausdorffT.cc"
|
#include "ModHausdorffT.cc"
|
||||||
#endif
|
#endif
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
#endif // MODHAUSDORFFT_HH defined
|
#endif // OPENMESH_DECIMATER_MODHAUSDORFFT_HH defined
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -30,17 +30,17 @@
|
|||||||
* License along with OpenMesh. If not, *
|
* License along with OpenMesh. If not, *
|
||||||
* see <http://www.gnu.org/licenses/>. *
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/*===========================================================================*\
|
/*===========================================================================*\
|
||||||
* *
|
* *
|
||||||
* $Revision$ *
|
* $Revision$ *
|
||||||
* $Date$ *
|
* $Date$ *
|
||||||
* *
|
* *
|
||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/** \file ModQuadricT.hh
|
/** \file ModQuadricT.hh
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@@ -48,59 +48,52 @@
|
|||||||
// CLASS ModQuadricT
|
// CLASS ModQuadricT
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
#ifndef OPENMESH_TOOLS_MODINDEPENDENTSETST_HH
|
#ifndef OPENMESH_TOOLS_MODINDEPENDENTSETST_HH
|
||||||
#define OPENMESH_TOOLS_MODINDEPENDENTSETST_HH
|
#define OPENMESH_TOOLS_MODINDEPENDENTSETST_HH
|
||||||
|
|
||||||
|
|
||||||
//== INCLUDES =================================================================
|
//== INCLUDES =================================================================
|
||||||
|
|
||||||
#include <OpenMesh/Tools/Decimater/ModBaseT.hh>
|
#include <OpenMesh/Tools/Decimater/ModBaseT.hh>
|
||||||
|
|
||||||
|
|
||||||
//== NAMESPACE ================================================================
|
//== NAMESPACE ================================================================
|
||||||
|
|
||||||
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
namespace OpenMesh { // BEGIN_NS_OPENMESH
|
||||||
namespace Decimater { // BEGIN_NS_DECIMATER
|
namespace Decimater { // BEGIN_NS_DECIMATER
|
||||||
|
|
||||||
|
|
||||||
//== CLASS DEFINITION =========================================================
|
//== CLASS DEFINITION =========================================================
|
||||||
|
|
||||||
|
|
||||||
/** Lock one-ring around remaining vertex after a collapse to prevent
|
/** Lock one-ring around remaining vertex after a collapse to prevent
|
||||||
* further collapses of halfedges incident to the one-ring vertices.
|
* further collapses of halfedges incident to the one-ring vertices.
|
||||||
*/
|
*/
|
||||||
template <class DecimaterType>
|
template<class DecimaterType>
|
||||||
class ModIndependentSetsT : public ModBaseT<DecimaterType>
|
class ModIndependentSetsT: public ModBaseT<DecimaterType> {
|
||||||
{
|
public:
|
||||||
public:
|
DECIMATING_MODULE( ModIndependentSetsT, DecimaterType, IndependentSets )
|
||||||
DECIMATING_MODULE( ModIndependentSetsT, DecimaterType, IndependentSets );
|
;
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
ModIndependentSetsT( DecimaterType &_dec ) : Base(_dec, true) {}
|
ModIndependentSetsT(DecimaterType &_dec) :
|
||||||
|
Base(_dec, true) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// override
|
||||||
|
void postprocess_collapse(const CollapseInfo& _ci) {
|
||||||
|
typename Mesh::VertexVertexIter vv_it;
|
||||||
|
|
||||||
/// override
|
Base::mesh().status(_ci.v1).set_locked(true);
|
||||||
void postprocess_collapse(const CollapseInfo& _ci)
|
vv_it = Base::mesh().vv_iter(_ci.v1);
|
||||||
{
|
for (; vv_it; ++vv_it)
|
||||||
typename Mesh::VertexVertexIter vv_it;
|
Base::mesh().status(vv_it).set_locked(true);
|
||||||
|
}
|
||||||
|
|
||||||
Base::mesh().status(_ci.v1).set_locked(true);
|
private:
|
||||||
vv_it = Base::mesh().vv_iter(_ci.v1);
|
|
||||||
for (; vv_it; ++vv_it)
|
|
||||||
Base::mesh().status(vv_it).set_locked(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// hide this method
|
||||||
private:
|
void set_binary(bool _b) { }
|
||||||
|
|
||||||
/// hide this method
|
|
||||||
void set_binary(bool _b) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
} // END_NS_DECIMATER
|
}// END_NS_DECIMATER
|
||||||
} // END_NS_OPENMESH
|
} // END_NS_OPENMESH
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
#endif // OPENMESH_TOOLS_MODINDEPENDENTSETST_HH defined
|
#endif // OPENMESH_TOOLS_MODINDEPENDENTSETST_HH defined
|
||||||
|
|||||||
@@ -49,15 +49,15 @@
|
|||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
|
||||||
#ifndef MODNORMALDEVIATIONT_HH
|
#ifndef OPENMESH_DECIMATER_MODNORMALDEVIATIONT_HH
|
||||||
#define MODNORMALDEVIATIONT_HH
|
#define OPENMESH_DECIMATER_MODNORMALDEVIATIONT_HH
|
||||||
|
|
||||||
|
|
||||||
//== INCLUDES =================================================================
|
//== INCLUDES =================================================================
|
||||||
|
|
||||||
#include <OpenMesh/Tools/Decimater/ModBaseT.hh>
|
#include <OpenMesh/Tools/Decimater/ModBaseT.hh>
|
||||||
#include <OpenMesh/Core/Utils/Property.hh>
|
#include <OpenMesh/Core/Utils/Property.hh>
|
||||||
#include <ACG/Geometry/Types/NormalConeT.hh>
|
#include <OpenMesh/Core/Geometry/NormalConeT.hh>
|
||||||
|
|
||||||
|
|
||||||
//== NAMESPACES ===============================================================
|
//== NAMESPACES ===============================================================
|
||||||
@@ -69,7 +69,20 @@ namespace Decimater {
|
|||||||
//== CLASS DEFINITION =========================================================
|
//== CLASS DEFINITION =========================================================
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief Use Normal deviation to control decimation
|
||||||
|
*
|
||||||
|
* The module tracks the normals while decimating
|
||||||
|
* a normal cone consisting of all normals of the
|
||||||
|
* faces collapsed together is computed and if
|
||||||
|
* a collapse would increase the size of
|
||||||
|
* the cone to a value greater than the given value
|
||||||
|
* the collapse will be illegal.
|
||||||
|
*
|
||||||
|
* In binary and mode, the collapse is legal if:
|
||||||
|
* - The normal deviation after the collapse is lower than the given value
|
||||||
|
*
|
||||||
|
* In continuous mode the maximal deviation is returned
|
||||||
|
*/
|
||||||
template <class DecimaterT>
|
template <class DecimaterT>
|
||||||
class ModNormalDeviationT : public ModBaseT< DecimaterT >
|
class ModNormalDeviationT : public ModBaseT< DecimaterT >
|
||||||
{
|
{
|
||||||
@@ -83,7 +96,7 @@ public:
|
|||||||
typedef typename Mesh::VertexHandle VertexHandle;
|
typedef typename Mesh::VertexHandle VertexHandle;
|
||||||
typedef typename Mesh::FaceHandle FaceHandle;
|
typedef typename Mesh::FaceHandle FaceHandle;
|
||||||
typedef typename Mesh::EdgeHandle EdgeHandle;
|
typedef typename Mesh::EdgeHandle EdgeHandle;
|
||||||
typedef ACG::Geometry::NormalConeT<Scalar> NormalCone;
|
typedef NormalConeT<Scalar> NormalCone;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -91,13 +104,12 @@ public:
|
|||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
ModNormalDeviationT(DecimaterT& _dec, float _max_dev = 180.0)
|
ModNormalDeviationT(DecimaterT& _dec, float _max_dev = 180.0)
|
||||||
: Base(_dec, true),
|
: Base(_dec, true), mesh_(Base::mesh())
|
||||||
mesh_(Base::mesh())
|
|
||||||
{
|
{
|
||||||
set_normal_deviation(_max_dev);
|
set_normal_deviation(_max_dev);
|
||||||
mesh_.add_property(normal_cones_);
|
mesh_.add_property(normal_cones_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~ModNormalDeviationT() {
|
~ModNormalDeviationT() {
|
||||||
@@ -105,12 +117,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Get normal deviation
|
/// Get normal deviation ( 0 .. 360 )
|
||||||
Scalar normal_deviation() const {
|
Scalar normal_deviation() const {
|
||||||
return normal_deviation_ / M_PI * 180.0;
|
return normal_deviation_ / M_PI * 180.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set normal deviation
|
/// Set normal deviation ( 0 .. 360 )
|
||||||
void set_normal_deviation(Scalar _s) {
|
void set_normal_deviation(Scalar _s) {
|
||||||
normal_deviation_ = _s / 180.0 * M_PI;
|
normal_deviation_ = _s / 180.0 * M_PI;
|
||||||
}
|
}
|
||||||
@@ -122,13 +134,26 @@ public:
|
|||||||
mesh_.add_property(normal_cones_);
|
mesh_.add_property(normal_cones_);
|
||||||
|
|
||||||
typename Mesh::FaceIter f_it = mesh_.faces_begin(),
|
typename Mesh::FaceIter f_it = mesh_.faces_begin(),
|
||||||
f_end = mesh_.faces_end();
|
f_end = mesh_.faces_end();
|
||||||
|
|
||||||
for (; f_it != f_end; ++f_it)
|
for (; f_it != f_end; ++f_it)
|
||||||
mesh_.property(normal_cones_, f_it) = NormalCone(mesh_.normal(f_it));
|
mesh_.property(normal_cones_, f_it) = NormalCone(mesh_.normal(f_it));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \brief Control normals when Decimating
|
||||||
|
*
|
||||||
|
* Binary and Cont. mode.
|
||||||
|
*
|
||||||
|
* The module tracks the normals while decimating
|
||||||
|
* a normal cone consisting of all normals of the
|
||||||
|
* faces collapsed together is computed and if
|
||||||
|
* a collapse would increase the size of
|
||||||
|
* the cone to a value greater than the given value
|
||||||
|
* the collapse will be illegal.
|
||||||
|
*
|
||||||
|
* @param _ci Collapse info data
|
||||||
|
* @return Half of the normal cones size (radius in radians)
|
||||||
|
*/
|
||||||
float collapse_priority(const CollapseInfo& _ci) {
|
float collapse_priority(const CollapseInfo& _ci) {
|
||||||
// simulate collapse
|
// simulate collapse
|
||||||
mesh_.set_point(_ci.v0, _ci.p1);
|
mesh_.set_point(_ci.v0, _ci.p1);
|
||||||
@@ -152,7 +177,7 @@ public:
|
|||||||
|
|
||||||
if (nc.angle() > max_angle) {
|
if (nc.angle() > max_angle) {
|
||||||
max_angle = nc.angle();
|
max_angle = nc.angle();
|
||||||
if (max_angle > 0.5*normal_deviation_)
|
if (max_angle > 0.5 * normal_deviation_)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,8 +188,7 @@ public:
|
|||||||
mesh_.set_point(_ci.v0, _ci.p0);
|
mesh_.set_point(_ci.v0, _ci.p0);
|
||||||
|
|
||||||
|
|
||||||
return (max_angle < 0.5*normal_deviation_ ?
|
return (max_angle < 0.5 * normal_deviation_ ? max_angle : float( Base::ILLEGAL_COLLAPSE ));
|
||||||
max_angle : float( Base::ILLEGAL_COLLAPSE ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -193,7 +217,7 @@ public:
|
|||||||
merge(mesh_.property(normal_cones_, _ci.fr));
|
merge(mesh_.property(normal_cones_, _ci.fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -208,6 +232,6 @@ private:
|
|||||||
} // END_NS_DECIMATER
|
} // END_NS_DECIMATER
|
||||||
} // END_NS_OPENMESH
|
} // END_NS_OPENMESH
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
#endif // MODNORMALDEVIATIONT_HH defined
|
#endif // OPENMESH_DECIMATER_MODNORMALDEVIATIONT_HH defined
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace Decimater { // BEGIN_NS_DECIMATER
|
|||||||
*
|
*
|
||||||
* This module can be used only as a binary module. The criterion
|
* This module can be used only as a binary module. The criterion
|
||||||
* of allowing/disallowing the collapse is the angular deviation between
|
* of allowing/disallowing the collapse is the angular deviation between
|
||||||
* the face normal of the orignal faces and normals of the faces after the
|
* the face normal of the original faces and normals of the faces after the
|
||||||
* collapse. The collapse will pass the test, if the deviation is below
|
* collapse. The collapse will pass the test, if the deviation is below
|
||||||
* a given threshold.
|
* a given threshold.
|
||||||
*/
|
*/
|
||||||
@@ -102,8 +102,8 @@ public:
|
|||||||
* -# Compute for each adjacent face of \c _ci.v0 the face
|
* -# Compute for each adjacent face of \c _ci.v0 the face
|
||||||
* normal if the collpase would be executed.
|
* normal if the collpase would be executed.
|
||||||
*
|
*
|
||||||
* -# Prevent the collapse, if the angle between the original and the
|
* -# Prevent the collapse, if the cosine of the angle between the
|
||||||
* new normal is below a given threshold.
|
* original and the new normal is below a given threshold.
|
||||||
*
|
*
|
||||||
* \param _ci The collapse description
|
* \param _ci The collapse description
|
||||||
* \return LEGAL_COLLAPSE or ILLEGAL_COLLAPSE
|
* \return LEGAL_COLLAPSE or ILLEGAL_COLLAPSE
|
||||||
@@ -148,9 +148,6 @@ public:
|
|||||||
/// get normal deviation
|
/// get normal deviation
|
||||||
float max_normal_deviation() const { return max_deviation_ / M_PI * 180.0; }
|
float max_normal_deviation() const { return max_deviation_ / M_PI * 180.0; }
|
||||||
|
|
||||||
/// \deprecated
|
|
||||||
float normal_deviation() const { return max_normal_deviation(); }
|
|
||||||
|
|
||||||
/** Set normal deviation
|
/** Set normal deviation
|
||||||
*
|
*
|
||||||
* Set the maximum angular deviation of the orignal normal and the new
|
* Set the maximum angular deviation of the orignal normal and the new
|
||||||
@@ -160,10 +157,6 @@ public:
|
|||||||
max_deviation_ = _f / 180.0 * M_PI;
|
max_deviation_ = _f / 180.0 * M_PI;
|
||||||
min_cos_ = cos(max_deviation_);
|
min_cos_ = cos(max_deviation_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \deprecated
|
|
||||||
void set_normal_deviation(float _f)
|
|
||||||
{ set_max_normal_deviation(_f); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ namespace Decimater {
|
|||||||
//== CLASS DEFINITION =========================================================
|
//== CLASS DEFINITION =========================================================
|
||||||
|
|
||||||
|
|
||||||
/** Mesh decimation module computing collapse priority based on error quadrics.
|
/** \brief Mesh decimation module computing collapse priority based on error quadrics.
|
||||||
*
|
*
|
||||||
* This module can be used as a binary and non-binary module.
|
* This module can be used as a binary and non-binary module.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
\*===========================================================================*/
|
\*===========================================================================*/
|
||||||
|
|
||||||
/** \file ModRoundnessT.hh
|
/** \file ModRoundnessT.hh
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@@ -49,8 +49,8 @@
|
|||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
#ifndef OPENMESH_TOOLS_MODROUNDNESST_HH
|
#ifndef OPENMESH_DECIMATER_MODROUNDNESST_HH
|
||||||
#define OPENMESH_TOOLS_MODROUNDNESST_HH
|
#define OPENMESH_DECIMATER_MODROUNDNESST_HH
|
||||||
|
|
||||||
|
|
||||||
//== INCLUDES =================================================================
|
//== INCLUDES =================================================================
|
||||||
@@ -72,33 +72,39 @@ namespace Decimater { // BEGIN_NS_DECIMATER
|
|||||||
//== CLASS DEFINITION =========================================================
|
//== CLASS DEFINITION =========================================================
|
||||||
|
|
||||||
|
|
||||||
/** Compute error value based on roundness criteria.
|
/** \brief Use Roundness of triangles to control decimation
|
||||||
*/
|
*
|
||||||
|
*
|
||||||
|
* In binary and mode, the collapse is legal if:
|
||||||
|
* - The roundness after the collapse is greater than the given value
|
||||||
|
*
|
||||||
|
* In continuous mode the roundness after the collapse is returned
|
||||||
|
*/
|
||||||
template <class DecimaterType>
|
template <class DecimaterType>
|
||||||
class ModRoundnessT : public ModBaseT<DecimaterType>
|
class ModRoundnessT : public ModBaseT<DecimaterType>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DECIMATING_MODULE( ModRoundnessT, DecimaterType, Roundness );
|
DECIMATING_MODULE( ModRoundnessT, DecimaterType, Roundness );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// typedefs
|
// typedefs
|
||||||
typedef typename Mesh::Point Point;
|
typedef typename Mesh::Point Point;
|
||||||
typedef typename vector_traits<Point>::value_type value_type;
|
typedef typename vector_traits<Point>::value_type value_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
ModRoundnessT( DecimaterType &_dec ) :
|
ModRoundnessT( DecimaterType &_dec ) :
|
||||||
Base(_dec, false),
|
Base(_dec, false),
|
||||||
min_r_(-1.0)
|
min_r_(-1.0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~ModRoundnessT() { }
|
~ModRoundnessT() { }
|
||||||
|
|
||||||
public: // inherited
|
public: // inherited
|
||||||
|
|
||||||
/** Compute collapse priority due to roundness of triangle.
|
/** Compute collapse priority due to roundness of triangle.
|
||||||
*
|
*
|
||||||
* The roundness is computed by dividing the radius of the
|
* The roundness is computed by dividing the radius of the
|
||||||
@@ -111,14 +117,14 @@ public: // inherited
|
|||||||
*/
|
*/
|
||||||
float collapse_priority(const CollapseInfo& _ci)
|
float collapse_priority(const CollapseInfo& _ci)
|
||||||
{
|
{
|
||||||
// using namespace OpenMesh;
|
// using namespace OpenMesh;
|
||||||
|
|
||||||
typename Mesh::ConstVertexOHalfedgeIter voh_it(Base::mesh(), _ci.v0);
|
typename Mesh::ConstVertexOHalfedgeIter voh_it(Base::mesh(), _ci.v0);
|
||||||
double r;
|
double r;
|
||||||
double priority = 0.0; //==LEGAL_COLLAPSE
|
double priority = 0.0; //==LEGAL_COLLAPSE
|
||||||
typename Mesh::FaceHandle fhC, fhB;
|
typename Mesh::FaceHandle fhC, fhB;
|
||||||
Vec3f B,C;
|
Vec3f B,C;
|
||||||
|
|
||||||
if ( min_r_ < 0.0 ) // continues mode
|
if ( min_r_ < 0.0 ) // continues mode
|
||||||
{
|
{
|
||||||
C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(voh_it)));
|
C = vector_cast<Vec3f>(Base::mesh().point( Base::mesh().to_vertex_handle(voh_it)));
|
||||||
@@ -126,19 +132,19 @@ public: // inherited
|
|||||||
|
|
||||||
for (++voh_it; voh_it; ++voh_it)
|
for (++voh_it; voh_it; ++voh_it)
|
||||||
{
|
{
|
||||||
B = C;
|
B = C;
|
||||||
fhB = fhC;
|
fhB = fhC;
|
||||||
C = vector_cast<Vec3f>(Base::mesh().point(Base::mesh().to_vertex_handle(voh_it)));
|
C = vector_cast<Vec3f>(Base::mesh().point(Base::mesh().to_vertex_handle(voh_it)));
|
||||||
fhC = Base::mesh().face_handle( voh_it.handle() );
|
fhC = Base::mesh().face_handle( voh_it.handle() );
|
||||||
|
|
||||||
if ( fhB == _ci.fl || fhB == _ci.fr )
|
if ( fhB == _ci.fl || fhB == _ci.fr )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// simulate collapse using position of v1
|
// simulate collapse using position of v1
|
||||||
r = roundness( vector_cast<Vec3f>(_ci.p1), B, C );
|
r = roundness( vector_cast<Vec3f>(_ci.p1), B, C );
|
||||||
|
|
||||||
// return the maximum non-roundness
|
// return the maximum non-roundness
|
||||||
priority = std::max( priority, (1.0-r) );
|
priority = std::max( priority, (1.0-r) );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,24 +155,23 @@ public: // inherited
|
|||||||
|
|
||||||
for (++voh_it; voh_it && (priority==Base::LEGAL_COLLAPSE); ++voh_it)
|
for (++voh_it; voh_it && (priority==Base::LEGAL_COLLAPSE); ++voh_it)
|
||||||
{
|
{
|
||||||
B = C;
|
B = C;
|
||||||
fhB = fhC;
|
fhB = fhC;
|
||||||
C = vector_cast<Vec3f>(Base::mesh().point(Base::mesh().to_vertex_handle(voh_it)));
|
C = vector_cast<Vec3f>(Base::mesh().point(Base::mesh().to_vertex_handle(voh_it)));
|
||||||
fhC = Base::mesh().face_handle( voh_it.handle() );
|
fhC = Base::mesh().face_handle( voh_it.handle() );
|
||||||
|
|
||||||
if ( fhB == _ci.fl || fhB == _ci.fr )
|
if ( fhB == _ci.fl || fhB == _ci.fr )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
priority = ( (r=roundness( vector_cast<Vec3f>(_ci.p1), B, C )) < min_r_)
|
priority = ( (r=roundness( vector_cast<Vec3f>(_ci.p1), B, C )) < min_r_)
|
||||||
? Base::ILLEGAL_COLLAPSE
|
? Base::ILLEGAL_COLLAPSE : Base::LEGAL_COLLAPSE;
|
||||||
: Base::LEGAL_COLLAPSE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (float) priority;
|
return (float) priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public: // specific methods
|
public: // specific methods
|
||||||
|
|
||||||
@@ -199,7 +204,7 @@ public: // specific methods
|
|||||||
* \param _min_roundness in range (0,1)
|
* \param _min_roundness in range (0,1)
|
||||||
* \param _binary Set true, if the binary mode should be enabled,
|
* \param _binary Set true, if the binary mode should be enabled,
|
||||||
* else false. In latter case the collapse_priority()
|
* else false. In latter case the collapse_priority()
|
||||||
* returns a float value if the constrain does not apply
|
* returns a float value if the constraint does not apply
|
||||||
* and ILLEGAL_COLLAPSE else.
|
* and ILLEGAL_COLLAPSE else.
|
||||||
*/
|
*/
|
||||||
void set_min_roundness( value_type _min_roundness, bool _binary=true )
|
void set_min_roundness( value_type _min_roundness, bool _binary=true )
|
||||||
@@ -282,8 +287,8 @@ public: // specific methods
|
|||||||
return nR;
|
return nR;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
value_type min_r_;
|
value_type min_r_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -297,6 +302,6 @@ private:
|
|||||||
# undef OM_ENABLE_WARNINGS
|
# undef OM_ENABLE_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
#endif // OPENMESH_TOOLS_PROGMESHT_HH defined
|
#endif // OPENMESH_DECIMATER_MODROUNDNESST_HH defined
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user