Page head image

Rendering GPS tracks


Sure, you can chose from numerous implementations if you want to render GPS tracks. But for scalable online maps, nothing I found was good for my purposes. The available on-demand renderers are too slow and need too much memory processing a data set with aproximately 100,000 fixes from all over California, Nevada, Arizona and Utah. Thus, I had to render the tiles offline. Basically, two free solutions for that exist: Mapnik and Osmarender.

Mapnik is terribly overblown for this purpose. It needs Postgresql, the PostGIS addon for psql, Boost, Python bindings to Boost, and lots of other libraries and tools I never used before. Worse, it is a really bad dependency nightmare.

Osmarender sounds more promising: basically, it is just an XSLT stylesheet that produces an SVG file from an OpenStreetMap file. To generate tiles, you need a filter to limit the OSM data to the region you want to render, an SVG renderer and something to cut the resulting large image into tiles. The Tiles@Home project provides the necessary scripts. However, it is specifically written to render and upload OSM tiles and it would need some tweaks and additional scripts to render custom data. I gave it a try again a couple of days ago, and all it rendered were broken PNG graphics. Apparently some issue with Inkscape, but I didn't bother to follow up on that.

With both Mapnik and Osmarender not being suitable for this specific job, I decided to brush up my Java knowledge and wrote my own renderer. Java Advanced Imaging (JAI) sounds like a good idea, as it can operate on tiled images. It is even possible to create your own tile handling. However, apart from the API and some far too simple tutorials, I didn't find any useful documentation on how to actually do that. In the end wrote my own tiled canvas implementation after wasting two days by searching for any kind of documentation. It allocates tiles only when they are actually used to save memory and can draw pixmaps and lines even over tile boundaries. The tiles are organized in a HashMap, which is fast and has an acceptable memory overhead. Rendering the track at zoom level 18 requires approximately 3.7 GB of RAM, which is 78 kB per tile, or 22% overhead. Could be better, but I expected worse.

Rendering 49,895 tiles took almost half an hour, which indeed is slower than anticipated. Profiling shows that most of the time gets spent internally in the Java AWT, mainly while converting the RGBA byte field to the internal raster and during PNG encoding. The latter is ridiculously slow. Sure, opposed to JPEG and TIFF processing which is implemented by C bindings, the PNG support was implemented purely in Java. Still it is no excuse to not fix it for more than ten years. What a shame, nobody tries to improve AWT anymore. The slowness of it is the main reason for all the prejudice against Java, after all.

Another time consuming task is the XML processing of the GPX file. I'm not satisfied with the speed of the SAX2 parser, but in this case it is at least acceptable. On the other hand, I'm positively surprised by the performance of the HashMap. Profiling showes that it even caches the last fetched item. I kept my own check though, as creating the string that serves as a hash key is notably more expensive than comparing two integer values...

If you want to know more about the program, or even like to extend it or fix bugs: It is GPLed and downloadable from It is a command line tool, the source code is the documentation. Beware of the abominable coding style, though.


There are currently no comments

New Comment


required (not published)