【算法】Graham 凸包扫描算法 ( 凸包概念 | 常用的凸包算法 | 角排序 | 叉积 | Python 代码示例 )

文章目录

  • 一、Graham 凸包扫描算法
    • 1、凸包概念
    • 2、常用的凸包算法
    • 3、Graham 凸包扫描算法
  • 二、Graham 算法前置知识点
    • 1、角排序
    • 2、叉积
    • 3、算法过程分析
  • 三、代码示例
    • 1、完整代码示例
    • 2、执行结果


使用 Graham 算法绘制的凸包效果 :
在这里插入图片描述

博客代码下载 : https://download.csdn.net/download/han1202012/89428182

  • 使用 PyCharm 打开 , 使用 Python 3.9 开发 ;
    在这里插入图片描述




一、Graham 凸包扫描算法




1、凸包概念


凸包概念 : 在二维平面中 , 包围点集的最小凸多边形 , 其顶点集包含了给定点集中的所有点 , 并且不存在任何一条线段可以穿过这个多边形的内部而不与多边形的边界相交 ;

下图中 ,

  • 左侧的 P1 图是凸包 ;
  • 右侧的 P2 图不是凸包 , 因为该图中 , A2 到 B2 的点连接线与 凸多边形 的边界发生了相交 ;
    在这里插入图片描述

2、常用的凸包算法


常用的凸包算法有 :

  • Graham 扫描法
  • Jarvis 步进法
  • 快速凸包算法

3、Graham 凸包扫描算法


在二维平面上给出一个有限个点的点集 , 其坐标都为 (x , y) ;

Graham 格雷厄姆 凸包扫描算法 , 可以找到上述点集的 凸包边界 , 其时间复杂度是 O(nlogn) ;





二、Graham 算法前置知识点




1、角排序


角排序 是 以角度大小进行排序 , 这里的角度是 选定的基准点 与 点集中的点 的 极角 进行排序 ;

角排序 是一种在计算几何学和算法设计中常用的技术 , 用于对点集中的点按照其与某一基准点的极角进行排序 ;

极角 , 又称为 " 极坐标角度 " , 是指一个点相对于 极点 与 极轴 之间的夹角 , 极角通常用来描述点在 极坐标系 中的位置 ;

  • 极点 是 中心的点 ;
  • 极轴 是 水平 x 轴 ;

极坐标系如下图所示 , 一个点的位置由 极角 ( 从极轴到点到极点连线的方向的角度 ) 和 极径 ( 点到极点的距离 ) 确定 ;

在这里插入图片描述


在角排序中 , 极角是指从基准点出发到其他点的连线与某一固定方向的夹角 ;

角排序用于解决凸包算法中的子问题 , 例如 Graham 扫描算法中 , 需要对点集中的点按照其与基准点的极角进行排序 , 以便确定凸包的边界顺序 ;


在本算法中 , 以极坐标的原点为中心 , 进行角排序 ;


2、叉积


叉积 , 又称为 " 向量积 " 或 " 矢量积 " , 是两个向量之间的一种运算 , 叉积 的结果是一个新的向量 , 值为两个向量所张成的平行四边形的面积 , 方向垂直于这个平行四边形的平面 , 符合右手定则 ;

判断 B 点 在 向量 OA 的左侧还是右侧 :

  • B 在 向量 OA 左侧 , 则 OA 与 OB 的 叉积为负数 ;
  • B 在 向量 OA 右侧 , 则 OA 与 OB 的 叉积为正数 ;
    在这里插入图片描述

给定平面上 3 个点 ABC , 叉积 可以判断一个 点 C 在向量 AB 的哪一边 ,

  • 如果 C 点在 向量 AB 左边 , 则 AB 与 AC 的叉积为正 ;
  • 如果 C 点在 向量 AB 右边 , 则 AB 与 AC 的叉积为负 ;

3、算法过程分析


设置一个 栈 数据结构 ,

将左下角的 2 个点放入 栈 中 ,

从 第三个点开始循环 , 循环内容如下 :

先将要遍历的点放入 栈中 , 判断 新放入的点 是否在 栈顶 2 个元素组成的向量的左边 ,

  • 如果在左边 , 说明该点是凸包上的点 , 栈中保留该点 , 则继续遍历下一个点 ;
  • 如果在右边 , 说明该点不是凸包上的点 , 从栈中弹出该点 , 继续遍历下一个点 ;




三、代码示例



博客代码下载 : https://download.csdn.net/download/han1202012/89428182

  • 使用 PyCharm 打开 , 使用 Python 3.9 开发 ;

1、完整代码示例


import tkinter as tk    # 导入 Tkinter 模块
import random           # 导入 random 模块用于生成随机数
import math             # 导入 math 模块用于数学计算# 定义点类
class Point:def __init__(self, x, y):self.x = xself.y = y# 计算两点之间的距离
def distance(p1, p2):return math.sqrt((p1.x - p2.x)**2 + (p1.y - p2.y)**2)# 通过计算叉乘计算 3 点方向
#   如果叉乘结果 = 0 , 则说明 p1/p2/p3 共线
#   如果叉乘结果 > 0 , 则为顺时针方向
#   如果叉乘结果 < 0 , 则为逆时针方向
def cross_product(p1, p2, p3):return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x)# 求点集的极角
def polar_angle(p0, p):return math.atan2(p.y - p0.y, p.x - p0.x)# 计算两点之间的距离的平方
def distance_squared(p1, p2):return (p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2# 角排序函数
def angle_sort(points):# 点集个数必须大于 3 个if len(points) < 2:return points# 找到最左下方的点作为起始点# p0 点作为极坐标的原点p0 = min(points, key=lambda p: (p.y, p.x))# 按照极角和距离的平方排序# 先按照极角进行排序 如果极角相同 则按照 p0 点到该点的距离排序sorted_points = sorted(points, key=lambda p: (polar_angle(p0, p), distance_squared(p0, p)))# 返回按照极角进行排序的 Point 集合return [p0] + sorted_points[1:]# Graham 扫描法找凸包
def graham_scan(points):if len(points) < 3:return points# 进行角排序sorted_points = angle_sort(points)# 栈数据结构stack = []for p in sorted_points:# 如果栈中的元素大于 2 个开始执行循环, 计算 p 点 在 栈顶两个元素(倒数第二个在前,倒数第一个再后)组成的向量的左侧还是右侧while len(stack) >= 2 and cross_product(stack[-2], stack[-1], p) <= 0:# 如果 p 点在栈顶两个元素组成的向量的左侧 则说明该点是凸边中的点 , 栈顶元素不是凸边中的点 , 将栈顶出栈 , 将本元素入栈stack.pop()# 向栈中添加新元素stack.append(p)return stack# 生成随机点集
# 界面为 800x600 , x 方向上在 50 ~ 750 之间生成点, y 方向上在 50 ~ 550 之间生成点
def generate_points(num_points):points = []for _ in range(num_points):x = random.randint(50, 750)  # 生成 x 坐标范围在 50 到 750 之间的随机数y = random.randint(50, 550)  # 生成 y 坐标范围在 50 到 550 之间的随机数points.append(Point(x, y))return points# 在画布上绘制点
def draw_points(canvas, points):for point in points:canvas.create_oval(point.x - 2, point.y - 2, point.x + 2, point.y + 2, fill="blue")  # 绘制圆点# 在画布上绘制凸包
def draw_convex_hull(canvas, convex_hull):for i in range(len(convex_hull)):p1 = convex_hull[i]p2 = convex_hull[(i + 1) % len(convex_hull)]canvas.create_line(p1.x, p1.y, p2.x, p2.y, fill="red")  # 绘制凸包的边# 主函数
def main():num_points = 100                       # 点的数量设置为 200 个points = generate_points(num_points)    # 生成随机点集convex_hull = graham_scan(points)  # 使用 Graham 扫描法找凸包root = tk.Tk()  # 创建 Tkinter 窗口root.title("Graham Scan Convex Hull")  # 设置窗口标题canvas = tk.Canvas(root, width=800, height=600, bg="white")  # 创建画布canvas.pack()  # 将画布放置在窗口中央draw_points(canvas, points)  # 绘制点集draw_convex_hull(canvas, convex_hull)  # 绘制凸包root.mainloop()  # 进入 Tkinter 主循环if __name__ == "__main__":main()  # 调用主函数

2、执行结果


执行上述代码后 , 在画面中随机生成了 100 个点 , 并进行 Graham 扫描算法 , 计算出了点集的凸集 , 绘制效果如下 :

在这里插入图片描述

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法刷题【二分法】

题目&#xff1a; 注意题目中说明了数据时非递减的&#xff0c;那么这样就存在二分性&#xff0c;能够实现logn的复杂度。二分法每次只能取寻找特定的某一个值&#xff0c;所以我们要分别求左端点和有端点。 分析第一组用例得到结果如下: 成功找到左端点8 由此可知&#xff0…

Spring Boot集成 Spring Retry 实现容错重试机制并附源码

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

verilog阻塞和非阻塞语法

阻塞和非阻塞是FPGA硬件编程中需要了解的一个概念,绝大部分时候,因为非阻塞的方式更加符合时序逻辑设计的思想,有利于时钟和信号的同步,更加有利于时序收敛,所以除非特殊情况,尽量采用非阻塞方式。 1,非阻塞代码 非阻塞赋值,A和B是同时被赋值的,具体是说在时钟的上升…

论文阅读:H-ViT,一种用于医学图像配准的层级化ViT

来自CVPR的一篇文章&#xff0c;https://openaccess.thecvf.com/content/CVPR2024/papers/Ghahremani_H-ViT_A_Hierarchical_Vision_Transformer_for_Deformable_Image_Registration_CVPR_2024_paper.pdf 用CNNTransformer混合模型做图像配准。可变形图像配准是一种在相同视场…

基于单片机的机械手臂控制系统设计

摘 要&#xff1a; 应用单片机 、 Arduino 及机械臂的有关知识&#xff0c;设计一款基于单片机的六自由度机械手臂&#xff0c;并详述其控制系统的软、 硬件设计 。 该机械手臂能够模仿人的上肢完成简单的动作&#xff0c;因此在实验教学演示平台 、 生产或生活中都极具应用价…

Dubbo 3.x源码(20)—Dubbo服务引用源码(3)

基于Dubbo 3.1&#xff0c;详细介绍了Dubbo服务的发布与引用的源码。 此前我们学习了调用createProxy方法&#xff0c;根据服务引用参数map创建服务接口代理引用对象的整体流程&#xff0c;我们知道会调用createInvokerForRemote方法创建远程引用Invoker&#xff0c;这是Dubbo …

Linux文件系统

目录 1.磁盘的结构 1.1磁盘的物理结构 1.2 磁盘的存储结构 1.3 磁盘的逻辑结构 2.文件系统 在上一篇文章基础IO中&#xff0c;我们主要是讲了被打开的文件与进程的关系&#xff0c;以及操作系统是如何管理这些被打开的文件的&#xff0c;但是磁盘有这么多文件&#xff0c;被打…

QT--DAY1

不使用图形化界面实现一个登陆界面 #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {//设置窗口标题this->setWindowTitle("登录界面");//设置窗口大小this->resize(535,410);//固定窗口大小this->setFixedSize(535,410)…

windows 环境下使用git命令导出差异化文件及目录

一、找出差异化的版本&#xff08;再此使用idea的show history&#xff09; 找到两个提交记录的id 分别为&#xff1a; 二、使用git bash执行命令&#xff08;主要使用 tar命令压缩文件&#xff09; 输出结果&#xff1a;

上心师傅的思路分享(三)--Nacos渗透

目录 1. 前言 2. Nacos 2.1 Nacos介绍 2.2 鹰图语法 2.3 fofa语法 2.3 漏洞列表 未授权API接口漏洞 3 环境搭建 3.1 方式一: 3.2 方式二: 3.3 访问方式 4. 工具监测 5. 漏洞复现 5.1 弱口令 5.2 未授权接口 5.3.1 用户信息 API 5.3.2 集群信息 API 5.3.3 配置…

kubernetes(k8s)集群部署(2)

目录 k8s集群类型 k8s集群规划&#xff1a; 1.基础环境准备&#xff1a; &#xff08;1&#xff09;保证可以连接外网 &#xff08;2&#xff09;关闭禁用防火墙和selinux &#xff08;3&#xff09;同步阿里云服务器时间&#xff08;达到集群之间时间同步&#xff09; &…

pytest并发执行时token异常处理问题

接前面加入钩子函数处理token复用的问题&#xff0c;只保证了用例的串联执行&#xff0c;我的部分测试用例中接入了通义千问的部分接口生成测试数据&#xff0c;七八个场景跑完差不多快要10分钟。考虑使用并发执行。 http://t.csdnimg.cn/ACexL 使用多线程和不使用耗时差距很大…

HyperBDR新版本上线,自动化容灾兼容再升级!

本次HyperBDR v5.5.0版本新增完成HCS&#xff08;Huawei Cloud Stack&#xff09;8.3.x和HCSO&#xff08;Huawei Cloud Stack Online&#xff09;自动化对接&#xff0c;另外还突破性完成了Oracle云(块存储模式)的自动化对接。 HyperBDR&#xff0c;云原生业务级别容灾工具。支…

Unity资源 之 最受欢迎的三消游戏开发包 - Bubble Shooter Kit 【免费领取】

三消游戏开发包 - Bubble Shooter Kit 免费领取 前言资源包内容领取兑换码 前言 如果你是一名 Unity 游戏开发者&#xff0c;并且正在寻找一种快速、简单的方式来创建自己的三消游戏&#xff0c;那么 Bubble Shooter Kit 就是你所需要的。 资源包内容 Bubble Shooter Kit 是…

代码随想录算法训练营第36期 last day

最后一次更新&#xff0c;之后去复习专业课和简历 583两个字符串的删除操作 自己做出来了&#xff1a; Code: class Solution {public://找到公共子序列的最大长度dp 最小步数串1.size-dp串2.size-dp int minDistance(string word1, string word2) { vector<v…

用智能插件(Fitten Code: Faster and Better AI Assistant)再次修改vue3 <script setup>留言板

<template><div><button class"openForm" click"openForm" v-if"!formVisible">编辑</button><button click"closeForm" v-if"formVisible">取消编辑</button><hr /><formv-i…

基于梯度下降的多元线性回归原理

为了展示多元线性回归的迭代过程&#xff0c;我们可以使用梯度下降算法手动实现多元线性回归。梯度下降是一种迭代优化算法&#xff0c;用于最小化损失函数。 我们将以下步骤进行手动实现&#xff1a; 初始化回归系数。计算预测值和损失函数。计算梯度。更新回归系数。重复步…

高分论文密码---大尺度空间模拟预测与数字制图

大尺度空间模拟预测和数字制图技术和不确定性分析广泛应用于高分SCI论文之中&#xff0c;号称高分论文密码。大尺度模拟技术可以从不同时空尺度阐明农业生态环境领域的内在机理和时空变化规律&#xff0c;又可以为复杂的机理过程模型大尺度模拟提供技术基础。我们将结合一些经典…

制造业几大系统(MES/WMS/QMS/ERP)的集成

制造业的几大系统包括MES&#xff08;制造执行系统&#xff09;、WMS&#xff08;仓库管理系统&#xff09;、QMS&#xff08;质量管理系统&#xff09;和ERP&#xff08;企业资源计划&#xff09;系统。这些系统在制造业中扮演着不同的角色&#xff0c;可以通过集成实现更高效…

Kafka高频面试题整理

文章目录 1、什么是Kafka?2、kafka基本概念3、工作流程4、Kafka的数据模型与消息存储机制1)索引文件2)数据文件 5、ACKS 机制6、生产者重试机制:7、kafka是pull还是push8、kafka高性能高吞吐的原因1&#xff09;磁盘顺序读写&#xff1a;保证了消息的堆积2&#xff09;零拷贝机…