Reputation: 1239
the well known function
from shapely.geometry import *
from shapely.wkt import loads
def cut(line, distance):
# Cuts a line in two at a distance from its starting point
if distance <= 0.0 or distance >= line.length:
return [LineString(line)]
coords = list(line.coords)
for i, p in enumerate(coords):
pd = line.project(Point(p))
if pd == distance:
return [
LineString(coords[:i+1]),
LineString(coords[i:])]
if pd > distance:
cp = line.interpolate(distance)
return [
LineString(coords[:i] + [(cp.x, cp.y)]),
LineString([(cp.x, cp.y)] + coords[i:])]
splits a shapely linestring into two lines at distance.
What I need to do is to cut a piece of a certain length from the line, at a certain position along the line
Example line:
line = loads("LINESTRING (12.0133696 47.8217147, 12.0132944 47.8216655, 12.0132056 47.8215749, 12.0131542 47.8215034, 12.0130522 47.8212931, 12.0129941 47.8211294, 12.0130381 47.8209553, 12.0131116 47.8208718, 12.013184 47.8208107, 12.0133547 47.8207312, 12.0135537 47.8206727, 12.013915 47.8206019, 12.0141624 47.8205671, 12.0144317 47.8204965)")
I tried an approach with getting the difference between some linestrings that i got by appliyng above cut functio, but the results are not good due to shapely limitations.
Any ideas?
Upvotes: 6
Views: 6275
Reputation: 39
You can also use intersection and normalize the interpolate to get a curve within specific range :
def cut(line, distance):
if distance <= 0.0 :#line.length:
return [None, LineString(line)]
elif distance >= 1.0:
return [LineString(line), None]
coords = list(line.coords)
for i, p in enumerate(coords):
pd = line.project(Point(p), normalized=True)
if pd == distance:
return [
LineString(coords[:i+1]),
LineString(coords[i:])]
if pd > distance:
cp = line.interpolate(distance, normalized=True)
return [
LineString(coords[:i] + [(cp.x, cp.y)]),
LineString([(cp.x, cp.y)] + coords[i:])]
def cut_piece(line,distance1, distance2):
""" From a linestring, this cuts a piece of length lgth at distance.
Needs cut(line,distance) func from above ;-)
"""
l1 = cut(line, distance1)[1]
l2 = cut(line, distance2)[0]
result = l1.intersection(l2)
return result
Example:
cir = Point(0.0, 0.0).buffer(200).exterior
cir.coords = list(cir.coords)[::-1] # to flip the curve direction
print(cir.is_ccw)
d = cut_piece(cir,0.25, 0.75)
Upvotes: 0
Reputation: 1239
I'll answer myself, and am happy about improvements:
def cut_piece(line,distance, lgth):
""" From a linestring, this cuts a piece of length lgth at distance.
Needs cut(line,distance) func from above ;-)
"""
precut = cut(line,distance)[1]
result = cut(precut,lgth)[0]
return result
Upvotes: 8