Purpose
A geographic target is rarely a single region. It is usually stated as one or more inclusions minus one or more exclusions — "target this state, but not this city" — and every layer of the stack from planning through execution has to agree on what that combination means before any of it can be measured. This page defines the effective-geography operation and the failure modes that show up when it is computed carelessly, or not computed at all before comparing two geographies.
The effective geography
Every inclusion is unioned into one set, every exclusion is unioned into a second set, and the effective target is the first set with the second subtracted out. This is a set operation, not a geometric one performed polygon-against-polygon — both sides must already be expressed as sets of H3 cells at a common resolution before the union and difference are evaluated, for reasons covered below.
Cases
- Include country, exclude city
- A large polygon minus a small polygon nested inside it. The excluded city's cells are removed from the country's cell set; cells outside the city are untouched.
- Include cells, exclude ZIPs
- An H3 cell set with a postal-code exclusion. The ZIP polygons must first be polyfilled to the same resolution as the included cells before the subtraction is meaningful.
- Include polygon, exclude point-radius
- A polygon inclusion with a circular exclusion cut out of it — for example, a trade area with a competitor's buffer removed. Both sides are normalized to H3 before the difference.
- Include parent cells, exclude child cells
- An inclusion stated at a coarse resolution with an exclusion stated at a finer resolution nested inside it. Requires resolution normalization first; see mixed-resolution handling below.
- Mixed-resolution include/exclude
- Inclusions and exclusions supplied at different H3 resolutions in the same request — common when one side comes from a compacted set and the other from a fixed-resolution polyfill.
- Overlapping source systems
- Inclusions or exclusions sourced from two systems whose boundary vintages disagree (e.g., last quarter's DMA file for inclusion, this quarter's for exclusion), producing a difference that reflects boundary drift rather than intended targeting.
- Unsupported exclusions
- An exclusion the execution platform cannot express at all. The platform silently drops it rather than erroring, so reported geography and executed geography diverge without any signal in the platform's own logs.
Why normalization must happen first
Union and set-difference are only well-defined operations on two sets drawn from the same universe. If inclusions are H3 cells at resolution 8 and exclusions are a ZIP polygon that has not been polyfilled, "subtract" is not a computable operation yet — there is no shared unit to subtract in. Every inclusion and exclusion source (polygon, point-radius, raw H3 cells at whatever resolution they arrived in) must be converted into H3 cells at one common working resolution before the union or the difference is taken. Doing the subtraction on raw geometry first and converting to H3 second produces a different, non-reproducible result depending on which geometry library performed the subtraction — the order matters, and normalize-then-combine is the only order that is reproducible from the H3 grid alone.
Precedence, empty results, and dangling exclusions
Exclusion always wins: a cell present in both the inclusion union and the exclusion union is removed, with no configuration that reverses this precedence — an "include and exclude the same cell" request is not ambiguous, it resolves to excluded. An effective geography can legitimately be empty (the exclusion union fully covers the inclusion union); this must be surfaced as an explicit empty-result state distinct from "no exclusions were supplied," since a downstream system that treats both cases the same way will silently launch against zero geography instead of raising an error. A dangling exclusion — an exclusion whose cells never intersected any inclusion cell in the first place — has no effect on the result but should still be reported, because it usually indicates a targeting mismatch (the two sides were built from misaligned assumptions about what the inclusion actually covers) worth surfacing even though it changed nothing.
Algorithm
import { effectiveGeography } from "@/lib/h3/setops";
// Normalizes every input to one resolution, then applies
// effective = union(inclusions) - union(exclusions).
const effective = effectiveGeography(
{ inclusions, exclusions },
{ resolution: 8 }
);
if (effective.cells.length === 0) {
// Explicit empty-result state — not the same as "no exclusions given."
flagEmptyEffectiveGeography(effective);
}
The same conversion with the Python bindings (h3-py v4):
import h3
def normalize_to_resolution(cells, resolution: int) -> set[str]:
normalized = set()
for cell in cells:
res = h3.get_resolution(cell)
if res == resolution:
normalized.add(cell)
elif res < resolution:
normalized.update(h3.cell_to_children(cell, resolution))
else:
normalized.add(h3.cell_to_parent(cell, resolution))
return normalized
def effective_geography(inclusions, exclusions, resolution: int = 8) -> set[str]:
include_set = normalize_to_resolution(inclusions, resolution)
exclude_set = normalize_to_resolution(exclusions, resolution)
# Plain Python set difference — well-defined only because both sides
# were normalized to the same resolution above.
return include_set - exclude_set
effective = effective_geography(inclusions, exclusions, resolution=8)
if not effective:
# Explicit empty-result state — not the same as "no exclusions given."
flag_empty_effective_geography()
The tested reference implementation in this knowledge base is the
TypeScript in lib/; this Python mirrors its normalize-then-combine
order using core h3-py calls plus ordinary Python set operations on
string cell ids.
Edge cases
Unsupported exclusions are the
most consequential failure mode here: when a platform cannot express an
exclusion (no negative-targeting primitive, or a cap on the number of
exclusion regions it accepts), it drops the exclusion rather than rejecting
the request, so what the platform reports as delivered geography silently
includes territory the requester believed was excluded. This must be
detected before launch by checking the platform's exclusion support against
the request, not discovered afterward by comparing delivery logs to intent.
Mixed resolutions between the inclusion and
exclusion sides are common whenever one side comes from a compacted cell set
and the other from a fixed-resolution polyfill — normalizing both sides to
one resolution, as effectiveGeography does internally, is mandatory before
any comparison, union, or subtraction is attempted.
Assumptions and limitations
This model assumes exclusions are geometric — describable as a set of H3 cells — and does not cover attribute-based exclusion (for example, "exclude households on a suppression list"), which operates on a different axis than geography and should not be folded into the same set-difference without first confirming the platform treats the two axes independently.
