PostGIS: ST_Buffer a lato singolo della stringa di linea produce un output strano

Aug 18 2020

Nell'esempio seguente ho una tabella PostGIS a stringa lineare (in nero e giallo) e un poligono di output ST_Buffer a un lato (in rosso). La distanza del buffer si basa su un valore di attributo memorizzato nella tabella della stringa di linea.

Come puoi vedere uno dei buffer non è corretto e taglia una sezione di se stesso per una certa quantità di esso. Perché è successo? Può essere riparato? Sembra essere un problema in cui la sezione della stringa di linea diventa concava.

Prova tu stesso usando una query simile:

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')

In un altro esempio vedo che ciò accade (la linea nera è una caratteristica, così come il poligono del buffer):

E prova questo con questo:

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')

Aumenta le distanze del buffer per risultati più strani. EPSG: 27700 in entrambi i casi.

Risposte

7 dr_jts Aug 18 2020 at 05:53

Questi sono causati da carenze nell'algoritmo del buffer unilaterale (non bug, sono limitazioni note del design dell'algoritmo).

Questo viene registrato come problema GEOS . Nessun ETA per una soluzione ancora però.

TheoF Aug 20 2020 at 01:04

Ho creato una pipeline di soluzione alternativa che risolve questo problema. Comporta la creazione di alcune tabelle intermedie temporanee lungo il percorso, ma è possibile eliminarle al volo.

  1. Buffer la tua linea usando ST_BUFFERnormalmente, non avrai un output caotico. (es. Non utilizzare il 'side=left/right'parametro).
  2. Utilizzare ST_Splitper dividere il buffer dal passaggio 1 a metà lungo il centro utilizzando la linea. ST_UNIONla linea con linee di collegamento adiacenti! questo garantirà che la linea di taglio si estenda attraverso e oltre il buffer. Altrimenti non taglierà nulla.
  3. Buffer di nuovo la linea ma questa volta buffer solo un lato. Questo deve essere il lato che non vuoi.
  4. Creare una tabella dei punti utilizzando ST_PointOnSurfaceper ciascuna forma di buffer laterale "sbagliata".
  5. Utilizzare questa nuova tabella dei punti per eliminare tutti i poligoni dal buffer dei poligoni divisi (dal passaggio 2) trovati intersecando i punti.
  6. Ora ti rimane la forma del buffer completo con il lato "sbagliato" rimosso da esso. cioè. ti rimane il lato corretto desiderato.

L'ho riassunto in modo massiccio e ho assunto per ogni segmento di linea che hai una linea di collegamento adiacente per aiutare con il taglio. L'ho fatto anche per una costa con migliaia di segmenti. Quindi ho usato una tabella host per inserire ogni iterazione dei passaggi precedenti in. Per scorrere ogni segmento di linea mi sono assicurato che la tabella delle linee avesse una colonna id con incremento automatico (quindi per ogni segmento di linea potevo unirla con il segmento prima e dopo di esso: es. N-1, n, n + 1). Aggiornerò presto questa risposta per chiarire di più.