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

📄 polymesht.cc

📁 penMesh is a generic and efficient data structure for representing and manipulating polygonal meshes
💻 CC
📖 第 1 页 / 共 2 页
字号:
//=============================================================================////                               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:51:49 $////=============================================================================//=============================================================================////  CLASS PolyMeshT - IMPLEMENTATION////=============================================================================#define OPENMESH_POLYMESH_C//== INCLUDES =================================================================#include <OpenMesh/Core/Mesh/PolyMeshT.hh>#include <OpenMesh/Core/Math/LoopSchemeMaskT.hh>#include <OpenMesh/Core/Utils/vector_cast.hh>#include <OpenMesh/Core/System/omstream.hh>#include <vector>//== NAMESPACES ===============================================================namespace OpenMesh {//== IMPLEMENTATION ==========================================================template <class Kernel>const typename PolyMeshT<Kernel>::VertexHandlePolyMeshT<Kernel>::InvalidVertexHandle;template <class Kernel>const typename PolyMeshT<Kernel>::HalfedgeHandlePolyMeshT<Kernel>::InvalidHalfedgeHandle;template <class Kernel>const typename PolyMeshT<Kernel>::EdgeHandlePolyMeshT<Kernel>::InvalidEdgeHandle;template <class Kernel>const typename PolyMeshT<Kernel>::FaceHandlePolyMeshT<Kernel>::InvalidFaceHandle;template <class Kernel_>uint PolyMeshT<Kernel_>::find_feature_edges(Scalar _angle_tresh){  assert(This::has_edge_status());//this function needs edge status property  uint n_feature_edges = 0;  for (EdgeIter e_it = edges_begin(); e_it != edges_end(); ++e_it)  {    if (fabs(calc_dihedral_angle(e_it)) > _angle_tresh)    {//note: could be optimized by comparing cos(dih_angle) vs. cos(_angle_tresh)      status(e_it).set_feature(true);      n_feature_edges++;    }    else    {      status(e_it).set_feature(false);    }  }  return n_feature_edges;}//-----------------------------------------------------------------------------template <class Kernel_>typename PolyMeshT<Kernel_>::HalfedgeHandlePolyMeshT<Kernel_>::find_halfedge( VertexHandle _start_vertex_handle,               VertexHandle _end_vertex_handle ) const{  assert(_start_vertex_handle.is_valid() && _end_vertex_handle.is_valid());  for (ConstVertexVertexIter vvIt=cvv_iter(_start_vertex_handle); vvIt; ++vvIt)    if (vvIt.handle() == _end_vertex_handle)      return vvIt.current_halfedge_handle();  return InvalidHalfedgeHandle;}//-----------------------------------------------------------------------------template <class Kernel>voidPolyMeshT<Kernel>::adjust_outgoing_halfedge(VertexHandle _vh){  for (ConstVertexOHalfedgeIter vh_it=cvoh_iter(_vh); vh_it; ++vh_it)  {    if (is_boundary(vh_it.handle()))    {      set_halfedge_handle(_vh, vh_it.handle());      break;    }  }}//-----------------------------------------------------------------------------namespace add_face_ns{  template <class _Handle>  struct NextCacheEntryT : public std::pair<_Handle, _Handle>  {    typedef std::pair<_Handle, _Handle> Base;    NextCacheEntryT(_Handle _heh0, _Handle _heh1)      : Base(_heh0, _heh1)    {      assert(_heh0.is_valid());      assert(_heh1.is_valid());    }  };};template <class Kernel>typename PolyMeshT<Kernel>::FaceHandlePolyMeshT<Kernel>::add_face(const std::vector<VertexHandle>& _vertex_handles){  VertexHandle                   vh;  unsigned int                   i, ii, n(_vertex_handles.size()), id;  std::vector<HalfedgeHandle>    halfedge_handles(n);  std::vector<bool>              is_new(n), needs_adjust(n, false);  HalfedgeHandle                 inner_next, inner_prev,                                 outer_next, outer_prev,                                 boundary_next, boundary_prev,                                 patch_start, patch_end;  // cache for set_next_halfedge and vertex' set_halfedge  typedef add_face_ns::NextCacheEntryT<HalfedgeHandle> NextCacheEntry;  typedef std::vector<NextCacheEntry>                  NextCache;  NextCache    next_cache;  next_cache.reserve(3*n);  // don't allow degenerated faces  assert (n > 2);  // test for topological errors  for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)  {    if ( !is_boundary(_vertex_handles[i]) )    {      omerr() << "PolyMeshT::add_face: complex vertex\n";      return InvalidFaceHandle;    }    halfedge_handles[i] = find_halfedge(_vertex_handles[i],                                        _vertex_handles[ii]);    is_new[i] = !halfedge_handles[i].is_valid();    if (!is_new[i] && !is_boundary(halfedge_handles[i]))    {      omerr() << "PolyMeshT::add_face: complex edge\n";      return InvalidFaceHandle;    }  }  // re-link patches if necessary  for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)  {    if (!is_new[i] && !is_new[ii])    {      inner_prev = halfedge_handles[i];      inner_next = halfedge_handles[ii];      if (next_halfedge_handle(inner_prev) != inner_next)      {        // here comes the ugly part... we have to relink a whole patch        // search a free gap        // free gap will be between boundary_prev and boundary_next        outer_prev = opposite_halfedge_handle(inner_next);        outer_next = opposite_halfedge_handle(inner_prev);        boundary_prev = outer_prev;        do          boundary_prev =            opposite_halfedge_handle(next_halfedge_handle(boundary_prev));        while (!is_boundary(boundary_prev) || boundary_prev==inner_prev);        boundary_next = next_halfedge_handle(boundary_prev);        assert(is_boundary(boundary_prev));        assert(is_boundary(boundary_next));        // ok ?        if (boundary_next == inner_next)        {          omerr() << "PolyMeshT::add_face: patch re-linking failed\n";          return InvalidFaceHandle;        }        // other halfedges' handles        patch_start = next_halfedge_handle(inner_prev);        patch_end   = prev_halfedge_handle(inner_next);        // relink        next_cache.push_back(NextCacheEntry(boundary_prev, patch_start));        next_cache.push_back(NextCacheEntry(patch_end, boundary_next));        next_cache.push_back(NextCacheEntry(inner_prev, inner_next));      }    }  }  // create missing edges  for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)    if (is_new[i])      halfedge_handles[i] = new_edge(_vertex_handles[i], _vertex_handles[ii]);  // create the face  FaceHandle fh(This::new_face());  set_halfedge_handle(fh, halfedge_handles[n-1]);  // setup halfedges  for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)  {    vh         = _vertex_handles[ii];    inner_prev = halfedge_handles[i];    inner_next = halfedge_handles[ii];    id = 0;    if (is_new[i])  id |= 1;    if (is_new[ii]) id |= 2;    if (id)    {      outer_prev = opposite_halfedge_handle(inner_next);      outer_next = opposite_halfedge_handle(inner_prev);      // set outer links      switch (id)      {        case 1: // prev is new, next is old          boundary_prev = prev_halfedge_handle(inner_next);          next_cache.push_back(NextCacheEntry(boundary_prev, outer_next));          set_halfedge_handle(vh, outer_next);          break;        case 2: // next is new, prev is old          boundary_next = next_halfedge_handle(inner_prev);          next_cache.push_back(NextCacheEntry(outer_prev, boundary_next));          set_halfedge_handle(vh, boundary_next);          break;        case 3: // both are new          if (!halfedge_handle(vh).is_valid())          {            set_halfedge_handle(vh, outer_next);            next_cache.push_back(NextCacheEntry(outer_prev, outer_next));          }          else          {            boundary_next = halfedge_handle(vh);            boundary_prev = prev_halfedge_handle(boundary_next);            next_cache.push_back(NextCacheEntry(boundary_prev, outer_next));            next_cache.push_back(NextCacheEntry(outer_prev, boundary_next));          }          break;      }      // set inner link      next_cache.push_back(NextCacheEntry(inner_prev, inner_next));    }    else needs_adjust[ii] = (halfedge_handle(vh) == inner_next);    // set face handle    set_face_handle(halfedge_handles[i], fh);  }  // process next halfedge cache  typename NextCache::const_iterator    ncIt(next_cache.begin()), ncEnd(next_cache.end());  for (; ncIt != ncEnd; ++ncIt)    set_next_halfedge_handle(ncIt->first, ncIt->second);  // adjust vertices' halfedge handle  for (i=0; i<n; ++i)    if (needs_adjust[i])      adjust_outgoing_halfedge(_vertex_handles[i]);  return fh;}//-----------------------------------------------------------------------------#if OM_OUT_OF_CLASS_TEMPLATEtemplate <typename Kernel>template <typename OtherMesh>PolyMeshT<Kernel>&PolyMeshT<Kernel>::assign(const OtherMesh& _rhs)#  include "PolyMeshT_assign.hh"#endif//-----------------------------------------------------------------------------template <class Kernel>typename PolyMeshT<Kernel>::NormalPolyMeshT<Kernel>::calc_face_normal(FaceHandle _fh) const{  assert(halfedge_handle(_fh).is_valid());  ConstFaceVertexIter fv_it(cfv_iter(_fh));  const Point& p0(point(fv_it));  ++fv_it;  const Point& p1(point(fv_it));  ++fv_it;  const Point& p2(point(fv_it));  return calc_face_normal(p0, p1, p2);}//-----------------------------------------------------------------------------template <class Kernel>typename PolyMeshT<Kernel>::NormalPolyMeshT<Kernel>::calc_face_normal(const Point& _p0,		 const Point& _p1,		 const Point& _p2) const{#if 1  // The OpenSG <Vector>::operator -= () does not support the type Point  // as rhs. Therefore use vector_cast at this point!!!  // Note! OpenSG distinguishes between Normal and Point!!!  Normal p1p0(_p0);  p1p0 -= vector_cast<Normal>(_p1);  Normal p1p2(_p2);  p1p2 -= vector_cast<Normal>(_p1);  Normal n    = cross(p1p2, p1p0);  Scalar norm = n.length();  // The expression ((n *= (1.0/norm)),n) is used because the OpenSG  // vector class does not return self after component-wise  // self-multiplication with a scalar!!!  return (norm != Scalar(0)) ? ((n *= (Scalar(1)/norm)),n) : Normal(0,0,0);#else  Point p1p0 = _p0;  p1p0 -= _p1;  Point p1p2 = _p2;  p1p2 -= _p1;  Normal n = vector_cast<Normal>(cross(p1p2, p1p0));  Scalar norm = n.length();  return (norm != 0.0) ? n *= (1.0/norm) : Normal(0,0,0);#endif}//-----------------------------------------------------------------------------template <class Kernel>voidPolyMeshT<Kernel>::update_normals(VertexNormalMode _mode){  if (This::has_face_normals())    update_face_normals();  if (This::has_vertex_normals())  update_vertex_normals(_mode);}//-----------------------------------------------------------------------------template <class Kernel>voidPolyMeshT<Kernel>::update_face_normals(){  FaceIter f_it(faces_begin()), f_end(faces_end());  for (; f_it != f_end; ++f_it)    set_normal(f_it.handle(), calc_face_normal(f_it.handle()));}//-----------------------------------------------------------------------------template <class Kernel>typename PolyMeshT<Kernel>::NormalPolyMeshT<Kernel>::calc_vertex_normal(VertexHandle _vh) const{  Normal n;  calc_vertex_normal_fast(_vh,n);  return n;}//-----------------------------------------------------------------------------template <class Kernel_>void PolyMeshT<Kernel_>::calc_vertex_normal_fast(VertexHandle _vh, Normal& _n) const{  _n[0]=_n[1]=_n[2]=Scalar(0.0);  for (ConstVertexFaceIter vf_it=cvf_iter(_vh); vf_it; ++vf_it)    _n += normal(vf_it.handle());  Scalar norm = _n.length();  if (norm != 0.0f) _n *= (1.0f/norm);}

⌨️ 快捷键说明

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