2010-08-31 25 views
8

Estoy escribiendo un sitio que básicamente busca lugares dentro de un radio de 25 millas de latitud y longitud usando php y mysql.PHP MySql y geolocalización

Me pregunto cómo algo así podría funcionar?

Me gustaría pasar un lat y largo para el scrip y hacer que saque solo las ubicaciones que están dentro de las 25 millas de latitud y longitud desde mi base de datos de ubicaciones.

¿Cuál es la mejor manera de hacerlo?

EDIT: Encontré este código para calcular la distancia entre 2 puntos.

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; 
     } 
} 

Es allí una manera de hacer esto Calc en el MYSQL mirar hacia arriba así que sólo puedo volver si milla = < 25?

+0

¿De dónde saca las otras ubicaciones? ¿Se almacenan todas las latitudes/longitudes de la ubicación deseada en una matriz o base de datos? – shamittomar

+0

Edité la pregunta. Tendré ciertas ubicaciones en mi base de datos y veré si alguna de ellas está dentro de las 25 millas. Si no, ninguno es devuelto. – shaneburgess

+0

algunos más información aquí: http://stackoverflow.com/questions/20865747/geolocation-mysql-query – miralong

Respuesta

6

Calcular la distancia usando esa función es bastante costoso desde el punto de vista computacional, porque involucra un conjunto completo de funciones trascendentales. Esto va a ser problemático cuando tiene una gran cantidad de filas para filtrar.

Aquí hay una alternativa, una aproximación que es mucho menos costoso computacionalmente:

Distancia aproximada en millas:

sqrt(x * x + y * y) 

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

Se puede mejorar la exactitud de este cálculo distancia aproximada mediante la adición de la función matemática del coseno:

distancia aproximada mejorada en millas:

sqrt(x * x + y * y) 

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

Fuente: http://www.meridianworlddata.com/Distance-Calculation.asp


me encontré con un montón de pruebas con conjuntos de datos generados al azar.

  • La diferencia en la precisión de los algoritmos 3 es mínima , especialmente en las distancias cortas
  • El algoritmo más lento es, por supuesto, el que tiene las funciones trigonométricas (la que está en su pregunta). Es 4 veces más lento que los otros dos.

Definitivamente no vale la pena. Solo ve con una aproximación.
Código está aquí: http://pastebin.org/424186


utilizar esto en MySQL, crear un stored procedure que se lleva a coordinar argumentos y devuelve la distancia, entonces usted puede hacer algo como:

SELECT columns 
    FROM table 
WHERE DISTANCE(col_x, col_y, target_x, target_y) < 25 
0

Puede hacerlo fácilmente en dos pasos:

  • Encuentra todas las ubicaciones dentro de las 25 millas en cada dirección del punto.Esto se verá así: WHERE lat BETWEEN $lat1 AND $lat2 AND lng BETWEEN $lng1 AND $lng2

  • Luego recorra cada resultado y verifique si realmente está dentro de las 25 millas usando su código. (. Es decir, a filtrar esos lugares que se encuentran en las esquinas de la plaza)

Para la primera parte, aquí hay un código que se tienen alrededor (no recuerdo la fuente):

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

Básicamente solo use ($lat - $lat_range, $lat + $lat_range) y ($lng - $lng_range, $lng + $lng_range) El radio está en millas.

Obviamente puedes limpiar las matemáticas un poco.

Editar: Me olvidé de mencionar que tendría que modificarlo un poco si necesita para apoyar ubicaciones cerca del ecuador, línea de fecha internacional, etc. Obviamente para América del Norte, estaría bien tal como está.

+0

Esto por supuesto tiene la desventaja de necesitar dos pasos de filtrado, ya que devuelve filas innecesarias. – NullUserException

+0

Sí, pero evita realizar cálculos en toda la base de datos. Con un radio pequeño y un gran conjunto de datos, eso puede ser importante. – Matthew

2

Es posible que desee echar un vistazo a this solution - una solución algo brillante.