36 votos

¿Devolver todos los resultados en un radio de 30 km de un punto específico de latitud y longitud?

Tengo una tabla con una columna the_geom que contiene datos similares a:

0103000020E61000000100000005000000CE473AACFA071E40F27FB23340744740336FE841C6231E40873BED903F744740FC150A0ACE231E40D19E2684637647409C9B443D00081E409A9AF82664764740CE473AACFA071E40F27FB23340744740

Que al aplicar la función ST_AsEWKT(the_geom) devoluciones:

SRID=4326;POLYGON((7.5077921782085 46.9082092877942,7.53493597966353 46.9081898840296,7.53496566473541 46.9249119938446,7.50781341296434 46.9249314035307,7.5077921782085 46.9082092877942))

Necesito seleccionar todos los datos que se encuentran en un radio de 30 km de un punto específico de lat/long, por ejemplo:

  • lat = 46,8167
  • lng = 6,9333

Sin embargo, siempre que he intentado utilizar ST_Distance() siempre recibía valores inferiores a 1, y utilizando ST_DWithin() siempre devuelve un valor verdadero.

35voto

That Brazilian Guy Puntos 423

Por favor, compruebe la siguiente consulta para PostgreSQL para obtener datos dentro de cierta distancia. Espero que sea de ayuda.

SELECT *
FROM your_table
WHERE ST_Distance_Sphere(the_geom, ST_MakePoint(your_lon,your_lat)) <= radius_mi * 1609.34

10voto

Vafa Puntos 175

En mi mundo, utilizando un SRID personalizado (para Google Maps) funcionó algo así:

SELECT * FROM addresses WHERE ST_DWithin(location, ST_SetSRID(ST_MakePoint(longitude, latitude), 3785), radius);

donde el tipo de location es una geometría(Punto,3785), y longitude , latitude y radius son flotantes (por ejemplo, -100, 44, 30 para "unidades" de 100W/44N/30 - véase más abajo)

Ver ¿Cuál es la mejor manera de encontrar todos los objetos dentro de un radio de otro objeto? en los documentos de Postgis:

El ST_DWithin(geometry, geometry, distance) es una forma práctica de realizar una búsqueda de distancia indexada. Funciona creando un rectángulo de búsqueda lo suficientemente grande como para encerrar el radio de la distancia, y luego realizando una búsqueda de distancia exacta en el subconjunto indexado de resultados.

ACTUALIZACIÓN: las unidades no son millas para el SRID 3785... parecen ser radianes o grados o algo así. Pero la especificación de mi SRID dice que sus unidades son metros o grados y definitivamente no es ninguno de esos, al menos no sin alguna conversión:

alex=# select * from spatial_ref_sys where srid=3785; srid | auth_name | auth_srid | srtext | proj4text 3785 | EPSG | 3785 | PROJCS["Popular Visualisation CRS / Mercator (deprecated)",GEOGCS["Popular Visualisation CRS",DATUM["Popular_Visualisation_Datum",SPHEROID["Popular Visualisation Sphere",6378137,0,AUTHORITY["EPSG","7059"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6055"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4055"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","3785"],AXIS["X",EAST],AXIS["Y",NORTH]] | +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs

6voto

David Holm Puntos 6165

Parece que estás almacenando tu geometría en una columna de geometría, no en una columna de geografía.
Eso está bien, pero la función ST_Distancia devolverá las medidas en unidades de proyección en lugar de siempre en metros. En tu caso (4326), serán grados.
El uso de un buffer con ST_Within tampoco funcionará, ya que el ST_Buffer también se medirá con grados.

Puedes convertir tus datos para usar la geografía en lugar de la geometría, o puedes convertir tu punto en alguna proyección que use metros, buffer, y luego volver a convertir a 4326 para ver lo que hay dentro:

SELECT
    *
FROM <your data>
WHERE ST_Within(the_geom, 
                ST_Transform(ST_Buffer(ST_Transform(ST_SetSRID(ST_MakePoint(6.9333, 46.8167), 4326), 3857), 30000), 4326)) = 1

Eso proyecta el punto en 3857 que es una proyección muy popular en los mapas web. A continuación, lo amortigua en 30.000 metros y lo vuelve a proyectar a 4326 antes de pasarlo a ST_Within.

2voto

Xavier Nodet Puntos 2498

Creo que esto debería funcionar:

SELECT gid FROM table 
WHERE ST_DWithin(the_geom, ST_SetSRID(ST_Point(6.9333, 46.8167), 4326), 30000)

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