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:
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
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/.
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:
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.
