凸包算法(Convex Hull Algorithm)
凸包
定义
平面上 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=[abxbcy−abybcx]
其中, 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 frontstd::iter_swap(yMinItr, backPoints.begin());//sort the left n-1 points based polar anglestd::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;
}
凸包算法(Convex Hull Algorithm)相关推荐
- 转 最小凸包算法(Convex Hull)(1)-Graham扫描法 -计算几何-算法导论
原文地址:http://blog.csdn.net/suwei19870312/article/details/542281 基本问题: 平面上有n个点p1,p2, ..., pn, 要求求出一个面积 ...
- 多边形快速凸包算法(Melkman‘s Algorithm)
前言 平面点集的凸包算法一文介绍了如何计算平面点集或者任意多边形的凸包.对于随机的平面点集,Graham scan和Andraw's 单调链算法已经是最快的算法了.但是对于没有自相交的封闭的简单多边形 ...
- R语言为散点图添加凸包(convex hull):数据预处理(创建一个包含每组数据凸包边界的数据集)、ggplot2使用geom_polygon函数为可视化图像添加凸包(convex hull)
R语言为散点图添加凸包(convex hull):数据预处理(创建一个包含每组数据凸包边界的数据集).ggplot2使用geom_polygon函数为可视化图像添加凸包(convex hull) 目录
- 寻找凸包 (Convex Hull)
凸包问题是算法中经典的题目了,最近算法课讲分治问题时提到了Convex Hull,算法导论的书上也花了篇幅讨论了Convex Hull的求解,主要是Graham方法. 为了能更好地理解分治和Graha ...
- 凸包算法详解(convex hull)
一.概念: 凸包(Convex Hull)是一个计算几何(图形学)中的概念. 在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包. X的凸包可以用X内所有点(X1,...X ...
- 凸包算法(Graham扫描法)
目录 一.概念 二.算法步骤 三.代码实现 转自:https://www.cnblogs.com/aiguona/p/7232243.html 一.概念 凸包(Convex Hull)是一个计算几何( ...
- Opencv 笔记7 凸包算法-Graham扫描法
一.凸包 凸包(convex hull)是一个计算几何的概念,通俗的来说就是在一个二维的平面中有n 个点,我们可通过在外面的点画出一个多边型使得所以的点都在这个多边形里面,如下所示 二.Graham扫 ...
- JavaScript:实现Convex hull凸包问题算法(附完整源码)
JavaScript:实现Convex hull凸包问题算法 function compare (a, b) {// Compare Function to Sort the points, a an ...
- matlab 凸包质心算法,求多边形凸包(线性算法)--陈氏凸包算法--Computing the convex hull of a simple polygon(源码)...
陈氏凸包算法-算法参考:Computing the convex hull of a simple polygon 作者:Chern-Lin Chen 陈氏算法提供了一个线性效率求凸包的算法,本文使用 ...
- 清华计算几何大作业(一):CG2017 PA1-1 Convex Hull (凸包)
CG2017 PA1-1 Convex Hull (凸包) 1. 前置知识 2. 思路分析 3. 伪代码 4. 可视化结果示例 5. 项目代码(待更新完整) 1.1.1 Numerical Tests ...
最新文章
- mysql+join+分库分表_MySQL分库分表篇
- Skynet通讯遇到的奇怪问题
- 创建两个相同名称的文件夹
- Types cannot be provided in put mapping requests, unless the include_type_name parameter is set to t
- 常用库函数_跑马灯实验和我为什么使用库函数?
- es过滤指定数据 java_elasticsearch 结构化搜索_在案例中实战基于range filter来进行范围过滤...
- 机器学习基础(三十五)—— 协同过滤(从匹配用户到匹配商品)
- matlab2012仿真电路图,cuk电路matlab仿真 - 全文
- 邮件监控云上脚本执行进度
- 电影《海贼王:红发歌姬》观后感
- 《数据安全法》实施一周年,企业和个人发生哪些转变?|上云那些事
- @TableField fill
- Python爬虫抓取LeetCode题解,获取力扣中国(leetcode-cn.com)提交代码,自动保存submission到本地,同步上传到github
- 程序员副业之如何利用空余时间从博客中赚钱?
- Servlet规范之转发请求
- 好看的常用背景色RGB数值
- 百家讲坛 雍正十三年(下部)
- 【自然语言处理】潜在语义分析【上】潜在语义分析
- 计算机网络:08---带宽与吞吐量
- 2020年JAVA最常见面试题汇总