如何检查多线串是否真的是多线串?

How to check if multilinestring really is multilinestring?

我有一个庞大的道路网络数据库,几何类型是MULTILINESTRING。我想过滤掉具有拓扑错误的 MULTILINESTRINGS。左右两行都是一对一的记录,由两条线组成。现在它们在右侧连接,所以它并没有真正打扰我,我可以稍后合并它们而不会出现拓扑错误。然而在左侧,它们没有连接,但它们仍然是一条记录。 到目前为止我尝试了什么:

SELECT gid 
FROM myschema.roads 
WHERE (
NOT ST_Equals(ST_Endpoint(ST_GeometryN(the_geom,1 )),ST_Startpoint(ST_GeometryN(the_geom,2 ))) 
    AND NOT ST_Equals(ST_Endpoint(ST_GeometryN(the_geom,2 )),ST_Startpoint(ST_GeometryN(the_geom,1 )))
)

如果我可以说 MULTILINESTRINGS 最多由两行组成,我认为它会起作用。不幸的是,其中一些由 10-20 行组成,我不能确定这些行的部分是按升序还是降序排列的。因此,在我看来,扩展我的 SQL 脚本不是一个选项。

(我正在使用带有 PostGIS 数据库的 QGIS,但我也有 ArcMap。)

您可以使用此函数来检查多线串是否已连接:

CREATE OR REPLACE FUNCTION is_connected(g geometry(MultiLineString)) RETURNS boolean
   LANGUAGE plpgsql AS
$$DECLARE
   i integer;
   point geometry := NULL;
   part geometry;
BEGIN
   FOR i IN 1..ST_NumGeometries(g) LOOP
      part := ST_GeometryN(g, i);

      IF NOT ST_Equals(point, ST_Startpoint(part)) THEN
         RETURN FALSE;
      END IF;

      point := ST_Endpoint(part);
   END LOOP;

   RETURN TRUE;
END;$$;

如果您只是想寻找一种方法来识别哪些 MultiLineStrings 包含多个行,您可以简单地使用 ST_LineMerge, then ST_Dump 并计算 returning LineStrings .如果几何包含非连续线,查询将 return 计数大于 1,例如

WITH j (geom) AS (
  VALUES ('MULTILINESTRING((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))'),
         ('MULTILINESTRING((10 10, 20 20, 10 40),(10 40, 30 30, 40 20, 30 10))'))
SELECT geom,(SELECT count(*) FROM ST_Dump(ST_LineMerge(geom))) 
FROM j;

                                geom                                 | count 
---------------------------------------------------------------------+-------
 MULTILINESTRING((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10)) |     2
 MULTILINESTRING((10 10, 20 20, 10 40),(10 40, 30 30, 40 20, 30 10)) |     1
(2 Zeilen)

另一种方法是在应用 ST_LineMerge 之后使用 ST_NumGeometries,例如

WITH j (geom) AS (
  VALUES ('MULTILINESTRING((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))'),
         ('MULTILINESTRING((10 10, 20 20, 10 40),(10 40, 30 30, 40 20, 30 10))'))
SELECT geom,ST_NumGeometries(ST_LineMerge(geom)) AS count
FROM j;
                                geom                                 | count 
---------------------------------------------------------------------+-------
 MULTILINESTRING((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10)) |     2
 MULTILINESTRING((10 10, 20 20, 10 40),(10 40, 30 30, 40 20, 30 10)) |     1
(2 Zeilen)