Преобразование из долготышироты в Декартовые координаты

У меня есть некоторые геоцентрической точки координат дается в виде широты и долготы (WGS-84).

Как я могу преобразовать их в Декартовые координаты (x,y,z) с началом в центре Земли?

8 ответов


недавно я сделал что-то похожее на это, используя "Формула хаверсина "по данным WGS-84, которая является производной от" закона Хаверсина " с очень удовлетворительными результатами.

да, WGS-84 предполагает, что Земля является эллипсоидом, но я считаю, что вы получаете только около 0,5% средней ошибки, используя такой подход, как "Формула Хаверсина", которая может быть приемлемой величиной ошибки в вашем случае. У вас всегда будет некоторая ошибка, если вы не говорите о расстоянии нескольких ноги и то есть теоретически существует искривление Земли... Если вам требуется более жесткий подход, совместимый с WGS-84, проверьте " формулу Винсенти."

Я понимаю, где 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 приблизительный радиус Земли (например 6371KM).

Если ваши тригонометрические функции ожидают радианы (что они, вероятно, делают), вам нужно будет сначала преобразовать долготу и широту в радианы. Очевидно, что вам нужно десятичное представление, а не градусы\минуты\секунды (см. например тут о конверсии).

формула для обратного преобразования:

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

asin, конечно, arc sine. читайте об atan2 в Википедии. Не забудьте преобразовать обратно из radians в степени.

на этой странице дает код C# для этого (обратите внимание, что он очень отличается от формул), а также некоторое объяснение и хорошая диаграмма, почему это правильно,


теория для преобразования GPS(WGS84) to декартовых координатах 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 высота. The 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.

в частности, у вас есть серьезный недостаток в ваших расчетах. Земля не является совершенной сферой, и приближение радиуса Земли может не сократить его для точных измерений.

Если в некоторых случаях приемлемо использовать функции homebrew, ГИС является хорошим примером области, в которой гораздо предпочтительнее использовать надежную, проверенную на практике библиотеку.


Если вы заботитесь о получении координат на основе эллипсоида, а не сферы, взгляните на http://en.wikipedia.org/wiki/Geodetic_system#From_geodetic_to_ECEF - он дает формулы, а также константы WGS84, необходимые для преобразования.

формулы там также учитывают высоту относительно опорной поверхности эллипсоида (полезно, если вы получаете данные о высоте от устройства GPS).


на 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;


}