Группировка гео координат

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Здравствуйте!

Хочу рассказать об кластеризации (группировке) геокоординат на стороне БД. Хотелось бы все это сделать в максимально простом виде, используя школьную математику. На работе появилась задача "отображение тепловой карты пожаров в МО". Пожары представлены виде географических координат. Нужно сгруппировать пожары, которые находятся в определенном радиусе, и на основе этих данных построить тепловую карту.

Готовые решения

Можно использовать стандартный тип geography Sql Server и с помощью distance процедуры рассчитать расстояния между точками и группировать их. Этот способ дорогой по времени, больше 10000 записей занимает примерно 5 минут на core i5 9600к.

Также можно использовать Tile38 (https://tile38.com/) не было времени внедрять, скорость вычисления идеальная. Но нет интеграции с SqlServer и для этого придеться синхронизировать координаты, и обеспечить отказаустойчивость для обеих систем.

Решение

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

Широту можно округлить не зависимо, например:

один градус широты = 2 * Pi * "Полярный радиус земли" / 360 ~ 111 км.

И так как по широте максимум может быть 90 градусов, получается ~ 9985 км. Это число нужно для того чтобы определить коэффициент разбиения по группам. Например Требуется округлить в радиусе 100 км, получается по широте может поместится ~ 100 групп. Итак, нам нужно еще получить до какой степени нужно округлить, - это мы получим следующей формулой.

6 - lg "масштаб группировки в метрах" - оставляем только целую часть

например 6 - lg 100000м = 1 и так нужно округлять первую цифру после запятой.

Итого формула для широты

declare @metersLatDegree float = round(9985238.0901698 / @maxMeters, 0);

declare @latituteCenter float = Round(Round(@latitude * @metersLatDegree / 90.0, 0) * (90.0 /@metersLatDegree), @precsion);

где @maxMeters это максимальная разница между координатами в метрах, @latitude широта, @precsion - степень округления.

Переходим к долготе и она будет зависеть от широты, так как при приближении к полису его периметр будет уменьшаться от ~ 40000 км до 0. и для того чтобы определить периметр нужно использовать cos(широты) по след формуле:

один градус долготы = 2 * Pi * "экваториальный радиус земли" * COS(широты) / 360 ~ 111 км. на экваторе когда широта равна 0 и когда широта равна 60 ~ 55 км.

Итоговая формула для долготы почти такая же

declare @metersLatDegree float= round(20037077.9445957 * cos(radians(@latitude)) / @maxMeters, 0);

declare @longitudeCenter float = Round(Round(@longitude * @metersLatDegree / 90.0, 0) * (90.0 /@metersLatDegree), @precsion);

@longitude - долгота

Чтобы получить @precsion формула одинаковая

@precsion int = 6 - round(log(@maxMeters), 10), 0)

Визуализируем результат для случайных 1000 точек по земле

на полюсах погрешность хромает, но для моего проекта подошло.

Источник: https://habr.com/ru/post/649001/


Интересные статьи

Интересные статьи

В данной пошаговой инструкции мы подробно опишем весь процесс получения доступа к WhatsApp Business API через официального партнера Facebook — сервис Gupshup и подключени...
Все «за» и «против» 1С-Битрикс, какие есть альтернативы и что выгоднее знать разработчику? Читать далее
Сейчас возможности Computer Vision (CV) полностью перекраивают ландшафт рынка Public Safety solutions. В то время, как традиционными системами видеонаблюдения уже не просто никого не ...
В 1С-Битрикс: Управление сайтом (как и в Битрикс24) десятки, если не сотни настраиваемых типов данных (или сущностей): инфоблоки, пользователи, заказы, склады, форумы, блоги и т.д. Стр...
В Челябинске проходят митапы системных администраторов Sysadminka, и на последнем из них я делал доклад о нашем решении для работы приложений на 1С-Битрикс в Kubernetes. Битрикс, Kubernetes, Сep...