I've started to put together some visualisations and maps spanning the last five millennia of nations, empires and dynasties, on a whim really.
Monday, 23 February 2026
Friday, 6 August 2021
Hexworld 2: Encoding
As mentioned in the first part, the map of Hexworld consists of a 864-by-360 staggered grid of hexagons. Each hexagon (hexel) holds an 8-bit index, so the whole thing fits into about 300KB of binary data. It can be stored as an 8-bit PNG weighing in at about 13½KB:
Greyscale optimisations and PNG Crush will reduce this to about 11½KB. However, reading the pixel index values back using JavaScript so that we can reconstruct the hexel data is problematic. One would think you could simply do the following:
- Encode the greyscale PNG as a data URL,
- Load it into an offscreen img element,
- Draw it into an offscreen canvas element,
- Capture the pixel data via getImageData() element, then
- Reconstruct the indices.
The two main stumbling blocks are:
- Loading images (even data URLs) is an asynchronous activity.
- Colour space management typically applied a "gamma" correction which means the greyscale RGB values are not one-to-one with the original indices.
The second issue cannot be solved without using a third-party JavaScript library (like pngjs) to decode the raw PNG data and extracting the indices directly.
Another option is to encode the raw pixel data (as opposed to the PNG) into the JavaScript script itself. For example:
This function takes a 311,040-element Uint8Array (that's 864 times 360) as an argument and fills it with the indices. Unfortunately, the hexadecimal string is over 600,000 characters long!
If we limit ourselves to ASCII JavaScript, can we do better?
Friday, 30 July 2021
Hexworld 1: World Map
I've long been fascinated by hexagonal grids. And maps. So it was probably only a matter of time before I created a world map based on a hexagonal grid: Hexworld.
I'm certainly not the first to try this, but most of the other attempts I've seen are either low resolution or do not try to capture national boundaries.
The obvious way of generating such a map is to take an existing one (in this case, an equirectangular projection) and post-process it. I started down this track but quickly discovered that it produces ugly results. As cartographers through the ages have discovered, making political maps (as opposed to maps for navigation) is more of an art-form that a science. So I dusted off my faithful copy of Paint Shop Pro 5 and hand-filled the 100,000 or so hexagons that make up the land masses:
I initially coloured the regions using five colours (red, green, blue, yellow and pink) and then used a Wikimedia four colour map as the basis for whittling it down to four.
With the seas coloured cyan (hue 180°), it made sense to use equidistant hues for the remaining four colours: red (324°), green (108°), blue (252°) and yellow (36°).
Each "hexel" is given one of 241 unique 8-bit indices:
- One index (0) is reserved for water,
- 193 indices cover the current full UN member states,
- 2 indices cover the UN observer states (Vatican and Palestine),
- 6 indices cover disputed territories (Western Sahara, Taiwan, Abkhazia, Crimea, Kosovo and South Ossetia),
- 28 indices cover overseas territories belonging to UN states (e.g. Falklands), and
- One index (255) for Antarctica.
The lowest two bits of the index encodes the region's colour; except for 0 and 255, which are treated specially. The world is indeed four-colourable!
Obviously, there's no real advantage in rendering a world map using hexagons instead of rectangular pixels or arbitrary polygons. But it's a fun exercise.
Friday, 11 January 2019
A Crowded Chronology of Cities
- The fall of the Roman Empire
- The fourteenth century plagues (that's my guess, anyway!)
Thursday, 25 July 2013
Tube Map Evolution
If you don't have access to HTML5, I've rendered out a (slightly less impressive) animated GIF.
Original maps copyright © Transport for London. Reproduced with kind permission. Thanks Saskia!
Friday, 7 September 2012
Map Demo 3.0
This is a bog-standard 32-bit Windows application with all the data embedded within it. Compiling the supplied source code with Visual C 2008 produces an executable of just 118KB; compressing this with UPX brings it down to 84KB, mainly through instruction-stream compression.
- Coastline and border data for 214 countries (including South Sudan and Montenegro);
- Over one hundred statistics and codes for each country;
- Vector-drawn flags for each country;
- 128 map projections;
- Choropleth statistically mapping;
- The ability to save the data table as a CSV file (significantly larger than the executable!); and
- The ability to save maps and flags as Windows Enhanced Metafiles.






