# Hack 31. Plot Dymaxion Maps in Perl

See Earth's surface as one world in one ocean, just as Bucky Fuller intended.

Any projection of Earth's surface onto a flat plane necessarily introduces distortions of one kind or another. [Hack #28] discusses the most common sorts of trade-offs that cartographic projections typically make in trying to preserve the area, shape, or relative locations of Earth's landmasses. However, cartographic projections can emphasize other aspects of the world's surface, as well.

Toward the end of "a precise means for seeing the world from the dynamic, cosmic and comprehensive viewpoint," R. Buckminster Fuller labored for decades to invent the Dymaxion projection, which projects Earth's spheroid onto an icosahedron aligned in such a way that 18 of its 20 triangular faces can be unwrapped onto a flat plane without splitting landmasses. The other two faces artfully split the Yellow Sea and the Indian Ocean. Across each individual face, distortion is relatively slight, so that the world is shown as "one island in one ocean," with the shapes and areas of the landmasses more or less preserved. Fuller's projection, although useless for navigation, can serve to represent other relationships in our world, without introducing the possibility of psychological distortion that some argue is engendered by more conventional cartographic projections.

For example, we might want to see the world's 100 major population centers on a Dymaxion projection, a visualization that can dispense with navigation as a potential requirement. Plotting latitude and longitude on a Dymaxion map, however, involves a bit of spherical trigonometry; the coordinates must first be converted to (x,y,z) coordinates on a spheroid with Earth's center as its origin, and then these points must be rotated and translated through space onto the flat plane that comprises our map. The mathematics is hardly for the faint of heart, which is why we're lucky that there are several sources of code out there that will do the trig for us!

3.11.1. The Code

One such source is Robert W. Gray's homepage, which offers some code for Dymaxion coordinate transformation at http://www.rwgrayprojects.com/rbfnotes/maps/graymap6.html. Gray's code does all the math, but it's written in Ca little complicated for simple visualization work. To make life a little easier on people who want to experiment with the Dymaxion projection, I used Brian Ingerson's terrific Inline.pm module to seamlessly glue Gray's code onto a Perl module called Geo::Dymaxion, which is freely distributed on the CPAN. Geo::Dymaxion requires you to have Inline installed, but you can install both automatically using the CPAN shell:

`\$ perl -MCPAN -e 'install Geo::Dymaxion'`

If you've never used the CPAN shell before, you will be asked a series of silly questions, but you will only need to do it once.

The Geo::Dymaxion API only has two method calls: new(), which creates a map object and specifies its dimensions in pixels (or other arbitrary measure), and plot(), which takes a point specified in latitude and longitude and returns its location on the Dymaxion map, using the upper left corner as the origin. The coordinates returned by plot() can be used by an image-manipulation library, like Imager.pm. You can install Imager using the CPAN shell, as above.

The following script, which we'll call plot_cities.pl, uses Imager.pm and Geo::Dymaxion to plot a list of cities on a Dymaxion map of the world:

```#!/usr/bin/perl
use Imager;
use Geo::Dymaxion;
use strict;

my \$map = Imager->new;
\$map->open( file => "dymaxion.png" );

my \$dymax = Geo::Dymaxion->new( \$map->getwidth, \$map->getheight );

open CITIES, "; # throw away the header line

for (1 .. 50) {
my \$line = ;
my @field = split /	/, \$line;

my \$lat = \$field[-2];
\$lat *= -1 if \$lat =~ /S/;
\$lat =~ y/0-9.-//cd; # throw away non-numeric characters

my \$long = \$field[-1];
\$long *= -1 if \$long =~ /W/;
\$long =~ y/0-9.-//cd; # throw away non-numeric characters

my (\$x, \$y) = \$dymax->plot( \$lat, \$long );
\$map->circle( x => \$x, y => \$y, r => 3, color => "red" );
}

\$map->write( file => "world_cities.png" )
or die \$map->errstr;```

The script starts by opening a text file called cities.txt and then discards the header line. Next, it reads the next 50 lines, one by one, splitting each line up into tab-separated fields, extracting the latitude and longitude from the second-to-last and last fields on each line, respectively. One important thing to note is that Geo::Dymaxion expects latitudes south of the equator and longitudes west of the prime meridian to be expressed with negative values; this is taken care of by the two regular expression matches in the main loop. The latitude and longitude are fed to Geo::Dymaxion, and the x- and y-coordinates are used to draw a three-pixel-wide red dot on the map in the appropriate location. Finally, the updated map is written to a PNG image called world_cities.png.

3.11.2. Running the Code

In order to run this code, we'll first need a list of cities. We've compiled just such a list for you, using data from world-gazetteer.com, which you can fetch from http://mappinghacks.com/data/cities.txt. The file is tab-separated and contains a bunch of other information, about which we won't go into detail here, but that you might find useful for other mapping projects. Next, we'll need a Dymaxion map of the world. Dymaxion maps are astonishingly hard to find on the Internet, so we prepared oneagain, using Geo::Dymaxionthat you can download from http://mappinghacks.com/maps/dymaxion.png. We put all three files in the same directory, and simply run the Perl script:

`\$ perl plot_cities.pl`

After running this code, you should have a nice Dymaxion map in world_cities.png, as shown in Figure 3-35, with the world's 100 largest cities by population highlighted with three-pixel-wide red dots.

Figure 3-35. The world's 50 largest cities by population, as shown on a Dymaxion projection

 If you're not interested in going through all of this work, but you still want to bask in the glow of Fuller's genius, you can explore the interactive web-based demo we've set up at http://mappinghacks.com/projects/dymaxion/.

That's all there is to using Geo::Dymaxion; a future version may instead rely on the Dymaxion routines from the Virtual Terrain Project (http://vterrain.org/), which would allow you to not onlly project lat/long points into the Fuller projection but to do the inverse as well, making it possible to script server-side HTML image maps of the Dymaxion projection. Finally, there is one thing you should be aware of, vis à vis the Dymaxion code that Geo::Dymaxion uses currently: it is distributed under a license that prohibits commercial use without Robert W. Gray's explicit permission. Find out more from his web site, if you happen to want to use Geo::Dymaxion in a commercial application. (Changing Geo::Dymaxion to rely on the VTP's BSD-licensed rendition of this code would fix that issue, also.)

Bucky Fuller once wrote, "When I am working on a problem, I never think about beauty. I only think about how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." With luck, the Dymaxion projectionand Geo::Dymaxionwill help you explore the world's many pressing questions, and find solutions that are both beautiful and right!

• [Hack #28]
• The Buckminster Fuller Institute (http://bfi.org/map.htm)

Mapping Hacks: Tips & Tools for Electronic Cartography
ISBN: 0596007035
EAN: 2147483647
Year: 2004
Pages: 172
Simiral book on Amazon