⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decimatert.cc

📁 penMesh is a generic and efficient data structure for representing and manipulating polygonal meshes
💻 CC
字号:
//=============================================================================////                               OpenMesh//      Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen//                           www.openmesh.org////-----------------------------------------------------------------------------////                                License////   This library is free software; you can redistribute it and/or modify it//   under the terms of the GNU Library General Public License as published//   by the Free Software Foundation, version 2.////   This library 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//   Library General Public License for more details.////   You should have received a copy of the GNU Library General Public//   License along with this library; if not, write to the Free Software//   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.////-----------------------------------------------------------------------------////   $Revision: 1.5 $//   $Date: 2005-12-21 13:55:20 $////=============================================================================/** \file DecimaterT.cc *///=============================================================================////  CLASS DecimaterT - IMPLEMENTATION////=============================================================================#define OPENMESH_DECIMATER_DECIMATERT_CC//== INCLUDES =================================================================#include <OpenMesh/Tools/Decimater/DecimaterT.hh>#include <OpenMesh/Tools/Utils/Progress.hh>#include <vector>#if defined(OM_CC_MIPS)#  include <float.h>#else#  include <cfloat>#endif#ifdef min# undef min#endif#ifdef max# undef max#endif//== NAMESPACE ===============================================================namespace OpenMesh  {namespace Decimater {//== IMPLEMENTATION ==========================================================template <class Mesh>DecimaterT<Mesh>::DecimaterT( Mesh& _mesh )  : mesh_(_mesh),    heap_(NULL),    cmodule_(NULL),    initialized_(false),    emit_progress_(false){  // default properties  mesh_.request_vertex_status();  mesh_.request_edge_status();  mesh_.request_face_status();  mesh_.request_face_normals();  // private vertex properties  mesh_.add_property( collapse_target_ );  mesh_.add_property( priority_ );  mesh_.add_property( heap_position_ );}//-----------------------------------------------------------------------------template <class Mesh>DecimaterT<Mesh>::~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_);  // remove modules  typename ModuleList::iterator m_it, m_end = bmodules_.end();  for( m_it=bmodules_.begin(); m_it!=m_end; ++m_it)    delete *m_it;  bmodules_.clear();  if (cmodule_)    delete cmodule_;}//-----------------------------------------------------------------------------template <class Mesh>voidDecimaterT<Mesh>::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() : "<None>") << std::endl;  _os << "is initialized : " << (initialized_ ? "yes" : "no") << std::endl;}//-----------------------------------------------------------------------------template <class Mesh>boolDecimaterT<Mesh>::initialize(){  typename ModuleList::iterator m_it, m_end;  if (!cmodule_) return false;//   // find priority module//   if (!cmodule_)//   {//     // test all modules//     for (m_it=bmodules_.begin(), m_end=bmodules_.end(); m_it!=m_end; ++m_it)//     {//       if ( ! (*m_it)->is_binary() )//       {// 	if ( !cmodule_ ) // only one non-binary module allowed!// 	  cmodule_ = *m_it;// 	else// 	{// 	  cmodule_ = NULL;// 	  return initialized_ = false;// 	}//       }//     }//     // no module found? look for quadric module//     for (m_it=bmodules_.begin(), m_end=bmodules_.end(); m_it!=m_end; ++m_it)//     {//       if ((*m_it)->name() == "Quadric")//       {// 	cmodule_ = *m_it;// 	break;//       }//     }//     // need one priority module//     if (!cmodule_) return initialized_ = false;//     // remove prio module from list of binary modules//     bmodules_.erase( std::find(bmodules_.begin(), bmodules_.end(), cmodule_ ) );//   }  // initialize modules  for (m_it=bmodules_.begin(), m_end=bmodules_.end(); m_it!=m_end; ++m_it)    (*m_it)->initialize();  cmodule_->initialize();  return initialized_ = true;}//-----------------------------------------------------------------------------template <class Mesh>boolDecimaterT<Mesh>::is_collapse_legal(const CollapseInfo& _ci){  // locked ? deleted ?  if (mesh_.status(_ci.v0).locked() ||      mesh_.status(_ci.v0).deleted())    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 tests ---  if (mesh_.status(_ci.v0).feature() &&      !mesh_.status(mesh_.edge_handle(_ci.v0v1)).feature())    return false;  // the other two edges removed by collapse must not be features  if (_ci.v0vl.is_valid() &&      mesh_.status(mesh_.edge_handle(_ci.v0vl)).feature())    return false;  if (_ci.vrv0.is_valid() &&      mesh_.status(mesh_.edge_handle(_ci.vrv0)).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.v0v1))    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 <class Mesh>floatDecimaterT<Mesh>::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 -1.0; // ILLEGAL_COLLAPSE  }  return cmodule_->collapse_priority(_ci);}//-----------------------------------------------------------------------------template <class Mesh>voidDecimaterT<Mesh>::heap_vertex(VertexHandle _vh){  float                           prio, best_prio(FLT_MAX);  typename Mesh::HalfedgeHandle   heh, collapse_target;  // find best target in one ring  if (!mesh_.status(_vh).locked())  {    for (typename Mesh::VOHIter voh_it=mesh_.voh_iter(_vh); voh_it; ++voh_it)    {      heh = voh_it.handle();      CollapseInfo  ci(mesh_, heh);      if (is_collapse_legal(ci))      {	prio = collapse_priority(ci);	if (prio >= 0.0 && prio < best_prio)	{	  best_prio       = prio;	  collapse_target = heh;	}      }    }  }  // target found -> put vertex on heap  if (collapse_target.is_valid())  {    mesh_.property(collapse_target_, _vh) = collapse_target;    mesh_.property(priority_, _vh)        = best_prio;    if (heap_->is_stored(_vh))  heap_->update(_vh);    else                        heap_->insert(_vh);  }  // not valid -> remove from heap  else  {    if (heap_->is_stored(_vh))  heap_->remove(_vh);    mesh_.property(collapse_target_, _vh) = collapse_target;    mesh_.property(priority_, _vh)        = -1;  }}//-----------------------------------------------------------------------------template <class Mesh>voidDecimaterT<Mesh>::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 <class Mesh>voidDecimaterT<Mesh>::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 <class Mesh>size_tDecimaterT<Mesh>::decimate_to( size_t _nv, size_t _nf ){  if ( !is_initialized() )    return 0;    if (_nv >= mesh_.n_vertices() || _nf >= mesh_.n_faces())    return 0;      // update progress  if (emit_progress_)    Progress().set_steps( std::min( (mesh_.n_vertices()-_nv),				    (mesh_.n_faces()-_nf)/2 ),			  "Decimating" );  typename Mesh::VertexIter         v_it, v_end(mesh_.vertices_end());  typename Mesh::VertexHandle       vp;  typename Mesh::HalfedgeHandle     v0v1;  typename Mesh::VertexFaceIter     vf_it;  unsigned int                      nv = mesh_.n_vertices();  unsigned int                      nf = mesh_.n_faces();  unsigned int                      nc = 0;  typename std::vector<typename Mesh::VertexHandle>::iterator vh_it, vh_end;  // initialize heap  HeapInterface  HI(mesh_, priority_, heap_position_);  heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));  heap_->reserve(mesh_.n_vertices());  for (v_it = mesh_.vertices_begin(); v_it != v_end; ++v_it)  {    heap_->reset_heap_position( v_it.handle() );    if (!mesh_.status(v_it).deleted())      heap_vertex( v_it.handle() );  }  // process heap  while ((!heap_->empty()) && (_nv < nv) && (_nf < nf))  {    // get 1st heap entry    vp   = heap_->front();    v0v1 = mesh_.property(collapse_target_, vp);    heap_->pop_front();    // setup collapse info    CollapseInfo ci(mesh_, v0v1);    // check topological correctness AGAIN !    if (!is_collapse_legal(ci))      continue;    // adjust complexity in advance (need boundary status)    ++nc;    --nv;    if (mesh_.is_boundary(ci.v0v1) ||	mesh_.is_boundary(ci.v1v0))      --nf;    else nf -= 2;    // pre-processing    preprocess_collapse(ci);    // perform collapse    mesh_.collapse(v0v1);    // update progress    if (emit_progress_)      if (!Progress().step())	break;    // update triangle normals    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    postprocess_collapse(ci);    // update heap (former one ring of decimated vertex)    for (vh_it = ci.one_ring.begin(), vh_end = ci.one_ring.end();	 vh_it != vh_end; ++vh_it)    {      assert(!mesh_.status(*vh_it).deleted());      heap_vertex(*vh_it);    }  }			    // delete heap  heap_.reset();  // update progress  if (emit_progress_)    Progress().finish();  // DON'T do garbage collection here! It's up to the application.  return nc;}//=============================================================================} // END_NS_DECIMATER} // END_NS_OPENMESH//=============================================================================

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -