-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ENH: Support LineStrings #11
Comments
I was just working on an H3 demo for a GIS forum, and wanted to demonstrate this. Came up with: from shapely.geometry.linestring import LineString
from typing import Iterator
def sequential_deduplication(func: Iterator[str]) -> Iterator[str]:
'''
Decorator that doesn't permit two consecutive items to be the same
'''
def inner(*args):
iterable = func(*args)
last = None
while (cell := next(iterable, None)) is not None:
if cell != last:
yield cell
last = cell
return inner
@sequential_deduplication # prevent consecutive repetition, esp. at low res
def h3polyline(line: LineString, resolution: int) -> Iterator[str]:
'''
Iterator yielding H3 cells representing a line,
retaining order and any self-intersections
'''
coords = zip(line.coords, line.coords[1:])
while (vertex_pair := next(coords, None)) is not None:
i, j = vertex_pair
a = h3.geo_to_h3(*i[::-1], resolution)
b = h3.geo_to_h3(*j[::-1], resolution)
yield from h3.h3_line(a, b) # inclusive of a and b Just thought it might help someone. I'm not sure there's any particular advantage doing this with generators, unless/until Not sure what is supposed to happen with repeated cells, but intuitively I thought it made sense to attempt to retain order and self-intersections rather than to just return an unordered set. Doesn't consider MultiLineStrings. |
Version 2, adding multilinestring as valid input type. from shapely.geometry.linestring import LineString
from shapely.geometry.multilinestring import MultiLineString
from typing import Iterator, Union
def sequential_deduplication(func: Iterator[str]) -> Iterator[str]:
'''
Decorator that doesn't permit two consecutive items to be the same
'''
def inner(*args):
iterable = func(*args)
last = None
while (cell := next(iterable, None)) is not None:
if cell != last:
yield cell
last = cell
return inner
@sequential_deduplication
def h3polyline(line: Union[LineString, MultiLineString], resolution: int) -> Iterator[str]:
'''
Iterator yeilding H3 cells representing a (multi)line,
retaining order and self-intersections
'''
if line.geom_type == 'MultiLineString':
# Recurse after getting component linestrings from the multiline
for l in map(lambda geom: h3polyline(geom, resolution), line.geoms):
yield from l
else:
coords = zip(line.coords, line.coords[1:])
while (vertex_pair := next(coords, None)) is not None:
i, j = vertex_pair
a = h3.geo_to_h3(*i[::-1], resolution)
b = h3.geo_to_h3(*j[::-1], resolution)
yield from h3.h3_line(a, b) # inclusive of a and b |
A great feature of the hexagonal shape of H3 is how naturally it can delineate LineStrings such as roads, rivers in a connected and visually pleasing way.
It would thus make sense to provide a method that would provide a "linestring
polyfill
", generating a continuous string of H3 cells that cover the linestring. This could be done in two steps:geo_to_h3
h3_line
The interface and implementation could be similar to other similar methods, e.g.
polyfill
The text was updated successfully, but these errors were encountered: