PHP MySQL получает местоположения в радиусе местоположения пользователя из GPS - PullRequest
5 голосов
/ 28 июля 2010

У меня в базе данных автомобильных происшествий например.Эти инциденты имеют широту и долготу.На мобильном телефоне с помощью GPS я получаю местоположение пользователя с его координатами.Пользователь может выбрать радиус, который он хочет знать, если вокруг него есть инциденты.Допустим, он хочет знать происшествия в 2 милях от него.

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

У вас есть идеи, как это сделать?

Ответы [ 5 ]

3 голосов
/ 28 июля 2010

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

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

1 минута = 1,86 километра = 1,15 мили

Просто найдите в БД инциденты в этом диапазоне (фактически квадрат, а не круг), и тогда вы можетеработать с ними с помощью PHP.


РЕДАКТИРОВАТЬ : вот альтернатива;приближение, которое намного дешевле в вычислительном отношении:

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

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


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

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

Определенно не стоит.Просто перейдите с приближением.

Код здесь: http://pastebin.org/424186

2 голосов
/ 28 июля 2010
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;
    }
  } // end function

$x_lat=center_of_serach;
$x_lon=center_of_serach;
$_distance=some_distance_in_miles;
$query1 = "SELECT * FROM `location_table` WHERE somefield=somefilter";
$result=mysql_db_query($db_conn, $query1);
$max_rows=mysql_num_rows($result); 
if ($max_rows>0)
  {
while ( $data1=mysql_fetch_assoc($result) )
  {
  if ( distance($x_lat,$x_lon,$data1['lat'],$data1['lng'],'m')<$_distance )
    {
    //do stuff
    }
  }

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

Это работает и для килограмм и морских миль.;)

0 голосов
/ 28 июля 2010

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

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

0 голосов
/ 28 июля 2010
 SELECT 3963 * ACOS(
    SIN(RADIANS($pointAlat)) * SIN(RADIANS($pointAlat)) + COS(RADIANS($pointAlat))  * COS(RADIANS($pointBlat)) * COS(RADIANS($pointAlong) - RADIANS($pointBlong)))
 AS
 distance;

Кроме того, если вы ищете хорошее руководство по чтению / обучению по этой теме. Проверьте здесь http://www.phpfreaks.com/forums/index.php/topic,208965.0.html

0 голосов
/ 28 июля 2010

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

Что касается PHP-кода, быстрый гугл обнаружил эту ссылку , которая выглядит так, как будто она работает.

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

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

...