終極大招來了,射線法是解決這一問題的最優方法,其他方法僅具有理論意義,如果工程應用的話,知道這個方法就夠了。
射線法的思想是:以目標點爲端點引一條射線,計算這條射線和多邊形所有邊的交點數目。如果交點個數爲奇數,則點在多邊形部,反之則在多邊形外部。
圖例說明,如下圖所示:
所謂射線法,關鍵在於單向發射,爲簡化問題,以水平線爲例,程序實現中也是這麼處理的。O點向右發出射線,與多邊形的交點是B、C、D,向左發出射線,交點是A,均爲奇數個。P點在多邊形外,無論想哪方向發出攝像,都有2個交點。
對於帶內島的形狀,射線法同樣適用,如上圖所示。在實際應用中,射線法會有很多特殊情況需要討論,全部都討論會比較複雜,但結論是一樣的。這裏不做過多討論了,不過可以給大家結論:射線法適用於所有類型的多邊形進行點與多邊形關係的判斷,且實現相對簡單,速度較快,是工程應用的不二之選。要注意的是,計算中所有數值都要選擇浮點數類型,以保證計算精度。
參考代碼如下:
int InPolygon_Ray(const CZPolygon& polygon, CZPoint_t pt) {
int itNumPt = polygon.size();
CZPoint_t pt_1, pt_2;
int itJunctionCount = 0;
for (int i = 0; i < (itNumPt - 1); i++) {
pt_1 = polygon[i];
pt_2 = polygon[i + 1];
if (((pt.y >= pt_1.y) && (pt.y <= pt_2.y)) || ((pt.y >= pt_2.y) && (pt.y <= pt_1.y))) {
double duT = (pt.y - pt_1.y) / (pt_2.y - pt_1.y);
double duXT = pt_1.x + duT * (pt_2.x - pt_1.x);
if (pt.x == duXT)
return ONSIDE;
if (pt.x > duXT)
itJunctionCount++;
}
}
return itJunctionCount % 2 ? INSIDE : OUTSIDE;
}
這次要上兩張圖了,以說明射線法的有效性。