Skip to main content

H3 Bound Cells

https://pypi.org/project/h3_bound_cells/

Convert geographic polygons into multi-resolution H3 cell coverings, with fast point-in-region lookups.

Rust core is built on h3o and exposed to Python via PyO3 / Maturin.

Generation uses h3-compactfill which is an extension to H3 which implements a short-circuited polygonToCells + compact Algorithm.

Overview

BoundCells holds a Compacted Polyfill of a target Polygon, keyed by H3 Resolution.

Generation - Fairly standard polyfill+compact step which converts a Polygon into contained H3 Cells. Start Resolution - This is the finest (highest) Resolution of the Cells, this is needed at cell edges to get a closer match to the polygon. Containment - Walks a datasets H3 Cells (checking each from fine->coarse) against the BoundCells for containment predicate. Prefilter allows for Parquet Predicate Pushdown which can Prune Row Groups by checking against Cell Index Ranges.

Install

The package is built locally with maturin: uv run maturin develop --release

Usage

import h3
from h3_bound_cells import polygon_to_bound_cells, cell_in_bound_cells, BoundCells

# Rectangle around central London. (lat, lng) pairs; the ring need not be closed.
exterior = [
    (51.50, -0.13),
    (51.52, -0.13),
    (51.52, -0.08),
    (51.50, -0.08),
]

bc = polygon_to_bound_cells(exterior, start_res=9)

print(bc)
# BoundCells(cells={8: 9, 9: 5, ...})

for res, cells in bc.cells.items():
    print(f"res {res}: {len(cells)} cells")

# Point-in-region check: Trafalgar Square at H3 resolution 11.
cell = h3.latlng_to_cell(51.5074, -0.1278, 11)
assert cell_in_bound_cells(cell, bc)

# JSON-friendly round trip
restored = BoundCells.from_dict(bc.to_dict())

API

  • polygon_to_bound_cells(exterior, holes=None, start_res=None, containment_mode=None, tolerance=None) -> BoundCells
    • exterior, holes — lists of (lat, lng) tuples. Note: this is (latitude, longitude), matching the H3 convention (e.g. h3.latlng_to_cell) — the reverse of GeoJSON/shapely/WKT, which use (longitude, latitude). Swap the order when feeding in GeoJSON coordinates.
    • start_res — H3 resolution to tile at. When omitted, it is auto-picked from the polygon's planar area.
    • containment_mode — a BCContainmentMode selecting which cells the fill keeps (default BCContainmentMode.ContainsCentroid). See BCContainmentMode below.
    • tolerance — Douglas–Peucker simplification distance in degrees, applied to the polygon before tiling. Tiling cost is linear in vertex count, so simplifying high-fidelity boundaries (e.g. OS/OSM data with metre-scale vertices) is a large speed-up. Defaults to 0 — no simplification, an exact covering identical to the raw geometry. Pass a small positive value (e.g. 1e-5, ≈1 m, for a ~5× speed-up on detailed boundaries) to opt in. Note that any non-zero tolerance is effectively-lossless rather than provably identical: a cell whose centroid lies within ~tolerance of the boundary can flip. Larger values are faster but shift more such edge cells.
  • cells_to_bound_cells(cells) -> BoundCells
    • Build a covering directly from an existing set of H3 cells, skipping polygon tiling. cells is an iterable of H3 cells as hex strings or u64 ints.
    • Input must be at a single resolution (mixed resolutions raise ValueError); duplicates are de-duplicated. An empty input yields an empty covering.
  • cell_in_bound_cells(cell: str, bound_cells: BoundCells) -> bool — membership test by H3 cell id.
  • BCContainmentMode — enum choosing which cells a polygon fill keeps (mirrors h3o's ContainmentMode):
    • ContainsCentroid (default) — cell kept when its centroid is inside. Fast, approximate interior.
    • ContainsBoundary — cell kept only when fully inside. Strict interior — no false positives, but omits edge cells only partly inside.
    • IntersectsBoundary — cell kept when it touches the polygon. Produces a superset covering that extends past the edge.
    • Covers — like IntersectsBoundary, also handling polygons smaller than a cell. Also a superset.
    • ⚠️ The overlap modes (IntersectsBoundary, Covers) make the covering a conservative superset, so cell_in_bound_cells then means "overlaps the region" and can report cells lying outside the polygon as inside. Use them when you want a covering, not exact point-in-region.
  • BoundCells — frozen class:
    • .cells — dict[str, list[str]] keyed by resolution.
    • .to_dict() / BoundCells.from_dict(d) — JSON-friendly round trip.
    • BoundCells.merge([bc1, bc2, ...]) — union of multiple results.
    • .cells_at_resolution(res) — flatten/expand the covering to a single H3 resolution (parents map up, coarser cells expand to their children).

Polars integration (optional)

Filter a Polars DataFrame/LazyFrame down to the rows whose H3 cell falls inside a covering.

Install the optional polars extra:

pip install h3_bound_cells[polars]

Importing h3_bound_cells registers a bound_cells namespace on Polars expressions (only registered when polars is installed):

import polars as pl
import h3_bound_cells  # registers the bound_cells namespace

bc = h3_bound_cells.polygon_to_bound_cells(exterior, start_res=9)

df = pl.DataFrame({"cell": [...]})  # H3 cells as hex strings or u64 ints

# Filter to rows inside the covering:
df.filter(pl.col("cell").bound_cells.is_in(bc))

# Or use the boolean result as a column:
df.with_columns(inside=pl.col("cell").bound_cells.is_in(bc))
  • pl.col(cell_column).bound_cells.is_in(bound_cells) — a boolean expression, true where the cell lies inside bound_cells.
  • Use it anywhere an expression is accepted (filter, select, with_columns, boolean combinations, …).
  • Works with both eager and lazy frames. Cells may be hex strings or u64 ints; a null cell maps to false (dropped by filter).

Predicate Pushdown (Parquet)

is_in is a native plugin, so the query optimiser can't see through it to prune a scan on its own. To fix that, is_in ANDs a pure H3-index range predicate in front of the exact check (prefilter=True, on by default). Because an H3 index sorts identically as a u64 and as its 15-char hex string, Polars can push that range test into a Parquet SCAN and skip whole row groups via their min/max statistics — often a large speed-up on big scans, with an identical result. The exact plugin check still runs, so correctness is unchanged.

This is ONLY recommended in Lazy Execution as it provides purely IO-bound wins, with a collected DataFrame there is no scan to prune so this then just becomes and additional filter to run.

lf = pl.scan_parquet("atlas.parquet")  # sorted by the H3 column

# UInt64 cell column (default dtype):
lf.filter(pl.col("h3").bound_cells.is_in(bc))

# Canonical 15-char hex-string cell column:
lf.filter(pl.col("h3point").bound_cells.is_in(bc, dtype=pl.Utf8))

For the prefilter to be correct and effective:

  • Resolution — by default the range predicate covers every resolution, so it is correct whatever resolution the column is at. If you know it, pass child_res=<res> (e.g. child_res=15) for the leanest predicate; the extra ranges of the default sit in empty u64 regions for a uniform-resolution column, so they don't weaken pruning either way.
  • Matching dtype — dtype must match the column: pl.UInt64 (default) for an integer column, or pl.Utf8 for a canonical 15-char lowercase-hex string column.
  • Sorted column — row-group skipping is dramatic only when the column is sorted (tight per-group min/max). On unsorted data the prefilter still trims per-row plugin cost but skips no row groups.

Pass prefilter=False for the exact-only behaviour.

Release files for h3_bound_cells 0.5.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for h3_bound_cells 0.5.2
File Size Uploaded
h3_bound_cells-0.5.2.tar.gz 69.5 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for h3_bound_cells 0.5.2
File
h3_bound_cells-0.5.2-cp39-abi3-win_arm64.whl CPython 3.9 abi3 Windows ARM64 Details
h3_bound_cells-0.5.2-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details
h3_bound_cells-0.5.2-cp39-abi3-win32.whl CPython 3.9 abi3 Windows x86-32 Details
h3_bound_cells-0.5.2-cp39-abi3-musllinux_1_2_x86_64.whl CPython 3.9 abi3 Linux musl 1.2+ x86-64 Details
h3_bound_cells-0.5.2-cp39-abi3-musllinux_1_2_i686.whl CPython 3.9 abi3 Linux musl 1.2+ x86-32 Details
h3_bound_cells-0.5.2-cp39-abi3-musllinux_1_2_aarch64.whl CPython 3.9 abi3 Linux musl 1.2+ ARM64 Details
h3_bound_cells-0.5.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.9 abi3 Linux glibc 2.17+ x86-64 Details
h3_bound_cells-0.5.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.9 abi3 Linux glibc 2.17+ ARM64 Details
h3_bound_cells-0.5.2-cp39-abi3-manylinux_2_12_i686.manylinux2010_i686.whl CPython 3.9 abi3 Linux glibc 2.12+ x86-32 Details
h3_bound_cells-0.5.2-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details

Total release size: 47.1 MB

Release files / h3_bound_cells-0.5.2.tar.gz

Download URL h3_bound_cells-0.5.2.tar.gz
Size 69.5 kB
Tags Source
SHA-256 checksum
How to use checksums
392160b3e196d6a8ce846b1d064f8d640a9857925a4824faef16d1c792e0303f
BLAKE2b-256 checksum
How to use checksums
67c98af56198a20a7f4c49f861cd3be2e10b061bf07b606e62fcd936c4b8d4b3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / h3_bound_cells-0.5.2-cp39-abi3-win_arm64.whl

Download URL h3_bound_cells-0.5.2-cp39-abi3-win_arm64.whl
Size 4.2 MB
Tags CPython 3.9 Windows ARM64 abi3
SHA-256 checksum
How to use checksums
701cc329a3166285072bb92065492150b17c357493eb3a4068fb19dfafc72e55
BLAKE2b-256 checksum
How to use checksums
d44f9b4d7db3516b7e3829dcfa8d0926bd583d9a184b56f22468aa10f998a914
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / h3_bound_cells-0.5.2-cp39-abi3-win_amd64.whl

Download URL h3_bound_cells-0.5.2-cp39-abi3-win_amd64.whl
Size 4.7 MB
Tags CPython 3.9 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
f978c6175226b77c42ee4a4865beb2d26c30b08d6af5c3e6f9d1ac732da2004e
BLAKE2b-256 checksum
How to use checksums
d56f9ff1edf369de119f7eca8e812380b49037ebf85d2b0681b36c534f41214a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / h3_bound_cells-0.5.2-cp39-abi3-win32.whl

Download URL h3_bound_cells-0.5.2-cp39-abi3-win32.whl
Size 4.2 MB
Tags CPython 3.9 Windows x86-32 abi3
SHA-256 checksum
How to use checksums
a7e72dd8dc8989f108202dd63d6636628858ea75d1f388055aff0829c0005fc7
BLAKE2b-256 checksum
How to use checksums
26e95273c6b9af1f16e44c5df26e22cdc66acea24486ca24f61f84f84bb97999
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / h3_bound_cells-0.5.2-cp39-abi3-musllinux_1_2_x86_64.whl

Download URL h3_bound_cells-0.5.2-cp39-abi3-musllinux_1_2_x86_64.whl
Size 5.0 MB
Tags CPython 3.9 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
e65d4dd14a6d415fbac7730809d7313f5a80adbdf81b6ac9826956c6a1150c54
BLAKE2b-256 checksum
How to use checksums
27715d15bcd8fc7d161f301382ebb3a4c6a68589d31f12695e809e8d6bb7ce5a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / h3_bound_cells-0.5.2-cp39-abi3-musllinux_1_2_i686.whl

Download URL h3_bound_cells-0.5.2-cp39-abi3-musllinux_1_2_i686.whl
Size 5.3 MB
Tags CPython 3.9 Linux musl 1.2+ x86-32 abi3
SHA-256 checksum
How to use checksums
60b313d291b23443591b2c0f0212adc0c6e74100a6e42a046ad56a3916190aab
BLAKE2b-256 checksum
How to use checksums
b8a5edad25217022762fe13e0afac5beb1e28dda3897f962e2a7ba9cdf65f989
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / h3_bound_cells-0.5.2-cp39-abi3-musllinux_1_2_aarch64.whl

Download URL h3_bound_cells-0.5.2-cp39-abi3-musllinux_1_2_aarch64.whl
Size 4.7 MB
Tags CPython 3.9 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
9f7e4f83f4f6673c0045eebcb935efbeba9aee4d384f37efc4f13a3f5940e34d
BLAKE2b-256 checksum
How to use checksums
d91f67ef869cb4a6bbb5a84c89e99db39d33e725e816643368e3c1ca8a18bc40
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / h3_bound_cells-0.5.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL h3_bound_cells-0.5.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 4.8 MB
Tags CPython 3.9 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
b028f31f59e6d0305443abb90f7cb795873e5815db9c47dd3123dfcd7029cf0d
BLAKE2b-256 checksum
How to use checksums
f510b7485ff0b55bcd643a4bc7bc7e936d0c21cbba91baa821fdb56e0606fef4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / h3_bound_cells-0.5.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL h3_bound_cells-0.5.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 4.5 MB
Tags CPython 3.9 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
829f07dc4ecc4b99c614595043e1251b8978e5da017c50de7b5d2b9d50650dca
BLAKE2b-256 checksum
How to use checksums
6eb3fdb9c78fb7a5566f3e06311b7bcdf1688d0ff2a0530cdbdb9d2849925b4c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / h3_bound_cells-0.5.2-cp39-abi3-manylinux_2_12_i686.manylinux2010_i686.whl

Download URL h3_bound_cells-0.5.2-cp39-abi3-manylinux_2_12_i686.manylinux2010_i686.whl
Size 5.2 MB
Tags CPython 3.9 Linux glibc 2.12+ x86-32 abi3
SHA-256 checksum
How to use checksums
021e968c1683554b3569e6002df793060e60b3f5d3725573b6564e64cbc1c8e0
BLAKE2b-256 checksum
How to use checksums
1e30913eb24c0df99ba40518c9263a1fff7e50277e9a155d12960a6e9074a90b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / h3_bound_cells-0.5.2-cp39-abi3-macosx_11_0_arm64.whl

Download URL h3_bound_cells-0.5.2-cp39-abi3-macosx_11_0_arm64.whl
Size 4.3 MB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
321d08755f4bc7236635d56a6cc1b825592d30d374bd5f81494471af5f9d1d0d
BLAKE2b-256 checksum
How to use checksums
f0b480ef7788250fcaf6ed6632f9ecf641ec7f4c517b900925b39667549eef55
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.5.3

11 release files

This release

0.5.2 This release

11 release files

0.5.1

11 release files

0.5.0

11 release files

0.4.1

11 release files

0.3.1

11 release files

0.3.0

11 release files

0.2.2

11 release files

0.2.1

11 release files

0.2.0

11 release files

0.1.5

92 release files

0.1.4

92 release files

0.1.3

92 release files

0.1.2

92 release files

0.1.0

92 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page