diff --git a/src/OpenMesh/Tools/Decimater/BaseDecimaterT.cc b/src/OpenMesh/Tools/Decimater/BaseDecimaterT.cc new file mode 100644 index 00000000..e33d4f71 --- /dev/null +++ b/src/OpenMesh/Tools/Decimater/BaseDecimaterT.cc @@ -0,0 +1,312 @@ +/*===========================================================================*\ + * * + * OpenMesh * + * 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 * + * 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 * + * following exceptions: * + * * + * If other files instantiate templates or use macros * + * or inline functions from this file, or you compile this file and * + * link it with other files to produce an executable, this file does * + * not by itself cause the resulting executable to be covered by the * + * GNU Lesser General Public License. This exception does not however * + * invalidate any other reasons why the executable file might be * + * covered by the GNU Lesser General Public License. * + * * + * OpenMesh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU LesserGeneral Public * + * License along with OpenMesh. If not, * + * see . * + * * + \*===========================================================================*/ + +/*===========================================================================*\ + * * + * $Revision$ * + * $Date$ * + * * + \*===========================================================================*/ + +/** \file DecimaterT.cc + */ + +//============================================================================= +// +// CLASS DecimaterT - IMPLEMENTATION +// +//============================================================================= +#define OPENMESH_BASE_DECIMATER_DECIMATERT_CC + +//== INCLUDES ================================================================= + +#include +#if defined(OM_CC_MIPS) +# include +#else +# include +#endif + +//== NAMESPACE =============================================================== + +namespace OpenMesh { +namespace Decimater { + +//== IMPLEMENTATION ========================================================== + +template +BaseDecimaterT::BaseDecimaterT(Mesh& _mesh) : + mesh_(_mesh), cmodule_(NULL), initialized_(false) { + // default properties + mesh_.request_vertex_status(); + mesh_.request_edge_status(); + mesh_.request_face_status(); + mesh_.request_face_normals(); +} + +//----------------------------------------------------------------------------- + +template +BaseDecimaterT::~BaseDecimaterT() { + // default properties + mesh_.release_vertex_status(); + mesh_.release_edge_status(); + mesh_.release_face_status(); + mesh_.release_face_normals(); + + // dispose of modules + { + set_uninitialized(); + typename ModuleList::iterator m_it, m_end = all_modules_.end(); + for (m_it = all_modules_.begin(); m_it != m_end; ++m_it) + delete *m_it; + all_modules_.clear(); + } +} + +//----------------------------------------------------------------------------- + +template +bool BaseDecimaterT::is_collapse_legal(const CollapseInfo& _ci) { + // std::clog << "McDecimaterT<>::is_collapse_legal()\n"; + + // locked ? deleted ? + if (mesh_.status(_ci.v0).locked() || mesh_.status(_ci.v0).deleted()) + return false; + + if (!mesh_.is_collapse_ok(_ci.v0v1)) + return false; + + if (_ci.vl.is_valid() && _ci.vr.is_valid() + && mesh_.find_halfedge(_ci.vl, _ci.vr).is_valid() + && mesh_.valence(_ci.vl) == 3 && mesh_.valence(_ci.vr) == 3) { + return false; + } + //--- feature test --- + + if (mesh_.status(_ci.v0).feature() + && !mesh_.status(mesh_.edge_handle(_ci.v0v1)).feature()) + return false; + + //--- test one ring intersection --- + + typename Mesh::VertexVertexIter vv_it; + + for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it) + mesh_.status(vv_it).set_tagged(false); + + for (vv_it = mesh_.vv_iter(_ci.v1); vv_it; ++vv_it) + mesh_.status(vv_it).set_tagged(true); + + for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it) + if (mesh_.status(vv_it).tagged() && vv_it.handle() != _ci.vl + && vv_it.handle() != _ci.vr) + return false; + + // if both are invalid OR equal -> fail + if (_ci.vl == _ci.vr) + return false; + + //--- test boundary cases --- + if (mesh_.is_boundary(_ci.v0)) { + if (!mesh_.is_boundary(_ci.v1)) { // don't collapse a boundary vertex to an inner one + return false; + } else { // edge between two boundary vertices has to be a boundary edge + if (!(mesh_.is_boundary(_ci.v0v1) || mesh_.is_boundary(_ci.v1v0))) + return false; + } + // only one one ring intersection + if (_ci.vl.is_valid() && _ci.vr.is_valid()) + return false; + } + + // v0vl and v1vl must not both be boundary edges + if (_ci.vl.is_valid() && mesh_.is_boundary(_ci.vlv1) + && mesh_.is_boundary(_ci.v0vl)) + return false; + + // v0vr and v1vr must not be both boundary edges + if (_ci.vr.is_valid() && mesh_.is_boundary(_ci.vrv0) + && mesh_.is_boundary(_ci.v1vr)) + return false; + + // there have to be at least 2 incident faces at v0 + if (mesh_.cw_rotated_halfedge_handle( + mesh_.cw_rotated_halfedge_handle(_ci.v0v1)) == _ci.v0v1) + return false; + + // collapse passed all tests -> ok + return true; +} + +//----------------------------------------------------------------------------- + +template +float BaseDecimaterT::collapse_priority(const CollapseInfo& _ci) { + typename ModuleList::iterator m_it, m_end = bmodules_.end(); + + for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) { + if ((*m_it)->collapse_priority(_ci) < 0.0) + return ModBaseT< Mesh >::ILLEGAL_COLLAPSE; + } + return cmodule_->collapse_priority(_ci); +} + +//----------------------------------------------------------------------------- + +template +void BaseDecimaterT::postprocess_collapse(CollapseInfo& _ci) { + typename ModuleList::iterator m_it, m_end = bmodules_.end(); + + for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) + (*m_it)->postprocess_collapse(_ci); + + cmodule_->postprocess_collapse(_ci); +} + +//----------------------------------------------------------------------------- + +template +void BaseDecimaterT::preprocess_collapse(CollapseInfo& _ci) { + typename ModuleList::iterator m_it, m_end = bmodules_.end(); + + for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) + (*m_it)->preprocess_collapse(_ci); + + cmodule_->preprocess_collapse(_ci); +} + + +//----------------------------------------------------------------------------- + +template +void BaseDecimaterT::info(std::ostream& _os) { + if (initialized_) { + _os << "initialized : yes" << std::endl; + _os << "binary modules: " << bmodules_.size() << std::endl; + for (ModuleListIterator m_it = bmodules_.begin(); m_it != bmodules_.end(); + ++m_it) { + _os << " " << (*m_it)->name() << std::endl; + } + _os << "priority module: " << cmodule_->name().c_str() << std::endl; + } else { + _os << "initialized : no" << std::endl; + _os << "available modules: " << all_modules_.size() << std::endl; + for (ModuleListIterator m_it = all_modules_.begin(); + m_it != all_modules_.end(); ++m_it) { + _os << " " << (*m_it)->name() << " : "; + if ((*m_it)->is_binary()) { + _os << "binary"; + if ((*m_it)->name() == "Quadric") { + _os << " and priority (special treatment)"; + } + } else { + _os << "priority"; + } + _os << std::endl; + } + } +} + +//----------------------------------------------------------------------------- + +template +bool BaseDecimaterT::initialize() { + if (initialized_) { + return true; + } + + // FIXME: quadric module shouldn't be treated specially. + // Q: Why? + // A: It isn't generic and breaks encapsulation. Also, using string + // name comparison is not reliable, since you can't guarantee that + // no one else will name their custom module "Quadric". + // Q: What should be done instead? + // A: ModBaseT API should support modules that can be both binary + // and priority, or BETTER YET, let the DecimaterT API specify the + // priority module explicitly. + + // find the priority module: either the only non-binary module in the list, or "Quadric" + Module *quadric = NULL; + Module *pmodule = NULL; + for (ModuleListIterator m_it = all_modules_.begin(), m_end = + all_modules_.end(); m_it != m_end; ++m_it) { + if ((*m_it)->name() == "Quadric") + quadric = *m_it; + + if (!(*m_it)->is_binary()) { + if (pmodule) { + // only one priority module allowed! + set_uninitialized(); + return false; + } + pmodule = *m_it; + } + } + + // Quadric is used as default priority module (even if it is set to be binary) + if (!pmodule && quadric) { + pmodule = quadric; + } + + if (!pmodule) { + // At least one priority module required + set_uninitialized(); + return false; + } + + // set pmodule as the current priority module + cmodule_ = pmodule; + + for (ModuleListIterator m_it = all_modules_.begin(), m_end = + all_modules_.end(); m_it != m_end; ++m_it) { + // every module gets initialized + (*m_it)->initialize(); + + if (*m_it != pmodule) { + // all other modules are binary, and go into bmodules_ list + bmodules_.push_back(*m_it); + } + } + + return initialized_ = true; +} + + + +//============================================================================= +}// END_NS_DECIMATER +} // END_NS_OPENMESH +//============================================================================= + diff --git a/src/OpenMesh/Tools/Decimater/BaseDecimaterT.hh b/src/OpenMesh/Tools/Decimater/BaseDecimaterT.hh new file mode 100644 index 00000000..66cdda02 --- /dev/null +++ b/src/OpenMesh/Tools/Decimater/BaseDecimaterT.hh @@ -0,0 +1,230 @@ +/*===========================================================================*\ + * * + * OpenMesh * + * 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 * + * 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 * + * following exceptions: * + * * + * If other files instantiate templates or use macros * + * or inline functions from this file, or you compile this file and * + * link it with other files to produce an executable, this file does * + * not by itself cause the resulting executable to be covered by the * + * GNU Lesser General Public License. This exception does not however * + * invalidate any other reasons why the executable file might be * + * covered by the GNU Lesser General Public License. * + * * + * OpenMesh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU LesserGeneral Public * + * License along with OpenMesh. If not, * + * see . * + * * +\*===========================================================================*/ + +/*===========================================================================*\ + * * + * $Revision$ * + * $Date$ * + * * +\*===========================================================================*/ + +/** \file BaseDecimaterT.hh + */ + +//============================================================================= +// +// CLASS McDecimaterT +// +//============================================================================= + +#ifndef OPENMESH_BASE_DECIMATER_DECIMATERT_HH +#define OPENMESH_BASE_DECIMATER_DECIMATERT_HH + + +//== INCLUDES ================================================================= + +#include + +#include +#include +#include + + + +//== NAMESPACE ================================================================ + +namespace OpenMesh { +namespace Decimater { + + +//== CLASS DEFINITION ========================================================= + + +/** base class decimater framework + \see BaseDecimaterT, \ref decimater_docu +*/ +class BaseDecimaterModule +{ +}; + +template < typename MeshT > +class BaseDecimaterT : private Utils::Noncopyable +{ +public: //-------------------------------------------------------- public types + + typedef BaseDecimaterT< MeshT > Self; + typedef MeshT Mesh; + typedef CollapseInfoT CollapseInfo; + typedef ModBaseT Module; + typedef std::vector< Module* > ModuleList; + typedef typename ModuleList::iterator ModuleListIterator; + +public: //------------------------------------------------------ public methods + BaseDecimaterT(Mesh& _mesh); + ~BaseDecimaterT(); + + /** Initialize decimater and decimating modules. + + Return values: + true ok + false No ore more than one non-binary module exist. In that case + the decimater is uninitialized! + */ + bool initialize(); + + + /// Returns whether decimater has been successfully initialized. + bool is_initialized() const { return initialized_; } + + + /// Print information about modules to _os + void info( std::ostream& _os ); + +public: //--------------------------------------------------- module management + + /// access mesh. used in modules. + Mesh& mesh() { return mesh_; } + + /// add module to decimater + template < typename _Module > + bool add( ModHandleT<_Module>& _mh ) + { + if (_mh.is_valid()) + return false; + + _mh.init( new _Module(mesh()) ); + all_modules_.push_back( _mh.module() ); + + set_uninitialized(); + + return true; + } + + + /// remove module + template < typename _Module > + bool remove( ModHandleT<_Module>& _mh ) + { + if (!_mh.is_valid()) + return false; + + typename ModuleList::iterator it = std::find(all_modules_.begin(), + all_modules_.end(), + _mh.module() ); + + if ( it == all_modules_.end() ) // module not found + return false; + + delete *it; + all_modules_.erase( it ); // finally remove from list + _mh.clear(); + + set_uninitialized(); + return true; + } + + + /// get module referenced by handle _mh + template < typename Module > + Module& module( ModHandleT& _mh ) + { + assert( _mh.is_valid() ); + return *_mh.module(); + } + + +protected: + + // Reset the initialized flag, and clear the bmodules_ and cmodule_ + void set_uninitialized() { + initialized_ = false; + cmodule_ = 0; + bmodules_.clear(); + } + + void update_modules(CollapseInfo& _ci) + { + typename ModuleList::iterator m_it, m_end = bmodules_.end(); + for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) + (*m_it)->postprocess_collapse(_ci); + cmodule_->postprocess_collapse(_ci); + } + + +protected: //---------------------------------------------------- private methods + + /// Is an edge collapse legal? Performs topological test only. + /// The method evaluates the status bit Locked, Deleted, and Feature. + /// \attention The method temporarily sets the bit Tagged. After usage + /// the bit will be disabled! + bool is_collapse_legal(const CollapseInfo& _ci); + + /// Calculate priority of an halfedge collapse (using the modules) + float collapse_priority(const CollapseInfo& _ci); + + /// Pre-process a collapse + void preprocess_collapse(CollapseInfo& _ci); + + /// Post-process a collapse + void postprocess_collapse(CollapseInfo& _ci); + +private: //------------------------------------------------------- private data + + + // reference to mesh + Mesh& mesh_; + + // list of binary modules + ModuleList bmodules_; + + // the current priority module + Module* cmodule_; + + // list of all allocated modules (including cmodule_ and all of bmodules_) + ModuleList all_modules_; + + bool initialized_; +}; + +//============================================================================= +} // END_NS_DECIMATER +} // END_NS_OPENMESH +//============================================================================= +#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_BASE_DECIMATER_DECIMATERT_CC) +#define OPENMESH_BASE_DECIMATER_TEMPLATES +#include "BaseDecimaterT.cc" +#endif +//============================================================================= +#endif // OPENMESH_BASE_DECIMATER_DECIMATERT_HH defined +//============================================================================= diff --git a/src/OpenMesh/Tools/Decimater/DecimaterT.cc b/src/OpenMesh/Tools/Decimater/DecimaterT.cc index 6401385c..e4fefca7 100644 --- a/src/OpenMesh/Tools/Decimater/DecimaterT.cc +++ b/src/OpenMesh/Tools/Decimater/DecimaterT.cc @@ -69,12 +69,8 @@ namespace Decimater { template DecimaterT::DecimaterT(Mesh& _mesh) : - mesh_(_mesh), heap_(NULL), cmodule_(NULL), initialized_(false) { - // default properties - mesh_.request_vertex_status(); - mesh_.request_edge_status(); - mesh_.request_face_status(); - mesh_.request_face_normals(); + BaseDecimaterT(_mesh), + mesh_(_mesh), heap_(NULL) { // private vertex properties mesh_.add_property(collapse_target_); @@ -86,208 +82,12 @@ DecimaterT::DecimaterT(Mesh& _mesh) : template DecimaterT::~DecimaterT() { - // default properties - mesh_.release_vertex_status(); - mesh_.release_edge_status(); - mesh_.release_face_status(); - mesh_.release_face_normals(); // private vertex properties mesh_.remove_property(collapse_target_); mesh_.remove_property(priority_); mesh_.remove_property(heap_position_); - // dispose of modules - { - set_uninitialized(); - typename ModuleList::iterator m_it, m_end = all_modules_.end(); - for (m_it = all_modules_.begin(); m_it != m_end; ++m_it) - delete *m_it; - all_modules_.clear(); - } -} - -//----------------------------------------------------------------------------- - -template -void DecimaterT::info(std::ostream& _os) { - if (initialized_) { - _os << "initialized : yes" << std::endl; - _os << "binary modules: " << bmodules_.size() << std::endl; - for (ModuleListIterator m_it = bmodules_.begin(); m_it != bmodules_.end(); - ++m_it) { - _os << " " << (*m_it)->name() << std::endl; - } - _os << "priority module: " << cmodule_->name().c_str() << std::endl; - } else { - _os << "initialized : no" << std::endl; - _os << "available modules: " << all_modules_.size() << std::endl; - for (ModuleListIterator m_it = all_modules_.begin(); - m_it != all_modules_.end(); ++m_it) { - _os << " " << (*m_it)->name() << " : "; - if ((*m_it)->is_binary()) { - _os << "binary"; - if ((*m_it)->name() == "Quadric") { - _os << " and priority (special treatment)"; - } - } else { - _os << "priority"; - } - _os << std::endl; - } - } -} - -//----------------------------------------------------------------------------- - -template -bool DecimaterT::initialize() { - if (initialized_) { - return true; - } - - // FIXME: quadric module shouldn't be treated specially. - // Q: Why? - // A: It isn't generic and breaks encapsulation. Also, using string - // name comparison is not reliable, since you can't guarantee that - // no one else will name their custom module "Quadric". - // Q: What should be done instead? - // A: ModBaseT API should support modules that can be both binary - // and priority, or BETTER YET, let the DecimaterT API specify the - // priority module explicitly. - - // find the priority module: either the only non-binary module in the list, or "Quadric" - Module *quadric = NULL; - Module *pmodule = NULL; - for (ModuleListIterator m_it = all_modules_.begin(), m_end = - all_modules_.end(); m_it != m_end; ++m_it) { - if ((*m_it)->name() == "Quadric") - quadric = *m_it; - - if (!(*m_it)->is_binary()) { - if (pmodule) { - // only one priority module allowed! - set_uninitialized(); - return false; - } - pmodule = *m_it; - } - } - - // Quadric is used as default priority module (even if it is set to be binary) - if (!pmodule && quadric) { - pmodule = quadric; - } - - if (!pmodule) { - // At least one priority module required - set_uninitialized(); - return false; - } - - // set pmodule as the current priority module - cmodule_ = pmodule; - - for (ModuleListIterator m_it = all_modules_.begin(), m_end = - all_modules_.end(); m_it != m_end; ++m_it) { - // every module gets initialized - (*m_it)->initialize(); - - if (*m_it != pmodule) { - // all other modules are binary, and go into bmodules_ list - bmodules_.push_back(*m_it); - } - } - - return initialized_ = true; -} - -//----------------------------------------------------------------------------- - -template -bool DecimaterT::is_collapse_legal(const CollapseInfo& _ci) { - // std::clog << "DecimaterT<>::is_collapse_legal()\n"; - - // locked ? deleted ? - if (mesh_.status(_ci.v0).locked() || mesh_.status(_ci.v0).deleted()) - return false; - - if (!mesh_.is_collapse_ok(_ci.v0v1)) - return false; - - if (_ci.vl.is_valid() && _ci.vr.is_valid() - && mesh_.find_halfedge(_ci.vl, _ci.vr).is_valid() - && mesh_.valence(_ci.vl) == 3 && mesh_.valence(_ci.vr) == 3) { - return false; - } - //--- feature test --- - - if (mesh_.status(_ci.v0).feature() - && !mesh_.status(mesh_.edge_handle(_ci.v0v1)).feature()) - return false; - - //--- test one ring intersection --- - - typename Mesh::VertexVertexIter vv_it; - - for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it) - mesh_.status(vv_it).set_tagged(false); - - for (vv_it = mesh_.vv_iter(_ci.v1); vv_it; ++vv_it) - mesh_.status(vv_it).set_tagged(true); - - for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it) - if (mesh_.status(vv_it).tagged() && vv_it.handle() != _ci.vl - && vv_it.handle() != _ci.vr) - return false; - - // if both are invalid OR equal -> fail - if (_ci.vl == _ci.vr) - return false; - - //--- test boundary cases --- - if (mesh_.is_boundary(_ci.v0)) { - if (!mesh_.is_boundary(_ci.v1)) { // don't collapse a boundary vertex to an inner one - return false; - } else { // edge between two boundary vertices has to be a boundary edge - if (!(mesh_.is_boundary(_ci.v0v1) || mesh_.is_boundary(_ci.v1v0))) - return false; - } - // only one one ring intersection - if (_ci.vl.is_valid() && _ci.vr.is_valid()) - return false; - } - - // v0vl and v1vl must not both be boundary edges - if (_ci.vl.is_valid() && mesh_.is_boundary(_ci.vlv1) - && mesh_.is_boundary(_ci.v0vl)) - return false; - - // v0vr and v1vr must not be both boundary edges - if (_ci.vr.is_valid() && mesh_.is_boundary(_ci.vrv0) - && mesh_.is_boundary(_ci.v1vr)) - return false; - - // there have to be at least 2 incident faces at v0 - if (mesh_.cw_rotated_halfedge_handle( - mesh_.cw_rotated_halfedge_handle(_ci.v0v1)) == _ci.v0v1) - return false; - - // collapse passed all tests -> ok - return true; -} - -//----------------------------------------------------------------------------- - -template -float DecimaterT::collapse_priority(const CollapseInfo& _ci) { - typename ModuleList::iterator m_it, m_end = bmodules_.end(); - - for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) { - if ((*m_it)->collapse_priority(_ci) < 0.0) - return ModBaseT >::ILLEGAL_COLLAPSE; - } - return cmodule_->collapse_priority(_ci); } //----------------------------------------------------------------------------- @@ -305,8 +105,8 @@ void DecimaterT::heap_vertex(VertexHandle _vh) { heh = voh_it.handle(); CollapseInfo ci(mesh_, heh); - if (is_collapse_legal(ci)) { - prio = collapse_priority(ci); + if (this->is_collapse_legal(ci)) { + prio = this->collapse_priority(ci); if (prio >= 0.0 && prio < best_prio) { best_prio = prio; collapse_target = heh; @@ -337,34 +137,10 @@ void DecimaterT::heap_vertex(VertexHandle _vh) { } } -//----------------------------------------------------------------------------- - -template -void DecimaterT::postprocess_collapse(CollapseInfo& _ci) { - typename ModuleList::iterator m_it, m_end = bmodules_.end(); - - for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) - (*m_it)->postprocess_collapse(_ci); - - cmodule_->postprocess_collapse(_ci); -} - -//----------------------------------------------------------------------------- - -template -void DecimaterT::preprocess_collapse(CollapseInfo& _ci) { - typename ModuleList::iterator m_it, m_end = bmodules_.end(); - - for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) - (*m_it)->preprocess_collapse(_ci); - - cmodule_->preprocess_collapse(_ci); -} - //----------------------------------------------------------------------------- template size_t DecimaterT::decimate(size_t _n_collapses) { - if (!is_initialized()) + if (!this->is_initialized()) return 0; typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end()); @@ -406,7 +182,7 @@ size_t DecimaterT::decimate(size_t _n_collapses) { CollapseInfo ci(mesh_, v0v1); // check topological correctness AGAIN ! - if (!is_collapse_legal(ci)) + if (!this->is_collapse_legal(ci)) continue; // store support (= one ring of *vp) @@ -426,7 +202,7 @@ size_t DecimaterT::decimate(size_t _n_collapses) { mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle())); // post-process collapse - postprocess_collapse(ci); + this->postprocess_collapse(ci); // update heap (former one ring of decimated vertex) for (s_it = support.begin(), s_end = support.end(); s_it != s_end; ++s_it) { @@ -446,7 +222,7 @@ size_t DecimaterT::decimate(size_t _n_collapses) { template size_t DecimaterT::decimate_to_faces(size_t _nv, size_t _nf) { - if (!is_initialized()) + if (!this->is_initialized()) return 0; if (_nv >= mesh_.n_vertices() || _nf >= mesh_.n_faces()) diff --git a/src/OpenMesh/Tools/Decimater/DecimaterT.hh b/src/OpenMesh/Tools/Decimater/DecimaterT.hh index a5fd3fcc..ef03ec04 100644 --- a/src/OpenMesh/Tools/Decimater/DecimaterT.hh +++ b/src/OpenMesh/Tools/Decimater/DecimaterT.hh @@ -58,7 +58,7 @@ #include #include -#include +#include @@ -75,15 +75,15 @@ namespace Decimater { \see BaseModT, \ref decimater_docu */ template < typename MeshT > -class DecimaterT +class DecimaterT : public BaseDecimaterT { public: //-------------------------------------------------------- public types - typedef DecimaterT< MeshT > Self; - typedef MeshT Mesh; - typedef CollapseInfoT CollapseInfo; - typedef ModBaseT Module; - typedef std::vector< Module* > ModuleList; + typedef DecimaterT< MeshT > Self; + typedef MeshT Mesh; + typedef CollapseInfoT CollapseInfo; + typedef ModBaseT Module; + typedef std::vector< Module* > ModuleList; typedef typename ModuleList::iterator ModuleListIterator; public: //------------------------------------------------------ public methods @@ -94,76 +94,6 @@ public: //------------------------------------------------------ public methods /// Destructor ~DecimaterT(); - - /** Initialize decimater and decimating modules. - - Return values: - true ok - false No ore more than one non-binary module exist. In that case - the decimater is uninitialized! - */ - bool initialize(); - - - /// Returns whether decimater has been successfully initialized. - bool is_initialized() const { return initialized_; } - - - /// Print information about modules to _os - void info( std::ostream& _os ); - -public: //--------------------------------------------------- module management - - /// access mesh. used in modules. - Mesh& mesh() { return mesh_; } - - /// add module to decimater - template < typename _Module > - bool add( ModHandleT<_Module>& _mh ) - { - if (_mh.is_valid()) - return false; - - _mh.init( new _Module(*this) ); - all_modules_.push_back( _mh.module() ); - - set_uninitialized(); - - return true; - } - - - /// remove module - template < typename _Module > - bool remove( ModHandleT<_Module>& _mh ) - { - if (!_mh.is_valid()) - return false; - - typename ModuleList::iterator it = std::find(all_modules_.begin(), - all_modules_.end(), - _mh.module() ); - - if ( it == all_modules_.end() ) // module not found - return false; - - delete *it; - all_modules_.erase( it ); // finally remove from list - _mh.clear(); - - set_uninitialized(); - return true; - } - - - /// get module referenced by handle _mh - template < typename Module > - Module& module( ModHandleT& _mh ) - { - assert( _mh.is_valid() ); - return *_mh.module(); - } - public: /** Decimate (perform _n_collapses collapses). Return number of @@ -174,8 +104,8 @@ public: /// Decimate to target complexity, returns number of collapses size_t decimate_to( size_t _n_vertices ) { - return ( (_n_vertices < mesh().n_vertices()) ? - decimate( mesh().n_vertices() - _n_vertices ) : 0 ); + return ( (_n_vertices < this->mesh().n_vertices()) ? + decimate( this->mesh().n_vertices() - _n_vertices ) : 0 ); } /** Decimate to target complexity (vertices and faces). @@ -183,16 +113,6 @@ public: */ size_t decimate_to_faces( size_t _n_vertices=0, size_t _n_faces=0 ); -private: - - void update_modules(CollapseInfo& _ci) - { - typename ModuleList::iterator m_it, m_end = bmodules_.end(); - for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) - (*m_it)->postprocess_collapse(_ci); - cmodule_->postprocess_collapse(_ci); - } - public: typedef typename Mesh::VertexHandle VertexHandle; @@ -240,29 +160,6 @@ private: //---------------------------------------------------- private methods /// Insert vertex in heap void heap_vertex(VertexHandle _vh); - /// Is an edge collapse legal? Performs topological test only. - /// The method evaluates the status bit Locked, Deleted, and Feature. - /// \attention The method temporarily sets the bit Tagged. After usage - /// the bit will be disabled! - bool is_collapse_legal(const CollapseInfo& _ci); - - /// Calculate priority of an halfedge collapse (using the modules) - float collapse_priority(const CollapseInfo& _ci); - - /// Pre-process a collapse - void preprocess_collapse(CollapseInfo& _ci); - - /// Post-process a collapse - void postprocess_collapse(CollapseInfo& _ci); - - // Reset the initialized flag, and clear the bmodules_ and cmodule_ - void set_uninitialized() { - initialized_ = false; - cmodule_ = 0; - bmodules_.clear(); - } - - private: //------------------------------------------------------- private data @@ -272,30 +169,11 @@ private: //------------------------------------------------------- private data // heap std::auto_ptr heap_; - // list of binary modules - ModuleList bmodules_; - - // the current priority module - Module* cmodule_; - - // list of all allocated modules (including cmodule_ and all of bmodules_) - ModuleList all_modules_; - - bool initialized_; - - // vertex properties VPropHandleT collapse_target_; VPropHandleT priority_; VPropHandleT heap_position_; - - -private: // Noncopyable - - DecimaterT(const Self&); - Self& operator = (const Self&); - }; //============================================================================= diff --git a/src/OpenMesh/Tools/Decimater/McDecimaterT.cc b/src/OpenMesh/Tools/Decimater/McDecimaterT.cc index 8c59353f..721c9129 100644 --- a/src/OpenMesh/Tools/Decimater/McDecimaterT.cc +++ b/src/OpenMesh/Tools/Decimater/McDecimaterT.cc @@ -69,7 +69,8 @@ namespace Decimater { template McDecimaterT::McDecimaterT(Mesh& _mesh) : - mesh_(_mesh), cmodule_(NULL), initialized_(false),randomSamples_(10) { + BaseDecimaterT(_mesh), + mesh_(_mesh), randomSamples_(10) { // default properties mesh_.request_vertex_status(); @@ -91,228 +92,13 @@ McDecimaterT::~McDecimaterT() { mesh_.release_face_status(); mesh_.release_face_normals(); - // dispose of modules - { - set_uninitialized(); - typename ModuleList::iterator m_it, m_end = all_modules_.end(); - for (m_it = all_modules_.begin(); m_it != m_end; ++m_it) - delete *m_it; - all_modules_.clear(); - } -} - -//----------------------------------------------------------------------------- - -template -void McDecimaterT::info(std::ostream& _os) { - if (initialized_) { - _os << "initialized : yes" << std::endl; - _os << "binary modules: " << bmodules_.size() << std::endl; - for (ModuleListIterator m_it = bmodules_.begin(); m_it != bmodules_.end(); - ++m_it) { - _os << " " << (*m_it)->name() << std::endl; - } - _os << "priority module: " << cmodule_->name().c_str() << std::endl; - } else { - _os << "initialized : no" << std::endl; - _os << "available modules: " << all_modules_.size() << std::endl; - for (ModuleListIterator m_it = all_modules_.begin(); - m_it != all_modules_.end(); ++m_it) { - _os << " " << (*m_it)->name() << " : "; - if ((*m_it)->is_binary()) { - _os << "binary"; - if ((*m_it)->name() == "Quadric") { - _os << " and priority (special treatment)"; - } - } else { - _os << "priority"; - } - _os << std::endl; - } - } -} - -//----------------------------------------------------------------------------- - -template -bool McDecimaterT::initialize() { - if (initialized_) { - return true; - } - - // FIXME: quadric module shouldn't be treated specially. - // Q: Why? - // A: It isn't generic and breaks encapsulation. Also, using string - // name comparison is not reliable, since you can't guarantee that - // no one else will name their custom module "Quadric". - // Q: What should be done instead? - // A: ModBaseT API should support modules that can be both binary - // and priority, or BETTER YET, let the McDecimaterT API specify the - // priority module explicitly. - - // find the priority module: either the only non-binary module in the list, or "Quadric" - Module *quadric = NULL; - Module *pmodule = NULL; - for (ModuleListIterator m_it = all_modules_.begin(), m_end = - all_modules_.end(); m_it != m_end; ++m_it) { - if ((*m_it)->name() == "Quadric") - quadric = *m_it; - - if (!(*m_it)->is_binary()) { - if (pmodule) { - // only one priority module allowed! - set_uninitialized(); - return false; - } - pmodule = *m_it; - } - } - - // Quadric is used as default priority module (even if it is set to be binary) - if (!pmodule && quadric) { - pmodule = quadric; - } - - if (!pmodule) { - // At least one priority module required - set_uninitialized(); - return false; - } - - // set pmodule as the current priority module - cmodule_ = pmodule; - - for (ModuleListIterator m_it = all_modules_.begin(), m_end = - all_modules_.end(); m_it != m_end; ++m_it) { - // every module gets initialized - (*m_it)->initialize(); - - if (*m_it != pmodule) { - // all other modules are binary, and go into bmodules_ list - bmodules_.push_back(*m_it); - } - } - - return initialized_ = true; -} - -//----------------------------------------------------------------------------- - -template -bool McDecimaterT::is_collapse_legal(const CollapseInfo& _ci) { - // std::clog << "McDecimaterT<>::is_collapse_legal()\n"; - - // locked ? deleted ? - if (mesh_.status(_ci.v0).locked() || mesh_.status(_ci.v0).deleted()) - return false; - - if (!mesh_.is_collapse_ok(_ci.v0v1)) - return false; - - if (_ci.vl.is_valid() && _ci.vr.is_valid() - && mesh_.find_halfedge(_ci.vl, _ci.vr).is_valid() - && mesh_.valence(_ci.vl) == 3 && mesh_.valence(_ci.vr) == 3) { - return false; - } - //--- feature test --- - - if (mesh_.status(_ci.v0).feature() - && !mesh_.status(mesh_.edge_handle(_ci.v0v1)).feature()) - return false; - - //--- test one ring intersection --- - - typename Mesh::VertexVertexIter vv_it; - - for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it) - mesh_.status(vv_it).set_tagged(false); - - for (vv_it = mesh_.vv_iter(_ci.v1); vv_it; ++vv_it) - mesh_.status(vv_it).set_tagged(true); - - for (vv_it = mesh_.vv_iter(_ci.v0); vv_it; ++vv_it) - if (mesh_.status(vv_it).tagged() && vv_it.handle() != _ci.vl - && vv_it.handle() != _ci.vr) - return false; - - // if both are invalid OR equal -> fail - if (_ci.vl == _ci.vr) - return false; - - //--- test boundary cases --- - if (mesh_.is_boundary(_ci.v0)) { - if (!mesh_.is_boundary(_ci.v1)) { // don't collapse a boundary vertex to an inner one - return false; - } else { // edge between two boundary vertices has to be a boundary edge - if (!(mesh_.is_boundary(_ci.v0v1) || mesh_.is_boundary(_ci.v1v0))) - return false; - } - // only one one ring intersection - if (_ci.vl.is_valid() && _ci.vr.is_valid()) - return false; - } - - // v0vl and v1vl must not both be boundary edges - if (_ci.vl.is_valid() && mesh_.is_boundary(_ci.vlv1) - && mesh_.is_boundary(_ci.v0vl)) - return false; - - // v0vr and v1vr must not be both boundary edges - if (_ci.vr.is_valid() && mesh_.is_boundary(_ci.vrv0) - && mesh_.is_boundary(_ci.v1vr)) - return false; - - // there have to be at least 2 incident faces at v0 - if (mesh_.cw_rotated_halfedge_handle( - mesh_.cw_rotated_halfedge_handle(_ci.v0v1)) == _ci.v0v1) - return false; - - // collapse passed all tests -> ok - return true; -} - -//----------------------------------------------------------------------------- - -template -float McDecimaterT::collapse_priority(const CollapseInfo& _ci) { - typename ModuleList::iterator m_it, m_end = bmodules_.end(); - - for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) { - if ((*m_it)->collapse_priority(_ci) < 0.0) - return ModBaseT >::ILLEGAL_COLLAPSE; - } - return cmodule_->collapse_priority(_ci); -} - -//----------------------------------------------------------------------------- - -template -void McDecimaterT::postprocess_collapse(CollapseInfo& _ci) { - typename ModuleList::iterator m_it, m_end = bmodules_.end(); - - for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) - (*m_it)->postprocess_collapse(_ci); - - cmodule_->postprocess_collapse(_ci); -} - -//----------------------------------------------------------------------------- - -template -void McDecimaterT::preprocess_collapse(CollapseInfo& _ci) { - typename ModuleList::iterator m_it, m_end = bmodules_.end(); - - for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) - (*m_it)->preprocess_collapse(_ci); - - cmodule_->preprocess_collapse(_ci); } //----------------------------------------------------------------------------- template size_t McDecimaterT::decimate(size_t _n_collapses) { - if (!is_initialized()) + if (!this->is_initialized()) return 0; unsigned int n_collapses(0); @@ -335,8 +121,8 @@ size_t McDecimaterT::decimate(size_t _n_collapses) { CollapseInfo ci(mesh_, tmpHandle); // Check if legal we analyze the priority of this collapse operation - if (is_collapse_legal(ci)) { - double energy = collapse_priority(ci); + if (this->is_collapse_legal(ci)) { + double energy = this->collapse_priority(ci); // Check if the current samples energy is better than any energy before if ( energy < bestEnergy ) { @@ -357,11 +143,11 @@ size_t McDecimaterT::decimate(size_t _n_collapses) { CollapseInfo ci(mesh_, bestHandle); // check topological correctness AGAIN ! - if (!is_collapse_legal(ci)) + if (!this->is_collapse_legal(ci)) continue; // pre-processing - preprocess_collapse(ci); + this->preprocess_collapse(ci); // perform collapse mesh_.collapse(bestHandle); @@ -374,7 +160,7 @@ size_t McDecimaterT::decimate(size_t _n_collapses) { mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle())); // post-process collapse - postprocess_collapse(ci); + this->postprocess_collapse(ci); } @@ -388,7 +174,7 @@ size_t McDecimaterT::decimate(size_t _n_collapses) { template size_t McDecimaterT::decimate_to_faces(size_t _nv, size_t _nf) { - if (!is_initialized()) + if (!this->is_initialized()) return 0; unsigned int nv = mesh_.n_vertices(); diff --git a/src/OpenMesh/Tools/Decimater/McDecimaterT.hh b/src/OpenMesh/Tools/Decimater/McDecimaterT.hh index d62f015c..9ee7af48 100644 --- a/src/OpenMesh/Tools/Decimater/McDecimaterT.hh +++ b/src/OpenMesh/Tools/Decimater/McDecimaterT.hh @@ -55,9 +55,7 @@ //== INCLUDES ================================================================= #include - -#include -#include +#include @@ -74,14 +72,14 @@ namespace Decimater { \see BaseModT, \ref decimater_docu */ template < typename MeshT > -class McDecimaterT +class McDecimaterT : public BaseDecimaterT { public: //-------------------------------------------------------- public types typedef McDecimaterT< MeshT > Self; typedef MeshT Mesh; typedef CollapseInfoT CollapseInfo; - typedef ModBaseT Module; + typedef ModBaseT Module; typedef std::vector< Module* > ModuleList; typedef typename ModuleList::iterator ModuleListIterator; @@ -93,76 +91,6 @@ public: //------------------------------------------------------ public methods /// Destructor ~McDecimaterT(); - - /** Initialize decimater and decimating modules. - - Return values: - true ok - false No ore more than one non-binary module exist. In that case - the decimater is uninitialized! - */ - bool initialize(); - - - /// Returns whether decimater has been successfully initialized. - bool is_initialized() const { return initialized_; } - - - /// Print information about modules to _os - void info( std::ostream& _os ); - -public: //--------------------------------------------------- module management - - /// access mesh. used in modules. - Mesh& mesh() { return mesh_; } - - /// add module to decimater - template < typename _Module > - bool add( ModHandleT<_Module>& _mh ) - { - if (_mh.is_valid()) - return false; - - _mh.init( new _Module(*this) ); - all_modules_.push_back( _mh.module() ); - - set_uninitialized(); - - return true; - } - - - /// remove module - template < typename _Module > - bool remove( ModHandleT<_Module>& _mh ) - { - if (!_mh.is_valid()) - return false; - - typename ModuleList::iterator it = std::find(all_modules_.begin(), - all_modules_.end(), - _mh.module() ); - - if ( it == all_modules_.end() ) // module not found - return false; - - delete *it; - all_modules_.erase( it ); // finally remove from list - _mh.clear(); - - set_uninitialized(); - return true; - } - - - /// get module referenced by handle _mh - template < typename Module > - Module& module( ModHandleT& _mh ) - { - assert( _mh.is_valid() ); - return *_mh.module(); - } - public: /** Decimate (perform _n_collapses collapses). Return number of @@ -173,8 +101,8 @@ public: /// Decimate to target complexity, returns number of collapses size_t decimate_to( size_t _n_vertices ) { - return ( (_n_vertices < mesh().n_vertices()) ? - decimate( mesh().n_vertices() - _n_vertices ) : 0 ); + return ( (_n_vertices < this->mesh().n_vertices()) ? + decimate( this->mesh().n_vertices() - _n_vertices ) : 0 ); } /** Decimate to target complexity (vertices and faces). @@ -182,84 +110,14 @@ public: */ size_t decimate_to_faces( size_t _n_vertices=0, size_t _n_faces=0 ); -private: - - void update_modules(CollapseInfo& _ci) - { - typename ModuleList::iterator m_it, m_end = bmodules_.end(); - for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) - (*m_it)->postprocess_collapse(_ci); - cmodule_->postprocess_collapse(_ci); - } - -public: - - typedef typename Mesh::VertexHandle VertexHandle; - typedef typename Mesh::HalfedgeHandle HalfedgeHandle; - - /// Heap interface - class HeapInterface - { - public: - - HeapInterface(Mesh& _mesh) - : mesh_(_mesh) - { } - - private: - Mesh& mesh_; - }; - - -private: //---------------------------------------------------- private methods - - /// Is an edge collapse legal? Performs topological test only. - /// The method evaluates the status bit Locked, Deleted, and Feature. - /// \attention The method temporarily sets the bit Tagged. After usage - /// the bit will be disabled! - bool is_collapse_legal(const CollapseInfo& _ci); - - /// Calculate priority of an halfedge collapse (using the modules) - float collapse_priority(const CollapseInfo& _ci); - - /// Pre-process a collapse - void preprocess_collapse(CollapseInfo& _ci); - - /// Post-process a collapse - void postprocess_collapse(CollapseInfo& _ci); - - // Reset the initialized flag, and clear the bmodules_ and cmodule_ - void set_uninitialized() { - initialized_ = false; - cmodule_ = 0; - bmodules_.clear(); - } - - private: //------------------------------------------------------- private data // reference to mesh Mesh& mesh_; - // list of binary modules - ModuleList bmodules_; - - // the current priority module - Module* cmodule_; - - // list of all allocated modules (including cmodule_ and all of bmodules_) - ModuleList all_modules_; - - bool initialized_; - unsigned int randomSamples_; -private: // Noncopyable - - McDecimaterT(const Self&); - Self& operator = (const Self&); - }; //============================================================================= @@ -271,6 +129,6 @@ private: // Noncopyable #include "McDecimaterT.cc" #endif //============================================================================= -#endif // OPENMESH_DECIMATER_DECIMATERT_HH defined +#endif // OPENMESH_MC_DECIMATER_DECIMATERT_HH defined //============================================================================= diff --git a/src/OpenMesh/Tools/Decimater/ModBaseT.hh b/src/OpenMesh/Tools/Decimater/ModBaseT.hh index a476476c..842b20a3 100644 --- a/src/OpenMesh/Tools/Decimater/ModBaseT.hh +++ b/src/OpenMesh/Tools/Decimater/ModBaseT.hh @@ -68,8 +68,7 @@ namespace Decimater { //== FORWARD DECLARATIONS ===================================================== -template class DecimaterT; -template class McDecimaterT; +template class BaseDecimaterT; //== CLASS DEFINITION ========================================================= @@ -77,6 +76,7 @@ template class McDecimaterT; /** Handle for mesh decimation modules \internal */ + template class ModHandleT : private Utils::Noncopyable { @@ -100,11 +100,9 @@ public: private: #if defined(OM_CC_MSVC) - friend class DecimaterT; - friend class McDecimaterT; + friend class BaseDecimaterT; #else - template friend class DecimaterT; - template friend class McDecimaterT; + template friend class BaseDecimaterT; #endif void clear() { mod_ = NULL; } @@ -146,10 +144,10 @@ private: * template parameter passed to ModBaseT. * \param Name Give the module a name. */ -#define DECIMATING_MODULE(Classname, DecimaterT, Name) \ - typedef Classname < DecimaterT > Self; \ +#define DECIMATING_MODULE(Classname, MeshT, Name) \ + typedef Classname < MeshT > Self; \ typedef OpenMesh::Decimater::ModHandleT< Self > Handle; \ - typedef OpenMesh::Decimater::ModBaseT< DecimaterT > Base; \ + typedef OpenMesh::Decimater::ModBaseT< MeshT > Base; \ typedef typename Base::Mesh Mesh; \ typedef typename Base::CollapseInfo CollapseInfo; \ DECIMATER_MODNAME( Name ) @@ -187,13 +185,13 @@ private: \todo "Tutorial on building a custom decimation module." */ -template + +template class ModBaseT { public: - - typedef typename DecimaterType::Mesh Mesh; - typedef CollapseInfoT CollapseInfo; + typedef MeshT Mesh; + typedef CollapseInfoT CollapseInfo; enum { ILLEGAL_COLLAPSE = -1, ///< indicates an illegal collapse @@ -204,8 +202,8 @@ protected: /// Default constructor /// \see \ref decimater_docu - ModBaseT(DecimaterType& _dec, bool _is_binary) - : dec_(_dec), is_binary_(_is_binary) {} + ModBaseT(MeshT& _mesh, bool _is_binary) + : mesh_(_mesh), is_binary_(_is_binary) {} public: @@ -242,19 +240,19 @@ public: // common interface * \return Collapse priority in the range [0,inf), * \c LEGAL_COLLAPSE or \c ILLEGAL_COLLAPSE. */ - virtual float collapse_priority(const CollapseInfoT& /* _ci */) + virtual float collapse_priority(const CollapseInfoT& /* _ci */) { return LEGAL_COLLAPSE; } /** Before _from_vh has been collapsed into _to_vh, this method will be called. */ - virtual void preprocess_collapse(const CollapseInfoT& /* _ci */) + virtual void preprocess_collapse(const CollapseInfoT& /* _ci */) {} /** After _from_vh has been collapsed into _to_vh, this method will be called. */ - virtual void postprocess_collapse(const CollapseInfoT& /* _ci */) + virtual void postprocess_collapse(const CollapseInfoT& /* _ci */) {} @@ -262,7 +260,7 @@ public: // common interface protected: /// Access the mesh associated with the decimater. - Mesh& mesh() { return dec_.mesh(); } + MeshT& mesh() { return mesh_; } private: @@ -270,8 +268,7 @@ private: ModBaseT(const ModBaseT& _cpy); ModBaseT& operator=(const ModBaseT& ); - // reference to decimater - DecimaterType &dec_; + MeshT& mesh_; bool is_binary_; }; diff --git a/src/Unittests/unittests_decimater.hh b/src/Unittests/unittests_decimater.hh index 80755a13..c54f6824 100644 --- a/src/Unittests/unittests_decimater.hh +++ b/src/Unittests/unittests_decimater.hh @@ -42,8 +42,8 @@ TEST_F(OpenMeshDecimater, DecimateMesh) { ASSERT_TRUE(ok); typedef OpenMesh::Decimater::DecimaterT< Mesh > Decimater; - typedef OpenMesh::Decimater::ModQuadricT< Decimater >::Handle HModQuadric; - typedef OpenMesh::Decimater::ModNormalFlippingT< Decimater >::Handle HModNormal; + typedef OpenMesh::Decimater::ModQuadricT< Mesh >::Handle HModQuadric; + typedef OpenMesh::Decimater::ModNormalFlippingT< Mesh >::Handle HModNormal; Decimater decimaterDBG(mesh_); HModQuadric hModQuadricDBG; diff --git a/src/Unittests/unittests_mc_decimater.hh b/src/Unittests/unittests_mc_decimater.hh index f9753346..9cc89e78 100644 --- a/src/Unittests/unittests_mc_decimater.hh +++ b/src/Unittests/unittests_mc_decimater.hh @@ -42,8 +42,8 @@ TEST_F(OpenMeshMultipleChoiceDecimater, DecimateMesh) { ASSERT_TRUE(ok); typedef OpenMesh::Decimater::McDecimaterT< Mesh > Decimater; - typedef OpenMesh::Decimater::ModQuadricT< Decimater >::Handle HModQuadric; - typedef OpenMesh::Decimater::ModNormalFlippingT< Decimater >::Handle HModNormal; + typedef OpenMesh::Decimater::ModQuadricT< Mesh >::Handle HModQuadric; + typedef OpenMesh::Decimater::ModNormalFlippingT< Mesh >::Handle HModNormal; Decimater decimaterDBG(mesh_); HModQuadric hModQuadricDBG;