官方文档:Polygon_mesh_processing Silcer 本文代码:Mesh_slicer.cpp
The CGAL::Polygon_mesh_slicer is an operator that intersects a triangle surface mesh with a plane. It records the intersection as a set of polylines since the intersection can be made of more than one connected component. The degenerate case where the intersection is a single point is handled.
Polygon_mesh_slicer是一个将三角形表面网格与平面相交的运算符。在CGAL中,此相交的计算结果为一组折线
- 因为交集可能由多个连通组件组成,所以CGAL没有帮你闭合成面,保留原始的相交结果,即折线集
- 本算法会处理相交结果退化成单点的情况
Figure 66.15 shows the polylines returned by the slicing operation for a triangle mesh and a set of parallel planes.
在左图中,蓝色物体是一个三角形表面网格。我们用多组平面与它相交,得到右图的结果。在右图中,可以看到蓝色物体被切割成了多组折线集。
- 这些平面在图中并未画出,从右图结果可知,这些平面从左到右相隔一定距离排序,并且它们是相互平行的
- 黄色物体只是为了叠加对比,没有被切片。
Figure 66.15 Slicing a mesh. A triangle mesh (left) and the polylines computed by the mesh slicer by intersecting a set of parallel planes (right).
官方示例
void Sample(const std::string& filename)
{
//将filename读取成Mesh
Mesh mesh;
if (!PMP::IO::read_polygon_mesh(filename, mesh) || is_empty(mesh) || !is_triangle_mesh(mesh))
{
std::cerr << "Invalid input." << std::endl;
return;
}
//
//用Mesh构造出切片器
//
CGAL::Polygon_mesh_slicer<Mesh, K> slicer(mesh);
Polylines polylines; //切片结果是一个线集
//用一个平面进行切片,获得线集
slicer(K::Plane_3(0, 0, 1, -0.4), std::back_inserter(polylines));
std::cout << "At z = 0.4, the slicer intersects " << polylines.size() << " polylines" << std::endl;
polylines.clear();
//用一个平面进行切片,获得线集
slicer(K::Plane_3(0, 0, 1, 0.2), std::back_inserter(polylines));
std::cout << "At z = -0.2, the slicer intersects " << polylines.size() << " polylines" << std::endl;
polylines.clear();
//
//使用AABB_tree加速
//
AABB_tree tree(edges(mesh).first, edges(mesh).second, mesh);
CGAL::Polygon_mesh_slicer<Mesh, K> slicer_aabb(mesh, tree);
slicer_aabb(K::Plane_3(0, 0, 1, -0.4), std::back_inserter(polylines));
std::cout << "At z = 0.4, the slicer intersects " << polylines.size() << " polylines" << std::endl;
polylines.clear();
}
性能测试代码:按某个间隔多次切片
void PerformanceTest(const std::string& filename, double interval, const std::string& out_dir)
{
Mesh mesh;
if (!PMP::IO::read_polygon_mesh(filename, mesh) || is_empty(mesh) || !is_triangle_mesh(mesh))
{
std::cerr << "Invalid input." << std::endl;
return;
}
//构造切片器
AABB_tree tree(edges(mesh).first, edges(mesh).second, mesh);
CGAL::Polygon_mesh_slicer<Mesh, K> slicer_aabb(mesh, tree);
Polylines polylines; //切片结果是一个线集
CGAL::Bbox_3 bbox = CGAL::bbox_3(mesh.points().begin(), mesh.points().end());
const double z_range = bbox.max(2) - bbox.min(2);
int size = static_cast<int>(z_range / interval + 0.5);
CGAL::Timer t;
t.start();
//切片
for (int i{0}; i < size; ++i)
{
double z = bbox.min(2) + i * interval;
slicer_aabb(K::Plane_3(0, 0, 1, z), std::back_inserter(polylines));
std::cout << "At z = " << z << ", the slicer intersects " << polylines.size() << " polylines" << std::endl;
ObjIOPlugin::PolylinesToObj(polylines, out_dir + "polylines" + std::to_string(i));
polylines.clear();
}
std::cout << "z的间隔范围" << interval << std::endl;
std::cout << "切片次数:" << size << std::endl;
std::cout << t.time() << " 秒." << std::endl;
}
测试数据
单体三角网
这个是一个石头模型(单体),是一个三角网。间隔为0.05,构造出多组与XOY面平行的切面
性能
- 模型:石头
- 顶点个数98;面片个数192
- 切片个数:756
- 计算时间:0.774秒
有空洞的三角网
用Meshlab将石头模型的三角网删掉一些,人为制造孔洞。然后,以间隔为0.5,构造出多组与XOY面平行的切面
结果显示,CGAL的切片支持有空洞的三角网。
复杂三角网(多个连通组件)
测试数据:半架飞机
测试:从zMin到zMax构造多个与XOY平行的切面,只有三四个平面有结果,其他平面都切不出结果
还没有找到原因