Skip to content

Commit

Permalink
split out experimental function to new function
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacbrodsky committed Dec 24, 2024
1 parent 4111529 commit 7f6c76a
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 41 deletions.
8 changes: 8 additions & 0 deletions src/h3/_h3shape.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
from abc import ABCMeta, abstractmethod
from enum import Enum


class ContainmentMode(int, Enum):
containment_center = 0
containment_full = 1
containment_overlapping = 2
containment_overlapping_bbox = 3


class H3Shape(metaclass=ABCMeta):
Expand Down
103 changes: 83 additions & 20 deletions src/h3/api/basic_int/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from ... import _cy
from ..._h3shape import (
ContainmentMode,
H3Shape,
LatLngPoly,
LatLngMultiPoly,
Expand Down Expand Up @@ -467,7 +468,7 @@ def uncompact_cells(cells, res):
return _out_collection(hu)


def h3shape_to_cells(h3shape, res, flags=0, experimental=False):
def h3shape_to_cells(h3shape, res):
"""
Return the collection of H3 cells at a given resolution whose center points
are contained within an ``LatLngPoly`` or ``LatLngMultiPoly``.
Expand All @@ -477,10 +478,6 @@ def h3shape_to_cells(h3shape, res, flags=0, experimental=False):
h3shape : ``H3Shape``
res : int
Resolution of the output cells
flags : int
Containment mode flags
experimental : bool
Whether to use experimental algorithm.
Returns
-------
Expand Down Expand Up @@ -510,21 +507,10 @@ def h3shape_to_cells(h3shape, res, flags=0, experimental=False):
# todo: not sure if i want this dispatch logic here. maybe in the objects?
if isinstance(h3shape, LatLngPoly):
poly = h3shape
if experimental:
mv = _cy.polygon_to_cells_experimental(
poly.outer,
res=res,
holes=poly.holes,
flags=flags
)
else:
mv = _cy.polygon_to_cells(poly.outer, res=res, holes=poly.holes)
mv = _cy.polygon_to_cells(poly.outer, res=res, holes=poly.holes)
elif isinstance(h3shape, LatLngMultiPoly):
mpoly = h3shape
if experimental:
mv = _cy.polygons_to_cells_experimental(mpoly.polys, res=res, flags=flags)
else:
mv = _cy.polygons_to_cells(mpoly.polys, res=res)
mv = _cy.polygons_to_cells(mpoly.polys, res=res)
elif isinstance(h3shape, H3Shape):
raise ValueError('Unrecognized H3Shape: ' + str(h3shape))
else:
Expand All @@ -533,11 +519,88 @@ def h3shape_to_cells(h3shape, res, flags=0, experimental=False):
return _out_collection(mv)


def polygon_to_cells(h3shape, res, flags=0, experimental=False):
def polygon_to_cells(h3shape, res):
"""
Alias for ``h3shape_to_cells``.
"""
return h3shape_to_cells(h3shape, res, flags=flags, experimental=experimental)
return h3shape_to_cells(h3shape, res)


def h3shape_to_cells_experimental(h3shape, res, flags=0):
"""
Return the collection of H3 cells at a given resolution whose center points
are contained within an ``LatLngPoly`` or ``LatLngMultiPoly``.
Parameters
----------
h3shape : ``H3Shape``
res : int
Resolution of the output cells
flags : int or string
Containment mode flags
Returns
-------
list of H3Cell
Examples
--------
>>> poly = LatLngPoly(
... [(37.68, -122.54), (37.68, -122.34), (37.82, -122.34),
... (37.82, -122.54)],
... )
>>> h3.h3shape_to_cells_experimental(poly, 6, 'containment_center')
['862830807ffffff',
'862830827ffffff',
'86283082fffffff',
'862830877ffffff',
'862830947ffffff',
'862830957ffffff',
'86283095fffffff']
Notes
-----
There is currently no guaranteed order of the output cells.
"""

if isinstance(flags, str):
try:
flags = ContainmentMode[flags]
except KeyError as e:
raise ValueError('Unrecognized flags: ' + flags) from e
if isinstance(flags, ContainmentMode):
flags = int(flags)
if not isinstance(flags, int):
raise ValueError(
'Flags should be ContainmentMode, str, or int, but got: ' + str(type(flags))
)

# todo: not sure if i want this dispatch logic here. maybe in the objects?
if isinstance(h3shape, LatLngPoly):
poly = h3shape
mv = _cy.polygon_to_cells_experimental(
poly.outer,
res=res,
holes=poly.holes,
flags=flags
)
elif isinstance(h3shape, LatLngMultiPoly):
mpoly = h3shape
mv = _cy.polygons_to_cells_experimental(mpoly.polys, res=res, flags=flags)
elif isinstance(h3shape, H3Shape):
raise ValueError('Unrecognized H3Shape: ' + str(h3shape))
else:
raise ValueError('Unrecognized type: ' + str(type(h3shape)))

return _out_collection(mv)


def polygon_to_cells_experimental(h3shape, res, flags=0):
"""
Alias for ``h3shape_to_cells_experimental``.
"""
return h3shape_to_cells_experimental(h3shape, res, flags=flags)


def cells_to_h3shape(cells, *, tight=True):
Expand Down
63 changes: 42 additions & 21 deletions tests/polyfill/test_h3.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,43 +119,64 @@ def test_polygon_to_cells():

def test_polygon_to_cells_experimental():
poly = h3.LatLngPoly(sf_7x7)
# Note that `polygon_to_cells` is an alias for `h3shape_to_cells`
out = h3.polygon_to_cells(poly, res=9, flags=0, experimental=True)
for flags in [0, 'containment_center', h3.ContainmentMode.containment_center]:
# Note that `polygon_to_cells` is an alias for `h3shape_to_cells`
out = h3.polygon_to_cells_experimental(poly, res=9, flags=flags)

assert len(out) == 1253
assert '89283080527ffff' in out
assert '89283095edbffff' in out
assert len(out) == 1253
assert '89283080527ffff' in out
assert '89283095edbffff' in out


def test_polygon_to_cells_experimental_full():
poly = h3.LatLngPoly(sf_7x7)
# Note that `polygon_to_cells` is an alias for `h3shape_to_cells`
out = h3.polygon_to_cells(poly, res=9, flags=1, experimental=True)
for flags in [1, 'containment_full', h3.ContainmentMode.containment_full]:
# Note that `polygon_to_cells` is an alias for `h3shape_to_cells`
out = h3.polygon_to_cells_experimental(poly, res=9, flags=flags)

assert len(out) == 1175
assert '89283082a1bffff' in out
assert '89283080527ffff' not in out
assert '89283095edbffff' in out
assert len(out) == 1175
assert '89283082a1bffff' in out
assert '89283080527ffff' not in out
assert '89283095edbffff' in out


def test_polygon_to_cells_experimental_overlapping():
poly = h3.LatLngPoly(sf_7x7)
# Note that `polygon_to_cells` is an alias for `h3shape_to_cells`
out = h3.polygon_to_cells(poly, res=9, flags=2, experimental=True)
for flags in [
2,
'containment_overlapping',
h3.ContainmentMode.containment_overlapping
]:
# Note that `polygon_to_cells` is an alias for `h3shape_to_cells`
out = h3.polygon_to_cells_experimental(poly, res=9, flags=flags)

assert len(out) == 1334
assert '89283080527ffff' in out
assert '89283095edbffff' in out
assert len(out) == 1334
assert '89283080527ffff' in out
assert '89283095edbffff' in out


def test_polygon_to_cells_experimental_overlapping_bbox():
poly = h3.LatLngPoly(sf_7x7)
# Note that `polygon_to_cells` is an alias for `h3shape_to_cells`
out = h3.polygon_to_cells(poly, res=9, flags=3, experimental=True)
for flags in [
3,
'containment_overlapping_bbox',
h3.ContainmentMode.containment_overlapping_bbox
]:
# Note that `polygon_to_cells` is an alias for `h3shape_to_cells`
out = h3.polygon_to_cells_experimental(poly, res=9, flags=flags)

assert len(out) == 1416
assert '89283080527ffff' in out
assert '89283095edbffff' in out
assert len(out) == 1416
assert '89283080527ffff' in out
assert '89283095edbffff' in out


def test_polygon_to_cells_experimental_invalid_mode():
poly = h3.LatLngPoly(sf_7x7)
for flags in [1.0, 'containment_overlapping_bbox_abc', None]:
with pytest.raises(ValueError):
print(flags)
# Note that `polygon_to_cells` is an alias for `h3shape_to_cells`
h3.polygon_to_cells_experimental(poly, res=9, flags=flags)


def test_polyfill_with_hole():
Expand Down

0 comments on commit 7f6c76a

Please sign in to comment.