方位と距離を指定して座標を計算する
-
22-08-2019 - |
質問
ここで説明されている関数の実装に問題があります ここ.
これは私の Java 実装です。
private static double[] pointRadialDistance(double lat1, double lon1,
double radianBearing, double radialDistance) {
double lat = Math.asin(Math.sin(lat1)*Math.cos(radialDistance)+Math.cos(lat1)
*Math.sin(radialDistance)*Math.cos(radianBearing));
double lon;
if(Math.cos(lat) == 0) { // Endpoint a pole
lon=lon1;
}
else {
lon = ((lon1-Math.asin(Math.sin(radianBearing)*Math.sin(radialDistance)/Math.cos(lat))
+Math.PI) % (2*Math.PI)) - Math.PI;
}
return (new double[]{lat, lon});
}
関数を呼び出す前に、度方位をラジアンに変換し、距離 (km) をラジアン距離に変換します。したがって、それは問題ではありません。
ただし、次のような座標を入力すると、緯度 = 49.25705;ロン = -123.140259;方位は 225 (南西)、距離は 1 km
これが返されます:緯度:-1.0085434360125864 LON:-3.7595299668539504
それは明らかに正しくありません。誰かが私が間違っていることを理解できますか?
ありがとう
解決
コードには次の問題があるようです。
- 変換する必要があります
lat1
そしてlon1
関数を呼び出す前にラジアンに変換します。 - スケーリングしている可能性があります
radialDistance
間違っています。 - 浮動小数点数が等しいかどうかをテストするのは危険です。正確な演算後に等しい 2 つの数値は、浮動小数点演算後には正確に等しくない場合があります。したがって
abs(x-y) < threshold
よりも安全ですx == y
2 つの浮動小数点数をテストする場合x
そしてy
平等のために。 - 変換したいと思います
lat
そしてlon
ラジアンから度まで。
Python でのコードの実装は次のとおりです。
#!/usr/bin/env python
from math import asin,cos,pi,sin
rEarth = 6371.01 # Earth's average radius in km
epsilon = 0.000001 # threshold for floating-point equality
def deg2rad(angle):
return angle*pi/180
def rad2deg(angle):
return angle*180/pi
def pointRadialDistance(lat1, lon1, bearing, distance):
"""
Return final coordinates (lat2,lon2) [in degrees] given initial coordinates
(lat1,lon1) [in degrees] and a bearing [in degrees] and distance [in km]
"""
rlat1 = deg2rad(lat1)
rlon1 = deg2rad(lon1)
rbearing = deg2rad(bearing)
rdistance = distance / rEarth # normalize linear distance to radian angle
rlat = asin( sin(rlat1) * cos(rdistance) + cos(rlat1) * sin(rdistance) * cos(rbearing) )
if cos(rlat) == 0 or abs(cos(rlat)) < epsilon: # Endpoint a pole
rlon=rlon1
else:
rlon = ( (rlon1 - asin( sin(rbearing)* sin(rdistance) / cos(rlat) ) + pi ) % (2*pi) ) - pi
lat = rad2deg(rlat)
lon = rad2deg(rlon)
return (lat, lon)
def main():
print "lat1 \t lon1 \t\t bear \t dist \t\t lat2 \t\t lon2"
testcases = []
testcases.append((0,0,0,1))
testcases.append((0,0,90,1))
testcases.append((0,0,0,100))
testcases.append((0,0,90,100))
testcases.append((49.25705,-123.140259,225,1))
testcases.append((49.25705,-123.140259,225,100))
testcases.append((49.25705,-123.140259,225,1000))
for lat1, lon1, bear, dist in testcases:
(lat,lon) = pointRadialDistance(lat1,lon1,bear,dist)
print "%6.2f \t %6.2f \t %4.1f \t %6.1f \t %6.2f \t %6.2f" % (lat1,lon1,bear,dist,lat,lon)
if __name__ == "__main__":
main()
出力は次のとおりです。
lat1 lon1 bear dist lat2 lon2
0.00 0.00 0.0 1.0 0.01 0.00
0.00 0.00 90.0 1.0 0.00 -0.01
0.00 0.00 0.0 100.0 0.90 0.00
0.00 0.00 90.0 100.0 0.00 -0.90
49.26 -123.14 225.0 1.0 49.25 -123.13
49.26 -123.14 225.0 100.0 48.62 -122.18
49.26 -123.14 225.0 1000.0 42.55 -114.51
他のヒント
基本的に、あなたの問題はあなたが度ではなくラジアンとして緯度、経度、ベアリングを渡しているということであることが表示されます。あなたは常にあなたの関数にラジアンを渡し、あなたが戻って得るものを見ていることを確実にしてみます。
私は、メッセージ5に設けられたアルゴリズムに問題があると思います。
これは、問題は、符号であるため経度、緯度のためだけのためではなく動作します。
データは自分自身のために語っています:
49.26 -123.14 225.0 1.0 49.25 -123.13
はのの -123.14°から開始し、WESTを行く場合は、FAR WESTで何かを持っている必要があります。ここでは、EASTに戻る(-123.13)!
式はどこかに含まれる必要があります:
degreeBearing =((360-degreeBearing)%360)
ラジアンconvertion前ます。
これを実装すると、結果の緯度は正確でしたが、経度が間違っていました。たとえば開始点:36.9460678N 9.434807E、45.03334、距離15.0083313kmの結果、結果は37.0412865N 9.315302Eで、これはさらに東ではなく私の出発点よりも西側でした。実際、方位が 315.03334 度であるかのようです。
さらにウェブで検索すると、次のことがわかりました。 http://www.movable-type.co.uk/scripts/latlong.html経度コードを以下に示します(C# ですべてラジアン単位で表記)
if ((Math.Cos(rLat2) == 0) || (Math.Abs(Math.Cos(rLat2)) < EPSILON))
{
rLon2 = rLon1;
}
else
{
rLon2 = rLon1 + Math.Atan2(Math.Sin(rBearing) * Math.Sin(rDistance) * Math.Cos(rLat1), Math.Cos(rDistance) - Math.Sin(rLat1) * Math.Sin(rLat2));
}
これは私にとってはうまくいくようです。お役に立てば幸いです。
のおかげで 私は私のユースケースでそれを設定してみました 私は2つの他の人の間での点の緯度経度を見つけようとしているところ 最初のポイントから設定距離でそれは非常にあなたのコードにsimilareていますので、 私の軸受を動的に計算されていることをアパート
始点(LAT1)lon1 / LAT1 = 55.625541、-21.142463
終点(LAT2)lon2 / LAT2 = 55.625792、-22.142248
私の結果はlon3 / LAT3でこれら二つの間のポイントでなければなりません unfortunetly I GET lon3 / LAT3 = 0.0267695450609,0.0223553243666
私は、これは緯度経度の違いかもしれないと思ったけどなし 私が追加またはサブときには、それが
良いではありません何かアドバイスは本当に素晴らしいことです おかげ
ここに私の実装があります。
距離= 0.001 イプシロン= 0.000001
動的に
ベアリング計算y = math.sin(distance) * math.cos(lat2);
x = math.cos(lat1)*math.sin(lat2) - math.sin(lat1)*math.cos(lat2)*math.cos(distance);
bearing = math.atan2(y, x)
計算LAT3 lon3動的に
rlat1 = (lat1 * 180) / math.pi
rlon1 = (lon1 * 180) / math.pi
rbearing = (bearing * 180) / math.pi
rdistance = distance / R # normalize linear distance to radian angle
rlat = math.asin( math.sin(rlat1) * math.cos(rdistance) + math.cos(rlat1) * math.sin(rdistance) * math.cos(rbearing) )
if math.cos(rlat) == 0 or abs(math.cos(rlat)) < epsilon: # Endpoint a pole
rlon=rlon1
else:
rlon = ( (rlon1 + math.asin( math.sin(rbearing)* math.sin(rdistance) / math.cos(rlat) ) + math.pi ) % (2*math.pi) ) - math.pi
lat3 = (rlat * math.pi)/ 180
lon3 = (rlon * math.pi)/ 180
すべてが意図したとおりに働いているが、問題は、あなたの数学は、現実にはそれが楕円に近似したときの球であることを、地球を前提としていることである。
「Vincentyフォーミュラ」のご愛用の検索エンジンの迅速なトロールは、うまくいけば有用であることが証明されます。