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

news2025/4/2 10:42:34

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 np

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

def 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_point

    while 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_point

        current_point = next_point

        if current_point == start_point:
            break

    return hull

def 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.coloradmin.cn/o/1371421.html

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

相关文章

【深度学习:数据增强】计算机视觉中数据增强的完整指南

【深度学习&#xff1a;数据增强】计算机视觉中数据增强的完整指南 为什么要做数据增强&#xff1f;等等&#xff0c;什么是数据增强&#xff1f;数据增强技术数据增强的注意事项和潜在陷阱什么时候应该做数据增强&#xff1f;类不平衡的数据增强那么我应该选择哪些转换呢&…

图像分类任务的可视化脚本,生成类别json字典文件

1. 前言 之前的图像分类任务可视化&#xff0c;都是在train脚本里&#xff0c; 用torch中dataloader将图片和类别加载&#xff0c;然后利用matplotlib库进行可视化。 如这篇文章中&#xff1a;CNN 卷积神经网络对染色血液细胞分类(blood-cells) 在分类任务中&#xff0c;必定…

如何在一张图里同时显示两个三维图

import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3Dplt.rcParams["font.sans-serif"] ["SimHei"]# 正确显示中文和负号 plt.rcParams["axes.unicode_minus"] False# 创建数据 x np.random.rand(50…

就是要你懂网络--一个网络包的旅程

原文地址:https://plantegg.github.io/2019/05/15/%E5%B0%B1%E6%98%AF%E8%A6%81%E4%BD%A0%E6%87%82%E7%BD%91%E7%BB%9C–%E4%B8%80%E4%B8%AA%E7%BD%91%E7%BB%9C%E5%8C%85%E7%9A%84%E6%97%85%E7%A8%8B/ 写在最前面的 我相信你脑子里关于网络的概念都在下面这张图上&#xff0c…

重新认识Elasticsearch-一体化矢量搜索引擎

前言 2023 哪个网络词最热&#xff1f;我投“生成式人工智能”一票。过去一年大家都在拥抱大模型&#xff0c;所有的行业都在做自己的大模型。就像冬日里不来件美拉德色系的服饰就会跟不上时代一样。这不前段时间接入JES&#xff0c;用上好久为碰的RestHighLevelClient包。心血…

深度解析高防产品---高防CDN

高防CDN是一种基于云计算技术的网络安全防御系统&#xff0c;通过在全球范围内部署多个节点&#xff0c;实现对网站内容的加速和保护。其主要作用和功能包括安全防护、加速访问、跨运营商、跨地域的全网覆盖、提高网站的稳定性以及节约成本。高防CDN可以有效地解决不同地区的网…

构建自己的私人GPT-支持中文

上一篇已经讲解了如何构建自己的私人GPT&#xff0c;这一篇主要讲如何让GPT支持中文。 privateGPT 本地部署目前只支持基于llama.cpp 的 gguf格式模型&#xff0c;GGUF 是 llama.cpp 团队于 2023 年 8 月 21 日推出的一种新格式。它是 GGML 的替代品&#xff0c;llama.cpp 不再…

dubbo与seata集成

1.seata是什么? Seata 是一款开源的分布式事务解决方案&#xff0c;致力于在微服务架构下提供高性能和简单易用的分布式事务服务。 2.seata的注解 GlobalTransactional&#xff1a;全局事务注解&#xff0c;添加了以后可实现分布式事务的回滚和提交&#xff0c;用法与spring…

了解什么是UV纹理?

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 什么是UV&#xff1f; UV 是与几何图形的顶点信息相对应的二维纹理坐…

基于GPT4+Python近红外光谱数据分析及机器学习与深度学习建模

详情点击链接&#xff1a;基于ChatGPT4Python近红外光谱数据分析及机器学习与深度学习建模教程 第一&#xff1a;GPT4基础 1、ChatGPT概述&#xff08;GPT-1、GPT-2、GPT-3、GPT-3.5、GPT-4模型的演变&#xff09; 2、ChatGPT对话初体验&#xff08;注册与充值、购买方法&am…

ESP32_ADC(Arduino)

ADC模数转换 ESP32集成了12位的逐次逼近式ADC&#xff0c;分别为ADC1模块ADC2模块&#xff0c;共支持18个模拟输入通道: ADC1模块&#xff1a;8个通道&#xff0c;32~39ADC2模块&#xff1a;10个通道&#xff0c;0&#xff0c;2&#xff0c;4&#xff0c;12 ~ 15&#xff0c;…

iTOP-3A5000开发板28路PCIE、4路SATA、2路USB2.0、2路USB3.0、LAN、RS232、VGAHDMI等

性能强 采用全国产龙芯3A5000处理器&#xff0c;基于龙芯自主指令系统 (LoongArch)的LA464微结构&#xff0c;并进一步提升频率&#xff0c;降低功耗&#xff0c;优化性能。 桥片 采用龙芯 7A2000&#xff0c;支持PCIE 3.0、USB 3.0和 SATA 3.0.显示接口2 路、HDMI 和1路 VGA…

创建一个郭德纲相声GPTs

前言 在这篇文章中&#xff0c;我将分享如何利用ChatGPT 4.0辅助论文写作的技巧&#xff0c;并根据网上的资料和最新的研究补充更多好用的咒语技巧。 GPT4的官方售价是每月20美元&#xff0c;很多人并不是天天用GPT&#xff0c;只是偶尔用一下。 如果调用官方的GPT4接口&…

从传统部署到无服务器计算:AI应用在AWS平台上的革新与飞跃

文章目录 《快速构建AI应用–AWS无服务器AI应用实战》内容简介作者简介目录 随着人工智能技术的不断发展&#xff0c;越来越多的企业开始将人工智能应用于各个业务场景&#xff0c;以提高效率、降低成本并创造新的商业模式。然而&#xff0c;传统的人工智能解决方案往往需要大量…

【好玩的开源项目】使用Docker部署briefing视频聊天系统

【好玩的开源项目】使用Docker部署briefing视频聊天系统 一、briefing介绍二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载briefing镜像五、部署briefing速查表5.1 使用dock…

界面组件DevExpress WPF v23.2 - 更轻量级的主题支持

DevExpress WPF Subscription拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 DevExp…

【Python机器学习】用于回归的决策树

用于回归的决策树与用于分类的决策树类似&#xff0c;在DecisionTreeRegressor中实现。DecisionTreeRegressor不能外推&#xff0c;也不能在训练数据范围之外的数据进行预测。 利用计算机内存历史及格的数据进行实验&#xff0c;数据展示&#xff1a; import pandas as pd im…

LeetCode-搜索插入位置(35)

题目描述&#xff1a; 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 思路&#xff1a; 给定数组查找指定元素值的…

免 费 搭 建 多模式商城:b2b2c、o2o、直播带货一网打尽

鸿鹄云商 b2b2c产品概述 【b2b2c平台】&#xff0c;以传统电商行业为基石&#xff0c;鸿鹄云商支持“商家入驻平台自营”多运营模式&#xff0c;积极打造“全新市场&#xff0c;全新 模式”企业级b2b2c电商平台&#xff0c;致力干助力各行/互联网创业腾飞并获取更多的收益。从消…

超级工具大盘点

在当今竞争激烈和快节奏的工作环境中&#xff0c;提高效率成为每个人追求的目标。为了更好地应对日常任务和项目&#xff0c;我们需要运用有效的工具和策略。软件是其中一种强大的支持工具&#xff0c;可以极大地提升工作效率和管理能力。在本文中&#xff0c;我将分享一些值得…