Геодезические системы пространственных координат: различия между версиями

Материал из GIS-Lab
Перейти к навигации Перейти к поиску
 
(не показаны 44 промежуточные версии 3 участников)
Строка 1: Строка 1:
{{Статья|Черновик}}
{{Статья|Опубликована|geodesic-coords}}


{{Аннотация|Показано, как осуществляется прямое и обратное преобразование координат между пространственными координатными системами. Приводится пример программной реализации на языке Питон.}}
{{Аннотация|Рассматриваются преобразования между пространственными координатными системами. Приводится пример программной реализации на языке Питон.}}


== Земной эллипсоид ==
== Земной эллипсоид ==
Строка 7: Строка 7:
Земным эллипсоидом называется эллипсоид вращения, поверхность которого по форме и размерам довольно близка к поверхности геоида.
Земным эллипсоидом называется эллипсоид вращения, поверхность которого по форме и размерам довольно близка к поверхности геоида.


Поверхность эллипсоида образуется вращением эллипса вокруг его малой оси.
Поверхность эллипсоида образуется вращением эллипса вокруг его малой оси, которая также является осью вращения эллипсоида.


Эллипс обычно определяется размером его большой полуоси ''a'' и сжатием ''f''. Реже вместо сжатия задаётся размер малой полуоси ''b'':
Эллипс обычно определяется размером его большой полуоси ''a'' и сжатием ''f''. Реже вместо сжатия задаётся размер малой полуоси ''b'':
Строка 38: Строка 38:
# Система геодезических координат:
# Система геодезических координат:
#; геодезическая широта ''B'' : угол между нормалью к поверхности эллипсоида и плоскостью экватора,
#; геодезическая широта ''B'' : угол между нормалью к поверхности эллипсоида и плоскостью экватора,
#; геодезическая долгота ''L'' : двугранный угол между плоскостями данного и начального меридианов,
#; геодезическая долгота ''L'' : угол между плоскостями данного и начального меридианов,
#; геодезическая высота ''H'' : кратчайшее расстояние до поверхности эллипсоида.
#; геодезическая высота ''H'' : кратчайшее расстояние до поверхности эллипсоида.
# Топоцентрические декартовы прямоугольные координаты:
# Топоцентрические декартовы прямоугольные координаты:
Строка 45: Строка 45:
#* ось ''x'' расположена в плоскости меридиана и направлена на север,
#* ось ''x'' расположена в плоскости меридиана и направлена на север,
#* ось ''y'' перпендикулярна к осям ''x'' и ''z'' и направлена на восток.
#* ось ''y'' перпендикулярна к осям ''x'' и ''z'' и направлена на восток.
Помимо широкого использования в геодезических целях, каждая из представленных координатных систем находит важное применение в прикладных областях.
Геодезические координаты со времён седой древности используются в навигации и картографии. В картографии они являются основой построения проекций.
Геоцентрическая система координат необходима для вычисления спутниковых орбит и решения других орбитальных задач.
Проекции, используемые картографами различных стран, основаны на различных геодезических датумах, т.е. созданы на различных эллипсоидах с разными размерами, положением центров и ориентацией осей в пространстве. Самый простой и точный способ пересчёта координат, заданных в разных датумах, зиждется на преобразованиях между геодезическими и геоцентрическими системами. В общем случае схема пересчёта координат между двумя проекциями выполняется в пять этапов:
#координаты первой проекции — в геодезические координаты на первом эллипсоиде,
#геодезические координаты — в геоцентрические координаты первого датума,
#геоцентрические координаты первого датума — в геоцентрические координаты второго датума,
#геоцентрические координаты — в геодезические координаты на втором эллипсоиде,
#геодезические координаты — в координаты второй проекции.
Топоцентрическая система координат — естественная система для работы различных наземных объектов: ракетных стартовых комплексов, станций слежения за спутниками, станций ПВО и других измерительных комплексов. Естественно, собираемая информация в каждом случае преобразуется в общую систему координат, связанную с Землёй — геодезическую систему координат.


== Преобразования координат ==
== Преобразования координат ==
Строка 52: Строка 67:
Это преобразование выполняется по следующим формулам:
Это преобразование выполняется по следующим формулам:


: <math>\begin{array}{rcl}
: <math>\begin{align}
x & = & (N + H) \cos B \cos L \\
x & = (N + H) \cos B \cos L \\
y & = & (N + H) \cos B \sin L \\
y & = (N + H) \cos B \sin L \\
z & = & (N + H - e^2 N) \sin B
z & = (N + H - e^2 N) \sin B
\end{array}</math>
\end{align}</math>


Здесь ''N'' — так называемый радиус кривизны первого вертикала:
Здесь ''N'' — так называемый радиус кривизны первого вертикала:


: <math>N = \frac{a}{1 - e^2 \sin^2 B} = \frac{c}{1 + e'^2 \cos^2 B}</math>
: <math>N = \frac{a}\sqrt{1 - e^2 \sin^2 B} = \frac{c}\sqrt{1 + e'^2 \cos^2 B}</math>


Реализация на Питоне:
Реализация на Питоне:
Строка 78: Строка 93:
=== Переход от геоцентрических координат к геодезическим ===
=== Переход от геоцентрических координат к геодезическим ===


Существует множество способов решения этой непростой задачи. Воспользуемся итеративным методом Боуринга.
Проще всего вычисляется долгота:


В начале находится предварительная оценка параметра ''θ'':
: <math>\operatorname{tg\,} L = \frac{y}{x}</math>


: <math>\operatorname{tg\,} \theta = \frac{z}{r} \left( 1 + e'^2 \frac{b}{\rho} \right) (1 - f)</math>
Сложнее с определением широты и высоты. Существует множество способов решения этой задачи. Воспользуемся итеративным методом Боуринга.


Здесь ''ρ'' — геоцентрический радиус-вектор, ''r'' — расстояние от оси вращения эллипсоида:
В начале находится предварительная оценка широты ''B'':


: <math>\rho = \sqrt{x^2 + y^2 + z^2} \qquad r = \sqrt{x^2 + y^2}</math>
: <math>\operatorname{tg\,} B = \frac{z}{p} \left( 1 + e'^2 \frac{b}{r} \right)</math>


Затем вычисляется тангенс широты:
Здесь ''r'' — геоцентрический радиус-вектор, ''p'' — расстояние от оси вращения эллипсоида:


: <math>\operatorname{tg\,} B = \frac{z + e'^2 b \sin^3 \theta}{p - e^2 a \cos^3 \theta}</math>
: <math>r = \sqrt{x^2 + y^2 + z^2} \qquad p = \sqrt{x^2 + y^2}</math>


и параметр ''θ'' уточняется:
Затем вычисляется параметр ''θ'' (приведённая широта) и получается уточнённое значение широты:


: <math>\operatorname{tg\,} \theta = (1 - f) \operatorname{tg\,} B</math>
: <math>\begin{align}
\operatorname{tg\,} \theta & = (1 - f) \operatorname{tg\,} B \\
\operatorname{tg\,} B & = \dfrac{z + e'^2 b \sin^3 \theta}{p - e^2 a \cos^3 \theta}
\end{align}</math>


Действия по последним двум формулам предполагается повторять до сходимости к требуемой точности. Как правило, бывает достаточно одной-двух итераций.
Действия по последним двум формулам предполагается повторять до сходимости к требуемой точности. Как правило, бывает достаточно одной итерации. В примере реализации метода Боуринга, приведённом ниже, запрограммировано две итерации.
 
В конце определяется высота:
 
: <math>H = \frac{p}{\cos B} - N = \frac{z}{\sin B} - N (1 - e^2)</math>


<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
Строка 127: Строка 149:
=== Переход от геоцентрических координат к топоцентрическим ===
=== Переход от геоцентрических координат к топоцентрическим ===


Обратная задача.
Постановка задачи: начало топоцентрической системы координат задано точкой ''Q''₀ (''B''₀, ''L''₀, ''H''₀); по геоцентрическим координатам точки ''Q'' (''x'', ''y'', ''z'') вычислить её топоцентрические координаты.


=== Переход от топоцентрических координат к геоцентрическим ===
Конформное преобразование между двумя декартовыми прямоугольными системами координат всегда может быть представлено последовательностью сдвигов и вращений координатной системы. Данное преобразование можно реализовать по следующему алгоритму:
* сместить начало координат вдоль оси ''z'' на величину ''e''² ''N''₀ sin ''B''₀ до вершины конуса, образованного нормалями, лежащими на параллели с широтой ''B''₀,
* повернуть систему координат вокруг оси ''z'' на угол ''L''₀, чтобы ось ''x'' оказалась в плоскости меридиана точки ''Q''₀,
* повернуть систему координат вокруг оси ''y'' на угол 90° − ''B''₀, чтобы ось ''z'' совпала с нормалью к поверхности эллипсоида в точке ''Q''₀,
* сместить начало координат вдоль оси ''z'' на величину ''N''₀ + ''H''₀ в точку ''Q''₀,
* изменить знак ''x'' на противоположный.


Прямая задача.
Реализация алгоритма:


== Программы ==
<syntaxhighlight lang="python">
def toTopo(lat0, lon0, h0, x, y, z, a, f):
    b, c, e2, e12 = initSpher(a, f)
    sin_lat = math.sin(lat0)
    n = a / math.sqrt(1. - e2 * sin_lat ** 2)
    z = z + e2 * n * sin_lat
    x, y = rotate(x, y, lon0)
    z, x = rotate(z, x, math.pi / 2. - lat0)
    z = z - (n + h0)
    x = -x
    return (x, y, z)
</syntaxhighlight>
 
Функция '''toTopo()''' содержит обращения к функции вращения '''rotate()''':


<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
import math
def rotate(x, y, a):
def rotate(x, y, a):
     c, s = math.cos(a), math.sin(a)
     c, s = math.cos(a), math.sin(a)
     return (x * c + y * s, -x * s + y * c)
     return (x * c + y * s, -x * s + y * c)
</syntaxhighlight>


def forward3d(lat1, lon1, h1, x, y, z, a, f):
=== Переход от топоцентрических координат к геоцентрическим ===
 
Постановка задачи: начало топоцентрической системы координат задано точкой ''Q''₀ (''B''₀, ''L''₀, ''H''₀); по топоцентрическим координатам точки ''Q'' (''x'', ''y'', ''z'') вычислить её геоцентрические координаты.
 
Алгоритм решения получается обращением алгоритма обратной задачи:
* изменить знак ''x'' на противоположный,
* сместить начало координат вдоль оси ''z'' на величину ''N''₀ + ''H''₀ в точку пересечения с осью вращения эллипсоида,
* повернуть систему координат вокруг оси ''y'' на угол ''B''₀ − 90°, чтобы ось ''z'' совпала с осью вращения эллипсоида,
* повернуть систему координат вокруг оси ''z'' на угол −''L''₀, чтобы ось ''x'' оказалась в плоскости начального меридиана,
* сместить начало координат вдоль оси ''z'' на величину ''e''² ''N''₀ sin ''B''₀ в центр эллипсоида.
 
Реализация алгоритма:
 
<syntaxhighlight lang="python">
def fromTopo(lat0, lon0, h0, x, y, z, a, f):
     b, c, e2, e12 = initSpher(a, f)
     b, c, e2, e12 = initSpher(a, f)
     sin_lat = math.sin(lat1)
     sin_lat = math.sin(lat0)
     n = a / math.sqrt(1. - e2 * sin_lat ** 2)
     n = a / math.sqrt(1. - e2 * sin_lat ** 2)
     x = -x
     x = -x
     z = z + (n + h1)
     z = z + (n + h0)
     z, x = rotate(z, x, lat1 - math.pi / 2.)
     z, x = rotate(z, x, lat0 - math.pi / 2.)
     x, y = rotate(x, y, -lon1)
     x, y = rotate(x, y, -lon0)
     z = z - e2 * n * sin_lat
     z = z - e2 * n * sin_lat
    return (x, y, z)
</syntaxhighlight>
=== Переход от геодезических координат к топоцентрическим. Обратная пространственная задача ===
Постановка задачи: начало топоцентрической системы координат задано точкой ''Q''₀ (''B''₀, ''L''₀, ''H''₀); по геодезическим координатам точки ''Q'' (''B'', ''L'', ''H'') вычислить её топоцентрические координаты ''x'', ''y'', ''z''.
Задача решается последовательным применением готовых алгоритмов:
* по геодезическим координатам точки ''B'', ''L'', ''H'' вычислить её геоцентрические координаты ''x'', ''y'', ''z'',
* по геоцентрическим координатам точки вычислить её топоцентрические координаты ''x'', ''y'', ''z''.
Реализация алгоритма:
<syntaxhighlight lang="python">
def inverse3d(lat0, lon0, h0, lat, lon, h, a, f):
    x, y, z = fromLatLong(lat, lon, h, a, f)
    return toTopo(lat0, lon0, h0, x, y, z, a, f)
</syntaxhighlight>
Рассмотренная задача является разновидностью обратной геодезической задачи в пространстве. Вместо декартовых прямоугольных топоцентрических координат может требоваться вычисление каких-то других связанных с ними величин, например, полярных координат «дальность-азимут-зенитное расстояние», варианты могут быть разные. Однако в большинстве случаев сначала находятся топоцентрические ''x'', ''y'', ''z'', по которым и выводятся искомые значения.
=== Переход от топоцентрических координат к геодезическим. Прямая пространственная задача ===
Постановка задачи: начало топоцентрической системы координат задано точкой ''Q''₀ (''B''₀, ''L''₀, ''H''₀); по топоцентрическим координатам точки ''Q'' (''x'', ''y'', ''z'') вычислить её геодезические координаты ''B'', ''L'', ''H''.
Задача решается через вычисление геоцентрических координат:
* по тороцентрическим координатам точки ''x'', ''y'', ''z'' вычислить её геоцентрические координаты,
* по геоцентрическим координатам точки ''x'', ''y'', ''z'' вычислить её геодезические координаты ''B'', ''L'', ''H''.
Реализация алгоритма:
<syntaxhighlight lang="python">
def forward3d(lat0, lon0, h0, x, y, z, a, f):
    x, y, z = fromTopo(lat0, lon0, h0, x, y, z, a, f)
     return toLatLong(x, y, z, a, f)
     return toLatLong(x, y, z, a, f)
</syntaxhighlight>


def inverse3d(lat1, lon1, h1, lat2, lon2, h2, a, f):
Эта задача является разновидностью прямой геодезической задачи в пространстве. Вместо декартовых прямоугольных топоцентрических координат могут задаваться какие-то другие связанные с ними величины, например, полярные координаты «дальность-азимут-зенитное расстояние», варианты могут быть разные. Однако в большинстве случаев сначала находятся топоцентрические ''x'', ''y'', ''z'', по которым и решается задача.
    b, c, e2, e12 = initSpher(a, f)
 
    sin_lat = math.sin(lat1)
== Пример программной реализации ==
    n = a / math.sqrt(1. - e2 * sin_lat ** 2)
 
    x, y, z = fromLatLong(lat2, lon2, h2, a, f)
Коды вышеприведённых функций находятся в архиве [[Медиа:Spheroid.zip|Spheroid.zip]] в файле '''spheroid.py'''. Напишем программы, которые используют их для преобразования координат.
    z = z + e2 * n * sin_lat
 
    x, y = rotate(x, y, lon1)
=== Пересчёт топоцентрических координат в геодезические ===
    z, x = rotate(z, x, math.pi / 2. - lat1)
 
    z = z - (n + h1)
В этом примере программы явно задаются параметры эллипсоида ''a'', ''f'' и геодезические координаты начала топоцентрической системы ''B''₀, ''L''₀, ''H''₀. Координаты точек ''x'', ''y'', ''z'' читаются из файла данных и пересчитанные значения ''B'', ''L'', ''H'' выводятся в консоль.
    x = -x
    return (x, y, z)
</syntaxhighlight>


<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
# -*- coding: utf-8 -*-
from sys import argv
from sys import argv
import math
import math
import latlong
import spheroid


script, fn = argv
script, fn = argv


a, f = 6378136., 1./298.25784 # ПЗ-90
a, f = 6378137., 1./298.257223563 # WGS 84


lat0, lon0, hgt0 = math.radians(65.), math.radians(45.), 500.
lat0, lon0, hgt0 = math.radians(65.), math.radians(45.), 500.
Строка 181: Строка 265:
for line in fp:
for line in fp:
     x, y, z = map(float, line.split(" "))
     x, y, z = map(float, line.split(" "))
     lat, lon, hgt = latlong.forward3d(lat0, lon0, hgt0, x, y, z, a, f)
     lat, lon, hgt = spheroid.forward3d(lat0, lon0, hgt0, x, y, z, a, f)
     print "%.8f %.8f %.3f" % (math.degrees(lat), math.degrees(lon), hgt)
     print "%.8f %.8f %.3f" % (math.degrees(lat), math.degrees(lon), hgt)
fp.close()
fp.close()
</syntaxhighlight>
</syntaxhighlight>
Этот скрипт находится в архиве [[Медиа:Spheroid.zip|Spheroid.zip]] в файле '''forwrd3d.py'''.
Файл данных должен содержать в каждой строке координаты одной точки ''x'', ''y'', ''z'', разделённые пробелом. Создадим файл данных '''fwd3d.dat''':
<pre>-40000 30000 0</pre>
Выполним скрипт в командной строке:
<pre>$ python forwrd3d.py fwd3d.dat</pre>
Координаты на выходе:
<pre>64.63992461 45.62743323 695.578</pre>
Запишем полученные координаты в файл результатов '''inv3d.dat''':
<pre>$ python forwrd3d.py fwd3d.dat > inv3d.dat</pre>
=== Пересчёт геодезических координат в топоцентрические ===
В этом примере программы явно задаются параметры эллипсоида ''a'', ''f'' и геодезические координаты начала топоцентрической системы ''B''₀, ''L''₀, ''H''₀. Координаты точек ''B'', ''L'', ''H'' читаются из файла данных и пересчитанные значения ''x'', ''y'', ''z'' выводятся в консоль.


<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
# -*- coding: utf-8 -*-
from sys import argv
from sys import argv
import math
import math
import latlong
import spheroid


script, fn = argv
script, fn = argv


a, f = 6378136., 1./298.25784 # ПЗ-90
a, f = 6378137., 1./298.257223563 # WGS 84


lat0, lon0, hgt0 = math.radians(65.), math.radians(45.), 500.
lat0, lon0, hgt0 = math.radians(65.), math.radians(45.), 500.
Строка 203: Строка 308:
     lat = math.radians(lat)
     lat = math.radians(lat)
     lon = math.radians(lon)
     lon = math.radians(lon)
     x, y, z = latlong.inverse3d(lat0, lon0, hgt0, lat, lon, hgt, a, f)
     x, y, z = spheroid.inverse3d(lat0, lon0, hgt0, lat, lon, hgt, a, f)
     print "%.3f %.3f %.3f" % (x, y, z)
     print "%.3f %.3f %.3f" % (x, y, z)
fp.close()
fp.close()
</syntaxhighlight>
</syntaxhighlight>


== Расчёты ==
Этот скрипт находится в архиве [[Медиа:Spheroid.zip|Spheroid.zip]] в файле '''invers3d.py'''.
 
Файл данных должен содержать в каждой строке координаты одной точки ''B'', ''L'', ''H'', разделённые пробелом. Используем в качестве файла данных созданный выше '''inv3d.dat''':
 
<pre>64.63992461 45.62743323 695.578</pre>
 
Выполним скрипт в командной строке:


<pre>-40000 30000 0</pre>
<pre>$ python invers3d.py inv3d.dat</pre>


<pre>64.63992455 45.62743333 695.578</pre>
Координаты на выходе:


<pre>-40000.000 30000.000 0.000</pre>
<pre>-40000.000 30000.000 0.000</pre>

Текущая версия от 09:34, 7 марта 2017

Эта страница опубликована в основном списке статей сайта
по адресу http://gis-lab.info/qa/geodesic-coords.html


Рассматриваются преобразования между пространственными координатными системами. Приводится пример программной реализации на языке Питон.

Земной эллипсоид

Земным эллипсоидом называется эллипсоид вращения, поверхность которого по форме и размерам довольно близка к поверхности геоида.

Поверхность эллипсоида образуется вращением эллипса вокруг его малой оси, которая также является осью вращения эллипсоида.

Эллипс обычно определяется размером его большой полуоси a и сжатием f. Реже вместо сжатия задаётся размер малой полуоси b:

В теории и практике вычислений широко используются такие параметры, как полярный радиус кривизны поверхности c, первый эксцентриситет e и второй эксцентриситет e′:

Пример функции Питона, вычисляющей по a и f параметры b, c, e и e′:

def initSpher(a, f):
    b = a * (1. - f)
    c = a / (1. - f)
    e2 = f * (2. - f)
    e12 = e2 / (1. - e2)
    return (b, c, e2, e12)

Системы координат

Рассмотрим следующие системы координат.

  1. Геоцентрические декартовы прямоугольные координаты:
    • начало координат находится в центре эллипсоида,
    • ось z расположена вдоль оси вращения эллипсоида и направлена в северный полюс,
    • ось x лежит в пересечении экватора и начального меридиана,
    • ось y лежит в пересечении экватора и меридиана с долготой L = 90°.
  2. Система геодезических координат:
    геодезическая широта B
    угол между нормалью к поверхности эллипсоида и плоскостью экватора,
    геодезическая долгота L
    угол между плоскостями данного и начального меридианов,
    геодезическая высота H
    кратчайшее расстояние до поверхности эллипсоида.
  3. Топоцентрические декартовы прямоугольные координаты:
    • начало координат находится в некоторой точке Q₀ (B₀, L₀, H₀) над эллипсоидом,
    • ось z расположена вдоль нормали к поверхности эллипсоида и направлена вверх,
    • ось x расположена в плоскости меридиана и направлена на север,
    • ось y перпендикулярна к осям x и z и направлена на восток.

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

Геодезические координаты со времён седой древности используются в навигации и картографии. В картографии они являются основой построения проекций.

Геоцентрическая система координат необходима для вычисления спутниковых орбит и решения других орбитальных задач.

Проекции, используемые картографами различных стран, основаны на различных геодезических датумах, т.е. созданы на различных эллипсоидах с разными размерами, положением центров и ориентацией осей в пространстве. Самый простой и точный способ пересчёта координат, заданных в разных датумах, зиждется на преобразованиях между геодезическими и геоцентрическими системами. В общем случае схема пересчёта координат между двумя проекциями выполняется в пять этапов:

  1. координаты первой проекции — в геодезические координаты на первом эллипсоиде,
  2. геодезические координаты — в геоцентрические координаты первого датума,
  3. геоцентрические координаты первого датума — в геоцентрические координаты второго датума,
  4. геоцентрические координаты — в геодезические координаты на втором эллипсоиде,
  5. геодезические координаты — в координаты второй проекции.

Топоцентрическая система координат — естественная система для работы различных наземных объектов: ракетных стартовых комплексов, станций слежения за спутниками, станций ПВО и других измерительных комплексов. Естественно, собираемая информация в каждом случае преобразуется в общую систему координат, связанную с Землёй — геодезическую систему координат.

Преобразования координат

Переход от геодезических координат к геоцентрическим

Это преобразование выполняется по следующим формулам:

Здесь N — так называемый радиус кривизны первого вертикала:

Реализация на Питоне:

def fromLatLong(lat, lon, h, a, f):
    b, c, e2, e12 = initSpher(a, f)
    cos_lat = math.cos(lat)
    n = c / math.sqrt(1. + e12 * cos_lat ** 2)
    p = (n + h) * cos_lat
    x = p * math.cos(lon)
    y = p * math.sin(lon)
    z = (n + h - e2 * n) * math.sin(lat)
    return (x, y, z)

Переход от геоцентрических координат к геодезическим

Проще всего вычисляется долгота:

Сложнее с определением широты и высоты. Существует множество способов решения этой задачи. Воспользуемся итеративным методом Боуринга.

В начале находится предварительная оценка широты B:

Здесь r — геоцентрический радиус-вектор, p — расстояние от оси вращения эллипсоида:

Затем вычисляется параметр θ (приведённая широта) и получается уточнённое значение широты:

Действия по последним двум формулам предполагается повторять до сходимости к требуемой точности. Как правило, бывает достаточно одной итерации. В примере реализации метода Боуринга, приведённом ниже, запрограммировано две итерации.

В конце определяется высота:

def toLatLong(x, y, z, a, f):
    b, c, e2, e12 = initSpher(a, f)
    p = math.hypot(x, y)
    if p == 0.:
        lat = math.copysign(math.pi / 2., z)
        lon = 0.
        h = math.fabs(z) - b
    else:
        t = z / p * (1. + e12 * b / math.hypot(p, z))
        for i in range(2):
            t = t * (1. - f)
            lat = math.atan(t)
            cos_lat = math.cos(lat)
            sin_lat = math.sin(lat)
            t = (z + e12 * b * sin_lat ** 3) / (p - e2 * a * cos_lat ** 3)
        lon = math.atan2(y, x)
        lat = math.atan(t)
        cos_lat = math.cos(lat)
        n = c / math.sqrt(1. + e12 * cos_lat ** 2)
        if math.fabs(t) <= 1.:
            h = p / cos_lat - n
        else:
            h = z / math.sin(lat) - n * (1. - e2)
    return (lat, lon, h)

Переход от геоцентрических координат к топоцентрическим

Постановка задачи: начало топоцентрической системы координат задано точкой Q₀ (B₀, L₀, H₀); по геоцентрическим координатам точки Q (x, y, z) вычислить её топоцентрические координаты.

Конформное преобразование между двумя декартовыми прямоугольными системами координат всегда может быть представлено последовательностью сдвигов и вращений координатной системы. Данное преобразование можно реализовать по следующему алгоритму:

  • сместить начало координат вдоль оси z на величину e² N₀ sin B₀ до вершины конуса, образованного нормалями, лежащими на параллели с широтой B₀,
  • повернуть систему координат вокруг оси z на угол L₀, чтобы ось x оказалась в плоскости меридиана точки Q₀,
  • повернуть систему координат вокруг оси y на угол 90° − B₀, чтобы ось z совпала с нормалью к поверхности эллипсоида в точке Q₀,
  • сместить начало координат вдоль оси z на величину N₀ + H₀ в точку Q₀,
  • изменить знак x на противоположный.

Реализация алгоритма:

def toTopo(lat0, lon0, h0, x, y, z, a, f):
    b, c, e2, e12 = initSpher(a, f)
    sin_lat = math.sin(lat0)
    n = a / math.sqrt(1. - e2 * sin_lat ** 2)
    z = z + e2 * n * sin_lat
    x, y = rotate(x, y, lon0)
    z, x = rotate(z, x, math.pi / 2. - lat0)
    z = z - (n + h0)
    x = -x
    return (x, y, z)

Функция toTopo() содержит обращения к функции вращения rotate():

def rotate(x, y, a):
    c, s = math.cos(a), math.sin(a)
    return (x * c + y * s, -x * s + y * c)

Переход от топоцентрических координат к геоцентрическим

Постановка задачи: начало топоцентрической системы координат задано точкой Q₀ (B₀, L₀, H₀); по топоцентрическим координатам точки Q (x, y, z) вычислить её геоцентрические координаты.

Алгоритм решения получается обращением алгоритма обратной задачи:

  • изменить знак x на противоположный,
  • сместить начало координат вдоль оси z на величину N₀ + H₀ в точку пересечения с осью вращения эллипсоида,
  • повернуть систему координат вокруг оси y на угол B₀ − 90°, чтобы ось z совпала с осью вращения эллипсоида,
  • повернуть систему координат вокруг оси z на угол −L₀, чтобы ось x оказалась в плоскости начального меридиана,
  • сместить начало координат вдоль оси z на величину e² N₀ sin B₀ в центр эллипсоида.

Реализация алгоритма:

def fromTopo(lat0, lon0, h0, x, y, z, a, f):
    b, c, e2, e12 = initSpher(a, f)
    sin_lat = math.sin(lat0)
    n = a / math.sqrt(1. - e2 * sin_lat ** 2)
    x = -x
    z = z + (n + h0)
    z, x = rotate(z, x, lat0 - math.pi / 2.)
    x, y = rotate(x, y, -lon0)
    z = z - e2 * n * sin_lat
    return (x, y, z)

Переход от геодезических координат к топоцентрическим. Обратная пространственная задача

Постановка задачи: начало топоцентрической системы координат задано точкой Q₀ (B₀, L₀, H₀); по геодезическим координатам точки Q (B, L, H) вычислить её топоцентрические координаты x, y, z.

Задача решается последовательным применением готовых алгоритмов:

  • по геодезическим координатам точки B, L, H вычислить её геоцентрические координаты x, y, z,
  • по геоцентрическим координатам точки вычислить её топоцентрические координаты x, y, z.

Реализация алгоритма:

def inverse3d(lat0, lon0, h0, lat, lon, h, a, f):
    x, y, z = fromLatLong(lat, lon, h, a, f)
    return toTopo(lat0, lon0, h0, x, y, z, a, f)

Рассмотренная задача является разновидностью обратной геодезической задачи в пространстве. Вместо декартовых прямоугольных топоцентрических координат может требоваться вычисление каких-то других связанных с ними величин, например, полярных координат «дальность-азимут-зенитное расстояние», варианты могут быть разные. Однако в большинстве случаев сначала находятся топоцентрические x, y, z, по которым и выводятся искомые значения.

Переход от топоцентрических координат к геодезическим. Прямая пространственная задача

Постановка задачи: начало топоцентрической системы координат задано точкой Q₀ (B₀, L₀, H₀); по топоцентрическим координатам точки Q (x, y, z) вычислить её геодезические координаты B, L, H.

Задача решается через вычисление геоцентрических координат:

  • по тороцентрическим координатам точки x, y, z вычислить её геоцентрические координаты,
  • по геоцентрическим координатам точки x, y, z вычислить её геодезические координаты B, L, H.

Реализация алгоритма:

def forward3d(lat0, lon0, h0, x, y, z, a, f):
    x, y, z = fromTopo(lat0, lon0, h0, x, y, z, a, f)
    return toLatLong(x, y, z, a, f)

Эта задача является разновидностью прямой геодезической задачи в пространстве. Вместо декартовых прямоугольных топоцентрических координат могут задаваться какие-то другие связанные с ними величины, например, полярные координаты «дальность-азимут-зенитное расстояние», варианты могут быть разные. Однако в большинстве случаев сначала находятся топоцентрические x, y, z, по которым и решается задача.

Пример программной реализации

Коды вышеприведённых функций находятся в архиве Spheroid.zip в файле spheroid.py. Напишем программы, которые используют их для преобразования координат.

Пересчёт топоцентрических координат в геодезические

В этом примере программы явно задаются параметры эллипсоида a, f и геодезические координаты начала топоцентрической системы B₀, L₀, H₀. Координаты точек x, y, z читаются из файла данных и пересчитанные значения B, L, H выводятся в консоль.

from sys import argv
import math
import spheroid

script, fn = argv

a, f = 6378137., 1./298.257223563 # WGS 84

lat0, lon0, hgt0 = math.radians(65.), math.radians(45.), 500.

fp = open(fn, 'r')
for line in fp:
    x, y, z = map(float, line.split(" "))
    lat, lon, hgt = spheroid.forward3d(lat0, lon0, hgt0, x, y, z, a, f)
    print "%.8f %.8f %.3f" % (math.degrees(lat), math.degrees(lon), hgt)
fp.close()

Этот скрипт находится в архиве Spheroid.zip в файле forwrd3d.py.

Файл данных должен содержать в каждой строке координаты одной точки x, y, z, разделённые пробелом. Создадим файл данных fwd3d.dat:

-40000 30000 0

Выполним скрипт в командной строке:

$ python forwrd3d.py fwd3d.dat

Координаты на выходе:

64.63992461 45.62743323 695.578

Запишем полученные координаты в файл результатов inv3d.dat:

$ python forwrd3d.py fwd3d.dat > inv3d.dat

Пересчёт геодезических координат в топоцентрические

В этом примере программы явно задаются параметры эллипсоида a, f и геодезические координаты начала топоцентрической системы B₀, L₀, H₀. Координаты точек B, L, H читаются из файла данных и пересчитанные значения x, y, z выводятся в консоль.

from sys import argv
import math
import spheroid

script, fn = argv

a, f = 6378137., 1./298.257223563 # WGS 84

lat0, lon0, hgt0 = math.radians(65.), math.radians(45.), 500.

fp = open(fn, 'r')
for line in fp:
    lat, lon, hgt = map(float, line.split(" "))
    lat = math.radians(lat)
    lon = math.radians(lon)
    x, y, z = spheroid.inverse3d(lat0, lon0, hgt0, lat, lon, hgt, a, f)
    print "%.3f %.3f %.3f" % (x, y, z)
fp.close()

Этот скрипт находится в архиве Spheroid.zip в файле invers3d.py.

Файл данных должен содержать в каждой строке координаты одной точки B, L, H, разделённые пробелом. Используем в качестве файла данных созданный выше inv3d.dat:

64.63992461 45.62743323 695.578

Выполним скрипт в командной строке:

$ python invers3d.py inv3d.dat

Координаты на выходе:

-40000.000 30000.000 0.000

Ссылки