postgresqlpostgisqgistopologymultilinestring

How to check if multilinestring really is multilinestring?


I have a huge database with a road network, and the geometry type is MULTILINESTRING. I would like to filter out the MULTILINESTRINGS with topological errors. Both the lines on the left side and on the right side are one-one record, made of two lines. Now on the right side they connect, so it doesn't really bother me, I can merge them later without a topological error. However on the left side they don't connect, but they still are one record. Multilinestrings What I've tried so far:

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 )))
)

If I could say that the MULTILINESTRINGS are made up of maximum two lines, it would work I assume. Unfortunatelly some of them are made up of 10-20 lines, and I cannot be sure that the line parts are folowwing each other in an ascending or descending order. So extending my SQL script is not an option in my opinion.

(I'm using QGIS with a PostGIS database, but I also posess ArcMap.)


Solution

  • If you're simply looking for a way to identify which MultiLineStrings contain more than one line you can simply use ST_LineMerge, then ST_Dump and count the returning LineStrings. In case a geometry contains non continuous lines the query will return a count bigger than 1, e.g.

    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)
    

    Another alternative is to use ST_NumGeometries after applying ST_LineMerge, e.g.

    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)