2012-07-20 11 views
20

16a de noviembre de 2012

me gustaría plantear esta pregunta de nuevo, ofreciendo una nueva recompensa por una buena solución sólida,. Parece que solo la solución (shubhansh's answer) no funciona de manera efectiva ahora. Explicaré por qué.Obtener resultados que caen dentro de radios marcadores de la base de datos de actualización de

primer lugar, este es el mapa en vivo que tengo con radios y las personas, los radios están en red y la gente están en blue.

enter image description here

Como se puede ver, hay two personas en este mapa con eight radios, básicamente, que estoy recibiendo sólo la persona que es Person A, pero no estoy recibiendo Person B , Supongo que el SQL no lo está recogiendo correctamente, y necesito que sea preciso y preciso a partir del radio de la persona y los radios marcadores.

Parece que lo que se recoge son los radios, no los que se superponen a un radio, necesito que pueda detectar los resultados de los radios que se superponen entre sí.

Estoy buscando un SQL preciso y preciso que la respuesta de shubhansh. Puede leer a continuación para leer exactamente cómo necesito la consulta para actuar y seleccionar personas precisas.

Los datos, PERSONAS:

+-----------+-----------+--------+ 
| latitude | longitude | radius | 
+-----------+-----------+--------+ 
| 51.517395 | -0.053129 | 5.6 | 
| 51.506607 | -0.116129 | 0.7 | 
+-----------+-----------+--------+ 

Tenga en cuenta que es radius en kilómetros.

+-----------+-----------+-----+ 
| latitude | longitude | km | 
+-----------+-----------+-----+ 
| 51.502117 | -0.103340 | 0.3 | 
| 51.498913 | -0.120850 | 0.7 | 
| 51.496078 | -0.108919 | 0.7 | 
| 51.496506 | -0.095873 | 0.7 | 
| 51.503399 | -0.090723 | 0.7 | 
| 51.508049 | -0.100336 | 0.7 | 
| 51.508797 | -0.112610 | 0.7 | 
| 51.505535 | -0.125227 | 0.7 | 
| 51.502331 | -0.108061 | 0.7 | 
+-----------+-----------+-----+ 

El SQL actual que utilizo:

SELECT ppl.latitude, 
     ppl.longitude, 
     ppl.radius 
FROM 
(
    people ppl 
), 
(
    SELECT latitude, longitude 
    FROM radiuses 
) AS radius 
WHERE (POW((ppl.longitude - radius.longitude) * 111.12 * COS(ppl.latitude), 2) + POW((ppl.longitude - radius.longitude) * 111.12, 2)) <= 4 
GROUP BY ppl.id 

Los datos de MySQL que se puede utilizar para probar la consulta,

INSERT INTO radiuses (id, latitude, longitude, km) VALUES ('1', '51.502117', '-0.103340', '0.3'), ('2', '51.498913', '-0.120850', '0.7'), ('3', '51.496078', '-0.108919', '0.7'), ('4', '51.496506', '-0.095873', '0.7'), ('5', '51.503399', '-0.090723', '0.7'), ('6', '51.508049', '-0.100336', '0.7'), ('7', '51.508797', '-0.112610', '0.7'), ('8', '51.505535', '-0.125227', '0.7'), ('9', '51.502331', '-0.108061', '0.7'); 

INSERT INTO people (id, latitude, longitude, radius) VALUES ('1', '51.517395', '-0.053129', '5.6'), ('2', '51.506607', '-0.116129', '0.7'); 

Resumen Antiguo

Nota: todas las latitudes y longitudes son hechas al azar.

que tienen un applet de mapa que un usuario puede colocar su radio de de una ubicación LAT/LNG, con un radio de 1 km.

Ahora, hay otro usuario que puede poner sus radios , en cualquier ubicación en el mapa, cada uno con un radio de 1 km (igual que el usuario anterior).

Como este El usuario A es rojo y El usuario B es azul.

enter image description here

Básicamente usuario A tiendas de sus radios en una mesa que tiene este aspecto:

+-----------+---------+-----------+-----------+ 
| radius_id | user_id | latitude | longitude | 
+-----------+---------+-----------+-----------+ 
|   1 |  1 | 81.802117 | -1.110035 | 
|   2 |  1 | 81.798272 | -1.144196 | 
|   3 |  1 | 81.726782 | -1.135919 | 
+-----------+---------+-----------+-----------+ 

Y usuario B tiendas de su radio en otra tabla que tiene este aspecto - (nota : solo pueden almacenar 1 coordenadas por cuenta):

+---------+-----------+-----------+ 
| user_id | latitude | longitude | 
+---------+-----------+-----------+ 
|  6 | 81.444126 | -1.244910 | 
+---------+-----------+-----------+ 

Quiero poder seleccionar aquellos usuarios que se encuentran dentro de los radios definidos, incluso si los círculos del radio se están tocando, en la imagen del mapa. Solo el marcador C podría recoger el radio único, cuando A y B no lo hacen.

Estoy seguro de que esto es posible, pero no sé cómo crear este tipo de sistema en MySQL.

Encontré esto en el sitio de Google Developers, está cerca, pero no solo de lo que funciona. Necesito.

EDITAR: he encontrado una mejor, esto es muy estrecha, pero todavía no lo que yo estoy buscando, ya que utiliza 1 atado de la latitud y la longitud coordina cuando tener múltiples en una mesa.

+0

Esto puede ser una respuesta que le da una pista http://stackoverflow.com/questions/11502469/find-records-with-lattitude-and-logintude/11502530#11502530 que acaba de agregar una distancia 'WHERE <1234 ' a la consulta. – fdomig

Respuesta

6

El punto esencial de su geometría es que dos círculos se superponen si la distancia entre sus centros es menor que la suma de sus radios. Ya que estamos haciendo una comparación, podemos usar el cuadrado de la distancia, ya que eso evita una operación de raíz cuadrada. En el original, cada radio se fija en 1, la suma de los dos radios es 2 y el cuadrado de la suma es 4.

Hay una gran diferencia entre la pregunta original y la nueva. En el primero tienes círculos de radio fijo y en el segundo tienes círculos de radio variable. La constante 4 en la expresión de comparación [...distance^2...] <= 4 necesita ser reemplazada, ya que eso es un artefacto del radio fijo del original. Para implementar esto, agregue el campo km en la consulta. Y como debe comprobar, no estaba usando ppl.radius en el filtro WHERE, por lo que no es de extrañar que la variación de ese valor no cambiara los resultados de su consulta.

SELECT ppl.latitude, ppl.longitude, ppl.radius 
FROM 
    (people ppl), 
    (SELECT latitude, longitude, km FROM radiuses) AS B 
WHERE [...distance^2...] <= POW(ppl.radius + B.km, 2) 

debería decir que esta cuestión tomó mucho más tiempo para entender de lo que debería, ya que está llamando a la entidad-eso es-not-a-persona una "radio", cuando en realidad usted tiene una propiedad que debería llamarse 'radio' en dos entidades diferentes. Así que nombre esa otra entidad algo descriptivo.

14

Para la solución de este que hay que entender ecuación del círculo, que es algo así Para cualquier punto (x, y) para caer dentro de círculo con centro (x1, y1) y unidades de radio r es

(x-x1)^2 + (y - y1)^2 <= r^2 

where a^b = a to the power b 

Aquí, en su caso del usuario B (latitud, longitud) son el centro del círculo, el usuario a de (latitud, longitud) son los puntos (x, y) y radio = 2 km.

Pero el problema básico es cambiar grados de latitudes a longitudes, por lo que aquí está la solución, 1 grado = 111.12 km. Así que para mantener las unidades igual en ambos lados de la ecuación, vamos a convertirlo en Kms

Así que nuestra ecuación final se convierte en:

((x-x1)*111.12)^2 + ((y-y1)*111.12)^2 = 4  (=2^2) 

instrucción SQL para el mismo debe ser algo como esto

SELECT A.user_id, A.radius_id, A.latitude, A.logitude 
FROM UserA AS A, 
    (SELECT user_id, latitude, longitude 
     FROM UserB 
     WHERE user_id = 8) AS B 
WHERE (POW((A.latitude-B.latitude)*111.12, 2) + POW((A.longitude - B.longitude)*111.12, 2)) <= 4 
/* **Edit** Here I have used (A.longitude - B.longitude)*111.12, for more accurate results one can replace it with (A.longitude - B.longitude)*111.12*cos(A.latitude)) or (A.longitude - B.longitude)*111.12*cos(B.latitude)) 

And, as i have suggested in the comments that first filter some records based on approximation, so whether one uses A.latitude or B.latitude it will not make much difference */ 

Espero que esto ayude ...

+0

Puede factorizar 111.12^2. Luego divide ambos lados por esa cantidad. DÓNDE (POW ((A.latitude-B.latitude), 2) + POW ((A.longitude - B.longitude), 2)) <= 4/(111.12^2). – walrii

+0

@walrii Sí, esto se puede hacer ... – Shubhansh

+2

Un grado = 111.12 km solo en el ecuador; a medida que avanzas hacia los polos, la latitud permanece relativamente constante, pero la longitud se aproxima a cero, por lo que esta solución se volverá cada vez más imprecisa a medida que te alejes del ecuador. –

7

En el corazón de su problema está la pregunta "¿cómo sé si dos círculos se superponen?". La respuesta a eso es "si la distancia entre sus centros es menor que la suma de sus radios". Entonces, lo que estás buscando es cómo determinar la distancia entre dos puntos.

La otra respuesta trata la latitud y la longitud como si tuvieran un plano cartesiano. que no lo hacen (la longitud tiende a cero al acercarse a los polos desde el ecuador).Ahora, como una aproximación, puede funcionar perfectamente para su solución, dependiendo de la precisión que necesite su solución. Por otro lado, si necesita que esto sea muy preciso, necesita la fórmula de Haversine. Hay una gran descripción de cómo implementarlo en MySQL aquí:

http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL

De diapositiva 7 de dicha presentación, que tiene la siguiente fórmula:

3956*2*ASIN(SQRT(POWER(SIN((orig.lat-dest.lat)*pi()/180/2),2)+ 
    COS(orig.lat*pi()/180)*COS(dest.lat*pi()/180)* 
    POWER(SIN((orig.lon-dest.lon)*pi()/180/2),2))) 

Tenga en cuenta que el primer número es la media radio de la tierra en millas; cambiar eso a 6371 por kilómetros.

El uso de esta distancia calculada dependerá de detalles no incluidos en su publicación, como el número de puntos que está tratando, la dispersión geográfica, los requisitos de rendimiento y si los datos son estáticos o no o estar continuamente actualizado.

Menciono estas cosas porque el rendimiento va a ser un problema, especialmente si tiene una cantidad significativa de datos y/o se actualiza continuamente (como las ubicaciones del usuario en función de los datos GPS de su teléfono).

Una forma en que puede ayudar con el problema de rendimiento es utilizar cuadrados en lugar de círculos, y usar la aproximación de un grado = 111.12 km. De esta forma, puede eliminar automáticamente cualquier punto que esté obviamente muy alejado el uno del otro. Entonces solo queda calcular la fórmula de Haversine solo para los pocos puntos que caen dentro del área de interés.

Espero que esto sea útil para orientarlo en la dirección correcta.

Cuestiones relacionadas