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.
$ createdb gis-se
$ psql gis-se < /usr/share/postgis-2.1/postgis.sql
$ psql gis-se < /usr/share/postgis-2.1/spatial_ref_sys.sql
$ shp2pgsql -S polygon_a | psql gis-se
$ shp2pgsql -S polygon_b | psql gis-se
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
-- Segments of the polygon A
CREATE VIEW segments_a AS SELECT sp, ep
FROM
-- extract the endpoints for every 2-point line segment for each linestring
(SELECT
ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,
ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep
FROM
-- extract the individual linestrings
(SELECT (ST_Dump(ST_Boundary(geom))).geom
FROM polygon_a
) AS linestrings
-- be sure that nothing is scrambled
ORDER BY sp, ep
) AS segments;
Tabel segmen poligon A:
SELECT
st_astext(sp) AS sp,
st_astext(ep) AS ep
FROM segments_a
LIMIT 3;
sp | ep
-------------------------------------------+--------------------------------------------
POINT(-292.268907321861 95.0342877387557) | POINT(-287.118411917425 99.4165242769195)
POINT(-287.118411917425 99.4165242769195) | POINT(-264.62129248575 93.2470010145007)
POINT(-277.459563916327 -44.5629543976138) | POINT(-292.268907321861 95.03428773875
Prosedur yang sama diterapkan pada poligon B.
-- Segments of the polygon B
CREATE VIEW segments_b AS SELECT sp, ep
FROM
-- extract the endpoints for every 2-point line segment for each linestring
(SELECT
ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,
ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep
FROM
-- extract the individual linestrings
(SELECT (ST_Dump(ST_Boundary(geom))).geom
FROM polygon_b
) AS linestrings
-- be sure that nothing is scrambled
ORDER BY sp, ep
) AS segments;
Tabel segmen poligon B
SELECT
st_astext(sp) AS sp,
st_astext(ep) AS ep
FROM segments_b
LIMIT 3;
sp | ep
-------------------------------------------+-------------------------------------------
POINT(-292.268907321861 95.0342877387557) | POINT(-287.118411917425 99.4165242769195)
POINT(-287.118411917425 99.4165242769195) | POINT(-264.62129248575 93.2470010145007)
POINT(-277.459563916327 -44.5629543976138) | POINT(-292.268907321861 95.0342877387557)
...
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.
CREATE VIEW segments_diff_a AS
SELECT st_makeline(b.sp, b.ep) as geom
FROM segments_b as b
LEFT JOIN segments_a as a ON (a.sp=b.sp and a.ep = b.ep)
-- filter segments without corresponding stuff in polygon A
WHERE a.sp IS NULL;
Dan hal-hal yang saling melengkapi:
CREATE VIEW segments_diff_b AS
SELECT st_makeline(a.sp, a.ep) as geom
FROM segments_a as a
LEFT JOIN segments_b as b ON (a.sp=b.sp and a.ep = b.ep)
-- filter segments without corresponding stuff in polygon B
WHERE b.sp IS NULL;
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:
CREATE VIEW segments_bi AS
SELECT distinct sp, ep
FROM (
SELECT
ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as sp,
ST_PointN(geom, generate_series(2, ST_NPoints(geom) )) as ep
FROM (
SELECT st_difference(b.seg, a.seg) as geom FROM
segments_diff_a as a, segments_diff_b as b
WHERE st_intersects(a.seg, b.seg)
) as cut
) as segments
WHERE sp IS NOT NULL AND ep IS NOT NULL
ORDER BY sp, ep;
Tetapi dengan hasil yang aneh ...