Вычисление усредненных координат широты и долготы

19

Как я могу вычислить среднее значение между несколькими точками широты и долготы?

Должен ли я просто вычислить среднее арифметическое для широты и спина?

aneuryzm
источник
3
Я думаю, что целесообразность усреднения зависит от вашего варианта использования. Если вы просто группируете места расположения городских ресторанов для веб-карты, усреднение будет работать в большинстве случаев. Однако в некоторых местах вы будете получать ошибки .. для прототипа или приложения с низким бюджетом, возможно, это нормально. Однако, если вы делаете что-то более серьезное или охватывает обширную область, вам, вероятно, нужно учитывать нюансы проекции.
Гленн
1
Как были собраны эти очки? Вместо того, чтобы спрашивать, как усреднить координаты, возможно, спросите, является ли усреднение подходящим способом компенсации ошибок измерения. Эта книга имеет много определений ошибок.
Кирк Куйкендалл
Просто отметим, что есть некоторые граничные случаи, когда «средняя точка» не является четко определенной: например, где-нибудь вдоль экватора может предположительно быть «среднее» для полюсов N. и S.
Дан С.

Ответы:

15

Для простого среднего значения вы не хотите усреднять координаты долготы и широты. Это может работать довольно хорошо в более низких широтах, но в более высоких широтах это начнет давать плохие результаты и полностью сломаться около полюсов.

Метод, который я использовал для этого типа вещей, заключается в преобразовании координат долготы / широты в трехмерные декартовы координаты (x, y, z). Усредните их (чтобы получить декартовой вектор), а затем снова конвертируйте. Обратите внимание, что вам, вероятно, не нужно нормализовать вектор, поэтому фактический средний процесс может быть простой суммой.


Изменить, вот мой код :

Следующее преобразовывает декартовы координаты в широту / долготу (в градусах): Удалите RAD2DEGконстанты для радиан.

Latitude = MPUtility.RAD2DEG * Math.Atan2(z, Math.Sqrt(x * x + y * y));
Longitude = MPUtility.RAD2DEG * Math.Atan2(-y, x);

И здесь мы вычисляем декартовы координаты по широте / долготе (указаны в радианах):

private void CalcCartesianCoord()
{
    _x = Math.Sin(LatitudeRadians) * Math.Cos(LongitudeRadians);
    _y = Math.Sin(LatitudeRadians) * Math.Sin(LongitudeRadians);
    _z = Math.Cos(LatitudeRadians); 
}

Оба они вырезаны и вставлены из реального кода, отсюда и сочетание градусов и радиан. Здесь есть свойства, которые выполняют некоторые преобразования (например, LatitudeRadiansэто свойство, которое возвращает значение в радианах).

Обратите внимание, что возможна оптимизация: например, вычисления с использованием повторяющихся синусов. Также триггерные вычисления могут быть кэшированы, если вы их много называете.

winwaed
источник
1
отличный момент. Я не могу поверить, что я забыл упомянуть, что ... усреднение около полюсов и линии даты укусило меня раньше.
Гленн
3
(+1) Проблема не ограничивается полюсами и меридианом + -180 градусов: когда широта точек, подлежащих усреднению, значительно варьируется, прямое усреднение координат широта / долгота равносильно использованию проекции Плато-Карри, которая вводит переменное метрическое искажение, увеличивающееся с широтой. Численных проблем нет, но среднее значение просто не в том месте. По этой причине расчеты широты / долготы, предложенные в ответе @ Glenn, редко бывают приемлемыми, за исключением относительно небольших неполярных областей.
whuber
@winwaed спасибо, можете ли вы предложить какой-нибудь (Java) фрагмент кода или хороший учебник для этого?
aneuryzm
1
Математика находится на en.wikipedia.org/wiki/Spherical_coordinates в разделе «Декартовы координаты». (моя реализация C # и частично оптимизирована - плюс я
набираю
1
Я думаю, что для точного инженерного использования вы очень правы. Однако, если не требуется исключительной точности, усреднение координат широты и долготы WGS84 в городе и даже в регионах работает чертовски хорошо и дает результаты, которые являются приемлемо точными для большинства применений, где будет использоваться усреднение.
Гленн
3

Параметры кластеризации : я думаю, что концептуальное модное слово, которое охватывает этот тип операции, - «кластеризация». Усреднение на сегодняшний день является самым простым в реализации и хорошо работает для большинства целей. Единственный раз, когда я бы использовал что-то другое, это если вы беспокоитесь о выбросах [Правка] -> или о полюсах или международной дате. [Edit] -> также усреднение, в то время как оно даст вам что-то, что выглядит близко к центру кластера, будет немного отклонено из-за неточностей проекции, вызванных тем, что градусы широты не всегда одинаковы друг от друга в км / миль. Чем больше область, которую вы усредняете, тем больше искажение.

Вот сравнение нескольких вариантов кластеризации

Среднее (легкое, быстрое, неточное): просто сложите значения в латах, поделите на счетчик и сделайте то же самое для значений lng. Обязательно следите за переполнением, если вы используете Int32, некоторые системы (особенно c #) будут молча переполняться обратно к младшим числам. Вы можете избежать этих ошибок, используя точность с плавающей запятой для вашего накопителя суммы. Одна из проблем этого метода заключается в том, что выбросы могут искажать ваше местоположение. [Редактировать] -> Другое - математика около полюсов и международной линии дат не очень хорошо усредняется и будет искажать местоположения.

Ближайший сосед (немного сложнее, медленнее, не предвзято смещен) Вместо усреднения вы можете использовать реальное местоположение широты с наименьшим средним расстоянием до всех соседей. Это похоже на «медиану». Недостатком является то, что это вычислительно дорого, потому что вы сравниваете каждую точку с каждой другой точкой и вычисляете расстояние между ними. Например, кластеризация 10000 точек потребует 100 миллионов вычислений расстояний ... не так медленно, но это определенно плохо масштабируется.

Ячейка сетки (требуется немного дополнительной настройки, намного быстрее, не предвзято) Это похоже на ближайшего соседа, но намного быстрее. Вы можете выбрать произвольный уровень точности, скажем, 0,01 градуса широты (что составляет примерно 1 км примерно в населенных широтах) и сгруппировать свои точки в 0,01 х 0,01 градуса. Затем вы можете выбрать корзину с наибольшим количеством точек и либо взять среднее значение этих точек, либо выполнить анализ ближайшего соседа только по этим точкам. Я часто использую этот метод с действительно большими наборами данных (сотни миллиардов записей) и нахожу хороший баланс между точностью и скоростью.

Выпуклый корпус Корпус (твердые, медленные, аккуратные результаты): Вы также можете нарисовать полосу вокруг своих точек, чтобы определить форму, которая покрывает их все ( см. Википедию ), а затем вычислить центральную точку этой формы. Типичные функции центроида не имеют центрально-взвешенного значения, поэтому вам нужно будет провести некоторый обратный анализ ближайшего соседа с использованием точек выборки внутри фигуры, пока вы не найдете точку, самую дальнюю от краев. Этот метод действительно более интересен из-за самой выпуклой оболочки, а не фактического алгоритма нахождения центра, который не является ни быстрым, ни особенно точным ... но форма корпуса может иметь другие полезные приложения с вашими данными.

Гленн
источник
@winwaed замечательно подходит для усреднения координат около полюсов, и я бы также добавил международную линию дат. Например, если у вас есть одна точка на одной стороне и одна на другой, вы получите плохие средние (а также ограничивающие рамки). Это редко возникает, но когда это происходит, это настоящая боль для отладки
Glenn
@whuber делает хорошее замечание о смещении центра, когда вы в среднем. В то время как усреднение даст вам то, что выглядит близко к центру скопления, оно будет немного отклонено из-за неточностей проекции, вызванных тем, что градусы широты не всегда находятся на одинаковом расстоянии друг от друга в км / милях. Чем больше средняя область, тем больше искажение.
Гленн
0

Не уверен, что вы пытаетесь достичь, но точка, широта которой представляет собой среднюю широту исходного набора точек, а долгота - среднюю долготу первоначального набора точек, будет средней точкой исходного набора точек. [ОБНОВЛЕНИЕ]: В приведенном выше AVG является среднее арифметическое.

GuillaumeC
источник
В вашем ответе avg = Среднее арифметическое?
aneuryzm
1
Да исправить. Вот что я имел ввиду извините за отсутствие ясности. Я обновил ответ. Но я не уверен, что привожу что-то ужасно полезное к столу здесь ...
GuillaumeC