如何判斷一個指定的經緯度點是否落在一個多邊形內

來源:互聯網
上載者:User

1、理論支援:如果從需要判斷的點出發的一條射線與該多邊形的焦點個數為奇數,則該點在此多邊形內,否則該點在此多邊形外。(射線不能與多邊形頂點相交)

2、編程思路:

該程式的思路是從A點出發向左做一條水平射線(平行於x軸,向X軸的反方向),判斷與各邊是否有焦點。

dLon1, dLon2, dLat1, dLat2分別表示邊的起點和終點的經度和緯度(x軸和y軸)。

先判斷A點是否在邊的兩端點d1和d2的水平平行線之間,不在則不可能有交點,繼續判斷下一條邊。

在之間則說明可能與A點向左的射線有交點,接下來利用幾何方法得到A點的水平直線與該邊交點的x座標。

然後判斷交點的x座標在A點的左側還是右側,左側則總交點數加一,右側則不在A點左射線上,繼續判斷下一條邊。

3、原文代碼如下(Dephi):
Type
  TMyPoint = packed record
    X : double;
    Y : double;
  end;

{*------------------------------------------------------------------------------
  判 斷指定的經緯度座標點是否落在指定的多邊形地區內
  @param ALon   指定點的經度
  @param ALat   指定點的緯度
  @param APoints   指定多邊形地區各個節點座標
  @return True 落在範圍內 False 不在範圍內
------------------------------------------------------------------------------*}
function IsPtInPoly(ALon, ALat: double; APoints: array of TMyPoint): Boolean;
var
  iSum, iCount, iIndex: Integer;
  dLon1, dLon2, dLat1, dLat2, dLon: double;
begin
  Result := False;
  if (Length(APoints) < 3) then
  begin
    Result := False;
    Exit;
  end;
  iSum := 0;
  iCount := Length(APoints);
  for iIndex :=0 to iCount - 1 do
  begin
    if (iIndex = iCount - 1) then
    begin
      dLon1 := APoints[iIndex].X;
      dLat1 := APoints[iIndex].Y;
      dLon2 := APoints[0].X;
      dLat2 := APoints[0].Y;
    end
    else
    begin
      dLon1 := APoints[iIndex].X;
      dLat1 := APoints[iIndex].Y;
      dLon2 := APoints[iIndex + 1].X;
      dLat2 := APoints[iIndex + 1].Y;
    end;
   //以下語句判斷A點是否在邊的兩端點的水平平行線之間,在則可能有交點,開始判斷交點是否在左射線上
    if ((ALat >= dLat1) and (ALat < dLat2)) or ((ALat>=dLat2) and (ALat < dLat1)) then
    begin
      if (abs(dLat1 - dLat2) > 0) then
      begin

       //得到 A點向左射線與邊的交點的x座標:
        dLon := dLon1 - ((dLon1 -dLon2) * (dLat1 -ALat)) / (dLat1 - dLat2);

       // 如果交點在A點左側(說明是做射線與 邊的交點),則射線與邊的全部交點數加一:
        if (dLon < ALon) then
          Inc(iSum);
      end;
    end;

  end;
  if (iSum mod 2 <> 0) then
    Result := True;
end;


(C#)

public bool IsPtInPoly(double ALon, double ALat, List<Point> APoints)
        {
            int iSum = 0, iCount;
            double dLon1, dLon2, dLat1, dLat2, dLon;
            if (APoints.Count < 3)
                return false;
            iCount = APoints.Count;
            for (int i = 0; i < iCount - 1; i++)
            {
                if (i == iCount - 1)
                {
                    dLon1 = APoints[i].X;
                    dLat1 = APoints[i].Y;
                    dLon2 = APoints[0].X;
                    dLat2 = APoints[0].Y;
                }
                else
                {
                    dLon1 = APoints[i].X;
                    dLat1 = APoints[i].Y;
                    dLon2 = APoints[i + 1].X;
                    dLat2 = APoints[i + 1].Y;
                }
                //以下語句判斷A點是否在邊的兩端點的水平平行線之間,在則可能有交點,開始判斷交點是否在左射線上
                if (((ALat >= dLat1) && (ALat < dLat2)) || ((ALat >= dLat2) && (ALat < dLat1)))
                {
                    if (Math.Abs(dLat1 - dLat2) > 0)
                    {
                        //得到 A點向左射線與邊的交點的x座標:
                        dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - ALat)) / (dLat1 - dLat2);

                        // 如果交點在A點左側(說明是做射線與 邊的交點),則射線與邊的全部交點數加一:
                        if (dLon < ALon)
                            iSum++;
                    }
                }
            }
            if (iSum % 2 != 0)
                return true;
            return false;
        }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.