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三角剖分学习笔记

实现代码

通过CGAL将一个多边形剖分成Delaunay三角网的更多相关文章

  1. 基于CGAL的Delaunay三角网应用

    目录 1. 背景 1.1 CGAL 1.2 cgal-bindings(Python包) 1.3 vtk-python 1.4 PyQt5 2. 功能设计 2.1 基本目标 2.2 待实现目标 3. ...

  2. css笔记:如何将一个页面平均分成四个部分?

    今天,我在刷面试题的时候,突然想到一道题:如何将一个页面平均分成四个部分(div)呢?其实难度也不大,于是直接上代码 <!DOCTYPE html> <html lang=" ...

  3. 将一个整数M分成N个整数 要求每个都在区间【minV, maxV】之间

    将一个整数M分成N个整数 要求每个都在区间[minV, maxV]之间,怎么分比较快捷???? 说明: N是>=1且<=9的数,分割的数据只要符合[minV, maxV]区间即可,可以是等 ...

  4. C++ 基于凸包的Delaunay三角网生成算法

    Delaunay三角网,写了用半天,调试BUG用了2天……醉了. 基本思路比较简单,但效率并不是很快. 1. 先生成一个凸包: 2. 只考虑凸包上的点,将凸包环切,生成一个三角网,暂时不考虑Delau ...

  5. CSS 将一个页面平均分成四个部分(div)

    在项目中遇到需求,数据监控页面需要同时显示4个板块内容,如下图: CSS 如何将一个页面平均分成四个部分(div)呢? <!DOCTYPE html> <html lang=&quo ...

  6. 将一个list均分成n个list

    /** * 将一个list均分成n个list,主要通过偏移量来实现的 * @param source * @return */ public <T> List<List<T&g ...

  7. OSG :三维无序离散点构建Delaunay三角网

    利用OSG的osgUtil库里面的DelaunayTriangulator类. points是需要构建三角网的点 osgUtil::DelaunayTriangulator* trig = new o ...

  8. 将一个压缩文件分成多个压缩文件;RAR文件分卷

    有时候需要上传压缩文件,但是限制了单个文件的大小,那我们怎么才能将一个比较大的压缩文件分割成多个压缩文件,从而符合要求的进行文件的上传呢?这里小编告诉你一个技巧. 工具/原料 电脑 winrar(一般 ...

  9. OpenCV中Delaunay三角网算法例子

    #include <opencv2/opencv.hpp> #include <vector> using namespace cv; using namespace std; ...

随机推荐

  1. C语言返回值

    C语言函数在结束的时候可以用一个数字表示运行的结果,这个数字就叫做函数的返回值. 主函数应该有一个返回值.如果这个返回值是0就表示程序希望计算机认为它正常结束,如果不是0就表示程序希望计算机认为它是出 ...

  2. [LC] 48. Rotate Image

    You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwise). ...

  3. Oracle 10G 服务端的安装

    安装依赖包yum -y install binutils compat-libstdc++-33 compat-libstdc++-33.i686 elfutils-libelf elfutils-l ...

  4. JAVA异常处理原则和log4j输出详细异常分析

    1.多用try,catch;不要一个try,catch包含所有内容 好处:不同模块抓取不同异常,某一模块异常挂了,不影响其他模块的程序的进行 2.多写几个catche:尽量不要使用Exception这 ...

  5. Hexo快速搭建博客

    1. 准备工作 ~ 安装node.js -> npm -> hexo-cli ~ 安装git -> 版本控制工具 2. 更换npm(nodejs package manager)源 ...

  6. fastdfs+nginx make时报错fatal error:fdfs_define.h: 没有那个文件或目录

    环境: ubuntu 18.04.1 fastdfs-nginx-module_v1.16 root@wang-machine:~/桌面/FastDFS# cd nginx-1.8.1/root@wa ...

  7. Dockfile自动创建discuz论坛和可道云

    将discuz论坛的zip包解压之后用tar包压缩,这样ADD可以直接解压tar包. [root@localhost centos6.9_ssh_discuz]# pwd /opt/dockerfil ...

  8. html一个页面链接携带参数跳转另一个页面基于vue2.0的element框架

    来给生活比个耶! 1.按钮 <el-button @click="albumList(scope.row.id)" size="mini" type=&q ...

  9. js 实现排序算法 -- 插入排序(Insertion Sort)

    原文: 十大经典排序算法(动图演示) 插入排序 插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描, ...

  10. JAVA 获取网页源代码保存到本地文件

    package httpget; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundExce ...