2009-07-28 6 views
3

Я собираюсь создать функцию в своем последнем проекте, предпочтительно используя PHP. Когда каждый пользователь подписывается, они собираются ввести свой почтовый индекс. Тогда, надеюсь, я буду преобразовывать это в lat/long, используя Open Street Map.Лучший способ для определения местоположения в радиусе начальной точки

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

Какой эффект может иметь следующий запрос в моей системе?

sql = "SELECT zipcode, (3959 * acos(cos(radians({$coords['latitude']})) 
    * cos(radians(latitude)) * cos(radians(longitude) 
    - radians({$coords['longitude']})) 
    + sin(radians({$coords['latitude']})) * sin(radians(latitude)))) 
    AS distance FROM zipcodes HAVING distance <= {$radius} ORDER BY distance"; 

Это потянуло из чьего-то блога.

У меня нет цифр для скорости регистрации или количества пользователей, поскольку она все еще находится в разработке.

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

+0

Это действительно вопрос, связанный с PHP? звучит как больше вопросов SQL. –

+0

Предпочтительными языками являются PHP/MySQL. Я не знал, есть ли какие-либо способы достижения этого, используя PHP, который, возможно, был пропущен иначе (очевидно, помимо выполнения вычислений в PHP). – 2009-07-28 14:18:56

ответ

2

Есть GIS и пространственные расширения для mySql в версии 4.1, см. here. Из описания вы найдете, что она используется для проблем, как у вас здесь:

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

Он добавляет несколько вещей, чтобы MySql как:

  • Spacial ключей и типа POINT:

    CREATE TABLE адрес ( адрес CHAR (80) NOT NULL, address_loc POINT NOT NULL, ПЕРВИЧНЫЙ КЛЮЧ (адрес), ПРОСТРАНСТВЕННЫЙ KEY (address_loc) );

  • преобразования подпрограммы

    вставить в адресные значения ('Foobar улице 12', GeomFromText ('POINT (2671 2500)'));

  • расчетные функции ГИС

    ВЫБОР c.cabdriver, ROUND (GLength (LineStringFromWKB (LineString (AsBinary (с.cab_loc), AsBinary (a.address_loc))))) AS расстояние Из кабины c, адрес a ORDER BY distance ASC LIMIT 1;

(примеры взяты из ссылки выше)

+1

За исключением того, что системы координат работают на основе 2D. Я искал GLength и нет никаких указаний на то, что он учитывает сферическую геометрию или делает что-либо иное, кроме вычисления теоремы Пифагора. –

+0

Это выглядит великолепно! Я собираюсь прочитать его сегодня вечером после работы, похоже, что я ищу! – 2009-07-28 14:19:32

0

Правда это Javascript не PHP, но это было бы тривиально преобразовать я бы себе представить.

Он вычисляет расстояние между двумя точками, учитывая кривизну Земли. Используется в логистическом приложении некоторое время назад, прежде чем заменять его кодом, который делает это, используя правильный маршрут дороги.

Это может быть полезны для вас ....

объектов
<script type="text/javascript"> 
function getDistance(lat1,lng1,lat2,lng2) 
{ 
    p1 = new VELatLong(lat1,lng1); 
    p2 = new VELatLong(lat2,lng2); 
    miles = true; 
    p1.Latitude= latLonToRadians(p1.Latitude); 
    p1.Longitude= latLonToRadians(p1.Longitude); 
    p2.Latitude= latLonToRadians(p2.Latitude); 
    p2.Longitude= latLonToRadians(p2.Longitude); 
    var R = 6371; // earth's mean radius in km 
    var dLat = p2.Latitude- p1.Latitude; 
    var dLong = p2.Longitude- p1.Longitude; 
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
    Math.cos(p1.Latitude) * Math.cos(p2.Latitude) * Math.sin(dLong/2) * 
Math.sin(dLong/2); 
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
    var disKm = R * c; 
    var disMiles = disKm * 0.6214; 
    alert (miles ? disMiles : disKm); 
} 
// convert lat/long in degrees to radians 
function latLonToRadians(point) 
{ 
    return point * Math.PI/180; 
} 
</script> 

О, и VELatLong приходят из API Virtual Earth (http://msdn.microsoft.com/en-us/library/bb412519.aspx), но в основном прославленная структура, поэтому вы должны быть может найти подходящую замену.

+0

OP не спрашивает о PHP (возможно, тег должен быть удален), а скорее о SQL-запросах. –

+0

На самом деле, он действительно говорит, что хочет реализовать этот проект на PHP и что он заинтересован в любых методах для соответствия пользователям в указанном радиусе. –

+0

Спасибо за вход. Не совсем то, что я искал, но это дает мне немного понимания математики! – 2009-07-28 14:22:40

1

Проблема может быть значительно упрощена, если вы хотите ослабить определение «в пределах определенного радиуса», чтобы не быть кругом. Если вы упростите «квадрат», вы можете найти все местоположение в пределах «радиуса» с помощью двух простых «между» предложениями (один для длинного лата). например:

SELECT * FROM location WHERE 
    lat BETWEEN (my_lat - radius) AND (my_lat + radius) 
    AND long BETWEEN (my_long - radius) AND (my_long + radius); 

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

+0

true ... хотя технически это дискриминирует людей, живущих вблизи международной линии дат или северных/южных полюсов :-) –

+0

Правда, поэтому «квадрат» находится в кавычках :) –

+0

Это тоже здорово! Я никогда не работал с лат-давно. Поэтому теоретически я мог бы выполнить свой первоначальный запрос по подмножеству данных, возвращенных из этого. Хорошая мысль! – 2009-07-28 14:20:55