Jarvis步进法(Jarvis March)凸包算法

Jarvis步进法(也称为包裹法): Jarvis步进法是一种逐步选择凸包顶点的算法。从点集中选择一个起始点,然后在每一步中选择下一个顶点,该顶点是当前点集中与当前点形成的线段上,极角最小的点。该算法的时间复杂度为O(nh),其中n是点的数量,h是凸包的顶点数。请帮我使用 python 实现该算法,并且绘制出原始的离散点和凸包的点并连接成凸包多边形

Jarvis步进法(Jarvis March),又称为包裹法(Gift Wrapping),是一种求解平面点集凸包问题的算法。凸包是包含给定点集合的最小凸多边形。以下是Jarvis步进法的基本数学原理:

  • 选择起始点: 算法首先需要选择一个起始点。通常情况下,选择最左下角的点,以确保算法的稳定性。选择起始点的过程可以通过遍历点集,找到y坐标最小的点,并在y坐标相同时,选择x坐标最小的点。

  • 极角排序: 在选择了起始点之后,对剩余的点按照相对于当前点的极角进行排序。极角可以使用反正切函数(atan2)计算,它表示从当前点到其他点的线段与x轴正方向之间的夹角。排序后的点集顺序将决定扫描过程中点的访问顺序。

  • 扫描过程: 从起始点开始,选择当前点(假设为p),然后选择下一个点(假设为q),这个点是当前点p与其他点形成的线段上,极角最小的点。通过比较极角大小,可以确定下一个点的选择。重复这个过程,直到回到起始点形成一个闭合的凸包。

  • 构建凸包: 扫描完成后,选择的点序列就是凸包的顶点,这个顺序是按照逆时针方向排列的。

    关键思想是通过在每一步中选择具有最小极角的点,逐步构建凸包。这样可以确保在构建的凸包上,点的极角是递增的,最终形成一个逆时针方向的凸多边形。算法的时间复杂度主要取决于对点的排序操作,通常为O(n log n),其中n是点的数量。 Jarivs步进法的优势在于其相对简单的实现和较好的性能。然而,在某些情况下,例如存在大量共线点的情况下,算法的性能可能会下降。

import matplotlib.pyplot as plt
import numpy as npclass Point:def __init__(self, x, y):self.x = xself.y = ydef orientation(p, q, r):val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)if val == 0:return 0  # 平行return 1 if val > 0 else 2  # 顺时针或逆时针def jarvis_march(points):n = len(points)if n < 3:print("Jarvis March requires at least 3 points.")return []hull = []# 找到最左下角的点作为起始点start_point = min(points, key=lambda p: (p.y, p.x))current_point = start_pointwhile True:hull.append(current_point)next_point = points[0]for candidate_point in points:if candidate_point != current_point:if next_point == current_point or orientation(current_point, next_point, candidate_point) == 2:next_point = candidate_pointcurrent_point = next_pointif current_point == start_point:breakreturn hulldef plot_convex_hull(points, convex_hull):x_values = [point.x for point in points]y_values = [point.y for point in points]hull_x = [point.x for point in convex_hull]hull_y = [point.y for point in convex_hull]hull_x.append(convex_hull[0].x)  # 闭合凸包hull_y.append(convex_hull[0].y)plt.scatter(x_values, y_values, color='blue', label='Original Points')plt.plot(hull_x, hull_y, color='red', linestyle='-', linewidth=2, label='Convex Hull')plt.legend()plt.xlabel('X')plt.ylabel('Y')plt.title('Jarvis March Convex Hull')plt.grid(True)plt.show()# 示例点集
new_points = [Point(1, 1), Point(2, 3), Point(4, 2), Point(5, 5), Point(7, 1), Point(8, 4), Point(9, 2), Point(10, 6)]# 计算凸包
new_convex_hull_points = jarvis_march(new_points)# 绘制原始离散点和凸包
plot_convex_hull(new_points, new_convex_hull_points)

在这里插入图片描述

#include <iostream>
#include <vector>
#include <algorithm>class Point {
public:double x, y;Point(double _x, double _y) : x(_x), y(_y) {}// 定义 == 运算符bool operator==(const Point& other) const {return (x == other.x) && (y == other.y);}// 定义 != 运算符bool operator!=(const Point& other) const {return !(*this == other);}
};int orientation(const Point& p, const Point& q, const Point& r) {double val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);if (val == 0) return 0;  // 平行return (val > 0) ? 1 : 2; // 顺时针或逆时针
}std::vector<Point> jarvisMarch(const std::vector<Point>& points) {size_t n = points.size();if (n < 3) {std::cerr << "Jarvis March requires at least 3 points." << std::endl;return std::vector<Point>();}std::vector<Point> hull;Point start_point = *std::min_element(points.begin(), points.end(),[](const Point& p1, const Point& p2) {return (p1.y < p2.y) || (p1.y == p2.y && p1.x < p2.x);});Point current_point = start_point;while (true) {hull.push_back(current_point);Point next_point = points[0];for (const auto& candidate_point : points) {if (candidate_point != current_point) {if (next_point == current_point || orientation(current_point, next_point, candidate_point) == 2) {next_point = candidate_point;}}}current_point = next_point;if (current_point == start_point) {break;}}return hull;
}int main() {// 示例点集std::vector<Point> newPoints = { {1, 1}, {2, 3}, {4, 2}, {5, 5}, {7, 1}, {8, 4}, {9, 2}, {10, 6} };// 计算凸包std::vector<Point> newConvexHullPoints = jarvisMarch(newPoints);// 打印凸包点信息std::cout << "Convex Hull Points:" << std::endl;for (const auto& point : newConvexHullPoints) {std::cout << "(" << point.x << ", " << point.y << ")" << std::endl;}return 0;
}

在这里插入图片描述

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

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

相关文章

限流式保护器在户外汽车充装的应用

摘 要&#xff1a;国家标准GB51348-2019中规定储备仓库、电动车充电等场所的末端回路应设置限流式电气防火保护器。电气防火限流式保护器可以有效克服传统断路器、空气开关和监控设备存在的短路电流大、切断短路电流时间长、短路时产生的电弧火花大&#xff0c;以及使用寿命短等…

XSS的利用(包含:蓝莲花、beef-xss)

0x00、环境搭建 dvwa靶场 操作指南和最佳实践:使用 DVWA 了解如何防止网站漏洞_dvwa源代码-CSDN博客 xss漏洞接收平台 下载:GitHub - firesunCN/BlueLotus_XSSReceiver 将解压后的BlueLotus_XSSReceiver原代码放置 phpstudy 安装目录的WWW文件夹下 访问平台:http://127…

【科研技巧】如何判断某个期刊是什么类别及影响因子?是否是顶会?如何期刊内检索?AI写综述?AI做PPT?

相关链接 查找和免费下载文献的方式汇总国内外各大期刊关系、如何查看期刊等级以及查看某篇论文属于哪个期刊登录和访问EI(Engineering Village)数据库查找文献 1 如何判断某个期刊是什么类别及影响因子 https://sci.justscience.cn/ IFold是影响因子 期刊类别为SCIE、查看…

基于springboot+vue心理测试管理系统

摘要 基于Spring Boot 和 Vue 的心理测试管理系统是一个综合利用现代Web开发技术的应用程序。系统采用了Spring Boot作为后端框架&#xff0c;通过其简化的配置和强大的功能提供了稳健的服务器端支持。前端则使用Vue.js&#xff0c;一个灵活、高效的JavaScript框架&#xff0c;…

装机必看:电脑Bios里的CSM兼容模块是啥?打开有啥用?

前言 最近朋友装了一台新的电脑&#xff0c;用的i5-13490f的CPU。但是由于预算有限&#xff0c;手边只有一块GTX650ti&#xff0c;没办法&#xff0c;只好先这么用着了。 谁知道出现了个大问题&#xff1a;电脑开机居然没办法显示。 由于电脑所有的配件基本上都是全新的&…

qt初入门2:qt选择一个文件或者目录,获取当前目录,操作文件目录等整理

最近用qt操作文件或者目录的动作比较多&#xff0c;简单整理一下常用的接口&#xff0c;方便回顾。 总的来说&#xff0c;其实就是用文件选择对话框QFileDialog类&#xff0c;以及操作文件信息的QFileInfo类&#xff0c;以及相关QCoreApplication中静态成员函数获取一些信息&a…

大模型学习与实践笔记(四)

一、大模型开发范式 RAG&#xff08;Retrieval Augmented Generation&#xff09;检索增强生成&#xff0c;即大模型LLM在回答问题或生成文本时&#xff0c;会先从大量的文档中检索出相关信息&#xff0c;然后基于这些检索出的信息进行回答或生成文本&#xff0c;从而可以提高回…

从事铁路工作保护足部,穿什么劳保鞋更安全

铁路运输在我国交通运输业中起着骨干作用&#xff0c;为国民经济的可持续发展和人口流动做出了巨大贡献。安全是铁路运输不可忽视的问题&#xff0c;在作业场地随处能见到“安全就是生命&#xff0c;责任重于泰山”的安全标语&#xff0c;由此可见安全问题是放在首位的。 铁路施…

PHP面试小结(20240108)

PHP 部分 1. php的包管理工具是如何实现自动加载的 换句话问&#xff1a;composer 实现原理是什么&#xff1f;spl_autoload_register() 首先&#xff0c;Composer 是 PHP 的一个包管理和包依赖管理的工具 &#xff0c; 打开安装之后生成的 "vendor" 文件, 里面有个…

使用 EmbeddingBag 和 Embedding 完成词嵌入

&#x1f368; 本文为[&#x1f517;365天深度学习训练营学习记录博客\n&#x1f366; 参考文章&#xff1a;365天深度学习训练营\n&#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制]\n&#x1f680; 文章来源&#xff1a;[K同学的学习圈子](https://www.yuque.co…

【MIdjourney】关于图像中人物视角的关键词

本篇仅是我个人在使用过程中的一些经验之谈&#xff0c;不代表一定是对的&#xff0c;如有任何问题欢迎在评论区指正&#xff0c;如有补充也欢迎在评论区留言。 1.全景镜头(panorama) 全景镜头是一种广角镜头&#xff0c;可以捕捉到比普通镜头更广阔的视野范围。全景镜头&…

挑选富集分析结果 enrichments

#2.2挑选term---selected_clusterenrichenrichmets[grepl(pattern "cilium|matrix|excular|BMP|inflamm|development|muscle|vaso|pulmonary|alveoli",x enrichmets$Description),]head(selected_clusterenrich) distinct(selected_clusterenrich)# remove duplica…