Задачи на сфере: линейная засечка: различия между версиями
ErnieBoyd (обсуждение | вклад) (Новая страница: «{{Статья|Черновик}} {{Аннотация|Линейная засечка — это нахождение положения точки по коо…») |
ErnieBoyd (обсуждение | вклад) м (→Алгоритм) |
||
(не показана 21 промежуточная версия 2 участников) | |||
Строка 1: | Строка 1: | ||
{{Статья| | {{Статья|Опубликована|sphere-geodesic-linear-resection}} | ||
{{Аннотация|Линейная засечка — это нахождение положения точки по координатам двух исходных пунктов и | {{Аннотация|Линейная засечка — это нахождение положения точки по координатам двух исходных пунктов и расстояниям от этих пунктов до определяемой точки.}} | ||
== Общие положения == | == Общие положения == | ||
Строка 19: | Строка 19: | ||
; Исходные данные | ; Исходные данные | ||
: координаты пунктов ''Q''₁, ''Q''₂ — ''φ''₁, ''λ''₁, ''φ''₂, ''λ''₂, | : координаты пунктов ''Q''₁, ''Q''₂ — ''φ''₁, ''λ''₁, ''φ''₂, ''λ''₂, | ||
: | : расстояния от пунктов ''Q''₁, ''Q''₂ до точки ''Q''₃ — ''σ''₁₃, ''σ''₂₃. | ||
; Определяемые величины | ; Определяемые величины | ||
: координаты точки ''Q''₃ — ''φ''₃, ''λ''₃. | : координаты точки ''Q''₃ — ''φ''₃, ''λ''₃. | ||
Строка 25: | Строка 25: | ||
== Алгоритм == | == Алгоритм == | ||
[[Image: | [[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''₃: по ''φ''₁, ''λ''₁, ''α''₁₃, ''σ''₁₃ вычислить ''φ''₃, ''λ''₃. | ||
Действия по первому и последнему пунктам рассмотрены в статьях [ | Действия по первому и последнему пунктам рассмотрены в статьях [http://gis-lab.info/qa/sphere-geodesic-invert-problem.html Задачи на сфере: обратная геодезическая задача] и [http://gis-lab.info/qa/sphere-geodesic-direct-problem.html Задачи на сфере: прямая геодезическая задача]. | ||
Угол ''β''₁ и азимут ''α''₁₃ вычисляются по формулам: | |||
: <math>\begin{ | : <math>\begin{align} | ||
\beta_1 & = | \cos \beta_1 & = \dfrac{\cos \sigma_{23} - \cos \sigma_{12} \cos \sigma_{13}}{\sin \sigma_{12} \sin \sigma_{13}} \\ | ||
\alpha_{13} & = \alpha_{12} \mp \beta_1 | |||
\sigma_{13} | \end{align}</math> | ||
\end{ | |||
Если величина косинуса превышает единицу, задача поставлена некорректно, не выполняется закон «Длина стороны не может превышать сумму длин других сторон». | |||
В общем случае имеется два решения, расположенных симметрично относительно большого круга ''Q''₁''Q''₂. Следует явно определить, с какой стороны от направления ''Q''₁''Q''₂ находится точка ''Q''₃: если слева, как на рисунке, то в последней формуле ставим знак минус, если же справа — знак плюс. | |||
== Пример программной реализации == | == Пример программной реализации == | ||
Пример функции <tt> | Пример функции <tt>SphereLinear</tt> на языке Си, реализующей вышеизоложенный алгоритм: | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
/* | /* | ||
* Решение | * Решение линейной засечки | ||
* | * | ||
* Аргументы исходные: | * Аргументы исходные: | ||
* pt1 | * pt1 - {широта, долгота} пункта Q1 | ||
* pt2 | * pt2 - {широта, долгота} пункта Q2 | ||
* | * dist13 - азимут направления Q1-Q3 | ||
* | * dist23 - азимут направления Q2-Q3 | ||
* clockwise - флаг направления: | |||
* 0 - налево от линии Q1-Q2, | |||
* 1 - направо от линии Q1-Q2 | |||
* | * | ||
* Аргументы определяемые: | * Аргументы определяемые: | ||
* pt3 - {широта, долгота} точки Q3 | * pt3 - {широта, долгота} точки Q3 | ||
*/ | */ | ||
int | int SphereLinear(double pt1[], double pt2[], double dist13, double dist23, | ||
int right, double pt3[]) | |||
{ | { | ||
double azi12, dist12, | double azi12, dist12, azi13; | ||
double cos_beta1 | double cos_beta1; | ||
if (dist13 == 0.) { // Решение - точка Q1. | |||
pt3[0] = pt1[0]; | pt3[0] = pt1[0]; | ||
pt3[1] = pt1[1]; | pt3[1] = pt1[1]; | ||
return 0; | return 0; | ||
} else if ( | } 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); | SphereDirect(pt1, azi13, dist13, pt3); | ||
Строка 114: | Строка 98: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Этот код находится в архиве [[Медиа:Sph. | Этот код находится в архиве [[Медиа:Sph.zip|Sph.zip]] в файле '''sph.c'''. Кроме того, в файл '''sph.h''' включены следующие определения: | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
Строка 122: | Строка 106: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Теперь напишем программу, которая обращается к функции <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, | 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, & | &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 ( | if (SphereLinear(pt1, pt2, dist13 / A_E, dist23 / A_E, clockwise, pt3)) | ||
puts("\t"); /* | 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. | В архиве [[Медиа:Sph.zip|Sph.zip]] этот код находится в файле '''lin.c'''. Создадим исполняемый модуль '''lin''' компилятором '''gcc''': | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
$ gcc -o | $ gcc -o lin lin.c sph.c -lm | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Впрочем, в архиве есть '''Makefile'''. Для MS Windows готовую программу ''' | Впрочем, в архиве есть '''Makefile'''. Для MS Windows готовую программу '''lin.exe''' можно найти в архиве [[Медиа:Sph-win32.zip|Sph-win32.zip]]. | ||
Программа читает данные из стандартного ввода консоли и отправляет результаты на стандартный вывод. Для чтения и записи файлов используются символы перенаправления потока «>» и «<» соответственно. Из каждой строки ввода программа считывает координаты первого и второго пунктов ''φ''₁, ''λ''₁, ''φ''₂, ''λ''₂, | Программа читает данные из стандартного ввода консоли и отправляет результаты на стандартный вывод. Для чтения и записи файлов используются символы перенаправления потока «>» и «<» соответственно. Из каждой строки ввода программа считывает координаты первого и второго пунктов ''φ''₁, ''λ''₁, ''φ''₂, ''λ''₂ в градусах, расстояния ''σ''₁₃ и ''σ''₂₃ в километрах (точнее, в единицах константы <tt>A_E</tt>) и признак направления (0 — налево от линии ''Q''₁''Q''₂, 1 — направо); решает линейную засечку; выводит в строку вывода координаты третьей точки ''φ''₃, ''λ''₃ в градусах. | ||
Создадим файл ''' | Создадим файл '''lin.dat''', содержащий одну строку данных: | ||
<pre> | <pre> | ||
30 0 60 30 | 30 0 60 30 5001.1309 1722.9431 1 | ||
</pre> | </pre> | ||
Строка 170: | Строка 155: | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
$ | $ lin < lin.dat | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Строка 176: | Строка 161: | ||
<pre> | <pre> | ||
52. | 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₃ — φ₃, λ₃.
Алгоритм
Решение любого вида засечек сводится к нахождению полярных координат искомой точки, т.е. начального направления и расстояния на неё с одного из исходных пунктов. На конечном этапе координаты находятся из решения прямой геодезической задачи. Поскольку в линейной засечке расстояния σ₁₃ и σ₂₃ уже заданы, остаётся определить направление α₁₃ или α₂₃.
На рисунке синим цветом выделены заданные элементы сферических треугольников, красным цветом неизвестные, зелёным — вспомогательные элементы. Итак, в треугольнике Q₁Q₂Q₃ известны только два элемента — стороны σ₁₃ и σ₂₃. Из решения обратной геодезической задачи для пунктов Q₁, Q₂ можно получить недостающий третий элемент — расстояние σ₁₂, а также азимут α₁₂.
Последовательность действий:
- решить обратную геодезическую задачу для Q₁, Q₂: по φ₁, λ₁, φ₂, λ₂ получить α₁₂, σ₁₂;
- в треугольнике Q₁Q₂Q₃ по σ₁₂, σ₁₃, σ₂₃ вычислить угол β₁;
- вычислить азимут α₁₃;
- решить прямую геодезическую задачу для Q₁, Q₃: по φ₁, λ₁, α₁₃, σ₁₃ вычислить φ₃, λ₃.
Действия по первому и последнему пунктам рассмотрены в статьях Задачи на сфере: обратная геодезическая задача и Задачи на сфере: прямая геодезическая задача.
Угол β₁ и азимут α₁₃ вычисляются по формулам:
Если величина косинуса превышает единицу, задача поставлена некорректно, не выполняется закон «Длина стороны не может превышать сумму длин других сторон».
В общем случае имеется два решения, расположенных симметрично относительно большого круга Q₁Q₂. Следует явно определить, с какой стороны от направления Q₁Q₂ находится точка 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 — налево от линии Q₁Q₂, 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
Ссылки
- Вычисление расстояния и начального азимута между двумя точками на сфере
- Вычисление угла образованного тремя точками на сфере
- Задачи на сфере: обратная геодезическая задача
- Задачи на сфере: прямая геодезическая задача
- Задачи на сфере: угловая засечка
- Краткий справочник по сферической тригонометрии
- Earth radius
- Степанов Н. Н. Сферическая тригонометрия