Как я могу вычислить среднее значение между несколькими точками широты и долготы?
Должен ли я просто вычислить среднее арифметическое для широты и спина?
Как я могу вычислить среднее значение между несколькими точками широты и долготы?
Должен ли я просто вычислить среднее арифметическое для широты и спина?
Ответы:
Для простого среднего значения вы не хотите усреднять координаты долготы и широты. Это может работать довольно хорошо в более низких широтах, но в более высоких широтах это начнет давать плохие результаты и полностью сломаться около полюсов.
Метод, который я использовал для этого типа вещей, заключается в преобразовании координат долготы / широты в трехмерные декартовы координаты (x, y, z). Усредните их (чтобы получить декартовой вектор), а затем снова конвертируйте. Обратите внимание, что вам, вероятно, не нужно нормализовать вектор, поэтому фактический средний процесс может быть простой суммой.
Изменить, вот мой код C # :
Следующее преобразовывает декартовы координаты в широту / долготу (в градусах): Удалите 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
это свойство, которое возвращает значение в радианах).
Обратите внимание, что возможна оптимизация: например, вычисления с использованием повторяющихся синусов. Также триггерные вычисления могут быть кэшированы, если вы их много называете.
Параметры кластеризации : я думаю, что концептуальное модное слово, которое охватывает этот тип операции, - «кластеризация». Усреднение на сегодняшний день является самым простым в реализации и хорошо работает для большинства целей. Единственный раз, когда я бы использовал что-то другое, это если вы беспокоитесь о выбросах [Правка] -> или о полюсах или международной дате. [Edit] -> также усреднение, в то время как оно даст вам что-то, что выглядит близко к центру кластера, будет немного отклонено из-за неточностей проекции, вызванных тем, что градусы широты не всегда одинаковы друг от друга в км / миль. Чем больше область, которую вы усредняете, тем больше искажение.
Вот сравнение нескольких вариантов кластеризации
Среднее (легкое, быстрое, неточное): просто сложите значения в латах, поделите на счетчик и сделайте то же самое для значений lng. Обязательно следите за переполнением, если вы используете Int32, некоторые системы (особенно c #) будут молча переполняться обратно к младшим числам. Вы можете избежать этих ошибок, используя точность с плавающей запятой для вашего накопителя суммы. Одна из проблем этого метода заключается в том, что выбросы могут искажать ваше местоположение. [Редактировать] -> Другое - математика около полюсов и международной линии дат не очень хорошо усредняется и будет искажать местоположения.
Ближайший сосед (немного сложнее, медленнее, не предвзято смещен) Вместо усреднения вы можете использовать реальное местоположение широты с наименьшим средним расстоянием до всех соседей. Это похоже на «медиану». Недостатком является то, что это вычислительно дорого, потому что вы сравниваете каждую точку с каждой другой точкой и вычисляете расстояние между ними. Например, кластеризация 10000 точек потребует 100 миллионов вычислений расстояний ... не так медленно, но это определенно плохо масштабируется.
Ячейка сетки (требуется немного дополнительной настройки, намного быстрее, не предвзято) Это похоже на ближайшего соседа, но намного быстрее. Вы можете выбрать произвольный уровень точности, скажем, 0,01 градуса широты (что составляет примерно 1 км примерно в населенных широтах) и сгруппировать свои точки в 0,01 х 0,01 градуса. Затем вы можете выбрать корзину с наибольшим количеством точек и либо взять среднее значение этих точек, либо выполнить анализ ближайшего соседа только по этим точкам. Я часто использую этот метод с действительно большими наборами данных (сотни миллиардов записей) и нахожу хороший баланс между точностью и скоростью.
Выпуклый корпус Корпус (твердые, медленные, аккуратные результаты): Вы также можете нарисовать полосу вокруг своих точек, чтобы определить форму, которая покрывает их все ( см. Википедию ), а затем вычислить центральную точку этой формы. Типичные функции центроида не имеют центрально-взвешенного значения, поэтому вам нужно будет провести некоторый обратный анализ ближайшего соседа с использованием точек выборки внутри фигуры, пока вы не найдете точку, самую дальнюю от краев. Этот метод действительно более интересен из-за самой выпуклой оболочки, а не фактического алгоритма нахождения центра, который не является ни быстрым, ни особенно точным ... но форма корпуса может иметь другие полезные приложения с вашими данными.
Не уверен, что вы пытаетесь достичь, но точка, широта которой представляет собой среднюю широту исходного набора точек, а долгота - среднюю долготу первоначального набора точек, будет средней точкой исходного набора точек. [ОБНОВЛЕНИЕ]: В приведенном выше AVG является среднее арифметическое.