如何使用Matlab进行三角剖分(自定义函数实现delaunayTriangulation 使用Bowyer-Watson 算法)

news2024/12/23 17:42:04

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、Delaunay三角形

二、使用步骤

1.Bowyer-Watson算法

2.算法步骤

三、动画演示

四、核心代码

五、对比matlab自带函数和我们的算法:

总结


前言

前一篇文章《Matlab三角剖分插值问题分析(二)_matlab 空间面的三角剖分-CSDN博客》,讲的是使用剖分后的结果进行不规则的散点插值,这篇文章主要是讲如何形成剖分


一、Delaunay三角形

给定平面上的一组点集 P,Delaunay 三角剖分是将点集划分成若干个不重叠的三角形,使得任何一个三角形的外接圆不包含其他点。

有很多博客详细描述了定义和性质,我这边就不详细描述了。

Delaunay三角剖分——BW算法-CSDN博客

Delaunay三角剖分算法_delaunay 三角剖分算法-CSDN博客

二、使用步骤

1.Bowyer-Watson算法

Bowyer-Watson算法是一种增量算法。它的工作原理是将点一次一个地,添加到所有点的子集的Delaunay三角剖分中。每次插入新点后,任何外接圆包含新点的三角形都被删除,留下一个星形多边形孔,然后使用新点重新三角化。

2.算法步骤

Bowyer-Watson算法是一种用于构建Delaunay三角剖分的增量算法。该算法通过逐步添加点并调整三角剖分来保持Delaunay性质。以下是Bowyer-Watson算法的基本步骤

  1. 初始三角剖分

    • 创建一个足够大的超级三角形,覆盖所有要处理的点。
    • 该超级三角形的顶点应位于所有点之外,以确保初始三角剖分包含所有点。
  2. 逐点插入

    • 对每个点进行以下操作:
      1. 找到所有包含该点的三角形(即该点在这些三角形的外接圆内)。
      2. 移除这些三角形。
      3. 创建新三角形,将新点与移除三角形的相邻顶点连接。
  3. 删除超级三角形相关的三角形

    • 移除所有包含超级三角形顶点的三角形,得到最终的Delaunay三角剖分。

下是Bowyer-Watson算法的伪代码引自 Delaunay三角剖分——BW算法-CSDN博客

 1 function BowyerWatson (pointList)
 2     // pointList is a set of coordinates defining the points to be triangulated
 3     triangulation := empty triangle mesh data structure
 4     add super-triangle to triangulation // must be large enough to completely contain all the points in pointList
 5     for each point in pointList do // add all the points one at a time to the triangulation
 6         badTriangles := empty set
 7         for each triangle in triangulation do // first find all the triangles that are no longer valid due to the insertion 对应第2步:新插入点是否在三角形外接圆中
 8             if point is inside circumcircle of triangle
 9                 add triangle to badTriangles
10         polygon := empty set
11         for each triangle in badTriangles do // find the boundary of the polygonal hole 比如图中的ABCD
12             for each edge in triangle do
13                 if edge is not shared by any other triangles in badTriangles
14                     add edge to polygon
15         for each triangle in badTriangles do // remove them from the data structure
16             remove triangle from triangulation
17         for each edge in polygon do // re-triangulate the polygonal hole
18             newTri := form a triangle from edge to point
19             add newTri to triangulation
20     for each triangle in triangulation // done inserting points, now clean up 插完所有点了,现在清理掉外围的三角形,如下图中的蓝色三角形之外的三角形。
21         if triangle contains a vertex from original super-triangle
22             remove triangle from triangulation
23     return triangulation

三、动画演示

如果对原理理解困难,youtube有个动画演示,讲的不错,我这边截下来分解动作再说说

https://www.youtube.com/watch?v=GctAunEuHt4&t=1s

要找上面四个点的德劳内三角剖分

先构造一个超级三角形,把所有点都包含在内

选择一个点,在你所有的三角形集内找一个三角形,它的外接圆包含我们这个点,当下只有超级三角满足

这不是我们想要的结果(显然超级三角形不是得劳内三角形,不满足只含三个点)我们把此点和三角形的三个顶点都连接上,形成新的三角形,都加到集内

现在处理下面的两个点,在三角形集内找到所有(外接圆)包含这个点的三角形,有两个

对这俩三角形处理,删除掉他们的公共边,形成“星形多边形”

同时这个黄点也要连接上所有的顶点,形成的新的四个小三角形也要加到集内

右侧这个点也要相同处理,有两个三角形的外接圆包含它

删掉公共边,形成星形多边形,把这个点和多边形的顶点连接起来

最后是最上面的点,也做相同的处理。

删掉 超三角形的边和顶点,那么那些连接线也得删掉,剩下就是我们要的得劳内三角剖分了

四、核心代码

triangles{1} = super_triangle;

for i = 1:length(points)
    point = points(i);
    triangles = AddPointToMesh(point, triangles);    
end

triangles = RemoveSuperTriangle(triangles, super_triangle);

mesh = triangles;

其中 AddpointToMesh

function good_triangles = AddPointToMesh(point,triangles)
    global Edge Circum_cricle Triangle
    k1 = 1;k2 =1;
    for i = 1:length(triangles)
        triangle = triangles{i};
        
%         plot_triangle(triangle);
%         plot_circumcircle(triangle);
        
        if IsInCircumCircle(point,triangle)
            edges{k1} = triangle.edges(1);
            edges{k1+1} = triangle.edges(2);
            edges{k1+2} = triangle.edges(3);
            k1 = k1+3;
        else
            good_triangles{k2} = triangle;
            k2 = k2+1;
        end
    end
    
    edges = GetUniqueEdges(edges);
    
    for i  = 1:length(edges)
        edge = edges{i};        
        e1 = Edge;        e2 = Edge;        e3 = Edge;        
        e1.points(1) = edge.points(1);
        e1.points(2) = edge.points(2);
        e2.points(1) = edge.points(2);
        e2.points(2) = point;
        e3.points(1) = point;
        e3.points(2) = edge.points(1);
        triangle = Triangle;
        triangle.edges(1) = e1;
        triangle.edges(2) = e2;
        triangle.edges(3) = e3;
        
        good_triangles{k2} = triangle;
%         plot_triangle(triangle);
        k2 = k2+ 1;
    end
    
end

 RemoveSuperTriangle

function mesh_triangles = RemoveSuperTriangle(triangles,super_triangle)
    super_tri_p1 = super_triangle.edges(1).points(1);
    super_tri_p2 = super_triangle.edges(2).points(1);
    super_tri_p3 = super_triangle.edges(3).points(1);
    k = 1;
    for i = 1:length(triangles)
        triangle = triangles{i};
        p1 = triangle.edges(1).points(1);
        p2 = triangle.edges(2).points(1);
        p3 = triangle.edges(3).points(1);
        
        if ~ ( is_point_same(p1,super_tri_p1) || is_point_same(p1 ,super_tri_p2) || is_point_same(p1, super_tri_p3) || ...
                    is_point_same(p2 ,super_tri_p1) || is_point_same(p2,super_tri_p2) || is_point_same(p2,super_tri_p3) || ...
                    is_point_same(p3, super_tri_p1) || is_point_same(p3,super_tri_p2) || is_point_same(p3, super_tri_p3))
            mesh_triangles{k} = triangle;
            k = k +1;
        end
    end
end

五、对比matlab自带函数和我们的算法:

        对比如下:自带函数

T = delaunay(x,y);
% tri = delaunayTriangulation(T, x, y ,z);

trisurf(T,x,y,z)

使用我们自己的

已经完全对上了

总结

完整的包可以从这里下载:

自定义函数实现delaunayTriangulation使用Bowyer-Watson算法资源-CSDN文库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1684947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】学习笔记——二叉搜索树

文章目录 十四、二叉搜索树1. 二叉搜索树的概念2. 二叉搜索树的实现查找插入中序遍历删除拷贝构造析构函数赋值重载完整代码 3. 二叉搜索树的应用K搜索模型KV搜索模型 未完待续 十四、二叉搜索树 1. 二叉搜索树的概念 二叉搜索树又称二叉排序树,它或者是一棵空树&…

BUUCTF---misc---[MRCTF2020]ezmisc

1、附件下载后是一张图片 2、查看属性,winhex分析,没发现什么 3、在kali中binwalk和foremost也没找到什么信息 4、用stegsolve分析也没发现什么 5、这里几乎常见的misc方法都试过了,还是没有发现什么 6、回归到图片本身,想到的…

正心归一、绽放真我 好普集团正一生命文化艺术大赛(中老年赛区)正式启动

为进一步弘扬社会主义核心价值观,弘扬生命文化,提升公众对生命价值的认识与尊重,同时展现中老年艺术家的创作才华,激发广大中老年朋友的艺术热情和创造力。好普集团主办,幸福金龄会与正一生命科学研究(广州…

CSS单行、同行文本左右对齐

再项目需求中,UI小姐姐常常要考虑项目的排版样式更简洁高级,常常会在项目设置内容或者字体两端对齐的效果,比如,在做表单时我们经常遇到让上下两个字段对齐的情况,比如姓名, 手机号码, 出生地等…

分布式音乐播放器适配了Stage模型

OpenAtom OpenHarmony(以下简称“OpenHarmony”)应用开发自API 8及其更早版本一直使用的是FA模型进行开发。FA模型是Feature Ability的缩写,它和PA(Particle Ability)两种类型是过往长期推广的术语,深入人心…

flannel详细介绍

一、前言 Flannel 是一个简单、高效的容器网络解决方案,适用于需要在多个主机上运行容器的场景。它通过虚拟网络技术和 IP 地址管理来实现容器之间的通信和跨主机连接,为容器平台提供了可靠的网络基础设施,flannel有三种模式,分别…

【OceanBase诊断调优】—— 直连普通租户时遇到报错:Tenant not in this server

本文介绍了直连 OceanBase 数据库中的普通租户时,出现报错:ERROR 5150 (HY000) : Tenant not in this server 的处理方法。 问题描述 在 n-n 或者 n-n-n (n>1) 的部署架构中,使用 2881 端口 直连 OceanBase 集群的普通租户,可…

Vue2基础及其进阶面试(一)

简单版项目初始化 新建一个vue2 官网文档:介绍 — Vue.js 先确保下载了vue的脚手架 npm install -g vue-cli npm install -g vue/cli --force vue -V 创建项目 vue create 自己起个名字 选择自己选择特性 选择: Babel:他可以将我们写…

华院计算 | 简单而复杂的“生命游戏”

人类是社会动物,而人类的社会活动则既简单又复杂。长期以来,数学家、计算机科学家和社会学家们一直试图用简单明了的方式方法去刻画错综复杂的社会现象,其中“生命游戏”提供了一个“寓科学于娱乐”的活动框架。 【一】导引 让我们先来玩一…

接口自动化测试Requests库实战超细详解

一、requests库 Requests is an elegant and simple HTTP library for Python, built for human beings. Requests库就是一个使用Python语言发送HTTP请求的一个类库。 github地址:GitHub - psf/requests: A simple, yet elegant, HTTP library. 中文地址&#xff…

【华为】将eNSP导入CRT,并解决不能敲Tab问题

华为】将eNSP导入CRT,并解决不能敲Tab问题 eNSP导入CRT打开eNSP,新建一个拓扑右键启动查看串口号关联CRT成功界面 SecureCRT连接华为模拟器ensp,Tab键不能补全问题选择Options(选项)-- Global Options (全局选项&#…

民国漫画杂志《时代漫画》第6期.PDF

时代漫画06.PDF: https://url03.ctfile.com/f/1779803-1247397790-72c351?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了,截止1937年6月战争来临被迫停刊共发行了39期。 ps:资源来源网络!

MySQL慢查询原因总结

文章目录 一.SQL没加索引二. SQL 索引不生效2.1 隐式的类型转换,索引失效2.2 查询条件包含or,可能导致索引失效2.3 like通配符可能导致索引失效2.4 查询条件不满足联合索引的最左匹配原则2.5 在索引列上使用mysql的内置函数2.6 对索引进行列运算&#xf…

低耦合双写一致性方案-使用canal+MQ

需求:继上一篇使用xxljob实现数据的全量同步到es后,当数据库中新增、删除、修改数据时,应该对es中的对应索引库实现增量同步。 本文介绍了2种双写一致性方案,对其中使用MQ的方案进行了实现。 1. 方案设计 1.1 数据一致性问题分析…

QT7_视频知识点笔记_5_线程,数据库

多线程 两种办法:第一种:Qt4.7之前的线程使用的方法(简单);第二种:Qt4.7之后的(灵活–推荐)----connect最后一个参数的作用:默认连接,队列连接,直…

vue3使用mitt.js进行各种组件间通信

我们在vue工程中,除开vue自带的什么父子间,祖孙间通信,还有一个非常方便的通信方式,类似Vue2.x 使用 EventBus 进行组件通信,而 Vue3.x 推荐使用 mitt.js。可以实现各个组件间的通信 优点:首先它足够小&…

从业务角度来看,DevOps 是什么?

如果您在我们的应用程序名称中看到“DevOps”,这意味着我们必须正确解释该术语,我们会这样做,但角度会有所不同。让我们从业务角度看看 DevOps 是什么。 通用名称 首先你应该知道,DevOps 没有明确的定义。是的。 大多数情况下&a…

分类和品牌关联

文章目录 1.数据库表设计1.多表关联设计2.创建表 2.使用renren-generator生成CRUD1.基本配置检查1.generator.properties2.application.yml 2.生成代码1.进入localhost:81生成代码2.将main目录覆盖sunliving-commodity模块的main目录 3.代码检查1.注释掉CategoryBrandRelationC…

使用xsd验证xml格式的正确性

1.1 基础知识介绍 XML简介:XML是可扩展标记语言(eXtensible Markup Language)的缩写,它是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据。xml文件、xml消息。XSD简介:是X…

JS对象超细

目录 一、对象是什么 1.对象声明语法 2.对象有属性和方法组成 二、对象的使用 1.对象的使用 (1)查 (2)改 (3)增 (4)删(了解) (5&#xf…