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

📄 edge_collapse_impl.h

📁 很多二维 三维几何计算算法 C++ 类库
💻 H
📖 第 1 页 / 共 2 页
字号:
// Copyright (c) 2006 Fernando Luis Cacciola Carballal. All rights reserved.//// This file is part of CGAL (www.cgal.org); you may redistribute it under// the terms of the Q Public License version 1.0.// See the file LICENSE.QPL distributed with CGAL.//// Licensees holding a valid commercial license may use this file in// accordance with the commercial license agreement provided with the software.//// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.//// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.3-branch/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/Detail/Edge_collapse_impl.h $// $Id: Edge_collapse_impl.h 37267 2007-03-19 14:40:37Z fcacciola $//// Author(s)     : Fernando Cacciola <fernando_cacciola@ciudad.com.ar>//#ifndef CGAL_SURFACE_MESH_SIMPLIFICATION_DETAIL_EDGE_COLLAPSE_IMPL_H#define CGAL_SURFACE_MESH_SIMPLIFICATION_DETAIL_EDGE_COLLAPSE_IMPL_HCGAL_BEGIN_NAMESPACEnamespace Surface_mesh_simplification {template<class M,class SP, class VIM,class EIM,class EBM, class CF,class PF,class V>EdgeCollapse<M,SP,VIM,EIM,EBM,CF,PF,V>::EdgeCollapse( ECM&                    aSurface                                                    , ShouldStop       const& aShould_stop                                                    , VertexIndexMap   const& aVertex_index_map                                                     , EdgeIndexMap     const& aEdge_index_map                                                     , EdgeIsBorderMap  const& aEdge_is_border_map                                                     , GetCost          const& aGet_cost                                                    , GetPlacement     const& aGet_placement                                                    , VisitorT*               aVisitor                                                     )  :    mSurface           (aSurface)  ,Should_stop        (aShould_stop)   ,Vertex_index_map   (aVertex_index_map)  ,Edge_index_map     (aEdge_index_map)  ,Edge_is_border_map (aEdge_is_border_map)  ,Get_cost           (aGet_cost)  ,Get_placement      (aGet_placement)  ,Visitor            (aVisitor)  {  CGAL_ECMS_TRACE(0,"EdgeCollapse of ECM with " << (num_edges(aSurface)/2) << " edges" );     CGAL_ECMS_DEBUG_CODE ( mStep = 0 ; )  #ifdef CGAL_SURFACE_SIMPLIFICATION_ENABLE_TRACE    vertex_iterator vb, ve ;         for ( tie(vb,ve) = vertices(mSurface) ; vb != ve ; ++ vb )        CGAL_ECMS_TRACE(2, vertex_to_string(*vb) ) ;          undirected_edge_iterator eb, ee ;    for ( tie(eb,ee) = undirected_edges(mSurface); eb!=ee; ++eb )      CGAL_ECMS_TRACE(2, edge_to_string(*eb) ) ;#endif}template<class M,class SP, class VIM,class EIM,class EBM, class CF,class PF,class V>int EdgeCollapse<M,SP,VIM,EIM,EBM,CF,PF,V>::run(){  CGAL_SURF_SIMPL_TEST_assertion( mSurface.is_valid() && mSurface.is_pure_triangle() ) ;  if ( Visitor )    Visitor->OnStarted(mSurface);     // First collect all candidate edges in a PQ  Collect();     // Then proceed to collapse each edge in turn  Loop();  CGAL_ECMS_TRACE(0,"Finished: " << (mInitialEdgeCount - mCurrentEdgeCount) << " edges removed." ) ;  int r = (int)(mInitialEdgeCount - mCurrentEdgeCount) ;      if ( Visitor )    Visitor->OnFinished(mSurface);      return r ;}template<class M,class SP, class VIM,class EIM,class EBM, class CF,class PF,class V>void EdgeCollapse<M,SP,VIM,EIM,EBM,CF,PF,V>::Collect(){  CGAL_ECMS_TRACE(0,"Collecting edges...");  //  // Loop over all the _undirected_ edges in the surface putting them in the PQ  //    Equal_3 equal_points = Kernel().equal_3_object();      size_type lSize = num_edges(mSurface) / 2 ;    CGAL_SURF_SIMPL_TEST_assertion( ( lSize * 2 ) == mSurface.size_of_halfedges() ) ;  mInitialEdgeCount = mCurrentEdgeCount = lSize;    mEdgeDataArray.reset( new Edge_data[lSize] ) ;    mPQ.reset( new PQ (lSize, Compare_cost(this), Undirected_edge_id(this) ) ) ;    std::size_t id = 0 ;    CGAL_SURF_SIMPL_TEST_assertion_code ( size_type lInserted    = 0 ) ;  CGAL_SURF_SIMPL_TEST_assertion_code ( size_type lNotInserted = 0 ) ;  undirected_edge_iterator eb, ee ;  for ( tie(eb,ee) = undirected_edges(mSurface); eb!=ee; ++eb )  {    edge_descriptor lEdge = *eb ;      CGAL_assertion( get_directed_edge_id(lEdge) == id ) ;    CGAL_assertion( get_directed_edge_id(opposite_edge(lEdge,mSurface)) == id+1 ) ;    Profile const& lProfile = create_profile(lEdge);              if ( !equal_points(lProfile.p0(),lProfile.p1()) )    {      Edge_data& lData = get_data(lEdge);      lData.cost() = get_cost(lProfile) ;      insert_in_PQ(lEdge,lData);            if ( Visitor )        Visitor->OnCollected(lProfile                            ,lData.cost() #ifdef CGAL_TESTING_SURFACE_MESH_SIMPLIFICATION_USING_EXTENDED_VISITOR                            ,get_placement(lProfile) #endif                            );      CGAL_SURF_SIMPL_TEST_assertion_code ( ++ lInserted ) ;    }    else    {      CGAL_SURF_SIMPL_TEST_assertion_code ( ++ lNotInserted ) ;    }        CGAL_ECMS_TRACE(2,edge_to_string(lEdge));        id += 2 ;  }   CGAL_SURF_SIMPL_TEST_assertion ( lInserted + lNotInserted == mInitialEdgeCount ) ;  CGAL_ECMS_TRACE(0,"Initial edge count: " << mInitialEdgeCount ) ;}template<class M,class SP, class VIM,class EIM,class EBM, class CF,class PF,class V>void EdgeCollapse<M,SP,VIM,EIM,EBM,CF,PF,V>::Loop(){  CGAL_ECMS_TRACE(0,"Collapsing edges...") ;  CGAL_SURF_SIMPL_TEST_assertion_code ( size_type lLoop_watchdog = 0 ) ;  CGAL_SURF_SIMPL_TEST_assertion_code ( size_type lNonCollapsableCount = 0 ) ;  //  // Pops and processes each edge from the PQ  //  optional<edge_descriptor> lEdge ;  while ( (lEdge = pop_from_PQ()) )  {    CGAL_SURF_SIMPL_TEST_assertion ( lLoop_watchdog ++ < mInitialEdgeCount ) ;    CGAL_ECMS_TRACE(3,"Poped " << edge_to_string(*lEdge) ) ;        Profile const& lProfile = create_profile(*lEdge);          Cost_type lCost = get_data(*lEdge).cost();        if ( Visitor )      Visitor->OnSelected(lProfile,lCost,mInitialEdgeCount,mCurrentEdgeCount);          if ( lCost )     {      if ( Should_stop(*lCost,lProfile,mInitialEdgeCount,mCurrentEdgeCount) )      {        if ( Visitor )          Visitor->OnStopConditionReached(lProfile);                  CGAL_ECMS_TRACE(0,"Stop condition reached with InitialEdgeCount=" << mInitialEdgeCount                       << " CurrentEdgeCount=" << mCurrentEdgeCount                       << " Current Edge: " << edge_to_string(*lEdge)                       );        break ;      }              if ( Is_collapsable(lProfile) )      {        Collapse(lProfile);      }      else      {        CGAL_SURF_SIMPL_TEST_assertion_code ( lNonCollapsableCount++ ) ;        if ( Visitor )          Visitor->OnNonCollapsable(lProfile);                  CGAL_ECMS_TRACE(1,edge_to_string(*lEdge) << " NOT Collapsable"  );      }      }    else    {      CGAL_ECMS_TRACE(1,edge_to_string(*lEdge) << " uncomputable cost."  );    }  }  CGAL_SURF_SIMPL_TEST_assertion ( mCurrentEdgeCount = mSurface.size_of_halfedges() * 2 ) ;}template<class M,class SP, class VIM,class EIM,class EBM, class CF,class PF,class V>bool EdgeCollapse<M,SP,VIM,EIM,EBM,CF,PF,V>::is_border( const_vertex_descriptor const& aV ) const{  bool rR = false ;    const_in_edge_iterator eb, ee ;   for ( tie(eb,ee) = in_edges(aV,mSurface) ; eb != ee ; ++ eb )  {    const_edge_descriptor lEdge = *eb ;    if ( is_undirected_edge_a_border(lEdge) )    {      rR = true ;      break ;    }  }        return rR ;  }// Some edges are NOT collapsable: doing so would break the topological consistency of the mesh.// This function returns true if a edge 'p->q' can be collapsed.//// An edge p->q can be collapsed iff it satisfies the "link condition"// (as described in the "Mesh Optimization" article of Hoppe et al (1993))//// The link conidition is as follows: for every vertex 'k' adjacent to both 'p and 'q',// "p,k,q" is a facet of the mesh.//template<class M,class SP, class VIM,class EIM,class EBM, class CF,class PF,class V>bool EdgeCollapse<M,SP,VIM,EIM,EBM,CF,PF,V>::Is_collapsable( Profile const& aProfile ){  bool rR = true ;  CGAL_ECMS_TRACE(3,"Testing collapsabilty of p_q=V" << aProfile.v0()->id() << "(%" << aProfile.v0()->vertex_degree() << ")"                 << "->V" << aProfile.v1()->id() << "(%" << aProfile.v1()->vertex_degree() << ")"                  );                   CGAL_ECMS_TRACE(4, "is p_q border:" << aProfile.is_v0_v1_a_border() );  CGAL_ECMS_TRACE(4, "is q_q border:" << aProfile.is_v1_v0_a_border() );  out_edge_iterator eb1, ee1 ;   out_edge_iterator eb2, ee2 ;   CGAL_ECMS_TRACE(4,"  t=V" << aProfile.vL()->ID << "(%" << aProfile.vL()->vertex_degree() << ")" );  CGAL_ECMS_TRACE(4,"  b=V" << aProfile.vR()->ID << "(%" << aProfile.vR()->vertex_degree() << ")" );  // The following loop checks the link condition for v0_v1.  // Specifically, that for every vertex 'k' adjacent to both 'p and 'q', 'pkq' is a face of the mesh.  //   for ( tie(eb1,ee1) = out_edges(aProfile.v0(),mSurface) ; rR && eb1 != ee1 ; ++ eb1 )  {    edge_descriptor v0_k = *eb1 ;        if ( v0_k != aProfile.v0_v1() )    {      vertex_descriptor k = target(v0_k,mSurface);            for ( tie(eb2,ee2) = out_edges(k,mSurface) ; rR && eb2 != ee2 ; ++ eb2 )      {        edge_descriptor k_v1 = *eb2 ;        if ( target(k_v1,mSurface) == aProfile.v1() )        {          // At this point we know p-q-k are connected and we need to determine if this triangle is a face of the mesh.          //          // Since the mesh is known to be triangular there are at most two faces sharing the edge p-q.          //          // If p->q is NOT a border edge, the top face is p->q->t where t is target(next(p->q))          // If q->p is NOT a border edge, the bottom face is q->p->b where b is target(next(q->p))          //          // If k is either t or b then p-q-k *might* be a face of the mesh. It won't be if k==t but p->q is border          // or k==b but q->b is a border (because in that case even though there exists triangles p->q->t (or q->p->b)          // they are holes, not faces)          //                bool lIsFace =   ( aProfile.vL() == k && aProfile.left_face_exists () )                        || ( aProfile.vR() == k && aProfile.right_face_exists() ) ;                                  CGAL_SURF_SIMPL_TEST_assertion_code          (             if ( lIsFace )            {              // Is k_v1 the halfedge bounding the face 'k-v1-v0'?              if ( !k_v1->is_border() && k_v1->next()->vertex() == aProfile.v0() )              {                CGAL_SURF_SIMPL_TEST_assertion( !k_v1->is_border() ) ;                CGAL_SURF_SIMPL_TEST_assertion(  k_v1                ->vertex() == aProfile.v1() ) ;                CGAL_SURF_SIMPL_TEST_assertion(  k_v1->next()        ->vertex() == aProfile.v0() ) ;                CGAL_SURF_SIMPL_TEST_assertion(  k_v1->next()->next()->vertex() == k ) ;

⌨️ 快捷键说明

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