PostGIS: ST_Buffer de un solo lado de la cadena de líneas produce una salida extraña

Aug 18 2020

En el siguiente ejemplo, tengo una tabla PostGIS de cadena de líneas (en negro y amarillo) y un polígono de salida ST_Buffer de un solo lado (en rojo). La distancia de la zona de influencia se basa en un valor de atributo almacenado en la tabla de cadenas de líneas.

Como puede ver, uno de los búferes es incorrecto y corta una sección de sí mismo por una cierta cantidad. ¿Por qué ha sucedido esto? ¿Se puede arreglar? Parece ser un problema donde la sección de la cadena de líneas se vuelve cóncava.

Pruebe esto usted mismo usando una consulta similar:

SELECT ST_BUFFER('LineString (638327 331059, 638337 331048, 638337 331037, 638343 331023, 638358 331014, 638380 330991, 638382 330978, 638391 330966, 638410 330959, 638420 330953)',50,'side=right')

En otro ejemplo, veo que esto sucede (la línea negra es una característica, al igual que el polígono de búfer):

Y prueba este con esto:

SELECT ST_BUFFER('LineString (600296 172961, 600304 172962, 600307 172965, 600307 172969, 600307 172971, 600309 172974, 600308 172976, 600307 172979, 600306 172981, 600307 172982, 600311 172980, 600313 172979, 600317 172979, 600321 172982, 600325 172982, 600327 172979, 600328 172976, 600331 172974, 600338 172974)',10,'side=right')

Aumente las distancias del búfer para obtener resultados extraños. EPSG: 27700 en ambos casos.

Respuestas

7 dr_jts Aug 18 2020 at 05:53

Estos son causados ​​por deficiencias en el algoritmo de búfer de un solo lado (no errores, son limitaciones conocidas del diseño del algoritmo).

Esto se registra como un problema de GEOS . Sin embargo, todavía no hay ETA para una solución.

TheoF Aug 20 2020 at 01:04

Creé una canalización de solución alternativa que soluciona este problema. Implica la creación de algunas tablas intermedias temporales a lo largo del camino, pero puede eliminarlas sobre la marcha.

  1. Almacene su línea usando ST_BUFFERnormalmente, no tendrá una salida caótica. (es decir, no utilice el 'side=left/right'parámetro).
  2. Use ST_Splitpara dividir el búfer del paso 1 por la mitad a lo largo del centro usando la línea. ST_UNIONla línea con líneas de conexión adyacentes! esto asegurará que la línea de corte se extienda a través y más allá del búfer. De lo contrario, no cortará nada.
  3. Almacene su línea nuevamente, pero esta vez solo un lado. Este debe ser el lado que no quieres.
  4. Cree una tabla de puntos usando ST_PointOnSurfacepara cada forma de búfer del lado "incorrecto".
  5. Utilice esta nueva tabla de puntos para eliminar los polígonos de la zona de influencia del polígono dividido (del paso 2) que se encuentra en la intersección de los puntos.
  6. Ahora le queda la forma de búfer completa con el lado "incorrecto" eliminado. es decir. se queda con el lado correcto deseado.

He resumido esto masivamente y asumí que para cada segmento de línea tiene una línea de conexión adyacente para ayudar con el corte. También hice esto para una costa con miles de segmentos. Entonces usé una tabla de host para insertar cada iteración de los pasos anteriores en. Para recorrer cada segmento de línea, me aseguré de que la tabla de línea tuviera una columna de identificación de incremento automático (por lo que para cada segmento de línea podría fusionarlo con el segmento anterior y posterior: es decir, n-1, n, n + 1). Actualizaré esta respuesta pronto para aclarar más.