Skip to content

Instantly share code, notes, and snippets.

@underchemist
Created February 15, 2020 22:55
Show Gist options
  • Save underchemist/9630c743fed9801311d02fdd3f15dcb9 to your computer and use it in GitHub Desktop.
Save underchemist/9630c743fed9801311d02fdd3f15dcb9 to your computer and use it in GitHub Desktop.
LINEAR_GEOMS = (shapely.geometry.LineString, shapely.geometry.LinearRing)
VALID_GEOMS = (*LINEAR_GEOMS, shapely.geometry.Polygon)
def linspace(start, stop, n):
assert n >= 0
try:
step = (stop - start) / (n-1)
except ZeroDivisionError:
step = 0
return [start + step * i for i in range(n)]
def lines_to_coords(lines):
return [coord for line in lines for coord in line.coords]
def vertices(geom):
if isinstance(geom, shapely.geometry.base.BaseMultipartGeometry):
raise TypeError("Multi part geometries are not supported")
return shapely.geometry.MultiLineString(list(pairwise(geom.coords)))
def _segmentize_line(line, n):
"""Segmentize a LineString by interpolating"""
starts = linspace(0., line.length, n)
points = [line.interpolate(start) for start in starts]
return shapely.geometry.LineString(points)
def _segmentize_shape(geom, n):
"""Segmentize a list of vertices"""
dense_shape = [_segmentize_line(line, n) for line in geom]
return lines_to_coords(dense_shape)
def _segmentize_linear_geom(geom, n):
"""Segmentize a linear geometry"""
starts = linspace(0., geom.length, n+1)
points = [geom.interpolate(start) for start in starts]
line = shapely.geometry.LineString(points)
return line
def segmentize(geom, n=200):
geom_type = type(geom)
if isinstance(geom, LINEAR_GEOMS):
starts = linspace(0.0, geom.length, n+1)
points = [geom.interpolate(start) for start in starts]
line = shapely.geometry.LineString(points)
return geom_type(line)
elif isinstance(geom, shapely.geometry.Polygon):
ext = geom.exterior
ints = geom.interiors
return geom_type(
segmentize(ext, n=n),
holes=[segmentize(i, n=n) for i in ints]
)
else:
raise TypeError("Only LineString, LinearRing, and Polygon geometries can be segmentized")
def segmentize2(geom, n=200):
assert isinstance(geom , VALID_GEOMS), \
"Only LineString, LinearRing, and Polygon geometries can be segmentized"
geom_type = type(geom)
dense_shapes = []
for g in iter_geom(geom):
starts = linspace(0.0, geom.length, n+1)
points = [g.interpolate(start) for start in starts]
line = shapely.geometry.LineString(points)
dense_shapes.append(line)
idense_shapes = iter(dense_shapes)
ext = next(idense_shapes)
ints = list(idense_shapes)
args = [ext]
if ints:
args += [ints]
return geom_type(*args)
def iter_geom(geom):
"""yield geometry if linear else yield exterior ring followed by interior ring(s)"""
if isinstance(geom, shapely.geometry.Polygon):
geoms = [geom.exterior] + list(geom.interiors)
else:
geoms = [geom]
for g in geoms:
yield g
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment