#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/boost/graph/copy_face_graph.h>
#include <CGAL/boost/graph/Face_filtered_graph.h>
#include<CGAL/Advancing_front_surface_reconstruction.h>
#include <CGAL/Polygon_mesh_processing/repair.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Surface_mesh<Kernel::Point_3> Mesh;
typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
// 参见 https://doc.cgal.org/latest/Advancing_front_surface_reconstruction/Advancing_front_surface_reconstruction_2reconstruction_fct_8cpp-example.html
struct Perimeter {
double bound;
Perimeter(double bound)
: bound(bound)
{}
template <typename AdvancingFront, typename Cell_handle>
double operator() (const AdvancingFront& adv, Cell_handle& c,
const int& index) const
{
// bound == 0 is better than bound < infinity
// as it avoids the distance computations
if (bound == 0) {
// smallest_radius_delaunay_sphere是指在给定的点集中,找到一个最小半径的球体,
// 该球体是 Delaunay 三角剖分的一部分。
return adv.smallest_radius_delaunay_sphere(c, index);
}
// If perimeter > bound, return infinity so that facet is not used
// 保证生成的facet的每条边长度都不超过bound
double d = 0;
d = sqrt(squared_distance(c->vertex((index + 1) % 4)->point(),
c->vertex((index + 2) % 4)->point()));
if (d > bound) return adv.infinity();
d += sqrt(squared_distance(c->vertex((index + 2) % 4)->point(),
c->vertex((index + 3) % 4)->point()));
if (d > bound) return adv.infinity();
d += sqrt(squared_distance(c->vertex((index + 1) % 4)->point(),
c->vertex((index + 3) % 4)->point()));
if (d > bound) return adv.infinity();
// Otherwise, return usual priority value: smallest radius of
// delaunay sphere
return adv.smallest_radius_delaunay_sphere(c, index);
}
};
bool is_small_hole(halfedge_descriptor h, Mesh& mesh,
double max_hole_diam, int max_num_hole_edges)
{
int num_hole_edges = 0;
CGAL::Bbox_3 hole_bbox;
for (halfedge_descriptor hc : CGAL::halfedges_around_face(h, mesh))
{
const Point& p = mesh.point(target(hc, mesh));
hole_bbox += p.bbox();
++num_hole_edges;
// Exit early, to avoid unnecessary traversal of large holes
if (num_hole_edges > max_num_hole_edges) return false;
if (hole_bbox.xmax() - hole_bbox.xmin() > max_hole_diam) return false;
if (hole_bbox.ymax() - hole_bbox.ymin() > max_hole_diam) return false;
if (hole_bbox.zmax() - hole_bbox.zmin() > max_hole_diam) return false;
}
return true;
}
int main()
{
std::vector<Kernel::Point_3> result; // 【输入】类柱面(管状)点云
...
typedef std::array<std::size_t, 3> Facet; // Triple of indices
std::vector<Facet> facets;
Perimeter perimeter(5.0); // 生成的面片应满足任意edge长度不超过5.0
CGAL::advancing_front_surface_reconstruction(result.begin(),
result.end(),
std::back_inserter(facets), perimeter);
// copy points for random access
std::vector<Point> vertices;
vertices.reserve(points.size());
std::copy(result.begin(), result.end(), std::back_inserter(vertices));
CGAL::Surface_mesh<Point> output_mesh;
CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(vertices, facets, output_mesh);
// 以下两个参数用于筛选出mesh中符合条件的边缘
double max_hole_diam = 1000.0; // 某一端闭合边缘最大半径
int max_num_hole_edges = 1000; // 某一端闭合边缘最多包含的Edge数量
std::vector<halfedge_descriptor> border_cycles;
// collect one halfedge per boundary cycle
PMP::extract_boundary_cycles(output_mesh, std::back_inserter(border_cycles));
for (halfedge_descriptor h : border_cycles)
{
if (max_hole_diam > 0 && max_num_hole_edges > 0 &&
!is_small_hole(h, output_mesh, max_hole_diam, max_num_hole_edges))
continue;
PMP::triangulate_hole(output_mesh, h);
}
// 【输出】
std::ofstream f("out_af.off");
f << output_mesh;
f.close();
...
}
标签:std,封口,return,CGAL,bound,mesh,max,点云,hole
From: https://blog.csdn.net/xmyzqs1212/article/details/142815425