some penguin's mapping woes

In June 2004, I went sailing with a friend who constantly carried a tiny GPS receiver linked via bluetooth to his mobile phone. After coming back, I was presented with a dense set of our coordinates, documenting our journey over all seven days of sailing rather well.

Naturally, I wanted to plot this data on a map of Adriatic; luckily, another friend of mine owns some MapTech raster charts of the area in the less-than-well documented BSB format, so I thought I'd find some software to display and manipulate those in no time...

And, boy, was I surprised!

There simply was NO software for that OS that some Finn started writing a while ago and still seems to be writing it, now helped by a bunch of strange people that have nothing better to do with their spare time, but to hack on an operating system. Naturally, there was abundance of tools for that other OS from Redmond, but since I have exorcised that one out of all my machines years ago, all that lot was of no help to me.

Wait... actually there was one tool, and a giant one at that, there was GRASS, whose documentation hinted that it might be able to import BSB maps. Unfortunately GRASS, a gigantic do-it-all GIS system, sported a ton of reference manuals, user manuals and tutorials and after fiddling with it for a few brief moments, my inability to do anything that would bring me closer to my goal (plotting our course on the maps, remember) made me believe that I will actually have to read at least some parts of the documentation.

Therefore I laid GRASS aside - I did not remove it from my system, mind you, I am quite sure one day I will have map-manipulating needs that GRASS will prove the right tool for - and went about it the hacker way: I decided to hack together a set of scripts that will allow me to convert the BSB maps to some format an ordinary image viewer can cope with, to compose many maps into a single Great Map(TM), and to plot the GPS data points on the map.

I don't really need to tell you that I succeeded, do I? It took two evenings, one marijuana bud, lots of green tea, some perl, a kind soul that wrote libbsb - a library for reading BSB raster images -, Image Magick and a lot of Google.

So, how do I do it, you wonder? Here comes the how-to in the canonic for-dummies formulation:

  1. first, let us suppose that you posses a set of maps of the area you are interested in and a number of CSV (for the extra dumb, CSV stands for Comma Separated Value, a popular format for storing tables that delimits columns with a dedicated character which is seldom a comma) text files with the GPS data points, in chronological order, with each line containing the following columns, delimited by a semicolon:
    Date;Wgs84Longitude;Wgs84Latitude;iWGS84Altitude;SpeedInKmh;Heading;Hdop;Satellites;IsValid
    
  2. we need to convert the BSB files into something that Image Magick will understand: PNG seemed like a nice choice. The bsb2png tool that comes with libbsb is just perfect for this task. Suppose, for example's sake, that you want to convert two maps, stored in files 1.KAP, 1.BSB, 2.KAP and 2.BSB: the conversion process yields two giant PNGs: 1.png and 2.png.
  3. these raster images are so large (in terms of pixels) that your head just wants to explode (to say nothing of your CPU and storage) and, furthermore, are probably not in the same scale, so you'd do best if you rescaled them, in order to make their sizes become acceptable and to make 1 pixel on each of them represent the same distance in meters. My first script, scale-maps.pl, does just that: it takes the desired horizontal and vertical distance in meters that should be represented by 1 pixel on the scaled maps as the first two arguments and 1 or more .KAP files on the rest of the command line; it also expects pregenerated PNG files with the same base name as the .KAP files. I believe that your map directory should at this point contain:
    1.KAP
    1.BSB
    1.png
    2.KAP
    2.BSB
    2.png
    
    As 50 meters per pixel seems like a nice scale, issuing the command
    scale-maps.pl 50 50 1.KAP 2.KAP
    
    will yield the following files
    1-out.png
    1-out.txt
    
    Now what are those?, you wonder... The 1-out.png is the scaled map and 1-out.txt includes some information calculated by the scale-maps.pl script from the metadata in the .KAP file. It includes, line by line, the following information:
  4. once we have the maps scaled properly, we need to compose them into one single map: the compose-maps.pl script takes a number of the maps generated in the previous step and composes them into a single big map:
    compose-maps.pl 1-out.txt 2-out.txt
    
    yields
    complete-map.png
    complete-map.txt
    
    Obviously, the complete-map.png file is the actual map image and the complete-map.txt contains the following information, each item in its own line:
  5. almost done, are we? All that is left is to run the plot-gps.pl script, giving it the map information file and any number of GPS data files in chronological order; suppose your GPS data is in files:
    day1.txt
    day2.txt
    day3.txt
    
    Running
    plot-gps.pl complete-map.txt day1.txt day2.txt day3.txt
    
    will plot your course with red ink on the map, storing the result in complete-map-plot.png.

The process is far from perfect: the overlaying parts of the maps are not perfectly covered with an error of 2 or 3 pixels being quite usual. Since no re-projections are done, results yielded by source maps that are too large or when attempting to cover a very large area of the earth's surface would probably look extremely funny. However, it does the very basic thing that I need and produces results that may be shown to the public; here is our course, plotted on one big map (3067x2436 pixels, suitable for downloading and viewing localy). You probably want to check this version first, since it has been rescaled to a miserable 1200 by 953 pixels size that your browser should feel much more comfortable with.

Copyright issues: all the scripts available for download on this page are free software, licensed under the terms of GNU GPL version 2. The maps are, of course, not freely distributable, but I do hope that providing the images of them, downscaled and composed as they are in the above images, won't bother the copyright holders.

If you find these scripts useful, please drop me an e-mail at jaka at gnu dot org; if you improve them, fix any (hmmm, are there any?) bugs, or change them in whatever unimaginable way, please share your changes with me.


jaka at gmajna dot net, 2004-08-31