Programing

경도 \ 위도에서 데카르트 좌표로 변환

lottogame 2020. 8. 28. 07:48
반응형

경도 \ 위도에서 데카르트 좌표로 변환


위도와 경도로 지정된 지구 중심 좌표 점 ( WGS-84 )이 있습니다.

원점을 지구의 중심에있는 데카르트 좌표 (x, y, z)로 변환하려면 어떻게해야합니까?


저는 최근에 WGS-84 데이터의 "Haversine Formula"를 사용하여 이와 유사한 작업을 수행했습니다. 이는 "Law of Haversines"의 파생물이며 매우 만족스러운 결과입니다.

예, WGS-84는 지구가 타원체라고 가정하지만 "Haversine Formula"와 같은 접근 방식을 사용하면 약 0.5 %의 평균 오류 만 발생한다고 생각합니다. 이는 귀하의 경우 허용 가능한 오류입니다. 몇 피트의 거리에 대해 이야기하지 않는 한 항상 약간의 오류가 있으며 이론적으로 지구의 곡률이 있습니다. 더 엄격하게 WGS-84 호환 접근 방식이 필요한 경우 "빈 센티 공식"을 확인하십시오.

나는 starblue어디에서 왔는지 이해 하지만 좋은 소프트웨어 엔지니어링은 종종 트레이드 오프에 관한 것이므로 모두 수행하는 작업에 필요한 정확성에 달려 있습니다. 예를 들어, "Manhattan Distance Formula"에서 계산 된 결과와 "Distance Formula"의 결과는 계산 비용이 더 저렴하므로 특정 상황에서는 더 좋을 수 있습니다. "가장 가까운 지점은?" 정확한 거리 측정이 필요하지 않은 시나리오.

"Haversine Formula"는 구현하기 쉽고 2 차원 삼각법을 기반으로하는 "Law of Cosines"기반 접근 방식 대신 "Spherical Trigonometry"를 사용하기 때문에 훌륭합니다. 따라서 정확도의 균형을 잘 맞 춥니 다. 복잡성에.

Chris Veness 라는 이름의 신사 http://www.movable-type.co.uk/scripts/latlong.html 에 귀하가 관심있는 개념을 설명하고 다양한 프로그래밍 방식 구현을 보여주는 멋진 웹 사이트를 운영 하고 있습니다. 이것은 x / y 변환 질문에도 답할 것입니다.


내가 찾은 답은 다음과 같습니다.

정의를 완성하기 위해 데카르트 좌표계에서 :

  • x 축은 long, lat (0,0)을 통과하므로 경도 0은 적도와 만나게됩니다.
  • y 축은 (0,90)을 통과합니다.
  • z 축은 극을 통과합니다.

변환은 다음과 같습니다.

x = R * cos(lat) * cos(lon)

y = R * cos(lat) * sin(lon)

z = R *sin(lat)

여기서 R은 대략적인 지구 반경입니다 (예 : 6371KM).

삼각 함수가 라디안을 예상하는 경우 (아마도 그렇게 할 것임) 먼저 경도와 위도를 라디안으로 변환해야합니다. 당신은 분명하지도 \ 분 \ 초 (참조, 진수 표현을 필요로 여기 예를 들어 변환에 대해).

역변환 공식 :

   lat = asin(z / R)
   lon = atan2(y, x)

asin은 물론 아크 사인입니다. wikipedia에서 atan2에 대해 읽어보십시오 . 라디안에서 도로 다시 변환하는 것을 잊지 마십시오.

이 페이지 는 이에 대한 C # 코드 (공식과 매우 다릅니다)와 이것이 올바른 이유에 대한 설명과 멋진 다이어그램을 제공합니다.


데카르트 좌표 로 변환 GPS(WGS84)하는 이론 https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinates

다음은 내가 사용하는 것입니다.

  • GPS (WGS84)의 경도와 데카르트 좌표는 동일합니다.
  • 위도는 WGS 84 타원체 매개 변수로 변환해야합니다. 반장 축은 6378137m이고
  • 평탄화의 역수는 298.257223563입니다.

내가 작성한 VB 코드를 첨부했습니다 .

Imports System.Math

'Input GPSLatitude is WGS84 Latitude,h is altitude above the WGS 84 ellipsoid

Public Function GetSphericalLatitude(ByVal GPSLatitude As Double, ByVal h As Double) As Double

        Dim A As Double = 6378137 'semi-major axis 
        Dim f As Double = 1 / 298.257223563  '1/f Reciprocal of flattening
        Dim e2 As Double = f * (2 - f)
        Dim Rc As Double = A / (Sqrt(1 - e2 * (Sin(GPSLatitude * PI / 180) ^ 2)))
        Dim p As Double = (Rc + h) * Cos(GPSLatitude * PI / 180)
        Dim z As Double = (Rc * (1 - e2) + h) * Sin(GPSLatitude * PI / 180)
        Dim r As Double = Sqrt(p ^ 2 + z ^ 2)
        Dim SphericalLatitude As Double =  Asin(z / r) * 180 / PI
        Return SphericalLatitude
End Function

h고도가 WGS 84 ellipsoid.

보통 GPS우리에게 H위의 MSL높이를 줄 것 입니다 . MSL높이는 높이로 변환하는 h상기 WGS 84 ellipsoid하여 중력 포텐샬 모델 EGM96( Lemoine은 등, 1998 ).
이것은 공간 해상도가 15 arc-minutes 인 지오이드 높이 파일의 그리드를 보간하여 수행됩니다.

Or if you have some level professional GPS has Altitude H (msl,heigh above mean sea level) and UNDULATION,the relationship between the geoid and the ellipsoid (m) of the chosen datum output from internal table. you can get h = H(msl) + undulation

To XYZ by Cartesian coordinates:

x = R * cos(lat) * cos(lon)

y = R * cos(lat) * sin(lon)

z = R *sin(lat)

The proj.4 software provides a command line program that can do the conversion, e.g.

LAT=40
LON=-110
echo $LON $LAT | cs2cs +proj=latlong +datum=WGS84 +to +proj=geocent +datum=WGS84

It also provides a C API. In particular, the function pj_geodetic_to_geocentric will do the conversion without having to set up a projection object first.


If you care about getting coordinates based on an ellipsoid rather than a sphere, take a look at http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEF - it gives the formulae as well as the WGS84 constants you need for the conversion.

The formulae there also take into account the altitude relative to the reference ellipsoid surface (useful if you are getting altitude data from a GPS device).


Why implement something which has already been implemented and test-proven?

C#, for one, has the NetTopologySuite which is the .NET port of the JTS Topology Suite.

Specifically, you have a severe flaw in your calculation. The earth is not a perfect sphere, and the approximation of the earth's radius might not cut it for precise measurements.

If in some cases it's acceptable to use homebrew functions, GIS is a good example of a field in which it is much preferred to use a reliable, test-proven library.


In python3.x it can be done using :

# Converting lat/long to cartesian
import numpy as np

def get_cartesian(lat=None,lon=None):
    lat, lon = np.deg2rad(lat), np.deg2rad(lon)
    R = 6371 # radius of the earth
    x = R * np.cos(lat) * np.cos(lon)
    y = R * np.cos(lat) * np.sin(lon)
    z = R *np.sin(lat)
    return x,y,z

Coordinate[] coordinates = new Coordinate[3];
coordinates[0] = new Coordinate(102, 26);
coordinates[1] = new Coordinate(103, 25.12);
coordinates[2] = new Coordinate(104, 16.11);
CoordinateSequence coordinateSequence = new CoordinateArraySequence(coordinates);

Geometry geo = new LineString(coordinateSequence, geometryFactory);

CoordinateReferenceSystem wgs84 = DefaultGeographicCRS.WGS84;
CoordinateReferenceSystem cartesinaCrs = DefaultGeocentricCRS.CARTESIAN;

MathTransform mathTransform = CRS.findMathTransform(wgs84, cartesinaCrs, true);

Geometry geo1 = JTS.transform(geo, mathTransform);

You can do it this way on Java.

public List<Double> convertGpsToECEF(double lat, double longi, float alt) {

    double a=6378.1;
    double b=6356.8;
    double N;
    double e= 1-(Math.pow(b, 2)/Math.pow(a, 2));
    N= a/(Math.sqrt(1.0-(e*Math.pow(Math.sin(Math.toRadians(lat)), 2))));
    double cosLatRad=Math.cos(Math.toRadians(lat));
    double cosLongiRad=Math.cos(Math.toRadians(longi));
    double sinLatRad=Math.sin(Math.toRadians(lat));
    double sinLongiRad=Math.sin(Math.toRadians(longi));
    double x =(N+0.001*alt)*cosLatRad*cosLongiRad;
    double y =(N+0.001*alt)*cosLatRad*sinLongiRad;
    double z =((Math.pow(b, 2)/Math.pow(a, 2))*N+0.001*alt)*sinLatRad;

    List<Double> ecef= new ArrayList<>();
    ecef.add(x);
    ecef.add(y);
    ecef.add(z);

    return ecef;


}

참고URL : https://stackoverflow.com/questions/1185408/converting-from-longitude-latitude-to-cartesian-coordinates

반응형