Задачи на сфере: линейная засечка: различия между версиями

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


{{Аннотация|Линейная засечка — это нахождение положения точки по координатам двух исходных пунктов и расстояниям от этих пунктов до определяемой точки.}}
{{Аннотация|Линейная засечка — это нахождение положения точки по координатам двух исходных пунктов и расстояниям от этих пунктов до определяемой точки.}}
Строка 25: Строка 25:
== Алгоритм ==
== Алгоритм ==


[[Image:sph_ang.png|frame|c|right|Угловая засечка]]
[[Image:sphere-task-linear.png|frame|c|right|Линейная засечка]]


Решение любого вида засечек сводится к нахождению полярных координат искомой точки, т.е. начального направления и расстояния на неё с одного из исходных пунктов. На конечном этапе координаты находятся из решения прямой геодезической задачи. Поскольку в угловой засечке направления ''α''₁₃ и ''α''₂₃ уже заданы, остаётся определить расстояние ''σ''₁₃ или ''σ''₂₃.
Решение любого вида засечек сводится к нахождению полярных координат искомой точки, т.е. начального направления и расстояния на неё с одного из исходных пунктов. На конечном этапе координаты находятся из решения прямой геодезической задачи. Поскольку в линейной засечке расстояния ''σ''₁₃ и ''σ''₂₃ уже заданы, остаётся определить направление ''α''₁₃ или ''α''₂₃.


На рисунке синим цветом выделены заданные элементы сферического треугольника, красным цветом неизвестные, зелёным — вспомогательные элементы. Очевидно, в треугольнике ''Q''₁''Q''₂''Q''₃ нет ни одного известного элемента. Однако из решения обратной геодезической задачи для пунктов ''Q''₁, ''Q''₂ могут быть получены расстояние ''σ''₁₂, а также азимуты ''α''₁₂ и ''α''₂₁, после чего углы ''β''₁ и ''β''₂ вычисляются как разности азимутов при соответствующих пунктах. Далее из решения треугольника ''Q''₁''Q''₂''Q''₃ найдём сторону ''σ''₁₃.
На рисунке синим цветом выделены заданные элементы сферических треугольников, красным цветом неизвестные, зелёным — вспомогательные элементы. Итак, в треугольнике ''Q''₁''Q''₂''Q''₃ известны только два элемента — стороны ''σ''₁₃ и ''σ''₂₃. Из решения обратной геодезической задачи для пунктов ''Q''₁, ''Q''₂ можно получить недостающий третий элемент — расстояние ''σ''₁₂, а также азимут ''α''₁₂.


'''Последовательность действий:'''
'''Последовательность действий:'''
# решить обратную геодезическую задачу для ''Q''₁, ''Q''₂: по ''φ''₁, ''λ''₁, ''φ''₂, ''λ''₂ получить ''α''₁₂, ''α''₂₁, ''σ''₁₂;
# решить обратную геодезическую задачу для ''Q''₁, ''Q''₂: по ''φ''₁, ''λ''₁, ''φ''₂, ''λ''₂ получить ''α''₁₂, ''σ''₁₂;
# вычислить углы ''β''₁, ''β''₂;
# в треугольнике ''Q''₁''Q''₂''Q''₃ по ''σ''₁₂, ''σ''₁₃, ''σ''₂₃ вычислить угол ''β''₁;
# в треугольнике ''Q''₁''Q''₂''Q''₃ по ''σ''₁₂, ''β'', ''β''вычислить ''σ''₁₃;
# вычислить азимут ''α''₁₃;
# решить прямую геодезическую задачу для ''Q''₁, ''Q''₃: по ''φ''₁, ''λ''₁, ''α''₁₃, ''σ''₁₃ вычислить ''φ''₃, ''λ''₃.
# решить прямую геодезическую задачу для ''Q''₁, ''Q''₃: по ''φ''₁, ''λ''₁, ''α''₁₃, ''σ''₁₃ вычислить ''φ''₃, ''λ''₃.


Действия по первому и последнему пунктам рассмотрены в статьях [[Задачи на сфере: обратная геодезическая задача]] и [[Задачи на сфере: прямая геодезическая задача]].
Действия по первому и последнему пунктам рассмотрены в статьях [http://gis-lab.info/qa/sphere-geodesic-invert-problem.html Задачи на сфере: обратная геодезическая задача] и [http://gis-lab.info/qa/sphere-geodesic-direct-problem.html Задачи на сфере: прямая геодезическая задача].


Углы ''β''₁, ''β''₂ и длина ''σ''₁₃ вычисляются по формулам:
Угол ''β''₁ и азимут ''α''₁₃ вычисляются по формулам:


: <math>\begin{array}{rcl}
: <math>\begin{align}
\beta_1 & = & \alpha_{12} - \alpha_{13} \\
\cos \beta_1 & = \dfrac{\cos \sigma_{23} - \cos \sigma_{12} \cos \sigma_{13}}{\sin \sigma_{12} \sin \sigma_{13}} \\
\beta_2 & = & \alpha_{23} - \alpha_{21} \\
\alpha_{13} & = \alpha_{12} \mp \beta_1
\sigma_{13} & = & \operatorname{arctg\,} \dfrac{\sin \beta_2 \sin \sigma_{12}}{\cos \beta_2 \sin \beta_1 + \sin \beta_2 \cos \beta_1 \cos \sigma_{12}}
\end{align}</math>
\end{array}</math>


Правда, до вычисления длины ''σ''₁₃ необходимо проанализировать полученные значения углов ''β''₁ и ''β''₂. Ниже в коде функции можно увидеть пример такого анализа:
Если величина косинуса превышает единицу, задача поставлена некорректно, не выполняется закон «Длина стороны не может превышать сумму длин других сторон».
* если линии ''Q''₁''Q''₃ и ''Q''₂''Q''₃ совпадают с ''Q''₁''Q''₂, решение не определено, т.к. решением может быть любая точка геодезической линии ''Q''₁''Q''₂;
* если одна из линий ''Q''₁''Q''₃ и ''Q''₂''Q''₃ совпадает с ''Q''₁''Q''₂, а другая нет, решением является пункт, из которого выходит другая;
* если линии ''Q''₁''Q''₃ и ''Q''₂''Q''₃ уходят в разные полушария от ''Q''₁''Q''₂, функция находит ближайшее к ''Q''₁''Q''₂ «ложное пересечение» этих линий.


Здесь необходимо пояснить, что на сфере две несовпадающие геодезические линии всегда пересекаются в двух точках-антиподах. В традиционной постановке задачи направление на нужное пересечение задаётся явно. Если же прямое и обратное направления по условию равнозначны, возникает вопрос выбора одного из антиподов: ''φ''₃, ''λ''₃ или ''φ''₃′ = −''φ''₃, ''λ''₃′ = ''λ''₃ ± 180°.
В общем случае имеется два решения, расположенных симметрично относительно большого круга ''Q''''Q''₂. Следует явно определить, с какой стороны от направления ''Q''''Q''₂ находится точка ''Q''₃: если слева, как на рисунке, то в последней формуле ставим знак минус, если же справа — знак плюс.


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


Пример функции <tt>SphereAngular</tt> на языке Си, реализующей вышеизоложенный алгоритм:
Пример функции <tt>SphereLinear</tt> на языке Си, реализующей вышеизоложенный алгоритм:


<syntaxhighlight lang="c">
<syntaxhighlight lang="c">
/*
/*
  * Решение угловой засечки
  * Решение линейной засечки
  *
  *
  * Аргументы исходные:
  * Аргументы исходные:
  *    pt1   - {широта, долгота} пункта Q1
  *    pt1   - {широта, долгота} пункта Q1
  *    pt2   - {широта, долгота} пункта Q2
  *    pt2   - {широта, долгота} пункта Q2
  *    azi13 - азимут направления Q1-Q3
  *    dist13 - азимут направления Q1-Q3
  *    azi23 - азимут направления Q2-Q3
  *    dist23 - азимут направления Q2-Q3
*    clockwise - флаг направления:
*                0 - налево от линии Q1-Q2,
*                1 - направо от линии Q1-Q2
  *
  *
  * Аргументы определяемые:
  * Аргументы определяемые:
  *    pt3 - {широта, долгота} точки Q3
  *    pt3 - {широта, долгота} точки Q3
  */
  */
int SphereAngular(double pt1[], double pt2[], double azi13, double azi23,
int SphereLinear(double pt1[], double pt2[], double dist13, double dist23,
  double pt3[])
int right, double pt3[])
{
{
   double azi12, dist12, azi21, dist13;
   double azi12, dist12, azi13;
   double cos_beta1, sin_beta1, cos_beta2, sin_beta2, cos_dist12, sin_dist12;
   double cos_beta1;


   SphereInverse(pt2, pt1, &azi21, &dist12);
   if (dist13 == 0.) {       // Решение - точка Q1.
  SphereInverse(pt1, pt2, &azi12, &dist12);
  cos_beta1 = cos(azi13 - azi12);
  sin_beta1 = sin(azi13 - azi12);
  cos_beta2 = cos(azi21 - azi23);
  sin_beta2 = sin(azi21 - azi23);
  cos_dist12 = cos(dist12);
  sin_dist12 = sin(dist12);
 
  if (sin_beta1 == 0. && sin_beta2 == 0.)    // Решение - любая точка
    return -1;       //  на большом круге Q1-Q2.
  else if (sin_beta1 == 0.) {
    pt3[0] = pt2[0];       // Решение - точка Q2.
    pt3[1] = pt2[1];
    return 0;
  } else if (sin_beta2 == 0.) {       // Решение - точка Q1.
     pt3[0] = pt1[0];
     pt3[0] = pt1[0];
     pt3[1] = pt1[1];
     pt3[1] = pt1[1];
     return 0;
     return 0;
   } else if (sin_beta1 * sin_beta2 < 0.) {   // Лучи Q1-Q3 и Q2-Q3 направлены
   } else if (dist23 == 0.) {       // Решение - точка Q2.
     if (fabs(sin_beta1) >= fabs(sin_beta2)) { //  в разные полусферы.
     pt3[0] = pt2[0];
      cos_beta2 = -cos_beta2;       // Выберем ближайшее решение:
    pt3[1] = pt2[1];
      sin_beta2 = -sin_beta2;       //  развернём луч Q2-Q3 на 180°;
     return 0;
     } else {       //    иначе
      cos_beta1 = -cos_beta1;       //  развернём луч Q1-Q3 на 180°.
      sin_beta1 = -sin_beta1;
    }
   }
   }
   dist13 = atan2(fabs(sin_beta2) * sin_dist12,
 
cos_beta2 * fabs(sin_beta1)
  SphereInverse(pt1, pt2, &azi12, &dist12);
+ fabs(sin_beta2) * cos_beta1 * cos_dist12);
   cos_beta1 = (cos(dist23) - cos(dist12) * cos(dist13))
    / (sin(dist12) * sin(dist13));
  if (fabs(cos_beta1) > 1.)       // Решение не существует.
    return -1;
  azi13 = clockwise ? azi12 + acos(cos_beta1) : azi12 - acos(cos_beta1);
   SphereDirect(pt1, azi13, dist13, pt3);
   SphereDirect(pt1, azi13, dist13, pt3);


Строка 114: Строка 98:
</syntaxhighlight>
</syntaxhighlight>


Этот код находится в архиве [[Медиа:Sph.tar.gz|Sph.tar.gz]] в файле '''sph.c'''. Кроме того, в файл '''sph.h''' включены следующие определения:
Этот код находится в архиве [[Медиа:Sph.zip|Sph.zip]] в файле '''sph.c'''. Кроме того, в файл '''sph.h''' включены следующие определения:


<syntaxhighlight lang="c">
<syntaxhighlight lang="c">
Строка 122: Строка 106:
</syntaxhighlight>
</syntaxhighlight>


Теперь напишем программу, которая обращается к функции <tt>SphereAngular</tt> для решения угловой засечки:
Теперь напишем программу, которая обращается к функции <tt>SphereLinear</tt> для решения линейной засечки:


<syntaxhighlight lang="c">
<syntaxhighlight lang="c">
Строка 133: Строка 117:
   char buf[1024];
   char buf[1024];
   double pt1[2], pt2[2], pt3[2];
   double pt1[2], pt2[2], pt3[2];
   double lat1, lon1, lat2, lon2, azi13, azi23;
   double lat1, lon1, lat2, lon2, dist13, dist23;
  int clockwise;


   while (fgets(buf, 1024, stdin) != NULL) {
   while (fgets(buf, 1024, stdin) != NULL) {
     sscanf(buf, "%lf %lf %lf %lf %lf %lf",
     sscanf(buf, "%lf %lf %lf %lf %lf %lf %d",
  &lat1, &lon1, &lat2, &lon2, &azi13, &azi23);
  &lat1, &lon1, &lat2, &lon2, &dist13, &dist23, &clockwise);
     pt1[0] = Radians(lat1);
     pt1[0] = Radians(lat1);
     pt1[1] = Radians(lon1);
     pt1[1] = Radians(lon1);
     pt2[0] = Radians(lat2);
     pt2[0] = Radians(lat2);
     pt2[1] = Radians(lon2);
     pt2[1] = Radians(lon2);
     if (SphereAngular(pt1, pt2, Radians(azi13), Radians(azi23), pt3))
     if (SphereLinear(pt1, pt2, dist13 / A_E, dist23 / A_E, clockwise, pt3))
       puts("\t"); /* Бесконечно много решений на большом круге Q1-Q2 */
       puts("\t"); /* Решений нет */
     else
     else
       printf("%f\t%f\n", Degrees(pt3[0]), Degrees(pt3[1]));
       printf("%f\t%f\n", Degrees(pt3[0]), Degrees(pt3[1]));
Строка 151: Строка 136:
</syntaxhighlight>
</syntaxhighlight>


В архиве [[Медиа:Sph.tar.gz|Sph.tar.gz]] этот код находится в файле '''ang.c'''. Создадим исполняемый модуль '''ang''' компилятором '''gcc''':
В архиве [[Медиа:Sph.zip|Sph.zip]] этот код находится в файле '''lin.c'''. Создадим исполняемый модуль '''lin''' компилятором '''gcc''':


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
$ gcc -o ang ang.c sph.c -lm
$ gcc -o lin lin.c sph.c -lm
</syntaxhighlight>
</syntaxhighlight>


Впрочем, в архиве есть '''Makefile'''. Для MS Windows готовую программу '''ang.exe''' можно найти в архиве [[Медиа:Sph-win32.zip|Sph-win32.zip]].
Впрочем, в архиве есть '''Makefile'''. Для MS Windows готовую программу '''lin.exe''' можно найти в архиве [[Медиа:Sph-win32.zip|Sph-win32.zip]].


Программа читает данные из стандартного ввода консоли и отправляет результаты на стандартный вывод. Для чтения и записи файлов используются символы перенаправления потока «&gt;» и «&lt;» соответственно. Из каждой строки ввода программа считывает координаты первого и второго пунктов ''φ''₁, ''λ''₁, ''φ''₂, ''λ''₂, начальные азимуты ''α''₁₃ и ''α''₂₃ в градусах; решает угловую засечку; выводит в строку вывода координаты третьей точки ''φ''₃, ''λ''₃ в градусах.
Программа читает данные из стандартного ввода консоли и отправляет результаты на стандартный вывод. Для чтения и записи файлов используются символы перенаправления потока «&gt;» и «&lt;» соответственно. Из каждой строки ввода программа считывает координаты первого и второго пунктов ''φ''₁, ''λ''₁, ''φ''₂, ''λ''₂ в градусах, расстояния ''σ''₁₃ и ''σ''₂₃ в километрах (точнее, в единицах константы <tt>A_E</tt>) и признак направления (0 — налево от линии ''Q''₁''Q''₂, 1 — направо); решает линейную засечку; выводит в строку вывода координаты третьей точки ''φ''₃, ''λ''₃ в градусах.


Создадим файл '''ang.dat''', содержащий одну строку данных:
Создадим файл '''lin.dat''', содержащий одну строку данных:


<pre>
<pre>
30 0 60 30 44.80406 110.389945
30 0 60 30 5001.1309 1722.9431 1
</pre>
</pre>


Строка 170: Строка 155:


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
$ ang < ang.dat
$ lin < lin.dat
</syntaxhighlight>
</syntaxhighlight>


Строка 176: Строка 161:


<pre>
<pre>
52.000000 54.000000
52.000001 54.000000
</pre>
</pre>
В архиве [[Медиа:Sph-py.zip|Sph-py.zip]] находится код на языке Питон. Выполнение скрипта в командной консоли:
<syntaxhighlight lang="bash">
$ python lin.py lin.dat
</syntaxhighlight>


== Ссылки ==
== Ссылки ==
* [[Вычисление расстояния и начального азимута между двумя точками на сфере]]
* [http://gis-lab.info/qa/great-circles.html Вычисление расстояния и начального азимута между двумя точками на сфере]
* [http://gis-lab.info/qa/angles-sphere.html Вычисление угла образованного тремя точками на сфере]
* [http://gis-lab.info/qa/angles-sphere.html Вычисление угла образованного тремя точками на сфере]
* [[Задачи на сфере: обратная геодезическая задача]]
* [http://gis-lab.info/qa/sphere-geodesic-invert-problem.html Задачи на сфере: обратная геодезическая задача]
* [[Задачи на сфере: прямая геодезическая задача]]
* [http://gis-lab.info/qa/sphere-geodesic-direct-problem.html Задачи на сфере: прямая геодезическая задача]
* [[Задачи на сфере: угловая засечка]]
* [http://gis-lab.info/qa/sphere-geodesic-angular-resection.html Задачи на сфере: угловая засечка]
* [http://www.pm298.ru/sferich.php Краткий справочник по сферической тригонометрии]
* [http://en.wikipedia.org/wiki/Earth_radius Earth radius]
* [http://en.wikipedia.org/wiki/Earth_radius Earth radius]
* [http://gis-lab.info/docs/books/sphere-trigonometry/sphere-trigonometry.rar Степанов Н. Н. Сферическая тригонометрия]
* [http://gis-lab.info/docs/books/sphere-trigonometry/sphere-trigonometry.rar Степанов Н. Н. Сферическая тригонометрия]

Текущая версия от 08:43, 21 июня 2014

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


Линейная засечка — это нахождение положения точки по координатам двух исходных пунктов и расстояниям от этих пунктов до определяемой точки.

Общие положения

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

Введём следующие обозначения:

  • φ — географическая широта,
  • λ — географическая долгота,
  • α — азимут дуги большого круга,
  • σ — сферическое расстояние (длина дуги большого круга, выраженная в долях радиуса шара).

Линейное расстояние по дуге большого круга s связано со сферическим расстоянием σ формулой s = R σ.

Постановка задачи

Исходные данные
координаты пунктов Q₁, Q₂ — φ₁, λ₁, φ₂, λ₂,
расстояния от пунктов Q₁, Q₂ до точки Q₃ — σ₁₃, σ₂₃.
Определяемые величины
координаты точки Q₃ — φ₃, λ₃.

Алгоритм

Линейная засечка

Решение любого вида засечек сводится к нахождению полярных координат искомой точки, т.е. начального направления и расстояния на неё с одного из исходных пунктов. На конечном этапе координаты находятся из решения прямой геодезической задачи. Поскольку в линейной засечке расстояния σ₁₃ и σ₂₃ уже заданы, остаётся определить направление α₁₃ или α₂₃.

На рисунке синим цветом выделены заданные элементы сферических треугольников, красным цветом неизвестные, зелёным — вспомогательные элементы. Итак, в треугольнике QQQ₃ известны только два элемента — стороны σ₁₃ и σ₂₃. Из решения обратной геодезической задачи для пунктов Q₁, Q₂ можно получить недостающий третий элемент — расстояние σ₁₂, а также азимут α₁₂.

Последовательность действий:

  1. решить обратную геодезическую задачу для Q₁, Q₂: по φ₁, λ₁, φ₂, λ₂ получить α₁₂, σ₁₂;
  2. в треугольнике QQQ₃ по σ₁₂, σ₁₃, σ₂₃ вычислить угол β₁;
  3. вычислить азимут α₁₃;
  4. решить прямую геодезическую задачу для Q₁, Q₃: по φ₁, λ₁, α₁₃, σ₁₃ вычислить φ₃, λ₃.

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

Угол β₁ и азимут α₁₃ вычисляются по формулам:

Если величина косинуса превышает единицу, задача поставлена некорректно, не выполняется закон «Длина стороны не может превышать сумму длин других сторон».

В общем случае имеется два решения, расположенных симметрично относительно большого круга QQ₂. Следует явно определить, с какой стороны от направления QQ₂ находится точка Q₃: если слева, как на рисунке, то в последней формуле ставим знак минус, если же справа — знак плюс.

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

Пример функции SphereLinear на языке Си, реализующей вышеизоложенный алгоритм:

/*
 * Решение линейной засечки
 *
 * Аргументы исходные:
 *     pt1    - {широта, долгота} пункта Q1
 *     pt2    - {широта, долгота} пункта Q2
 *     dist13 - азимут направления Q1-Q3
 *     dist23 - азимут направления Q2-Q3
 *     clockwise - флаг направления:
 *                 0 - налево от линии Q1-Q2,
 *                 1 - направо от линии Q1-Q2
 *
 * Аргументы определяемые:
 *     pt3 - {широта, долгота} точки Q3
 */
int SphereLinear(double pt1[], double pt2[], double dist13, double dist23,
		 int right, double pt3[])
{
  double azi12, dist12, azi13;
  double cos_beta1;

  if (dist13 == 0.) {			      // Решение - точка Q1.
    pt3[0] = pt1[0];
    pt3[1] = pt1[1];
    return 0;
  } else if (dist23 == 0.) {		      // Решение - точка Q2.
    pt3[0] = pt2[0];
    pt3[1] = pt2[1];
    return 0;
  }

  SphereInverse(pt1, pt2, &azi12, &dist12);
  cos_beta1 = (cos(dist23) - cos(dist12) * cos(dist13))
    / (sin(dist12) * sin(dist13));
  if (fabs(cos_beta1) > 1.)		      // Решение не существует.
    return -1;
  azi13 = clockwise ? azi12 + acos(cos_beta1) : azi12 - acos(cos_beta1);
  SphereDirect(pt1, azi13, dist13, pt3);

  return 0;
}

Этот код находится в архиве Sph.zip в файле sph.c. Кроме того, в файл sph.h включены следующие определения:

#define A_E 6371.0				// радиус Земли в километрах
#define Degrees(x) (x * 57.29577951308232)	// радианы -> градусы
#define Radians(x) (x / 57.29577951308232)	// градусы -> радианы

Теперь напишем программу, которая обращается к функции SphereLinear для решения линейной засечки:

#include <stdio.h>
#include <stdlib.h>
#include "sph.h"

int main(int argc, char *argv[])
{
  char buf[1024];
  double pt1[2], pt2[2], pt3[2];
  double lat1, lon1, lat2, lon2, dist13, dist23;
  int clockwise;

  while (fgets(buf, 1024, stdin) != NULL) {
    sscanf(buf, "%lf %lf %lf %lf %lf %lf %d",
	   &lat1, &lon1, &lat2, &lon2, &dist13, &dist23, &clockwise);
    pt1[0] = Radians(lat1);
    pt1[1] = Radians(lon1);
    pt2[0] = Radians(lat2);
    pt2[1] = Radians(lon2);
    if (SphereLinear(pt1, pt2, dist13 / A_E, dist23 / A_E, clockwise, pt3))
      puts("\t"); /* Решений нет */
    else
      printf("%f\t%f\n", Degrees(pt3[0]), Degrees(pt3[1]));
  }
  return 0;
}

В архиве Sph.zip этот код находится в файле lin.c. Создадим исполняемый модуль lin компилятором gcc:

$ gcc -o lin lin.c sph.c -lm

Впрочем, в архиве есть Makefile. Для MS Windows готовую программу lin.exe можно найти в архиве Sph-win32.zip.

Программа читает данные из стандартного ввода консоли и отправляет результаты на стандартный вывод. Для чтения и записи файлов используются символы перенаправления потока «>» и «<» соответственно. Из каждой строки ввода программа считывает координаты первого и второго пунктов φ₁, λ₁, φ₂, λ₂ в градусах, расстояния σ₁₃ и σ₂₃ в километрах (точнее, в единицах константы A_E) и признак направления (0 — налево от линии QQ₂, 1 — направо); решает линейную засечку; выводит в строку вывода координаты третьей точки φ₃, λ₃ в градусах.

Создадим файл lin.dat, содержащий одну строку данных:

30 0 60 30 5001.1309 1722.9431 1

После запуска программы

$ lin < lin.dat

получим φ₃, λ₃:

52.000001 54.000000

В архиве Sph-py.zip находится код на языке Питон. Выполнение скрипта в командной консоли:

$ python lin.py lin.dat

Ссылки