【CGAL实战】深入理解二维受约束 Delaunay 网格生成

在计算几何、有限元分析(FEA)以及地形建模中,网格生成(Mesh Generation) 是一个至关重要的步骤。如何将一个任意形状的多边形区域离散化为高质量的三角形网格?

本文将以 CGAL (Computational Geometry Algorithms Library) 为例,通过一段标准代码,深入剖析如何生成受约束 Delaunay 三角网格 (Constrained Delaunay Triangulation, CDT),并重点解读控制网格质量的核心参数。

1. 什么是受约束 Delaunay 三角剖分 (CDT)?

普通的 Delaunay 三角剖分虽然能保证三角形尽可能"圆润"(避免极细长的三角形),但它无法强制保留我们指定的边界线段

CDT (Constrained Delaunay Triangulation) 解决了这个问题:它允许我们定义"约束边(Constraints)"。这些边必须出现在最终的网格中,哪怕它们破坏了 Delaunay 性质。在此基础上,CGAL 的网格生成算法(Mesher)会通过插入额外的点(Steiner Points)来优化网格,使其既满足边界约束,又满足形状和大小的要求。

2. 核心代码实现

下面是一个完整的 C++ 示例,展示了如何定义一个"风筝形"区域并对其进行网格细化。

cpp 复制代码
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Delaunay_mesher_2.h>
#include <CGAL/Delaunay_mesh_face_base_2.h>
#include <CGAL/Delaunay_mesh_size_criteria_2.h>
#include <iostream>

// --- 1. 类型定义与内核配置 ---
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_vertex_base_2<K> Vb;

// 关键点:必须使用 Delaunay_mesh_face_base_2 以支持细化算法
typedef CGAL::Delaunay_mesh_face_base_2<K> Fb; 
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds;
typedef CGAL::Constrained_Delaunay_triangulation_2<K, Tds> CDT;
typedef CGAL::Delaunay_mesh_size_criteria_2<CDT> Criteria;

typedef CDT::Vertex_handle Vertex_handle;
typedef CDT::Point Point;

int main()
{
    CDT cdt;

    // --- 2. 定义几何边界 ---
    // 定义一个菱形/风筝形
    Vertex_handle va = cdt.insert(Point(-4,0));
    Vertex_handle vb = cdt.insert(Point(0,-1));
    Vertex_handle vc = cdt.insert(Point(4,0));
    Vertex_handle vd = cdt.insert(Point(0,1));
    
    // 插入一个内部点
    cdt.insert(Point(2, 0.6));

    // --- 3. 插入约束边 ---
    cdt.insert_constraint(va, vb);
    cdt.insert_constraint(vb, vc);
    cdt.insert_constraint(vc, vd);
    cdt.insert_constraint(vd, va);

    std::cout << "初始顶点数: " << cdt.number_of_vertices() << std::endl;

    // --- 4. 执行网格细化 ---
    std::cout << "正在生成网格..." << std::endl;
    
    // 核心函数:设置细化标准
    CGAL::refine_Delaunay_mesh_2(cdt, CGAL::parameters::criteria(Criteria(0.125, 0.5)));

    std::cout << "细化后顶点数: " << cdt.number_of_vertices() << std::endl;
    
    return 0;
}

3. 避坑指南:类型定义

很多初学者在使用 CGAL 网格生成时会遇到编译错误或运行时崩溃,原因通常出在 Face_base 的选择上。

请注意这行代码:

cpp 复制代码
typedef CGAL::Delaunay_mesh_face_base_2<K> Fb;

普通的三角剖分使用 Triangulation_face_base_2 即可,但如果你要使用 refine_Delaunay_mesh_2 算法,必须 使用 Delaunay_mesh_face_base_2。因为细化算法需要在每个三角形对象中存储额外的状态信息(如三角形是否在约束区域内、是否满足尺寸要求等)。

4. 深度解析:Criteria 参数的魔法

代码中最关键的一行是:

cpp 复制代码
CGAL::refine_Delaunay_mesh_2(cdt, CGAL::parameters::criteria(Criteria(0.125, 0.5)));

这里的 Criteria(0.125, 0.5) 控制着最终网格的质量和密度。很多开发者不知道如何调整这两个数字。

参数一:Shape Bound (形状标准) = 0.125

这个参数控制三角形的形状质量 ,具体来说是限制三角形的最小角

  • 含义:它定义了一个常数 ,使得 。
  • 为何是 0.125? 这是 CGAL 的推荐值。当 时,算法保证生成的网格中所有三角形的最小角 。
  • 建议保持 0.125 不变。这是该算法能保证数学上收敛(终止)的最严格限制。如果设得更小(试图追求接近 60° 的完美三角形),算法可能会陷入死循环。如果你不关心形状只关心大小,可以设为 0。

参数二:Size Bound (尺寸标准) = 0.5

这个参数控制三角形的最大大小(网格密度)。

  • 含义:网格中任意三角形的任意边长都不能超过这个值。

  • 影响

  • 值越小:网格越密,顶点越多,计算量越大。

  • 值越大:网格越稀疏。

  • 设为 0:不限制大小,只为了满足形状要求或边界约束而加点。

  • 示例:在上面的代码中,几何体跨度为 8 (-4 到 4),我们将尺寸限制为 0.5。这意味着原来的大三角形会被切碎,算法会自动插入大量的 Steiner Points 直到所有边长都小于 0.5。

5. 进阶技巧:非均匀网格

如果你希望在某些区域网格密(如应力集中区),某些区域网格稀,Criteria 的第二个参数其实可以接受一个函数对象 (Functor) 而不仅仅是 double

你可以编写一个类,根据坐标 返回不同的尺寸限制值,从而实现自适应网格生成。

cpp 复制代码
// 伪代码思路
struct Variable_sizing {
    double operator()(const Point& p) const {
        if (is_important_region(p)) return 0.1; // 核心区域加密
        return 1.0; // 边缘区域稀疏
    }
};

6. 总结

使用 CGAL 生成二维网格的流程可以概括为:

  1. 配置 Kernel 和 Traits (别忘了 Delaunay_mesh_face_base_2)。
  2. 构建 CDT,插入点和约束边。
  3. 设置 Criteria :记住 0.125 是形状的黄金标准,调节第二个参数来控制网格密度。
  4. **调用 refine_Delaunay_mesh_2** 一键生成。
相关推荐
疑惑的杰瑞2 小时前
【C】函数与数组
c语言·开发语言·算法·可变参数
郝学胜-神的一滴2 小时前
人工智能与机器学习:从理论到实践的技术全景
人工智能·python·程序人生·算法·机器学习
2401_841495642 小时前
并行程序设计与实现
c++·python·算法·cuda·mpi·并行计算·openmp
算法与编程之美2 小时前
不同的优化器对分类精度的影响以及损失函数对分类精度的影响.
人工智能·算法·机器学习·分类·数据挖掘
sali-tec2 小时前
C# 基于halcon的视觉工作流-章71 深度学习-预处理OCR
开发语言·人工智能·深度学习·数码相机·算法·计算机视觉·ocr
rannn_1112 小时前
【SQL题解】力扣高频 SQL 50题|DAY4
数据库·后端·sql·leetcode·题解
q行2 小时前
MySQL学习日志--DQL和它的七大字句
数据库·学习·mysql
咕噜企业分发小米2 小时前
腾讯云知识图谱实体链接的准确率如何评估?
人工智能·算法·机器学习
MicroTech20252 小时前
MLGO微算法科技发布改进量子ODE算法,支持不可对角化矩阵与非齐次系统实现指数级误差优化
科技·算法·矩阵