Buat mosaik seperti Voronoi Diagram dari poligon disjoint

12

Ilustrasi di bawah ini menunjukkan masalahnya :

masukkan deskripsi gambar di sini

seperti pada (a) Saya punya satu set poligon terpisah, seperti geometri di PostGIS. Saya memerlukan sesuatu seperti (b) , "mosaik" dari rangkaian poligon ini, membangunnya dengan kriteria "wilayah pengaruh" ... Seperti konstruksi Voronoi (diilustrasikan oleh (c) ): pada kenyataannya, jika poligon itu adalah Poin, pengaruh daerah adalah Voronoi.

Meringkas: Saya membutuhkan algoritma SQL (atau spesifik untuk PostGIS) yang menghasilkan "mosaik" dari serangkaian poligon terpisah. (mungkin loop operasi ST_Buffer kecil dan ST_Difference)

PS: Saya perlu, seperti Voronoi, bahwa pembatasan ruang (bingkai kuadrat dalam (b) ) diabaikan.


Masalah ini mirip dengan ini tentang garis lainnya .

EDIT (setelah komentar @FelixIP)

Saya lebih suka tinggal di alam semesta vektor , untuk tidak kehilangan presisi (mis. Menggunakan ST_DelaunayTriangles dan menambah dan mengurangi interior dengan poligon asli, mereka mengadaptasi solusi grafik ganda ) ... Beberapa paket sederhana dan otomatis seperti pprepair (dibantu seperti alat topologi QGIS tidak otomatis). Tetapi raster mungkin lebih sederhana dan lebih sedikit memakan CPU.

Ilustrasi "proses GRID" ini juga berlaku sebagai solusi, dengan asumsi bahwa hal itu dapat memungkinkan ketepatan yang sama dan "pertumbuhan pengaruh wilayah euclidean".

masukkan deskripsi gambar di sini

Dalam ARCGIS terdapat alat analisis spasial yang dikenal sebagai Alokasi Euclidean , jadi, mungkin ada solusi serupa PostGIS , dimulai dengan set poligon (mengklasifikasikan, merasterisasi dan membuat kembali poligon).

Peter Krauss
sumber
Terima kasih @Nir, maaf kebingungan dengan poin, saya tidak menggunakan poin, hanya poligon sebagai item (a) dan (b) dari ilustrasi ... Apakah Anda memiliki tautan petunjuk Anda tentang solusi?
Peter Krauss
Dalam arcgis ada solusi raster yang disebut alokasi eucledean atau kedekatan
FelixIP
Terima kasih @FelixIP, saya diedit ke "solusi well raster" ;-)
Peter Krauss
Jika Anda menghapus poligon dari jangkauannya .aspolygon, Anda akan dibiarkan dengan poligon. Kerangka itu gis.stackexchange.com/questions/177/… adalah apa yang Anda butuhkan saya kira. Implementasinya adalah masalah besar
FelixIP
1
@Cyril, saya dapat meninjau skrip Anda ... Minggu depan. Posting sesuatu yang tampaknya merupakan solusi dengan fungsi PostGIS modern, akan menjadi langkah pertama yang baik.
Peter Krauss

Jawaban:

1

Jadi, saya akan menyiapkan kue untuk Anda - piring buah, menggunakan alat PostGis, seperti yang Anda minta, jika saya benar memahami pertanyaan itu, dan seperti yang saya sebutkan, tanggung jawab untuk pengoperasian oven PostGIS ditanggung oleh tim kreatifnya.

Saya akan meminta untuk tidak tersinggung oleh siapa pun dengan gaya lucu saya dan memahaminya sebagai permainan!

File aslinya adalah irisan buah dan bentuk sederhana (selanjutnya disebut buah), lihat Gambar 1 di bawah ini.

masukkan deskripsi gambar di sini

Ini resep saya, dan saya akan dibantu oleh programmer-programmer terkasih, yang akan Anda pelajari nanti. Mari kita mulai, dan untuk ini kita akan membuat adonan di mana buah-buahan kita akan diletakkan, untuk yang menjalankan skrip:

create table poly_extent as SELECT ST_SetSRID(ST_Buffer(ST_Envelope(ST_Extent(geom)),0.05),4326) as geom FROM poly;

Lihat hasilnya pada Gambar 2 di bawah ini

masukkan deskripsi gambar di sini

Sekarang, jika ada beberapa buah, seperti dalam gambar saya, buat batas buffer eksternal pada buah, atau jika ada banyak buah, buat perbatasan buffer negatif, untuk yang menjalankan skrip:

create table poly_buff_dump as SELECT ((ST_Dump(ST_Boundary(ST_Union(ST_Buffer((geom),0.01, 'join=mitre mitre_limit=5.0'))))).geom) geom FROM poly;

Dan iris garis penyangga di sekitar masing-masing buah

UPDATE poly_buff_dump SET geom=ST_RemovePoint(geom, ST_NPoints(geom)-1) WHERE ST_IsClosed(geom)=true; Lihat hasilnya pada Gambar 3 di bawah ini

masukkan deskripsi gambar di sini

(Sebenarnya, saya berpikir bahwa sebagai hasilnya saya akan mendapatkan garis putus-putus (seperti dalam lingkaran), tetapi jika angka-angka itu sulit, kadang-kadang angka diperoleh, yang salah, misalnya, satu sisi persegi panjang jatuh, dll. )

Maka Anda perlu membagi garis yang diperoleh dengan cara yang nyaman bagi Anda menjadi segmen yang sama dan mengekstrak poin dari mereka

create table poly_buff_dump_pt as SELECT (ST_DumpPoints((geom))).geom geom FROM poly_buff_segm;

Hasilnya, lihat Gambar 4 di bawah ini

masukkan deskripsi gambar di sini

Sekarang jalankan alat Voronoi, di tempat ini saya menggunakan alat yang disarankan oleh tautan MickyT: /gis//a/172246/120129 , sebagai hasilnya Anda akan membuat tabel dengan nama “voronoi ”Untuk fakta bahwa“ asisten pertamaku ”terpisah dari koki, terima kasih dari koki! :-).

Cara kedua dalam langkah ini adalah menjalankan fungsi ST_VoronoiPolygons.

Hasilnya, lihat Gambar 5 di bawah ini

masukkan deskripsi gambar di sini

Sekarang, potong bagian tambahan dengan menjalankan skrip:

create table poly_voronoi_cut as SELECT ST_Intersection(a.geom, b.geom) geom FROM voronoi a INNER JOIN poly_extent b ON ST_Intersects(a.geom, b.geom); Hasilnya, lihat Gambar 6 di bawah ini.

masukkan deskripsi gambar di sini

Sekarang jalankan skrip untuk menyelaraskan tipe geodata di LineString:

create table poly_voronoi_dump as SELECT (ST_Dump(geom)).geom as geom FROM poly_voronoi_cut; Dan sekarang saya akan meminta "teman kedua saya" untuk mengambil tugas saya dan mencampur kue dengan baik (Jeff - /gis//a/785/120129 ), meratakannya dalam satu lapisan, dan untuk itu terima kasih untuk itu!

CREATE TABLE poly_overlay_cut AS SELECT geom FROM ST_Dump(( SELECT ST_Polygonize(geom) AS geom FROM ( SELECT ST_Union(geom) AS geom FROM ( SELECT ST_ExteriorRing(geom) AS geom FROM poly_voronoi_dump) AS lines ) AS noded_lines ) ); Sekarang saatnya bagi saya untuk mulai bekerja, di mana saya menjalankan skrip:

create table poly_voronoi_union as SELECT b.id, (ST_ConvexHull(ST_Union(a.geom, b.geom))) geom FROM poly_overlay_cut a INNER JOIN poly_buff_dump b ON ST_Intersects(a.geom, b.geom) GROUP BY b.id, a.geom, b.geom; dan skrip lain:

create table poly_voronoi_union_area as SELECT ST_Union(ST_ConvexHull(ST_BuildArea(geom))) as geom FROM poly_voronoi_union GROUP BY id; lihat gambar 7 di bawah ini

masukkan deskripsi gambar di sini

Seperti yang Anda lihat dalam gambar, potongan kami memiliki lapisan kecil, yang dapat dihapus, sebagai opsi menggunakan ST_SnapToGrid (atau dengan cara lain):

Dan akhirnya, kita akan memotong buah panggang kita dari pai kita, aku bahkan sedikit lelah berdiri di dekat oven, :-)

create table polygon_voronoi_result as SELECT (ST_Dump(ST_Difference(a.geom, b.geom))).geom as geom FROM poly_voronoi_union_area_snap as a JOIN poly b ON ST_Intersects(a.geom, b.geom); Hasilnya lihat gambar 8 masukkan deskripsi gambar di sini

Semuanya mulai hari ini, sekarang semua orang akan belajar memanggang pai lezat - piring buah. Bantu dirimu Semua, dan pilih bagianmu, cukup untuk semua orang.

(Sayang sekali saya benar-benar tidak bisa memberi makan semua orang, tidak dengan kue elektronik, tetapi dengan kue asli, mungkin kelaparan akan berakhir di Bumi ...)

Sunting: Ceri pada pai bisa terlihat seperti ini :-):

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM poly),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT ST_Intersection(a.geom, b.geom) geom FROM tblb a JOIN poly_extent b ON ST_Intersects(a.geom,b.geom)),
tbld AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM poly GROUP BY id, geom)
SELECT id, ST_Union(a.geom) as geom FROM tblc a JOIN tbld b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

atau

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM polygons),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM polygons GROUP BY id, geom)
SELECT id, ST_Union(a.geom) geom FROM tblb a JOIN tblc b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

Dengan Anda baik dan adil Mr.Baker, terima kasih semua dan semoga sukses,: -) ...

Solusi asli.

Script ini disebut: ST_VoronoiDiagramsFromPolygons.

Cyril Mikhalchenko
sumber
1
Hai, ilustrasi yang bagus, dan sepertinya hasil yang bagus (!). Saran untuk diskusi singkat, lihat solusi @geogeek, langkah-langkah dalam QG tampaknya langkah utama PostGIS di sini ... Mengapa Anda perlu ST_Bufferdan ST_ConvexHull? Ada algoritma alternatif?
Peter Krauss
1) Lihat, ST_Buffer dan poligon dibuat untuk mengurangi garis pemisah antara angka asli selama penerapan fungsi Voronoi, oleh karena itu, semakin besar ukuran buffer yang dapat Anda tentukan, semakin halus garis pemisah akan dibangun sebagai fungsi Voronoi ... 2) ST_ConvexHull dari banyaknya angka pada setiap poligon, poligon yang kita butuhkan ... 3) Hari ini, ini adalah visi saya untuk menyelesaikan pertanyaan Anda, saya tidak tahu apa yang akan terjadi pada kita semua dan keputusan kita di masa depan ...
Cyril Mikhalchenko
Nilai penting lainnya dari garis penyangga adalah bahwa mereka akan membantu kami memilih fragmen dari hasil fungsi Voronoi untuk membuat poligon gabungan untuk setiap bentuk ...
Cyril Mikhalchenko
Omong-omong, saya menyambut perbaikan kode dan pendekatan, sehingga mereka tidak memperburuk hasilnya ...
Cyril Mikhalchenko
1
Halo Cyril, saya setuju bahwa ST_Buffer adalah pilihan yang baik untuk menormalkan garis kontur, sempurna (!). Soal ST_ConvexHull, hanya rasa ingin tahu, hasil apa yang bisa kita peroleh setelah Gambar 6, poly_voronoi_uniontanpa ST_ConvexHull.
Peter Krauss
8

Postgis tidak memiliki fungsi khusus untuk voronoi, tetapi Qgis berisi fungsi vornoi yang dapat membuat poligon voronoi dari poin, jadi menggunakan qgis saya telah mengikuti langkah-langkah berikut untuk mendapatkan hasil ini:

-membuat poin dari poligon menggunakan extract nodesfungsi.

-membuat poligon vornoi menggunakan fungsi voroi di Qgis.

-membuat gabungan spasial di Qgis.

Hasil -dolve.

masukkan deskripsi gambar di sini

geogeek
sumber
1
Solusi yang bagus (!), Dan terima kasih ilustrasinya. Bisakah Anda meningkatkannya? Lihat persegi panjang kiri di bawah, itu 4 poin di Voronoi, dan pusat persegi panjang tidak memiliki representasi, mendistorsi wilayahnya (kehilangan adalah ke segitiga) ... Mungkin meningkatkan dimungkinkan melakukan pengambilan sampel reguler setiap poligon ... dan mungkin juga beberapa poin interior.
Peter Krauss
Saya menggunakan alat densify di ArcGIS. Ini secara signifikan meningkatkan poligon kedekatan. +1
FelixIP
3

OK - Pikirkan tentang ini sedikit dan menemukan itu seperti sesuatu yang saya lihat belakangan ini.

Ambil polis awal Anda:

masukkan deskripsi gambar di sini

Hasilkan atribut baru dengan angka (100 dalam kasus saya) Gunakan alat Vector-> Research -> Poin acak di dalam alat poligon ini akan menghasilkan (100) poin di dalam setiap poligon: masukkan deskripsi gambar di sini

Kemudian Vector-> Geometry tools -> Voronoi untuk menghasilkan polys berdasarkan pada layer titik tersebut.

masukkan deskripsi gambar di sini

Sekarang, Anda dapat menggunakan alat Vektor -> Kueri Spasial: Pilih titik-titik yang dimiliki oleh satu poligon (atau salah satu poligon) Gunakan alat kueri spasial untuk menghasilkan pilihan poligon voronoi Anda yang berlaku untuk poligon itu. Tambahkan atribut ke poligon voroni yang sesuai dengan poligon yang menarik. (Saya hanya menggunakan 1,2,3,4)

Sekarang Anda dapat Vector-> Geoprocessing Tools-> larut berdasarkan atribut baru Anda.

masukkan deskripsi gambar di sini

A A
sumber
Terima kasih @Ames (!), Ilustrasinya bagus, dan metode ini merupakan alternatif yang baik ... Tetapi pertanyaannya adalah tentang "algoritma SQL (atau spesifik untuk PostGIS)" dan sekarang, karunia tentang penggunaan fungsi ST_VoronoiPolygons () , yang mungkin menyelesaikan semua masalah dalam satu klik ;-)
Peter Krauss
@AAmes Pencarian cepat mengungkapkan bahwa metode ini memang dapat digunakan di PostGIS juga. Cara membuat titik acak dalam poligon di postgis menjelaskan pembuatan titik dari poligon dan dari sana harus cukup lurus ke depan.
Phil G
Karunia saya adalah untuk Anda, sebagai insentif (selamat datang di sini!), Tetapi JAWABAN INI BERLAKU untuk pertanyaan dan persyaratan hadiah.
Peter Krauss
Terima kasih Peter, saya melihat catatan Anda tetapi sayangnya saya belum memiliki kesempatan untuk kembali dan mengatasinya. Saya belum memiliki pengalaman apa pun di PostGIS dan butuh lebih banyak waktu daripada yang saya miliki untuk memberikan tanggapan yang baik. Saya harap eksplorasi ruang ini bermanfaat bagi orang-orang di masa depan, mungkin. Jika saya mendapatkan celah di PostGIS segera saya akan kembali dan mengambil pukulan lain untuk latihan!
AA
2

Poin acak adalah ide yang baik untuk menghasilkan poligon voronoi dari poligon, itu bekerja dengan cukup baik, tetapi cukup buruk untuk poligon yang berdekatan: masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

ST_ApproximateMedialAxis adalah alternatif lain yang baik jika menggunakan PostGIS: Menghitung Diagram Voronoi untuk poligon

Leo
sumber