如何检查多线串是否真的是多线串?
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)
我有一个庞大的道路网络数据库,几何类型是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)