Как вычислить / определить расстояние между одной точкой координат X и рядом других точек координат Y,Z,…, в заведомо известном радиусе с центром в X

В наше время требования к веб-приложениям значительно возросли. От простых веб-страниц мы пришли к сложным системам, требующим сложной логики для реализации тех или иных задач. Не достаточно просто разработать продукт, который будет работать. Он должен быть уникальным, предлагать быстрый и надежный инструмент, для решение поставленной задачи. Сценарий работы, должен быть тщательно проработан.   В одном из проектов, Мы столкнулись с задачей работы с координатами. Суть заключалась в том, чтобы определить расстояние (дистанцию) от координат пользователя в определенном радиусе поиска, до всех объектов, которые в него (радиус поиска) попадают. Проблемой стало то, что при большом количестве пользователей, необходимо было обеспечить быструю и отказоустойчивую систему, которая выполняла бы поставленную задачу с минимальными затратами ресурсов времени. Проблема:

Как вычислить расстояние от точки координат, заданной в виде центра окружности с определенным радиусом, до точек, которые входят в нее (окружность)?

Проработав большое количество вариантов реализации данной задачи, было принято решение переложить всю ответственность на один SQL-запрос, который полностью удовлетворит поставленной цели. Было необходимо построить его так, чтобы он работал быстро и эффективно. Решение:

-- это координаты точки, которая будет задана в качестве центра зоны поиска

-- в условие WHERE нужно передать id, для которого нужно произвести поиск

SELECT @home_latitude := latitude, @home_longitude := longitude FROM geo_location.geo_object WHERE id = 1;

-- константы/параметры для дальнейших вычислений

-- константа радиус Земли в км

SELECT @earth_radius := 6371;

-- параметр дистанции поиска в км

SELECT @distance_limit := 10;

-- коэффициенты пересчета км в градусы координат

SELECT @ratio_latitude := 1.2 * 360 / (2 * PI() * @earth_radius);

SELECT @ratio_longitude := 1.2 * @ratio_latitude * cos ( radians ( @home_latitude ) );

-- тело запроса

SELECT id, object_name,

(

-- расчет расстояния объектов от центра поиска

@earth_radius * acos

(

cos ( radians ( @home_latitude ) ) *

cos ( radians ( latitude ) ) *

cos ( radians ( longitude ) -

radians( @home_longitude ) ) +

sin ( radians ( @home_latitude ) ) *

sin ( radians ( latitude ) )

)

)

AS distance

FROM geo_location.geo_object

-- предварительный отбор объектов, которые попадают в квадрат поиска

-- требуется для того, чтобы не рассчитывать расстояние для тех объектов,

-- которые заведомо не подходят.

WHERE

latitude > @home_latitude - ( @distance_limit * @ratio_latitude ) AND

latitude < @home_latitude + ( @distance_limit * @ratio_latitude ) AND

longitude > @home_longitude - ( @distance_limit * @ratio_longitude ) AND

longitude < @home_longitude + ( @distance_limit * @ratio_longitude )

-- отбор и сортировка по расстоянию объектов, у которых расстояние от центра меньше заданной дистанции

HAVING distance < @distance_limit

ORDER BY distance

-- ограничение выборки в 100 строк;

-- если нужно, можно удалить или изменить

LIMIT 0 , 100;

Данное решение полностью удовлетворяет заданной цели. Синтаксис данного запроса соответствует СУБД MySql, но с легкостью может быть перестроен для любой другой реляционной базы данных. В итоге удалось достичь заданной цели. Система работает быстро с минимальным количеством затрат ресурсов и времени. Легко настраивается, удобно модифицируется, работает быстро и надежно.