Tôi nghĩ rằng nó là một chút khó khăn, bởi vì các tập hợp nút khác nhau của cả hai đa giác của bạn (đa giác màu xanh lá cây A, các phân đoạn đa giác B màu đỏ khác nhau). So sánh các phân đoạn của cả hai đa giác cho một manh mối mà các phân đoạn của đa giác B sẽ được sửa đổi.
Nút đa giác A
Các nút của đa giác phân đoạn "khác nhau"
Thật không may, điều này chỉ cho thấy sự khác biệt trong cấu trúc phân khúc, nhưng tôi hy vọng nó là điểm khởi đầu và nó hoạt động như thế này:
Sau quá trình tải xuống và giải nén, tôi đã nhập bộ dữ liệu bằng PostgrSQL 9.46, PostGIS 2.1 trong Debian Linux Jessie với các lệnh.
$ 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
Giả sử rằng các phân đoạn của đa giác A không nằm trong B và ngược lại, tôi cố gắng xây dựng sự khác biệt giữa các phân đoạn của cả hai tập hợp đa giác, bỏ qua tư cách thành viên phân đoạn cho đa giác trong mỗi nhóm (A hoặc B). Vì các lý do mô phạm, tôi xây dựng các công cụ SQL trong một số khung nhìn.
Tương ứng với bài viết về GIS-SE này , tôi phân tách cả hai đa giác thành các bảng phân đoạn segments_a
vàsegments_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;
Bảng phân đoạn đa giác 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
Quy trình tương tự đã được áp dụng cho đa giác 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;
Bảng phân đoạn đa giác 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)
...
Tôi có thể xây dựng một khung nhìn bảng khác biệt được đặt tên segments_diff_{a,b}
. Sự khác biệt được đưa ra bởi sự không xuất hiện của điểm bắt đầu hoặc điểm kết thúc được sắp xếp trong phân đoạn A và 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;
Và các công cụ bổ sung:
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;
Kết luận: Để có được kết quả phù hợp cho các phân đoạn nhỏ mà bạn đã đánh dấu bằng mũi tên màu đỏ, cả hai đa giác phải có cùng cấu trúc nút và bước giao nhau trên cấp độ nút (chèn đỉnh của đa giác A trong B) là bắt buộc. Giao lộ có thể được thực hiện bởi:
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;
Nhưng với kết quả kỳ lạ ...