博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
计算几何--凸包总结
阅读量:6293 次
发布时间:2019-06-22

本文共 2612 字,大约阅读时间需要 8 分钟。

了解凸包及Graham扫描法

       问题描述:二位平面内,给定n个散乱的点,求一个最小凸多边形(凸包),使得n个点都不在凸多边形外。

       问题的解决用到Graham算法:

算法步骤:

  1.取y坐标最小的一点,作为p0,显然p0一定在凸包上。

 

  2.将p0作为坐标系原点,其他点按极角从小到大排序,从p1开始编号。

 

 

  3.从小到大遍历所有点:显然[p0, p1] 在凸包中

 

 

  4.连接p1, p2的时候需要判断:p0->p1 叉乘 p1->p2 是否大于0:

    > 0 p1->p2 在 p0->p1 夹角小于π,物理意义:p1->p2 在 p0->p1的左边,满足凸多边形定义。

    = 0 p1->p2 与 p0->p1 共线,同向满足,相反不满足。

    < 0 p1->p2 在 p0->p1 夹角大于π,不满足。

 

 

  5.连接p2, p3 向量p2->p3在p1->p2左边,满足定义,当连接p3, p4的时候,发现不满足定义了,此时要放弃p3, 从p2开始回溯,找到第一个满足要求的点。

 

 

  6.以此类推,知道回到p0点。

 

 

Graham scan 正确性:

       令散点的数量为k,散点(p0 ~ pk – 1)已经按照极角排序。

       当k=3时,显然,p0->p1时凸包的一条边,且p2 极角小于p1, 那么p1->p2在p0->p1的左侧,所以p1->p2保留。

       当k=n时,假设此时(p0 ~ pn – 1) 都按照Graham scan找出“最完美的凸包”

       当k=n+1时,如果pn – 1 -> pn 在 pn – 2 > pn – 1左边,如下图,如果舍弃pn,直接连接pn – 1 -> p0, 那么pn在多边形外,不满足要求。

      

 

              证毕。

代码实现:

/****************************凸包模板*******************************/const double eps = 1e-8;int sgn(double x) {  if (fabs(x) < eps)    return 0;  if (x < 0)    return -1;  else    return 1;}struct Point {  double x, y;  Point() {}  Point(double _x, double _y) {    x = _x;    y = _y;  }  Point operator-(const Point &b) const { return Point(x - b.x, y - b.y); }  //叉积  double operator^(const Point &b) const { return x * b.y - y * b.x; }  //点积  double operator*(const Point &b) const { return x * b.x + y * b.y; }  void input() {    scanf("%lf%lf", &x, &y);  }};struct Line {  Point s, e;  Line() {}  Line(Point _s, Point _e) {    s = _s;    e = _e;  }};//*两点间距离double dist(Point a, Point b) { return sqrt((a - b) * (a - b)); }/* * 求凸包,Graham算法 * 点的编号0~n-1 * 返回凸包结果Stack[0~top-1]为凸包的编号 */const int MAXN = 1010;Point List[MAXN];int Stack[MAXN];  //用来存放凸包的点int top;  //表示凸包中点的个数//相对于List[0]的极角排序bool _cmp(Point p1, Point p2) {  double tmp = (p1 - List[0]) ^(p2 - List[0]);  if (sgn(tmp) > 0)    return true;  else if (sgn(tmp) == 0 && sgn(dist(p1, List[0]) - dist(p2, List[0])) <= 0)    return true;  else    return false;}void Graham(int n) {  Point p0;  int k = 0;  p0 = List[0];  //找最下边的一个点  for (int i = 1; i < n; i++) {    if ((p0.y > List[i].y) || (p0.y == List[i].y && p0.x > List[i].x)) {      p0 = List[i];      k = i;    }  }  swap(List[k], List[0]);  sort(List + 1, List + n, _cmp);  if (n == 1) {    top = 1;    Stack[0] = 0;    return;  }  if (n == 2) {    top = 2;    Stack[0] = 0;    Stack[1] = 1;    return;  }  Stack[0] = 0;  Stack[1] = 1;  top = 2;  for (int i = 2; i < n; i++) {    while (top > 1 &&        sgn((List[Stack[top - 1]] - List[Stack[top - 2]]) ^ (List[i] - List[Stack[top - 2]])) <= 0)      top--;    Stack[top++] = i;  }}/****************************凸包模板*******************************/

 

转载于:https://www.cnblogs.com/wuwangchuxin0924/p/6223152.html

你可能感兴趣的文章
轻松学PHP
查看>>
Linux中的网络监控命令
查看>>
this的用法
查看>>
windows下安装redis
查看>>
CentOS7 yum 安装git
查看>>
启动日志中频繁出现以下信息
查看>>
httpd – 对Apache的DFOREGROUND感到困惑
查看>>
分布式锁的一点理解
查看>>
idea的maven项目,install下载重复下载本地库中已有的jar包,而且下载后jar包都是lastupdated问题...
查看>>
2019测试指南-web应用程序安全测试(二)指纹Web服务器
查看>>
树莓派3链接wifi
查看>>
js面向对象编程
查看>>
Ruby中类 模块 单例方法 总结
查看>>
jQuery的validate插件
查看>>
5-4 8 管道符 作业控制 shell变量 环境变量配置
查看>>
Enumberable
查看>>
开发者论坛一周精粹(第五十四期) 求购备案服务号1枚!
查看>>
validate表单验证及自定义方法
查看>>
javascript 中出现missing ) after argument list的错误
查看>>
使用Swagger2构建强大的RESTful API文档(2)(二十三)
查看>>