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