算法就不介紹了,其他地方應該也搜得到。
如何判斷三點A, B, C連線是逆時針?
(1) 通過判斷C在AB連線上方還是下方判斷,但需要根據斜率的正負,A, B位置關係分類討論,比較麻煩。
(2) 通過計算向量叉積的方法。
在一般的常識或者教科書中規定叉乘只有3維才擁有,其實2維也可以拓展出來一個叉乘形式。
拓展方式:假設有兩個2維向量a,b,我們直接把他們視爲3維向量,z軸補0,那麼這個時候的a,b向量的叉乘結果c,c.x=0,c.y=0,c.z=a.x* b.y-b.x *a.y。
有這樣的性質:設k是a,b向量的叉積,如果k>0時,那麼a正旋轉到b的角度爲<180°,如果k<0,那麼a正旋轉到b的角度爲>180°,如果k=0 那麼a,b向量平行。
代碼
#include<stdio.h>
#include<math.h>
#include<time.h>
#include<stdlib.h>
#define PI 3.14159
typedef struct Point {
int x, y;
double angle;
}Point;
int less(Point a, Point b) { //定義點a小於點b法則(排序用)
if (a.angle != b.angle) return a.angle < b.angle;
else return a.x < b.x;
}
int ifAnticlockwise(Point a, Point b, Point c) { //是否爲逆時針
int crossProduct = (b.x - a.x)*(c.y - b.y) - (b.y - a.y)*(c.x - b.x); //求向量積
return crossProduct >= 0; //向量積爲正表示逆時針
}
int main() {
srand((unsigned)time(NULL));
int n, minx, maxx, miny, maxy;
scanf("%d%d%d%d%d", &n, &minx, &maxx, &miny, &maxy);
Point point[105];
for (int i = 0; i < n; i++) { //生成隨機座標
point[i].x = rand() % (maxx - minx + 1) + minx;
point[i].y = rand() % (maxy - miny + 1) + miny;
}
double sx = 1000, sy = 1000;
for (int i = 0; i < n; i++) { //尋找起始點
if (point[i].y < sy) sx = point[i].x, sy = point[i].y;
else if (point[i].y == sy && point[i].x < sx) sx = point[i].x;
}
for (int i = 0; i < n; i++) { //求夾角
if (point[i].x == sx && point[i].y == sy) point[i].angle = 0;
else if (point[i].x == sx) point[i].angle = 90;
else {
point[i].angle = atan((point[i].y - sy)*1.0 / (point[i].x - sx));
if (point[i].angle < 0) point[i].angle = PI + point[i].angle;
//轉換爲與x軸正方向夾角
}
}
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) { //冒泡排序
if (less(point[j], point[i])) {
Point temp = point[i];
point[i] = point[j];
point[j] = temp;
}
}
}
int cnt = 3; //棧頂指針
for (int i = 3; i < n; i++) {
if (ifAnticlockwise(point[cnt - 2], point[cnt - 1], point[i])) {
point[cnt++] = point[i]; //模擬入棧
}
else point[cnt - 1] = point[i]; //模擬出棧+入棧
}
for (int i = cnt - 1; i >= 0; i--) { //逆序輸出
printf("%4d %4d ", point[i].x, point[i].y);
}
return 0;
}
程序測試
爲了驗證程序的正確性,先縮小了樣本,隨機生成橫縱座標都在-10~10範圍內的6個點,輸出第一行爲隨機生成的6個點的橫縱座標,接着輸出結果。將點在matlab中繪製,可以驗證程序正確。