参考:

找凸包方法_RedGeek的博客-CSDN博客

以及老师上课的PPT(幕布里)

#include <iostream>
#include <utility>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<double, double> POINT;
vector<POINT>vec;              //POINT 是 pair<double, double>
/*
函数方向确定线段的方向
p1p相对于p点转向p2p
如果返回值为正,则表示顺时针方向;
如果返回值为负,则menas为逆时针方向;
零表示在同一条线上;
*/
double direction(POINT p, POINT p1, POINT p2)
{POINT v1, v2;       //这个时候v1和v2就不是点了,而是向量。first是向量的括号的第一个数v1.first = p2.first - p.first;v1.second = p2.second - p.second;v2.first = p1.first - p.first;v2.second = p1.second - p.second;return v1.first * v2.second - v1.second * v2.first; //两个向量叉积的计算公式
}
//看点p是否可能在线段p1p2上面,类似【快速排斥】,只不过判断的不是两线段是否相交,而是某点是否可能落在p1p2上面。
//结合d==0(说明共线)和这个的true(说明p在p1p2圈出的矩形里面)就可以明确判断p是在p1p2线段上。
bool on_segment(POINT p, POINT p1, POINT p2)
{double min_x = p1.first < p2.first ? p1.first : p2.first;double max_x = p1.first > p2.first ? p1.first : p2.first;double min_y = p1.second < p2.second ? p1.second : p2.second;double max_y = p1.second > p2.second ? p1.second : p2.second;if (p.first >= min_x && p.first <= max_x && p.second >= min_y && p.second <= max_y)return true;elsereturn false;
}POINT startPoint;  //简称点s
//跟老师讲的不一样。他好像是真的用皮筋环绕的方法写的,因为没有弹栈的动作,说明他每次得到的point[0]都是皮筋该绕的点。。。
bool sortByPolorAngle(const POINT& p1, const POINT& p2)  //函数返回true的时候,会把p1放在前面!!!!!懂了sort的排序原理了
{double d = direction(startPoint, p1, p2); //direction判断【p1s到p2s】的旋转方向!!!if (d < 0) return true;    //d<0说明逆时针。所以他是按【p1s到p2s】为逆时针的情况来排序p1和p2,所以拍完之后point[0]的位置就是橡皮筋最外面的那个结点,66666666//结合这张图比划一下https://api2.mubu.com/v3/document_image/1639107215964ad0a.jpgif (d > 0) return false;if (d == 0 && on_segment(startPoint, p1, p2)) return true;  //如果在一条直线上,再判断点s是否在线段p1p2上面(s在p1p2上面这种情况就很诡异,问老师吧)if (d == 0 && on_segment(p2, startPoint, p1)) return true;  //如果在一条直线上,再判断点p2是否在线段sp1上面//如果是,那就把p1放在p2前面,因为p1是最远的,为啥不是p2最远??return false;      //其他情况就把p2放p1前面
}//找凸包convex_hull
void find_convex_hull(vector<POINT>& point)
{POINT p0 = point[0];int k = 0;for (int i = 1; i < point.size(); i++){if (point[i].second < p0.second ||point[i].second == p0.second && point[i].first < p0.first){p0 = point[i];k = i;} //首先 找到最下面的点p0,如果找到最下边的点有相同的,那么选择最左边的点。 }point.erase(point.begin() + k); //k是凸包集中的一个点 ,把凸包移除 (不和自己) (先把自己移出,然后再加到头部?)point.insert(point.begin(), p0); //把最低点放到point[0] vector<POINT> convex_hull; // 作为栈使用 do {convex_hull.push_back(point[0]);      //要进去之前肯定得判断,肯定是再上一个while循环里面判断的startPoint = point[0];      //已入栈的那个点point.erase(point.begin());//删除插入的坐标。相当于这个点从point跑到了hull//这个排序涉及到startPoint这个初始点和两个没有进栈的点sort(point.begin(), point.end(), sortByPolorAngle); //意思是对一整个剩下的point按照极角大小进行排序?应该没这么简单if (point[0] == convex_hull[0]) break; //此时point[0]是指向下一个坐标,如果回到起点,循环结束 //等于先把队首给hull的尾巴,然后最后再复制hull的尾巴到自己的尾巴,point的元素数量保持不变point.push_back(convex_hull[convex_hull.size() - 1]);   //把hull里面最后一个元素入point的尾巴干嘛??可能真的就是为了能判断break的条件。那感觉只要把第一个塞进队尾就行了,但是这样出现重复的点可能在排序的时候出问题。} while (1);//输出凸包的坐标for (int i = 0; i < convex_hull.size(); i++){cout << convex_hull[i].first << ' '<< convex_hull[i].second << endl;}
}void initVector()
{vec.push_back(POINT(-1, -2));vec.push_back(POINT(1, -1));vec.push_back(POINT(3, -1));vec.push_back(POINT(2, 1));vec.push_back(POINT(4, 2));vec.push_back(POINT(1, 3));vec.push_back(POINT(0, 2));vec.push_back(POINT(-1, 1));vec.push_back(POINT(-2, 2));
}
int main() {initVector();find_convex_hull(vec);return 0;
}

实验三:凸包(输入点坐标计算凸包坐标)相关推荐

  1. 数据统计与分析基础实验三:常规数学统计计算(R语言,还没写完)

    数据统计与分析基础实验三:常规数学统计计算 1.随机生成一个10x15的高斯矩阵,均值为自己学号后两位,方差为1.对该矩阵分别进行LU.QR.奇异值,并展示分解结果. LU QR 奇异值 2.利用软件 ...

  2. 实验三 FFT及其在卷积计算和谱分析中的应用

    目录 一.实验目的 二.实验内容 三.实验思考 一.实验目的 1.在理论学习的基础上,通过本实验,加深对FFT的理解,熟悉FFT子程序: 2.熟练掌握FFT实现两个序列的线性卷积的方法: 3.熟悉应用 ...

  3. 实验三 数据输入与输出(长沙理工大学—)

    第1关:各位数字之和 任务描述 本关任务:输入一个三位正整数,输出其个位.十位和百位上数字之和. 编程要求 根据提示,在右侧编辑器补充代码,输入一个三位正整数,输出其个位.十位和百位上数字之和. 测试 ...

  4. 旋转矩阵的应用:已知旋转前后的点坐标计算旋转中心坐标

    点A(x1,y1)绕圆心C(x,y)旋转角为点B(x2,y2),已知点A.B坐标以及角,求解圆心C(x,y)坐标. 根据二维旋转公式: 根据此问题将A相对C的坐标和B相对C的坐标代入以上公式: 因为, ...

  5. 全站仪坐标计算机公式,全站仪使用方法及坐标计算讲解

    大家都知道随着建筑工程和仪器设备的发展,全站仪现已替代了经纬仪广泛应用于建筑工程中. 为了更好的掌握测量放线知识,今天对全站仪的使用和坐标计算和大家相互交流学习一下. 全站仪常规注意事项 在使用本仪器 ...

  6. 次坐标从0开始_全站仪测量使用方法及坐标计算教程

    全站仪常规注意事项: 在使用本仪器之前, 要把各种注意事项烂熟于心,务必检查并确认该仪器各项功能运行正常. 1.不要将仪器直接对准太阳 将仪器直接对准太阳会严重伤害眼睛.若仪器的物镜直接对准太阳, 也 ...

  7. 次坐标从0开始_全站仪测量使用方法及坐标计算,视频一步一步讲解

    全站仪常规注意事项: 在使用本仪器之前, 要把各种注意事项烂熟于心,务必检查并确认该仪器各项功能运行正常. 1.不要将仪器直接对准太阳 将仪器直接对准太阳会严重伤害眼睛.若仪器的物镜直接对准太阳, 也 ...

  8. 次坐标从0开始_全站仪使用方法及坐标计算讲解

    大家都知道随着建筑工程和仪器设备的发展,全站仪现已替代了经纬仪广泛应用于建筑工程中. 为了更好的掌握测量放线知识,今天对全站仪的使用和坐标计算和大家相互交流学习一下. 全站仪常规注意事项 在使用本仪器 ...

  9. python编译程序输入上网时间并计算上网费用 计算方法_同济大学Python程序设计基础 实验三:选择结构...

    实验三 第一题 1.求一元二次方程的根. 要求:输入一元二次方程的三个系数a.b.c,根据系数值,可得出如下三种根: (1)△>0,两个实根 (2)△=0,重根,即相同根 (3)△<0,无 ...

最新文章

  1. 网络运行时间提高100倍,Google使用的AI视频理解架构有多强?
  2. FPGA之道(52)状态机的概念
  3. 错误:请求“ ..”中的成员“ ..”属于非类类型
  4. 基于MT6752/32平台 Android L版本驱动移植步骤
  5. 深入浅出谈接口(interface)和类间继承(extends)
  6. Redis 的应用场景
  7. 流浪宠物救助网站前端页面_全国爱心人士齐聚鞍山 救助流浪猫狗
  8. Linux查看tar实用程序,linux tar指令常用选项
  9. android gpu 视频编码,android – 编码器崩溃对Adreno GPU编码从Surface
  10. C Primer Plus 第9章 函数 9.4 多源代码文件程序的编译
  11. Hibernate中saveOrUpdate()和merge()的区别
  12. C语言———不定参数标准库 stdarg.h
  13. 虚拟机文件系统混乱,导致编译失败
  14. pdf需要简体中文语言支持包_收集全网最好用的PDF转Word工具,赶快收藏起来!...
  15. 苹果13可以用无线充电宝吗?苹果专用无线充电宝推荐
  16. JAVA课程设计——医院挂号系统
  17. ie禁用java怎么办,您如何解决IE中禁用javascript的问题?
  18. eclipse 3.7 中英文自由切换
  19. 拉格朗日插值法 【python】
  20. Oracle主机变量锚定、游标变量

热门文章

  1. 电脑快捷修改计算机名
  2. 自建服务器同步软件,黑群晖自建anki服务器电脑anki软件设置同步
  3. sit是什么环境_测试环境是什么_搭建测试环境要遵循什么原则?
  4. 计算机视觉领域的一些牛人博客,研究机构等的网站链接 机器学习算法中文视频教程
  5. 多线程-day-09CAS原理
  6. ios16隐藏的六个实用功能,你知道几个?
  7. 中国人民银行 中国银行业监督管理委员会关于印发农村信用社改革试点专项中央银行票据兑付考核办法的通知(银发[2004]253号)
  8. python保存不了_python文件无法保存怎么解决
  9. java实现word文件转图片,支持分页
  10. 固件-驱动-软件 区别