Her iki çokgeninizin farklı düğüm kümeleri (yeşil poligon A, kırmızı poligon B bölümleri) nedeniyle biraz zor olduğunu düşünüyorum. Her iki poligonun segmentlerinin karşılaştırılması, poligon B segmentlerinin değiştirileceği hakkında bir ipucu verir.
Çokgen A düğümleri
"Farklı" segmentlerin düğümleri çokgen B
Ne yazık ki bu sadece segment yapısındaki farkı gösterir, ancak umarım bir başlangıç noktasıdır ve şöyle çalışır:
Bir indirme ve unzip işleminden sonra komutları ile Debian Linux Jessie altında PostgrSQL 9.46, PostGIS 2.1 kullanarak veri kümesini içe aktardım.
$ 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
Çokgen A segmentlerinin B ve yardımcı verada olmadığını varsayarsak, her iki poligon setinin segmentleri arasındaki farkı oluşturmaya çalışarak, her gruptaki (A veya B) çokgenlere segment üyeliğini ihmal ederim. Didaktik nedenlerden ötürü, SQL öğelerini çeşitli görünümlerde formüle ederim.
Bu GIS-SE yazısına karşılık olarak , her iki poligonu da segment tablolarına ayırıyorum segments_a
vesegments_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;
Segment tablosu çokgen 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
Poligon B'ye aynı prosedür uygulandı.
-- 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;
Segment tablosu çokgen 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)
...
Adlı bir fark tablosu görünümü oluşturabilirim segments_diff_{a,b}
. Fark, A ve B segment kümesinde sıralı başlangıç veya bitiş noktalarının oluşmamasıyla verilir.
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;
Ve tamamlayıcı şeyler:
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;
Sonuç: Kırmızı okla işaretlediğiniz küçük küçük segmentler için uygun bir sonuç elde etmek için, her iki poligonun da düğüm yapısına sahip olması ve düğüm seviyesinde bir kesişim aşaması olması gerekir (B'de çokgen A'nın tepe noktalarının eklenmesi). Kavşak şu şekilde yapılabilir:
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;
Ama garip sonuçlarla ...