Math
This program makes use of some pretty cool math, if I do say so myself. Most of the equations came straight from Wikipedia, but many of the more complicated ones I had to derive myself. Here I detail all of my equations. As a convention, I always use φ and λ for latitude and longitude respectively in radians measured from the equator where north and east are positive, r and θ for planar polar coordinates where θ is in radians measured counterclockwise from the bottom of the unit circle, and x and y for general cartesian coordinates.
Oblique aspect equations
The first thing I derived was the oblique map projection equation, used to transform a latitude and longitude to be relative to an arbitrary pole. There are a lot of holes and signs that you have to keep track of when computing it, but for the sake of simplicity, I'll just give you the basic equations. First, the forward equations, used to get relative spherical coordinates given absolute spherical coordinates and the pole:
\phi_r = \arcsin{[\sin\phi_P\sin\Phi+\cos\phi_P\cos\Phi\cos{(\lambda_P-\Lambda)}]}
\lambda_r = \pm\arccos\left[\frac{\sin\phi_P\cos\Phi\cos{(\lambda_P-\Lambda)}-\cos\phi_P\sin\Phi}{\cos\phi_r}\right]
For raster maps, you need the inverse of these equations, which gives the absolute coordinates given some relative spherical coordinates and the pole:
\Phi = \arcsin[\sin\phi_P\,\sin\phi_r+\cos\phi_P\,\cos\phi_r\,\cos(\lambda_P-\lambda_r)]
\Lambda = \lambda_P\pm\arccos\left(\frac{\sin\phi_1}{\cos\phi_P\,\cos\Phi}-\tan\phi_P\,\tan\Phi\right)
Projection analysis
The MapAnalyzer, MapPlotter, and MapOptimizer all use the same formulae for quantifying the distortion in a map. I concocted these metrics myself, but I think anyone will find that they are logical ways to rank a map projection, and they fit pretty nicely with my intuition of how good a map projection is.
Characterising size distortion is quite simple. The scale at any point on the sphere is given by
\frac{A}{a} = \left(\frac{\partial{x}}{\partial{\lambda}}\frac{\partial{y}}{\partial{\phi}}-\frac{\partial{x}}{\partial{\phi}}\frac{\partial{y}}{\partial{\lambda}}\right)\sec{\phi}
The average size distortion, then, is given by the standard deviation of the log of scale,
D_\mathrm{size} = \sqrt{\left\langle\left(\ln{\frac{A}{a}}-\left\langle\ln{\frac{A}{a}}\right\rangle\right)^2\right\rangle}
The shape distortion is measured in a similar fashion. The stretch factor at any point is given by the formula
\sigma_1+\sigma_2 = \sqrt{\left(\frac{\partial{x}}{\partial{\lambda}}\sec{\phi}+\frac{\partial{y}}{\partial{\phi}}\right)^2+\left(\frac{\partial{x}}{\partial{\phi}}-\frac{\partial{y}}{\partial{\lambda}}\sec{\phi}\right)^2}
\sigma_1-\sigma_2 = \sqrt{\left(\frac{\partial{x}}{\partial{\lambda}}\sec{\phi}-\frac{\partial{y}}{\partial{\phi}}\right)^2+\left(\frac{\partial{x}}{\partial{\phi}}+\frac{\partial{y}}{\partial{\lambda}}\sec{\phi}\right)^2}
\frac{\sigma_1}{\sigma_2} = \frac{(\sigma_1+\sigma_2)+(\sigma_1-\sigma_2)}{(\sigma_1+\sigma_2)-(\sigma_1-\sigma_2)}
The average shape distortion is then defined as the root mean square of the log of stretch,
D_\mathrm{shape} = \sqrt{\left\langle\left(\ln{\frac{\sigma_1}{\sigma_2}}\right)^2\right\rangle}
Invented projections
Now for the projections I've invented. As before, I will let it be known that these equations are riddled with holes. I don't want to explain all of them, so if it matters to you, you can solve the limits yourself.
First is Pseudostereographic. If you are familiar with Hammer and Aitoff, this will probably be quite simple for you:
x = \mathrm{I'll simplify and transcribe this later}
y = \mathrm{Just go read about how Hammer and Azimuthal work}
Slightly more complicated is the Hyperellipower projection. It is a pseudocylindrical projection with the shape of a hyperellipse and a power function controlling the parallel distance from equator. The equations work out to
y' = 1 - \left(1-\left|\frac{\phi}{\pi/2}\right|\right)^n
x = \sqrt[k]{1 - y'^k}*\frac{\lambda}{\pi}
y = \frac{ay'}{2\sqrt{n}}*\mathrm{signum}\,\phi
Or, in inverse form,
\phi = \frac{\pi}{2}\left[1 - (1-|y|)^\frac{1}{n}\right]*\mathrm{signum}\,y
\lambda = \pi\frac{x}{\sqrt[k]{1 - |y|^k}}
Next is the TetraGraph, an equidistant tetrahedral projection. Before applying the projection, one must first divide the sphere into four equally spaced, equally sized, and equally shaped quadrants – one for each face. Each quadrant must then be divided into three sectors depending on to which other face each point is closest. This projection is derived with a linear mapping from a γ-λ coordinate system on the sphere to an x-θ coordinate system on the plane.
What are γ and λ, you ask? λ is the azimuthal angle from the pole, or longitude, and γ is the azimuthal angle from a point transverse to the pole, which I call the Justitude. This coordinate system, which I dub Justesian coordinates, breaks down on the orthodrome containing the pole and the Justimuth. Luckily, TetraGraph does not use this part of the sphere, because for a given sector, the azimuth is defined as the center of that sector's quadrant, and the Justimuth is defined equidistant from the centers of the two nearest quadrants. Furthermore, λ is zero on the orthodrome connecting the centers of the two nearest quadrants and γ is zero on the orthodrome connecting the pole and the Justimuth. With this coordinate system in mind (and the hopefully self-explanatory x-θ coordinate system), the projection inside each sector is defined as
x = \gamma
\theta = \lambda
This renders each sector as an obtuse isoceles triangle. Three sector triangles tesselate into an equilateral triangle, and these quadrant triangles can the be tesselated however the cartographer sees fit. If you would prefer latitude to Justitude and r to x, use the expansion
r = \arctan(\cot\phi\cos\lambda)\sec\lambda
\phi = \tan(r\cos\lambda)\sec\lambda
Next is TetraPower, almost identical to TetraGraph save some power functions thrown in to make it more optimisable. The forward equations work out to
\theta = \frac{\pi}{3}*\frac{1-\left(\frac{\left|\lambda\right|}{\pi/2}\right)^{k_1}}{1-\left(\frac{1}{3}\right)^{k_1}}*\mathrm{signum}\lambda
k_R = k_3\frac{\left|\theta\right|}{\pi/3}+k_2\left(1-\frac{\left|\theta\right|}{\pi/3}\right)
r_\triangle = \frac{1}{2}\sec\theta
r_\circ = \frac{1}{\arctan\sqrt{2}}\arctan(\cot\phi\sec\lambda)*r_\triangle
r = \frac{1-(1-r_\circ)^{k_R}}{1-(1-r_\triangle)^{k_R}}*\frac{2}{3}r_\triangle
The inverse equations are
\lambda = \left(1-\frac{3}{\pi}\left\{1-|\theta|\left[1-\left(\frac{1}{3}\right)^{k_1}\right]\right\}^\frac{1}{k_1}\right)*\frac{\pi}{2}\mathrm{signum}\,\theta
k_R = k_3\frac{\left|\theta\right|}{\pi/3}+k_2\left(1-\frac{\left|\theta\right|}{\pi/3}\right)
r_\triangle = \frac{1}{2}\sec{\theta}
r_\circ = 1 - \left\{\frac{r}{r_\triangle}\left[1-(1-r_\triangle)^{k_R}\right]\right\}^\frac{1}{k_R}
\phi=\arctan\left[\cos\lambda\cot\left(\frac{r_\circ}{r_\triangle}\arctan\sqrt{2}\right)\right]
Finally, we have Two-point Equalised, based heavily on Two-point Equidistant. The forward equations work out as follows:
x = \mathrm{I'll simplify all this later}
y =
The inverse is:
\phi =
\lambda =