- added the set_error_tolerance_factor function to ModBaseT and implemented it in inherited classes as necessary

- added the set_error_tolerance_factor function to BaseDecimaterT, which calls set_error_tolerance_factor for all loaded Mods
- implemented a decimate_constraints_only function for the McDecimater (and adjusted the MixedDecimater accordingly)
- implemented stop criterions for the McDecimater
- added some OpenMP loops for the sample generation to the McDecimater

git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@685 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
Isaak Lim
2012-09-19 16:15:39 +00:00
parent 33b72fb6ba
commit 48289493f3
18 changed files with 493 additions and 119 deletions

View File

@@ -207,6 +207,19 @@ void BaseDecimaterT<Mesh>::preprocess_collapse(CollapseInfo& _ci) {
cmodule_->preprocess_collapse(_ci); cmodule_->preprocess_collapse(_ci);
} }
//-----------------------------------------------------------------------------
template<class Mesh>
void BaseDecimaterT<Mesh>::set_error_tolerance_factor(double _factor) {
if (_factor >= 0.0 && _factor <= 1.0) {
typename ModuleList::iterator m_it, m_end = bmodules_.end();
for (m_it = bmodules_.begin(); m_it != m_end; ++m_it)
(*m_it)->set_error_tolerance_factor(_factor);
cmodule_->set_error_tolerance_factor(_factor);
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@@ -199,6 +199,16 @@ protected: //---------------------------------------------------- private method
/// Post-process a collapse /// Post-process a collapse
void postprocess_collapse(CollapseInfo& _ci); void postprocess_collapse(CollapseInfo& _ci);
/**
* This provides a function that allows the setting of a percentage
* of the original contraint of the modules
*
* Note that some modules might re-initialize in their
* set_error_tolerance_factor function as necessary
* @param factor_ has to be in the closed interval between 0.0 and 1.0
*/
void set_error_tolerance_factor(double _factor);
private: //------------------------------------------------------- private data private: //------------------------------------------------------- private data

View File

@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org * * www.openmesh.org *
* * * *
*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*
* This file is part of OpenMesh. * * This file is part of OpenMesh. *
* * * *
* OpenMesh is free software: you can redistribute it and/or modify * * OpenMesh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as * * it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of * * published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the * * the License, or (at your option) any later version with the *
@@ -33,7 +33,7 @@
\*===========================================================================*/ \*===========================================================================*/
/*===========================================================================*\ /*===========================================================================*\
* * * *
* $Revision$ * * $Revision$ *
* $Date$ * * $Date$ *
* * * *
@@ -214,6 +214,7 @@ size_t DecimaterT<Mesh>::decimate(size_t _n_collapses) {
// 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;
} }
@@ -307,6 +308,7 @@ size_t DecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
// 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;
} }

View File

@@ -59,6 +59,9 @@
#else #else
# include <cfloat> # include <cfloat>
#endif #endif
#ifdef USE_OPENMP
#include <omp.h>
#endif
//== NAMESPACE =============================================================== //== NAMESPACE ===============================================================
@@ -103,17 +106,33 @@ size_t McDecimaterT<Mesh>::decimate(size_t _n_collapses) {
unsigned int n_collapses(0); unsigned int n_collapses(0);
bool collapsesUnchanged = false;
// old n_collapses in order to check for convergence
unsigned int oldCollapses = 0;
// number of iterations where no new collapses where
// performed in a row
unsigned int noCollapses = 0;
while ( n_collapses < _n_collapses) { while ( n_collapses < _n_collapses) {
if (noCollapses > 20) {
omlog() << "[McDecimater] : no collapses performed in over 20 iterations in a row\n";
break;
}
// Optimal id and value will be collected during the random sampling // Optimal id and value will be collected during the random sampling
typename Mesh::HalfedgeHandle bestHandle(-1); typename Mesh::HalfedgeHandle bestHandle(-1);
typename Mesh::HalfedgeHandle tmpHandle(-1);
double bestEnergy = FLT_MAX; double bestEnergy = FLT_MAX;
double energy = FLT_MAX;
// Generate random samples for collapses // Generate random samples for collapses
#ifdef USE_OPENMP
#pragma omp parallel for private(energy,tmpHandle) shared(bestEnergy,bestHandle)
#endif
for ( int i = 0; i < (int)randomSamples_; ++i) { for ( int i = 0; i < (int)randomSamples_; ++i) {
// Random halfedge handle // Random halfedge handle
typename Mesh::HalfedgeHandle tmpHandle = typename Mesh::HalfedgeHandle((static_cast<double>(rand()) / RAND_MAX) * (mesh_.n_halfedges()-1) ); tmpHandle = typename Mesh::HalfedgeHandle((static_cast<double>(rand()) / RAND_MAX) * (mesh_.n_halfedges()-1) );
// if it is not deleted, we analyse it // if it is not deleted, we analyse it
if ( ! mesh_.status(tmpHandle).deleted() ) { if ( ! mesh_.status(tmpHandle).deleted() ) {
@@ -122,13 +141,22 @@ size_t McDecimaterT<Mesh>::decimate(size_t _n_collapses) {
// Check if legal we analyze the priority of this collapse operation // Check if legal we analyze the priority of this collapse operation
if (this->is_collapse_legal(ci)) { if (this->is_collapse_legal(ci)) {
double energy = this->collapse_priority(ci); #ifdef USE_OPENMP
#pragma omp critical(energyUpdate)
{
#endif
energy = this->collapse_priority(ci);
// Check if the current samples energy is better than any energy before if (energy != ModBaseT<Mesh>::ILLEGAL_COLLAPSE) {
if ( energy < bestEnergy ) { // Check if the current samples energy is better than any energy before
bestEnergy = energy; if ( energy < bestEnergy ) {
bestHandle = tmpHandle; bestEnergy = energy;
bestHandle = tmpHandle;
}
} }
#ifdef USE_OPENMP
}
#endif
} else { } else {
continue; continue;
} }
@@ -153,6 +181,11 @@ size_t McDecimaterT<Mesh>::decimate(size_t _n_collapses) {
mesh_.collapse(bestHandle); mesh_.collapse(bestHandle);
++n_collapses; ++n_collapses;
// store current collapses state
oldCollapses = n_collapses;
noCollapses = 0;
collapsesUnchanged = false;
// update triangle normals // update triangle normals
typename Mesh::VertexFaceIter vf_it = mesh_.vf_iter(ci.v1); typename Mesh::VertexFaceIter vf_it = mesh_.vf_iter(ci.v1);
for (; vf_it; ++vf_it) for (; vf_it; ++vf_it)
@@ -162,6 +195,15 @@ size_t McDecimaterT<Mesh>::decimate(size_t _n_collapses) {
// post-process collapse // post-process collapse
this->postprocess_collapse(ci); this->postprocess_collapse(ci);
} else {
if (oldCollapses == n_collapses) {
if (collapsesUnchanged == false) {
noCollapses = 1;
collapsesUnchanged = true;
} else {
noCollapses++;
}
}
} }
} }
@@ -177,34 +219,43 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
if (!this->is_initialized()) if (!this->is_initialized())
return 0; return 0;
// check if no vertex or face contraints were set
if ( (_nv == 0) && (_nf == 1) )
return decimate_constraints_only(1.0);
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);
// check if no vertex or face contraints were set bool collapsesUnchanged = false;
bool contraintsOnly = (_nv == 0) && (_nf == 1); // old n_collapses in order to check for convergence
unsigned int oldCollapses = 0;
// number of iterations where no new collapses where
// performed in a row
unsigned int noCollapses = 0;
// check if no legal collapses were found three times in a row while ( (_nv < nv) && (_nf < nf) ) {
// for the sampled halfedges if (noCollapses > 20) {
bool foundNoLegalCollapsesThrice = false; omlog() << "[McDecimater] : no collapses performed in over 20 iterations in a row\n";
break;
// store the last two amount of legal collapses found }
int lastLegalCollapses = -1;
int beforeLastLegalCollapses = -1;
while ( !foundNoLegalCollapsesThrice && (_nv < nv) && (_nf < nf) ) {
// Optimal id and value will be collected during the random sampling // Optimal id and value will be collected during the random sampling
typename Mesh::HalfedgeHandle bestHandle(-1); typename Mesh::HalfedgeHandle bestHandle(-1);
typename Mesh::HalfedgeHandle tmpHandle(-1);
double bestEnergy = FLT_MAX; double bestEnergy = FLT_MAX;
double energy = FLT_MAX;
// Generate random samples for collapses // Generate random samples for collapses
unsigned int legalCollapses = 0; #ifdef USE_OPENMP
#pragma omp parallel for private(energy,tmpHandle) shared(bestEnergy,bestHandle)
#endif
for ( int i = 0; i < (int)randomSamples_; ++i) { for ( int i = 0; i < (int)randomSamples_; ++i) {
// Random halfedge handle // Random halfedge handle
typename Mesh::HalfedgeHandle tmpHandle = typename Mesh::HalfedgeHandle((static_cast<double>(rand()) / RAND_MAX) * (mesh_.n_halfedges()-1) ); tmpHandle = typename Mesh::HalfedgeHandle((static_cast<double>(rand()) / RAND_MAX) * (mesh_.n_halfedges()-1) );
// if it is not deleted, we analyse it // if it is not deleted, we analyse it
if ( ! mesh_.status(tmpHandle).deleted() ) { if ( ! mesh_.status(tmpHandle).deleted() ) {
@@ -213,14 +264,22 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
// Check if legal we analyze the priority of this collapse operation // Check if legal we analyze the priority of this collapse operation
if (this->is_collapse_legal(ci)) { if (this->is_collapse_legal(ci)) {
++legalCollapses; #ifdef USE_OPENMP
double energy = this->collapse_priority(ci); #pragma omp critical(energyUpdate)
{
#endif
energy = this->collapse_priority(ci);
// Check if the current samples energy is better than any energy before if (energy != ModBaseT<Mesh>::ILLEGAL_COLLAPSE) {
if ( energy < bestEnergy ) { // Check if the current samples energy is better than any energy before
bestEnergy = energy; if ( energy < bestEnergy ) {
bestHandle = tmpHandle; bestEnergy = energy;
bestHandle = tmpHandle;
}
}
#ifdef USE_OPENMP
} }
#endif
} else { } else {
continue; continue;
} }
@@ -228,15 +287,6 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
} }
if (contraintsOnly) {
// check if no legal collapses were found three times in a row
foundNoLegalCollapsesThrice = (beforeLastLegalCollapses == 0) && (lastLegalCollapses == 0) && (legalCollapses == 0);
// store amount of last legal collapses found
beforeLastLegalCollapses = lastLegalCollapses;
lastLegalCollapses = legalCollapses;
}
// Found the best energy? // Found the best energy?
if ( bestEnergy != FLT_MAX ) { if ( bestEnergy != FLT_MAX ) {
@@ -267,6 +317,11 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
mesh_.collapse(bestHandle); mesh_.collapse(bestHandle);
++n_collapses; ++n_collapses;
// store current collapses state
oldCollapses = n_collapses;
noCollapses = 0;
collapsesUnchanged = false;
// update triangle normals // update triangle normals
typename Mesh::VertexFaceIter vf_it = mesh_.vf_iter(ci.v1); typename Mesh::VertexFaceIter vf_it = mesh_.vf_iter(ci.v1);
for (; vf_it; ++vf_it) for (; vf_it; ++vf_it)
@@ -276,6 +331,15 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
// post-process collapse // post-process collapse
this->postprocess_collapse(ci); this->postprocess_collapse(ci);
} else {
if (oldCollapses == n_collapses) {
if (collapsesUnchanged == false) {
noCollapses = 1;
collapsesUnchanged = true;
} else {
noCollapses++;
}
}
} }
} }
@@ -284,6 +348,155 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
return n_collapses; return n_collapses;
} }
//-----------------------------------------------------------------------------
template<class Mesh>
size_t McDecimaterT<Mesh>::decimate_constraints_only(float _factor) {
if (!this->is_initialized())
return 0;
if (_factor < 1.0)
this->set_error_tolerance_factor(_factor);
unsigned int n_collapses(0);
unsigned int nv = mesh_.n_vertices();
unsigned int nf = mesh_.n_faces();
bool lastCollapseIllegal = false;
// number of illegal collapses that occured in a row
unsigned int illegalCollapses = 0;
bool collapsesUnchanged = false;
// old n_collapses in order to check for convergence
unsigned int oldCollapses = 0;
// number of iterations where no new collapses where
// performed in a row
unsigned int noCollapses = 0;
while ( (noCollapses <= 20) && (illegalCollapses <= 10) && (nv > 0) && (nf > 1) ) {
// Optimal id and value will be collected during the random sampling
typename Mesh::HalfedgeHandle bestHandle(-1);
typename Mesh::HalfedgeHandle tmpHandle(-1);
double bestEnergy = FLT_MAX;
double energy = FLT_MAX;
// Generate random samples for collapses
#ifdef USE_OPENMP
#pragma omp parallel for private(energy,tmpHandle) shared(bestEnergy,bestHandle)
#endif
for ( int i = 0; i < (int)randomSamples_; ++i) {
// Random halfedge handle
tmpHandle = typename Mesh::HalfedgeHandle((static_cast<double>(rand()) / RAND_MAX) * (mesh_.n_halfedges()-1) );
// if it is not deleted, we analyse it
if ( ! mesh_.status(tmpHandle).deleted() ) {
CollapseInfo ci(mesh_, tmpHandle);
// Check if legal we analyze the priority of this collapse operation
if (this->is_collapse_legal(ci)) {
#ifdef USE_OPENMP
#pragma omp critical(energyUpdate)
{
#endif
energy = this->collapse_priority(ci);
if (energy == ModBaseT<Mesh>::ILLEGAL_COLLAPSE){
if (lastCollapseIllegal) {
illegalCollapses++;
} else {
illegalCollapses = 1;
lastCollapseIllegal = true;
}
} else {
illegalCollapses = 0;
lastCollapseIllegal = false;
// Check if the current samples energy is better than any energy before
if ( energy < bestEnergy ) {
bestEnergy = energy;
bestHandle = tmpHandle;
}
}
#ifdef USE_OPENMP
}
#endif
} else {
continue;
}
}
}
// Found the best energy?
if ( bestEnergy != FLT_MAX ) {
// setup collapse info
CollapseInfo ci(mesh_, bestHandle);
// check topological correctness AGAIN !
if (!this->is_collapse_legal(ci))
continue;
// adjust complexity in advance (need boundary status)
// One vertex is killed by the collapse
--nv;
// If we are at a boundary, one face is lost,
// otherwise two
if (mesh_.is_boundary(ci.v0v1) || mesh_.is_boundary(ci.v1v0))
--nf;
else
nf -= 2;
// pre-processing
this->preprocess_collapse(ci);
// perform collapse
mesh_.collapse(bestHandle);
++n_collapses;
// store current collapses state
oldCollapses = n_collapses;
noCollapses = 0;
collapsesUnchanged = false;
// update triangle normals
typename Mesh::VertexFaceIter vf_it = mesh_.vf_iter(ci.v1);
for (; vf_it; ++vf_it)
if (!mesh_.status(vf_it).deleted())
mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));
// post-process collapse
this->postprocess_collapse(ci);
} else {
if (oldCollapses == n_collapses) {
if (collapsesUnchanged == false) {
noCollapses = 1;
collapsesUnchanged = true;
} else {
noCollapses++;
}
}
}
}
if (_factor < 1.0)
this->set_error_tolerance_factor(1.0);
// DON'T do garbage collection here! It's up to the application.
return n_collapses;
}
//============================================================================= //=============================================================================
}// END_NS_MC_DECIMATER }// END_NS_MC_DECIMATER
} // END_NS_OPENMESH } // END_NS_OPENMESH

View File

@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org * * www.openmesh.org *
* * * *
*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*
* This file is part of OpenMesh. * * This file is part of OpenMesh. *
* * * *
* OpenMesh is free software: you can redistribute it and/or modify * * OpenMesh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as * * it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of * * published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the * * the License, or (at your option) any later version with the *
@@ -30,10 +30,10 @@
* 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 (Fr, 04 Nov 2011) $ * * $Date: 2011-11-04 13:59:37 +0100 (Fr, 04 Nov 2011) $ *
* * * *
@@ -111,6 +111,12 @@ public:
*/ */
size_t decimate_to_faces( size_t _n_vertices=0, size_t _n_faces=0 ); size_t decimate_to_faces( size_t _n_vertices=0, size_t _n_faces=0 );
/**
* Decimate only with constraints, while _factor gives the
* percentage of the constraints that should be used
*/
size_t decimate_constraints_only(float _factor);
size_t samples(){return randomSamples_;} size_t samples(){return randomSamples_;}
void set_samples(const size_t _value){randomSamples_ = _value;} void set_samples(const size_t _value){randomSamples_ = _value;}

View File

@@ -94,6 +94,7 @@ size_t MixedDecimaterT<Mesh>::decimate(const size_t _n_collapses, const float _m
r_collapses = McDecimaterT<Mesh>::decimate(n_collapses_mc); r_collapses = McDecimaterT<Mesh>::decimate(n_collapses_mc);
if (_mc_factor < 1.0) if (_mc_factor < 1.0)
r_collapses += DecimaterT<Mesh>::decimate(n_collapses_inc); r_collapses += DecimaterT<Mesh>::decimate(n_collapses_inc);
return r_collapses; return r_collapses;
} }
@@ -106,13 +107,18 @@ size_t MixedDecimaterT<Mesh>::decimate_to_faces(const size_t _n_vertices,const
std::size_t r_collapses = 0; std::size_t r_collapses = 0;
if (_mc_factor > 0.0) if (_mc_factor > 0.0)
{ {
size_t mesh_faces = this->mesh().n_faces(); bool constraintsOnly = (_n_vertices == 0) && (_n_faces == 1);
size_t mesh_vertices = this->mesh().n_vertices(); if (!constraintsOnly) {
//reduce the mesh only for _mc_factor size_t mesh_faces = this->mesh().n_faces();
size_t n_vertices_mc = static_cast<size_t>(mesh_vertices - _mc_factor * (mesh_vertices - _n_vertices)); size_t mesh_vertices = this->mesh().n_vertices();
size_t n_faces_mc = static_cast<size_t>(mesh_faces - _mc_factor * (mesh_faces - _n_faces)); //reduce the mesh only for _mc_factor
size_t n_vertices_mc = static_cast<size_t>(mesh_vertices - _mc_factor * (mesh_vertices - _n_vertices));
size_t n_faces_mc = static_cast<size_t>(mesh_faces - _mc_factor * (mesh_faces - _n_faces));
r_collapses = McDecimaterT<Mesh>::decimate_to_faces(n_vertices_mc, n_faces_mc); r_collapses = McDecimaterT<Mesh>::decimate_to_faces(n_vertices_mc, n_faces_mc);
} else {
r_collapses = McDecimaterT<Mesh>::decimate_constraints_only(_mc_factor);
}
} }
//update the mesh::n_vertices function, otherwise the next Decimater function will delete to much //update the mesh::n_vertices function, otherwise the next Decimater function will delete to much
@@ -122,6 +128,7 @@ size_t MixedDecimaterT<Mesh>::decimate_to_faces(const size_t _n_vertices,const
if (_mc_factor < 1.0) if (_mc_factor < 1.0)
r_collapses += DecimaterT<Mesh>::decimate_to_faces(_n_vertices,_n_faces); r_collapses += DecimaterT<Mesh>::decimate_to_faces(_n_vertices,_n_faces);
return r_collapses; return r_collapses;
} }

View File

@@ -173,6 +173,20 @@ float ModAspectRatioT<MeshT>::collapse_priority(const CollapseInfo& _ci) {
} }
} }
//-----------------------------------------------------------------------------
template<class MeshT>
void ModAspectRatioT<MeshT>::set_error_tolerance_factor(double _factor) {
if (_factor >= 0.0 && _factor <= 1.0) {
// the smaller the factor, the larger min_aspect_ gets
// thus creating a stricter constraint
// division by (2.0 - error_tolerance_factor_) is for normalization
double min_aspect = min_aspect_ * (2.0 - _factor) / (2.0 - this->error_tolerance_factor_);
set_aspect_ratio(1.0/min_aspect);
this->error_tolerance_factor_ = _factor;
}
}
//============================================================================= //=============================================================================
} }
} }

View File

@@ -118,6 +118,9 @@ class ModAspectRatioT: public ModBaseT<MeshT> {
/// update aspect ratio of one-ring /// update aspect ratio of one-ring
void preprocess_collapse(const CollapseInfo& _ci); void preprocess_collapse(const CollapseInfo& _ci);
/// set percentage of aspect ratio
void set_error_tolerance_factor(double _factor);
private: private:
/** \brief return aspect ratio (length/height) of triangle /** \brief return aspect ratio (length/height) of triangle

View File

@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org * * www.openmesh.org *
* * * *
*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*
* This file is part of OpenMesh. * * This file is part of OpenMesh. *
* * * *
* OpenMesh is free software: you can redistribute it and/or modify * * OpenMesh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as * * it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of * * published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the * * the License, or (at your option) any later version with the *
@@ -30,10 +30,10 @@
* 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$ *
* * * *
@@ -88,11 +88,11 @@ public:
public: public:
/// Default constructor /// Default constructor
ModHandleT() : mod_(NULL) {} ModHandleT() : mod_(NULL) {}
/// Destructor /// Destructor
~ModHandleT() { /* don't delete mod_, since handle is not owner! */ } ~ModHandleT() { /* don't delete mod_, since handle is not owner! */ }
/// Check handle status /// Check handle status
/// \return \c true, if handle is valid, else \c false. /// \return \c true, if handle is valid, else \c false.
bool is_valid() const { return mod_ != NULL; } bool is_valid() const { return mod_ != NULL; }
@@ -132,13 +132,13 @@ private:
/** Convenience macro, to be used in derived modules /** Convenience macro, to be used in derived modules
* The macro defines the types * The macro defines the types
* - \c Handle, type of the module's handle. * - \c Handle, type of the module's handle.
* - \c Base, type of ModBaseT<>. * - \c Base, type of ModBaseT<>.
* - \c Mesh, type of the associated mesh passed by the decimater type. * - \c Mesh, type of the associated mesh passed by the decimater type.
* - \c CollapseInfo, to your convenience * - \c CollapseInfo, to your convenience
* and uses DECIMATER_MODNAME() to define the name of the module. * and uses DECIMATER_MODNAME() to define the name of the module.
* *
* \param Classname The name of the derived class. * \param Classname The name of the derived class.
* \param MeshT Pass here the mesh type, which is the * \param MeshT Pass here the mesh type, which is the
* template parameter passed to ModBaseT. * template parameter passed to ModBaseT.
@@ -160,7 +160,7 @@ private:
/** Base class for all decimation modules. /** Base class for all decimation modules.
Each module has to implement this interface. Each module has to implement this interface.
To build your own module you have to To build your own module you have to
-# derive from this class. -# derive from this class.
-# create the basic settings with DECIMATING_MODULE(). -# create the basic settings with DECIMATING_MODULE().
-# override collapse_priority(), if necessary. -# override collapse_priority(), if necessary.
@@ -199,20 +199,20 @@ public:
}; };
protected: protected:
/// Default constructor /// Default constructor
/// \see \ref decimater_docu /// \see \ref decimater_docu
ModBaseT(MeshT& _mesh, bool _is_binary) ModBaseT(MeshT& _mesh, bool _is_binary)
: mesh_(_mesh), is_binary_(_is_binary) {} : error_tolerance_factor_(1.0), mesh_(_mesh), is_binary_(_is_binary) {}
public: public:
/// Virtual desctructor /// Virtual desctructor
virtual ~ModBaseT() { } virtual ~ModBaseT() { }
/// Set module's name (using DECIMATER_MODNAME macro) /// Set module's name (using DECIMATER_MODNAME macro)
DECIMATER_MODNAME(ModBase); DECIMATER_MODNAME(ModBase);
/// Returns true if criteria returns a binary value. /// Returns true if criteria returns a binary value.
bool is_binary(void) const { return is_binary_; } bool is_binary(void) const { return is_binary_; }
@@ -222,11 +222,11 @@ public:
public: // common interface public: // common interface
/// Initialize module-internal stuff /// Initialize module-internal stuff
virtual void initialize() { } virtual void initialize() { }
/** Return collapse priority. /** Return collapse priority.
* *
* In the binary mode collapse_priority() checks a constraint and * In the binary mode collapse_priority() checks a constraint and
* returns LEGAL_COLLAPSE or ILLEGAL_COLLAPSE. * returns LEGAL_COLLAPSE or ILLEGAL_COLLAPSE.
@@ -237,7 +237,7 @@ public: // common interface
* constraint is violated, collapse_priority() must return * constraint is violated, collapse_priority() must return
* ILLEGAL_COLLAPSE. * ILLEGAL_COLLAPSE.
* *
* \return Collapse priority in the range [0,inf), * \return Collapse priority in the range [0,inf),
* \c LEGAL_COLLAPSE or \c ILLEGAL_COLLAPSE. * \c LEGAL_COLLAPSE or \c ILLEGAL_COLLAPSE.
*/ */
virtual float collapse_priority(const CollapseInfoT<MeshT>& /* _ci */) virtual float collapse_priority(const CollapseInfoT<MeshT>& /* _ci */)
@@ -250,11 +250,23 @@ public: // common interface
{} {}
/** After _from_vh has been collapsed into _to_vh, this method /** After _from_vh has been collapsed into _to_vh, this method
will be called. will be called.
*/ */
virtual void postprocess_collapse(const CollapseInfoT<MeshT>& /* _ci */) virtual void postprocess_collapse(const CollapseInfoT<MeshT>& /* _ci */)
{} {}
/**
* This provides a function that allows the setting of a percentage
* of the original contraint.
*
* Note that the module might need to be re-initialized again after
* setting the percentage
* @param factor_ has to be in the closed interval between 0.0 and 1.0
*/
virtual void set_error_tolerance_factor(double _factor) {
if (_factor >= 0.0 && _factor <= 1.0)
error_tolerance_factor_ = _factor;
}
protected: protected:
@@ -262,6 +274,9 @@ protected:
/// Access the mesh associated with the decimater. /// Access the mesh associated with the decimater.
MeshT& mesh() { return mesh_; } MeshT& mesh() { return mesh_; }
// current percentage of the original constraint
double error_tolerance_factor_;
private: private:
// hide copy constructor & assignemnt // hide copy constructor & assignemnt

View File

@@ -76,6 +76,20 @@ float ModEdgeLengthT<MeshT>::collapse_priority(const CollapseInfo& _ci) {
return ( (sqr_length <= sqr_edge_length_) ? sqr_length : float(Base::ILLEGAL_COLLAPSE)); return ( (sqr_length <= sqr_edge_length_) ? sqr_length : float(Base::ILLEGAL_COLLAPSE));
} }
//-----------------------------------------------------------------------------
template<class MeshT>
void ModEdgeLengthT<MeshT>::set_error_tolerance_factor(double _factor) {
if (_factor >= 0.0 && _factor <= 1.0) {
// the smaller the factor, the smaller edge_length_ gets
// thus creating a stricter constraint
// division by error_tolerance_factor_ is for normalization
float edge_length = edge_length_ * _factor / this->error_tolerance_factor_;
set_edge_length(edge_length);
this->error_tolerance_factor_ = _factor;
}
}
//============================================================================= //=============================================================================
} }
} }

View File

@@ -99,6 +99,9 @@ class ModEdgeLengthT: public ModBaseT<MeshT> {
*/ */
float collapse_priority(const CollapseInfo& _ci); float collapse_priority(const CollapseInfo& _ci);
/// set the percentage of edge length
void set_error_tolerance_factor(double _factor);
private: private:
Mesh& mesh_; Mesh& mesh_;

View File

@@ -269,9 +269,21 @@ collapse_priority(const CollapseInfo& _ci)
return ( ok ? Base::LEGAL_COLLAPSE : Base::ILLEGAL_COLLAPSE ); return ( ok ? Base::LEGAL_COLLAPSE : Base::ILLEGAL_COLLAPSE );
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template<class MeshT>
void ModHausdorffT<MeshT>::set_error_tolerance_factor(double _factor) {
if (_factor >= 0.0 && _factor <= 1.0) {
// the smaller the factor, the smaller tolerance gets
// thus creating a stricter constraint
// division by error_tolerance_factor_ is for normalization
Scalar tolerance = tolerance_ * _factor / this->error_tolerance_factor_;
set_tolerance(tolerance);
this->error_tolerance_factor_ = _factor;
}
}
//-----------------------------------------------------------------------------
template <class MeshT> template <class MeshT>
void void
@@ -380,8 +392,11 @@ compute_sqr_error(FaceHandle _fh, const Point& _p) const
#pragma omp parallel for private(e) shared(emax) #pragma omp parallel for private(e) shared(emax)
for (int i = 0; i < pointsCount; ++i) { for (int i = 0; i < pointsCount; ++i) {
e = distPointTriangleSquared(points[i], p0, p1, p2, dummy); e = distPointTriangleSquared(points[i], p0, p1, p2, dummy);
#pragma omp critical(emaxUpdate)
{
if (e > emax) if (e > emax)
emax = e; emax = e;
}
} }
#else #else
for (; p_it!=p_end; ++p_it) { for (; p_it!=p_end; ++p_it) {

View File

@@ -124,6 +124,9 @@ class ModHausdorffT: public ModBaseT<MeshT> {
/// re-distribute points /// re-distribute points
virtual void postprocess_collapse(const CollapseInfo& _ci); virtual void postprocess_collapse(const CollapseInfo& _ci);
/// set the percentage of tolerance
void set_error_tolerance_factor(double _factor);
private: private:
/// squared distance from point _p to triangle (_v0, _v1, _v2) /// squared distance from point _p to triangle (_v0, _v1, _v2)

View File

@@ -87,7 +87,7 @@ template <class MeshT>
class ModNormalDeviationT : public ModBaseT< MeshT > class ModNormalDeviationT : public ModBaseT< MeshT >
{ {
public: public:
DECIMATING_MODULE( ModNormalDeviationT, MeshT, NormalDeviation ); DECIMATING_MODULE( ModNormalDeviationT, MeshT, NormalDeviation );
typedef typename Mesh::Scalar Scalar; typedef typename Mesh::Scalar Scalar;
@@ -191,6 +191,18 @@ public:
return (max_angle < 0.5 * normal_deviation_ ? max_angle : float( Base::ILLEGAL_COLLAPSE )); return (max_angle < 0.5 * normal_deviation_ ? max_angle : float( Base::ILLEGAL_COLLAPSE ));
} }
/// set the percentage of normal deviation
void set_error_tolerance_factor(double _factor) {
if (_factor >= 0.0 && _factor <= 1.0) {
// the smaller the factor, the smaller normal_deviation_ gets
// thus creating a stricter constraint
// division by error_tolerance_factor_ is for normalization
Scalar normal_deviation = (normal_deviation_ * 180.0/M_PI) * _factor / this->error_tolerance_factor_;
set_normal_deviation(normal_deviation);
this->error_tolerance_factor_ = _factor;
}
}
void postprocess_collapse(const CollapseInfo& _ci) { void postprocess_collapse(const CollapseInfo& _ci) {
// account for changed normals // account for changed normals

View File

@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org * * www.openmesh.org *
* * * *
*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*
* This file is part of OpenMesh. * * This file is part of OpenMesh. *
* * * *
* OpenMesh is free software: you can redistribute it and/or modify * * OpenMesh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as * * it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of * * published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the * * the License, or (at your option) any later version with the *
@@ -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 ModNormalFlippingT.hh /** \file ModNormalFlippingT.hh
*/ */
//============================================================================= //=============================================================================
@@ -67,44 +67,44 @@ namespace Decimater { // BEGIN_NS_DECIMATER
//== CLASS DEFINITION ========================================================= //== CLASS DEFINITION =========================================================
/** Decimating module to avoid flipping of faces. /** Decimating module to avoid flipping of faces.
* *
* 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 original 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.
*/ */
template <typename MeshT> template <typename MeshT>
class ModNormalFlippingT : public ModBaseT< MeshT > class ModNormalFlippingT : public ModBaseT< MeshT >
{ {
public: public:
DECIMATING_MODULE( ModNormalFlippingT, MeshT, NormalFlipping ); DECIMATING_MODULE( ModNormalFlippingT, MeshT, NormalFlipping );
public: public:
/// Constructor /// Constructor
ModNormalFlippingT( MeshT &_mesh) : Base(_mesh, true) ModNormalFlippingT( MeshT &_mesh) : Base(_mesh, true)
{ {
set_max_normal_deviation( 90.0f ); set_max_normal_deviation( 90.0f );
} }
~ModNormalFlippingT()
~ModNormalFlippingT()
{ } { }
public: public:
/** Compute collapse priority due to angular deviation of face normals /** Compute collapse priority due to angular deviation of face normals
* before and after a collapse. * before and after a collapse.
* *
* -# 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 cosine of the angle between the * -# Prevent the collapse, if the cosine of the angle between the
* original and 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
* *
@@ -114,13 +114,13 @@ public:
{ {
// simulate collapse // simulate collapse
Base::mesh().set_point(_ci.v0, _ci.p1); Base::mesh().set_point(_ci.v0, _ci.p1);
// check for flipping normals // check for flipping normals
typename Mesh::ConstVertexFaceIter vf_it(Base::mesh(), _ci.v0); typename Mesh::ConstVertexFaceIter vf_it(Base::mesh(), _ci.v0);
typename Mesh::FaceHandle fh; typename Mesh::FaceHandle fh;
typename Mesh::Scalar c(1.0); typename Mesh::Scalar c(1.0);
for (; vf_it; ++vf_it) for (; 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)
@@ -129,40 +129,51 @@ public:
typename Mesh::Normal n2 = Base::mesh().calc_face_normal(fh); typename Mesh::Normal n2 = Base::mesh().calc_face_normal(fh);
c = dot(n1, n2); c = dot(n1, n2);
if (c < min_cos_) if (c < min_cos_)
break; break;
} }
} }
// undo simulation changes // undo simulation changes
Base::mesh().set_point(_ci.v0, _ci.p0); Base::mesh().set_point(_ci.v0, _ci.p0);
return float( (c < min_cos_) ? Base::ILLEGAL_COLLAPSE : Base::LEGAL_COLLAPSE ); return float( (c < min_cos_) ? Base::ILLEGAL_COLLAPSE : Base::LEGAL_COLLAPSE );
} }
/// set the percentage of maximum normal deviation
void set_error_tolerance_factor(double _factor) {
if (_factor >= 0.0 && _factor <= 1.0) {
// the smaller the factor, the smaller max_deviation_ gets
// thus creating a stricter constraint
// division by error_tolerance_factor_ is for normalization
float max_normal_deviation = (max_deviation_ * 180.0/M_PI) * _factor / this->error_tolerance_factor_;
set_max_normal_deviation(max_normal_deviation);
this->error_tolerance_factor_ = _factor;
}
}
public: 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; }
/** 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
* normal in degrees. * normal in degrees.
*/ */
void set_max_normal_deviation(float _f) { void set_max_normal_deviation(float _f) {
max_deviation_ = _f / 180.0 * M_PI; max_deviation_ = _f / 180.0 * M_PI;
min_cos_ = cos(max_deviation_); min_cos_ = cos(max_deviation_);
} }
private: private:
// hide this method // hide this method
void set_binary(bool _b) {} void set_binary(bool _b) {}
private: private:
// maximum normal deviation // maximum normal deviation

View File

@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org * * www.openmesh.org *
* * * *
*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*
* This file is part of OpenMesh. * * This file is part of OpenMesh. *
* * * *
* OpenMesh is free software: you can redistribute it and/or modify * * OpenMesh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as * * it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of * * published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the * * the License, or (at your option) any later version with the *
@@ -30,10 +30,10 @@
* 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$ *
* * * *
@@ -129,6 +129,23 @@ initialize()
} }
} }
//-----------------------------------------------------------------------------
template<class MeshT>
void ModQuadricT<MeshT>::set_error_tolerance_factor(double _factor) {
if (this->is_binary()) {
if (_factor >= 0.0 && _factor <= 1.0) {
// the smaller the factor, the smaller max_err_ gets
// thus creating a stricter constraint
// division by error_tolerance_factor_ is for normalization
double max_err = max_err_ * _factor / this->error_tolerance_factor_;
set_max_err(max_err);
this->error_tolerance_factor_ = _factor;
initialize();
}
}
}
//============================================================================= //=============================================================================
} // END_NS_DECIMATER } // END_NS_DECIMATER

View File

@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org * * www.openmesh.org *
* * * *
*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*
* This file is part of OpenMesh. * * This file is part of OpenMesh. *
* * * *
* OpenMesh is free software: you can redistribute it and/or modify * * OpenMesh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as * * it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of * * published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the * * the License, or (at your option) any later version with the *
@@ -30,10 +30,10 @@
* 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$ *
* * * *
@@ -138,6 +138,9 @@ public: // inherited
Base::mesh().property(quadrics_, _ci.v0); Base::mesh().property(quadrics_, _ci.v0);
} }
/// set the percentage of maximum quadric error
void set_error_tolerance_factor(double _factor);
public: // specific methods public: // specific methods

View File

@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org * * www.openmesh.org *
* * * *
*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*
* This file is part of OpenMesh. * * This file is part of OpenMesh. *
* * * *
* OpenMesh is free software: you can redistribute it and/or modify * * OpenMesh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as * * it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of * * published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the * * the License, or (at your option) any later version with the *
@@ -30,10 +30,10 @@
* 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$ *
* * * *
@@ -96,7 +96,7 @@ class ModRoundnessT : public ModBaseT<MeshT>
/// Constructor /// Constructor
ModRoundnessT( MeshT &_dec ) : ModRoundnessT( MeshT &_dec ) :
Base(_dec, false), Base(_dec, false),
min_r_(-1.0) min_r_(-1.0)
{ } { }
@@ -109,14 +109,14 @@ class ModRoundnessT : public ModBaseT<MeshT>
* *
* The roundness is computed by dividing the radius of the * The roundness is computed by dividing the radius of the
* circumference by the length of the shortest edge. The result is * circumference by the length of the shortest edge. The result is
* normalized. * normalized.
* *
* \return [0:1] or ILLEGAL_COLLAPSE in non-binary mode * \return [0:1] or ILLEGAL_COLLAPSE in non-binary mode
* \return LEGAL_COLLAPSE or ILLEGAL_COLLAPSE in binary mode * \return LEGAL_COLLAPSE or ILLEGAL_COLLAPSE in binary mode
* \see set_min_roundness() * \see set_min_roundness()
*/ */
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);
@@ -126,11 +126,11 @@ class ModRoundnessT : public ModBaseT<MeshT>
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)));
fhC = Base::mesh().face_handle( voh_it.handle() ); fhC = Base::mesh().face_handle( voh_it.handle() );
for (++voh_it; voh_it; ++voh_it) for (++voh_it; voh_it; ++voh_it)
{ {
B = C; B = C;
fhB = fhC; fhB = fhC;
@@ -153,7 +153,7 @@ class ModRoundnessT : public ModBaseT<MeshT>
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() );
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;
@@ -171,6 +171,19 @@ class ModRoundnessT : public ModBaseT<MeshT>
return (float) priority; return (float) priority;
} }
/// set the percentage of minimum roundness
void set_error_tolerance_factor(double _factor) {
if (this->is_binary()) {
if (_factor >= 0.0 && _factor <= 1.0) {
// the smaller the factor, the smaller min_r_ gets
// thus creating a stricter constraint
// division by error_tolerance_factor_ is for normalization
value_type min_roundness = min_r_ * _factor / this->error_tolerance_factor_;
set_min_roundness(min_roundness);
this->error_tolerance_factor_ = _factor;
}
}
}
public: // specific methods public: // specific methods
@@ -197,12 +210,12 @@ public: // specific methods
double r2 = roundness(A,B,C); double r2 = roundness(A,B,C);
set_min_roundness( value_type(std::min(r1,r2)), true ); set_min_roundness( value_type(std::min(r1,r2)), true );
} }
/** Set a minimum roundness value. /** Set a minimum roundness value.
* \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 constraint does not apply * returns a float value if the constraint does not apply
* and ILLEGAL_COLLAPSE else. * and ILLEGAL_COLLAPSE else.
@@ -230,11 +243,11 @@ public: // specific methods
// //
// then define // then define
// //
// radius of circumference // radius of circumference
// R := ----------------------- // R := -----------------------
// length of shortest edge // length of shortest edge
// //
// ||a|| * ||b|| * ||c|| // ||a|| * ||b|| * ||c||
// --------------------- // ---------------------
// 4 * Area ||a|| * ||b|| * ||c|| // 4 * Area ||a|| * ||b|| * ||c||
// = ----------------------- = ----------------------------------- // = ----------------------- = -----------------------------------
@@ -254,7 +267,7 @@ public: // specific methods
// //
// At angle 60<36> R has it's minimum for all edge lengths = sqrt(1/3) // At angle 60<36> R has it's minimum for all edge lengths = sqrt(1/3)
// //
// Define normalized roundness // Define normalized roundness
// //
// nR := sqrt(1/3) / R // nR := sqrt(1/3) / R
// //
@@ -266,7 +279,7 @@ public: // specific methods
{ {
const value_type epsilon = value_type(1e-15); const value_type epsilon = value_type(1e-15);
static const value_type sqrt43 = value_type(sqrt(4.0/3.0)); // 60<36>,a=b=c, **) static const value_type sqrt43 = value_type(sqrt(4.0/3.0)); // 60<36>,a=b=c, **)
Vec3f vecAC = C-A; Vec3f vecAC = C-A;
Vec3f vecAB = B-A; Vec3f vecAB = B-A;
@@ -281,7 +294,7 @@ public: // specific methods
return 0.0; return 0.0;
double nom = AA * std::min( std::min(aa,bb),cc ); double nom = AA * std::min( std::min(aa,bb),cc );
double denom = aa * bb * cc; double denom = aa * bb * cc;
double nR = sqrt43 * sqrt(nom/denom); double nR = sqrt43 * sqrt(nom/denom);
return nR; return nR;