Jaa


Map Projections

When displaying geospatial data you’ve got some decisions to make about what map projection to use.  One way to look at it is this: the world isn’t flat.  I know that isn’t news in the 21’st century, but that does turn out to be the problem.  The world isn’t flat, but the map is.  There is a lot of very interesting mathematics here.  The thing to notice is that while the earth isn’t flat, it isn’t exactly three dimensional either.  The surface of the earth is still two dimensional, but instead of being a a two dimensional plane, it is the surface of a sphere.  The word used to describe these two dimensional spaces is manifolds. Really the first place you run into this study is multi-variable calculus which is in the 2nd year of College Calculus. 

A map projection is simply a function that maps the points on the surface of the sphere to points in the plane.  The simplest possible projection is called the cylindrical projection.  You simply take the longitude and latitude and that becomes your X and Y coordinates.  It is called the cylindrical projection because geometrically, it is equivalent to wrapping the map around the globe to form a cylinder with the height of the cylinder being the height of the globe.  If you drew a line between the poles in the globe and then projected a ray at a normal from the line through the surface of the sphere and mapped that point to the point on the cylinder that the ray touched you’d get exactly the cylindrical projection.

Of course, there are infinitely many map projections.  All they need to do is map every point exactly once on the sphere to a point in the plane and you can draw a map.  But not all projections are created equal.  It turns out that there is no such thing as the perfect projection.  When you try to draw a large portion of the globe on a nice flat piece of paper there must be some distortion.  You can’t take a balloon, cut along one side, and lay it flat without stretching it in one way or another. And so instead a projection is chosen to have the features that you want with the resulting distortion being something you can live with.

One popular projection is the Mercator Projection. The Mercator projection preserves angles at the cost of distorting area. The Mercator projection also distorts the geodesic (the path that lies on the shortest distance between two points)   The Mercator projection is a sort of cylindrical projection, but the projection is stretched in the Y direction.  The map is stretched more  and more as you get closer to the poles.  This stretching gets so severe at the top and bottom of the map that the projection is largely useless north and south of 70 degrees.

Another interesting projection is the Scalar Projection.  This projection preserves area, at the cost of distorting angles.   A cylindrical projection distorts things more as they get towards the poles, just like the Mercator projection. In order to offset this distortion the map is contracted left-to-right more at the top and the bottom.  While the shapes may be distorted, the areas of the shapes are preserved.

Just so this post isn’t completely without a little code, I’ve coded up the Mercator and Sinusoidal projections in a little class below.

    // This code is provided AS-IS it implies no warrinties and conferres no rights
class MapProjection
{

        static public Double DegToRad(Double degrees)
{
return degrees * Math.PI / 180;
}

        static public Double RadToDeg(Double radians)
{
return radians * 180 / Math.PI;
}

        static public System.Windows.Point Mercator(Double baseLongitude, Double longitude, Double latitude)
{
System.Windows.Point point = new System.Windows.Point();
point.X = longitude - baseLongitude;
Double phi = DegToRad(latitude);
point.Y = RadToDeg(Math.Log(Math.Tan(Math.PI / 4 + phi / 2)));
//point.Y = RadToDeg((Math.Log((1 + Math.Sin(phi))/(1 - Math.Sin(phi)))/2);
//point.Y = RadToDeg(Math.Log(Math.Tan(phi) + 1 / Math.Cos(phi)));

            return point;
}

        static public System.Windows.Point Sinusodal(Double baseLongitude, Double longitude, Double latitude)
{
System.Windows.Point point = new System.Windows.Point();
Double phi = DegToRad(latitude);
point.X = RadToDeg((DegToRad(longitude) - DegToRad(baseLongitude)) * Math.Cos(phi));
point.Y = latitude;

            return point;
}

    }