PostGIS: ST_Buffer satu sisi dari linestring menghasilkan keluaran yang aneh
Dalam contoh di bawah ini saya memiliki tabel PostGIS linestring (dalam warna hitam dan kuning) dan poligon keluaran ST_Buffer satu sisi (berwarna merah). Jarak buffer didasarkan pada nilai atribut yang disimpan dalam tabel linestring.
Seperti yang Anda lihat salah satu buffer tidak benar, dan memotong sebagian dari dirinya sendiri untuk jumlah tertentu. Mengapa ini terjadi? Apakah bisa diperbaiki? Tampaknya menjadi masalah di mana bagian linestring menjadi cekung.

Coba ini sendiri menggunakan kueri serupa:
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')
Dalam contoh lain saya melihat ini terjadi (garis hitam adalah fitur 1, seperti poligon penyangga):

Dan coba yang ini dengan ini:
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')
Tingkatkan jarak penyangga untuk hasil yang lebih asing. EPSG: 27700 dalam kedua kasus.
Jawaban
Ini disebabkan oleh kekurangan dalam algoritme buffer satu sisi (bukan bug, ini adalah batasan desain algoritme).
Ini dicatat sebagai masalah GEOS . Belum ada ETA untuk perbaikan.
Saya telah membuat pipeline solusi yang memperbaiki masalah ini. Ini memang melibatkan pembuatan beberapa tabel perantara sementara di sepanjang jalan, tetapi Anda dapat menghapusnya dengan cepat.
- Buffer baris Anda menggunakan
ST_BUFFER
normal, Anda tidak akan memiliki output yang kacau. (mis. Jangan gunakan'side=left/right'
parameter). - Gunakan
ST_Split
untuk membagi buffer dari langkah 1 menjadi dua di sepanjang tengah menggunakan garis.ST_UNION
garis dengan garis penghubung yang berdekatan! ini akan memastikan garis pemotongan melewati dan melewati penyangga. Itu tidak akan memotong apapun. - Buffer baris Anda lagi tetapi kali ini hanya buffer satu sisi. Ini pasti sisi yang tidak Anda inginkan.
- Buat tabel titik menggunakan
ST_PointOnSurface
untuk setiap bentuk penyangga sisi yang 'salah'. - Gunakan tabel titik baru ini untuk menghapus poligon dari penyangga poligon terpisah (dari langkah 2) yang ditemukan memotong titik-titik.
- Sekarang Anda akan mendapatkan bentuk buffer penuh dengan sisi yang 'salah' dihilangkan. yaitu. Anda ditinggalkan dengan sisi yang benar yang diinginkan.
Saya telah menyimpulkan ini secara besar-besaran dan berasumsi untuk setiap segmen garis Anda memiliki garis penghubung yang berdekatan untuk membantu pemotongan. Saya juga melakukan ini untuk garis pantai dengan 1000 segmen. Jadi saya menggunakan tabel host untuk memasukkan setiap iterasi dari langkah-langkah di atas. Untuk mengulang melalui setiap segmen garis saya memastikan tabel garis memiliki kolom id auto-incrementing (jadi untuk setiap segmen garis saya bisa menggabungkannya dengan segmen sebelum dan sesudahnya: yaitu. N-1, n, n + 1). Saya akan segera memperbarui jawaban ini untuk memperjelas lebih lanjut.