通过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界面上绘制一个多边形,只用多边形上的点,最后的三角网格效果:

imglink1

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

imglink2

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

4. 参考

  1. Delaunay三角剖分学习笔记

实现代码

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
CGAL (Computational Geometry Algorithms Library) 是一个C ++库,提供了许多计算几何算法的实现。其中之一是Delaunay 三角分算法,可以通过CGAL库进行实现。 要使用CGAL实现Delaunay 三角分,需要定义一些约束条件来限制三角分的结果。这些约束条件可以是点、直线、圆或球。在CGAL中,可以使用不同的约束类型来定义这些约束条件,例如Point_2,Line_2,Circle_2等。 一旦定义了约束条件,可以使用CGALDelaunay_triangulation_2类来计算Delaunay三角分。该类提供了一些函数来插入点、删除点、查询最近邻点、查询包含点的三角形和边界等功能。 下面是一个简单的示例代码,演示如何使用CGAL实现Delaunay 三角分: ```c++ #include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Delaunay_triangulation_2.h> typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Delaunay_triangulation_2<K> Delaunay; int main() { Delaunay dt; dt.insert(K::Point_2(0, 0)); dt.insert(K::Point_2(1, 0)); dt.insert(K::Point_2(0, 1)); dt.insert(K::Point_2(1, 1)); std::cout << "Number of vertices: " << dt.number_of_vertices() << std::endl; std::cout << "Number of triangles: " << dt.number_of_faces() << std::endl; return 0; } ``` 该代码创建了一个Delaunay_triangulation_2对象,并插入了四个点。然后,它打印出了三角形和顶点的数量。 需要注意的是,这只是一个简单的示例,实际上,CGAL提供了更多的功能和选项来控制Delaunay 三角分的行为。例如,可以定义不同的距离函数来计算点之间的距离,或者使用其他类型的约束来定义三角分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

charlee44

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值