He hecho esta pregunta varias veces en stackoverflow e irc entre #qgis y #postgis y también intenté codificarlo o implementarlo yo mismo en postgis sin una respuesta real.
Usando la programación (más preferiblemente python), me gustaría dibujar una línea desde una capa de puntos, hasta su proyección en la línea más cercana de una línea o capa de polígono.
A partir de ahora, la mayoría de mis datos están en forma de ESRI y formatos postgis; sin embargo, prefiero mantenerme alejado de una solución postgis ya que soy predominantemente un usuario shp + qgis.
Una solución ideal sería implementar GDAL / OGR con python o bibliotecas similares
- Usando las bibliotecas GDAL / OGR, ¿por dónde debería comenzar? ¿Sería posible dar un plan de solución?
- ¿Puedo usar NetworkX para hacer el análisis de vecino más cercano?
- ¿Es esto realmente posible?
Si es más fácil, los puntos podrían conectarse al punto final del segmento en lugar de un punto proyectado
Respuestas:
Esta pregunta resultó ser un poco más complicada de lo que pensé. Hay muchas implementaciones de la distancia más corta en sí misma, como la distancia proporcionada por Shapely (desde GEOS). Sin embargo, pocas de las soluciones proporcionan el punto de intersección en sí, pero solo la distancia.
Mi primer intento amortiguó el punto por la distancia entre el punto y el polígono, y busqué intersecciones, pero los errores de redondeo impiden que esto dé una respuesta exacta.
Aquí hay una solución completa usando Shapely, basada en estas ecuaciones :
Para la posteridad, parece que esta extensión ArcView maneja este problema bastante bien, lástima que esté en una plataforma muerta escrita en un idioma muerto ...
fuente
pairs
esto es algorítmicamente O (n) o algo así. La solución @eprand quizás se puede modificar para usar KNN, sin embargo, hasta ahora pude vivir sin PostGIS ...Una respuesta PostGIS (para multilínea, si es lineal, elimine la función st_geometryn)
fuente
Esto es un poco viejo, pero hoy estaba buscando soluciones a este problema (punto -> línea). La solución más simple que he encontrado para este problema relacionado es:
fuente
Si entiendo bien, la funcionalidad que está solicitando está integrada en PostGIS.
Para obtener un punto proyectado en una línea, puede usar ST_Closestpoint (en PostGIS 1.5)
Algunos consejos sobre cómo usarlo se pueden leer aquí: http://blog.jordogskog.no/2010/02/07/how-to-use-the-new-distance-related-functions-in-postgis-part1/
También se puede utilizar para encontrar el punto más cercano en un polígono a otro polígono, por ejemplo.
Si desea la línea entre los dos puntos más cercanos en ambas geometrías, puede usar ST_Shortestline. ST_Closestpoint es el primer punto en ST_Shortestline
La longitud de ST_Shortestline entre dos geometrías es la misma que ST_Distance entre las geometrías.
fuente
Vea el comentario a continuación sobre cómo mi respuesta no debe considerarse una solución confiable ... Dejaré esta publicación original aquí solo para que otros puedan examinar el problema.
Si entiendo la pregunta, este procedimiento general debería funcionar.
Para encontrar la ruta más corta entre un punto (como se define por x, y o x, y, z) y una poliina (como se define por un conjunto de conexión de x, y o x, y, z) dentro del espacio euclidiano:
1) Desde un punto definido por el usuario (lo llamaré pt0), encuentre el vértice más cercano de la polilínea (pt1). OGRinfo puede sondear los vértices de una polilínea, y luego se pueden hacer cálculos de distancia a través de métodos estándar. Por ejemplo, iterar sobre una distancia calculada como: distance_in_radians = 2 * math.asin (math.sqrt (math.pow ((math.sin ((pt0_radians-ptx_radians) / 2)), 2) + math.cos (pt0_radians) * math.cos (ptx_radians) * math.pow ((math.sin ((pt0_radians-ptx_radians) / 2)), 2)))
2) Almacene el valor de distancia mínima asociado (d1) y (pt1)
3) mire los dos segmentos que se derivan de pt1 (en la cadena lineal de ogrinfo, estos serán los vértices anteriores y posteriores). Registre estos vértices (n2 y n3).
4) crea y = mx + b fórmula para cada segmento
5) Relacione su punto (pt0) con la perpendicular para cada una de esas dos fórmulas
6) Calcular la distancia y las intersecciones (d2 y d3; pt2, pt3)
7) Compara las tres distancias (d1, d2, d3) para la más corta. Su pt0 al nodo asociado (pt1, pt2 o pt3) es el enlace más corto.
Esa es una respuesta de flujo de conciencia; con suerte, mi imagen mental del problema y la solución encajan.
fuente
Aquí hay un script de Python para QGIS> 2.0 hecho a partir de las sugerencias y soluciones dadas anteriormente. Funciona bien para una cantidad razonable de puntos y líneas. Pero no lo intenté con una gran cantidad de objetos.
Por supuesto, tenía que ser copiado en inactivo o cualquier otra "solución pitónica" y guardarlo como "más cercano.punto.py".
En la caja de herramientas QGIS, vaya a script, herramientas, agregue un script y elíjalo.
!!! ADVERTENCIA !!! Tenga en cuenta que se pueden producir algunos puntos proyectados "extraños" / incorrectos debido a este comando de línea:
El
counterSelec
valor establecido establece cuántos vecinos más cercanos se devuelven. De hecho, cada punto debe proyectarse a la distancia más corta posible a cada objeto de línea; y la distancia mínima encontrada daría la línea correcta y el punto proyectado como los vecinos más cercanos que buscamos. Para reducir el tiempo de bucle, se utiliza el comando vecino más cercano. Elegir uncounterSelec
valor reducido a 1 devolverá el "primer" objeto cumplido (es el cuadro delimitador más exactamente) y puede que no sea el correcto. Los objetos de diferentes tamaños de línea pueden obligar a elegir pueden ser 3 o 5, o incluso más objetos más cercanos para determinar la distancia más corta. Cuanto mayor sea el valor, más tiempo se necesita. Con cientos de puntos y líneas, comienza a ser muy lento con 3 o 5 vecinos más cercanos, con miles puede fallar con tales valores.fuente
Dependiendo de sus intereses y caso de uso, puede ser útil buscar "algoritmos de correspondencia de mapas". Por ejemplo, hay un proyecto RoadMatcher en el wiki de OSM: http://wiki.openstreetmap.org/wiki/Roadmatcher .
fuente