Поиск расстояния до точки на карте по координатам
В проекте, для которого мы использовали базу GeoIP, появилась новая задача: в базе у нас уже хранится много записей о салонах и теперь необходима возможность искать по этой базе ближайшие по расстоянию объекты или, например, салоны, которые находятся на расстоянии менее 10км. Тут на помощь пришла редко используемая в современной тригонометрии функция гаверсинус. По сути, она и является правильной формулой для сферического приближения, которая выглядит так:
Данная формула подвержена проблеме точек-антиподов, чтобы ее решить используется следующая ее модификация.
Но тут в нашем классе, который и отвечал за вычисления пришлось ввести константу, задающую радиус земли в километрах:
const EARTH_RADIUS_KM = 6373;
Осталось дело за малым: наиболее рационально пользоваться этой формулой. Так как, я повторюсь, данные с координатами у нас лежат в таблице, то и вычислять нужные нам расстояния мы будем при помощи SQL.
Вот сама функция формирующая запрос для вычисления расстояния:
private function _getHaversineWithAntipodDotsDistanceCondition($latitude,$longitude)
{
$numerator = 'POW(COS(RADIANS(latitude)) * SIN(ABS(RADIANS('.$longitude.')-RADIANS(longitude))),2)';
$numerator .= ' + POW(
COS(RADIANS('.$latitude.')) * SIN(RADIANS(latitude)) - SIN(RADIANS('.$latitude.'))
* COS(RADIANS(latitude))*COS(ABS(RADIANS('.$longitude.')-RADIANS(longitude)))
,2)';
$numerator = 'SQRT('.$numerator.')';
$denominator = 'SIN(RADIANS(latitude))*SIN(RADIANS('.$latitude.')) +
COS(RADIANS(latitude))*COS(RADIANS('.$latitude.'))*
COS(ABS(RADIANS('.$longitude.')-RADIANS(longitude)))';
$condition = 'ATAN('.$numerator.'/('.$denominator.')) * '.self::EARTH_RADIUS_KM;
return $condition;
}
В данную функцию мы передаем две координаты точки, от которой нам нужно считать наше расстояние: широту и долготу.
В таблице, по которой мы ищем наши объекты, также должны быть поля latitude и longitude. Как мы можем применить нашу функцию?! Например, нам нужно найти все записи таблицы `table`, описывающие объекты, которые находятся от данной точки с известными нам координатами на определенном расстоянии. Делается так:
public function getNearestsObjectsByDistance( $latitude_start, $longitude_start, $distance )
{
$condition = $this->_getHaversineWithAntipodDotsDistanceCondition($latitude_start, $longitude_start);
$sqlQuery = 'SELECT
*,
'.$condition.' as distance
FROM
table
WHERE distance <'.intval($distance);
}
В эту функцию мы передаем следующие параметры: широта нашей точки, долгота, максимальное удаление, на котором могут находиться объекты. Задав, например координаты, полученные по IP пользователя в предыдущем посте и дальность 100 км, мы получим следующий запрос:
SELECT *, ATAN(SQRT(POW(COS(RADIANS(latitude)) * SIN(ABS(RADIANS(-111.8147)-RADIANS(longitude))),2) + POW( COS(RADIANS(41.692)) * SIN(RADIANS(latitude)) - SIN(RADIANS(41.692)) * COS(RADIANS(latitude))*COS(ABS(RADIANS(-111.8147)-RADIANS(longitude))) ,2))/(SIN(RADIANS(latitude))*SIN(RADIANS(41.692)) + COS(RADIANS(latitude))*COS(RADIANS(41.692))* COS(ABS(RADIANS(-111.8147)-RADIANS(longitude))))) * 6373 as distance FROM table WHERE distance <100
Пожалуй, правильней было бы использовать тут хранимые процедуры, что, возможно, в скором времени и придется сделать.
Иногда написав кучу кода, а потом случайно что-то удалив, жалеешь, что не установил на компьютер А чтобы не забывать что и куда вы пишете можете установить на компьютер клавиатурный шпион. Всем хорошего дня и креативного настроения в работе




Великолепная подача! Все, у кого есть дополнительная инфа - пожалуйста в асю пять672404пять2.
Как только появится больше свободного времени обещаю написать еще парочку статей по данному вопросу
Как ни крути, а это ваш самый лучший пост. Добавил в закладки.
Спасибо. Посты на самом деле еще далеки от совершенства, но я работаю над своим стилем, сочинения в школе писал лучше девчонок. Буду стараться преподносить материал более интерестно
Только сегодня наткнулся на ваш сайт
Прочёл от корки до корки. Но именно этот пост однозначно один из самых лучших!
Мда… Примерно тоже самое прочел на 7дей.ру. Уже много раз замечал. Просто сам сталкивался с этим. Впрочем… может меня и подглючивает .
Честно признаться формулу я не выводил
а вот всю программную реализацию делал сам
Великолепный пост. Добавил в бобрдобр.
Спасибо. Пока этот я считаю самым удачным
и интерестным
К стати, диз в опере немного коряв. Проверьте style.css.
Спасибо, проверю!
Супер, но сегодня дочитать не успею, добавил в закладки.
Эмм.. а можно ли у вас брать посты с рсс канала? Ссылку на вас обязательно поставлю.
Целиком посты нет, можно брать заголовок или начало поста, а дальше ставить ссылку на меня - блог молодой и дублирование контента ему очень не нужно, простите
Уже не первую неделю читаю. Но более всего нравится стиль изложения. Даже чем-то на Гришковца похоже. Буквально на раз все прочитываю.
Спасибо :)) Я не специально, я так и в жизни рассказываю
Хотел спросить, а может вы напишете что-нибудь про кризис? Что делать и что будет потом… А то меня уволили с работы, не знаю что делать дальше. Думаю многим будет интересно!
В принципе, кризис затронул и меня и тема довольно-таки интересная, о нем писано-переписано уйма, но можно изложить и свою точку зрения, если будет что сказать конечно-же
Очень долго писал, а потом подумал, а почему надрываться? В общем, нужно писать более полезные посты. Вот буквально прошлый - замечательный. А вот этот - уже не так. Держите планку!
Спасибо за критику, буду стараться
Как вижу тут многие выскащываются, что вы хорошо пишите. Так вот, как копирайтер заявляю - уровень у вас как у хорошего писателя!
Все хорошо, только, как я думаю, стоит обновляться побольше!
Здравствуйте. Можно сказать, что совсем недавно попал на ваш блог, теперь каждое утро захожу глянуть, а не написали ли чего нового.
Но, к сожалению, вы не каждый день свой блог обновляете
Да, к сожалению не всегда хватает времени писать о том что хочется, да и хорошо подать материал тоже требует времени, но я буду стараться
Если не секрет, откуда вы родом? Уж очень на украинца похожи
:))) почти угадали - родился и вырос в Западной Беларуси
Подписался на РСС канал, буду следить =)
Спасибо, еще и друзей приводите
Спасибо за статью, у меня как раз проект, работающий с Яндекс.Картами. И поиск ближайшей точки на карте является актуальной задачей.