How to split polygons with overlapping polygons AND count overlaps in PostgreSQL?
我正在尝试在一个包含1000个重叠多边形(多部分,有些带有孔)的单个表上创建SQL查询(PosgreSQL PostGIS),该查询将:
。将多边形切成不重叠的部分
。计算发生重叠的次数。
我发现了一些使用谷歌搜索的示例,但是都没有完整的答案。例如,这是一种切割多边形的方法(基于:相当于ArcMap Union的PostGIS),但是如果多边形有孔,则不能正确切割。而且我不知道如何添加计数重叠的列:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | WITH forest AS ( SELECT * FROM (VALUES (1,ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0) ,(1 1, 1 3, 3 3, 3 1, 1 1))',0)) ,(2,ST_GeomFromText('POLYGON((10 0,20 0,20 10,10 10,10 0))',0)) ,(3,ST_GeomFromText('POLYGON((2 2,4 2,4 4,2 4,2 2))',0)) /* hole in first */ ,(4,ST_GeomFromText('POLYGON((8 5,12 5,12 9,8 9,8 5))',0)) /* overlapping */ ,(5,ST_GeomFromText('POLYGON((12 2,14 2,14 4,12 4,12 2))',0)) /* hole in second */ ) forest(id, geom) ) SELECT (dump).path[1] id, (dump).geom FROM ( -- c) Polygonize the unioned rings (returns a GEOMETRYCOLLECTION) -- Dump them to return individual geometries SELECT ST_Dump(ST_Polygonize(geom)) dump FROM ( -- b) Union all rings in one big geometry SELECT ST_Union(geom) geom FROM ( -- a) First get the exterior ring from all geoms SELECT ST_ExteriorRing(geom) geom FROM forest ) a ) b ) c |
输入:
结果:
此处引用的答案需要自定义扩展名:https://gis.stackexchange.com/questions/300800/get-single-part-polygon-by-their-intersection-in-postgis,尽管其中包括对重叠和处理孔时,结果还包含重叠的多边形。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | WITH geomtable AS ( SELECT 1 id, ST_GeomFromText('POLYGON((0 1, 3 2, 3 0, 0 1), (1.5 1.333, 2 1.333, 2 0.666, 1.5 0.666, 1.5 1.333))') geom UNION ALL SELECT 2 id, ST_GeomFromText('POLYGON((1 1, 3.8 2, 4 0, 1 1))') geom UNION ALL SELECT 3 id, ST_GeomFromText('POLYGON((2 1, 4.6 2, 5 0, 2 1))') geom UNION ALL SELECT 4 id, ST_GeomFromText('POLYGON((3 1, 5.4 2, 6 0, 3 1))') geom UNION ALL SELECT 5 id, ST_GeomFromText('POLYGON((3 1, 5.4 2, 6 0, 3 1))') geom UNION ALL SELECT 6 id, ST_GeomFromText('POLYGON((1.75 1, 1 2, 2 2, 1.75 1))') geom ), parts AS ( SELECT a.id, unnest(ST_SplitAgg(a.geom, b.geom, 0.00001)) geom FROM geomtable a, geomtable b WHERE ST_Equals(a.geom, b.geom) OR ST_Contains(a.geom, b.geom) OR ST_Contains(b.geom, a.geom) OR ST_Overlaps(a.geom, b.geom) GROUP BY a.id, ST_AsEWKB(a.geom) ) SELECT COUNT(*) nb, ST_Union(geom) geom FROM parts GROUP BY ST_Centroid(geom) |
结果:
我希望有一种方法可以通过一些调整使其适用于所有类型的多边形...
所以,我再次回答自己的问题...
这是我想出的,希望它能对其他有类似问题的人有所帮助:
。此代码适用于带孔的多边形(至少对于我测试过的情况);
。有两部分:第一部分将多个重叠的多边形拆分为各个部分,第二部分(针对每个部分中的一个点)检查与多少个输入多边形相交;
。该代码将处理"几个"重叠的多边形,但未经在大型表上进行测试-如果对输入数据进行正确索引,则可以提高性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | WITH forest AS ( SELECT * FROM (VALUES (1,ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(1 1, 1 3, 3 3, 3 1, 1 1))',0)) ,(2,ST_GeomFromText('POLYGON((10 0,20 0,20 10,10 10,10 0))',0)) ,(3,ST_GeomFromText('POLYGON((2 2,4 2,4 4,2 4,2 2))',0)) /* hole in first */ ,(4,ST_GeomFromText('POLYGON((8 5,12 5,12 9,8 9,8 5))',0)) /* overlapping */ ,(5,ST_GeomFromText('POLYGON((12 2,14 2,14 4,12 4,12 2))',0)) /* hole in second */ ) forest(id, geom) ), parts AS( SELECT path[1] id, geom FROM ST_Dump(( SELECT ST_Polygonize(the_geom) AS the_geom FROM ( SELECT ST_Union(the_geom) AS the_geom FROM ( SELECT ST_Boundary(geom) AS the_geom FROM forest) AS LINES ) AS noded_lines ) )) SELECT a.geom, COUNT(*) nb FROM parts a , forest b WHERE ST_Within(ST_PointOnSurface(a.geom),b.geom) GROUP BY a.id, a.geom |