公司項目,要實現用戶在矩形的紅外圖像上圈一塊區域,計算該區域內部的平均溫度、最大、最小溫度,圈的區域有可能是矩形、橢圓、或者任意由多條線段構成的多邊形,實現這個需求可以轉換為求一個點是否在該幾何圖形內部,下麵總結一下各種幾何圖形的判斷方法。 1.矩形 判斷點是否在矩形內,只要確定點的坐標在矩形四個頂 ...
公司項目,要實現用戶在矩形的紅外圖像上圈一塊區域,計算該區域內部的平均溫度、最大、最小溫度,圈的區域有可能是矩形、橢圓、或者任意由多條線段構成的多邊形,實現這個需求可以轉換為求一個點是否在該幾何圖形內部,下麵總結一下各種幾何圖形的判斷方法。
1.矩形
判斷點是否在矩形內,只要確定點的坐標在矩形四個頂點限定範圍內即可
如上圖,滿足x<=x2&&x>x1&&y>y1&&y<y即可
2.橢圓
判斷點是否在橢圓內,可以根據橢圓表達式求得
如上圖,如果a>b,即焦點在x軸上,則滿足(x*x/a/a+y*y/b/b < 1)的點在橢圓內,如果a<b,即焦點在y軸上,則滿足(y*y/a/a+x*x/b/b<1)的點在橢圓內
3.由多個點構成的不規則圖形
對於不規則圖形,可以通過射線法判斷,即計算射線與多邊形各邊的交點,如果是偶數,則點在多邊形外,否則在多邊形內
演算法代碼如下:
public bool Contains(Point test) { int i; int j; bool result = false; for (i = 0, j = _pointList.Count - 1; i < _pointList.Count; j = i++) { if ((_pointList[i].Y > test.Y) != (_pointList[j].Y > test.Y) && (test.X < (_pointList[j].X - _pointList[i].X) * (test.Y - _pointList[i].Y) / (_pointList[j].Y - _pointList[i].Y) + _pointList[i].X)) { result = !result; } } return result; }
要計算射線與線段的交叉,可以觀察下圖:
- t點與線段(v1-v2)要發生相交,t.y必須線上段的兩個頂點的y值之間,即 t.y<v2.y&&t.y>v1.y
- 滿足上面這個條件以後,只需要判斷該點線上段的左側還是右側,如果線上段左側,則該射線與線段相交,要判斷t在左側還是右側,需要先求得水平線與線段的交點c的x坐標:c.x=(t.y-v1.y)*(v2.x-v1.x)/(v2.y-v1.y)+v1.x
由上兩條,可以推得,t點與線段相交的條件為: t.y<v2.y && t.y>v1.y && c.x<((t.y-v1.y)*(v2.x-v1.x)/(v2.y-v1.y)+v1.x)
接下來考慮一些特殊情況:
- v1.y==v2.y,即射線與線段重合,該情況不滿足第一個條件,因而對結果沒有影響
- 射線在頂點上相交,有如下幾種情況:
A頂點為交叉計數提供奇數(1),B、C為交叉計數提供偶數(分別是0、2),正好符合演算法條件,A是多邊形真正的交叉,B、C不是
演算法測試結果如下:
測試程式地址:https://github.com/xienb/SpatialRelationTest