h3-py
h3-py copied to clipboard
v4 Python Bindings: h3.Polygon has no "len()"
h3.polygon_to_cells requires an h3 polygon input.
I get the following error when running h3.polygon_to_cells on an polygon, however: TypeError: object of type 'Polygon' has no len()
I see that there is a no length variable tied to the h3.Polygon object, but there is a value for lengh under Polygon.outer.length
This prevents me from doing any type of polyfill-ing (er, i mean polygon_to_cells-ifying)

Thanks for the report! It is definitely an experimental object, so I'm happy to hear any and all feedback you have about your experience using it!
What version of Python are you using? Is this a runtime error or a type-checking error?
@KcTheMapper Are you trying to pass in a shapely polygon? I assume h3 only supports geojson-like coordinates
Hey @ajfriend, I appreciate your attention to this!
I am using Python Version 3.9.6, h3 version 4 The error I am receiving is a Type-Error: "TypeError: object of type 'Polygon' has no len()"
@kylebarron I am trying to pass in an h3 polygon, which appears to be the only acceptable poly to pass into in v4.
Apologies; I haven't followed the API changes in v4 and didn't know there was a new Polygon class
@kylebarron no worries! All these changes have thrown me for quite the loop as well
Can you share a code snippet that gives you this error? The following works for me:
import h3
poly = h3.Polygon(
[(37.68, -122.54), (37.68, -122.34), (37.82, -122.34), (37.82, -122.54)],
[(37.76, -122.51), (37.76, -122.44), (37.81, -122.51)],
)
h3.polygon_to_cells(poly, 6)
I can reproduce your error if I call len(poly)
, but I'm not sure if len()
even makes sense for an h3.Polygon
object. How would we define it? Number of holes? Total number of lat/lng points?
I'm curious what bit of your code might be trying to call len()
.
And it is true that Polygon is currently the only acceptable input for polygon_to_cells
. I hope to add GeoJSON functionality to the next beta release to get feature parity with v3 (which will basically just convert the GeoJSON to an h3.Polygon
or list of them and pass that off to polygon_to_cells
).
Also, the h3.Polygon
class was an experiment to clean up the API. It definitely isn't set in stone, and I would love any feedback or alternative proposals you might have.
I'm encountering the same issue on h3==4.0.0b2
running in Python 3.10.8
. Here's the code to reproduce
import geopandas as gpd
import h3
path = gpd.datasets.get_path('nybb')
df = gpd.read_file(path).to_crs(epsg=4326)
# finding largest polygon in multipolygon
polygon = max(df.loc[0, "geometry"].geoms, key=lambda a: a.area)
assert isinstance(polygon, shapely.geometry.polygon.Polygon)
h3_poly = h3.Polygon(polygon)
assert isinstance(h3_poly, h3.Polygon)
# raises "TypeError: object of type 'Polygon' has no len()"
h3.polygon_to_cells(h3_poly, 9)
Stack Trace:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[58], line 10
8 h3_poly = h3.Polygon(polygon)
9 assert isinstance(h3_poly, h3.Polygon)
---> 10 h3.polygon_to_cells(h3_poly, 9)
File [~/.pyenv/versions/3.10.8/envs/crash-data-extraction-3.10/lib/python3.10/site-packages/h3/api/_api_template.py:429](https://file+.vscode-resource.vscode-cdn.net/Users/sergey/Coding/business/three-sigma-etl/src/risk_score/notebooks/~/.pyenv/versions/3.10.8/envs/crash-data-extraction-3.10/lib/python3.10/site-packages/h3/api/_api_template.py:429), in _API_FUNCTIONS.polygon_to_cells(self, polygon, res)
400 def polygon_to_cells(self, polygon, res):
401 """
402 Return the set of H3 cells at a given resolution whose center points
403 are contained within a `h3.Polygon`
(...)
427 '86283095fffffff'}
428 """
--> 429 mv = _cy.polygon_to_cells(polygon.outer, res, holes=polygon.holes)
431 return self._out_unordered(mv)
File geo.pyx:160, in h3._cy.geo.polygon_to_cells()
File geo.pyx:108, in h3._cy.geo.GeoPolygon.__cinit__()
File geo.pyx:71, in h3._cy.geo.make_geoloop()
TypeError: object of type 'Polygon' has no len()
I was able to fix it by changing
# h3_poly = h3.Polygon(polygon)
h3_poly = h3.Polygon(polygon.exterior.coords)
My first thought is maybe this has something do with holes? When I print the working code I see
>>> h3_poly
<h3.Polygon |outer|=8877, |holes|=()>
Attempting to print the non working one returns an error (although it initializes with no issues).
>>> h3_poly
File [~/.pyenv/versions/3.10.8/envs/crash-data-extraction-3.10/lib/python3.10/site-packages/h3/_polygon.py:52](https://file+.vscode-resource.vscode-cdn.net/Users/sergey/Coding/business/three-sigma-etl/src/risk_score/notebooks/~/.pyenv/versions/3.10.8/envs/crash-data-extraction-3.10/lib/python3.10/site-packages/h3/_polygon.py:52), in Polygon.__repr__(self)
50 def __repr__(self):
51 s = '<h3.Polygon |outer|={}, |holes|={}>'.format(
---> 52 len(self.outer),
53 tuple(map(len, self.holes)),
54 )
56 return s
TypeError: object of type 'Polygon' has no len()
I don't totally understand this behavior but it seems like a foot gun.
@KcTheMapper Are you trying to pass in a shapely polygon? I assume h3 only supports geojson-like coordinates
it is quite the opposite. shapely
IS "geojson"-compliant, but h3.Polygon
is the opposite.
the whole difference is lon,lat
vs lat,lon
. the X,Y
vs Y,X
.
@ajfriend may i ask you to speed up that "geojson" support? i started with 4.0.0b2
last week and now i have to write a bunch of xy-yx
conversion code. this is a bit inconvenient
Ah, thanks for the info @spawn-guy! Indeed the old xy vs yx order seems to be at the root of my trouble.
I'm really not liking working with the h3.Polygon (with inners and outters) class. But i bet I could find some examples with which to better acquaint myself.
Thanks @Filimoa! That's getting me in a closer direction so it seems.
@spawn-guy @KcTheMapper Thanks for the feedback on this! Apologies that I've let this languish in beta for so long. I'm hoping to get back into active development.
That being said, please do keep the feedback coming around the h3.Polygon
class! It is very much an experiment with the interface, and we can change it now while we're in still beta. But we'll be stuck with whatever's in the final release. @KcTheMapper, what would feel more ergonomic to you?
@ajfriend well, you asked for it 😅
Why not just implement the __geo_interface__
?! In the way python describes it. I see this link in my Google https://gist.github.com/sgillies/2217756
I think, most of the current py geo tools support this. What do you think?
@spawn-guy, I'm glad I did ask for it! This is great! 😄
I wasn't aware of the interface, but the fact that it seems pretty much standard makes things easier.