关闭

二维凸包算法

标签: 算法
366人阅读 评论(0) 收藏 举报
分类:

博客参考:http://blog.csdn.net/chao_xun/article/details/8042403
谢谢 【chao_xun】把凸包写的这么详细。

原始思路

关于凸包的问题的解决的最初思路是这样的。
<1>找到一个基准点<必须在凸边上>
<2>以基准点做射线,然后将该射线向固定方向旋转,直到接触到一个新的点。
<3>以<2>中找到的点作为新的基准点,作射线继续朝着一开始的固定的方向旋转
<4>反复重复2,3直到最后所有边闭合起来
如下图:
这里写图片描述

**

算法步骤

**
下文是参照了【chao_xun】博客中的算法的理解写出的步骤
1.首先选取一个极点,最下边的点,若最低高度相等取最左边(只要保证此点必为凸边上的点即可),以此作为基准点;
2.易知,该点一定在凸包的边上,所以可以以该点与另外一个点连线成边,作为凸包的边:以基准点为射线的端点,做一条X轴正方向的水平射线,扫面各个点与基准点所构成的向量与x轴正方向所构成的夹角,依照夹角进行排序,然后进行第三步的连边(排序的作用意义非常),下图是扫描排序的结果
这里写图片描述

3.接下来开始连边了
为了方便,以下图作为辅助
这里写图片描述
图片说明部分:
1. 经过第二步的扫描之后得到点的排列顺序为 A,B,C,D,E,F,其中A为基准点,数字分别表示两点连接成的边。
2. 规定按照逆时针方向为固定旋转方向,各点的连接顺序按照排序的结果,所以连接{A,B}就有了边【1】,可知边【1】是由前一段射线逆时针旋转过去。
3. 然后按照排序后的结果,尝试连接{B,C},可知 【2】也是以B为端点,方向与1相同的射线逆时针旋转,方向仍然是逆时针,此时也没有问题。
4. 然后按照排序的结果,连接{C,D},这时发现是顺时针旋转了,问题就来了,与我们规定的方向不相同,于是撤销边【2】和边【3】,直接连接{B,D}形成边【4】。

也就是说:假设 三个点 p2 , p3 , p4 ,数字代表他们在连边过程中加入的顺序,那么向量 p3p4一定是由向量p2p3由固定方向(逆时针)旋转过去的,如果不是,则需要将P3删除,直接连点p2和点p4,文字略为啰嗦,具体参照上图说明
最终反复循环可以连成凸包。

算法理解

关于整个算法,上面都只是步骤,个人的理解是这样的,排序后的各点的按顺序连接,最后头尾相连,其实就是结果,但是这个结果是粗糙的,为了使之成为真正的结果–凸包(也就是包含各个点,但是边长最短的图形),由三角形两边之和大于第三边,我们可以通过旋转判断从而去掉使图形凹陷的点,得到最终结果。
这里写图片描述

  • 必备知识

关于判断两个向量之间的旋转是逆时针还是顺时针,可以把二维向量扩充成三维,然后进行叉乘运算进而判断
如两个向量a=(xa,ya,0), b=(xb,yb,0)
由叉乘的运算得到 a x b=0 * i+0 * j+k(xa * yb - xb * ya);
所以只需要判断(xa * yb - xb * ya)的正负就可以确定旋转方向;

  • 推荐题目

    HDU 1392,1348

最后,个人水平是在有限,理解难免有错漏之处,希望大家指正。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:13897次
    • 积分:570
    • 等级:
    • 排名:千里之外
    • 原创:36篇
    • 转载:21篇
    • 译文:0篇
    • 评论:7条
    最新评论