PHP MySql и геолокация - PullRequest
       18

PHP MySql и геолокация

9 голосов
/ 31 августа 2010

Я пишу сайт, который в основном ищет места в радиусе 25 миль от широты и долготы, используя php и mysql.

Мне интересно, как что-то подобное будет работать?

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

Каков наилучший способ сделать это?

РЕДАКТИРОВАТЬ: я нашел этот код для расчета расстояния между 2 точками.

    function distance($lat1, $lon1, $lat2, $lon2, $unit) { 

  $theta = $lon1 - $lon2; 
  $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); 
  $dist = acos($dist); 
  $dist = rad2deg($dist); 
  $miles = $dist * 60 * 1.1515;
  $unit = strtoupper($unit);

  if ($unit == "K") {
    return ($miles * 1.609344); 
  } else if ($unit == "N") {
      return ($miles * 0.8684);
    } else {
        return $miles;
      }
}

Это способ сделать это вычисление в MYSQL посмотреть, поэтому я могу вернуться только если мили = <25</p>

Ответы [ 3 ]

6 голосов
/ 31 августа 2010

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

Вот альтернатива, приблизительное вычисление, которое намного дешевле в вычислительном отношении:

Приблизительное расстояние в милях:

sqrt(x * x + y * y)

where x = 69.1 * (lat2 - lat1) 
and y = 53.0 * (lon2 - lon1) 

Вы можете повысить точность вычисления приблизительного расстояния, добавив математическую функцию косинуса:

Улучшенное приблизительное расстояние в милях:

sqrt(x * x + y * y)

where x = 69.1 * (lat2 - lat1) 
and y = 69.1 * (lon2 - lon1) * cos(lat1/57.3) 

Источник: http://www.meridianworlddata.com/Distance-Calculation.asp


Я провел несколько тестов со случайно сгенерированными наборами данных.

  • Разница в точности для трех алгоритмов составляет минимальная , особенно на небольших расстояниях
  • Самый медленный алгоритм - это, конечно, алгоритм с триггерными функциями (тот, что на вашем вопросе).Это в 4 раза медленнее, чем два других.

Определенно не стоит.Просто перейдите к приближению.
Код здесь: http://pastebin.org/424186


Чтобы использовать это в MySQL, создайте хранимую процедуру , которая принимает аргументы координат и возвращает расстояние,тогда вы можете сделать что-то вроде:

SELECT columns 
  FROM table 
 WHERE DISTANCE(col_x, col_y, target_x, target_y) < 25
2 голосов
/ 31 августа 2010

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

1 голос
/ 31 августа 2010

Вы можете сделать это легко в два этапа:

  • Найти все места в пределах 25 миль в каждом направлении от точки. Это будет выглядеть так: WHERE lat BETWEEN $lat1 AND $lat2 AND lng BETWEEN $lng1 AND $lng2

  • Затем выполните цикл по каждому результату и проверьте, действительно ли он находится в пределах 25 миль с использованием вашего кода. (т.е. отфильтровать те места, которые находятся в углах квадрата.)

Для первой части, вот некоторый код, который я разложил (не помню источник):

$lat_range = $radius / ((6076 / 5280) * 60);
$lng_range = $radius / (((cos(($city['lat'] * 3.141592653589 / 180)) * 6076) / 5280) * 60);

В основном просто используйте ($lat - $lat_range, $lat + $lat_range) и ($lng - $lng_range, $lng + $lng_range) Радиус в милях.

Очевидно, вы можете немного почистить математику.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...