LRS Creation and Compatibility

This notebook covers creating a new Linear Referencing System from geometries, working with M-enabled geometry formats, and processing various data sources.

[1]:
import linref as lr

# Load roadways dataset with LRS pre-configured
roadways = lr.datasets.load('roadways', set_lrs=True)

Saving and Loading M-Enabled Geometry with WKT

Due to limited support of M-enabled geometries in shapely and geopandas, saving and loading data containing linref’s LineStringM geometries is best done using WKT.

  • Loading Data. When loading data, you can parse WKT with an M dimension using df.lr.parse_geom_m_wkt(inplace=True). Be sure that the M-enabled geometry column is included in the LRS being used.

  • Saving Data When saving data to a text-based format, LineStringM objects will automatically be converted to WKT. When saving data to a database format, you must indicate the type of the M-enabled geometry column using dtype={'geometry_m': str}, such as when using pandas’ to_sql or geopandas’ to_postgis.

Processing Various Data Formats

Depending on the source, your data may be in a variety of states. Here is some general guidance on how to prepare data given a few case examples:

1. Spatialized linear layer with no existing LRS

Load the data using geopandas and generate a new LRS on the data using the df.lr.generate_linear_events method described below.

2. Spatialized linear or point layer with event begin and end or location measures

Load the data using geopandas and validate the existing LRS. First, check that all records have valid event information using df.lr.invalid_events.sum() > 0 or by dropping invalid events with df.lr.drop_invalid_events(). Then, for linear events only, confirm that the data is properly chained with no disjoints within any unique route (i.e., dissolving the linear data produces single-part LineStrings) using df.lr.is_chained.

3. Spatialized linear layer with M-enabled geometries

As of version 2.1, shapely provides some basic support of loading M-enabled geometries. Geopandas may require the use_arrow=True parameter when loading the data to be able to process these geometries without losing the M dimension. Load the data using geopandas and convert the shapely LineString objects containing M values which have minimal support to the linref LineStringM class using df['geometry_m'] = lr.ext.parse_geoms_m_shapely(df.geometry) or similar. Because the M dimension in the loaded geometry column may cause issues with some functionality, you can then remove the M dimension using df['geometry'] = df.lr.geoms_m_reduced. Finally, extract the begin and end measures from the processed M-enabled geometries for each event using df.lr.extract_m_values(inplace=True).

Generating a Linear Referencing System on Linear Data

If you have a dataset that contains linear geometries but is not linearly referenced, you can generate a new linear referencing system on that data using the generate_linear_events method. This will analyze your dataset, finding chains of contiguous geometries that share the same key column values. It then computes event begin and end measures according to the lengths of the chained geometries, defining each geometry’s event boundaries.

This can be helpful when working with data that doesn’t already include a linear referencing system (e.g., OpenStreetMaps roadway network data), enabling LRS-driven data engineering, analysis, and more using linref or another program like QGIS. Other associated data can then be projected to this new LRS, such as point or linear assets like street signs or project boundaries, creating a unified data system.

The generate_linear_events method will typically add a chain column to identify contiguous groups of geometries within each route. This is controlled by the chain_col parameter on the LRS, which defines the column name used for chain indices. When a route like 'Main St' appears in multiple disconnected locations, each contiguous group of geometries gets a unique chain index, ensuring the LRS is not disjointed. If you are certain that this feature is not needed, you can avoid adding the chaining column with the parameter add_chain=False.

[2]:
# Generate a linear referencing system based on existing geometries
generated = roadways.lr.generate_linear_events(
    scale=5280, # Scales the distances calculated based on the coordinate reference system (e.g., unit conversion)
    decimals=0, # Round the computed event measures after scaling is applied
    add_chain=False, # Don't add chaining because we already know routes are not disjointed
    replace=True # Replaces existing LRS information for the sake of this example
)
print(generated.lr.get_group('I-5')[['route', 'beg', 'end']])
  route      beg      end
7   I-5      0.0  22283.0
8   I-5  22283.0  45831.0
9   I-5  45831.0  67330.0