問題描述:已知點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的跨立條件成立,相交。
參考資料: