Saya punya tabel PostGIS polygon_b
dengan beberapa fitur poligon. Ada juga tabel polygon_a
yang berisi poligon yang sama polygon_b
tetapi dengan perubahan kecil. Sekarang saya ingin membuat garis untuk memvisualisasikan perbedaan antara fitur poligon.
Saya kira itu ST_ExteriorRing
dan ST_Difference
akan melakukan pekerjaan tetapi klausa WHERE tampaknya cukup rumit.
CREATE VIEW line_difference AS SELECT
row_number() over() AS gid,
g.geom::geometry(LineString, yourSRID) AS geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(ST_ExteriorRing(polygon_a.geom), ST_ExteriorRing(polygon_b.geom))))).geom AS geom
FROM polygon_a, polygon_b
WHERE
-- ?
) AS g;
Ada yang bisa bantu saya?
EDIT 1
Seperti yang diposting oleh 'tilt' Saya sudah mencoba ST_Overlaps(polygon_a.geom, polygon_b.geom) AND NOT ST_Touches(polygon_a.geom, polygon_b.geom)
tetapi hasilnya tidak seperti yang diharapkan.
CREATE VIEW line_difference AS SELECT
row_number() over() AS gid,
g.geom::geometry(LineString, your_SRID) AS geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(ST_ExteriorRing(polygon_a.geom), ST_ExteriorRing(polygon_b.geom))))).geom AS geom
FROM polygon_a, polygon_b
WHERE
ST_Overlaps(polygon_a.geom, polygon_b.geom) AND NOT ST_Touches(polygon_a.geom, polygon_b.geom))
AS g;
EDIT 2
workupload.com/file/J0WBvRBb (contoh dataset)
Saya sudah mencoba mengubah poligon menjadi multilines sebelum menggunakan ST_Difference, tetapi hasilnya masih aneh.
CREATE VIEW multiline_a AS SELECT
row_number() over() as gid,
ST_Union(ST_ExteriorRIng(polygon_a.geom))::geometry(multilinestring, 4326) AS geom
FROM
polygon_a;
CREATE VIEW multiline_b AS SELECT
row_number() over() as gid,
ST_Union(ST_ExteriorRIng(polygon_b.geom))::geometry(multilinestring, 4326) AS geom
FROM
polygon_b;
CREATE VIEW line_difference AS SELECT
row_number() over() as gid,
g.geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(multiline_a.geom, multiline_b.geom)))).geom::geometry(linestring, 4326) AS geom
FROM
multiline_a, multiline_b)
As g;
sumber
Jawaban:
Berikut adalah beberapa trik baru, menggunakan:
EXCEPT
untuk menghapus geometri dari salah satu tabel yang sama, sehingga kami hanya dapat fokus pada geometri yang unik untuk setiap tabel (A_only
danB_only
).ST_Snap
untuk mendapatkan noding yang tepat untuk operator overlay.ST_SymDifference
operator overlay untuk menemukan perbedaan simetris antara dua set geometri untuk menunjukkan perbedaan. Pembaruan :ST_Difference
menunjukkan hasil yang sama untuk contoh ini. Anda dapat mencoba salah satu fungsi untuk melihat apa yang mereka dapatkan.Ini harus mendapatkan apa yang Anda harapkan:
Untuk membongkar jawaban ini sedikit lebih banyak, langkah pertama dengan
ST_Boundary
mendapatkan batas setiap poligon, bukan hanya bagian luar. Misalnya, jika ada lubang, ini akan dilacak oleh batas.The
EXCEPT
klausul digunakan untuk menghapus geometri dari A yang merupakan bagian dari B, dan baris dari B yang merupakan bagian dari A. Hal ini akan mengurangi jumlah baris yang merupakan bagian dari A saja, dan bagian dari B saja. Misalnya, untuk mendapatkan A_only:Berikut adalah 6 baris A_only, dan 3 baris B_only:
Lanjut,
ST_Union(DISTINCT A_only.geom)
digunakan untuk menggabungkan garis ke dalam geometri tunggal, biasanya MultiLineString.ST_Snap digunakan untuk mengambil node dari satu geometri ke geometri lainnya. Misalnya
ST_Snap(A, B, tol)
akan mengambil geometri A, dan menambahkan lebih banyak node dari geometri B, atau memindahkannya ke geometri B, jika berada dalamtol
jarak. Mungkin ada beberapa cara untuk menggunakan fungsi-fungsi ini, tetapi idenya adalah untuk mendapatkan koordinat dari setiap geometri yang tepat satu sama lain. Jadi dua geometri setelah memotret terlihat seperti ini:Dan untuk menunjukkan perbedaan, Anda dapat memilih untuk menggunakan salah satu
ST_SymDifference
atauST_Difference
. Keduanya menunjukkan hasil yang sama untuk contoh ini.sumber
Saya pikir ini sedikit rumit, karena set simpul yang berbeda dari kedua poligon Anda (poligon hijau A, segmen polon B yang berbeda merah). Membandingkan segmen dari kedua poligon memberikan petunjuk mana segmen poligon B yang akan dimodifikasi.
Node poligon A
Node dari segmen "berbeda" poligon B
Sayangnya ini hanya menunjukkan perbedaan dalam struktur segmen, tapi saya harap ini adalah titik awal dan berfungsi seperti ini:
Setelah proses unduh dan unzip, saya mengimpor set data menggunakan PostgrSQL 9.46, PostGIS 2.1 di bawah Debian Linux Jessie dengan perintah.
Dengan asumsi bahwa segmen poligon A tidak dalam B dan sebaliknya, saya mencoba untuk membangun perbedaan antara segmen dari kedua set poligon, mengabaikan keanggotaan segmen ke poligon di setiap kelompok (A atau B). Untuk alasan didaktik saya merumuskan hal-hal SQL dalam beberapa tampilan.
Sesuai dengan posting GIS-SE ini , saya menguraikan kedua poligon menjadi tabel segmen
segments_a
dansegments_b
Tabel segmen poligon A:
Prosedur yang sama diterapkan pada poligon B.
Tabel segmen poligon B
Saya dapat membangun tampilan tabel perbedaan bernama
segments_diff_{a,b}
. Perbedaan tersebut diberikan oleh tidak adanya titik awal atau titik akhir yang diurutkan dalam segmen set A dan B.Dan hal-hal yang saling melengkapi:
Kesimpulan: Untuk mendapatkan hasil yang tepat untuk segmen kecil kecil yang Anda tandai dengan panah merah, kedua poligon harus memiliki struktur simpul yang sama dan langkah persimpangan pada tingkat simpul (diperlukan pemasukan simpul dari poligon A dalam B). Persimpangan dapat dilakukan dengan:
Tetapi dengan hasil yang aneh ...
sumber
Melihat contoh, perubahan menyiratkan bahwa fitur dari tabel baru yang telah diubah akan selalu tumpang tindih fitur dari tabel lama. Karena itu Anda akan selesai dengan
Negasi pada sentuhan adalah karena fitur juga tumpang tindih jika perbatasan mereka berbagi lokasi simpul yang sama.
sumber