Mengidentifikasi poligon "panjang dan sempit" dengan PostGIS


10

Saya memiliki satu set poligon yang mewakili area yang luas, katakanlah lingkungan kota. Saya ingin mengidentifikasi area besar yang tumpang tindih di antara mereka.

Tapi ada masalah: kadang-kadang poligon ini akan tumpang tindih di sepanjang perimeter mereka (karena mereka digambar dengan sedikit presisi). Ini akan menghasilkan tumpang tindih yang panjang dan sempit yang tidak saya pedulikan.

Tetapi di lain waktu akan ada tumpang tindih besar poligon kuat, yang berarti area besar di mana poligon lingkungan saling tumpang tindih. Saya hanya ingin memilih ini.

Lihat gambar di bawah ini hanya tumpang tindih. Bayangkan saya hanya ingin memilih poligon biru di sudut kiri bawah.

tumpang tindih

Saya bisa melihat daerah, tetapi kadang-kadang yang sempit begitu lama mereka akhirnya memiliki area sebesar poligon biru. Saya sudah mencoba melakukan rasio area / perimeter, tetapi itu juga menghasilkan hasil yang beragam.

Saya bahkan sudah mencoba menggunakan ST_MinimumClearance, tetapi kadang-kadang area yang luas akan memiliki bagian sempit yang melekat padanya, atau dua simpul yang sangat dekat.

Adakah ide pendekatan lain?


Pada akhirnya apa yang paling berhasil bagi saya adalah menggunakan buffer negatif, seperti yang disarankan oleh @Cyril dan @FGreg di bawah ini.

Saya menggunakan sesuatu seperti:

ST_Area(ST_Buffer(geom, -10)) as neg_buffer_area

Dalam kasus saya, unit adalah meter, jadi 10 m buffer negatif.

Untuk poligon sempit, area ini mengembalikan nol (juga, geometri akan kosong). Lalu saya menggunakan kolom ini untuk menyaring poligon yang sempit.


4
Tentu saja rasio area / perimeter dapat digunakan untuk ini.
Vince

Sulit untuk mengetahui di mana poligon yang berbeda berasal dari gambar, tetapi melakukan sesuatu seperti gis.stackexchange.com/a/265233/64838 ini mungkin berhasil? Hitung kotak batas minimum diputar kemudian buang yang dengan lebar kecil atau tinggi.
FGreg

Anda juga dapat mencoba menggunakan buffer negatif seperti yang dijelaskan di sini: Bagaimana saya bisa mengidentifikasi poligon yang sangat tipis di file bentuk saya?
FGreg

Jawaban:


5

Saya akan mencoba membuat buffer negatif, jika ia makan poligon tipis, maka itu baik, jika tidak memakan poligon, maka itu adalah milikku ... :-)

jalankan skrip ini, setelah sebelumnya menetapkan 2/3 dari lebar poligon linier ...

create table name_table as
SELECT ST_Buffer(
(ST_Dump(
(ST_Union(
ST_Buffer(
(geom),-0.0001))))).geom,
0.0001)) as geom from source_table

OS: -) ...


pada akhirnya saran Anda adalah yang terbaik bagi saya. Saya akhirnya menggunakan sesuatu seperti ST_Area(ST_Buffer(geom, -10)), -10 yang -10 meter dalam kasus saya. Jika ada yang mengembalikan 0 dari ekspresi itu maka saya bisa memfilternya.
bplmp

9

Alih-alih area / perimeter, lebih baik menggunakan area yang dibagi dengan kuadrat perimeter (atau kebalikannya).

Ini juga disebut "indeks bentuk". Kuadrat perimeter dibagi dengan area memiliki nilai minimum 4 * Pi () (dalam kasus disk, yang merupakan geometri 2D paling kompak), sehingga dapat dinormalisasi dengan 4 * Pi () untuk memudahkan interpretasi (nilai dinormalisasi mendekati 1 maka berarti Anda memiliki objek yang sangat kompak dan kotak memiliki nilai sekitar 1,27).

EDIT: Ambang batas pada area akan berguna untuk menghapus artefak yang sangat kecil, yang bisa dipadatkan. Maka indeks bentuk akan menunjukkan kontras yang lebih baik. EDIT: selain jawaban ini, penggunaan ST_Snap dapat membantu Anda memecahkan masalah sebelum terjadi.


Terima kasih! Tapi saya tidak yakin bagaimana ST_Snap dapat membantu dalam kasus ini ... Jika saya benar, Anda menyarankan sesuatu seperti (o.overlap_perimeter^2 / o.overlap_area) / (4 * Pi()) as overlap_ratio? Ini memiliki hasil yang lebih buruk bagi saya daripada hanya area / perimeter.
bplmp

Sekarang menggunakan o.overlap_perimeter / (4 * sqrt(o.overlap_area)) as overlap_ratiomenurut makalah ini, tetapi hasilnya masih lebih buruk (meskipun itu sulit untuk mengukur apa yang saya maksud dengan lebih buruk) adalahprs-ann-photogramm-remote-sens-spatial-inf-sci.net/I-7/135/… , halaman 183.
bplmp

2
Terima kasih untuk ini, saya belum pernah mendengar "indeks bentuk". Saya selalu berpikir bahwa menggunakan persegi panjang batas minimum adalah cara terbaik untuk menjawab pertanyaan semacam ini. Saya menemukan ini, repository.asu.edu/attachments/111230/content/… , yang menarik.
John Powell

@JohnPowell memotong kertas, terima kasih. Saya melihat bahwa apa yang saya tahu sebagai indeks bentuk disebut indeks sirkularitas di kertas. Masalah saya dengan persegi panjang batas minimum adalah bahwa ia tidak bekerja dengan objek yang sangat cekung (misalnya berbentuk U)
radouxju

@bplmp ST_Snap akan membantu Anda mengambil simpul dari "hampir" poligon yang berdekatan sehingga mereka tidak tumpang tindih lagi. Tidak ada skala pada angka Anda, tetapi artefak Anda terlihat seperti garis, jadi saya kira Anda dapat menggunakan nilai toleransi theat cukup untuk menghindari artefak tetapi tidak mempengaruhi poligon besar.
radouxju

5

Salah satu opsi adalah menggunakan rasio luas poligon dengan garis terpanjang yang dapat ditarik menggunakan ekstremitasnya. Mengidentifikasi poligon sempit yang panjang.

select * from polygons where ST_Length(ST_LongestLine(geom, geom)) < ST_Area(geom) * 4

Ini bekerja cukup baik untuk poligon sliver. Anda dapat menyesuaikan rasio apa (apa yang Anda kalikan dengan daerah) sesuai dengan kebutuhan dan proyeksi Anda.


1

Kedengarannya seperti ini mungkin cocok dengan kasus penggunaan Anda: Hilangkan poligon yang dipilih

Menggabungkan poligon yang dipilih dari lapisan input dengan poligon yang berdekatan tertentu dengan menghapus batas umum mereka. Poligon yang berdekatan dapat menjadi salah satu yang memiliki area terbesar atau terkecil atau yang berbagi batas umum terbesar dengan poligon yang akan dihilangkan.

Eliminasi biasanya digunakan untuk menghilangkan sliver poligon, yaitu poligon kecil yang merupakan hasil dari proses persimpangan poligon di mana batas input sama tetapi tidak identik.

Sepertinya Anda ingin mencoba opsi "Batas Umum Terbesar".


Saya menyadari sekarang Anda meminta solusi postgis bukan solusi qgis. Saya minta maaf, saya tidak berpikir postgis memiliki fungsi yang setara tetapi saya akan meninggalkan ini untuk anak cucu.
FGreg

0

Bagi saya ini seperti kasus penggunaan yang sempurna untuk ekstensi topologi PostGIS . Parameter toleransi topologi akan menentukan seberapa jauh Anda membiarkan simpul untuk snap ke poligon lain yang ada, untuk mengatasi rendahnya presisi data sumber dan untuk membersihkannya.

Singkatnya, strateginya adalah:

1. Aktifkan ekstensi topologi

CREATE EXTENSION postgis_topology;

2. Buat topologi kosong baru

SELECT topology.CreateTopology('neighborhoods_topo', 4326, 1e-7);

Parameter ketiga adalah toleransi, dalam satuan CRS; pilihlah dengan bijak. Idealnya, Anda menginginkan CRS di mana unit adalah meter. Jika unit CRS bukan meter, seperti WGS 84 alias 4326, gunakan ST_Transformuntuk memproyeksikan ulang poligon Anda.

3. Tambahkan kolom TopoGeometry ke tabel poligon

SELECT topology.AddTopoGeometryColumn('neighborhoods_topo', 'public', 'neighborhoods', 'topogeom', 'POLYGON');

Ini mengembalikan yang baru layer_id. Simpan itu, itu akan dibutuhkan nanti. Ini akan menjadi layer 1jika Anda memulai dari awal, dan bertambah pada setiap panggilan baru.

4. Tambahkan semua poligon ke dalam topologi

UPDATE public.neighborhoods
SET topogeom = topology.toTopoGeom(geom, 'neighborhoods_topo', 1, 1e-7);

Ini bisa memakan waktu beberapa jam untuk dataset yang besar, bersabarlah. 1adalah layer_id yang dikembalikan sebelumnya.

5. Temukan wajah yang muncul di beberapa lingkungan

Temukan semua wajah dari topologi yang ada di 2 atau lebih topogeometri. Saya akan meninggalkan pertanyaan sebagai latihan. Mungkin yang paling mudah adalah dengan GetTopoGeomElementsfungsinya, lalu kelompokkan dengan id wajah, dan lihat yang dengan hitungan 2 atau lebih. Sebagai alternatif, Anda dapat membuat tabel baru dengan geometri yang dibersihkan dari kolom topogeom, cukup masukkan ke geometri standar topogeom::geometry, dan ulangi apa yang sudah Anda miliki sekarang, tetapi sekarang dengan dataset yang bersih tanpa tumpang tindih sliver.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.