← Index fig. 9

Healthcare Access in Metro Atlanta

weighted Voronoi diagrams to measure Atlanta's health system imbalance

Year
2024
Kind
Research
Role
solo author
With
Georgia Southern University
Tools
Computational Geometry, Clustering, GIS
Web app showing a map of Atlanta divided into coloured Voronoi regions around ten health facilities, with a parameters panel and a score table

Public health clinics aren’t spread out evenly. Some sit in the middle of a dense ZIP code and get buried; others are on the edge of town and half-empty. I wanted a way to measure that imbalance, and then to ask where the clinics should be.

TLDR: a paper, “Dynamic Optimization of Health Facility Accessibility: A Voronoi Diagram Approach”. Every population point is assigned to its nearest facility with a Voronoi diagram, each facility gets a load score, and then a weighted k-means moves the facilities to even out the load. On 37 Atlanta ZIP codes and 10 public health facilities, the spread in population per facility dropped 44%, and the spread in load score dropped 55%. Later I turned it into a web app you can run on your own data.

First page of the paper with the title, author and abstract
Page one of the paper.

The idea

A Voronoi diagram splits a map into cells, one per facility, where every point in a cell is closer to that facility than to any other. That’s a decent first guess at “who goes where”.

The companion notebook walks through a toy version first: a grid of random populations and five facilities, each cell coloured by how loaded it is.

Five Voronoi cells on a small grid, coloured by load score from green to red
The notebook toy: five facilities on a 7×7 grid. Red cells are overloaded.

Scoring a facility

Plain population per cell isn’t enough. Someone who lives far from their nearest clinic is worse off than someone next door to it, even if they’re in the same cell. So the score adds three things: the population in the cell, extra weight for people living farther than a radius r, and a fraction (ω) of the people just across the border in neighbouring cells, who might come over anyway.

Atlanta ZIP population points in blue, facilities in red, each facility circled by its radius, with Voronoi edges
Atlanta: ZIP population points (blue), facilities (red) and the radius around each one. Points outside every circle count extra.

Moving the clinics

Then I let the facilities move. Each iteration, every facility slides toward the population-weighted centre of its cell, with people beyond r weighted double and neighbours within c weighted by ω. Recompute the cells, repeat. It’s Lloyd’s algorithm with a public-health opinion baked into the weights.

Python source for the weighted centroid update with double weight beyond r and omega-weighted external population
The weighted k-means update. The two if-blocks are the whole idea.
Voronoi cells over Atlanta coloured by score at iteration zero, with one large red overloaded cell
Iteration 0: facilities where they really are. The big red cell is carrying far more than its share.
Voronoi cells over Atlanta at iteration six, with more even colouring after facilities have moved
Iteration 6: facilities have moved and the load is much more even.

Making it usable

The paper’s code was a script with hard-coded file paths. In 2026 I wrapped it in a small Flask app: upload facilities and population points (or use the Atlanta sample), set r, c and ω, and watch the regions update on a real map. There’s an iteration history so you can see it converge.

Web app after optimisation: relocated facility markers on a map of Atlanta, a facility table, and an iteration history chart that drops then flattens
After a run. The chart on the right is the load spread per iteration: a steep drop, then flat.

What I’d fix

The parameters committed in the repo have drifted from the paper (r is 0.05 there, 0.1 in the paper), and with those values the run doesn’t settle: from iteration 6 it flips between two layouts. Matching the paper’s values is the first fix. The bigger one is distance. I used straight-line distance on latitude and longitude, and nobody drives to a clinic in a straight line. Travel time would be the honest version.