Postgres / postgis - 确保所有的多边形都是闭合的

5

我需要编写一个查询,找到任何未关闭的多边形,并通过复制第一个点并创建一个额外的结束点来将其关闭。

我能够选择无效的行:

SELECT delivery_zone_id, polygon from delivery_zone WHERE ST_IsClosed(polygon::geometry) = FALSE;

我可以从每个多边形中提取单独的点:

SELECT delivery_zone_id, ST_AsText((dp).geom) FROM
    (SELECT delivery_zone_id, ST_DumpPoints(polygon::geometry) AS dp 
        FROM delivery_zone 
        WHERE ST_IsClosed(polygon::geometry) = FALSE
    ) AS coords;

结果看起来像这样:

1   POINT(-96.80037 33.09812)  ## Copy this point and add it to the set
1   POINT(-96.80427 33.0956)
1   POINT(-96.80401 33.09219)
1   POINT(-96.79603 33.09222)
1   POINT(-96.79346 33.09647)
1   POINT(-96.80037 33.09857)

4   POINT(-96.80037 33.099)    ## Copy this point and add it to the set
4   POINT(-96.80427 33.0956)
4   POINT(-96.80401 33.09219)
4   POINT(-96.79603 33.09222)
4   POINT(-96.79346 33.09647)
4   POINT(-96.80037 33.09923)

这是我缺乏SQL技能的地方。我需要帮助复制第一个点并创建一个新的终点来保存该数据。伪查询也可以 - 我只需要看看它可能是什么样子的,然后我可以填补空白。
更新:最终解决方案 感谢下面JGH的答案,我能够创建以下更新查询。这将查找任何未关闭的多边形并通过复制第一个点添加新的结束点。

注意:这仅适用于简单的“单一”多边形。如果您有复杂的外部和内部多边形,则需要对此查询进行一些重大更改。

UPDATE delivery_zone dz
SET polygon=ST_MakePolygon(ST_AddPoint(subquery.openline, ST_PointN(subquery.openline, 1), -1))
FROM (
  SELECT delivery_zone_id, ST_ExteriorRing(polygon::geometry) AS openline 
  FROM delivery_zone WHERE ST_IsClosed(polygon::geometry) = FALSE
) AS subquery
WHERE dz.delivery_zone_id = subquery.delivery_zone_id;

polygon列的数据类型是什么? - JGH
我提供了一种填补日期间隙的解决方案技术,我认为它可能适用于您的问题,但不确定。请看这里:https://stackoverflow.com/a/34140783/460557 - Jorge Campos
列是地理位置,但如果这样做可以简化事情,很高兴将其更改为几何形状。这些多边形不是很大,所以地球曲线并不重要。 - Ryan Wheale
1个回答

2
你可以尝试使用线条添加点,然后转换为多边形。
需要注意的是,创建一个未闭合的多边形是不可能的......不太确定你是如何得到这样一个多边形的,希望你能首先将它们转换为线条。
因此,想法是获取线条,然后在最后位置(-1)添加一个点。该点将与此线条的第一个点(位置1)相同。最后,你可以转换为多边形。
WITH src AS (
    SELECT ST_GeomFromText('LINESTRING(0 0, 0 1, 1 1, 1 0)') As openline)
SELECT st_asText(openline), 
        st_asText(ST_MakePolygon(st_addPoint(openline,st_PointN(openline,1),-1)))
FROM src;



      st_astext          |           st_astext
-----------------------------+--------------------------------
 LINESTRING(0 0,0 1,1 1,1 0) | POLYGON((0 0,0 1,1 1,1 0,0 0))
(1 row)

你的回答为我提供了完成查询所需的所有东西。非常感谢!请向上查看以查看最终更新查询。 - Ryan Wheale

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接