문제

여기에 설명 된 기능을 구현하는 데 문제가 있습니다 여기.

이것은 나의 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)를 라디안 거리로 변환합니다. 따라서 문제가되지 않습니다.

그러나 I를 입력 할 때 : LAT = 49.25705; lon = -123.140259; 225 (남서부)의 베어링과 1km 거리

나는 이것을 반환합니다 : LAT : -1.0085434360125864 lon : -3.759529968539504

분명히 맞지 않습니다. 누구든지 내가 뭘 잘못하고 있는지 볼 수 있습니까?

감사

도움이 되었습니까?

해결책

코드의 문제인 것 같습니다.

  1. 변환해야합니다 lat1 그리고 lon1 기능을 호출하기 전에 라디안에게.
  2. 당신은 스케일링 될 수 있습니다 radialDistance 틀리게.
  3. 평등에 대한 부동 소수점 수를 테스트하는 것은 위험합니다. 정확한 산술 후에 동일한 두 개의 숫자는 부동 소수점 산술 후에 정확히 같지 않을 수 있습니다. 따라서 abs(x-y) < threshold 보다 안전합니다 x == y 두 개의 부동 소수점 번호를 테스트합니다 x 그리고 y 평등을 위해.
  4. 나는 당신이 변환하고 싶다고 생각합니다 lat 그리고 lon 라디안에서도까지.

파이썬에서 코드 구현은 다음과 같습니다.

#!/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° 서쪽으로 가면 서쪽에서 멀리 떨어져 있어야합니다. 여기서 우리는 동쪽으로 돌아갑니다 (-123.13)!

공식에는 어딘가에 포함되어야합니다.

학위 베어링 = ((360-Degreebearing)%360)

라디안 변환 전에.

내가 이것을 구현했을 때, 나의 결과 위도는 정확했지만 종단은 잘못되었습니다. 예를 들어 시작점 : 36.9460678N 9.434807E, 45.03334, 거리 15.0083313km 결과는 동쪽이 아닌 내 출발점보다 서쪽으로 서쪽으로 37.0412865N 9.315302E입니다. 실제로 베어링이 315.03334 도인 것처럼 보입니다.

더 많은 웹 검색으로 인해 : http://www.movable-type.co.uk/scripts/latlong.html경도 코드는 아래에 표시됩니다 (Radian의 모든 내용이있는 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));
        }

이것은 나에게 잘 작동하는 것 같습니다. 도움이되기를 바랍니다.

파이썬 코드에 감사드립니다. 제 1 지점에서 설정된 거리에서 다른 두 지점의 LAT LON을 찾으려고 노력하는 사용 케이스에서 설정을 시도했습니다. 동적으로 계산됩니다

STARTPOINT (LAT1) LON1/LAT1 = 55.625541, -21.142463

종말점 (Lat2) Lon2/Lat2 = 55.625792, -22.142248

내 결과는 Lon3/Lat3 에서이 두 가지 사이에 있어야합니다.

나는 이것이 Lat Lon의 차이라고 생각했지만 내가 추가하거나 서브 할 때는 좋지 않다.

모든 조언은 정말 좋은 감사입니다

내 구현은 다음과 같습니다

거리 = 0.001 Epsilon = 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 Formula'를 위해 선호하는 검색 엔진의 빠른 트롤은 희망적으로 유용 할 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top