diff --git a/src/OpenMesh/Tools/Decimater/DecimaterT.cc b/src/OpenMesh/Tools/Decimater/DecimaterT.cc index 9cd66afb..b1fd61e0 100644 --- a/src/OpenMesh/Tools/Decimater/DecimaterT.cc +++ b/src/OpenMesh/Tools/Decimater/DecimaterT.cc @@ -103,14 +103,13 @@ DecimaterT:: mesh_.remove_property(priority_); mesh_.remove_property(heap_position_); - // dispose modules + // dispose of modules { - typename ModuleList::iterator m_it, m_end = bmodules_.end(); - for( m_it=bmodules_.begin(); m_it!=m_end; ++m_it) + 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; - bmodules_.clear(); - if (cmodule_) - delete cmodule_; + all_modules_.clear(); } } @@ -123,15 +122,33 @@ void DecimaterT:: info( std::ostream& _os ) { - typename ModuleList::iterator m_it, m_end = bmodules_.end(); - - _os << "binary modules: " << bmodules_.size() << std::endl; - for( m_it=bmodules_.begin(); m_it!=m_end; ++m_it) - _os << " " << (*m_it)->name() << std::endl; - - _os << "priority module: " - << (cmodule_ ? cmodule_->name().c_str() : "") << std::endl; - _os << "is initialized : " << (initialized_ ? "yes" : "no") << std::endl; + 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; + } + } } @@ -143,56 +160,64 @@ bool DecimaterT:: initialize() { - typename ModuleList::iterator m_it, m_end = bmodules_.end(); + 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* origC = NULL; - - // If already initialized, remember original cModule (priority module) - // if no new cmodule is provided use old one - if (initialized_) - origC = cmodule_; - - cmodule_ = NULL; - - for (m_it=bmodules_.begin(); m_it != m_end; ++m_it) + 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 ( !(*m_it)->is_binary() ) { - if ( !cmodule_ ) // only one non-binary module allowed! - cmodule_ = *m_it; - else + if(pmodule) + { + // only one priority module allowed! + set_uninitialized(); return false; + } + pmodule = *m_it; } - (*m_it)->initialize(); + } + + // Quadric is used as default priority module (even if it is set to be binary) + if(!pmodule && quadric) { + pmodule = quadric; } - // If the decimater has already been initialized and we have no new cmodule, - // use the old cmodule - if ( initialized_ && !cmodule_ ) { - cmodule_ = origC; - cmodule_->initialize(); + if(!pmodule) { + // At least one priority module required + set_uninitialized(); + return false; } - if (!cmodule_) // one non-binary module is mandatory! + // 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) { - if (!quadric) - return false; - else - { - cmodule_ = quadric; // let the quadric become the priority module - } - } + // every module gets initialized + (*m_it)->initialize(); - // If we do not reuse the original cmodule delete the new cmodule from the - // binary module list - if ( !initialized_ || (cmodule_ != origC) ) { - m_it = std::find(bmodules_.begin(), bmodules_.end(), cmodule_ ); - bmodules_.erase( m_it ); + if(*m_it != pmodule) { + // all other modules are binary, and go into bmodules_ list + bmodules_.push_back(*m_it); + } } return initialized_ = true; @@ -303,7 +328,7 @@ DecimaterT::collapse_priority(const CollapseInfo& _ci) for (m_it = bmodules_.begin(); m_it != m_end; ++m_it) { if ( (*m_it)->collapse_priority(_ci) < 0.0) - return -1.0; // ILLEGAL_COLLAPSE + return ModBaseT >::ILLEGAL_COLLAPSE; } return cmodule_->collapse_priority(_ci); } diff --git a/src/OpenMesh/Tools/Decimater/DecimaterT.hh b/src/OpenMesh/Tools/Decimater/DecimaterT.hh index 3743868f..e9758647 100644 --- a/src/OpenMesh/Tools/Decimater/DecimaterT.hh +++ b/src/OpenMesh/Tools/Decimater/DecimaterT.hh @@ -73,6 +73,7 @@ public: //-------------------------------------------------------- public types typedef CollapseInfoT CollapseInfo; typedef ModBaseT Module; typedef std::vector< Module* > ModuleList; + typedef typename ModuleList::iterator ModuleListIterator; public: //------------------------------------------------------ public methods @@ -113,9 +114,10 @@ public: //--------------------------------------------------- module management return false; _mh.init( new _Module(*this) ); - bmodules_.push_back( _mh.module() ); + all_modules_.push_back( _mh.module() ); - initialized_ = false; + set_uninitialized(); + return true; } @@ -127,25 +129,18 @@ public: //--------------------------------------------------- module management if (!_mh.is_valid()) return false; - if ( cmodule_ == _mh.module() ) { - cmodule_ = 0; - initialized_ = false; // reset initialized state - _mh.clear(); - return true; - } + typename ModuleList::iterator it = std::find(all_modules_.begin(), + all_modules_.end(), + _mh.module() ); - typename ModuleList::iterator it = std::find(bmodules_.begin(), - bmodules_.end(), - _mh.module() ); - - if ( it == bmodules_.end() ) // module not found + if ( it == all_modules_.end() ) // module not found return false; delete *it; - bmodules_.erase( it ); // finally remove from list + all_modules_.erase( it ); // finally remove from list _mh.clear(); - initialized_ = false; // reset initialized state + set_uninitialized(); return true; } @@ -242,7 +237,12 @@ private: //---------------------------------------------------- private methods /// 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 @@ -254,10 +254,15 @@ private: //------------------------------------------------------- private data // heap std::auto_ptr heap_; - // list of modules + // 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_;