使用PostGIS基于交点分离多边形


36

我有一个多边形的PostGIS表,其中一些相互相交。这就是我想要做的:

  • 对于由id选择的给定多边形,请给我所有相交的多边形。基本上,select the_geom from the_table where ST_Intersects(the_geom, (select the_geom from the_table where source_id = '123'))
  • 从这些多边形中,我需要创建一个新的多边形,使交点成为一个新的多边形。因此,如果多边形A与多边形B相交,我将得到3个新多边形:A减去AB,AB和B减去AB。

有任何想法吗?


1
嗯,我想看看您要获得的是什么,但是简单的图形可能会帮助我们(和其他人)准确地了解您想要的内容。
杰森

在我的答案中添加了一些内容。
亚当·马坦

Answers:


29

由于您说的是每个感兴趣的多边形都有一组相交的多边形,因此您可能需要创建一个称为“多边形叠加层”的多边形。

这并不是亚当的解决方案正在做的事情。要查看差异,请看以下ABC交叉点图片:

ABC路口

我相信Adam的解决方案将创建一个覆盖“ AB!C”和“ ABC”区域的“ AB”多边形,以及一个覆盖“ AC!B”和“ ABC”的“ AC”多边形,以及一个“ BC”多边形,即“ BC!A”和“ ABC”。因此,“ AB”,“ AC”和“ BC”输出多边形将全部与“ ABC”区域重叠。

多边形叠加层会产生非重叠的多边形,因此AB!C将是一个多边形,而ABC将是一个多边形。

实际上,在PostGIS中创建多边形叠加层非常简单。

基本上有三个步骤。

步骤1是提取线条[请注意,我使用的是多边形的外环,如果要正确处理孔,它的确会更加复杂]:

SELECT ST_ExteriorRing(polygon_col) AS the_geom FROM my_table) AS lines

步骤2是“连接”线条(在每个相交处生成一个节点)。有些库(例如JTS)具有“ Noder”类,您可以使用它来执行此操作,但是在PostGIS中,ST_Union函数可以为您执行此操作:

SELECT ST_Union(the_geom) AS the_geom FROM (...your lines...) AS noded_lines

第3步是通过ST_Polygonize函数创建所有可能来自所有这些线的非重叠面:

SELECT ST_Polygonize(the_geom) AS the_geom FROM (...your noded lines...)

您可以将每个步骤的输出保存到临时表中,也可以将它们全部合并为一个语句:

CREATE TABLE my_poly_overlay AS
SELECT geom FROM ST_Dump((
    SELECT ST_Polygonize(the_geom) AS the_geom FROM (
        SELECT ST_Union(the_geom) AS the_geom FROM (
            SELECT ST_ExteriorRing(polygon_col) AS the_geom FROM my_table) AS lines
        ) AS noded_lines
    )
)

我之所以使用ST_Dump,是因为ST_Polygonize的输出是一个几何图形集合,并且(通常)使用一个表(其中每一行都是构成多边形叠加层的多边形之一)更为方便。


请注意ST_ExteriorRing掉落任何孔。ST_Boundary将保留内部环,但也会在内部创建一个多边形。
jpmc26

多边形过多时,外环的并集会崩溃。不幸的是,这种“直截了当”的解决方案仅适用于较小的覆盖范围。
皮埃尔·拉辛

13

如果我理解正确,那么您想学习(A是左侧的几何图形,B是右侧的几何图形):

A∪B的图片http://img838.imageshack.us/img838/3996/intersectab1.png

并提取:

∖AB

A∖AB的图片http://img830.imageshack.us/img830/273/intersectab2.png

AB

AB的图片http://img828.imageshack.us/img828/7413/intersectab3.png

和B∖AB

B∖AB的图片http://img839.imageshack.us/img839/5458/intersectab4.png

也就是说-每个相交的对都有三种不同的几何形状。

首先,让我们创建所有相交几何的视图。假设您的表名是polygons_table,我们将使用:

CREATE OR REPLACE VIEW p_intersections AS    -- Create a view with the 
SELECT t1.the_geom as t1_geom,               -- intersecting geoms. Each pair
       t2.the_geom as t2_geom                -- appears once (t2.id<t2.id)
    FROM polygons_table t1, polygons_table t2  
         WHERE t1.id<t2.id AND t1.the_geom && t2.the_geom 
                           AND intersects t1.the_geom, t2.the_geom;

现在,我们有了一个视图(实际上是一个只读表),该视图存储成对的相交几何图形,其中每对由于t1.id<t2.id条件而仅出现一次。

现在,让我们收集您的交叉口- A∖ABAB并且B∖AB,使用SQL的UNION所有三个查询:

--AB:
SELECT ST_intersection(t1.the_geom, t2.the_geom) 
    AS geom 
    FROM p_intersections

UNION 

--AAB:
SELECT ST_Difference(t1.the_geom, t2.the_geom) 
    AS geom 
    FROM p_intersections

UNION

--BAB:
SELECT ST_Difference(t2.the_geom, t1.the_geom) 
    AS geom 
    FROM p_intersections;

笔记:

  1. &&运营商作为前一个过滤器intersects操作,以提高性能。
  2. 我选择创建一个VIEW而不是一个巨大的查询。这只是为了方便。
  3. 如果你的意思AB是工会,没有交集,中AB-使用ST_Union而不是在st_intersection UNION在适当的位置查询。
  4. 符号是Set差异的unicode符号;如果它使您的数据库混乱,请将其从代码中删除。
  5. 图片由Wikimedia Commons的nice Set理论类别提供


很好的解释!结果与scw解决方案中的结果相同,但是他的方法应该更快(不计算/或存储/附加A和B的交集)
stachu 2010年

谢谢!我想我不存储任何其他信息,因为我仅创建SQL VIEW,而不创建表。
亚当·马坦

是的,的确如此,但是您可以计算A和B的附加交集,这不是
必需的

5
此答案中的图像不再起作用。
Fezter

8

您要描述的是Union运算符在ArcGIS中的工作方式,但与GEOS世界中的Union或Intersection稍有不同。Shapely手册中有一些示例,说明了集如何在GEOS中工作。但是,PostGIS Wiki确实有一个很好的示例,说明了使用线条的技巧,该技巧可以为您解决问题。

另外,您可以计算三件事:

  1. ST_Intersection(geom_a,geom_b)
  2. ST_Difference(geom_a,geom_b)
  3. ST_Difference(geom_b,geom_a)

这些应该是您在第二个要点中提到的三个多边形。


2
PostGIS Wiki示例很好
fmark

如果ST_Intersects相交或不相交,是否不返回布尔值?我认为ST_Intersection将起作用。
杰森

是的,我的错别字-现在已固定在原文中,谢谢杰森!
SCW

-2

就像是:

插入new_table VALUES((选择id,从old_table中选择the_geom,其中st_intersects(the_geom,(从old_table中选择the_geom,其中id ='123'))= true

编辑:您需要多边形的实际交点。

插入到new_table值中((选择id,ST_Intersection(the_geom,(从id = 123的旧版本中选择the_geom)))

看看是否可行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.