当前位置: 首页 > news >正文

Bowyer-Watson算法

数学原理及算法过程

Delaunay 三角剖分是一种特殊的三角剖分方法,它满足以下两个重要性质:

  • 最大化最小角性质:Delaunay 三角剖分通过避免细长的三角形来最大化所有三角形的最小角。
  • 空外接圆性质:在 Delaunay 三角剖分中,每个三角形的外接圆不包含任何其他点。这意味着,对于三角剖分中的任意三角形,其外接圆内没有其他输入点。

基于这些性质,Delaunay 三角剖分算法的一种实现方式是 Bowyer-Watson 算法,这是一种增量算法。以下是具体的算法步骤:

算法过程
  1. 初始化超级三角形:
  • 创建一个足够大的超级三角形,包含所有输入点。这个三角形的三个顶点坐标远离实际输入点的范围,使其能够覆盖所有点。
  1. 逐点插入:
  • 对于每个输入点,找到所有包含该点的外接圆的三角形。这些三角形被称为“坏三角形”。
  1. 构建多边形:
  • 对于所有坏三角形,它们的每条边,如果只被一个坏三角形共享,则称其为边界边。这些边将形成一个多边形。
  1. 删除坏三角形:
  • 将所有坏三角形从三角剖分中删除。
  1. 重新三角化多边形:
  • 用新插入的点和多边形的边构成新的三角形,并将这些三角形加入三角剖分中。
  1. 移除超级三角形的影响:
  • 在所有点都插入后,移除包含超级三角形顶点的所有三角形,得到最终的 Delaunay 三角剖分。

数学原理

  • 外接圆计算

    • 对于每个三角形,计算其外接圆。外接圆的圆心(外心)和半径可以通过三角形顶点的坐标计算。
    • 设三角形顶点为 ( x 1 , y 1 ) , ( x 2 , y 2 ) , ( x 3 , y 3 ) (x_1, y_1), (x_2, y_2), (x_3, y_3) (x1,y1),(x2,y2),(x3,y3)。外接圆的圆心 ( u , v ) (u, v) (u,v) 计算如下:
      d = 2 ( x 1 ( y 2 − y 3 ) + x 2 ( y 3 − y 1 ) + x 3 ( y 1 − y 2 ) ) d = 2 \left( x_1(y_2 - y_3) + x_2(y_3 - y_1) + x_3(y_1 - y_2) \right) d=2(x1(y2y3)+x2(y3y1)+x3(y1y2))

    u = ( ( x 1 2 + y 1 2 ) ( y 2 − y 3 ) + ( x 2 2 + y 2 2 ) ( y 3 − y 1 ) + ( x 3 2 + y 3 2 ) ( y 1 − y 2 ) ) d u = \frac{((x_1^2 + y_1^2)(y_2 - y_3) + (x_2^2 + y_2^2)(y_3 - y_1) + (x_3^2 + y_3^2)(y_1 - y_2))}{d} u=d((x12+y12)(y2y3)+(x22+y22)(y3y1)+(x32+y32)(y1y2))

    v = ( ( x 1 2 + y 1 2 ) ( x 3 − x 2 ) + ( x 2 2 + y 2 2 ) ( x 1 − x 3 ) + ( x 3 2 + y 3 2 ) ( x 2 − x 1 ) ) d v = \frac{((x_1^2 + y_1^2)(x_3 - x_2) + (x_2^2 + y_2^2)(x_1 - x_3) + (x_3^2 + y_3^2)(x_2 - x_1))}{d} v=d((x12+y12)(x3x2)+(x22+y22)(x1x3)+(x32+y32)(x2x1))

    r = ( x 1 − u ) 2 + ( y 1 − v ) 2 r = \sqrt{(x_1 - u)^2 + (y_1 - v)^2} r=(x1u)2+(y1v)2

import matplotlib.pyplot as plt
import numpy as npclass Point:def __init__(self, x, y):self.x = xself.y = yclass Triangle:def __init__(self, p1, p2, p3):self.p1 = p1self.p2 = p2self.p3 = p3self.circumcenter, self.circumradius = self.circumcircle()def circumcircle(self):"""Calculate the circumcenter and circumradius of the triangle."""ax, ay = self.p1.x, self.p1.ybx, by = self.p2.x, self.p2.ycx, cy = self.p3.x, self.p3.yd = 2 * (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by))ux = ((ax*ax + ay*ay) * (by - cy) + (bx*bx + by*by) * (cy - ay) + (cx*cx + cy*cy) * (ay - by)) / duy = ((ax*ax + ay*ay) * (cx - bx) + (bx*bx + by*by) * (ax - cx) + (cx*cx + cy*cy) * (bx - ax)) / dcircumcenter = Point(ux, uy)circumradius = np.sqrt((ax - ux)**2 + (ay - uy)**2)return circumcenter, circumradiusdef contains_point(self, p):"""Check if the point p is inside the circumcircle of the triangle."""return np.sqrt((p.x - self.circumcenter.x)**2 + (p.y - self.circumcenter.y)**2) < self.circumradiusdef delaunay_triangulation(points):"""Perform Delaunay triangulation on a set of points."""super_triangle = Triangle(Point(-1e5, -1e5), Point(1e5, -1e5), Point(0, 1e5))triangulation = [super_triangle]for p in points:bad_triangles = []for tri in triangulation:if tri.contains_point(p):bad_triangles.append(tri)polygon = []for tri in bad_triangles:for edge in [(tri.p1, tri.p2), (tri.p2, tri.p3), (tri.p3, tri.p1)]:is_shared = Falsefor other in bad_triangles:if other != tri and (edge in [(other.p1, other.p2), (other.p2, other.p3), (other.p3, other.p1)] or edge[::-1] in [(other.p1, other.p2), (other.p2, other.p3), (other.p3, other.p1)]):is_shared = Truebreakif not is_shared:polygon.append(edge)for tri in bad_triangles:triangulation.remove(tri)for edge in polygon:triangulation.append(Triangle(edge[0], edge[1], p))triangulation = [tri for tri in triangulation if not (super_triangle.p1 in [tri.p1, tri.p2, tri.p3] or super_triangle.p2 in [tri.p1, tri.p2, tri.p3] or super_triangle.p3 in [tri.p1, tri.p2, tri.p3])]return triangulationdef plot_triangulation(triangles, points):for tri in triangles:plt.plot([tri.p1.x, tri.p2.x], [tri.p1.y, tri.p2.y], 'b-')plt.plot([tri.p2.x, tri.p3.x], [tri.p2.y, tri.p3.y], 'b-')plt.plot([tri.p3.x, tri.p1.x], [tri.p3.y, tri.p1.y], 'b-')for p in points:plt.plot(p.x, p.y, 'ro')plt.show()
# Generate random points in the unit square
rectangle_corners = [Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)]
random_points = [Point(np.random.rand(), np.random.rand()) for _ in range(20)]
points = rectangle_corners + random_pointstriangles = delaunay_triangulation(points)
plot_triangulation(triangles, points)

在这里插入图片描述

相关文章:

Bowyer-Watson算法

数学原理及算法过程 Delaunay 三角剖分是一种特殊的三角剖分方法&#xff0c;它满足以下两个重要性质&#xff1a; 最大化最小角性质&#xff1a;Delaunay 三角剖分通过避免细长的三角形来最大化所有三角形的最小角。空外接圆性质&#xff1a;在 Delaunay 三角剖分中&#xf…...

计算机基础之:fork进程与COW机制

在Unix-like操作系统中&#xff0c;fork()是一个系统调用&#xff0c;用于创建一个与调用进程&#xff08;父进程&#xff09;几乎完全相同的新进程&#xff08;子进程&#xff09;&#xff0c;包括父进程的内存空间、环境变量、文件描述符等。这个过程是通过写时复制&#xff…...

47.各种类型的线程池

线程池继承体系 Executor(interface)->ExecutorService(interface)->ThreadPoolExecutor(class) Executors.newFixedThreadPool 核心线程数最大线程数&#xff08;没有救急线程被创建&#xff09;&#xff0c;所以也无需超时时间阻塞队列LinkedBlockingQueue,可以放任意…...

多目标优化-NSGA-II

文章目录 一、前置知识NSGA-II帕累托前沿 二、算法流程1.NSGA2.NSGA-II 一、前置知识 1.NSGA(非支配排序遗传算法):旨在同时优化多个冲突的目标函数&#xff0c;寻找帕累托前沿上的解集。 什么是多个冲突的目标: 比如你看上了一辆车&#xff0c;你既想要它便宜&#xff0c;又…...

元宇宙数字藏品交易所,未来发展的大趋势

随着科技的飞速进步&#xff0c;元宇宙以其独特的魅力为数字世界绘制了一幅前所未有的宏伟蓝图。在这一宏大的背景下&#xff0c;数字藏品交易所作为连接虚拟与现实的桥梁&#xff0c;正以其卓越的优势&#xff0c;引领着数字藏品市场迈向新的高度。 首先&#xff0c;元宇宙为…...

通配符https数字证书260

随着越来越多的人开始使用互联网&#xff0c;互联网上的信息变得繁杂&#xff0c;用户很难识别网站信息的真实性&#xff0c;为了维护互联网的环境&#xff0c;开发者开始使用https证书对网站传输数据进行加密和身份认证&#xff0c;以此来保护用户的隐私以及标示网站的真实性。…...

C++ | Leetcode C++题解之第133题克隆图

题目&#xff1a; 题解&#xff1a; class Solution { public:Node* cloneGraph(Node* node) {if (node nullptr) {return node;}unordered_map<Node*, Node*> visited;// 将题目给定的节点添加到队列queue<Node*> Q;Q.push(node);// 克隆第一个节点并存储到哈希…...

yangwebrtc x86_64环境搭建

版本&#xff1a;5.0.099 sudo apt-get install libxext-dev sudo apt-get install x11proto-xext-dev sudo apt-get install libxi-dev sudo apt install libasound2-dev sudo apt install libgl1-mesa-dev sudo apt-get install libxtst-dev 用qt打开以下两个项目的.pro met…...

前端面试题日常练-day53 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末 1. 在PHP中&#xff0c;以下哪个函数可以用于从一个数组的末尾删除一个元素并返回被删除的元素&#xff1f; a) array_pop() b) array_push() c) array_shift() d) array_unshift() 2. 在PHP中&…...

空间不够用了怎么办

空间告急啊哥们 整理一下清理空间有用的一些blog吧。 【linux】公共服务器如何清理过多的.cache缓存 linux根目录空间不足&#xff0c;追加空间到根目录下 【linux】linux磁盘空间 目录查看清理 和 文件查看清理...

pytorch数学操作

文章目录 1.torch.bitwise_not()2.torch.bitwise_and()3.torch.ceil()3.torch.clamp()4.torch.torch.floor() 1.torch.bitwise_not() 在 PyTorch 中&#xff0c;torch.bitwise_not() 是一个函数&#xff0c;用于执行逐元素的位非&#xff08;bitwise NOT&#xff09;操作。 t…...

如何做好电子内窥镜的网络安全管理?

电子内窥镜作为一种常用的医疗器械&#xff0c;其网络安全管理对于保护患者隐私和医疗数据的安全至关重要。以下是一些基本原则和步骤&#xff0c;用于确保电子内窥镜的网络安全&#xff1a; 1. 数据加密 为了防止数据泄露&#xff0c;电子内窥镜在传输患者图像数据时应采取有…...

Spring Boot项目中,如何在yml配置文件中读取maven pom.xml文件中的properties标签下的属性值

一、前言 在最近的项目开发过程中&#xff0c;有一个需求&#xff0c;需要在Spring Boot项目的yml配置文件中读取到mave的 pom.xml文件中的properties标签下的属性值&#xff0c;这个要怎么实现呢&#xff1f; 二、技术实践 pom.xml文件中增加测试属性 <properties><…...

C++:模板进阶

✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来! 文章目录 文章目录 前言 一 非类型模板参数 二 模板的特化 2.1 概念 2.2 函数模板特化 函数模板的易错点 2.3 类模板特化 2.3.1 全特化 2.3.2 偏特化 部分特化 参数更进一步的限制 2.3.3 类模板特化应用示例…...

Linux 磁盘分区步骤

1.lsblk用于查看磁盘分区情况&#xff0c;lsblk -f用于查看uuid字符串以及挂载点。 以下是虚拟机部分添加磁盘的步骤。 其余没展示的都按照默认设置进入下一步即可。 2.添加完成后使用reboot重新进入后再使用lsblk就会发现磁盘sdb已经有了&#xff0c;但是没有分区。现在添加分…...

【TB作品】 51单片机8x8点阵显示滚动汉字仿真

功能 题目5基于51单片机LED8x8点阵显示 流水灯 直接滚动显示HELLO 直接滚动显示老师好 代码 void main( void ) {/** 移位后&#xff0c;右边的是第一个595&#xff0c;接收0X02&#xff0c;显示出0X02* 移位后&#xff0c;左边的是第2个595&#xff0c;接收0Xfe&#xff0c…...

c++简略实现共享智能指针Shared_Ptr<T>

重点&#xff1a; 1.引用计数在堆上&#xff08;原本应为原子变量&#xff09; 2.引用计数增加减少需要加锁保证线程安全。 3.内部实现Release函数用于释放资源 4.未实现&#xff0c;增加自定义删除器可以将Release修改为模板函数&#xff0c;传入可调用参数。对于shared_p…...

2024会声会影全新旗舰版,下载体验!

在当今数字时代&#xff0c;视频内容已成为最受欢迎的媒介之一。无论是个人娱乐、教育还是商业推广&#xff0c;优秀的视频制作都是吸引观众的关键。为了满足广大用户对高质量视频制作软件的需求&#xff0c;我们隆重推出了会声会影2024最新旗舰版。这款软件不仅集成了最先进的…...

使用 Node.js 和 Azure Function App 自动更新 Elasticsearch 索引

作者&#xff1a;来自 Elastic Jessica Garson 维护最新数据至关重要&#xff0c;尤其是在处理频繁变化的动态数据集时。这篇博文将指导你使用 Node.js 加载数据&#xff0c;并通过定期更新确保数据保持最新。我们将利用 Azure Function Apps 的功能来自动执行这些更新&#xf…...

UE4_Ben_图形52_水下效果处理

学习笔记&#xff0c;不喜勿喷&#xff0c;欢迎指正&#xff0c;侵权立删&#xff01;祝愿生活越来越好&#xff01; 在这个后期处理的效果中&#xff0c;我们可以看到有很多不同的&#xff0c;这里有浓雾&#xff0c;波纹扭曲&#xff0c;镜头扭曲和边缘模糊&#xff0c;在第4…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...

前端开发者常用网站

Can I use网站&#xff1a;一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use&#xff1a;Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站&#xff1a;MDN JavaScript权威网站&#xff1a;JavaScript | MDN...

篇章二 论坛系统——系统设计

目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...