【计算几何】凸包问题 (Convex Hull)

【计算几何】凸包问题 (Convex Hull)

引言

凸多边形

凸多边形是指所有内角大小都在 [ 0 , π ] [0,π] [0,π]范围内的简单多边形

凸包

在平面上能包含所有给定点的最小凸多边形叫做凸包。

其定义为:对于给定集合 X,所有包含 X 的凸集的交集 S 被称为 X 的 凸包。

实际上可以理解为用一个橡皮筋包含住所有给定点的形态。

凸包用最小的周长围住了给定的所有点。如果一个凹多边形围住了所有的点,它的周长一定不是最小,如下图。根据三角不等式,凸多边形在周长上一定是最优的。

在这里插入图片描述

凸包的求法

主要介绍Graham扫描法

Graham Scan 算法求凸包

Graham Scan 算法是一种十分简单高效的二维凸包算法,能够在 O ( n l o g n ) O(nlogn) O(nlogn)
的时间内找到凸包。

Graham Scan 算法的做法是先确定一个起点(一般是最左边的点和最右边的点),然后一个个点扫过去,如果新加入的点和之前已经找到的点所构成的 “壳” 凸性没有变化,就继续扫,否则就把已经找到的最后一个点删去,再比较凸性,直到凸性不发生变化。分别扫描上下两个 “壳”,合并在一起,凸包就找到了。这么说很抽象,我们看图来解释:

在这里插入图片描述
在这里插入图片描述

先找 “下壳”,上下其实是一样的。首先加入两个点 A 和 B。

然后插入第三个点 C,并计算 A B ⃗ × B C ⃗ \vec{AB} \times \vec{BC} AB ×BC 的向量积,却发现向量积系数小于(等于)0,也就是说 B C ⃗ \vec{BC} BC
A B ⃗ \vec{AB} AB 的顺时针方向上。

在这里插入图片描述

于是删去 B 点。

在这里插入图片描述

按照这样的方法依次扫描,找完 “下壳” 后,再找 “上壳”。


#include <algorithm>

struct Point {
    double x, y;

    // 重载减法运算符,用于计算向量差
    Point operator-(Point& p) {
        Point t;
        t.x = x - p.x;
        t.y = y - p.y;
        return t;
    }

    // 计算向量叉积
    double cross(Point p) {
        return x * p.y - p.x * y;
    }
};

// 比较函数,用于排序点
bool cmp(Point& p1, Point& p2) {
    if (p1.x != p2.x) return p1.x < p2.x;
    return p1.y < p2.y;
}

Point point[1005];  // 无序点
int convex[1005];   // 保存组成凸包的点的下标
int n;              // 坐标系的无序点的个数

// 获取凸包的函数
int GetConvexHull() {
    // 按照x坐标排序,如果x相同则按照y坐标排序
    sort(point, point + n, cmp);
    int temp;
    int total = 0;

    // 构建下凸包
    for (int i = 0; i < n; i++) {
        // 如果当前栈中至少有两个点,并且新点使得栈顶的两个点与新点形成的向量不满足逆时针方向
        while (total > 1 &&
               (point[convex[total - 1]] - point[convex[total - 2]])
                       .cross(point[i] - point[convex[total - 1]]) <= 0)
            total--;  // 弹出栈顶点

        convex[total++] = i;  // 将当前点加入栈中
    }

    temp = total;  // 记录下凸包的点数

    // 构建上凸包
    for (int i = n - 2; i >= 0; i--) {
        // 如果当前栈中至少有两个点,并且新点使得栈顶的两个点与新点形成的向量不满足逆时针方向
        while (total > temp &&
               (point[convex[total - 1]] - point[convex[total - 2]])
                       .cross(point[i] - point[convex[total - 1]]) <= 0)
            total--;  // 弹出栈顶点

        convex[total++] = i;  // 将当前点加入栈中
    }

    return total - 1;  // 返回组成凸包的点的个数,实际上多了一个,就是起点,所以组成凸包的点个数是 total - 1
}

代码解释

结构体 Point:

  • 包含两个成员变量 x 和 y,表示点的坐标。

  • 重载了减法运算符 operator-,用于计算两个点的向量差。

  • 定义了 cross 方法,用于计算两个向量的叉积。

比较函数 cmp:

  • 用于对点进行排序,首先按 x 坐标排序,如果 x 坐标相同则按 y 坐标排序。

全局变量:

  • point 数组存储无序点。

  • convex 数组存储组成凸包的点的下标。

  • n 表示无序点的个数。

函数 G e t C o n v e x H u l l GetConvexHull GetConvexHull:

  • 首先对点进行排序。

  • 构建下凸包:从左到右遍历点,使用栈来维护凸包的点,确保每次新加入的点与栈顶的两个点形成的向量满足逆时针方向。

  • 构建上凸包:从右到左遍历点,使用栈来维护凸包的点,确保每次新加入的点与栈顶的两个点形成的向量满足逆时针方向。

  • 返回组成凸包的点的个数,注意实际点的个数是 total - 1,因为起点被重复计算了一次。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT文件生成可执行的exe程序

将qt项目生成可执行的exe程序可按照以下步骤进行&#xff1a; 1、在qt中构建运行生成.exe文件&#xff1b; 2、从自定义的路径中取出exe文件放在一个单独的空文件夹中&#xff08;exe文件在该文件夹中的release文件夹中&#xff09;&#xff1b; 3、从开始程序中搜索qt&#xf…

Python入门 2024/7/8

目录 数据容器 dict(字典&#xff0c;映射) 语法 定义字典字面量 定义字典变量 定义空字典 从字典中基于key获取value 字典的嵌套 字典的常用操作 新增元素 更新元素 删除元素 清空字典 获取全部的key 遍历字典 统计字典内的元素数量 练习 数据容器的通用操作…

运维锅总详解设计模式

本首先简介23种设计模式&#xff0c;然后用Go语言实现这23种设计模式进行举例分析。希望对您理解这些设计模式有所帮助&#xff01; 一、设计模式简介 设计模式是软件设计中用于解决常见设计问题的一套最佳实践。它们不是代码片段&#xff0c;而是解决特定问题的通用方案。设…

(图文详解)小程序AppID申请以及在Hbuilderx中运行

今天小编给大家带来了如何去申请APPID&#xff0c;如果你是小程序的开发者&#xff0c;就必须要这个id。 申请步骤 到小程序注册页面&#xff0c;注册一个小程序账号 微信公众平台 填完信息后提交注册 会在邮箱收到 链接激活账号 确认。邮箱打开链接后&#xff0c;会输入实…

线程并发库复习

1.进行和线程 什么是进程&#xff1a;进程是内存分配的基本单位&#xff0c;它是程序执行时的一个实例&#xff0c;会被放到进程就绪队列&#xff0c;等进程调度器选择它&#xff0c;给它时间片&#xff0c;它才会运行。在java中启动进程&#xff0c;main&#xff0c;test&…

14-54 剑和诗人28 - 用于实时嵌入查找的向量检索

介绍 LLM 成功的关键因素是向量嵌入的使用。通过将文本转换为数字向量表示&#xff0c;我们可以将语义含义映射到数学向量空间。这使得模型能够根据向量之间的相似性在语言中概括模式。 随着我们的模型和数据集变得越来越大&#xff0c;高效地存储、组织和检索这些嵌入变得至关…

STM32智能交通灯控制系统教程

目录 引言环境准备智能交通灯控制系统基础代码实现&#xff1a;实现智能交通灯控制系统 4.1 数据采集模块 4.2 数据处理与控制算法 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;交通灯管理与优化问题解决方案与优化收尾与总结 1. 引言 智能交通灯控…

【UE5】仅修改结构体的若干个数据

蓝图中的结构体变量 | 虚幻引擎4.27文档 (unrealengine.com) 连线连到傻&#xff0c;因为如果某个变量set空值也一起过去了。一查发现有这个节点。

Kubernetes 为pod指定DNS

在k8s里面&#xff0c;默认创建pod会给pod默认分配一个默认的dns&#xff0c;这个dns是哪来的呢&#xff1f;可不可以改成其他的dns呢&#xff1f; 先进入到pod里面来&#xff0c;可以看到这里面默认设置的DNS服务器&#xff0c;这个服务器地址为10.96.0.10。这个地址是k8s自动…

Qt入门(二):Qt的基本组件

目录 Designer程序面板 1、布局Layout 打破布局 贴合窗口 2、QWidget的属性 3、Qlabel标签 显示图片 4、QAbstractButton 按钮类 按钮组 5、QLineEdit 单行文本输入框 6、ComboBox 组合框 7、若干与数字相关的组件 Designer程序面板 Qt包含了一个Designer程序 &…

【Notepad】Notepad_6.3.1 的中文版安装详情

目录 &#x1f33c;1. Notepad的认识 &#x1f33c;2. Notepad中文版安装详情 &#x1f33c;1. Notepad的认识 Notepad 是 Windows 操作系统中的一个文本编辑器程序&#xff0c;通常用于创建和编辑简单的文本文件&#xff0c;如文本文档 (.txt)。它非常轻量且功能简单&#…

Spring-AOP(二)

作者&#xff1a;月下山川 公众号&#xff1a;月下山川 1、什么是AOP AOP&#xff08;Aspect Oriented Programming&#xff09;是一种设计思想&#xff0c;是软件设计领域中的面向切面编程&#xff0c;它是面向对象编程的一种补充和完善&#xff0c;它以通过预编译方式和运行期…

算法学习笔记(8.2)-动态规划入门进阶

目录 问题判断: 问题求解步骤&#xff1a; 图例&#xff1a; 解析&#xff1a; 方法一&#xff1a;暴力搜索 实现代码如下所示&#xff1a; 解析&#xff1a; 方法二&#xff1a;记忆化搜索 代码示例&#xff1a; 解析&#xff1a; 方法三&#xff1a;动态规划 空间…

全球激光位移传感器市场规模逐渐扩大 企业数量不断增多

全球激光位移传感器市场规模逐渐扩大 企业数量不断增多 位移传感器又称为距离传感器&#xff0c;是用于测量与被测物体之间距离的一种传感器。根据工作原理&#xff0c;位移传感器可以分为超声波位移传感器、红外线位移传感器、激光位移传感器等。其中&#xff0c;激光位移传感…

2024年06月CCF-GESP编程能力等级认证Python编程五级真题解析

本文收录于专栏《Python等级认证CCF-GESP真题解析》&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 一、单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 第 1 题 在Python中&#xff0c;print((c for c in “GESP”))的输…

vue实例和容器的一夫一制——04

//准备容器 <div classapp> <h1>{{mag}}</h1> </div> //准备容器 <div classapp> <h1>{{mag}}</h1> </div> //准备容器 <div classapp2> <h1>{{name}}</h1> </div> <script> // 验…

深度整合全球资源,分贝通打造高效、合规的海外差旅管理平台

在全球化商业活动的背景下,中国企业出海已成为常态。然而,随着海外差旅市场的全面增长,企业在海外支出管理上面临诸多挑战。据2023年数据显示,分贝通出海差旅业务GMV同比增长高达500倍,这一增长背后隐藏着企业对于更省钱、更高效管控方式的迫切需求。 面对与日俱增的开支,企业开…

嵌入式代码升级——IAP

目录 IAP的特点 实现 IAP 功能 STM32 正常的程序运行流程 STM32 加入IAP后的运行流程 程序执行流程 BootLoader程序 APP1程序 APP2程序 验证操作步骤 IAP&#xff08;In-Application Programming&#xff09;指的是在应用程序运行时对其自身的Flash存储器进行编程的操作…

LLM - Transformer 的 多头自注意力(MHSA) 理解与源码

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/140281680 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 在 Transformer 中,多头自注意力机制 (MHSA, Multi-Head Self-Attenti…

【pytorch18】Logistic Regression

回忆线性回归 for continuous:y xwbfor probability output:yσ(xwb) σ:sigmoid or logistic 线性回归是简单的线性模型&#xff0c;输入是x&#xff0c;网络参数是w和b&#xff0c;输出是连续的y的值 如何把它转化为分类问题?加了sigmoid函数&#xff0c;输出的值不再是…