Return the H3 cells at a given resolution whose centers fall inside a WKT polygon.
H3_POLYFILL(polygon_wkt, resolution)
## Overview Returns the H3 cells at the requested resolution whose centers lie inside the given polygon. The polygon is provided as a WKT POLYGON string in (longitude latitude) coordinate order. This is the canonical way to rasterize a geographic region into an H3 cover: pass a polygon, get back a sorted set of cell IDs that you can then join against an H3-indexed table. Use it whenever you need to intersect a region with an H3-bucketed dataset without running a point-in-polygon test per row. The typical pattern is `polyfill -> explode -> join on h3_cell`, which pushes the spatial test to an equi-join on a BIGINT column and runs orders of magnitude faster than a geometric filter. ## Behavior - Returns an ARRAY<BIGINT> of H3 cell IDs at the requested resolution. - Coverage is center-based: a cell is included iff its geometric center falls strictly inside the polygon. Cells that overlap the boundary but whose center lies outside are not included. - Returns NULL if the polygon WKT is malformed, has fewer than 3 distinct vertices, or cannot be parsed. - Returns NULL if the resolution is outside [0, 15]. - Returns NULL if either argument is NULL. - The polygon is interpreted on the ellipsoid; very long edges are not re-projected, so at continental scale the fill may miss or include edge cells near cell-size-fraction boundaries. - Results are capped at approximately 10,000,000 cells; fills exceeding this return NULL to protect memory. - Coordinate order in WKT is (lng lat), opposite of the (lat lng) order used by H3_LATLNG_TO_CELL. ## Polyfill mode This implementation uses the center-containment mode: a cell is included if and only if its center point falls inside the polygon. Other modes that exist in the H3 specification: - **contain-all**: include a cell only if the entire cell is inside the polygon (smallest output). - **contain-centroid** (the mode used here): include a cell if its center is inside the polygon. - **cover-any**: include a cell if any part of it intersects the polygon (largest output). For exact boundary coverage, combine this function with a boundary ring from the coarser polygon and a set union. ## H3 resolution reference | Res | Average edge length | Cells per km^2 (hexagon) | | --- | --- | --- | | 7 | 1.22 km | ~0.19 | | 8 | 461 m | ~1.36 | | 9 | 174 m | ~9.5 | | 10 | 65.9 m | ~67 | | 12 | 9.4 m | ~3,260 | ## Compatibility - Follows the standard H3 hierarchical hex grid specification for polygon fill. The coverage semantics match the centroid-containment mode.
| Name | Type | Description |
|---|---|---|
polygon_wkt | Specifies the polygon to fill, as a WKT POLYGON string with (longitude latitude) coordinate order. The ring must be closed (first vertex equals last vertex) and must have at least three distinct vertices. Holes are not supported. | |
resolution | Specifies the H3 resolution of the fill cells, as an integer from 0 through 15. Finer resolutions produce more cells; expect cell count to grow as roughly 7 per resolution level. |
-- Returns every resolution 8 cell whose center falls inside the polygon.
SELECT H3_POLYFILL(
'POLYGON((-0.15 51.50, -0.15 51.52, -0.10 51.52, -0.10 51.50, -0.15 51.50))',
8
) AS cells;
-- Cell count grows with area and with resolution. Use this to estimate workload.
SELECT SIZE(H3_POLYFILL(
'POLYGON((-73.95 40.70, -73.95 40.80, -73.93 40.80, -73.93 40.70, -73.95 40.70))',
9
)) AS cell_count;
-- Intersect a polygon region with an H3-bucketed events table by exploding the polyfill.
WITH region_cells AS (
SELECT EXPLODE(H3_POLYFILL(
'POLYGON((2.29 48.86, 2.29 48.88, 2.34 48.88, 2.34 48.86, 2.29 48.86))',
9
)) AS h3_cell
)
SELECT SUM(events) AS region_events
FROM region_cells r
JOIN analytics.curated.h3_events_res9 e
ON e.h3_cell = r.h3_cell;
SELECT
SIZE(H3_POLYFILL('POLYGON((139.60 35.65, 139.60 35.70, 139.75 35.70, 139.75 35.65, 139.60 35.65))', 8)) AS res8_cells,
SIZE(H3_POLYFILL('POLYGON((139.60 35.65, 139.60 35.70, 139.75 35.70, 139.75 35.65, 139.60 35.65))', 9)) AS res9_cells;
-- An unclosed ring or fewer than 3 vertices returns NULL.
SELECT H3_POLYFILL('POLYGON((0 0, 1 0))', 8) AS cells;