Voronoi Cartogram¶
Centroidal Voronoi Tessellation (CVT) cartograms via Lloyd relaxation.
Overview¶
The voronoi_cartogram module places geometry centroids so that each point
claims an equal-area (or proportionally weighted) Voronoi cell within the
outer union boundary. The result is a set of non-overlapping tiles that
collectively preserve the topology of the input while making cell areas
proportional to a data variable.
Core Algorithm: iteratively label pixels by nearest centroid → compute weighted centroid of each cell → over-relax toward centroid → repeat until area coefficient of variation drops below tolerance.
graph TD
A[Input GeoDataFrame] --> B[Prescale components]
B --> C[Initialize centroids]
C --> D[Label pixels / compute cells]
D --> E[Compute weighted centroids]
E --> F[Over-relaxed update]
F --> G[Convergence check]
G -->|Not converged| D
G -->|Converged| H[VoronoiCartogram]
Main Interface¶
| Sub-module | Description |
|---|---|
| API | create_voronoi_cartogram, make_groups_contiguous |
| Options | VoronoiOptions, TopologyRepair — iteration count, stopping criteria, topology repair schedule |
| Backends | RasterBackend (default), ExactBackend, RelaxationSchedule, AdhesiveBoundary, ElasticBoundary |
| Result | VoronoiCartogram, TopologyAnalysis, TopologyRepairReport — positions, cells, metrics, plot & repair methods |
| History | VoronoiSnapshot — per-iteration snapshot |
Computation¶
| Sub-module | Description |
|---|---|
| Field | BaseField, RasterField, ExactField — Lloyd relaxation engines |
| Geodesic Labeling | Topology-respecting pixel labeling via multi-source BFS |
Analysis¶
| Sub-module | Description |
|---|---|
| Contiguity | make_groups_contiguous — repair satellite Voronoi cells for grouped regions |
Output¶
| Sub-module | Description |
|---|---|
| Visualization | plot_cartogram, plot_comparison, plot_convergence, plot_displacement, plot_topology, plot_topology_repair |
| Animation | animate_voronoi_history, save_animation |
Workflow Patterns¶
Basic Voronoi Cartogram¶
import carto_flow.voronoi_cartogram as vor
import carto_flow.data as examples
us_states = examples.load_us_census(population=True)
result = vor.create_voronoi_cartogram(
us_states,
weights="Population (Millions)",
)
result.plot(column="Population (Millions)", legend=True)
Choosing a Backend¶
# Default: raster nearest-neighbor (10–50× faster than exact)
result = vor.create_voronoi_cartogram(gdf, weights="value")
# Exact scipy Voronoi + shapely clipping (higher accuracy, slower)
result = vor.create_voronoi_cartogram(
gdf, weights="value",
backend=vor.ExactBackend(),
)
# Raster with elastic boundary — boundary vertices advected by area pressure
result = vor.create_voronoi_cartogram(
gdf, weights="value",
backend=vor.RasterBackend(
resolution=400,
boundary=vor.ElasticBoundary(strength=0.3),
),
)
Geodesic Labeling¶
For datasets with complex coastlines or water gaps (where Euclidean nearest-neighbor would incorrectly assign pixels across bays or straits):
result = vor.create_voronoi_cartogram(
gdf, weights="value",
backend=vor.RasterBackend(distance_mode="geodesic"),
)
Topology Repair¶
When grouped regions (e.g. congressional districts by state) produce
disconnected satellite cells, pass group_by to the main call and
call repair_topology() on the result:
result = vor.create_voronoi_cartogram(
gdf, weights="value",
group_by="state",
)
report = result.repair_topology("state")
result = report.cartogram
print(report.after)
Recording History¶
# record_history=True captures every iteration; pass an int to subsample
result = vor.create_voronoi_cartogram(
gdf, weights="value",
options=vor.VoronoiOptions(record_history=5), # snapshot every 5 iters
)
for snap in result.history:
print(f"Iter {snap.iteration}: area_cv={snap.area_cv:.4f}")