【问题标题】:Applying ST_Intersection on a list of geometries在几何列表上应用 ST_Intersection
【发布时间】:2016-09-14 18:27:48
【问题描述】:

我是 postgis 的新手,所以,如果这是一个愚蠢的问题,对不起。

我在表格中有一个多边形列表,我想找到所有多边形之间的交集。 我可以做一个 ST_Union 没有这样的问题:

select ST_Union(t.geom) from mytable t

但同样不适用于 ST_Intersection

select ST_Intersection(t.geom) from mytable t` ERROR: function st_intersection(geometry) does not exist

查看ST_UnionST_Intersection 的文档,它们确实有不同的签名,这表明 unlinke ST_Union, ST_Intersection 只能应用于恰好 2 个几何体。

有解决办法吗?

提前致谢

【问题讨论】:

  • 您想找到所有几何图形的交集吗?它们是否都与一个共同区域重叠?
  • ?1 没错。 ?2 是的,在大多数情况下。如果不是,那么交叉路口将有一个 0 区域,并且该信息也很重要。

标签: sql postgresql postgis


【解决方案1】:

您可以使用WITH RECURSIVE common table expression 来处理geometry[] 的每个元素并产生运行结果。

以下是一些示例数据,基于重叠缓冲的随机位置(图中的蓝色多边形):

DROP TABLE IF EXISTS ar;
SELECT array_agg(ST_Buffer(ST_MakePoint(random(), random()), 0.5, 3)) AS geoms
INTO TEMP ar
FROM generate_series(1, 6) AS id;
SELECT ST_Collect(geoms) FROM ar;

这就是魔法:

WITH RECURSIVE inter AS (
   -- First geometry
   SELECT 1 AS idx, geoms[1] AS geom FROM ar a
   UNION ALL
   -- Remaining geometries with the previous result
   SELECT a.idx + 1, ST_Intersection(a.geom, b.geoms[a.idx + 1])
   FROM inter a, ar b
   WHERE a.idx + 1 <= array_length(geoms, 1) AND NOT ST_IsEmpty(a.geom)
)
SELECT * FROM inter
ORDER BY idx DESC LIMIT 1;

“递归”在最后一个数组索引处停止,或者如果结果为空。此外,您可以通过注释掉最后一行来查看每个交叉点。

【讨论】:

    【解决方案2】:

    您需要self join。 例如:

    SELECT ST_intersection(a.geom,b.geom) 
    FROM mytable AS a, mytable AS b 
    WHERE st_equals(a.geom, b.geom) IS FALSE AND ST_intersects(a.geom, b.geom);
    

    通过这种方式,您可以将表格与其自身进行比较。两个 where 条件保证:

    • 这两个几何形状不一样
    • 两个几何相交(否则 ST_Intersections 将返回 GEOMETRYCOLLECTION EMPTY

    如果你的表有一个 ID 列,你可以使用

    WHERE a.id != b.id
    

    而不是

    WHERE st_equals(a.geom, b.geom) IS FALSE 
    

    【讨论】:

    • 谢谢!这不完全是我所需要的,这个想法将来可能会派上用场。
    【解决方案3】:

    我发现this solution 似乎最适合我的情况。

    按照建议创建函数ST_IntersectionArray

    create or replace function ST_IntersectionArray(geoms geometry[]) returns geometry as $$ declare i integer; tmpGeom geometry; begin tmpGeom := geoms[1]; FOR i IN 1..array_length(geoms,1) LOOP tmpGeom:= ST_Intersection(tmpGeom,geoms[i]); END LOOP; return tmpGeom; end; $$ LANGUAGE plpgsql;

    你可以的

    select ST_Intersection(array_agg(distinct t.geom)) from mytable t

    区别很重要。如果有相同的多边形 if 可能会报错。

    这对我来说最有效。

    【讨论】:

      猜你喜欢
      • 2020-12-29
      • 2018-06-25
      • 2021-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多