I've got a method for making cross-section points along a shapely LineString object that I'm not totally happy with.

My strategy is:

  1. Create regular points every 50cm along a LineString
  2. Create an offset point 1cm away from the 50.1cm point
  3. Use these two points to find a slope
# Get 50cm spaced points                    
points = [linestr.interpolate(dist) for dist in np.arange(0, linestr.length, 0.5)]

# Get points at 50.1cm
_offsetpts = [linestr.interpolate(currDist+0.001) for currDist in np.arange(0, linestr.length, 0.5)]

# Use these two points to do rise/run and get a slope
slopes = [((points[idx].coords[0][1] - _offsetpts[idx].coords[0][1]) /
           (points[idx].coords[0][0] - _offsetpts[idx].coords[0][0])) for idx, pt in enumerate(_offsetpts)]

It works but it's not very elegant and I worry it will break for edge cases (like when 1 extra cm runs over the edge of the line)

Does anyone know a better way to get the slope of a line a known distance along a LineString object using python and shapely?

  • What exactly is your goal? Jan 7, 2017 at 17:56

1 Answer 1


You don't need a second list of points to find the slopes

import itertools
# iterate by pairs of points
slopes = [(second.y-first.y)/(second.x-first.x)for first, second in itertools.izip(points, points[1:])]

If you want the mean slope of the slopes

import numpy as np
def mean_slope(xs,ys):
    m = (((np.mean(xs)*np.mean(ys)) - np.mean(xs*ys)) /((np.mean(xs)**2) - np.mean(xs*xs)))
    return m
print mean_slope(slopes)

You can also use NumPy or SciPy

x, y = zip(*[(pt.x, pt.y) for pt in points])
slope, intercept = np.polyfit(x,y,1)
print slope
from scipy import stats
slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
print slope

If the LineString is straight all the values of slopes = slope

If you want the slope between two point

first = points[5]
second = points[6]
print (second.y-first.y)/(second.x-first.x) 
-2.2934712193638029 #straight line in my case
print np.polyfit([second.x,first.x],[second.y,first.y],1)[0]
print stats.linregress([second.x,first.x],[second.y,first.y])[0]
  • This is so close to what I need. I guess the only outstanding piece is that I don't have the two points. All I have is a line and a distance along that line. Maybe this is trivial and I'm missing something but is there a shapely way to find the line segment at distance x along a line segment? Do I need to break the LineString into pieces and test coordinate pairs until I find the one that contains the intersection?
    – Raychaser
    Jan 9, 2017 at 19:31
  • 1
  • Thanks. Finally got to this and managed to get it working. Trouble was that it became really slow for lines with huge point counts. So I wrote a bisecting algorithm to locate it and it works pretty well.
    – Raychaser
    Jan 17, 2017 at 23:06

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.