CGAL 5.6 - Surface Mesh: User Manual
Surface_mesh 类是半边数据结构的实现,可用来表示多面体表面。它是半边数据结构(Halfedge Data Structures)和三维多面体表面(3D Polyhedral Surface)这两个 CGAL 软件包的替代品。其主要区别在于它是基于索引的,而不是基于指针的。此外,向顶点、半边、边和面添加信息的机制要简单得多,而且是在运行时而不是编译时完成的。
由于数据结构使用整数索引作为顶点、半边、边和面的描述符,因此它的内存占用比基于指针的 64 位版本更少。由于索引是连续的,因此可用作存储属性的向量索引。
当元素被移除时,它们只会被标记为已移除,必须调用垃圾回收函数才能真正移除它们。
Surface_mesh 提供了四个嵌套类,分别代表半边数据结构的基本元素:Surface_mesh::Vertex_index曲面网格::顶点索引
Surface_mesh::Halfedge_index曲面网格::半边索引
Surface_mesh::Face_index曲面网格::面索引
Surface_mesh::Edge_index曲面网格::边索引
1、新建Surface_mesh结构
cpp
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
typedef CGAL::Simple_cartesian<double> K;
typedef CGAL::Surface_mesh<K::Point_3> Mesh; //mesh结构
typedef Mesh::Vertex_index vertex_descriptor;
typedef Mesh::Face_index face_descriptor;
int main()
{
Mesh m;
// Add the points as vertices
vertex_descriptor u = m.add_vertex(K::Point_3(0, 1, 0));
vertex_descriptor v = m.add_vertex(K::Point_3(0, 0, 0));
vertex_descriptor w = m.add_vertex(K::Point_3(1, 1, 0));
m.add_face(u, v, w);
int num = num_faces(m); //结果num = 1
return 0;
}
2、自相交判断
在很多算法中,对于输入的Mesh都要求是非自相交的模型。现在来检查以下上述模型是否自相交
cpp
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/self_intersections.h>
typedef CGAL::Simple_cartesian<double> K;
typedef CGAL::Surface_mesh<K::Point_3> Mesh; //mesh结构
typedef Mesh::Vertex_index vertex_descriptor;
typedef Mesh::Face_index face_descriptor;
int main()
{
Mesh m;
// Add the points as vertices
vertex_descriptor u = m.add_vertex(K::Point_3(0, 1, 0));
vertex_descriptor v = m.add_vertex(K::Point_3(0, 0, 0));
vertex_descriptor w = m.add_vertex(K::Point_3(1, 1, 0));
vertex_descriptor x = m.add_vertex(K::Point_3(1, 0, 0));
m.add_face(u, v, w);
int num = num_faces(m); //结果num = 1
face_descriptor f = m.add_face(u, v, x);
if (f == Mesh::null_face())
{
std::cerr << "The face could not be added because of an orientation error." << std::endl;
//结果intersect = true; 即当前模型为自相交模型
bool intersect = CGAL::Polygon_mesh_processing::does_self_intersect(m);
std::cout << "intersect:"<< intersect << std::endl;
assert(f != Mesh::null_face());
f = m.add_face(u, x, v);
num = num_faces(m);
//结果intersect = true; 即当前模型为自相交模型
intersect = CGAL::Polygon_mesh_processing::does_self_intersect(m);
std::cout << "intersect:" << intersect << std::endl;
assert(f != Mesh::null_face());
}
std::cout << num << std::endl;
return 0;
}
3、获取Surface_Mesh的所有点
cpp
#include <vector>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
typedef CGAL::Simple_cartesian<double> K;
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
typedef Mesh::Vertex_index vertex_descriptor;
typedef Mesh::Face_index face_descriptor;
int main()
{
Mesh m;
// u x
// +------------+
// | |
// | |
// | f |
// | |
// | |
// +------------+
// v w
// Add the points as vertices
vertex_descriptor u = m.add_vertex(K::Point_3(0, 1, 0));
vertex_descriptor v = m.add_vertex(K::Point_3(0, 0, 0));
vertex_descriptor w = m.add_vertex(K::Point_3(1, 0, 0));
vertex_descriptor x = m.add_vertex(K::Point_3(1, 1, 0));
/* face_descriptor f = */ m.add_face(u, v, w, x);
{
std::cout << "all vertices " << std::endl;
// The vertex iterator type is a nested type of the Vertex_range
Mesh::Vertex_range::iterator vb, ve;
Mesh::Vertex_range r = m.vertices();
// The iterators can be accessed through the C++ range API
vb = r.begin();
ve = r.end();
// or with boost::tie, as the CGAL range derives from std::pair
for (boost::tie(vb, ve) = m.vertices(); vb != ve; ++vb) {
std::cout << *vb << std::endl;
}
// Instead of the classical for loop one can use
// the boost macro for a range
for (vertex_descriptor vd : m.vertices()) {
std::cout << vd << std::endl;
}
}
return 0;
}
4、获取Surface_Mesh点、边、面的关联点
cpp
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
#include <vector>
typedef CGAL::Simple_cartesian<double> K;
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
typedef Mesh::Vertex_index vertex_descriptor;
typedef Mesh::Face_index face_descriptor;
int main()
{
Mesh m;
// u x
// +------------+
// | |
// | |
// | f |
// | |
// | |
// +------------+
// v w
// Add the points as vertices
vertex_descriptor u = m.add_vertex(K::Point_3(0, 1, 0));
vertex_descriptor v = m.add_vertex(K::Point_3(0, 0, 0));
vertex_descriptor w = m.add_vertex(K::Point_3(1, 0, 0));
vertex_descriptor x = m.add_vertex(K::Point_3(1, 1, 0));
face_descriptor f = m.add_face(u, v, w, x);
{
std::cout << "vertices around vertex " << v << std::endl;
CGAL::Vertex_around_target_circulator<Mesh> vbegin(m.halfedge(v), m), done(vbegin);
do {
std::cout << *vbegin++ << std::endl;
} while (vbegin != done);
}
{
std::cout << "vertices around face " << f << std::endl;
CGAL::Vertex_around_face_iterator<Mesh> vbegin, vend;
for (boost::tie(vbegin, vend) = vertices_around_face(m.halfedge(f), m);
vbegin != vend;
++vbegin) {
std::cout << *vbegin << std::endl;
}
}
std::cout << "=====" << std::endl;
// or the same again, but directly with a range based loop
for (vertex_descriptor vd : vertices_around_face(m.halfedge(f), m)) {
std::cout << vd << std::endl;
}
return 0;
}