6

ここで説明されている機能の実装に問題があります。

これは私の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) をラジアン距離に変換します。これは問題ではありません。

ただし、次のような座標を入力すると: lat = 49.25705; 経度 = -123.140259; 方位225(南西)、距離1km

これが返されます: lat: -1.0085434360125864 lon: -3.7595299668539504

明らかに正しくありません。誰かが私が間違っていることを見ることができますか?

ありがとう

4

6 に答える 6

19

これらはあなたのコードの問題のようです:

  1. 関数を呼び出す前にlat1とをラジアンに変換する必要があります。lon1
  2. スケーリングがradialDistance間違っている可能性があります。
  3. 浮動小数点数が等しいかどうかをテストするのは危険です。厳密な算術演算の後で等しい 2 つの数値は、浮動小数点演算の後で完全に等しくない場合があります。したがって、2 つの浮動小数点数のテストや等価性のテストabs(x-y) < thresholdよりも安全です。x == yxy
  4. ラジアンから度に変換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
于 2009-05-18T20:06:43.353 に答える
4

メッセージ 5 で提供されているアルゴリズムに問題があると思います。

それは機能しますが、緯度に対してのみ、経度に対しては記号のために問題があります。

データが物語っています:

49.26 -123.14 225.0 1.0 49.25 -123.13

-123.14°から開始して西に行くと、西に何かが遠くにあるはずです。ここで EAST (-123.13) に戻ります。

数式には次の場所が含まれている必要があります。

DegreeBearing = ((360-degreeBearing)%360)

ラジアン変換前。

于 2011-10-18T16:58:23.620 に答える
3

基本的に、あなたの問題は、緯度、経度、方位をラジアンではなく度として渡していることです。常にラジアンを関数に渡していることを確認し、何が返されるかを確認してください。

PS:ここここ で議論されている同様の問題を参照してください。

于 2009-05-18T12:44:08.440 に答える
1

これを実装すると、緯度は正しくなりましたが、経度は間違っていました。たとえば、開始点: 36.9460678N 9.434807E、方位 45.03334、距離 15.0083313km 結果は 37.0412865N 9.315302E でした。これは、私の開始点より東ではなく西です。実際、方位が 315.03334 度であるかのようです。

さらに Web を検索すると、http ://www.movable-type.co.uk/scripts/latlong.html にたどり着きました。

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

これは私にとってはうまくいくようです。お役に立てば幸いです。

于 2009-08-27T10:28:44.473 に答える
0

あなたのpythonコードに感謝します。最初のポイントから設定された距離にある他の2つのポイントの間の緯度経度を見つけようとしているユースケースで設定しようとしました。動的に計算されます

開始点 (lat1) lon1/lat1 = 55.625541、-21.142463

終点 (lat2) lon2/lat2 = 55.625792,-22.142248

私の結果は、残念ながらlon3/lat3でこれら2つの間のポイントになるはずですが、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
于 2010-10-01T07:40:27.247 に答える
0

すべてが意図したとおりに機能していますが、問題は、実際には地球が楕円体に近似しているのに、数学では地球が球体であると想定していることです。

「Vincenty Formula」のお気に入りの検索エンジンを簡単に調べてみると、役立つことが期待できます。

于 2011-05-07T13:41:29.910 に答える