Skip to content

Instantly share code, notes, and snippets.

@snorfalorpagus
Created April 25, 2016 16:32
Show Gist options
  • Select an option

  • Save snorfalorpagus/cd62e3fac632a3e648eb382f95f646b3 to your computer and use it in GitHub Desktop.

Select an option

Save snorfalorpagus/cd62e3fac632a3e648eb382f95f646b3 to your computer and use it in GitHub Desktop.
import fiona
from shapely.geometry import shape, mapping, LineString, MultiLineString
from copy import deepcopy
def split_segments(geometry, length):
"""Split a LineString into segments
Parameters
----------
geometry : shapely geometry
length : float
Returns
-------
A MultiLineString representing the original geometry split into segments.
Each segment is an individual part of the geometry.
"""
# TODO: 3D distance
# TODO: mulitlinestring input
# TODO: better exceptions
assert(length > 0.0)
coords = list(geometry.coords)
l_cur = 0.0
x_cur, y_cur = coords[0][0:2]
coords_new = [coords[0]]
lines = []
for n in range(0, len(coords)-1):
while True:
x_next, y_next = coords[n+1]
if x_cur == x_next and y_cur == y_next:
break
dx = x_next - x_cur
dy = y_next - y_cur
distance = (dx**2 + dy**2)**0.5
if distance > (length - l_cur):
x_cur += dx * (length - l_cur) / distance
y_cur += dy * (length - l_cur) / distance
coords_new.append((x_cur, y_cur))
line = LineString(coords_new)
lines.append(line)
coords_new = [(x_cur, y_cur)]
l_cur = 0.0
else:
x_cur, y_cur = x_next, y_next
l_cur += distance
coords_new.append((x_cur, y_cur))
line = LineString(coords_new)
lines.append(line)
return MultiLineString(lines)
with fiona.open('D:/tmp/syphons.shp', 'r') as src:
meta = deepcopy(src.meta)
meta['schema']['properties']['id_seg'] = 'int:10'
meta['schema']['properties']['firstX'] = 'float:10.1'
meta['schema']['properties']['firstY'] = 'float:10.1'
meta['schema']['properties']['lastX'] = 'float:10.1'
meta['schema']['properties']['lastY'] = 'float:10.1'
meta['schema']['properties']['length'] = 'float:10.3'
meta['schema']['properties']['chainage'] = 'float:10.3'
with fiona.open('output.shp', 'w', **meta) as dst:
for feature in src:
geometry = shape(feature['geometry'])
count = 0
assert(isinstance(geometry, LineString))
segments = split_segments(geometry, 50.0)
length = 0.0
for segment in segments:
feature['geometry'] = mapping(segment)
feature['properties']['id_seg'] = count + 1
feature['properties']['firstX'] = segment.coords[0][0]
feature['properties']['firstY'] = segment.coords[0][0]
feature['properties']['lastX'] = segment.coords[-1][0]
feature['properties']['lastY'] = segment.coords[-1][0]
feature['properties']['length'] = segment.length
feature['properties']['chainage'] = length
dst.write(feature)
length += segment.length
count += 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment