Этот ответ состоит из нескольких разделов:
Анализ и уменьшение проблемы , показывая, как найти нужную точку с помощью «стандартных» процедур.
Иллюстрация: рабочий прототип , дающий рабочий код.
Пример , показывающий примеры решений.
Подводные камни , обсуждение потенциальных проблем и способы их решения.
Реализация ArcGIS , комментарии о создании специального инструмента ArcGIS и о том, где можно получить необходимые подпрограммы.
Анализ и уменьшение проблемы
Давайте начнем с наблюдения, что в (идеально круглой) сферической модели всегда найдется решение - фактически два решения. Для заданных базовых точек A, B и C каждая пара определяет свой «перпендикулярный биссектрис», который представляет собой набор точек, равноудаленных от двух данных точек. Этот биссектриса является геодезической (большой круг). Сферическая геометрия эллиптическая : любые две геодезические пересекаются (в двух уникальных точках). Таким образом, точки пересечения биссектрисы AB и биссектрисы BC по определению равноудалены от A, B и C, что решает проблему. (См. Первый рисунок ниже.)
На эллипсоиде все выглядит сложнее, но поскольку это небольшое возмущение сферы, мы можем ожидать аналогичного поведения. (Анализ этого приведет нас слишком далеко.) Сложные формулы, используемые (внутри ГИС) для вычисления точных расстояний на эллипсоиде, не являются концептуальным осложнением: проблема в основном та же. Чтобы увидеть, насколько на самом деле проста проблема, давайте сформулируем ее несколько абстрактно. В этом утверждении «d (U, V)» относится к истинному, полностью точному расстоянию между точками U и V.
Для трех точек A, B, C (в виде лат-длинных пар) на эллипсоиде найдите точку X, для которой (1) d (X, A) = d (X, B) = d (X, C) и ( 2) это общее расстояние как можно меньше.
Эти три расстояния все зависит от неизвестного X . Таким образом, различия в расстояниях u (X) = d (X, A) - d (X, B) и v (X) = d (X, B) - d (X, C) являются действительными функциями X. Опять же, несколько абстрактно, мы можем собрать эти различия в упорядоченную пару. Мы также будем использовать (lat, lon) в качестве координат для X, что позволит нам рассматривать его как упорядоченную пару, скажем, X = (phi, lambda). В этой настройке функция
F (фи, лямбда) = (u (X), v (X))
является функцией от части двумерного пространства, принимающей значения в двумерном пространстве, и наша задача сводится к
Найти все возможные (фи, лямбда), для которых F (фи, лямбда) = (0,0).
Вот где абстракция окупается: существует множество отличного программного обеспечения для решения этой (чисто численной многомерной задачи поиска корней). Это работает так, что вы пишете подпрограмму для вычисления F , а затем передаете ее программному обеспечению вместе с любой информацией об ограничениях на ее вход ( phi должно лежать в диапазоне от -90 до 90 градусов, а лямбда должна лежать в диапазоне от -180 до 180 градусов). Он запускается за доли секунды и возвращает (обычно) только одно значение ( фи , лямбда ), если он может найти его.
Есть детали для обработки, потому что в этом есть искусство: есть разные методы решения на выбор, в зависимости от того, как F «ведет себя»; это помогает «управлять» программным обеспечением, предоставляя ему разумную отправную точку для его поиска (это один из способов получить ближайшее решение, а не любое другое); и вам обычно нужно указать, насколько точным вы хотите, чтобы решение было (чтобы он знал, когда прекратить поиск). (Для получения дополнительной информации о том, что аналитики ГИС должны знать о таких деталях, которые часто встречаются в проблемах ГИС, посетите разделы «Рекомендации», которые необходимо включить в курс «Компьютерные науки для геопространственных технологий») и посмотрите в конце раздела «Разное». )
Иллюстрация: рабочий прототип
Анализ показывает нам нужно запрограммировать две вещи: неочищенную первоначальную оценку решения и вычисление F сам.
Первоначальная оценка может быть сделана «сферическим средним» трех базовых точек. Это получается путем представления их в геоцентрических декартовых (x, y, z) координатах, усреднения этих координат и проецирования этого среднего обратно в сферу и повторного ее выражения по широте и долготе. Размер сферы не имеет значения, и поэтому расчеты производятся просто: поскольку это только отправная точка, нам не нужны эллипсоидальные вычисления.
Для этого рабочего прототипа я использовал Mathematica 8.
sphericalMean[points_] := Module[{sToC, cToS, cMean},
sToC[{f_, l_}] := {Cos[f] Cos[l], Cos[f] Sin[l], Sin[f]};
cToS[{x_, y_, z_}] := {ArcTan[x, y], ArcTan[Norm[{x, y}], z]};
cMean = Mean[sToC /@ (points Degree)];
If[Norm[Most@cMean] < 10^(-8), Mean[points], cToS[cMean]] / Degree
]
(Конечное If
условие проверяет, может ли среднее значение явно не указывать долготу; если это так, оно возвращается к прямому арифметическому среднему значению широт и долгот своего входа - возможно, это не лучший выбор, но, по крайней мере, правильный. Для тех, кто использует этот код для руководства по реализации, обратите внимание, что аргументы Mathematica ArcTan
обращены вспять по сравнению с большинством других реализаций: его первый аргумент - это координата x, второй - координата y, и он возвращает угол, заданный вектором ( х, у).)
Что касается второй части, поскольку Mathematica - как ArcGIS и почти все другие ГИС - содержит код для вычисления точных расстояний на эллипсоиде, писать практически нечего. Мы просто вызываем процедуру поиска корня:
tri[a_, b_, c_] := Block[{d = sphericalMean[{a, b, c}], sol, f, q},
sol = FindRoot[{GeoDistance[{Mod[f, 180, -90], Mod[q, 360, -180]}, a] ==
GeoDistance[{Mod[f, 180, -90], Mod[q, 360, -180]}, b] ==
GeoDistance[{Mod[f, 180, -90], Mod[q, 360, -180]}, c]},
{{f, d[[1]]}, {q, d[[2]]}},
MaxIterations -> 1000, AccuracyGoal -> Infinity, PrecisionGoal -> 8];
{Mod[f, 180, -90], Mod[q, 360, -180]} /. sol
];
Наиболее примечательным аспектом этой реализации является то, как она избегает необходимости ограничивать широту ( f
) и долготу ( q
), всегда вычисляя их по модулю 180 и 360 градусов соответственно. Это позволяет избежать необходимости ограничивать проблему (что часто создает осложнения). Параметры управления MaxIterations
и т. Д. Настроены так, чтобы этот код обеспечивал максимально возможную точность.
Чтобы увидеть это в действии, давайте применим его к трем базовым пунктам, приведенным в связанном вопросе :
sol = tri @@ (bases = {{-6.28530175, 106.9004975375}, {-6.28955287, 106.89573839}, {-6.28388865789474, 106.908087643421}})
{-6.29692, 106.907}
Вычисленные расстояния между этим решением и тремя точками
{1450.23206979, 1450.23206979, 1450.23206978}
(это метры). Они соглашаются через одиннадцатую значащую цифру (которая на самом деле является слишком точной, поскольку расстояния редко бывают точными с точностью до миллиметра или около того). Вот изображение этих трех точек (черный), их три взаимных биссектрисы и решение (красный):
пример
Чтобы протестировать эту реализацию и лучше понять, как ведет себя проблема, вот контурный график среднеквадратичного расхождения расстояний для трех широко расположенных базовых точек. (Среднеквадратичное расхождение получается путем вычисления всех трех разностей d (X, A) -d (X, B), d (X, B) -d (X, C) и d (X, C) -d (X). , A), усредняя их квадраты и беря квадратный корень.Это равно нулю, когда X решает проблему, и в противном случае возрастает, когда X удаляется от решения, и таким образом измеряет, насколько «мы близки» к тому, чтобы быть решением в любом месте. )
Базовые точки (60, -120), (10, -40) и (45,10) показаны красным цветом в этой проекции Плато Карри; решение (49.2644488, -49.9052992), для вычисления которого потребовалось 0,03 секунды, выделено желтым цветом. Его среднеквадратичное отклонение составляет менее трех нанометров , несмотря на то, что все соответствующие расстояния составляют тысячи километров. Темные области показывают небольшие значения RMS, а светлые области показывают высокие значения.
Эта карта ясно показывает, что рядом находится другое решение (-49.2018206, 130.0297177) (вычислено для среднеквадратичного значения в два нанометра путем установки начального значения поиска, диаметрально противоположного первому решению.)
Ловушки
Численная нестабильность
Когда базовые точки почти коллинеарны и близки друг к другу, все решения будут располагаться почти на полмира, и их будет очень сложно точно определить. Причина в том, что небольшие изменения в местоположении по всему земному шару - перемещение его к базовым точкам или от них - вызовет только невероятно малые изменения в разнице расстояний. Просто нет точности и точности, встроенной в обычный расчет геодезических расстояний, чтобы определить результат.
Например, начиная с базовых точек в (45.001, 0), (45, 0) и (44.999,0), которые разделены вдоль простого меридиана только на 111 метров между каждой парой, tri
получают решение (11.8213, 77.745) ). Расстояния от него до базовых точек составляют 8 127 964,998; 77; 8 127 964,998; 41; и 8 127 964,998 65 метров соответственно. Они согласны с точностью до миллиметра! Я не уверен, насколько точным может быть этот результат, но не удивлюсь, если другие реализации вернут местоположения далеко от этого, демонстрируя почти такое же хорошее равенство трех расстояний.
Время вычислений
Эти вычисления, поскольку они включают в себя значительный поиск с использованием сложных вычислений расстояния, не являются быстрыми и обычно требуют заметной доли секунды. Приложения реального времени должны знать об этом.
Реализация ArcGIS
Python является предпочтительной средой сценариев для ArcGIS (начиная с версии 9). В пакете scipy.optimize есть многомерный rootfinder, root
который должен делать то, что FindRoot
делает в коде Mathematica . Конечно, сама ArcGIS предлагает точные расчеты эллипсоидального расстояния. Остальное - это все детали реализации: решить, как будут получены координаты базовой точки (из слоя, набранного пользователем, из текстового файла, из мыши) и как будет представлен результат (в виде координат). отображается на экране (в виде графической точки, как новый точечный объект в слое), напишите этот интерфейс, перенесите код Mathematica, показанный здесь (прямо), и все будет готово.