2

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? – bugmenot123 Jan 7 '17 at 17:56
2

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)
-2.2934712193638029

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
-2.2934712193638029
from scipy import stats
slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
print slope
-2.2934712193638029

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]
-2.2934712193638029 
print stats.linregress([second.x,first.x],[second.y,first.y])[0]
-2.2934712193638029 
| improve this answer | |
  • 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 '17 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 '17 at 23:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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