Estoy tratando de crear polígonos voronoi en QGIS que consideren "agujeros" en el dominio general. Un ejemplo sería:
De hecho, creé el Voronois en esta imagen usando QGIS a través del comando GRASS, luego usando la herramienta "Diferencia" para crear los agujeros. Se usó un archivo de forma de polígono separado, que contiene la extensión de los agujeros, como la capa "Diferencia". Una aplicación de ejemplo sería crear polígonos alrededor de puntos de muestreo que se recopilaron entre estructuras que deberían excluirse del análisis.
Aquí surgen dos problemas:
La función "diferencia" no parece funcionar al 100% correctamente, con algunos límites de polígono que se extienden hacia los "agujeros". Esto se puede solucionar encontrando una fila en la tabla de atributos que no tenga un número de identificación de polígono (o una identificación de "0").
Este tipo de "perforación" después del hecho puede dar lugar a polígonos discontinuos, como lo muestra la flecha roja en la imagen.
Mi pregunta es: ¿existe una herramienta o complemento Voronoi que pueda considerar la presencia de "agujeros" en el centro del dominio, como un proceso de un solo paso, y también eliminar la generación de polígonos discontinuos? Me imagino que una herramienta así extendería un límite de polígono a la intersección más cercana con otro límite, a menos que ese otro límite golpee primero un límite de "agujero".
fuente
Respuestas:
Esto podría ser posible usando rásteres. Primero convierta sus puntos y polígonos de límite en un ráster de alta resolución. Establezca una máscara para sus límites usando
r.mask
. Luego, correr.grow.distance
en GRASS y usa elValue= output
. Esto te dará por cada píxel, que es el punto más cercano. Convierta esto nuevamente en polígonos vectoriales. Es posible que se necesiten pasos adicionales para deshacerse de los polígonos de astilla.fuente
Esto es ciertamente posible con rásteres.
Con suerte, esta captura de pantalla muestra el problema más claramente. La parte B del voronoi está más cerca 'mientras el cuervo vuela' al centro original del voronoi, pero esto no tiene en cuenta el hecho de que tomaría más tiempo caminar por el edificio. Entiendo que la pregunta del OP es que el voronoi debe tener en cuenta esta distancia adicional para caminar por el edificio.
Me gusta la sugerencia de @Guillaume. Sin embargo, cuando lo probé tuve problemas
r.grow.distance
para honrar la máscara (ver más abajo. Las ondas no deberían pasar por los edificios).Mi conocimiento de Grass no es tan fuerte como podría ser, así que tal vez estoy haciendo algo estúpido. Definitivamente, primero revisa esa sugerencia ya que será mucho menos trabajo que la mía ;-)
Paso 1: crear una superficie de costo
El primer paso es crear una superficie de costo. Esto solo debe hacerse una vez.
use la calculadora ráster para convertir esto en una superficie de costo. Estableceré 'afuera' en 1 y 'adentro' en 9999. Esto hará que moverse por los edificios sea extremadamente difícil.
(("máscara @ 1" = 1) * 1) + (("máscara @ 1" = 0) * 9999)
Puede obtener resultados más 'orgánicos' agregando un poco de ruido a la superficie de costo (por ejemplo, use un número aleatorio del 1 al 3, en lugar de solo 1 para pxiels al aire libre).
Paso 2. Crear rásteres de costos acumulativos para cada centro voronoi
Ahora podemos ejecutar (para una celda voronoi a la vez) el algoritmo GRASS
r.cost.coordinates
contra nuestra capa de superficie de costo.Para la coordenada de inicio, use el centro vornoi. Para la coordenada final, elija una de las esquinas de su área. Sugiero usar 'Knights Tour' ya que esto da resultados más suaves.
El resultado muestra líneas de igual tiempo de viaje desde un centro voronoi. Tenga en cuenta cómo las bandas se envuelven alrededor de los edificios.
No estoy seguro de la mejor manera de automatizar esto. Tal vez el modo de procesamiento por lotes, o hecho en pyqgis.
Paso 3. Combina los rásteres
Esto probablemente necesitará código. El algoritmo sería
Ese enfoque debería generar un ráster donde cada celda está categorizada por el centro voronoi más cercano, teniendo en cuenta los obstáculos.
Entonces podría usar raster-to-polygon. A continuación, puede usar el complemento Generalizar para eliminar los artefactos de efecto "paso" del ráster.
Disculpas por la vaguedad en los pasos 2 y 3 ... Espero que alguien intervenga con una solución más elegante :)
fuente
Nota # 1 : No pude reproducir el problema propuesto porque la herramienta Diferencia funcionó bien para mí en varias pruebas que realicé (tal vez se debió a la geometría simple del problema o porque la herramienta se ha mejorado desde que la pregunta fue preguntado hace 1 año).
Sin embargo, propongo una solución alternativa en PyQGIS para evitar el uso de la herramienta Diferencia . Todo se basa en la intersección local entre dos capas de entrada (ver figura a continuación):
Nota # 2 : Como no quiero usar la herramienta Diferencia , no puedo evitar la creación de "astillas" (ver entonces), así que necesitaba ejecutar la
v.clean
herramienta para eliminarlas. Además, como dijo @Chris W,Después de estas premisas necesarias, publico mi código:
lo que lleva a este resultado:
Solo por claridad, este sería el resultado sin el uso de la
v.clean
herramienta:La diferencia con el resultado de @LeaningCactus es que, por ahora, las geometrías no están rotas y podrían "limpiarse" sin errores .
fuente