Преобразование из долготышироты в декартовы координаты
У меня есть некоторые земные координатные точки, заданные как широта и долгота (WGS-84).
Как я могу преобразовать их в декартовы координаты (x,y,z) с началом координат в центре Земли?
8 ответов:
Я недавно сделал что-то подобное с помощью "Формула гаверсинуса" на эллипсоиде WGS-84 данных, который является производным от "закона Haversines" с очень удовлетворительные результаты.
да, WGS-84 предполагает, что Земля является эллипсоидом, но я считаю, что вы получаете только около 0,5% средней ошибки, используя такой подход, как "Формула Хаверсина", которая может быть приемлемой величиной ошибки в вашем случае. Вы всегда будете иметь некоторое количество ошибок, если вы не говорите о расстоянии нескольких ноги и то есть теоретически существует искривление Земли... Если вам требуется более жестко совместимый с WGS-84 подход, проверьте " формулу Vincenty."
Я понимаю, где starblue исходит, но хорошая разработка программного обеспечения часто связана с компромиссами, поэтому все зависит от точности, которую вы требуете для того, что вы делаете. Например, результат, вычисленный из "Формулы расстояния Манхэттена" по сравнению с результатом из "Формулы расстояния", может быть лучше для некоторые ситуации, как это вычислительно дешевле. Подумайте "какая точка ближе всего?"сценарии, где вам не нужно точное измерение расстояния.
Что касается "Формулы Хаверсина", ее легко реализовать и приятно, потому что она использует" сферическую тригонометрию "вместо подхода, основанного на" законе косинусов", который основан на двумерной тригонометрии, поэтому вы получаете хороший баланс точности над сложностью.
джентльмены по имени Крис Венесс имеет большой сайт в 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 приблизительный радиус Земли (например 6371КМ).
Если ваши тригонометрические функции ожидают радианы (что они, вероятно, делают), вам сначала нужно будет преобразовать долготу и широту в радианы. Очевидно, что вам нужно десятичное представление, а не градусы\минуты\секунды (см. например тут о конверсии).
формула для обратного преобразования:
lat = asin(z / R) lon = atan2(y, x)
asin, конечно, синусоида дуги. читайте об atan2 в Википедии. Не забудьте преобразовать обратно из радианов в степени.
на этой странице дает код c# для этого (обратите внимание, что он очень отличается от формул), а также некоторые объяснения и хорошую диаграмму, почему это правильно,
теория для преобразования
GPS(WGS84)
до декартовых координатах https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinatesвот что я использую:
- долгота в GPS(WGS84) и декартовых координатах одинаковы.
- широта должна быть преобразована параметрами эллипсоида WGS 84 полу-большая ось 6378137 m, и
- взаимное сплющивание 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 et al, 1998).
Это делается путем интерполяции сетки файла высота геоида с пространственным разрешением 15 угловых минут.или если у вас есть какой-то уровень профессиональный
GPS
ВысотаH
(msl, высота над средним уровнем моря) иUNDULATION
отношения междуgeoid
иellipsoid (m)
избранных вывод данных из внутренней таблицы. вы можете получитьh = H(msl) + undulation
в XYZ по декартовой координаты:
x = R * cos(lat) * cos(lon) y = R * cos(lat) * sin(lon) z = R *sin(lat)
зачем реализовывать то, что уже реализовано и проверено тестами?
C#, например, имеет NetTopologySuite который является .NET-портом пакета топологии JTS.
в частности, у вас есть серьезный недостаток в ваших расчетах. Земля не является совершенной сферой, и приближение радиуса Земли не может сократить его для точных измерений.
Если в некоторых случаях допустимо использовать доморощенные функции, ГИС является хорошим примером области, в которой гораздо предпочтительнее использовать надежную, проверенную тестами библиотеку.
Если вы заботитесь о получении координат на основе эллипсоида, а не сферы, взгляните на http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEF - он дает формулы, а также константы WGS84, необходимые для преобразования.
формулы там также учитывают высоту относительно опорной поверхности эллипсоида (полезно, если вы получаете данные о высоте от устройства GPS).
The proj.4 программное обеспечение предоставляет программу командной строки, которая может сделать преобразование, например
LAT=40 LON=-110 echo $LON $LAT | cs2cs +proj=latlong +datum=WGS84 +to +proj=geocent +datum=WGS84
Он также обеспечивает C API. В частности, функция
pj_geodetic_to_geocentric
будет выполнять преобразование без необходимости сначала настроить объект проекции.
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);
вы можете сделать это на 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; }