【问题标题】:Generating single KML for multiple geometries in PostgreSQL/PostGIS在 PostgreSQL/PostGIS 中为多个几何图形生成单个 KML
【发布时间】:2014-10-29 12:53:14
【问题描述】:

我有一个 PostgreSQL 表,如下所示:

CREATE TABLE area
(
  area_code character varying(10) NOT NULL,
  shape geometry NOT NULL,
  CONSTRAINT pk_area PRIMARY KEY (area_code)
)

并且在几何列上有一个索引。

我想编写一个函数,传入一个 area_code 数组并返回一个表示这些区域的组合 KML 的值。要返回 KML,我使用 ST_AsKML。要将所有区域合并在一起,我使用ST_UNION。为了确保联合返回单个几何而不是集合,我使用ST_MULTI。这一切都给了我:

SELECT ST_AsKML(ST_MULTI(ST_UNION(shape))) as KML
FROM area
WHERE area_code = ANY(thearray)

在 pgAdmin III 中运行时出现错误:

错误:lwgeom_to_kml2:'GeometryCollection' 几何类型不是 支持的 SQL 状态:XX000 上下文:SQL 函数“st_askml”语句 1

但据我所知,这不应该发生。 ST_MULTI 应确保传递给 ST_AsKML 的值不是 GeometryCollection。我的方法是否正确但需要修复,还是我使用了完全错误的技术来生成 KML?

【问题讨论】:

    标签: postgresql postgis


    【解决方案1】:

    如果您的ST_Union 操作出于某种原因生成PointsLinestrings,或者您在ST_Union 的输入中混合了几何类型(即,多边形或多多边形除外),就会发生这种情况。正如Google KML docs 中所述,KML 不支持GeometryCollections

    您可以通过调用 ST_Union 两次来解决此问题,使用 ST_Dump 将联合几何体分开,并仅从第一个联合体(转储)中选择那些生成多边形或多多边形的几何体——您可以在不生成 GeometryCollection 的情况下组合它们。您需要使用 ST_Union 两次,就像您在 Polygon 和 MultiPolygon 上使用 ST_Collect 一样,您将再次获得 GeometryCollection。

    WITH polygons (geom) as 
       (SELECT (ST_Dump(ST_Union(shape))).geom 
           FROM area 
           WHERE area_code = any(thearray))
       SELECT ST_AsKML(ST_Multi(ST_Union(geom))) as KML 
           FROM polygons 
           WHERE ST_GeometryType(geom) in ('ST_Polygon','ST_MultiPolygon');
    

    您可以通过运行以下查询来查看 ST_Multi 的问题,该查询尝试从点和线串中创建多几何:

    SELECT 
       ST_AsText(
           ST_Multi(
             ST_Union(
               ST_MakePoint(0,0),
               ST_MakeLine(ST_MakePoint(5,5), ST_MakePoint(10,10))
             )
          )
     );
    

    返回GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(5 5,10 10))。 ST_Multi 不是聚合函数,因此基本上只是将 Multi 和一对额外的 () 添加到任何可以制成 Multi 的东西,但如果您有两种类型的几何,其联合将强制几何集合,则不会产生任何影响。

    编辑:注意两者之间的区别,

     SELECT 
       ST_AsText(
         ST_Multi(
           ST_Collect(
             ST_Multi(ST_Expand(ST_MakePoint(0,0),2)),
             ST_Expand(ST_MakePoint(5,5), 1)
          )
       )
    );
    

    产生GEOMETRYCOLLECTION(MULTIPOLYGON(((-2 -2,-2 2,2 2,2 -2,-2 -2))),POLYGON((4 4,4 6,6 6,6 4,4 4)))

    SELECT 
       ST_AsText(
         ST_Multi(
           ST_Union(
             ST_Multi(ST_Expand(ST_MakePoint(0,0),2)),
             ST_Expand(ST_MakePoint(5,5), 1)
          )
       )
    );
    

    产生MULTIPOLYGON(((-2 -2,-2 2,2 2,2 -2,-2 -2)),((4 4,4 6,6 6,6 4,4 4)))

    因为 Polygon 可以成为 MultiPolygon 的一部分,所以在联合之后,您可以避免第二种情况下可怕的 GeometryCollection。但是,如果您将任何线或点放入混合中,您将回到 GeomtryCollection 领域。

    编辑 2: 在 OP 的 cmets 之后,Google KML docs 声明在 KML 中不支持 GeometryCollections。由于无法在不生成 GeometryCollection 的情况下将点和/或线与多边形组合,因此上述(多)多边形方法是唯一可行的方法。

    【讨论】:

    • 谢谢。有几件事。请从 WHERE area_code = ... 行的末尾编辑掉逗号,因为它不应该存在并停止查询工作。除非我更改至少 6 个字符,否则我无法编辑。您是否有任何文档的链接,说明这将使用哪些 GeometryTypes?它只是 ST_Polygon 还是 ST_MultiPolygon 可以工作?我不想扔掉太多。
    • 谢谢,逗号被删除了,我只是在写一系列的 with 子句,所以有点逗号疯了。是的,它也适用于 MultiPolygon。我还编辑了第二个查询,因为您不需要第二个 ST_Union 的开销,您可以使用 ST_Collect,因为在转储后您知道所有(多)多边形都不会重叠。
    • 实际上,如果您使用的是MultiPolygon和Polygons,那么您确实需要在第二次查询中使用ST_Union。
    • 谢谢。在此过程中进行投票。我宁愿不扔掉线条和点,但如果我必须这样做,它也不是一个阻碍。因此,我明天会接受这个作为答案,除非另一个答案允许我在所有地区都这样做。
    • 安迪,我已经稍微更新了这个问题。正如您所发现的,KML 不支持几何集合,并且不同几何类型的任何组合(不包括具有相同类型的多个(某种类型))将根据定义生成 GeometryCollection。如果你想保留点/线,一个可能的技巧是将它们缓冲一小部分。由于 KML 主要用于显示而不是 GIS 类型分析(我并不是说以消极的方式),因此在我认为的许多情况下这可能是可以接受的。
    猜你喜欢
    • 1970-01-01
    • 2013-01-02
    • 2014-02-14
    • 2021-05-04
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    相关资源
    最近更新 更多