基于matlab的凸包(Convex Hull)算法理解与测试

基于matlab的凸包Convex Hull算法理解与测试

  • 0 引言
  • 1 Graham扫描算法原理
  • 2 Graham扫描算法实现
  • 3 Graham扫描算法关键函数
  • 4 结语


0 引言

💻💻AI一下💻💻

  凸包算法是计算给定点集的最小凸包的一种算法。凸包是包含给定点集中所有点的最小凸多边形。根据具体的实现和算法思想,凸包算法可以分为以下几类:

  (1) Jarvis算法(也称为包裹算法):该算法通过找到初始点,然后沿着点集中的边界逐步扩展凸包,直到回到初始点为止。这种算法的时间复杂度为O(nh),其中n是点集的大小,h是凸包的边数。

  (2) Graham扫描算法:该算法首先选取一个最低点作为起始点,然后根据与起始点的极角进行排序。然后依次将每个点加入凸包中,如果加入后出现了凹角,则将凸包中的一些点删除,直到不再出现凹角。

  (3) QuickHull算法:该算法通过递归地将点集分成较小的两部分,并构造凸包。具体过程是:选择距离最远的两点作为凸包的两个顶点,然后将点集划分为两个子集,分别在凸包的左侧和右侧。然后对两个子集分别进行递归,直到遍历了所有的点。该算法的时间复杂度取决于点集的分布,平均情况下为O(nlogn)。

  (4) Chan算法(也称为增量算法):该算法结合了Jarvis算法和Graham扫描算法的优点。首先将点集分成多个子集,在每个子集上运用Graham扫描算法构造凸包。然后通过Jarvis算法将所有的子凸包合并成一个凸包。该算法的时间复杂度为O(nlogh),其中h是凸包的边数。

  以上是一些常见的凸包算法分类和介绍,根据具体的应用场景和性能要求,可以选择合适的算法来计算凸包。

  本篇结合网上搜集到的资料和程序,介绍下Graham扫描法原理实现过程

1 Graham扫描算法原理

  上面讲到了Graham扫描算法思想是以一点为基准,最好是特殊点(如左下角点、中心点),然后根据与起始点的极角进行排序,排序之后每3个一组遍历所有点集,然后判断3个点的位置关系是否满足凸包原则,把满足的点留下,不满足的点从点集中删除,每删除一个点,都要从新遍历所有点集,直至推出整个遍历过程,那留下的点所构成的图形即为包围所有点集的凸多边形。下面用一个简单案例,详细描述下上述过程:

  (1) 为了便于描述,用下面5个点进行原理描述。首先,确定基准点,本过程选取O为基准;

  (2) 计算其它点与 O O O点的极角 ( α ) (α) (α),并按大小进行排序,下图的排序顺序为 [ D E A B C ] [D E A B C] [DEABC]的顺序,图中 X O D XOD XOD即为 D D D点对应的极角;


  (3) 遍历排序数组,每次拿3个出来,我们以 A B C ABC ABC为例,以 A A A为交点,判断向量 A B ⃗ \vec{AB} AB A C ⃗ \vec{AC} AC 的位置关系,由图可以看出,向量 A C ⃗ \vec{AC} AC 可由向量 A B ⃗ \vec{AB} AB 逆时针旋转得到,或向量 A B ⃗ \vec{AB} AB 在向量 A C ⃗ \vec{AC} AC 右侧,而B点明显是凸点,所以依据该准则能够找到所有满足条件的点;

  (4) 再以 C D E CDE CDE为例,以 C C C点为角点,向量 C D ⃗ \vec{CD} CD 到向量 C E ⃗ \vec{CE} CE 需要顺时针旋转,所以 D D D点就不是凸点,应该从点集中删除;

  (5) 用向量叉乘描述向量 A B ⃗ \vec{AB} AB 和向量 A C ⃗ \vec{AC} AC 的位置关系。具体以下图为例,假设向量 O Y ⃗ = [ 0 , 1 , 0 ] \vec{OY}=[0,1,0] OY =[0,1,0],向量 O A ⃗ = [ 1 , 1 , 0 ] \vec{OA} = [1,1,0] OA =[1,1,0],向量 O B ⃗ = [ − 1 , 1 , 0 ] \vec{OB} = [-1,1,0] OB =[1,1,0],计算 O Y ⃗ × O A = [ 0 , 0 , 1 ] ⃗ \vec{OY} \times \vec{OA = [0,0 ,1]} OY ×OA=[0,0,1] ,计算 O Y ⃗ × O B = [ 0 , 0 , − 1 ] ⃗ \vec{OY} \times \vec{OB = [0,0 ,-1]} OY ×OB=[0,0,1] ,由叉乘结果的正负就可以判断位置关系,负值为逆时针,正值为顺时针。对应到(3)和(4)就是留下向量叉积小于0的点,删除叉积结果大于0的点,上面5个点中 D D D点是要删除的点;


2 Graham扫描算法实现

💦💦💦💦💦

clc;clear
n = 50;
point = rand(n,2);figure
scatter(point(:,1),point(:,2));
konvexHullPoints = GrahamScanAlgorithm(point);
%% Visualise konvex Hull
drawHull(konvexHullPoints(:,1),konvexHullPoints(:,2));

  50个随机点构成的凸多边形结果展示。
在这里插入图片描述

3 Graham扫描算法关键函数

💦💦💦💦💦

function [KonvexHullPoints] = GrahamScanAlgorithm(points)
%GRAHAMASCANALGORITHM Summary of this function goes here
xMax = max(points(:,1));
xMin = min(points(:,1));
yMax = max(points(:,2));
yMin = min(points(:,2));Z.x = xMin + (xMax-xMin)/2;
Z.y = yMin + (yMax-yMin)/2;
% scatter(Z.x,Z.y,'*'); %turn on for visualisation of center point%% calculate all arcs between the randpoints and center Z
degHold = []; %holds all the degrees 
for(a=1:1:length(points))degHold(end+1) = calcArc(Z,points(a,:));
end
degHold = transpose(degHold);%% Sort Points 
pointIndice = transpose(1:1:length(points));
degHold = table(degHold, pointIndice,points(:,1),points(:,2));
degHoldSort = sortrows(degHold,'degHold','ascend');
degHoldSort.Properties.VariableNames{3} = 'x';
degHoldSort.Properties.VariableNames{4} = 'y';
KonvexHull = degHoldSort;
%% Calculate Convex Hull
noMoreRemove = false; %condition for staying in while-loop
k = 1;% Increment
cas = 0; % case while(noMoreRemove == false ) %stay in while until no points need to be removed anymoreif(k<=height(KonvexHull)-2)%standard case far away from the vector endP1 = [KonvexHull{k,3},KonvexHull{k,4}];P2 = [KonvexHull{k+1,3},KonvexHull{k+1,4}];P3 = [KonvexHull{k+2,3},KonvexHull{k+2,4}];cas = 0;elseif(k==height(KonvexHull)-1)%k is the penultimate element must now be k+1 = last vector element and k+2 == 1st vector elementP1 = [KonvexHull{k,3},KonvexHull{k,4}];P2 = [KonvexHull{k+1,3},KonvexHull{k+1,4}];P3 = [KonvexHull{1,3},KonvexHull{1,4}];cas = 0;elseif(k==height(KonvexHull))%k is the last element must now be k+1 == 1st vector element and k+2 == 2nd vector element P1 = [KonvexHull{k,3},KonvexHull{k,4}];P2 = [KonvexHull{1,3},KonvexHull{1,4}];P3 = [KonvexHull{2,3},KonvexHull{2,4}];cas = 1;endpolyTest = polyCheck(P1,P2,P3);if(polyTest <= 0 && cas == 0)% concave must be removeKonvexHull(k+1,:) = []; %removek = 0;elseif(polyTest < 0 && cas == 1)KonvexHull(1,:) = []; %removek = 0;elseif(k==height(KonvexHull)&&polyTest>0)     noMoreRemove = true;break;endk = k+1;
endKonvexHullPoints = [KonvexHull{:,3},KonvexHull{:,4}];
end
function [ArcDeg] = calcArc(Z,point)
%CALCARC Summary of this function goes here
toDeg = 180/pi;
dY = point(2) - Z.y;
dX = point(1) - Z.x;
ArcRad  = atan2(dY,dX); if(ArcRad < 0)  ArcDeg = 360 - ((abs(ArcRad)/pi)*180);
elseArcDeg = ArcRad * toDeg;
endend
function  drawHull(HullX,HullY)
%DRAWHULL Summary of this function goes here
%    Plot the wrapping polygon
%% Andreas Bernatzky 19.08.2019
hold(gca,'on');plot(HullX,HullY,'r','LineStyle','--','LineWidth',2);
lastPartX = [HullX(end);HullX(1)];
lastPartY = [HullY(end);HullY(1)];
plot(lastPartX,lastPartY,'r','LineStyle','--','LineWidth',2);
sz = 50;
scatter(HullX,HullY,sz,'*');
%title('Graham-Scan Algorithm for calculating a convex hullpolygon around a pointcloud');
%set(gca,'FontSize',16,'FontWeight','bold');
end

4 结语

💦💦💦💦💦
  本篇介绍了Graham扫描算法的原理和实现步骤,并结合matlab程序,展示了该算法生成凸多边形的结果。希望对你有所帮助。






😜
😜😜
😜😜😜😜

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

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

相关文章

golang有序map

最近使用go开发排行榜的需求, 有些情况会用到有序map, 但是go竟然没有有序map的实现 本着自己动手丰衣足食的原则, 就自己实现了一个 原理 原理比较简单, 主要结合了container/list双向链表和map 使用双向链表存储key和value, 保证顺序, 使用map存储key和节点信息, 保证查找…

Conmi的正确答案——在Kibana中搜索Elasticsearch的索引

Elasticsearch版本&#xff1a;7.17.25 Kibana版本&#xff1a;7.17.25 0、进入首页 1、点击空间名“默”&#xff08;我的默认空间名就是“默认”&#xff09;&#xff1b; 2、点击气泡弹窗的“管理空间”进入管理页面&#xff1b; 3、点击“索引模式”&#xff0c;进入索引模…

Elasticsearch Date类型,时间存储相关说明

本文介绍了在SpringBoot中处理Elasticsearch中日期时间格式的问题。当时间输出为UTC格式并存在时区差异时&#xff0c;可通过设置字段格式如yyyy-MM-dd HH:mm:ss并指定时区为GMT8来解决。存储Date类型数据时&#xff0c;可以使用JSON库如json-lib, fastjson, Jackson或gson进行…

QT访问数据库:应用提示Driver not loaded

在QT中运行完全正确错误截图 解决办法1 我用的是MySQL。我把libmysql.dll复制到应用程序的目录下&#xff0c;即可正常访问数据库。 解决办法2 bool open_work_db() {QString info "support drivers:";for (int i0; i<QSqlDatabase::drivers().size(); i){inf…

用图说明 CPU、MCU、MPU、SoC 的区别

CPU CPU 负责执行构成计算机程序的指令&#xff0c;执行这些指令所指定的算术、逻辑、控制和输入/输出&#xff08;I/O&#xff09;操作。 MCU (microcontroller unit) 不同的 MCU 架构如下&#xff0c;注意这里的 MPU 表示 memory protection unit MPU (microprocessor un…

你需要了解的Android repo工具

在 Android 开发中&#xff0c;repo 是 Google 用来管理多 Git 仓库的一种工具。Android 项目代码由多个 Git 仓库组成&#xff0c;repo 提供了一个高效的机制来批量管理这些仓库&#xff0c;尤其适用于大型项目和团队协作。 1. 什么是 Repo 工具&#xff1f; repo 是一个基于…

尚硅谷-react教程-求和案例-数据共享(下篇)-完成数据共享-笔记

#1024程序员节&#xff5c;征文# public/index.html <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>redux</title></head><body><div id"root"></div></body> </html&…

事件的传递

如果一个事件在 Qt 中未被处理&#xff0c;事件将按照以下机制进行传递和释放&#xff1a; 事件的传递&#xff1a;逐级向上传递 在 Qt 中&#xff0c;如果事件未在某个对象上被处理&#xff08;即 event() 或具体的事件处理函数没有调用 accept() 接受事件&#xff09;&#…

Linux环境下Mongodb部署

文章目录 一、系统环境二、MongoDb安装添加MongoDB官方库安装MongoDB配置MongoDB 三、MongoDB常见操作四、MongoDB用户管理创建用户修改密码删除用户 五、启用安全控制六、备份与还原1. 备份2. 恢复 七、外部工具连接MongoDB 一、系统环境 CentOS Stream 9 64bit 二、MongoD…

LeetCode总结-链表

一、遍历链表 1290.二进制链表转整数 2058.找出临界点之间的最小和最大距离 2181.合并零之间的节点 二、删除节点 问&#xff1a;为什么没有修改 dummy&#xff0c;但 dummy.next 却是新链表的头节点&#xff1f;如果删除了 head&#xff0c;那么最后返回的是不是原链表的头…

项目模块十二:TcpServer模块

一、模块设计思路 1、目的 对所有模块整合&#xff0c;实现一个服务器模块供外部快速搭建服务器。 2、管理 监听套接字 主 Reactor&#xff0c;创建 EventLoop _baseloop 对象&#xff0c;进行对监听套接字的管理 哈希表管理所有新连接的 Channel 创建线程池进行连接的事…

保险大模型革新:全面自动化倒计时

摘 要 大模型于保险业不仅是一个技术升级的过程&#xff0c;更是一种商业模式的变革 未来将会是一切都连接着AI的世界——科技杂志《连线》创始主编凯文凯利&#xff08;KevinKelly&#xff09;曾在《5000天后的世界》中预测。 ChatGPT催生大模型热潮已将近两年&#xff0c;…

python项目实战 查询手机号码归属地源码

get_mobile_from.py # 引入框架 import requests from lxml import etree from flask import Flask, render_template, request# 创建一个app app Flask(__name__)def get_phone_from(phone):# 发送请求的地址url f"https://www.ip138.com/mobile.asp?mobile{phone}&a…

Elasticsearch —— ES 环境搭建、概念、基本操作、文档操作、SpringBoot继承ES

文章中会用到的文件&#xff0c;如果官网下不了可以在这下 链接: https://pan.baidu.com/s/1SeRdqLo0E0CmaVJdoZs_nQ?pwdxr76 提取码: xr76 一、 ES 环境搭建 注&#xff1a;环境搭建过程中的命令窗口不能关闭&#xff0c;关闭了服务就会关闭&#xff08;除了修改设置后重启的…

Go语言的使用

在安装Go和配置镜像时&#xff0c;可以根据操作系统和网络环境来选择适合的步骤。以下是详细的安装步骤和镜像配置&#xff1a; 1. 安装Go 1.1 通过官方下载 访问 Go的官方下载页面 下载适合操作系统的安装包&#xff08;Windows、macOS 或 Linux&#xff09;。安装包下载完…

Python编程中提升效率的8个实用代码

引言 Python 以其简洁易读著称&#xff0c;但有时候&#xff0c;一些巧妙的小技巧能让代码变得更加高效、优雅。本文将介绍八种提升 Python 编程效率的单行代码技巧&#xff0c;帮助你在日常开发中更加得心应手。下面&#xff0c;我们将从基础出发&#xff0c;逐步深入&#x…

OKHTTP断点续传

OKHTTP断点续传 文章目录 OKHTTP断点续传HTTP断点续传知识点RangeContent RangeEtag&If-Range&#xff08;文件唯一标志&#xff09; OKHTTP断点下载OKHTTP 简单短断点下载代码示例 Android 断点续传一直是面试的高频问点&#xff0c;这里从HTTP断点续传知识和Android续传思…

Android 音量调节流程分析

音量调节流程分析 按下音量键 音量键被按下后&#xff0c;按键事件会一路派发给Acitivity&#xff0c;如果无人拦截并处理&#xff0c;承载当前Activity的显示PhoneWindow类的onKeyDown()以及onKeyUp()函数将会被处理&#xff0c;从而开始通过音量键调整音量的处理流程&#x…

【设计模式】《Java 设计模式魔法:解锁高效编程的秘密武器》

标题&#xff1a;《Java 设计模式奇幻之旅&#xff1a;解锁高效编程的魔法钥匙》 摘要&#xff1a; 本文将深入探讨 Java 中的十种设计模式&#xff0c;包括单例模式、工厂方法模式、抽象工厂模式…迭代器模式、组合模式、模板方法模式等。通过详细的解释、生动有趣的例子以及…

如何防止U盘盗取电脑数据?

数据安全无论是对企业还是个人都至关重要。这些用户群体随时面临着数据被窃取的风险&#xff0c;而 U 盘则成为了潜在的安全隐患。如果你想要禁止电脑上使用 这类USB 存储设备&#xff0c;看完这篇文章&#xff0c;防止 U 盘盗取数据并非难事。 禁止使用usb存储设备 打开电脑上…