1. 程式人生 > >判斷某一點是否在幾何圖形內部

判斷某一點是否在幾何圖形內部

求一個 lis return 一個 項目 用戶 需要 公司 通過

  公司項目,要實現用戶在矩形的紅外圖像上圈一塊區域,計算該區域內部的平均溫度、最大、最小溫度,圈的區域有可能是矩形、橢圓、或者任意由多條線段構成的多邊形,實現這個需求可以轉換為求一個點是否在該幾何圖形內部,下面總結一下各種幾何圖形的判斷方法。

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

判斷某一點是否在幾何圖形內部