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