¿Cómo obtener el punto más cercano en una cadena lineal a un punto dado?

28

¡He estado usando PostGIS durante mucho tiempo, pero nunca tuve que usar la LINESTRINGgeometría ...! :)

Esto es lo que me gustaría hacer: tengo una tabla de cadenas lineales (que representan las calles de una ciudad determinada, SRID 3395) y me gustaría encontrar las cadenas lineales más cercanas a un punto determinado (posición GPS, SRID 4326).

La solución que encontré es seleccionar todas las cadenas de líneas dentro de mi punto usando el expand()método y determinar la distancia entre cada cadena de líneas y mi punto usando el ST_Distance()método.

Aquí está el SQL:

SELECT myLineId, myLineName, ST_Distance(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395),myLineGeom) AS myLineDistance
FROM myLines
WHERE myLineGeom && expand(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395), 100)
ORDER BY myLineDistance;

Los resultados que obtengo se ven bien, pero tengo la sensación de que algo está mal en mi implementación.

1) ¿Ustedes piensan que expand()pueden obtener todas las cadenas de líneas en cuestión?

2) ¿Ustedes piensan que ST_Distance()es el método correcto para usar? Supongo que lo estoy haciendo mal, ya que la distancia que me gustaría obtener es la distancia más pequeña entre el punto y mi línea y no la distancia entre el punto y uno de los puntos de la cadena lineal.

Ilustración:

texto alternativo

Vivi
fuente

Respuestas:

11

anuncio 1) Mirando la documentación de sus funciones utilizadas, yo diría: "Sí, se encontrarán todas las cadenas de líneas en cuestión".

expandir (geometría, flotación)

Esta función devuelve un cuadro delimitador expandido en todas las direcciones desde el cuadro delimitador de la geometría de entrada, en una cantidad especificada en el segundo argumento. Muy útil para consultas de distancia (), para agregar un filtro de índice a la consulta.

A y B

El operador "&&" es el operador "superpuesto". Si el cuadro delimitador de A se superpone al cuadro delimitador de B, el operador devuelve verdadero.

anuncio 2) Debería poder lograr lo que desea a través de:

line_interpolate_point(linestring, line_locate_point(LineString, Point))

line_interpolate_point (cadena de líneas, ubicación)

Interpola un punto a lo largo de una línea. El primer argumento debe ser un LINESTRING. El segundo argumento es un float8 entre 0 y 1 que representa una fracción de la longitud total 2d en la que debe ubicarse el punto.

line_locate_point (LineString, Point)

Devuelve un flotante entre 0 y 1 que representa la ubicación del punto más cercano en LineString al Punto dado, como una fracción de la longitud total de la línea 2d. Puede usar la ubicación devuelta para extraer un Punto (line_interpolate_point)

Fuente: http://main.merlin.com.ua/doc/postgis/docs/ch06.html

bajo oscuro
fuente
Para el punto 2), me preguntaba si ST_Distance entre una geometría POINT y una geometría LINESTRING proporciona la menor distancia posible entre tesis (también conocida como la longitud de la línea perpendicular entre POINT y LINGESTRING); Quiero distancia de cada geometría LINESTRING :)
Vivi
Y supongo que no es la distancia lo que estoy buscando ya que "la función line_locate_point le da un valor entre 0 y 1 que representa la ubicación del punto más cercano en LineString al Punto dado": /
Vivi
Me temo que me perdiste en tu último comentario. Ahora ya no estoy seguro de lo que quieres;)
oscuro
1
Lo siento :) Me gustaría esto: dando una geometría LINESTRING (que representa una ruta) y una geometría POINT, quiero tener la geometría POINT más cercana que está en la ruta (que puede no ser un punto de la definición de geometría LINESTRING). ¿Está limpio? Tal vez debería actualizar mi publicación con un dibujo: D
Vivi
No puedo actualizar mi publicación, así que aquí hay un enlace a un dibujo de lo que me gustaría obtener: i.imgur.com/UwPxo.jpg
Vivi
7

Hola

Primero la pregunta sobre qué ST_Distance devuelve. ST_Distance devuelve la distancia más corta entre la línea y el punto (o qué tipos de geometría se incorporan) Eso significa que ST_Distance entre el punto (1 3) y la cadena lineal (0 0,0 10) devolverá 1. La distancia no se medirá entre punto y (0 0) o el punto y (0 10) pero desde el punto (1 3) a (0 3).

Entonces, por lo que entiendo, ST_Distance te da la respuesta que deseas.

Si desea encontrar el punto (0 3) en el ejemplo anterior, puede usar ST_Closestpoint si tiene PostGIS 1.5. Para mi ejemplo, lo usa así: ST_Closestpoint ('LINESTRING (0 0,0 10)' :: geometry, ' POINT (1 3) ':: geometry), entonces debería obtener el punto (0 3) a cambio, el punto en la línea que está más cerca de su punto.

HTH Nicklas

Nicklas Avén
fuente
5

Lo encontré :) (Bueno, supongo: P)

Usando ST_Line_Locate_Point()y ST_Line_Interpolate_point()logré obtener un punto que NO ES parte de la definición de LINESTRING, pero ESTÁ en la línea mencionada :) Todo lo que tengo que hacer es obtener la distancia desde mi punto hasta este punto y listo.

SELECT AsText(ST_Line_Interpolate_Point(myLineGeom,ST_Line_Locate_Point(myLineGeom,ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395))))
FROM myLines
WHERE myGeom && expand(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395), 100)

El ST_Line_Locate_Point()método encuentra la ubicación del punto más cercano en la línea al punto dado, el ST_Line_Interpolate_Pointmétodo convierte esta ubicación en un punto.

Vivi
fuente
1
St_distance entre el punto y la línea te dará la misma respuesta. ¿Por qué crees que tienes que hacerlo de esta manera?
Nicklas Avén
1
Creo que ST_Distance se puede usar con cualquier tipo de geometría. postgis.refractions.net/docs/ST_Distance.html :ST_Distance(geometry g1, geometry g2)
Magno C