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:
Jan Möbius
2011-11-16 09:45:08 +00:00
parent bbf5e47a82
commit d4487aaa79
15 changed files with 698 additions and 817 deletions

View File

@@ -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();

View File

@@ -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 );
} }

View File

@@ -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

View File

@@ -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
//============================================================================= //=============================================================================

View File

@@ -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);
} }
} }
//============================================================================= //=============================================================================
} }
} }

View File

@@ -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
//============================================================================= //=============================================================================

View File

@@ -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 ));
} }
//============================================================================= //=============================================================================
} }
} }

View File

@@ -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
//============================================================================= //=============================================================================

View File

@@ -49,7 +49,7 @@
// //
//============================================================================= //=============================================================================
#define MODHAUSDORFFT_C #define OPENMESH_DECIMATER_MODHAUSDORFFT_C
//== INCLUDES ================================================================= //== INCLUDES =================================================================

View File

@@ -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
//============================================================================= //=============================================================================

View File

@@ -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

View File

@@ -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
//============================================================================= //=============================================================================

View File

@@ -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:

View File

@@ -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.
*/ */

View File

@@ -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
//============================================================================= //=============================================================================