8 votos

¿Cómo saber si un punto está dentro de un rectángulo en el mapa?

Tengo cuatro puntos que representan un rectángulo (a,b,c,d). Estos puntos los he obtenido del GPS del móvil.

En mi base de datos tengo esta tabla de sedes comerciales:

bussId | longitude | latitude
-----------------------------
  ..      ..          ..

¿Cómo puedo saber qué empresas están dentro del rectángulo?

Quiero implementar esta función:

function isInsideRectangle(Point buss,Point a,Point b,Point c,Point d)

donde el Punto contiene la longitud y latitud.

0 votos

Descubrirá que esto funciona mucho mejor si utiliza un tipo de datos de Geometría (Punto) en lugar de campos separados de latitud y longitud, ya que podrá utilizar las funciones espaciales directamente e indexar el campo espacial, lo que dará lugar a mejoras de rendimiento no triviales a medida que el tamaño de la tabla aumente. ¿Está usted en condiciones de hacer esto?

6voto

rkthkr Puntos 6651

La respuesta real es una mezcla de las otras respuestas/comentarios que ya has recibido.

MySQL está limitado

Veo por las etiquetas que estás usando MySQL, el problema es que sólo puede hacer cuadros delimitadores hasta la 5.6, no las geometrías reales. http://dev.mysql.com/doc/refman/5.0/en/spatial-relation-functions.html

Si quieres utilizar el cuadro delimitador:

SELECT *
FROM `test`
WHERE CONTAINS(`bounds`, geomfromtext('POLYGON(0 0,10 0,10 10,0 10,0 0)'))

En 5.6.1 puede hacer las geometrías reales, así que sólo hay que cambiar CONTAINS à ST_CONTAINS . http://dev.mysql.com/doc/refman/5.6/en/spatial-relation-functions.html#functions-that-test-spatial-relationships-between-geometries

SELECT *
FROM `test`
WHERE ST_CONTAINS(`bounds`, geomfromtext('POLYGON(0 0,10 0,10 10,0 10,0 0)'))

Índices espaciales

Tenga en cuenta, en consonancia con el comentario de John (y el problema con la respuesta de David), es que cualquiera que sea la base de datos que usted va con, usted quiere ser el almacenamiento de sus datos como un point tipo de datos espaciales. Ver: https://dev.mysql.com/doc/refman/5.0/en/spatial-datatypes.html - Esto le permite aprovechar una serie de optimizaciones, incluidos los índices espaciales, que agilizarán las cosas. Véase también esta pregunta: https://stackoverflow.com/questions/5453063/benefits-of-spatial-over-using-standard-bounding-box-query

1 votos

No hace mucho respondí a una pregunta similar en SO, que muestra cómo crear un tipo de espacio e indexarlo, en caso de que se opte por esa vía. stackoverflow.com/questions/25232316/

1 votos

También vale la pena mencionar que incluso con 5.6, todas las operaciones son todavía planas, es decir, no hay soporte para las reproyecciones y los sistemas de coordenadas. Además, y esto aparentemente cambiará en una próxima versión, sólo se pueden indexar geometrías en MyISAM. Así que, si quieres soporte transaccional (InnoDB) y espacial juntos, no puedes.

3voto

nanonerd Puntos 101

A partir de las coordenadas de longitud y latitud, puede crear estructuras espaciales (Puntos) en su base de datos (espacial), como PostGIS. (ver ST_GeomFromText )
En lugar de su bussId | longitud | latitud, tendría una base de datos bussId, Point llamada BussSpatial. A continuación, sólo puede consultar lo siguiente

    var request =
    'SELECT bussID
    FROM BussSpatial
    WHERE ST_CONTAINS(ST_MakePolygon(ST_GeomFromText('LINESTRING(' + a + ',+'+' + b + ',' + ' + c ','+ d+ ')'), buss);';

donde a, b, c y d serían sus variables (en realidad debería ser a.longitud, a.latitud, etc...)

Cuidado: esta sentencia SQL no se puede utilizar directamente así, es una String en su

function isInsideRectangle(Point buss,Point a,Point b,Point d)

y entonces puedes hacer la petición dentro de la función.

2voto

Stuart Carnie Puntos 2961

La consulta del cuadro delimitador para SQL es (usando PDO)

$sql ="SELECT bussid FROM tablename WHERE(latitude  BETWEEN ? AND ? )AND (longitude  BETWEEN ? AND ?)";
$stmt = $dbh->prepare($sql);
// Assign parameters
$stmt->bindParam(1,$minLat);
$stmt->bindParam(2,$maxLat);
$stmt->bindParam(3,$minLng);
$stmt->bindParam(4,$maxLng);

Los parámetros WHERE provienen de la parte superior izquierda y de la parte inferior derecha del rectángulo

0 votos

Gracias por su respuesta! pero esto funcionará sólo si ab paralelo a x y el ad paralelo a y, ¿tiene otra sugerencia?

0 votos

Utilizar sólo para el rectángulo. Si se trata de un polígono, utilice la consulta del cuadro delimitador para eliminar la mayoría de los puntos que se encuentran fuera del cuadro delimitador y, a continuación, utilice un algoritmo de punto en polígono para eliminar los que se encuentran fuera del polígono. este para ilustrar

1voto

Elyrith Puntos 46

Si el map tiene un campo p de tipo POINT con índice SPATIAL se puede hacer esto:

set @p = concat('Polygon((',_x0,' ',_y0,',',_x1,' ',_y0,',',_x1,' ',_y1,',',_x0,' ',_y1,',',_x0,' ',_y0,'))');

select * from map
where mbrcontains(GeomFromText(@p),p);

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X