The standard projection used in converting latitudes and longitudes on the (roughly) spherical earth to a planar map depends on what you’re projecting.

Most people know about the Mercator projection.

The one used extensively for maps of the United States is called the Albers Equal-Area Conic projection.

The wikipedia article gives some formulas:

You must first choose two reference latitudes. Latitudes are referred to by the letter phi and longitudes by the letter lambda. So the two references are phi_1 and phi_2.

You also choose a center for the map, at phi_0, lambda_0.

From these four values you calculate n, C and then rho_0, which are each the same for every transformation in this projection.

Finally, for each coordinate phi, lambda one calculates rho and theta and then finally

x = rho sin theta

y = rho_0 - rho cos theta

This, however, is for the assumption of a spherical earth. The equations for an ellipsoid are a bit harder.

The wikipedia article gives this url for a pdf and I found the same report referenced in this answer to a question on Stack Exchange.

so that was lucky, because it gave me not only the equations but also a worked numerical example for each, which helped greatly in finding my mistakes in the code.

The math is explained in a write-up done in LaTeX, as a Dropbox link to a pdf. The math has been encoded as Python scripts sphere.py and ellipsoid.py here.

Here are screenshots from the manual:

The test is a latitude of 35°N., -96°W., which should give a result (for the ellipsoid) of

> python ellipsoid.py

test1

p0: 23.0

l0: -96.0

p: 35.0

l: -75.0

x: 1885472.7

y: 1535925.0

The first part of the output is the center we chose. The result for x and y matches the source.

So then, for a script in the same directory as ellipsoid.py, we can do import project and do

> python3 map_counties.py counties.geo.txt AL

No longer squashed.

Naturally, there is software out there that will do this. In particular, the Proj transformation software.

I obtained it with Homebrew

> brew install proj

> echo 55.2 12.2 | proj +proj=merc +lat_ts=56.5 +ellps=GRS80

3399483.80 752085.60

which matches their example.

Of course, we really want the Albers equal area conical projection based on the ellipsoid.

> echo -75 35 | proj +proj=aea +lat_1=29.5 +lat_2=44.5 +lat_0=23 +lon_0=-96 +ellps=clrk66

1887211.95 1533994.75

These are close but don't quite match. I will have to explore Proj more to know why.

Put the input data into a file and do:

> cat data.txt | proj +proj=aea +lat_1=29.5 +lat_2=44.5 +lat_0=23 +lon_0=-96 +ellps=clrk66 1887211.95 1533994.75 >