课程:计算几何
书籍:计算几何:算法与应用
Jarvis March算法也是一种递增式的思路。以极边的一个端点为起点,来查找另一条极边。以此进行下去,最后构成一个环路时(极点的末端等于最初的起始端点)。凸包构造结束。
关于以一个极边为起始点的一天极边。可以用ToLeft测试进行比较,就如同O(n^2)中对点集逆时针排序那样。
关于如何确定起始点,我们选取字典序最小的点作为起始点(Y值最小的点,如果存在多个Y最小值一样的点,再选取X最小的点),起始方向,我们可随意设定。
代码:
Point.h 没有变化
Main.cpp
/* indere 2018/6/23
* O(hn)构造凸包算法思路为:Jarvis March
* 输入:顶点数以及顶点坐标
* 输出:极点编号(看情况是否按Counter-Clockwise输出)
/
/*
10
7 9
-8 -1
-3 -1
1 4
-3 9
6 -4
7 5
6 6
-6 10
0 8
*/
#include "Point.h"
Point *points;
int pointsize;
void Initialize(); //初始化points数组
void ConstructConvexHull(Point* points); //根据Point数组信息 构造凸包
int LTL(Point* points); //得到顶点数组中字典序最小的索引
int ToLeft(Point v1, Point v2, Point s); //
int main() {
Initialize();
ConstructConvexHull(points);
for (int i = 0; i < pointsize; i++) {
if (points[i].isExtremePoint)
cout << points[i];
}
return 0;
}
void Initialize() {
cin >> pointsize;
points = new Point[pointsize];
for (int i = 0; i < pointsize; i++) {
float x, y;
cin >> x >> y;
points[i] = Point(i + 1, x, y);
}
}
void ConstructConvexHull(Point* points) {
for (int i = 0; i < pointsize; i++) {
points[i].isExtremePoint = false;
}
int ltl = LTL(points);
int begin, end;
begin = ltl;
do {
points[begin].isExtremePoint = true;
end = -1;
for (int i = 0; i < pointsize; i++) {
if (i != begin && i != end && (end == -1 || ToLeft(points[begin], points[end], points[i]) == -1))
end = i;
}
begin = end;
} while (begin != ltl);
}
int LTL(Point* points) {
int k = 0;
for (int i = 1; i < pointsize; i++) {
if (points[k].y > points[i].y || (points[k].y == points[i].y && points[k].x > points[i].x)) {
k = i;
}
}
return k;
}
int ToLeft(Point v1, Point v2, Point s) {
float result = (v2.x *s.y + v1.x * v2.y + v1.y * s.x)
- (v1.y * v2.x + v1.x * s.y + v2.y * s.x);
if (result > 0.0f) //左侧
return 1;
if (result == 0.0f) //共线
return 2;
if (result < 0.0f) //右侧
return -1;
}