- 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:
@@ -207,6 +207,19 @@ void BaseDecimaterT<Mesh>::preprocess_collapse(CollapseInfo& _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);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -199,6 +199,16 @@ protected: //---------------------------------------------------- private method
|
||||
/// Post-process a collapse
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -214,6 +214,7 @@ size_t DecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
||||
// delete heap
|
||||
heap_.reset();
|
||||
|
||||
|
||||
// DON'T do garbage collection here! It's up to the application.
|
||||
return n_collapses;
|
||||
}
|
||||
@@ -307,6 +308,7 @@ size_t DecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
||||
// delete heap
|
||||
heap_.reset();
|
||||
|
||||
|
||||
// DON'T do garbage collection here! It's up to the application.
|
||||
return n_collapses;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,9 @@
|
||||
#else
|
||||
# include <cfloat>
|
||||
#endif
|
||||
#ifdef USE_OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
//== NAMESPACE ===============================================================
|
||||
|
||||
@@ -103,17 +106,33 @@ size_t McDecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
||||
|
||||
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) {
|
||||
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
|
||||
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
|
||||
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 ( ! 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
|
||||
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);
|
||||
|
||||
if (energy != ModBaseT<Mesh>::ILLEGAL_COLLAPSE) {
|
||||
// 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;
|
||||
}
|
||||
@@ -153,6 +181,11 @@ size_t McDecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
||||
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)
|
||||
@@ -162,6 +195,15 @@ size_t McDecimaterT<Mesh>::decimate(size_t _n_collapses) {
|
||||
// post-process collapse
|
||||
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())
|
||||
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 nf = mesh_.n_faces();
|
||||
unsigned int n_collapses(0);
|
||||
|
||||
|
||||
// check if no vertex or face contraints were set
|
||||
bool contraintsOnly = (_nv == 0) && (_nf == 1);
|
||||
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;
|
||||
|
||||
// check if no legal collapses were found three times in a row
|
||||
// for the sampled halfedges
|
||||
bool foundNoLegalCollapsesThrice = false;
|
||||
|
||||
// store the last two amount of legal collapses found
|
||||
int lastLegalCollapses = -1;
|
||||
int beforeLastLegalCollapses = -1;
|
||||
|
||||
while ( !foundNoLegalCollapsesThrice && (_nv < nv) && (_nf < nf) ) {
|
||||
while ( (_nv < nv) && (_nf < nf) ) {
|
||||
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
|
||||
typename Mesh::HalfedgeHandle bestHandle(-1);
|
||||
typename Mesh::HalfedgeHandle tmpHandle(-1);
|
||||
double bestEnergy = FLT_MAX;
|
||||
double energy = FLT_MAX;
|
||||
|
||||
|
||||
// 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) {
|
||||
|
||||
// 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 ( ! 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
|
||||
if (this->is_collapse_legal(ci)) {
|
||||
++legalCollapses;
|
||||
double energy = this->collapse_priority(ci);
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp critical(energyUpdate)
|
||||
{
|
||||
#endif
|
||||
energy = this->collapse_priority(ci);
|
||||
|
||||
if (energy != ModBaseT<Mesh>::ILLEGAL_COLLAPSE) {
|
||||
// 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;
|
||||
}
|
||||
@@ -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?
|
||||
if ( bestEnergy != FLT_MAX ) {
|
||||
|
||||
@@ -267,6 +317,11 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
||||
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)
|
||||
@@ -276,6 +331,15 @@ size_t McDecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
|
||||
// post-process collapse
|
||||
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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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_OPENMESH
|
||||
|
||||
@@ -111,6 +111,12 @@ public:
|
||||
*/
|
||||
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_;}
|
||||
void set_samples(const size_t _value){randomSamples_ = _value;}
|
||||
|
||||
|
||||
@@ -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);
|
||||
if (_mc_factor < 1.0)
|
||||
r_collapses += DecimaterT<Mesh>::decimate(n_collapses_inc);
|
||||
|
||||
return r_collapses;
|
||||
|
||||
}
|
||||
@@ -106,6 +107,8 @@ size_t MixedDecimaterT<Mesh>::decimate_to_faces(const size_t _n_vertices,const
|
||||
std::size_t r_collapses = 0;
|
||||
if (_mc_factor > 0.0)
|
||||
{
|
||||
bool constraintsOnly = (_n_vertices == 0) && (_n_faces == 1);
|
||||
if (!constraintsOnly) {
|
||||
size_t mesh_faces = this->mesh().n_faces();
|
||||
size_t mesh_vertices = this->mesh().n_vertices();
|
||||
//reduce the mesh only for _mc_factor
|
||||
@@ -113,6 +116,9 @@ size_t MixedDecimaterT<Mesh>::decimate_to_faces(const size_t _n_vertices,const
|
||||
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);
|
||||
} 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
|
||||
@@ -122,6 +128,7 @@ size_t MixedDecimaterT<Mesh>::decimate_to_faces(const size_t _n_vertices,const
|
||||
if (_mc_factor < 1.0)
|
||||
r_collapses += DecimaterT<Mesh>::decimate_to_faces(_n_vertices,_n_faces);
|
||||
|
||||
|
||||
return r_collapses;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,9 @@ class ModAspectRatioT: public ModBaseT<MeshT> {
|
||||
/// update aspect ratio of one-ring
|
||||
void preprocess_collapse(const CollapseInfo& _ci);
|
||||
|
||||
/// set percentage of aspect ratio
|
||||
void set_error_tolerance_factor(double _factor);
|
||||
|
||||
private:
|
||||
|
||||
/** \brief return aspect ratio (length/height) of triangle
|
||||
|
||||
@@ -203,7 +203,7 @@ protected:
|
||||
/// Default constructor
|
||||
/// \see \ref decimater_docu
|
||||
ModBaseT(MeshT& _mesh, bool _is_binary)
|
||||
: mesh_(_mesh), is_binary_(_is_binary) {}
|
||||
: error_tolerance_factor_(1.0), mesh_(_mesh), is_binary_(_is_binary) {}
|
||||
|
||||
public:
|
||||
|
||||
@@ -255,6 +255,18 @@ public: // common interface
|
||||
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:
|
||||
@@ -262,6 +274,9 @@ protected:
|
||||
/// Access the mesh associated with the decimater.
|
||||
MeshT& mesh() { return mesh_; }
|
||||
|
||||
// current percentage of the original constraint
|
||||
double error_tolerance_factor_;
|
||||
|
||||
private:
|
||||
|
||||
// hide copy constructor & assignemnt
|
||||
|
||||
@@ -76,6 +76,20 @@ float ModEdgeLengthT<MeshT>::collapse_priority(const CollapseInfo& _ci) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,9 @@ class ModEdgeLengthT: public ModBaseT<MeshT> {
|
||||
*/
|
||||
float collapse_priority(const CollapseInfo& _ci);
|
||||
|
||||
/// set the percentage of edge length
|
||||
void set_error_tolerance_factor(double _factor);
|
||||
|
||||
private:
|
||||
|
||||
Mesh& mesh_;
|
||||
|
||||
@@ -269,9 +269,21 @@ collapse_priority(const CollapseInfo& _ci)
|
||||
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>
|
||||
void
|
||||
@@ -380,9 +392,12 @@ compute_sqr_error(FaceHandle _fh, const Point& _p) const
|
||||
#pragma omp parallel for private(e) shared(emax)
|
||||
for (int i = 0; i < pointsCount; ++i) {
|
||||
e = distPointTriangleSquared(points[i], p0, p1, p2, dummy);
|
||||
#pragma omp critical(emaxUpdate)
|
||||
{
|
||||
if (e > emax)
|
||||
emax = e;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (; p_it!=p_end; ++p_it) {
|
||||
e = distPointTriangleSquared(*p_it, p0, p1, p2, dummy);
|
||||
|
||||
@@ -124,6 +124,9 @@ class ModHausdorffT: public ModBaseT<MeshT> {
|
||||
/// re-distribute points
|
||||
virtual void postprocess_collapse(const CollapseInfo& _ci);
|
||||
|
||||
/// set the percentage of tolerance
|
||||
void set_error_tolerance_factor(double _factor);
|
||||
|
||||
private:
|
||||
|
||||
/// squared distance from point _p to triangle (_v0, _v1, _v2)
|
||||
|
||||
@@ -191,6 +191,18 @@ public:
|
||||
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) {
|
||||
// account for changed normals
|
||||
|
||||
@@ -141,6 +141,17 @@ public:
|
||||
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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -138,6 +138,9 @@ public: // inherited
|
||||
Base::mesh().property(quadrics_, _ci.v0);
|
||||
}
|
||||
|
||||
/// set the percentage of maximum quadric error
|
||||
void set_error_tolerance_factor(double _factor);
|
||||
|
||||
|
||||
|
||||
public: // specific methods
|
||||
|
||||
@@ -171,6 +171,19 @@ class ModRoundnessT : public ModBaseT<MeshT>
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user