现在的位置: 首页 > 综合 > 正文

如何判断一个指定的经纬度点是否落在一个多边形内

2013年09月14日 ⁄ 综合 ⁄ 共 2970字 ⁄ 字号 评论关闭

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;
        }

抱歉!评论已关闭.