All sections

H3 To Equal Area Circle

Approximating an H3 cell with a disk of the same area for reach and planning estimates, with no containment guarantee in either direction

approximatestableh35 min read
Source geometry
h3_cell_set
Destination geometry
point_radius

Purpose

Planning tools — reach estimators, budget allocators, market-sizing dashboards — often need a single representative circle per cell whose area matches the cell, without caring whether that circle sits inside or outside the true boundary. The equal-area circle is that construction. It is the right tool for area-weighted reach math and the wrong tool for anything that will be executed as a real target, because it makes no containment claim at all.

Source geometry and destination geometry

Source is an h3_cell_set, one circle computed per cell. Destination is point_radius: a center latitude/longitude and a radius in meters, one pair per input cell.

Definition

Center is the H3 cell center. Radius is derived directly from cell area, with no boundary sampling at all:

r=cell areaπr = \sqrt{\frac{\text{cell area}}{\pi}}

where cell area is cellArea(cell, "m2"), the h3-js spherical-model area of the true cell. No SAFETY_MARGIN, no edge densification, and no distance-to-boundary computation is involved — this is the only one of the three circle constructions that does not touch the cell's boundary geometry at all.

Containment guarantee — there is none

No exact containment, in either direction

The equal-area circle is not a subset of the cell and the cell is not a subset of the circle. Because a disk and a hexagon are different shapes, matching their areas forces the disk to extend beyond the hexagon's edges in some directions (near the edge midpoints, where the hexagon is "thinnest" relative to a disk of the same area) while falling short of the hexagon's corners in others. Gaps and overlaps exist simultaneously in the same circle, not as alternative failure modes — this is the defining property of the construction, not an edge case of it.

Resolution behavior

Radius scales with sqrt(cell area), and cell area shrinks by exactly 7× per resolution step in H3's aperture-7 hierarchy, so radius shrinks by sqrt(7) ≈ 2.65× per step — identical scaling behavior to the inscribed and circumscribed radii. The simultaneous-gap-and-overlap property is scale-invariant: it is a function of matching a disk's area to a hexagon's area, independent of how large either one is.

Units and CRS

Center is [lat, lng] (h3-js native order), EPSG:4326. cellArea uses h3-js's spherical model; the radius derived from it is therefore a spherical-model radius, consistent with the inscribed and circumscribed constructions but not with an ellipsoidal (WGS84) area computation.

Algorithm

function equalAreaRadius(cell):
    area = cellArea(cell)     # h3 spherical-model area, m^2
    return sqrt(area / pi)
import { equalAreaCircle } from "@/lib/h3/circles";

const approx = equalAreaCircle(cell);
// approx.center: [lat, lng]
// approx.radiusMeters: sqrt(cellAreaM2 / Math.PI)
// approx.cellAreaM2 === approx.circleAreaM2 (by construction, up to fp error)
// approx.mode === "equal_area"

The same conversion with the Python bindings (h3-py v4):

import math
import h3

def equal_area_radius_m(cell: str) -> float:
    area_m2 = h3.cell_area(cell, unit="m^2")
    return math.sqrt(area_m2 / math.pi)

Unlike the inscribed and circumscribed pages, this one really is a one-liner in both languages — h3.cell_area (h3-py's spherical-model area, same model as h3-js's cellArea) is the only call involved, with no boundary densification or safety margin. The tested reference implementation is the TypeScript in lib/.

inscribed (172 m) ≤ equal-area (184 m) ≤ circumscribed (206 m) for one R9 cell.
Rendered from the tested conversion code · inscribed (172 m) ≤ equal-area (184 m) ≤ circumscribed (206 m) for one R9 cell.

Parameters

None beyond the cell itself — there is no edge-sample count or safety margin to configure, since the construction never inspects the boundary.

Outputs

A center and radius per cell, with cellAreaM2 equal to circleAreaM2 by construction (the entire point of the method), which also means area-based quality metrics computed against the cell itself — as opposed to against a neighbor or a requested polygon — are close to meaningless here: of course the areas match, that is the definition, not a result.

Quality metrics

coverage_ratio, overreach_ratio, and underreach_ratio computed against the true cell boundary are all simultaneously non-zero and, for a regular hexagon, roughly balanced: the circle covers most of the cell interior, misses a thin sliver near each corner, and extends past the boundary near each edge midpoint by a comparable amount, so overreach_ratio and underreach_ratio are both small but nonzero and neither approaches the 0% figure that the exact-polygon page reports or the near-10%/20% one-directional figures the inscribed and circumscribed pages report. jaccard (area of intersection over area of union with the true cell) is the single most informative summary statistic here, since it captures both effects at once.

Radius ordering

For a regular hexagon the three constructions in this section order as:

rinscribed  (0.866R)    requal-area  (0.909R)    rcircumscribed  (=R)r_{\text{inscribed}} \; (\approx 0.866R) \; \le \; r_{\text{equal-area}} \; (\approx 0.909R) \; \le \; r_{\text{circumscribed}} \; (= R)

where R is the hexagon's circumradius. The equal-area radius sits between the other two for every regular cell, which is a useful sanity check when validating a new implementation: if a computed equal-area radius falls outside the [inscribed, circumscribed] interval for a given cell, something in the area or radius computation is wrong.

Edge cases

No edge cases are tracked separately for this conversion: because the construction never samples the boundary, it is unaffected by pentagon irregularity, icosahedron face-crossings, or antimeridian wrapping in the way the boundary-sampling constructions are — cellArea and cellToLatLng already handle those correctly inside h3-js. The construction's weakness is not in edge handling; it is in the fundamental non-containment property above.

Assumptions and limitations

Never treat an equal-area circle as an execution target when the requirement is "reach exactly this cell" or "do not reach outside this cell" — it satisfies neither. It is appropriate for aggregate planning math (summed reach estimates across many cells, where the per-cell gaps and overlaps partially cancel across a large footprint) and inappropriate as the geometry actually handed to a delivery platform; for that, use the inscribed or circumscribed circle depending on whether the platform-side risk is under- or over-targeting.