pythonpython-3.xogrmultilinestringosgeo

Accessing M-values associated to LINESTRING M and MULTILINESTRING M geometries


How can I access a line geometry's multiple M-values? Consider that the line geometry in question can be either a LINESTRING M or MULTILINESTRING M geometry that was created using osgeo/ogr.

Here's a small reproducible example:

from osgeo import ogr

line_wkt  = 'LINESTRING M (0 0 5, 0 1 6, 1 1 10)'
line_geom = ogr.CreateGeometryFromWkt(line_wkt)


mline_wkt = 'MULTILINESTRING M ((0 0 5, 0 1 6, 1 1 10), (1 1 10, 2 1 20, 3 1 30))'
mline_geom = ogr.CreateGeometryFromWkt(mline_wkt)

In the example above, the line_geom and mline_geom objects are successfully stored with their respective M-values, but I'm having a hard time accessing them.

I'm searching for a function that will return [5,6,10] for the line_geom object and [[5,6,10],[10,20,30]] for the mline_geom object.

Here are the alternatives I've tried but ultimately did not work:

Using the GetM() method

The GetM() method doesn't seem to give me exactly what I want. For example, when I do line_geom.GetM(), I just get back 5.0. I think it just gives me the M-value for the first point in the line.

Also, when I try line_geom.GetM(), I get back 0.0 and then a bunch of ERROR 6: Incompatible geometry for operation.

Using the GetPoints() method

I thought I would be able to iterate over a line' points using the GetPoints() method and access the M-values through there. Unfortunately, that didn't work either - when I run line_geom.GetPoints(), the resulting list does not contain the M-values: [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)].

Also, when I try mline_geom.GetPoints(), I just get a bunch of ERROR 6: Incompatible geometry for operation.

Note

The solution needs to be in Python. I know that I can do a lot of stuff using ogr2ogr's CLI, but this is a small part of something bigger and this needs to be in Python.


Solution

  • See the OGR Geometry docs:

    GetM(Geometry self, int point=0)

    By default, just calling line_geom.GetM() will return the measure for the first point - default point=0 argument.

    For the multilinestring, you need to get each individual geometry, before getting the points and measures.

    line_wkt  = 'LINESTRING M (0 0 5, 0 1 6, 1 1 10)'
    line_geom = ogr.CreateGeometryFromWkt(line_wkt)
    
    for i, point in enumerate(line_geom.GetPoints()):
        print(line_geom.GetM(i), point)
    
    
    mline_wkt = 'MULTILINESTRING M ((0 0 5, 0 1 6, 1 1 10), (1 1 10, 2 1 20, 3 1 30))'
    mline_geom = ogr.CreateGeometryFromWkt(mline_wkt)
    
    for j in range(mline_geom.GetGeometryCount()):
        geom = mline_geom.GetGeometryRef(j)
        for i, point in enumerate(geom.GetPoints()):
            print(geom.GetM(i), point)
    

    Output:

    5.0 (0.0, 0.0)
    6.0 (0.0, 1.0)
    10.0 (1.0, 1.0)
    5.0 (0.0, 0.0)
    6.0 (0.0, 1.0)
    10.0 (1.0, 1.0)
    10.0 (1.0, 1.0)
    20.0 (2.0, 1.0)
    30.0 (3.0, 1.0)