凸包算法(Convex Hull Algorithm)

[图形学]凸包生成算法附C++实现 凸包Convex Hull)是一个计算几何(图形学)中的概念,简单的来说就是对于一个给定的点集,我们需要求得一个凸多边形把给定的点集全部包含起来。 先附上我的结果: 如上图可以看到用绿色的线连成的一个凸多边形,就是一个凸包,它包含点集中所有的点。 一、算法流程 1、求出点集中满足min(x-y)、min(x+y)、max(x-y)、max(x+y)的四个点,并按逆时针(或者顺时针)方... 阅读详情

凸包

定义


平面上 N 个点的凸包是包围这 N 个点的最小多边形


应用


  • 机器人运动路径规划:找到起点 S 到终点 T 之间的最短路径,而且需要避开一个多边形路障

在这里插入图片描述
s 和 t 之间的最短路径就是 s 和 t 之间的直线距离,或者凸包中上下折线中的其中之一

  • 最远的两点:平面上有 N 个点,希望找到这 N 个点中,距离最远的那一个点对

在这里插入图片描述

距离最远的那一对点,一定在凸包上


属性


  • 在凸包上,可以只通过做逆时针转弯而遍历闭凸包
  • 以最小的 y 值点 p 为原点,与其他点的连线的极角逐渐增大

凸包算法-Graham scan

算法思想


Graham scan 算法思想是基于凸包的两个属性:

  • 求取 N 个点中,y 值最小的点 p
  • 将剩余的 N - 1 个点,按照与点 p 的极角值进行排序
  • 遍历排序后的 N - 1 个点,只保留那些进行逆时针旋转的点

逆时针旋转点


现在有三个点,a, b, c。如何确定 a -> b -> c 是逆时针旋转点?

只有当 c 在 a -> b 连线的左侧的时候,c 才是逆时针旋转点

在这里插入图片描述

当 c 是逆时针旋转点的时候,数学上有:

ab⃗×bc⃗=[abxbcy−abybcx] \vec {ab} \times \vec{bc} = \begin{bmatrix} ab_xbc_y-ab_ybc_x \end{bmatrix} ab×bc=[abxbcyabybcx]
其中, abxbcy - abybcx > 0

这个用右手法则也很好想,当 c 是逆时针旋转点的时候,从 ab 扫到 bc ,大拇指指向一定是正向;相反,则一定是反向;


代码实现


struct Point
{
	float x;
	float y;

	Point() {
		x = 0;
		y = 0;
	}

	Point(float xi, float yi) {
		x = xi;
		y = yi;
	}

	bool operator==(const Point& other) {
		if (std::abs(other.x - x) < 0.000001 && std::abs(other.y - y) < 0.0000001)
			return true;
		return false;
	}

	bool operator!=(const Point& other) {
		return !(*this == other);
	}

	friend std::ostream& operator <<(std::ostream& out, const Point& p) {
		out << p.x << ", " << p.y;
		return out;
	}
};

//return the cos value of the polar angle
float calPolarAngle(const Point& base, const Point& another) {

	float xDistance = another.x - base.x;
	float yDistance = another.y - base.y;
	float distance = std::sqrtf(xDistance * xDistance + yDistance * yDistance);
	return xDistance / distance;
}

struct  YLess
{
	bool operator()(const Point& lhs, const Point& rhs) {
		return lhs.y < rhs.y;
	}
};

struct PolarAngleLess
{
	PolarAngleLess(const Point& p) : base(p) {}

	bool operator()(const Point& lhs, const Point& rhs) {
		return calPolarAngle(base, lhs) > calPolarAngle(base, rhs);
	}
	Point base;
};



bool ccwTurn(const Point& a, const Point& b, const Point& c) {
	Point ab(b.x - a.x, b.y - a.y);
	Point bc(c.x - b.x, c.y - b.y);
	return ab.x*bc.y - ab.y*bc.x > 0;
}

std::vector<Point> convecHull(std::vector<Point>& points) {

	if (points.size() <= 3) return points;

	std::vector<Point> backPoints(points);
	auto yMinItr = std::min_element(backPoints.begin(), backPoints.end(), YLess());
	//put the yMinPoint to the front
	std::iter_swap(yMinItr, backPoints.begin());
	//sort the left n-1 points based polar angle
	std::sort(backPoints.begin() + 1, backPoints.end(), PolarAngleLess(backPoints.front()));


	for (auto it = backPoints.begin(); it != backPoints.end() - 2; ++it) {
		while (!ccwTurn(*it, *(it + 1), *(it + 2))) {
			backPoints.erase(it + 1);
			it = it - 1;
		}
	}
	return backPoints;
}
计算几何——凸包构造算法 本文一共总结了凸包构造的四种算法:Incremental Construction、Jarvis步进法、Graham Scan和Divide-And-Conquer 就像插入排序一样,每次选一个不在凸包集合内的点加入,判断加入的点是否影响凸包极点(边界点)的size,若加入的点使得size变化或边界集合改变,则调整,如下图6,7,9所示。先对多边形进行一个“预处理”,给每个点按序编号,类比有序向量二分查找的思想,来逐步缩小规模。如下图: 首先任选一点为基准点(蓝色点),然后用二分 阅读详情

相关推荐

凸包的计算(附完整代码)——几何算法

1 平面点集的凸包 1.1 凸包的定义 将平面有限点集 P 的凸包定义为:顶点取自于 P 且包含 P 中所有点的那个唯一的凸多边形(convex polygon)。 正如我们已经定义的,P 的凸包是一个凸多边形。表示多边形的一种自然的方法,就是从任一顶点开始,沿顺时针方向依次列出所有顶点。因此,我们所要求解的问题就变成: 1.2 凸包的简单实现 1.2.1 实现思路及算法 根据凸包的定义,很容易得出,相对于凸包边界上任一边所在的直线,P中所有点均居于同侧。 如下图: 凸包某条边的端点p和q都来自于P;另

luolei188的博客 4893

凸包算法

1、凸包定义 凸包问题可以描述为:给定一个点集P,求最小点集S,使得S构成的形状能包含这些点集。 凸包的定义为:平面的一个子集S被称为是“凸”的,当且进当对于任意两点p,q∈S,线段 都完全属于S。几何S的凸包CH(S),就是包含S的最小凸集,更准确地说,它是包含S的所有凸集的交[2]。由此还可以推出凸包的很多性质,包括一条直线如果与凸包相交(不是相切)的话,最多交于两条边或者两个面 二...

lihaidong的博客 8685

RV1126 ROS2环境交叉编译及部署(基于官方Docker)

我的所有基于`RV1126`的机器人项目都是在`Ubuntu22.04`下进行开发的,在`Ubuntu18.04 Docker`容器中实现`RV1126`的`SDK`编译,详细可参考我之前的博客[《Ubuntu20.04/22.04下Docker方案实现多平台SDK编译》第2章](https://blog.csdn.net/w1820020635/article/details/147342689),`RV1126`的`ROS1`部署没什么难度,可以参考我之前的博客,这里记录了`ROS2`交叉编译及问题解决

w1820020635的博客 1102

(转载)凸包问题的五种解法

前言: 首先,什么是凸包? 假设平面上有p0~p12共13个点,过某些点作一个多边形,使这个多边形能把所有点都“包”起来。当这个多边形是凸多边形的时候,我们就叫它“凸包”。如下图: 然后,什么是凸包问题? 我们把这些点放在二维坐标系里面,那么每个点都能用 (x,y) 来表示。 现给出点的数目13,和各个点的坐标。求构成凸包的点? 解一:穷举法(蛮力法) 时间复杂度:O(n³)。 思路:两点确定一条直线,如果剩余的其它点都在这条直线的同一侧,则这两个点是凸包上的点,否则就不是。 步骤...

门前大桥下,游过一群鸭,快来看一看,原来是C++ 3528

C# 凸包的快速凸包算法(Quickhull Algorithm for Convex Hull)

本文介绍了计算点集凸包算法,重点讲解了QuickHull分治算法凸包是包含所有给定点的最小凸多边形,当点少于3个时无法构成。QuickHull算法通过递归地将点集分割并找到距离边界最远的点来构建凸包,其平均时间复杂度为O(nlogn),最坏情况为O()。文中提供了C#实现代码示例,演示了如何找到输入点集的凸包顶点,并给出了Jarvis算法和Graham扫描法的相关资源链接。该算法在计算几何中有广泛应用,如模式识别和图像处理等领域。

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 411

JavaScript 凸包的快速凸包算法(Quickhull Algorithm for Convex Hull)

本文介绍了计算凸包算法及其实现。凸包是包含所有给定点的最小凸多边形,文中通过示例展示了输入点集及其对应的凸包输出结果。重点介绍了QuickHull分治算法,其思路类似快速排序,通过递归处理点集来构建凸包。文章提供了JavaScript实现代码,包括核心函数findSide、lineDist和quickHull,并分析了算法的时间复杂度(平均O(nLogn),最坏O())和空间复杂度(O(n))。此外还列出了Jarvis算法和Graham扫描法的相关资源链接。

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 288

Java 凸包的快速凸包算法(Quickhull Algorithm for Convex Hull)

本文介绍了凸包问题的几种算法,重点分析了QuickHull分治算法。通过示例展示了凸包的计算过程,当点数不足3个时无法构成凸包。文章详细阐述了QuickHull的实现步骤:找到极值点划分区域,递归处理子问题,排除三角形内部点。提供了完整的Java实现代码,使用快速排序处理点集,时间复杂度平均O(nlogn),最坏O()。最后列出了Jarvis算法和Graham扫描法的相关资源链接。

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 312

Python 凸包的快速凸包算法(Quickhull Algorithm for Convex Hull)

本文介绍了计算凸包的几种算法,重点讲解了QuickHull分治算法凸包是包含所有给定点的最小凸多边形,至少需要3个点才能构成。文章通过示例演示了凸包计算结果,并详细说明了QuickHull算法的实现步骤:1)找到x坐标最小和最大的点;2)递归处理分割区域;3)保留距离最远的点作为凸包顶点。提供了Python实现代码,时间复杂度平均为O(nlogn),最坏情况下为O()。文章还列出了Jarvis算法和Graham扫描法的相关资源链接。

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 277

C++ 凸包的快速凸包算法(Quickhull Algorithm for Convex Hull)

本文介绍了计算平面点集凸包的几种算法,重点讲解了QuickHull分治算法。该算法通过递归地寻找距离边界线最远的点来构建凸包,类似于快速排序的划分过程。文中提供了C++实现代码示例,并分析了算法的时间复杂度(平均O(nlogn),最坏O())和空间复杂度(O(n))。同时列出了Jarvis算法和Graham扫描法的多语言实现参考链接,以及快速排序算法的相关资源。文章最后给出了点集输入输出示例,并说明至少需要3个点才能构成凸包

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 273

C++ 利用分治算法凸包(Convex Hull using Divide and Conquer Algorithm)

本文介绍了计算几何中的凸包概念及其应用。凸包是包含给定点集的最小凸多边形,在碰撞检测、图像处理和数据可视化等领域有重要作用。文章重点阐述了使用分治算法求解凸包的方法:将点集递归分割,对少量点使用暴力算法(时间复杂度O())求凸包,再通过寻找切线合并左右子集的凸包算法实现包括确定上下切线、合并凸包等关键步骤,整体时间复杂度为O(nlogn)。文末提供了C++代码示例,展示了如何计算给定点集的凸包

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 457

Python 使用 Jarvis 算法或包装的凸包Convex Hull using Jarvis’ Algorithm or Wrapping)

例如,当输入 (0, 3), (0, 0), (0, 1), (3, 0), (3, 3) 时,它产生 (0, 3) (0, 0) (3, 0) (3, 3) 的输出;当输入 (0, 3), (0, 1), (0, 0), (3, 0), (3, 3) 时,输出为 (0, 3) (0, 1) (0, 0) (3, 0) (3, 3)。下一个点被选为在逆时针方向上领先于所有其他点的点,即,如果对于任何其他点 r,我们有“orientation(p, q, r) = 逆时针”,则下一个点是 q。

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 1417

Python 利用分治算法凸包(Convex Hull using Divide and Conquer Algorithm)

本文介绍了计算几何中凸包的概念及其应用,重点讲解了分治算法求解凸包的实现方法。凸包是包含给定点集的最小凸多边形,在碰撞检测、图像处理和数据可视化等领域有重要应用。文章详细阐述了分治算法的步骤:将点集递归分割,对小于5个点的子集使用暴力算法求解,再通过寻找上下切线合并左右子集的凸包。提供了完整的Python实现代码,包括比较函数、方向判断和合并算法等关键部分。该算法的时间复杂度为O(n logn),空间复杂度为O(n)。文章最后展示了算法在示例点集上的运行结果。

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 381

JavaScript 利用分治算法凸包(Convex Hull using Divide and Conquer Algorithm)

本文介绍了计算几何中凸包的概念及其应用,重点阐述了分治算法求解凸包的实现方法。凸包作为包含点集的最小凸多边形,在碰撞检测、图像处理和数据可视化等领域具有重要价值。文章详细描述了分治算法的步骤:先对点集排序,然后递归分割直至点数足够少时采用暴力算法凸包,最后通过寻找上下切线合并左右凸包。作者提供了JavaScript实现代码,并分析了算法的时间复杂度为O(n logn)。针对特殊情况下可能出现的无限循环问题,文章建议当点数≤5时直接计算凸包。该方法有效解决了凸包计算问题,具有较高的实用价值。

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 266

凸包算法总结

一、定义: 凸包是一个相对于点集的概念,对于一个已经确定的点集,凸包就是由其中某些点构成的一个子集,这个子集中的点构成一个凸多边形,该多边形完全包围点集中所有点。 关于凸包有一个形象的比喻:把点集中各点看作钉子,拿一个橡皮筋套住所有的钉子,最终橡皮筋就是一个凸包,使橡皮筋绷紧的钉子就是凸包中的顶点。 二、求法: 目前比较常见的两种求法分别为Graham扫描法和Andrew算法,由于两个算法都需要对点进行排序,因此它们的时间复杂度均为O(nlogn)...

Cloth的博客 6690

凸包问题的五种解法

前言: 首先,什么是凸包? 假设平面上有p0~p12共13个点,过某些点作一个多边形,使这个多边形能把所有点都“包”起来。当这个多边形是凸多边形的时候,我们就叫它“凸包”。如下图: 然后,什么是凸包问题? 我们把这些点放在二维坐标系里面,那么每个点都能用 (x,y) 来表示。 现给出点的数目13,和各个点的坐标。求构成凸包的点? 解一:穷举法(...

baningtao1470的博客 3406

图形几何算法 -- 凸包算法

凸包是一个点集所包围的最小的凸多边形。可以想象用一根绳子围绕着一群钉子,绳子所形成的轮廓便是这些钉子的凸包。在计算几何中,凸包得到了广泛的应用,涉及领域包括模式识别、图像处理和优化问题等。

qq_32813921的博客 3226

凸包算法详解

一些废话:写这篇博客是因为在听算法网课老师讲分治的时候提到过分治法求凸包的问题,当时没怎么听懂也没太在意这个(因为老师只是提了一嘴,没有细讲),结果好巧不巧,第二天力扣的每日一题就是凸包问题,题目在这:力扣 然后就想着好好学一下凸包算法,但因为我比较懒。。。立了计划后给这篇博客起了个头就没管了,直到几乎20天后,力扣的每日一题又又又有一题可以用凸包做,题目:力扣 所以我特意抽出一个下午好好看了一下各种凸包算法,写下了这篇博客。 注:一下算法均围绕力扣题目 587.安装栅栏 来讨论 前置知识: 设平

m0_54123999的博客 5125

平面点集的凸包(卷包裹算法

凸包在GIS空间算法中也是比较重要的内容,今天分享三种凸包检测的算法,同时扩展一下scipy库中相关的内容,辅助学习。

2301_77671395的博客 1505

数学:凸包算法详解

一.概念: 凸包Convex Hull)是一个计算几何(图形学)中的概念。 在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。 X的凸包可以用X内所有点(X1,...Xn)的线性组合来构造. 在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。 用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含...

dengguan2720的博客 4507

分立器件---电感介绍(7000字)

电感基础整理

HW-BASE的博客 2314

CUDA 12.4版本安装包

CUDA 12.4版本安装包

上一篇: 乱序算法(shuffling algorithm)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值