简述思路
借助CGAL几何库,分为以下步骤:
1. 借助CGAL中Constrained_Delaunay_triangulation_2这个类,这个类实际就是处理限制剖分的
2. 把曲面转为曲面为surface mesh类型,因为要polygon processing接口,其他格式可以用copy_face_graph转换;但是限制剖分需要通过标记限制区域进行曲面的复制
2. 利用mark_domain_in_triangulation进行区域标记,这应该是5.6新出的函数,5.5的时候例子里面有但没有在源码里面
问题
- 实际上Constrained_Delaunay_triangulation_2类进行限制剖分的时候根据实验无法自动添加与边界的交点,这导致了产生的三角面出现共面或退化的概率大大增加,这个需要自动处理(处理方法为求出交点重新生成新边界或者改进CCGAL提供的限制剖分算法)
- 删除面的时候用remove_face而不是先expand_face_selection_for_removal+CGAL::Euler::remove_face是因为不希望进行优化处理
- 对于其他的限制是一样的,只要不是封闭边界其实都可以按照点来处理直接insert
- 限制剖分的原理其实就是检测边界,优先处理边界,之后就是满足三角剖分的条件
接口原型
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
#include <CGAL/Vector_3.h>
#include <CGAL/Surface_mesh.h>
//Constrained_Delaunay
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
#include <CGAL/mark_domain_in_triangulation.h>
//copy_face_graph复制用的
#include <CGAL/boost/graph/copy_face_graph.h>
#include <CGAL/boost/graph/graph_traits_Constrained_Delaunay_triangulation_2.h>
#include <CGAL/boost/graph/graph_traits_Constrained_triangulation_2.h>
#include <CGAL/boost/graph/graph_traits_Constrained_triangulation_plus_2.h>
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Projection_traits = CGAL::Projection_traits_xy_3<Kernel>;
using Point_3 = Kernel::Point_3;
using Mesh = CGAL::Surface_mesh<Kernel::Point_3>;
using Polyline3D = std::vector<Point_3>;
using Polyline3Ds = std::vector<Polyline3D>;
using TIN = CGAL::Constrained_Delaunay_triangulation_2<Projection_traits/*, CGAL::Default, Itag*/>;
/// <summary>
/// 对限制剖分曲面进行复制
/// </summary>
/// <param name="tin">用于剖分的曲面类型分工不同都是DCEL结构</param>
/// <param name="mesh">surface mesh类型曲面,主要用于曲面处理</param>
void Constrained_CopyGraph(TIN& tin, Mesh& GenratedMesh);
/// <summary>
/// 内外边界限制剖分
/// </summary>
/// <param name="pset">剖分点集</param>
/// <param name="OuterBoundary">外边界</param>
/// <param name="InnerBoundaries">内边界集</param>
/// <param name="GenratedMesh">生成的mesh</param>
void ConstrainedTrigulation(Point_set& pset, Polyline3D& OuterBoundary,Polyline3Ds& InnerBoundaries,Mesh& GenratedMesh);
代码
void ConstrainedTrigulation(Point_set& pset, Polyline3D& OuterBoundary,Polyline3Ds& InnerBoundaries,Mesh& GenratedMesh)
{
typedef TIN::Face_handle Face_handle;
typedef boost::associative_property_map< std::unordered_map<Face_handle, bool> > MarkFaceInfo;
//删除边界以外的面
std::unordered_map<Face_handle, bool> in_domain_map;
MarkFaceInfo in_domain(in_domain_map);
//Mark facets that are inside the domain bounded by the polygon
CGAL::mark_domain_in_triangulation(tin, in_domain);
std::set<Mesh::Face_index> face_selection;
Mesh::Property_map<Mesh::Face_index, bool> face_selection_map
= mesh.add_property_map<Mesh::Face_index, bool>("is_selected", false).first;
CGAL::copy_face_graph(tin, mesh,
CGAL::parameters::face_to_face_output_iterator
(boost::make_function_output_iterator
([&](const std::pair<Face_handle, Mesh::Face_index>& ff)
{
if (!get(in_domain, ff.first))
{
//face_selection_map[ff.second] = true;
face_selection.insert(ff.second);
}
}
)));
//用于删除时优化的代码
// CGAL::expand_face_selection_for_removal(face_selection, mesh, face_selection_map);
// face_selection.clear();
// for (Mesh::Face_index fi : faces(mesh))
// if (face_selection_map[fi])
// face_selection.insert(fi);
// //std::cerr << face_selection.size() << " face(s) are selected for removal after expansion" << std::endl;
// for (Mesh::Face_index fi : face_selection)
// CGAL::Euler::remove_face(halfedge(fi, mesh), mesh);
for (Mesh::Face_index fi : face_selection)
{
mesh.remove_face(fi);
}
//mesh的gc,一般删除或各种处理的时候collect_garbage便于信息更新和实际删除
mesh.collect_garbage();
}
void ConstrainedTrigulation(Point_set& pset, Polyline3D& OuterBoundary,Polyline3Ds& InnerBoundaries,Mesh& GenratedMesh)
{
TIN tin;
tin.insert(pset.points().begin(), pset.points().end());
tin.insert_constraint(OuterBoundary.begin(), OuterBoundary.end(), true);
for (auto& boundary : InnerBoundaries)
{
tin.insert_constraint(boundary.begin(), boundary.end(), true);
}
Constrained_CopyGraph(tin, GenratedMesh);
}
结果
声明:
本文采用
BY-NC-SA
协议进行授权,如无注明均为原创,转载请注明转自
几何代码及文字整理
本文地址: 代码实践篇六 如何进行限制剖分/给曲面添加内外边界?
本文地址: 代码实践篇六 如何进行限制剖分/给曲面添加内外边界?
您必须 登录 才能发表评论