Created
February 15, 2020 22:55
-
-
Save underchemist/9630c743fed9801311d02fdd3f15dcb9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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