课程:计算几何
书籍:计算几何:算法与应用
极边:对凸包有贡献的那些边。从Counter Clockwise来看,所有点都会落在极边的左侧(或者在极边上),而右侧为空。
根据该思路,我们只需判断任意两点所构成的边是否为极边,即其他点是否都在同一侧(后者在边上)。
判断点在边上的哪一侧,我们仍然使用O(n^4)算法中的ToLeft测试。
代码:
Patch.h与O(n^4)算法算法一样,就不再重复表述出来。
Main.cpp
/* indere 2018/6/22
* O(n^3)构造凸包算法思路为:其他所有顶点都落在一条边的一侧,则该边为极边,边的端点是极点
* 输入:顶点数以及顶点坐标
* 输出:极点编号(看情况是否按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 ToLeft(int v1, int v2, int s); //ToLeft Test
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;
}
for (int i = 0; i < pointsize; i++) {
for (int j = i + 1; j < pointsize; j++) {
bool EXISTLEFT = true;
bool EXISTRIGHT = true;
for (int s = 0; s < pointsize; s++) {
if (s != i && s != j ) {
int judge = ToLeft(i, j, s);
//这里我们对顶点在边上的情况不做判断 避免其产生错误结果
if (judge == 1) {
EXISTLEFT = false;
}
else if(judge == -1)
EXISTRIGHT = false;
}
}
if (EXISTLEFT || EXISTRIGHT) { //当其他所有顶点位于向量同侧时
points[i].isExtremePoint = true;
points[j].isExtremePoint = true;
}
}
}
}
int ToLeft(int v1, int v2, int s) {
float result = (points[v2].x * points[s].y + points[v1].x * points[v2].y + points[v1].y * points[s].x)
- (points[v1].y * points[v2].x + points[v1].x * points[s].y + points[v2].y * points[s].x);
if (result > 0.0f) //左侧
return 1;
if (result == 0.0f) //共线
return 2;
if (result < 0.0f) //右侧
return -1;
}