경도 \ 위도에서 데카르트 좌표로 변환
위도와 경도로 지정된 지구 중심 좌표 점 ( 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;
}
'Programing' 카테고리의 다른 글
구아바 라이브러리는 Maven 저장소에서 사용할 수 있습니까? (0) | 2020.08.28 |
---|---|
"!"의 목적은 무엇입니까? (0) | 2020.08.28 |
Bash, 인수 없음 경고 및 케이스 결정 (0) | 2020.08.28 |
JavaScript를 통해 CSS : hover 효과를 비활성화 할 수 있습니까? (0) | 2020.08.28 |
데이터 프레임 전치 (0) | 2020.08.28 |