轉自http://blog.sina.com.cn/s/blog_73000beb0101d4m0.htmlhtml
在GIS(地理信息管理系統)中,判斷一個座標是否在多邊形內部是個常常要遇到的問題。乍聽起來還挺複雜。根據W. Randolph Franklin 提出的PNPoly算法,只需區區幾行代碼就解決了這個問題。
假設多邊形的座標存放在一個數組裏,首先咱們須要取得該數組在橫座標和縱座標的最大值和最小值,根據這四個點算出一個四邊型,首先判斷目標座標點是否在這個四邊型以內,若是在這個四邊型以外,那能夠跳事後面較爲複雜的計算,直接返回false。
算法
if (p.x < minX || p.x > maxX || p.y < minY || p.y > maxY) {
// 這個測試都過不了。。。直接返回false;
}
接下來是核心算法部分:
int pnpoly (int nvert, float *vertx, float *verty, float testx, float testy) {數組
int i, j, c = 0;
for (i = 0, j = nvert-1; i < nvert; j = i++) {
if ( ( (verty[i]>testy) != (verty[j]>testy) ) &&
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
c = !c;
}
return c;
}
額,代碼就這麼簡單,但到底啥意思呢:
首先,參數nvert 表明多邊形有幾個點。浮點數testx, testy表明待測試點的橫座標和縱座標,*vertx,*verty分別指向儲存多邊形橫縱座標數組的首地址。
咱們注意到,每次計算都涉及到相鄰的兩個點和待測試點,而後考慮兩個問題:測試
1. 被測試點的縱座標testy是否在本次循環所測試的兩個相鄰點縱座標範圍以內?即htm
verty[i] <testy < verty[j]blog
或者數學
verty[j] <testy < verty[i]test
2. 待測點test是否在i,j兩點之間的連線之下?看不懂後半短if statement的朋友請自行在紙上寫下i,j兩點間的斜率公式,要用到一點初中解析幾何和不等式的知識範疇,對廣大碼農來講小菜一碟。循環
而後每次這兩個條件同時知足的時候咱們把返回的布爾量取反。float
可這究竟是啥意思啊?
這個表達式的意思是說,隨便畫個多邊形,隨便定一個點,而後經過這個點水平劃一條線,先數數看這條橫線和多邊形的邊相交幾回,(或者說先排除那些不相交的邊,第一個判斷條件),而後再數這條橫線穿越多邊形的次數是否爲奇數,若是是奇數,那麼該點在多邊形內,若是是偶數,則在多邊形外。詳細的數學證實這裏就不作了,不過讀者能夠自行畫多邊形進行驗證。