Commit 48289493 authored by Isaak Lim's avatar Isaak Lim

- added the set_error_tolerance_factor function to ModBaseT and implemented it...

- 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
parent 33b72fb6
......@@ -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
......
......@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*
* 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 *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
......@@ -33,7 +33,7 @@
\*===========================================================================*/
/*===========================================================================*\
* *
* *
* $Revision$ *
* $Date$ *
* *
......@@ -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;
}
......
......@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*
* 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 *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
......@@ -30,10 +30,10 @@
* License along with OpenMesh. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
\*===========================================================================*/
/*===========================================================================*\
* *
* *
* $Revision: 448 $ *
* $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 );
/**
* 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,13 +107,18 @@ size_t MixedDecimaterT<Mesh>::decimate_to_faces(const size_t _n_vertices,const
std::size_t r_collapses = 0;
if (_mc_factor > 0.0)
{
size_t mesh_faces = this->mesh().n_faces();
size_t mesh_vertices = this->mesh().n_vertices();
//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);
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
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);
} 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
......
......@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*
* 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 *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
......@@ -30,10 +30,10 @@
* License along with OpenMesh. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
\*===========================================================================*/
/*===========================================================================*\
* *
* *
* $Revision$ *
* $Date$ *
* *
......@@ -88,11 +88,11 @@ public:
public:
/// Default constructor
ModHandleT() : mod_(NULL) {}
ModHandleT() : mod_(NULL) {}
/// Destructor
~ModHandleT() { /* don't delete mod_, since handle is not owner! */ }
/// Check handle status
/// \return \c true, if handle is valid, else \c false.
bool is_valid() const { return mod_ != NULL; }
......@@ -132,13 +132,13 @@ private:
/** 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 Base, type of ModBaseT<>.
* - \c Mesh, type of the associated mesh passed by the decimater type.
* - \c CollapseInfo, to your convenience
* and uses DECIMATER_MODNAME() to define the name of the module.
*
*
* \param Classname The name of the derived class.
* \param MeshT Pass here the mesh type, which is the
* template parameter passed to ModBaseT.
......@@ -160,7 +160,7 @@ private:
/** Base class for all decimation modules.
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.
-# create the basic settings with DECIMATING_MODULE().
-# override collapse_priority(), if necessary.
......@@ -199,20 +199,20 @@ public:
};
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:
/// Virtual desctructor
virtual ~ModBaseT() { }
virtual ~ModBaseT() { }
/// Set module's name (using DECIMATER_MODNAME macro)
DECIMATER_MODNAME(ModBase);
/// Returns true if criteria returns a binary value.
bool is_binary(void) const { return is_binary_; }
......@@ -222,11 +222,11 @@ public:
public: // common interface
/// Initialize module-internal stuff
virtual void initialize() { }
/** Return collapse priority.
/** Return collapse priority.
*
* In the binary mode collapse_priority() checks a constraint and
* returns LEGAL_COLLAPSE or ILLEGAL_COLLAPSE.
......@@ -237,7 +237,7 @@ public: // common interface
* constraint is violated, collapse_priority() must return
* 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.
*/
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
will be called.
will be called.
*/
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,8 +392,11 @@ 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) {
......
......@@ -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)
......
......@@ -87,7 +87,7 @@ template <class MeshT>
class ModNormalDeviationT : public ModBaseT< MeshT >
{
public:
DECIMATING_MODULE( ModNormalDeviationT, MeshT, NormalDeviation );
typedef typename Mesh::Scalar Scalar;
......@@ -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
......
......@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*
* 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 *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
......@@ -30,17 +30,17 @@
* License along with OpenMesh. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
\*===========================================================================*/
/*===========================================================================*\
* *
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
/** \file ModNormalFlippingT.hh
*/
//=============================================================================
......@@ -67,44 +67,44 @@ namespace Decimater { // BEGIN_NS_DECIMATER
//== CLASS DEFINITION =========================================================
/** Decimating module to avoid flipping of faces.
*
*
* This module can be used only as a binary module. The criterion
* of allowing/disallowing the collapse is the angular deviation between
* 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
* a given threshold.
*/
*/
template <typename MeshT>
class ModNormalFlippingT : public ModBaseT< MeshT >
{
{
public:
DECIMATING_MODULE( ModNormalFlippingT, MeshT, NormalFlipping );
public:
/// Constructor
ModNormalFlippingT( MeshT &_mesh) : Base(_mesh, true)
{
set_max_normal_deviation( 90.0f );
}
~ModNormalFlippingT()
~ModNormalFlippingT()
{ }
public:
/** Compute collapse priority due to angular deviation of face normals
* before and after a collapse.
*
* -# 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
* original and the new normal is below a given threshold.
*
*
* \param _ci The collapse description
* \return LEGAL_COLLAPSE or ILLEGAL_COLLAPSE
*
......@@ -114,13 +114,13 @@ public:
{
// simulate collapse
Base::mesh().set_point(_ci.v0, _ci.p1);
// check for flipping normals
typename Mesh::ConstVertexFaceIter vf_it(Base::mesh(), _ci.v0);
typename Mesh::FaceHandle fh;
typename Mesh::Scalar c(1.0);
for (; vf_it; ++vf_it)
for (; vf_it; ++vf_it)
{
fh = vf_it.handle();
if (fh != _ci.fl && fh != _ci.fr)
......@@ -129,40 +129,51 @@ public:
typename Mesh::Normal n2 = Base::mesh().calc_face_normal(fh);
c = dot(n1, n2);
if (c < min_cos_)
break;
}
}
// undo simulation changes
Base::mesh().set_point(_ci.v0, _ci.p0);
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:
/// get normal deviation
float max_normal_deviation() const { return max_deviation_ / M_PI * 180.0; }
/** Set normal deviation
*
*
* Set the maximum angular deviation of the orignal normal and the new
* normal in degrees.
*/
void set_max_normal_deviation(float _f) {
max_deviation_ = _f / 180.0 * M_PI;
void set_max_normal_deviation(float _f) {
max_deviation_ = _f / 180.0 * M_PI;
min_cos_ = cos(max_deviation_);
}
private:
// hide this method
void set_binary(bool _b) {}
private:
// maximum normal deviation
......
......@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*
* 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 *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
......@@ -30,10 +30,10 @@
* License along with OpenMesh. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
\*===========================================================================*/
/*===========================================================================*\
* *
* *
* $Revision$ *
* $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
......
......@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*
* 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 *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
......@@ -30,10 +30,10 @@
* License along with OpenMesh. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
\*===========================================================================*/
/*===========================================================================*\
* *
* *
* $Revision$ *
* $Date$ *
* *
......@@ -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
......
......@@ -4,10 +4,10 @@
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
*---------------------------------------------------------------------------*
* 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 *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
......@@ -30,10 +30,10 @@
* License along with OpenMesh. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
\*===========================================================================*/
/*===========================================================================*\
* *
* *
* $Revision$ *
* $Date$ *
* *
......@@ -96,7 +96,7 @@ class ModRoundnessT : public ModBaseT<MeshT>
/// Constructor
ModRoundnessT( MeshT &_dec ) :
Base(_dec, false),
Base(_dec, false),
min_r_(-1.0)
{ }
......@@ -109,14 +109,14 @@ class ModRoundnessT : public ModBaseT<MeshT>
*
* The roundness is computed by dividing the radius of the
* circumference by the length of the shortest edge. The result is
* normalized.
* normalized.
*