OK - He estado luchando con esto durante aproximadamente 3 meses de forma intermitente y desde que he agotado todas las fórmulas de proximidad geográfica que he encontrado y que No estoy más cerca de obtener los resultados correctos, pensé que era hora de pedir ayuda.Faltan resultados debido a la fórmula de proximidad geográfica (localizador de tiendas)
EL OBJETIVO
Soy la creación de una aplicación bastante básica de un localizador de tiendas. El usuario ingresa su código postal y selecciona de una lista predefinida de radios de búsqueda. La API de gmaps genera coordenadas lat/long para esta dirección y las pasa a una secuencia de comandos php. En este script las coordenadas de usuario se preguntó en contra de una tabla de base de datos MySQL (estructura de abajo)
post_id int(11)
post_type varchar(20)
lat float(10,6)
lng float(10,6)
Los resultados de esta consulta (post IDS) se introducen en una consulta de wordpress que genera el XML que contiene los datos del mapa de marcadores. (La consulta wordpress utiliza post__in y posts_per_page -1 para mostrar la información para todos ID generado por la consulta
EL PROBLEMA
En pocas palabras, cada implementación de la fórmula Haversine que he encontrado parece ser el resultado en marcadores faltantes, específicamente cualquier marcador que esté muy cerca de las coordenadas ingresadas por los usuarios (no lo sé con precisión, pero creo que está dentro de los 500 m). Este es un gran problema, como si el usuario ingresara su código postal y hay una tienda muy cerca a su ubicación no aparecerá.
He intentado unas 8 permutaciones diferentes de la forumla que he desenterrado fr om varios tutoriales con los mismos resultados. A continuación se muestra la fórmula que estoy usando actualmente en el sitio que ofrece todos los marcadores excepto por el los más cercanos a los usuarios la posición entrado:
$center_lat = $_GET["lat"];
$center_lng = $_GET["lng"];
$radius = $_GET["radius"];
// Calculate square radius search
$lat1 = (float) $center_lat - ((int) $radius/69);
$lat2 = (float) $center_lat + ((int) $radius/69);
$lng1 = (float) $center_lng - (int) $radius/abs(cos(deg2rad((float) $center_lat)) * 69);
$lng2 = (float) $center_lng + (int) $radius/abs(cos(deg2rad((float) $center_lat)) * 69);
$sqlsquareradius = "
SELECT
post_id, lat, lng
FROM
wp_geodatastore
WHERE
lat BETWEEN ".$lat1." AND ".$lat2."
AND
lng BETWEEN ".$lng1." AND ".$lng2."
"; // End $sqlsquareradius
// Create sql for circle radius check
$sqlcircleradius = "
SELECT
t.post_id,
3956 * 2 * ASIN(
SQRT(
POWER(
SIN(
(".(float) $center_lat." - abs(t.lat)) * pi()/180/2
), 2
) + COS(
".(float) $center_lat." * pi()/180
) * COS(
abs(t.lat) * pi()/180
) * POWER(
SIN(
(".(float) $center_lng." - t.lng) * pi()/180/2
), 2
)
)
) AS distance
FROM
(".$sqlsquareradius.") AS t
HAVING
distance <= ".(int) $radius."
ORDER BY distance
"; // End $sqlcircleradius
$result = mysql_query($sqlcircleradius);
$row = mysql_fetch_array($result);
while($row = mysql_fetch_array($result)) {
// the contents of each row
$post_ids[] = $row['post_id'];
}
Hubo 1 fórmula que he intentado que se sugirió por Mike Pelley aquí : Geolocation SQL query not finding exact location
Esta fórmula parecía mostrar marcadores que estaban muy cerca de la ubicación de los usuarios introducidos, pero se perdieron otros que deberían haberse mostrado dentro del radio dado. Para aclarar cualquier confusión que esto es el código que utilicé:
$center_lat = $_GET["lat"];
$center_lng = $_GET["lng"];
$radius = $_GET["radius"];
$sql = "
SELECT post_id, lat, lng,
truncate((degrees(acos(sin(radians(lat))
* sin(radians(".$center_lat."))
+ cos(radians(lat))
* cos(radians(".$center_lat."))
* cos(radians(".$center_lng." - lng))))
* 69.09*1.6),1) as distance
FROM wp_geodatastore HAVING distance <= ".$radius." ORDER BY distance desc
"; // End $sqlcircleradius
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
while($row = mysql_fetch_array($result)) {
// Print out the contents of each row
$post_ids[] = $row['post_id'];
}
LA SOLICITUD
Básicamente me gustaría saber por qué ninguno de estos bloques de código están mostrando los marcadores correctos. Si alguien puede sugerir una mejora al código o me puede apuntar hacia algún recurso que podría haber perdido que sería grande
EDITAR
pensaba que mi respuesta psudeo funcionaba pero como resulta que todavía estaba teniendo problemas. Terminé yendo por un rumbo muy diferente ahora y estoy usando un muy buen localizador de tiendas jquery que se puede encontrar aquí: http://www.bjornblog.com/web/jquery-store-locator-plugin
No funcionará para todos los proyectos, pero para mis necesidades es perfecto (y funciona!)
¿Hay alguna razón por la que no esté utilizando las capacidades geospaciales integradas de MySQL? http://dev.mysql.com/doc/refman/5.0/en/creating-a-spatially-enabled-mysql-database.html – Kenneth
Estoy luchando por comprender algunas cosas en tu código. ¿Por qué 'HAVING' en lugar de' WHERE'? ¿Qué está pasando con las cosas 'int' en' (float) $ center_lat - ((int) $ radius/69); 'y' truncado' en su otra consulta? Tenga en cuenta este hecho al aplicar las fórmulas: un minuto de longitud en el ecuador se define como una milla náutica. Un grado entero es 60 millas náuticas. Finalmente, intente deshacerse de 'BETWEEN' y usar 'WHERE a> = lat1 AND a <= lat2' en su lugar. Debe dar la misma complejidad de consulta y explica la inclusividad/exclusividad del rango que está buscando. –
@Kenneth - No estoy utilizando las consultas geoespaciales por un par de razones. Primero, estoy usando el [plugin de la tienda de geodatos] (http://wordpress.org/extend/plugins/geo-data-store) para crear y mantener mi tabla de datos de marcadores. Este complemento genera la estructura de tabla que mostré arriba. En segundo lugar, la gran mayoría de los tutoriales que he encontrado para crear mapas de tipo localizador de tiendas parecen recomendar una estructura de tabla similar a la que figura en la lista. Tal vez estas no sean las mejores razones, pero he llegado hasta aquí con la configuración actual y estoy bastante seguro de que lo que estoy tratando de hacer debería ser posible. – FourStacks