向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) 编辑 收藏 举报