3

I am using Python to obtain the central line of a polygon (blue line) which represents the contour of a road (red line). To do so, I have used the Centerline library as shown below:

from centerline.geometry import Centerline
import geopandas as gpd

# Load the polygon representing the road contour as a GeoDataFrame

shapefile_path = 'contorno_alpha02_suavizado025_cc.shp'
gdf = gpd.read_file(shapefile_path)

# Calculates central line of the polygon

gdf['centerline'] = gdf['geometry'].apply(
    lambda x: calculate_centerline(x, {"id": 1, "name": "polygon", "valid": True}))

# New GeoDataFrame to store central lines

centerlines_gdf = gpd.GeoDataFrame(geometry=gdf['centerline'])

# Save central lines in a new shapefile.

output_shapefile_path = 'centerlines_shapefile_025_CC.shp'  
centerlines_gdf.to_file(output_shapefile_path)

The code works and gives a central line, but it has several branches that are not desirable, as they are not part of the road axis. The branches appear mainly in the curved parts of the polygon (see attached images). Is there any way to removes those "branches" with Python (ideally) or in any GIS software?

enter image description here

3
  • Calculate line lengths and remove/delete lines that are short?
    – GBG
    Commented Jan 24 at 16:23
  • I can´t do that because the resulting shapefile is a single line, and it has many vertices, not only in the insertion points. Commented Jan 29 at 11:32
  • What do you get when you explode your multi-part shapefile to a single part shapefile? Maybe post a picture with each line a different color. If the geometry works out you can select the center line, then switch the selection and delete the spurs.
    – GBG
    Commented Jan 29 at 16:18

1 Answer 1

3

The pygeoops library has a functionality that tries to do exactly that: pygeoops.centerline. There are some optional parameters you can use to finetune the generation and cleanup if needed.

Sample script based on your code (untested as I don't have a test file):

import geopandas as gpd
import pygeoops

# Load the polygon representing the road contour as a GeoDataFrame
shapefile_path = 'contorno_alpha02_suavizado025_cc.shp'
gdf = gpd.read_file(shapefile_path)

# Calculate centerline of the polygons
gdf.geometry = pygeoops.centerline(gdf.geometry)

# Save centerlines in a new shapefile.
output_shapefile_path = 'centerlines_shapefile_025_CC.shp'  
gdf.to_file(output_shapefile_path)

Disclaimer: I'm the developer of pygeoops.

3
  • Thank you very much Pieter, this is exactly whay I was looking for. However, I have tried to install pygeoops but I am struggling to ger the version I need to make the code work. I installed first with pip and then with conda, but the version I get is 3.8. However for the code to work I need version 3.10 according this error message I get: "UnsupportedGEOSVersionError: 'segmentize' requires at least GEOS 3.10.0." So I have also tried to update to version 3.10 by using conda cmd and Conda Navigator buy I haven´t´ succeed. Commented Jan 29 at 11:24
  • The easiest way to get a working situation is probably to create a new conda environment specifically with the packages you need. E.g. this command in the conda cmd window should do the trick: conda create -n geoenv --channel conda-forge python=3.11 geopandas pygeoops
    – Pieter
    Commented Jan 29 at 16:09
  • 1
    Thank you very much! Now it works Commented Feb 2 at 11:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.