Commit d4487aaa authored by Jan Möbius's avatar Jan Möbius
Browse files

Documentation for decimater modules, updated decimater, more modules

git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@460 fdac6126-5c0c-442c-9429-916003d36597
parent bbf5e47a
......@@ -64,6 +64,10 @@
#include <OpenMesh/Tools/Utils/getopt.h>
#include <OpenMesh/Tools/Utils/Timer.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/ModQuadricT.hh>
#include <OpenMesh/Tools/Decimater/ModProgMeshT.hh>
......@@ -116,13 +120,17 @@ struct DecOptions
CmdOption<bool> decorate_name;
CmdOption<float> n_collapses;
CmdOption<float> Q; // Quadrics
CmdOption<float> NF; // Normal Flipping
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>
bool init( CmdOption<T>& _o, const std::string& _val )
{
......@@ -160,15 +168,18 @@ struct DecOptions
strip(name);
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 == "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);
return false;
}
std::string& strip(std::string & line)
{
std::string::size_type pos = 0;
......@@ -238,18 +249,52 @@ decimate(const std::string &_ifname,
// ---- 1 - create decimater instance
Decimater decimater( mesh );
// ---- 2 - registrate modules
// ---- 2 - register modules
if (gverbose)
clog << " registrate modules" << endl;
clog << " register modules" << endl;
typename OpenMesh::Decimater::ModQuadricT<Decimater>::Handle modQ;
if (_opt.Q.is_enabled())
typename OpenMesh::Decimater::ModAspectRatioT<Decimater>::Handle modAR;
if (_opt.AR.is_enabled())
{
decimater.add(modQ);
if (_opt.Q.has_value())
decimater.module( modQ ).set_max_err( _opt.Q );
decimater.add(modAR);
if (_opt.AR.has_value())
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;
......@@ -258,20 +303,23 @@ decimate(const std::string &_ifname,
{
decimater.add(modNF);
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;
if ( _opt.PM.is_enabled() )
decimater.add(modPM);
typename OpenMesh::Decimater::ModQuadricT<Decimater>::Handle modQ;
typename OpenMesh::Decimater::ModIndependentSetsT<Decimater>::Handle modIS;
if ( _opt.IS.is_enabled() )
decimater.add(modIS);
if (_opt.Q.is_enabled())
{
decimater.add(modQ);
if (_opt.Q.has_value())
decimater.module( modQ ).set_max_err( _opt.Q );
}
typename OpenMesh::Decimater::ModRoundnessT<Decimater>::Handle modR;
......@@ -475,26 +523,25 @@ void usage_and_exit(int xcode)
}
std::cerr << std::endl;
if (xcode)
{
if (xcode) {
std::cerr << "Error " << xcode << ": " << errmsg << std::endl << std::endl;
}
std::cerr << "Usage: decimator [Options] -i input-file -o output-file\n"
<< " Decimating a mesh using quadrics and normal flipping.\n"
<< std::endl;
std::cerr << "Options\n"
<< std::endl;
<< " Decimating a mesh using quadrics and normal flipping.\n" << std::endl;
std::cerr << "Options\n" << std::endl;
std::cerr << " -M \"{Module-Name}[:Value]}\"\n"
<< " Use named module with eventually given parameterization\n"
<< std::endl;
<< " Use named module with eventually given parameterization\n" << std::endl;
std::cerr << " -n <N>\n"
<< " N >= 1: do N halfedge collapses.\n"
<< " N <=-1: decimate down to |N| vertices.\n"
<< " 0 < N < 1: decimate down to N%.\n"
<< std::endl;
<< " 0 < N < 1: decimate down to N%.\n" << std::endl;
std::cerr << std::endl;
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 << " ND[:angle] - ModNormalDeviation\n";
std::cerr << " NF[:angle] - ModNormalFlipping\n";
std::cerr << " PM[:file name] - ModProgMesh\n";
std::cerr << " Q[:error] - ModQuadric\n";
......
......@@ -30,14 +30,14 @@
* License along with OpenMesh. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
\*===========================================================================*/
/** \file CollapseInfoT.hh
Provides data class CollapseInfoT for storing all information
......@@ -49,20 +49,16 @@
// STRUCT CollpaseInfoT
//
//=============================================================================
#ifndef OPENMESH_DECIMATER_COLLAPSEINFOT_HH
#define OPENMESH_DECIMATER_COLLAPSEINFOT_HH
//== INCLUDES =================================================================
//== NAMESPACE ================================================================
namespace OpenMesh {
namespace Decimater {
//== CLASS DEFINITION =========================================================
/** Stores information about a halfedge collapse.
......@@ -73,10 +69,9 @@ namespace Decimater {
\image html collapse_info.png
\see ModProgMeshT::Info
*/
template <class Mesh>
struct CollapseInfoT
{
public:
template<class Mesh>
struct CollapseInfoT {
public:
/** Initializing constructor.
*
* Given a mesh and a halfedge handle of the halfedge to be collapsed
......@@ -108,49 +103,38 @@ public:
//@}
};
//-----------------------------------------------------------------------------
// CollapseInfoT::CollapseInfoT( _mesh, _heh )
//
// Local configuration of halfedge collapse to be stored in CollapseInfoT:
/*
vl
*
/ \
/ \
/ fl \
v0 *------>* v1
\ fr /
\ /
\ /
*
vr
/**
* Local configuration of halfedge collapse to be stored in CollapseInfoT:
*
* vl
* *
* / \
* / \
* / fl \
* v0 *------>* v1
* \ fr /
* \ /
* \ /
* *
* vr
*
*
* @param _mesh Reference to mesh
* @param _heh The halfedge (v0 -> v1) defining the collapse
*/
// Parameters:
// _mesh Reference to mesh
// _heh The halfedge (v0 -> v1) defining the collapse
//
template <class Mesh>
inline
CollapseInfoT<Mesh>::
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))
template<class Mesh>
inline CollapseInfoT<Mesh>::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
if (fl.is_valid())
{
if (fl.is_valid()) {
vlv1 = mesh.next_halfedge_handle(v0v1);
v0vl = mesh.next_halfedge_handle(vlv1);
vl = mesh.to_vertex_handle(vlv1);
......@@ -158,10 +142,8 @@ CollapseInfoT(Mesh& _mesh, typename Mesh::HalfedgeHandle _heh) :
v0vl = mesh.opposite_halfedge_handle(v0vl);
}
// get vr
if (fr.is_valid())
{
if (fr.is_valid()) {
vrv0 = mesh.next_halfedge_handle(v1v0);
v1vr = mesh.next_halfedge_handle(vrv0);
vr = mesh.to_vertex_handle(vrv0);
......@@ -171,7 +153,7 @@ CollapseInfoT(Mesh& _mesh, typename Mesh::HalfedgeHandle _heh) :
}
//=============================================================================
} // END_NS_DECIMATER
}// END_NS_DECIMATER
} // END_NS_OPENMESH
//=============================================================================
#endif // OPENMESH_DECIMATER_COLLAPSEINFOT_HH defined
......
......@@ -30,28 +30,25 @@
* License along with OpenMesh. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
\*===========================================================================*/
/** \file DecimaterT.cc
*/
//=============================================================================
//
// CLASS DecimaterT - IMPLEMENTATION
//
//=============================================================================
#define OPENMESH_DECIMATER_DECIMATERT_CC
//== INCLUDES =================================================================
#include <OpenMesh/Tools/Decimater/DecimaterT.hh>
......@@ -63,26 +60,16 @@
# include <cfloat>
#endif
//== NAMESPACE ===============================================================
namespace OpenMesh {
namespace Decimater {
//== IMPLEMENTATION ==========================================================
template <class Mesh>
DecimaterT<Mesh>::
DecimaterT( Mesh& _mesh )
: mesh_(_mesh),
heap_(NULL),
cmodule_(NULL),
initialized_(false)
{
template<class Mesh>
DecimaterT<Mesh>::DecimaterT(Mesh& _mesh) :
mesh_(_mesh), heap_(NULL), cmodule_(NULL), initialized_(false) {
// default properties
mesh_.request_vertex_status();
mesh_.request_edge_status();
......@@ -90,19 +77,15 @@ DecimaterT( Mesh& _mesh )
mesh_.request_face_normals();
// private vertex properties
mesh_.add_property( collapse_target_ );
mesh_.add_property( priority_ );
mesh_.add_property( heap_position_ );
mesh_.add_property(collapse_target_);
mesh_.add_property(priority_);
mesh_.add_property(heap_position_);
}
//-----------------------------------------------------------------------------
template <class Mesh>
DecimaterT<Mesh>::
~DecimaterT()
{
template<class Mesh>
DecimaterT<Mesh>::~DecimaterT() {
// default properties
mesh_.release_vertex_status();
mesh_.release_edge_status();
......@@ -118,40 +101,33 @@ DecimaterT<Mesh>::
{
set_uninitialized();
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;
all_modules_.clear();
}
}
//-----------------------------------------------------------------------------
template <class Mesh>
void
DecimaterT<Mesh>::
info( std::ostream& _os )
{
if(initialized_)
{
template<class Mesh>
void DecimaterT<Mesh>::info(std::ostream& _os) {
if (initialized_) {
_os << "initialized : yes" << 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 << "priority module: " << cmodule_->name().c_str() << std::endl;
}
else {
} else {
_os << "initialized : no" << 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() << " : ";
if((*m_it)->is_binary()) {
if ((*m_it)->is_binary()) {
_os << "binary";
if((*m_it)->name() == "Quadric") {
if ((*m_it)->name() == "Quadric") {
_os << " and priority (special treatment)";
}
} else {
......@@ -162,17 +138,11 @@ info( std::ostream& _os )
}
}
//-----------------------------------------------------------------------------
template <class Mesh>
bool
DecimaterT<Mesh>::
initialize()
{
if(initialized_)
{
template<class Mesh>
bool DecimaterT<Mesh>::initialize() {
if (initialized_) {
return true;
}
......@@ -187,17 +157,15 @@ initialize()
// priority module explicitly.
// find the priority module: either the only non-binary module in the list, or "Quadric"
Module *quadric=NULL;
Module *pmodule=NULL;
for (ModuleListIterator m_it=all_modules_.begin(), m_end=all_modules_.end(); m_it != m_end; ++m_it)
{
if ( (*m_it)->name() == "Quadric")
Module *quadric = NULL;
Module *pmodule = NULL;
for (ModuleListIterator m_it = all_modules_.begin(), m_end =
all_modules_.end(); m_it != m_end; ++m_it) {
if ((*m_it)->name() == "Quadric")
quadric = *m_it;
if ( !(*m_it)->is_binary() )
{
if(pmodule)
{
if (!(*m_it)->is_binary()) {
if (pmodule) {
// only one priority module allowed!
set_uninitialized();
return false;
......@@ -207,11 +175,11 @@ initialize()
}
// Quadric is used as default priority module (even if it is set to be binary)
if(!pmodule && quadric) {
if (!pmodule && quadric) {
pmodule = quadric;
}
if(!pmodule) {
if (!pmodule) {
// At least one priority module required
set_uninitialized();
return false;
......@@ -220,12 +188,12 @@ initialize()
// set pmodule as the current priority module
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
(*m_it)->initialize();
if(*m_it != pmodule) {
if (*m_it != pmodule) {
// all other modules are binary, and go into bmodules_ list
bmodules_.push_back(*m_it);
}
......@@ -234,39 +202,32 @@ initialize()
return initialized_ = true;
}
//-----------------------------------------------------------------------------
template <class Mesh>
bool
DecimaterT<Mesh>::is_collapse_legal(const CollapseInfo& _ci)
{
template<class Mesh>
bool DecimaterT<Mesh>::is_collapse_legal(const CollapseInfo& _ci) {
// std::clog << "DecimaterT<>::is_collapse_legal()\n";
// locked ? deleted ?
if (mesh_.status(_ci.v0).locked() ||
mesh_.status(_ci.v0).deleted())
if (mesh_.status(_ci.v0).locked() || mesh_.status(_ci.v0).deleted())
return false;
/*
/*
if (!mesh_.is_collapse_ok(_ci.v0v1))
{
return false;
}
*/
if (_ci.vl.is_valid() && _ci.vr.is_valid() &&
mesh_.find_halfedge(_ci.vl, _ci.vr).is_valid() &&
mesh_.valence(_ci.vl) == 3 && mesh_.valence(_ci.vr) == 3)
{
*/
if (_ci.vl.is_valid() && _ci.vr.is_valid()
&& mesh_.find_halfedge(_ci.vl, _ci.vr).is_valid()
&& mesh_.valence(_ci.vl) == 3 && mesh_.valence(_ci.vr) == 3) {
return false;
}
//--- feature test ---
if (mesh_.status(_ci.v0).feature() &&
!mesh_.status(mesh_.edge_handle(_ci.v0v1)).feature())
if (mesh_.status(_ci.v0).feature()
&& !mesh_.status(mesh_.edge_handle(_ci.v0v1)).feature())
return false;
//--- test one ring intersection ---
typename Mesh::VertexVertexIter vv_it;
......@@ -278,24 +239,19 @@ DecimaterT<Mesh>::is_collapse_legal(const CollapseInfo& _ci)
mesh_.status(vv_it).set_tagged(true);
for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it)
if (mesh_.status(vv_it).tagged() &&
vv_it.handle() != _ci.vl &&
vv_it.handle() != _ci.vr)
if (mesh_.status(vv_it).tagged() && vv_it.handle() != _ci.vl
&& vv_it.handle() != _ci.vr)
return false;
// if both are invalid OR equal -> fail
if (_ci.vl == _ci.vr) return false;
if (_ci.vl == _ci.vr)
return false;
//--- test boundary cases ---