通过CGAL将一个多边形剖分成Delaunay三角网

简介: 通过CGAL将一个多边形剖分成Delaunay三角网

通过CGAL将一个多边形剖分成Delaunay三角网

目录

1. 概述

对于平面上的点集,通过Delaunay三角剖分算法能够构建一个具有空圆特性和最大化最小角特性的三角网。空圆特性其实就是对于两个共边的三角形,任意一个三角形的外接圆中都不能包含有另一个三角形的顶点,这种形式的剖分产生的最小角最大。

更进一步的,可以给Delaunay三角网加入一些线段的约束条件,使得构建的Delaunay三角网能够利用这些线段。利用这个特性,可以将一个多边形剖分成Delaunay三角网,开源工具CGAL就正好提供了这个功能。

2. 实现

因为要显示三角网的效果,所以我在《使用QT绘制一个多边形》这篇博文提供的QT界面上进行修改,正好这篇文章提供的代码还实现了在QT中绘制多边形的功能。

关于网格化以及三角网剖分,在CGAL中提供了非常详尽繁复的解决方案,我这里选择了CGAL::refine_Delaunay_mesh_2这个接口,这个接口能够将多边形区域构建成一个Delaunay三角网,如果当前的存在三角形不满足Delaunay,就会在其中补充一些点来满足Delaunay的相关特性。主要的实现代码如下(具体代码见文章最后):

#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>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
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;
//三角化
void GraphicsPainter::Triangulate()
{
    //找到边界上所有的像素点
    vector<Vector2d> ROIBoundPointList;
    CalBoundPoint(ROIBoundPointList);
    CDT cdt;
    vector<Vertex_handle> vertexList;
    cout<<ROIBoundPointList.size()<<endl;
//    for(int i = 0; i<pointList.size(); i++)
//    {
//        vertexList.push_back(cdt.insert(Point(pointList[i].x(), pointList[i].y() )));
//    }
    for(int i = 0; i<ROIBoundPointList.size(); i++)
    {
        vertexList.push_back(cdt.insert(Point(ROIBoundPointList[i].x, ROIBoundPointList[i].y )));
    }
    for(unsigned int i =0;i<vertexList.size()-1;i++)
    {
        cdt.insert_constraint(vertexList[i],vertexList[i+1]);
    }
    //cdt.insert_constraint(vertexList[vertexList.size()-1],vertexList[0]);
    std::cout << "Number of vertices: " << cdt.number_of_vertices() <<std::endl;
    std::cout << "Meshing the triangulation..." << std::endl;
    CGAL::refine_Delaunay_mesh_2(cdt, Criteria());
    std::cout << "Number of vertices: " << cdt.number_of_vertices() <<std::endl;
    CDT::Face_iterator fit;
    for (fit = cdt.faces_begin(); fit!= cdt.faces_end(); ++fit)
    {
        QVector<QPointF> triPoint;
        triPoint.push_back(QPointF(fit->vertex(0)->point().x(), fit->vertex(0)->point().y()));
        triPoint.push_back(QPointF(fit->vertex(1)->point().x(), fit->vertex(1)->point().y()));
        triPoint.push_back(QPointF(fit->vertex(2)->point().x(), fit->vertex(2)->point().y()));
        QPolygonF tri(triPoint);
        triList.push_back(tri);
    }
    bTri = true;
    update();
}

3. 结果

在QT界面上绘制一个多边形,只用多边形上的点,最后的三角网格效果:

通过这篇博文《矢量线的一种栅格化算法》提供的栅格化算法,可以将一个多边形栅格化,这样就可以得到一个栅格多边形,通过这个算法网格化,最后的效果:

可以发现这种方式会在内部新添加一些点,来满足Delaunay特性。并且会形成边界密集,中间稀疏的网格效果。在一些图形、图像处理中,会用到这种自适应网格(Adaptive Mesh)。

4. 参考

  1. Delaunay三角剖分学习笔记

实现代码

分类: 计算几何

标签: 三角剖分 , 三角网 , Delaunay , CGAL


相关文章
|
存储 数据采集 数据可视化
Open3d系列 | 1. Open3d实现点云数据读写、点云配准、点云法向量计算
Open3d系列 | 1. Open3d实现点云数据读写、点云配准、点云法向量计算
17447 1
Open3d系列 | 1. Open3d实现点云数据读写、点云配准、点云法向量计算
|
存储 传感器 自动驾驶
几种常见的点云格式数据解析与在线预览
3D模型在线转换网站支持pcd、pts、xyz、las、laz、asc、ply等点云格式文件在线预览,同时支持将点云格式在线转换为ply、xyz等模型格式。
7807 1
|
C++
UE4/5中DataTable数据表的使用
UE4/5中DataTable数据表的使用
1822 1
UE4/5中DataTable数据表的使用
|
图形学
模型UV纹理设置工具
贴图可以赋予模型丰富的外观纹理和颜色信息,而法线贴图可以增加模型的细节和真实感。这两种纹理贴图技术相互配合,共同营造出逼真的三维场景。
581 3
模型UV纹理设置工具
|
监控 Linux
Linux 进程标识符:深入探讨 getpid() 和 getppid()
在Linux操作系统中,进程管理是一项重要的任务。为了正确管理和监控进程,我们需要了解如何获取进程的标识符。本文将详细介绍两个重要的Linux系统调用函数:`getpid()`和`getppid()`。这两个函数用于获取当前进程的进程ID(PID)和父进程的PID。我们将深入探讨它们的用途、使用方法以及示例代码。
3166 0
|
网络协议 Linux
纯ipv6的linux服务器网络配置方案
纯ipv6的linux服务器网络配置方案
1439 0
|
弹性计算 Ubuntu Linux
阿里云服务器一键安装Docker社区版教程,基于系统运维管理OOS
阿里云服务器一键安装Docker社区版教程,基于系统运维管理OOS自动化部署。支持Ubuntu 22.04/20.04、CentOS 7.7-7.9及Alibaba Cloud Linux 3.2104 LTS。前提条件:ECS实例需运行中且有公网。步骤:选择Docker扩展并安装,验证成功通过命令`docker -v`查看版本号。
982 79
|
11月前
|
存储 图形学 索引
unity 使物体跟随路径点自动移动位置
在Unity中,物体沿路径点自动移动的核心原理是通过预设路径点,控制物体依次移动。路径点可用空对象或三维向量数组定义,并按顺序存储。移动时,计算当前位置与下一个路径点的向量差以确定方向,使用`Vector3.MoveTowards`逐步靠近目标点。代码实现包括路径点设置、移动控制及插值计算,确保物体平滑移动和旋转。
|
消息中间件 Dubbo 应用服务中间件
微服务调用中TraceId是如何传递的?
由于网络原因,我暂时无法解析提供的网页链接。请检查链接是否有效,或稍后再试。如果您有其他问题或需要帮助,请随时告诉我。
微服务调用中TraceId是如何传递的?
|
SQL 自然语言处理 IDE
LLM的IDE使用一段时间后的体会
使用Windsurf开发Web应用,全程无需手写代码,仅通过自然语言交流指导大模型完成任务。初期体验流畅高效,尤其适合快速实现小规模项目。然而,面对需求变更时,代码设计易受影响,需细致指导大模型以保持良好设计。整体而言,LLM辅助编程如同结对编程中的导航员角色,用户需提升自身指导能力以发挥其最大效能。
446 0
LLM的IDE使用一段时间后的体会