向CGAL的Polyhedron_3中添加访问一环邻域顶点功能

CGAL的Polyhedron_3缺省情况下不直接提供遍历一环顶点的功能,而这又是一个比较常用的操作。因此考虑通过扩展顶点和Polyhedron_3来实现这个功能。其实我实在是刚刚接触CGAL,谢谢学习过程中群里天堂序曲的帮助。希望路过的朋友们发现错误的话,帮忙指出来,谢谢大家了。

如果把模板参数写全的话(实际上还省略了一个),声明一个Polyhedron对象是这样的:Polyhedron_3<Traits, CGAL::Polyhedron_items_3, CGAL::HalfedgeDS_default> Polyhedron;

一个Polyhedron所使用的底层的顶点、面和半边的类型实际上是由Polyhedron_3的模板参数中的Polyhedron_items_3封装的。因此在扩展顶点、面或边的时候还要相应的修改这个items封装类。

首先扩展顶点类,其中的OutputOneRingNeighbours函数只是为了测试用:

template<class Refs, class Point>
class Enhanced_Vertex : public CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, Point>
{
private:
    std::list<Enhanced_Vertex> m_OneRingNeighbours;
public:
    Enhanced_Vertex(){}
    ~Enhanced_Vertex(){}
    //重要!非默认构造函数必须提供,否则编译器不知道怎样用Point<R_>构造一个Enhanced_Vertex对象
    //会产生cannot convert parameter 1 from 'const CGAL::Point_3<R_>' to 'const My_vertex<Refs,P> & 这样的错误
    //所以在扩展的时候必须提供非默认构造函数,告诉编译器怎样使用Point
    Enhanced_Vertex(const Point & pt):CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, Point>(pt){}
    std::list<Enhanced_Vertex> & OneRingNeighbours(){ return m_OneRingNeighbours; }
    void OutputOneRingNeighbours()
    {
        std::list<Enhanced_Vertex>::iterator it;
        for(it = m_OneRingNeighbours.begin(); it != m_OneRingNeighbours.end(); ++it)
        {
            std::cout<<it->point()<<std::endl;
        }
    }
};

然后在items封装类里进行相应修改:

struct Enhanced_Items : public CGAL::Polyhedron_items_3
{
    template<class Refs, class Traits>
    struct Vertex_wrapper
    {
        typedef typename Traits::Point_3 Point;
        typedef Enhanced_Vertex<Refs, Point> Vertex;
    };
};

这个时候顶点只是具有了存储其一环邻域顶点的功能。获取一环顶点的功能我是通过扩展Polyhedron_3来添加的,也可以通过Functor或者直接在顶点类里添加。

template<class traits, class items>
class Enhanced_Polyhedron_3 : public CGAL::Polyhedron_3<traits, items>
{
public:
    typedef typename Halfedge_around_vertex_circulator HV_circulator;
private:
 
public:
    void GetOneRingNeighbourVertices()
    {
        HV_circulator pHalfedge,temp;
        for(Vertex_iterator it = vertices_begin(); it != vertices_end(); ++it)
        {
            pHalfedge = it->vertex_begin();
            temp = pHalfedge;
            CGAL_For_all(pHalfedge, temp)
            {
                (it->OneRingNeighbours()).push_back(*(pHalfedge->opposite()->vertex()));
            }
        }
    }
};

下面是测试程序,只输出了一个顶点的一环邻域:

int _tmain(int argc, _TCHAR* argv[])
{
    typedef CGAL::Simple_cartesian<double> Kernel;
    typedef Enhanced_Polyhedron_3<Kernel,Enhanced_Items> Mesh;
    typedef Mesh::Vertex_iterator Vertex_iterator;
    std::string filepath = "F:\\3DModels\\cube\\cube_r.off";
    std::ifstream file(filepath);
    Mesh somemesh;
    file>>somemesh;
    somemesh.GetOneRingNeighbourVertices();
    Vertex_iterator it = somemesh.vertices_begin();
    std::cout<<"current vertex: "<<it->point()<<std::endl;
    it->OutputOneRingNeighbours();
    system("pause");
    return 0;
}

关于扩展过程中模板参数的讨论:

模板参数可以根据具体的需要添加。比如顶点类默认的模板参数可能是Refs和Point,在需要添加法向量的时候,如果法向量想使用Polyhedron的Traits类中的某种类型,则可以添加一个法向量类型的模板参数:

template <class Refs, class Point, class Normal>
class Enriched_vertex : public CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, Point>
{
public:
    typedef typename N Normal;
    ...
private:
    Normal m_normal;
    ...
public:
    Enriched_vertex(){}
    // repeat mandatory constructors
    Enriched_vertex(const P& pt) : CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, Point>(pt)
    {
    }
 
    // normal
    Normal&    normal() { return    m_normal;    }
    const    Normal&    normal() const { return    m_normal;    }
    ...
};

模板参数的特化实际也是在items封装类里进行的:

struct Enriched_items : public CGAL::Polyhedron_items_3
{
    // wrap    vertex
    template <class Refs, class Traits>
    struct Vertex_wrapper
    {
        typedef typename Traits::Vector_3 Normal;
        typedef Enriched_vertex<Refs, Point, Normal> Vertex;
    };
    ...
};

posted on 2012-04-24 08:20  youthlion  阅读(2086)  评论(0编辑  收藏  举报

导航