我认为这有点棘手,因为两个多边形的节点集不同(绿色多边形A,红色多边形B的不同部分)。比较两个多边形的线段,可以得出多边形B的哪些线段将被修改的线索。
节点多边形A
“不同”分段多边形B的节点
不幸的是,这仅显示了段结构的差异,但是我希望这是一个起点,并且它的工作方式如下:
在完成下载和解压缩之后,我已经在Debian Linux Jessie下使用PostgrSQL 9.46,PostGIS 2.1和命令导入了数据集。
$ 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
假设多边形A的段不在B中,反之亦然,我尝试建立两个多边形集的段之间的差异,而忽略每个组(A或B)中多边形的段成员。由于教学上的原因,我在几种视图中阐述了SQL的内容。
对应于此GIS-SE帖子,我将两个多边形分解为段表segments_a
,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;
段表多边形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
将相同的步骤应用于多边形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
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)
...
我可以建立一个名为的差异表视图segments_diff_{a,b}
。差异由段集A和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;
和补充的东西:
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;
结论:为了获得用红色箭头标记的小片段的正确结果,两个多边形必须具有相同的结点结构,并且需要在结点级别上有一个相交步骤(在B中插入多边形A的顶点)。交叉口可以通过以下方式完成:
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;
但是结果很奇怪...