【計算幾何】點在多邊形內部

一點心青發表於2013-08-01

問題描述:已知點P(x,y)和多邊形Poly,判斷點P(x,y)是否在多邊形內部。

基本方法:射線法

以點P為端點,向左方作射線L,由於多邊形是有界的,所以射線L的左端一定在多邊形外部,考慮沿著L從無究遠處開始自左向右移動。

遇到和多邊形的第一個交點的時候,進入到了多邊形的內部,遇到第二個交點的時候,離開了多邊形...

因而當L和多邊形的交點數目C是奇數的時候,P在多邊形內,是偶數,則P在多邊形外。

特殊情況分析,如圖下圖(a),(b),(c),(d)所示。

圖(a)中,L和多邊形的頂點相交,交點只能計算一個。

圖(b)中,L和多邊形頂點的交點不應被計算。

圖(c)和(d)中,L和多邊形的一條邊重合,這條邊應該被忽略不計。

程式碼實現如下:

 1 typedef struct Point
 2 {
 3     int x;
 4     int y;
 5 }Point;
 6 //  The function will return YES if the point x,y is inside the polygon, or
 7 //  NO if it is not.  If the point is exactly on the edge of the polygon,
 8 //  then the function may return YES or NO.
 9 bool IsPointInPolygon(std::vector<Point> poly,Point pt)
10 {
11     int i,j;
12     bool c = false;
13     for (i = 0,j = poly.size() - 1;i < poly.size();j = i++)
14     {
15         if ((((poly[i].y <= pt.y) && (pt.y < poly[j].y)) ||
16             ((poly[j].y <= pt.y) && (pt.y < poly[i].y)))
17             && (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y)/(poly[j].y - poly[i].y) + poly[i].x))
18         {
19             c = !c;
20         }
21     }
22     return c;
23 }

程式碼分析:

條件1:((ploy[i].y <= pt.y) && (pt.y < poly[j].y)) || ((ploy[j].y <= pt.y) && (pt.y < poly[i].y))

由於判斷過程主要是判斷,射線L與多邊形每條邊是否存在交點,而射線L平行於X軸,因此條件1相當於判斷點P在Pi和Pj在垂直距離之間。

條件2: (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y)/(poly[j].y - poly[i].y) + poly[i].x)

條件2可轉換成:(pt.x - poly[i].x) * (poly[j].y - poly[i].y) - (poly[j].x - poly[i].x) * (pt.y - poly[i].y) < 0,相當於向量PiP和向量PiPj的叉積。

當向量PiP和向量PiPj的叉積小於0時,向量PiP在向量PiPj的逆時針方向,相當於向量PiP在向量PiPj的右側,而射線L由左側射出,而且點P在Pi和Pj在垂直距離之間,因此,射線L和PiPj的跨立條件成立,相交。

參考資料:

http://alienryderflex.com/polygon/

相關文章