問題描述
現有一個點p(x0,y0),多變形ptPolypon,判斷點p是否在多邊形內。
算法
判斷一個點是否在多邊形內,我們可以從該點引出一條水平射線(任意射線都可,但水平便於計算),觀察射線與多變形的交點個數,如果交點個數為奇數,則該點在多邊形內,如果為 偶數 則在多邊形外。
如圖 點在多邊形內,從該點做一條水平射線,與多邊形交點個數為2*n+1 為奇數,同理若點在多變形外為偶數。
如何判斷水平射線與多變形的邊有交點呢?
顯然,如果某條邊是水平的,那么肯定沒有交點
if (p1.y == p2.y) continue;
如果點p的縱坐標比多邊形某邊的縱坐標都小或都大,那么他們的交點一定在延長線上,如圖所示
if (p.y < min(p1.y, p2.y))
continue;
if (p.y >= max(p1.y, p2.y))
continue;
接下來我們考慮一般情況。要想判斷有沒有交點,我們只需要將多邊形某邊所在直線的方程求出,將p點的縱坐標y0帶入,即可求得交點橫坐標x,將x與x0比較,如果下x0<x,該點在多邊形內反之在多邊形外。
公式為:
\[x = (y0- p1.y)*(p2.x - p1.x)/ (p2.y - p1.y)+ x0 \]
完整代碼
struct Point
{
double x, y;
};
bool IsInPolygon(Point p,Point *ptPolygon,int ncount)
{
int ncross = 0;
for (int i = 0; i < ncount; i++)
{
Point p1 = ptPolygon[i];
Point p2 = ptPolygon[(i + 1) % ncount]; //相鄰兩條邊p1,p2
if (p1.y == p2.y)
continue;
if (p.y < min(p1.y, p2.y))
continue;
if (p.y >= max(p1.y, p2.y))
continue;
double x = (p.y - p1.y)*(p2.x - p1.x) / (p2.y - p1.y) + p1.x;
if (x > p.x)
ncross++; //只統計單邊交點
}
return(ncross % 2 == 1);
}