@TOCCGAL 2D三角剖分
三角剖分概念
三角剖分是代数拓扑学里最基本的研究方法。
特性:(1)每一个面都是一个三角形(2)任何两个这样的曲边三角形,要么不相交,要么恰好相交于一条公共边
CGAL中三角剖分(2D)
cgal简单介绍:
计算几何算法库,是一个大型C + +库的几何数据结构和算法。如Delaunay三角网,网格生成,布尔运算的多边形,以及各种几何处理算法。
主要内容
三角剖分(看官方文档,参考地址:https://doc.cgal.org/latest/Manual/packages.html#PartTriangulationsAndDelaunayTriangulations)
三角测量和Delaunay三角测量(TriangulationsAndDelaunayTriangulations)
(1)首先了解CGAL三角剖分可以实现哪些功能,可以现在官网提供的demo
可以根据提供的点、线‘、面绘制三角剖分
(2)介绍三角剖分数据结构
三角数据结构概念(Triangulation Data Structure)
(1)三角剖分数据结构可以被视为面(Faces)和顶点(Vertices)的容器,保持它们之间的关联和邻接关系
(2)每个三角形面都可以访问它的三个关联顶点和它的三个相邻面。每个顶点都可以访问其一个入射面,并通过该面访问其入射面的循环列表。
如图:
面的三个顶点用0、1和2来索引。
面的邻居也用0、1和2进行索引,其索引方式与具有相同索引的顶点相反。
根据句柄(Vertex_handle、Face_handle)访问顶点以及面
根据迭代器可以访问所有顶点、边、面
循环器访问与给定顶点相关的所有顶点、边和面
提供新添加一个顶点分割面或边、反转相邻的面等操作
三角剖分基础数据存储结构:Triangulation_data_structure_2
使用时需引入Triangulation_data_structure_2.h源文件
根据顶点(Triangulation_ds_vertex_base_2)以及面(Triangulation_ds_face_base_2)构建三角剖分存储结构(Triangulation_data_structure_2)
例如: CGAL::Triangulation_data_structure_2<Vb,Fb>
其中Vb: Triangulation_ds_vertex_base_2 Fb:Triangulation_ds_face_base_2
数据结构应用:
Triangulation_data_structure_2是Triangulation_2<Traits,Tds> 以及其他所有二维三角分剖的参数
Tds:Triangulation_data_structure_2
任何一种二维的三角剖分依赖于三角剖分数据结构
首先了解类声明以及具有哪些属性、方法
(3)介绍不同的二维三角剖分
每种三角剖分对应不同的类
CGAL中三角剖分参数
第一个参数:几何特征(geometric traits )(提供三角剖分的几何图元(点、线段和三角形)以及对这些对象的基本操作(谓词或构造)的类。)
第二个参数:三角剖分数据结构(triangulation data structure)(用于表示三角剖分的面和顶点的类型,以及用于访问面和顶点的附加类型(句柄、迭代器和循环器)。)
基本三角剖分的类以及属性、方法
基本三角剖分:简单说平面划分,有界面都是三角形,其中无限顶点没有有效的坐标、也没有几何谓词应用于它和无限面
基本三角剖分(Triangulation_2)
案例:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> 几何特征
#include <CGAL/Triangulation_2.h> 基本三角剖分结构
//typedef 定义一种类型的别名
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_2<K> Triangulation;
//不填写或者CGAL::Default 例如 typedef CGAL::Triangulation_2<K,CGAL::Default> Triangulation;
typedef Triangulation::Vertex_circulator Vertex_circulator;
typedef Triangulation::Point Point;
//输入顶点
std::list<Point> points;
points.push_back(Point(10,10));
points.push_back(Point(-10,-10));
points.push_back(Point(10,-10));
points.push_back(Point(-10,10));
//基本三角剖分对象
Triangulation t;
//插入顶点
t.insert(points.begin(),points. end());
//输出所有顶点、面个数
std::cout << t.number_of_vertices() << std::endl;
std::cout << t.number_of_faces() << std::endl;
//遍历所有面、顶点、边
for (Triangulation::Vertex_iterator it = t.vertices_begin(); it != t.vertices_end();it++) {
std::cout << it->point() << std::endl;
}
//有限顶点
//t.finite_vertices_begin()
//t.finite_faces_begin()
//无限面的个数
int infiniteCount = 0;
for (Triangulation::Face_iterator it = t.faces_begin(); it != t.faces_end(); it++) {
if (t.is_infinite(it)) {
infiniteCount++;
continue;
}
for (int i = 0; i < 3; i++) {
//根据索引获取邻居,判断是否存在邻居
Triangulation::Face_handle f = it->neighbor(i);
//是不是有限面
if (t.is_infinite(f)) {
continue;
}
for (int j = 0; j < 3; j++) {
//输出顶点坐标
std::cout << f->vertex(j)->point() << std::endl;
}
}
}
for (Triangulation::All_faces_iterator it = t.all_faces_begin(); it != t.all_faces_end(); it++) {
if (t.is_infinite(it)) {
infiniteCount++;
}
}
std::cout << "无限个数:" << infiniteCount << std::endl;
//读取无限顶点关联的顶点,取到三角剖分的凸包的顶点输出
Vertex_circulator vc = t.incident_vertices(t.infinite_vertex()),
done(vc);
if (vc != nullptr) {
do {
std::cout << vc->point() << std::endl;
} while (++vc != done);
}
其他三角剖分继承基本三角剖分,使用方式与基本三角剖分相似,同时又有各自的特征
主要讲解 约束Delaunay三角剖分,因为后期使用了网格生成算法,依赖与约束Delaunay三角剖分
其他简单描述,有需求的可以看官方文档
约束三角剖分(Constrained_triangulation_2)
受约束的三角剖分是一组点的三角剖分,它必须在其边中包括一组给定的连接这些点的折线。
给定的折线称为限制并且三角测量中的相应边被称为约束边。
对应的源文件 #include <CGAL/Delaunay_triangulation_2.h>
例如:
CGAL::Constrained_triangulation_2< Traits, Tds, Itag >
Traits:几何特征
Tds: 三角剖分数据结构或者默认
Itag: 是交集标签,用于在处理约束交集的不同策略之间进行选择
//该类有自己的的属性、方法
例如 插入、删除、查询约束边等
约束Delaunay三角剖分(Constrained_Delaunay_triangulation_2)
该类继承Constrained_triangulation_2
空圆属性(也称为Delaunay属性):三角剖分的任何面的外接圆在其内部都不包含该集合的点。
对应的源文件 #include <CGAL/Constrained_Delaunay_triangulation_2.h>
案例1:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Exact_predicates_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<K, CGAL::Default, Itag> CDT;
typedef CDT::Point Point;
typedef CDT::Edge Edge;
//输入顶点
std::list<Point> points;
points.push_back(Point(10, 10));
points.push_back(Point(5, 5));
points.push_back(Point(-10, -10));
points.push_back(Point(-5, -5));
points.push_back(Point(10, -10));
points.push_back(Point(-10, 10));
//基本三角剖分对象
CDT cdt;
//插入顶点
cdt.insert(points.begin(), points.end());
//插入约束边
std::list<Point> constraints;
constraints.push_back(Point(20, 20));
constraints.push_back(Point(-20, -20));
cdt.insert_constraint(constraints.begin(), constraints.end());
//是否有效
assert(cdt.is_valid());
int count = 0;
for (const Edge& e : cdt.finite_edges())
//是不是约束边
if (cdt.is_constrained(e))
++count;
std::cout << "The number of resulting constrained edges is ";
std::cout << count << std::endl;
案例2(涉及网格生成):
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>; //内部核心
#include <CGAL/Constrained_Delaunay_triangulation_2.h>; //约束Delaunay三角剖分
#include <CGAL/Delaunay_mesh_size_criteria_2.h>; //约束Delaunay三角剖分网格:网格划分标准。
#include <CGAL/Delaunay_mesher_2.h>; //实现2D网格生成器,调用细化
#include <CGAL/Delaunay_mesh_face_base_2.h>;
#include <CGAL/Delaunay_mesh_vertex_base_2.h>;
#include <CGAL/lloyd_optimize_mesh_2.h>; //全局网格优化
#include <CGAL/Projection_traits_xy_3.h> //三维在xy平面的投影
//内部核心
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
//根据几何特征创建投影信息
typedef CGAL::Projection_traits_xy_3<K> GT;
//顶点
//typedef CGAL::Triangulation_vertex_base_2<K> Vb; //基本三角剖分的顶点基类
//添加了两个功能,可访问double标记 对网格优化器很有用,可在修改网格时将网格密度保持在各处
typedef CGAL::Delaunay_mesh_vertex_base_2<GT> Vb;
//面类 添加了两个函数,可访问布尔标记,该布尔标记指示面是否在网格划分域中
typedef CGAL::Delaunay_mesh_face_base_2<GT> Fb;
// 函数模板通过<>里的参数进行实例化
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds; //三角剖分数据结构(指定顶点基类以及面基类)
//No_intersection_tag 如果不允许输入约束的交集,
//Exact_predicates_tag 允许输入约束之间的交集,并在traits类提供确切谓词但交集点的近似构造时使用,
//Exact_intersections_tag 允许输入约束之间的交集,并与精确的算术类型结合使用。
typedef CGAL::Exact_predicates_tag Itag;
//约束Delaunay三角剖分,基础特性,类结构
typedef CGAL::Constrained_Delaunay_triangulation_2<GT, Tds, Itag> CDT;
typedef CDT::Point Point;
typedef CDT::Vertex_handle Vertex_handle;
typedef CDT::Face_handle Face_handle;
typedef CDT::Edge Edge;
typedef CDT::Triangle Triangle;
typedef CDT::Segment Segment;
//CDT 必须是2D约束的Delaunay三角剖分。 三角形的形状标准
typedef CGAL::Delaunay_mesh_size_criteria_2<CDT> Criteria;
//此类实现2D网格生成器 对CDT的类结构有要求
typedef CGAL::Delaunay_mesher_2<CDT, Criteria> Mesher;
/**
* 生成约束边
*/
template <typename Iterator>
static void GenerateConstraintLine(CDT &cdt, Iterator b, Iterator e)
{
Point p, q;
Vertex_handle vh, wh;
Iterator it = b;
vh = cdt.insert(*it);
p = *it;
++it;
for (; it != e; ++it){
q = *it;
if (p != q){
wh = cdt.insert(*it);
cdt.insert_constraint(vh, wh);
vh = wh;
p = q;
}
else {
std::cout << "duplicate point: " << p << std::endl;
}
}
}
CDT cdt;
//转换成CGAL点对象
std::list<Point> points;
//插入约束
for(int i = 0; i < constraints->size(); i++)
{
points.clear();
for(int j = 0; j < constraints->at(i).size(); j++)
{
points.push_back(Point(constraints->at(i).at(j).X, constraints->at(i).at(j).Y, constraints->at(i).at(j).Z));
}
if(points.size()>0){
GenerateConstraintLine(cdt, points.begin(), points.end());
}
}
//创建网格
Mesher mesher(cdt);
//设置生成的三角网标准:角度、边长上限
mesher.set_criteria(Criteria(b, edgeLength));
//设置种子:确定哪些洞不参与生成三角网
points.clear();
for(int i = 0; i < seeds->size(); i++){
points.push_back(Point(seeds->at(i).X, seeds->at(i).Y, seeds->at(i).Z));
}
if(points.size()>0){
mesher.set_seeds(points.begin(), points.end(), false);
}
//生成细化的网格
mesher.refine_mesh();
Delaunay三角剖分(Delaunay_triangulation_2) 没有细研究,有需要的可以看官方文档
空圆属性(也称为Delaunay属性):三角剖分的任何面的外接圆在其内部都不包含该集合的点。
对于没有超过三个点的共圆情况的点集,Delaunay三角剖分是唯一的,它是点的Voronoi图的对偶。
对应的源文件 #include <CGAL/Delaunay_triangulation_2.h>
正则三角剖分(Regular_triangulation_2) 没有细研究,有需要的可以看官方文档
用于维护一组加权点的正则三角剖分
对应的源文件 #include <CGAL/Regular_triangulation_2.h>
(4)主要搭建环境,执行cgal中demo,更深层次的了解cgal中的三角剖分
我只需要运行cgal中的二维三角剖分,配置环境时只设置了cgal以及boost,qt
下载cgal最新版本,配置环境变量,
根据使用的编译工具以及下载的CGAL版本安装对应的boost以及qt
个人使用的是visualstudio2019,下载的最新版本CGAL5.5.1,boost_1_76_0-msvc-14.2-64
在项目中配置cgal以及boost环境
(1)配置项目属性页面,包含目录、库目录
(2)链接器