今天实现以下Graham Scan算法算法,看了网上的资料,个人理解
1、找左下角点
2、对所有点相对该点的极角进行排序
3、将1、2入栈,以后的点逐个入栈,下一个新点如果满足逆时针旋转(右手准则),则该点入栈,如果是顺时针则该点放弃,再重复步骤 3,直到扫描到最后一个点结束
这里可以参考:https://blog.csdn.net/houszchina/article/details/79271765
https://blog.csdn.net/allenjiao/article/details/83828021
一下代码是参考别人的,主要把输入和输出参量用容器代替
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
struct Point
{
float x, y;
};
//小于0,说明向量p0p1的极角大于p0p2的极角,大于零,逆时针,小于零,顺时针
float multiply(Point p1, Point p2, Point p0)
{
return((p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y));
}
float dis(Point p1, Point p2)
{
return(sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y)));
}
vector<Point> My_Graham_Scan(vector<Point> PointSet, vector<Point> hull) // Graham扫描法
{
int i, j, k = 0, top = 2;
Point tmp;
int n = PointSet.size();
//找到最下且偏左的那个点
for (i = 1; i < n; i++)
{
if ((PointSet[i].y < PointSet[k].y) || ((PointSet[i].y == PointSet[k].y) && (PointSet[i].x < PointSet[k].x)))
{
k = i;
}
}
//将这个点指定为PointSet[0]
tmp = PointSet[0];
PointSet[0] = PointSet[k];
PointSet[k] = tmp;
//按极角从小到大,距离偏短排前进行遍历排序
for (i = 1; i<n - 1; i++)
{
k = i;
for (j = i + 1; j<n; j++)
{
if ((multiply(PointSet[j], PointSet[k], PointSet[0])>0) // k角大于i角 即基准角大于判断角,进行交换
|| ((multiply(PointSet[j], PointSet[k], PointSet[0]) == 0)
&& (dis(PointSet[0], PointSet[j]) < dis(PointSet[0], PointSet[k])))) // 最近点 即基准角大于判断角,进行交换
{
k = j; //k保存极角最小的那个点,或者相同距离原点最近
}
}
tmp = PointSet[i];
PointSet[i] = PointSet[k];
PointSet[k] = tmp;
}
//初始第一对向量,其中0,1位点边界
hull.push_back(PointSet[0]);
hull.push_back(PointSet[1]);
hull.push_back(PointSet[2]);
//判断与其余所有点的关系
for (i = 3; i<n; i++)
{
// 不满足向左转的关系,栈顶元素出栈
while (multiply(PointSet[i], hull[top], hull[top - 1]) >= 0)
{
top--;
hull.pop_back();
}
//当前点与栈内所有点满足向左关系,因此入栈.
hull.push_back(PointSet[i]);
++top;
}
return hull;
}
void main()
{
vector<Point> dot, hull;
Point p;
p.x = 10;
p.y = 20;
dot.push_back(p);
p.x = 3;
p.y = 5;
dot.push_back(p);
p.x = 6;
p.y = 2;
dot.push_back(p);
p.x = 8;
p.y = 10;
dot.push_back(p);
p.x = 15;
p.y = 10;
dot.push_back(p);
p.x = 7;
p.y = 9;
dot.push_back(p);
p.x = 8;
p.y = 1;
dot.push_back(p);
p.x = 4;
p.y = 3;
dot.push_back(p);
hull = My_Graham_Scan(dot, hull);
for(int i = 0; i < hull.size(); i++)
{
cout << "x:" << hull[i].x << " y:" << hull[i].y << endl;
}
system("pause");
}