使用ST_Difference删除重叠的功能?


11

我正在尝试使用PostGis 2.1(和Postgres SQL 9.3)使用ST_Difference创建一组多边形(processing.trimmedparcelsnew),这些多边形不包含另一组多边形(test.single_geometry_1)所覆盖的任何区域。这是我的查询:

CREATE TABLE processing.trimmedparcelsnew AS
SELECT
    orig.id, ST_Difference(orig.geom, cont.geom) AS difference
FROM 
    test.single_geometry_1 cont,
    test.multi_geometry_1 orig;

但是生成的多边形尚未修剪,相反,它们似乎在与另一层相交的地方被拆分了。我试过只运行选择而不将结果放在表中以及其他我能想到的东西,但是我似乎无法使该功能正常工作。

我已附上结果图

在此处输入图片说明


评论后,我尝试添加WHERE子句。我希望没有交集的宗地,而其他宗地的相交区域被删除(图层test.single_geometry表示要从宗地中删除的污染)。我尝试了一个相交,但是我当然想要非相交,所以我现在尝试分离。我也尝试过将折纸添加到表中,但是ST_Difference的文档(http://postgis.net/docs/ST_Difference.html)确实说它返回了我需要的精确几何图形(表示几何图形A的那部分,不会与几何B)相交,所以我对为什么要在表格中使用原始多边形感到困惑。无论如何,这是我修改后的代码:

CREATE TABLE processing.trimmedparcelsnew AS
SELECT
    orig.id, ST_Difference(orig.geom, cont.geom) AS difference, orig.geom AS geom
FROM 
    test.single_geometry_1 cont,
    test.multi_geometry_1 orig
WHERE ST_Disjoint(orig.geom, cont.geom);

根据dbaston的回答,我现在尝试:

CREATE TABLE processing.parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM test.single_geometry_1 b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM test.multi_geometry_1 a;

结果只是一份test.multi_geometry_1的副本。尽管现在不再发生分裂。

我尝试了早期版本,但再次获得了test.multi_geometry_1的副本:

CREATE TABLE processing.parcels_trimmed_no_coalesce AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM test.single_geometry_1 b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM test.multi_geometry_1 a;

我开始怀疑我是否在做其他错误的事情?程序声明为:

DROP TABLE IF EXISTS processing.parcels_trimmed_no_coalesce;

我正在从PostgreSQL SQL查询窗口和Openjump运行查询。

我用来查看该表的语句是:

SELECT * FROM processing.parcels_trimmed_no_coalesce;

为了简化起见,我现在将此查询简化为:

SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM test.geometriestocutagainst b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM test.geometriestocut a;

当所需的结果是针对test.geometriestocut的原始修剪时,这仍然仅会导致原始多边形(test.geometriestocut)。


您未指定WHERE子句,因此结果表中可能具有多项式展开。有多少行trimmedparcelsnew
文斯

如果只希望它们相交的地方不同,则可以尝试添加WHERE ST_Intersects(orig.geom,cont.geom)。否则,两个不相交的多边形的差就是原始多边形。
John Powell 2015年

修剪后的包裹中有24行是新的,即使它们不相交,我也要有所不同,所以我是否需要在表中使用orig.geom而不是不同?
集市

甲不相交测试应该产生多项式展开-在每个特征CONT用于在每个特征出现一次原稿不重叠,并且差异将永不改变输入几何
文斯

好的,谢谢您的澄清,但是我仍然不确定为什么原始代码不起作用。如果ST_Difference(orig.geom,cont.geom)返回不与b相交的a中的几何,那么为什么表格中包含拆分几何而不是不与b相交的a中的几何。
集市

Answers:


14

自联接使您可以处理两个要素之间的关系。但是我不认为您对成对感兴趣:对于每个功能,您都希望处理该功能与数据集中所有其他功能之间的关系。您可以使用子查询表达式来完成此操作:

CREATE TABLE parcels_trimmed AS
SELECT id, ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                FROM parcels b
                                WHERE ST_Intersects(a.geom, b.geom)
                                  AND a.id != b.id))
FROM parcels a;

不过,您可能会在结果中看到一些奇怪的地方。没有重叠的包裹将被完全丢弃!这是因为ST_Union空记录集上的聚合将是NULL,并且ST_Difference(geom, NULL)NULL。为了解决这个问题,您需要将ST_Difference通话包装在中COALESCE

CREATE TABLE parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM parcels b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM parcels a;

这意味着,如果的结果ST_DifferenceNULL,则合并的表达式将求值为原始几何。

上面的查询将从您的域中完全删除重叠的区域。如果您想选择获胜者,则可以选择a.id < b.id或其他标准a.id != b.id


不幸的是,感谢您的答复,我很难让它为我工作,而只是以原始的多边形(a)结尾。我将使用更多信息来编辑我的问题。再次感谢。
集市2015年

2

我和你有同样的问题。我不知道您是否已经找到解决问题的方法,但是我修改了上面接受的答案,然后得到了我想要的。

CREATE TABLE parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Collect(b.geom) 
                                         FROM parcels b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         )), a.geom)
FROM parcels a;

1

我使用PostGIS插件中的 ST_DifferenceAgg()。您必须将两个表合并在一起,在几何列上具有唯一的标识符和索引。这是一个简短的示例:

WITH overlappingtable 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))')
  UNION ALL
  SELECT 3 id, ST_GeomFromText('POLYGON((2 1, 4.6 2, 5 0, 2 1))')
  UNION ALL
  SELECT 4 id, ST_GeomFromText('POLYGON((3 1, 5.4 2, 6 0, 3 1))')
  UNION ALL
  SELECT 5 id, ST_GeomFromText('POLYGON((3 1, 5.4 2, 6 0, 3 1))')
)
SELECT a.id, ST_DifferenceAgg(a.geom, b.geom) geom
FROM overlappingtable a,
     overlappingtable b
WHERE a.id = b.id OR -- Make sure to pass at least once the polygon with itself
      ((ST_Contains(a.geom, b.geom) OR -- Select all the containing, contained and overlapping polygons
        ST_Contains(b.geom, a.geom) OR
        ST_Overlaps(a.geom, b.geom)) AND
       (ST_Area(a.geom) < ST_Area(b.geom) OR -- Make sure bigger polygons are removed from smaller ones
        (ST_Area(a.geom) = ST_Area(b.geom) AND -- If areas are equal, arbitrarily remove one from the other but in a determined order so it's not done twice.
         a.id < b.id)))
GROUP BY a.id
HAVING ST_Area(ST_DifferenceAgg(a.geom, b.geom)) > 0 AND NOT ST_IsEmpty(ST_DifferenceAgg(a.geom, b.geom));

这会将重叠的部分与最大的重叠多边形合并。如果要使重叠部分保持分离,请查看ST_splitAgg()示例。

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.