convex_hull/convex_hull.c

77 lines
1.8 KiB
C
Raw Permalink Normal View History

2024-12-13 07:20:28 +00:00
#include <stdlib.h>
2024-12-17 09:52:09 +00:00
// 定义点结构
2024-12-13 07:20:28 +00:00
typedef struct {
2024-12-17 09:52:09 +00:00
int x;
int y;
2024-12-13 07:20:28 +00:00
} Point;
2024-12-17 09:52:09 +00:00
// 计算叉积
double crossProduct(Point p0, Point p1, Point p2) {
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
2024-12-13 07:20:28 +00:00
}
2024-12-17 09:52:09 +00:00
// 计算两点间距离的平方
double distanceSquare(Point p1, Point p2) {
return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);
2024-12-13 07:20:28 +00:00
}
2024-12-17 09:52:09 +00:00
// 比较函数
Point p0;
int comparePoints(const void* vp1, const void* vp2) {
Point* p1 = (Point*)vp1;
Point* p2 = (Point*)vp2;
double cross = crossProduct(p0, *p1, *p2);
if (cross == 0) {
return (distanceSquare(p0, *p1) - distanceSquare(p0, *p2));
}
return (cross < 0) ? 1 : -1;
}
// 导出的凸包计算函数
void convexHull(Point* points, int n, Point* result, int* resultSize) {
2024-12-13 07:20:28 +00:00
if (n < 3) {
2024-12-17 09:52:09 +00:00
// 点数小于3直接复制所有点
for (int i = 0; i < n; i++) {
result[i] = points[i];
}
*resultSize = n;
2024-12-13 07:20:28 +00:00
return;
}
2024-12-17 09:52:09 +00:00
// 找到y坐标最小的点
int min = 0;
for (int i = 1; i < n; i++) {
if (points[i].y < points[min].y ||
(points[i].y == points[min].y && points[i].x < points[min].x)) {
min = i;
}
}
// 将最下方的点交换到points[0]
Point temp = points[0];
points[0] = points[min];
points[min] = temp;
// 保存最下方的点用于排序
p0 = points[0];
// 按极角排序
qsort(&points[1], n-1, sizeof(Point), comparePoints);
2024-12-13 07:20:28 +00:00
// 构建凸包
2024-12-17 09:52:09 +00:00
int m = 0;
result[m++] = points[0];
result[m++] = points[1];
result[m++] = points[2];
for (int i = 3; i < n; i++) {
while (m > 1 && crossProduct(result[m-2], result[m-1], points[i]) <= 0) {
2024-12-13 07:20:28 +00:00
m--;
2024-12-17 09:52:09 +00:00
}
2024-12-13 07:20:28 +00:00
result[m++] = points[i];
}
2024-12-17 09:52:09 +00:00
*resultSize = m;
}