zoukankan      html  css  js  c++  java
  • 利用CGAL对网格填洞( Filling holes)

    CGAL的资料尤其是中文资料少之又少,现根据自己要完成的工作进行一个记录和总结,也希望能填补资料的空缺。

    在CGAL中,使用半边结构Halfedge Data Structure来存储网格信息,另外一个类似于CGAL的库OpenMesh同样使用的是这种半边结构。

    关于半边结构,请点这里:http://www.flipcode.com/archives/The_Half-Edge_Data_Structure.shtml

    CGAL内部通过三层结构(Polyhedron Layer、Halfedge data structure Layer、Items Layer)实现半边结构,如图所示:

    hds_design_col.png

    Polyehdron Layer 提供了易用的借口,我们可以通过Halfedge_Handle 、 Facet_Handle、 Vertex_Handle及对应的迭代器Iterator来进行访问、遍历及更新数据。同时也可以通过一些简单的成员函数进行欧拉操作(Euler Operations)等。

    Items Layer 负责存储底层的数据,包括顶点Vertex、Halfedge、Face的信息。

    中间层Halfedge_data_structure Layer负责组织和管理Items Layer的信息,内部使用双向链表(bidirectional list)或者容器(vector)来实现。

    在CGAL的Include目录里有一个undocumented头文件:triangulate_polyhedron.h,顾名思义这个头文件的作用是对多面体进行三角化的。

    通过这个库文件引用的头文件可以看得出CGAL是通过Triangulation_2_filtered_projection_traits_3.h将三维坐标点映射到二维平面上,再通过Constrained_Delaunay_triangulation_2.h对其进行三角化,随后通过HalfedgeDS_decorator.h对原多面体进行三角化。

    我将此库文件进行重新注释解读如下:

    // Copyright (c) 2010-2011  GeometryFactory Sarl (France).
    // All rights reserved.
    //
    // This file is part of CGAL (www.cgal.org).
    // You can redistribute it and/or modify it under the terms of the GNU
    // General Public License as published by the Free Software Foundation,
    // either version 3 of the License, or (at your option) any later version.
    //
    // 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$
    // $Id$
    //
    //
    // Author(s)     : Laurent Rineau
    
    #ifndef CGAL_TRIANGULATE_POLYHEDRON_H
    
    #include <CGAL/Modifier_base.h>
    #include <CGAL/HalfedgeDS_decorator.h>
    
    #include <CGAL/Triangulation_vertex_base_with_info_2.h>
    #include <CGAL/Triangulation_face_base_with_info_2.h>
    #include <CGAL/Constrained_Delaunay_triangulation_2.h>
    #include <CGAL/Constrained_triangulation_plus_2.h>
    #include <CGAL/Triangulation_2_filtered_projection_traits_3.h>
    
    #include <CGAL/internal/Operations_on_polyhedra/compute_normal.h>
    
    #include <queue>
    #include <vector>
    #include <utility>
    
    namespace CGAL {
    
    template <class Polyhedron>
    class Triangulate_modifier
      : public CGAL::Modifier_base<typename Polyhedron::HalfedgeDS> 
    {
      typedef typename Polyhedron::HalfedgeDS HDS;
      typedef typename Polyhedron::Traits Traits;
    
      typedef typename Polyhedron::Halfedge_handle Halfedge_handle;
      typedef typename Polyhedron::Facet Facet;
      typedef typename Polyhedron::Facet_iterator Facet_iterator;
      typedef typename Polyhedron::Facet_handle Facet_handle;
    
      typedef CGAL::Triangulation_2_filtered_projection_traits_3<Traits>   P_traits;
    
      typedef CGAL::Triangulation_vertex_base_with_info_2<Halfedge_handle,
                                                          P_traits>        Vb;
    
      struct Face_info {
        typename Polyhedron::Halfedge_handle e[3];
        bool is_external;
      };
    
      typedef CGAL::Triangulation_face_base_with_info_2<Face_info,
                                                        P_traits>          Fb1;
    
      typedef CGAL::Constrained_triangulation_face_base_2<P_traits, Fb1>   Fb;
      typedef CGAL::Triangulation_data_structure_2<Vb,Fb>                  TDS;
      typedef CGAL::No_intersection_tag                                    Itag;
      typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits,
                                                         TDS,
                                                         Itag>             CDTbase;
      typedef CGAL::Constrained_triangulation_plus_2<CDTbase>              CDT;
    
    public:
      Triangulate_modifier() 
      {
      }    
    
      bool is_external(typename CDT::Face_handle fh) const {
        return fh->info().is_external;
      }
    
      void operator()(HDS& hds) {
        CGAL::HalfedgeDS_decorator<HDS> decorator(hds);
        typedef typename HDS::Halfedge Halfedge;
    
           // 存储多面体所有的facets
           // 在modifier的过程中,facets list 会被修改,所以必须先存储到vector里
        std::vector<Facet_handle> facets;
        facets.reserve(hds.size_of_faces());
        for(Facet_iterator 
              fit = hds.faces_begin(),
              end = hds.faces_end();
            fit != end; ++fit) {
          facets.push_back(fit);
        }
        
            // 对多面体进行三角化的总循环 ( Main Loop )
            
        for(typename std::vector<Facet_handle>::iterator 
              fit_it = facets.begin(),
              end = facets.end();
            fit_it != end; ++fit_it)
        {
          Facet_handle fit = *fit_it;
          // 计算所有面的法向量normal ( normal of each facet )
          typename Traits::Vector_3 normal = 
            compute_facet_normal<Facet,Traits>(*fit);
                
                // 定义 constrained delaunay triangulation ( 沿着normal降维 Projection_Traits )
          P_traits cdt_traits(normal);
          CDT cdt(cdt_traits);
    
                // Halfedge_around_facet_circulator意为circulator of halfedges around a facet (ccw = counterclockwise)
                // 即沿着facet以逆时针方向遍历一边halfedge 
          typename Facet::Halfedge_around_facet_circulator 
            he_circ = fit->facet_begin(),
            he_circ_end(he_circ);
          // 定义两个CDT Vertex_handle ,分别为previous和first
          typename CDT::Vertex_handle previous, first;
          // 将facet上的所有顶点( vertex )指向的三维点 ( point() ) 插入进cdt中
          // 因为cdt在之前已经定义过为Projection_traits,所以直接转化为二维坐标
          do {
            typename CDT::Vertex_handle vh = cdt.insert(he_circ->vertex()->point());
            if(first == 0) {
              first = vh;
            }
            vh->info() = he_circ;
            if(previous != 0 && previous != vh) {
              cdt.insert_constraint(previous, vh);
            }
            previous = vh;
          } while( ++he_circ != he_circ_end );
          // cdt insert constraint 
          cdt.insert_constraint(previous, first);
    
          // sets mark is_external
          // 检测是否为external面
          for(typename CDT::All_faces_iterator
                fit = cdt.all_faces_begin(),
                end = cdt.all_faces_end();
              fit != end; ++fit)
          {
            fit->info().is_external = false;
          }
          std::queue<typename CDT::Face_handle> face_queue;
          face_queue.push(cdt.infinite_vertex()->face());
          while(! face_queue.empty() ) {
            typename CDT::Face_handle fh = face_queue.front();
            face_queue.pop();
            if(fh->info().is_external) continue;
            fh->info().is_external = true;
            for(int i = 0; i <3; ++i) {
              if(!cdt.is_constrained(std::make_pair(fh, i)))
              {
                face_queue.push(fh->neighbor(i));
              }
            }
          }
                // 开始对多面体进行三角化( 循环到的这个facet )
            // 首先将这个面变成hole
          decorator.make_hole(fit->halfedge());
          for(typename CDT::Finite_edges_iterator
                eit = cdt.finite_edges_begin(),
                end = cdt.finite_edges_end();
              eit != end; ++eit)
          {
            typename CDT::Face_handle fh = eit->first;
            const int index = eit->second;
            typename CDT::Face_handle opposite_fh = fh->neighbor(eit->second);
            const int opposite_index = opposite_fh->index(fh);
            const typename CDT::Vertex_handle va = fh->vertex(cdt. cw(index));
            const typename CDT::Vertex_handle vb = fh->vertex(cdt.ccw(index));
    
            if( ! (is_external(fh) && is_external(opposite_fh)) && 
                ! cdt.is_constrained(*eit) ) 
            {
              // strictly internal edge
              Halfedge_handle h = hds.edges_push_back(Halfedge(),
                                                      Halfedge());
              fh->info().e[index] = h;
              opposite_fh->info().e[opposite_index] = h->opposite();
    
              decorator.set_vertex(h, va->info()->vertex());
              decorator.set_vertex(h->opposite(), vb->info()->vertex());
            }
            if( cdt.is_constrained(*eit) )
            {
              if(!is_external(fh)) {
                fh->info().e[index] = va->info();
              }
              if(!is_external(opposite_fh)) {
                opposite_fh->info().e[opposite_index] = vb->info();
              }
            }
          }
          for(typename CDT::Finite_faces_iterator
                fit = cdt.finite_faces_begin(),
                end = cdt.finite_faces_end();
              fit != end; ++fit)
          {
            if(!is_external(fit)) 
            {
              Halfedge_handle h0 = fit->info().e[0];
              Halfedge_handle h1 = fit->info().e[1];
              Halfedge_handle h2 = fit->info().e[2];
              CGAL_assertion( h0 != Halfedge_handle() );
              CGAL_assertion( h1 != Halfedge_handle() );
              CGAL_assertion( h2 != Halfedge_handle() );
    
              typedef typename Halfedge::Base HBase;
              h0->HBase::set_next(h1);
              decorator.set_prev(h1, h0);
              h1->HBase::set_next(h2);
              decorator.set_prev(h2, h1);
              h2->HBase::set_next(h0);
              decorator.set_prev(h0, h2);
    
              decorator.fill_hole(h0);        
            }
          }
        } // end loop on facets of the input polyhedron
      }
    }; // end class Triangulate_modifier
    
    template <typename Polyhedron>
    void triangulate_polyhedron(Polyhedron& p)
    {
      CGAL::Triangulate_modifier<Polyhedron> modifier;
      p.delegate(modifier);
    }
    
    } // end namespace CGAL
    
    #endif // CGAL_TRIANGULATE_POLYHEDRON_H
  • 相关阅读:
    sourceTree和eclipse 的使用
    oracle习题练习
    oracle详解
    单例模式
    反射详解
    Oracle 存储过程判断语句正确写法和时间查询方法
    MVC4 Jqgrid设计与实现
    遇到不支持的 Oracle 数据类型 USERDEFINED
    ArcGIS Server10.1 动态图层服务
    VS2010连接Oracle配置
  • 原文地址:https://www.cnblogs.com/jast/p/4253081.html
Copyright © 2011-2022 走看看