目录

1 凸包的定义

1.1 顶点定义法

1.2 其他定义方法

2 Gift-wrapped算法

2.1 算法的思想

2.2 程序流程图

3 算法的实现(Java)

3.1 案例分析

3.2 代码


1 凸包的定义

凸包可分为二维凸包(Polygon)与三维凸包(Polyhedron),本文主要介绍二维凸包。

1.1 顶点定义法

给定空间上的有限点集S,由点集中有限个极点(Extreme Point)构成的凸对象(Convex Object),就称为凸多胞体。

极点可看成是多胞体的顶点,以二维多边形为例,极点就相当于凸多边形的顶点。使用严格的数学定义来说,极点是指那些不能由凸多胞体内的其它点的凸组合(Convex Combination)表示出来的点。给定点,...,一共k个点它的凸组合可以用下面的等式表示:

                                                            

一条线段就是它的端点的所有的凸组合,三角形就是它的三个顶点的凸组合,一个四面体是它的四个顶点的凸组合。

换句话,对于空间中的对象K,如果对象中的任意两个点构成的线段,也包含在对象K内,则称对象K是凸的。如下图所示的两个多边形P1和P2,多边形P1中的任意两点连成的线段也在多边形内,因此多边形P1是凸的;但是多边形P2中,存在两点的连成的线段不存多边形内的情况,如图中的线段,因此多边形P2不是凸的。

图1. 多边形P1、P2

1.2 其他定义方法

其它定义方法还包括:半空间半定义法、面(Facet)的定义、岭(Ridge)的定义等,本文主要介绍顶点定义法。

2 Gift-wrapped算法

2.1 算法的思想

  1. 找一个极点(左上角、左下角、右上角、右下角);
  2. 遍历所有点,找出和极点偏转角度最小的点(顺时针),当偏转角度相同时找与极点距离更远的点 ;
  3. 将当前点作为下一个极点,继续找点 ;
  4. 直到找到第一个极点,算法结束 。

2.2 程序流程图

图2. gift-wrapped算法流程图

3 算法的实现(Java)

3.1 案例分析

考虑依次输入的五个点(1,1)、(10,10)、(1,10)、(1,2)、(2,3)、(3,2),要求计算构成凸包周长顶点的输入点的最小子集。

对于这个问题,结合前面的算法思想,我们需要先完成一个计算与极点转动角度的函数calculateBearingtoPoint(double currentbearing, int currentX, int currentY, int targetX, int targetY)。

这个函数的思想就是:首先依据给定的起始点、目标点的坐标分坐标轴的四个象限来讨论计算出它们连线与north方向的夹角x(此时假设currentbearing为0),最后分两种情况:1.夹角角度大于起始角度:转动角度就等于夹角与起始角度的差值;2.夹角角度小于起始角度:转动角度就等于360.0与起始角度的差值再加上x。依据此原理,设计的calculateBearingToPoint函数:

public static double calculateBearingToPoint(double currentBearing, int currentX, int currentY, int targetX, int targetY) {double x=0,t1=0,t2=0,angle=0;t1 = (double) targetX - currentX;t2 = (double) targetY - currentY;angle = Math.toDegrees(Math.atan(t1 / t2));if(t2 == 0)x = t1 > 0 ? 90 : 270;else if((t1>=0 && t2>0) || (t1<0 && t2!=0))x = angle;elsex = 270 - angle;if(x >= currentBearing)return x - currentBearing;elsereturn 360 - currentBearing + x;}

然后结合前面的gift-wrapped算法的分析,完成convexHull(Set<Point> points)函数。

3.2 代码

public static double calculateBearingToPoint(double currentBearing, int currentX, int currentY, int targetX, int targetY) {double x=0,t1=0,t2=0,angle=0;t1 = (double) targetX - currentX;t2 = (double) targetY - currentY;angle = Math.toDegrees(Math.atan(t1 / t2));if(t2 == 0)x = t1 > 0 ? 90 : 270;else if((t1>=0 && t2>0) || (t1<0 && t2!=0))x = angle;elsex = 270 - angle;if(x >= currentBearing)return x - currentBearing;elsereturn 360 - currentBearing + x;}public static Set<Point> convexHull(Set<Point> points) {//throw new RuntimeException("implement me!");ArrayList<Point> cH = new ArrayList<Point>();ArrayList<Point> scH = new ArrayList<Point>();scH.addAll(points);int length = scH.size();Point p;if(length > 3){p = scH.get(0);for(int i=1; i<length; i++) //首先确定左下角的点为极点{if(p.x() > scH.get(i).x())p = scH.get(i);else if(p.x() == scH.get(i).x() && p.y() > scH.get(i).y())p = scH.get(i);}cH.add(p); // 将第一个极点加入凸包Point current=p;double smallangle,smalldis;int i=0;scH.remove(current);while(true){double currentbearing = 360.0, dis=0.0;Point point = null;for (Point target : scH){smallangle = calculateBearingToPoint(0, (int) current.x(), (int) current.y(),(int) target.x(), (int) target.y());smalldis = Math.pow(current.x() - target.x(), 2) + Math.pow(current.y() - target.y(), 2);if (smallangle < currentbearing){point = target;currentbearing = smallangle;dis = smalldis;}else if (smallangle == currentbearing && smalldis > dis) //偏角相同,取距离远的{point = target;dis = smalldis;}}current = point;cH.add(point);scH.remove(point);i++;if(i == 1)scH.add(p);if(cH.get(i) == p) //若再次遇到初始极点,则算法终止break;} Set<Point> res = new HashSet<Point>();res.addAll(cH);return res;}elsereturn points;}

凸包问题的gift-wrapped算法相关推荐

  1. 计算几何入门 1.4:凸包的构造——Jarvis March算法

    回顾凸包构造算法:极点法.极边法和增量构造法,其复杂度分别为O(n^4).O(n^3)和O(n^2),效率经过优化已经大大提高了.接下来引入一种新的算法--Jarvis March,其复杂度也是O(n ...

  2. [Poj 2187] 计算几何之凸包(二) {更高效的算法}

    { 承上一节 继续介绍点集的凸包  (下文中所有凸包 若不做特殊说明均指点集的凸包) 这一节介绍相比更高效的算法 } ========================================= ...

  3. C++ 基于凸包的Delaunay三角网生成算法

    Delaunay三角网,写了用半天,调试BUG用了2天--醉了. 基本思路比较简单,但效率并不是很快. 1. 先生成一个凸包: 2. 只考虑凸包上的点,将凸包环切,生成一个三角网,暂时不考虑Delau ...

  4. 计算几何入门 1.6:凸包的构造——Graham Scan算法

    上文简要分析出了凸包构造问题算法的下界:O(nlogn),在此就引入一种下界意义上最优的算法:Graham Scan算法.这种算法可以保证在最坏情况下时间复杂度也不超过nlogn.我们先大致了解一下算 ...

  5. 凸包问题的快包算法代码(C语言)

    二维凸包可以用来解决围栏问题.城市规划问题.聚类分析等等. 原文链接:http://blog.csdn.net/bone_ace/article/details/46239187 分治法 时间复杂度: ...

  6. HDUOJ 1392凸包graham算法

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  7. c++ 凸包 分治算法_三维凸包

    缘起 众所周知,二维凸包可以使用 Graham 扫描 内解决. 所以本文来学习一下三维空间中凸包的一种直观算法--增量算法(increment algorithm) 分析 有一条叫 Willy 的苹果 ...

  8. 分治法在求解凸包问题中的应用(JAVA)--快包算法

    分治法在求解凸包问题中的应用(JAVA) 之前写过一篇蛮力法在求解凸包问题中的应用(JAVA)还算简单易懂,没有基础的读者最好先去阅读以下. 这里用分治法来求解凸包问题,由于这个算法和快速排序十分相似 ...

  9. 算法学习笔记2:凸包及其解法

    凸包及其解法 凸包概念 解法 暴力解法 判断方向 分治 点到直线距离 Jarvis步进法 Graham扫描法 Andrew算法 凸包概念 在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集 ...

  10. 上凸包和下凸包_使用凸包聚类

    上凸包和下凸包 I recently came across the article titled High-dimensional data clustering by using local af ...

最新文章

  1. Linux 中的远程登陆
  2. 列表左右箭头滑动_我写了一套框架,把滑动窗口算法变成了默写题
  3. java 调度quartz,java quartz任务调度
  4. 再被补刀!Flash又遭抛弃,你会怀念它吗?
  5. 【POJ - 2632】Crashing Robots(模拟)
  6. 【文末有福利】5个字极简入门朴素贝叶斯模型
  7. 855计算机应用基础,2017年曲阜师范大学信息技术与传播学院855计算机应用基础考研导师圈点必考题汇编...
  8. Linux学习笔记7
  9. (18)FPGA面试技能提升篇(CACHE、MMU、DMA)
  10. php中统一编码语句,统一编码
  11. 微软2010年1月安全公告 Windows2000独领风骚
  12. 怎么样eclipse发达国家多重聚合关系maven项目和使用git管理
  13. python lambda表达式及用法_Python中lambda表达式的常见用法
  14. C++中的万能头文件
  15. java如何让源码加密还能运行_如何有效防止Java程序源码被人偷窥?
  16. android模拟器录制视频教程,畅玩安卓模拟器怎么录制视频?畅玩模拟器录制游戏视频图文教程...
  17. [单片机] KeilC51单块数码管演示与原理
  18. lvm扩容lv扩容操作记录
  19. “毒液” 高危漏洞背后的技术较量
  20. 华为路由器和交换机在BootROM下清除Console口密码

热门文章

  1. Linux内核win_minmax代码解读
  2. 戴着镣铐起舞的算法市场
  3. 22-05-15 西安 javaweb(01) html 、css、javaScript
  4. UML建模(五)需求之系统用例图
  5. win10误删微软商店,重新安装微软商店的方法
  6. Java执行cmd命令启动进程
  7. python之word文档生成
  8. 【阿里云短信验证码】麻瓜教程~~~从注册---申请---代码---执行
  9. HUAWEI 华为 MateBook X Pro 2020安装Ubuntu 18.04 LTS注意事项
  10. Java 图形化界面设计(GUI)实战练习(代码)