Marble's Secrets Part I: Behind the Scenes of Marble...
This is the first part of a new series about Marble. I'll try to address a few frequently asked questions as well as the current status of the development. So stay tuned.
If you've ever followed KDE 4 development then you've probably heard about Marble. Marble is a virtual globe which displays the earth. So Marble can be used as a nice digital replacement for your desktop globe at home where you can look up places.
But wait! There's more to it: Actually these days Marble can also display flat maps (thanks to Carlos Licea), can show different "map themes" and can serve as a Qt4-widget as well as an application! This means that as a programmer you can use Marble in your very own project as a map widget (License: LGPL). Marble was designed to run on any device and on any operating system supported by Qt4 without any further requirements. You can download the latest version of Marble together with KDE 4.0.1 here (It's part of the KDE-EDU module).
How Marble stores texture data
If you start Marble you might realize that the startup time is pretty good: It usually takes maybe 2-5 secs to start Marble (and we are working on improving that dramatically). If you zoom into the earth you might notice that Marble doesn't get slower while zooming in. Looking at the amount of memory being used up you will also see that memory numbers don't change either. No matter how much you zoom in it's as little as 65-100MB which is pretty lean compared to other virtual globes.
Among other concepts this is being accomplished by loading the map piece by piece. Marble uses a concept that is very popular among virtual globes: Quadtiles. In fact we are using the most simple form of Quadtiles compared to other more sophisticated solutions. We decided to do so for reasons of pragmatism and in order to keep things easy to understand for people who want to contribute to Marble.
This means that for different zoomlevels the map is available at different pixel resolutions: level 0: 1350x675, level 1: 2700x1350, level 2: 5400x2700, ... . The highest zoom level currently provided from http://download.kde.org measures 86400x43200 pixel which equals about 500m per pixel at the equator.
Loading maps this large would exceed the physical memory or would at least take very long to load. So the maps are stored as a 2:1 ratio checkboard of several tiles. In Marble each of those tiles measures 675x675 pixel. The next higher zoom level gets created by dividing every tile into 4 pieces measuring 675x675 pixel each:
So level 0 consists of a row of two 675x675 pixel tiles (1350x675). Level 1 consists of two rows of 675x675 pixel tiles with four columns each (2700x1300) and so on. You can see this in the screenshots which also show the filenames of the tiles: They contain the row number (counted from north to south) and the column number (counted from west to east). As you can see Marble will only load about 5-6 tiles for any view. For Spherical Projection ("Globe") these tiles get mapped onto the globe.
So in theory there is technically no limit as to how far Marble can zoom into the earth. As you can see in the screenshot we have tested Marble with data from the kind folks from the OpenStreetMap Project ( http://www.openstreetmap.org ) already and there we are down to approximately level 13 where you can see objects that can reasonably get measured at the order of centimeters already (The test data tiles were kindly created by Artem Pavlenko of Mapnik fame).
During the very first application start of Marble you might have noticed that the first start takes a bit longer: According to the dialog Marble needs to "initialize the map". Actually it just creates the tiles from the huge base image while showing the dialog.
How to create your own maps in Marble?
Marble looks for maps on the local file system: these maps get specified in a .dgml-files. So that's what Marble will look for right from the start. Marble will search your home directory's ~/.marble/data/maps/earth as well as the respective system directory ( e.g. /usr/share/apps/marble/data/maps/earth ). The *.dgml file is a small XML-file that mostly contains
- the real "name" of the map,
- the name of the directory ("prefix") ( Usually a PNG file ),
- the icon that gets used in the Marble application's "Map View"/"Theme" listview and
- the actual file name of the basemap ("installmap"). This file should be available in JPG format. If you have map data available which got stored as tiles using the correct format then the installmap file isn't needed of course.
You can simply create your own map by copying over an existing directory ( e.g. "citylights" ) from the system directory. Of course you need to change the name of the target directory to something different:
tackat@tackat-laptop:~$ cp -r /usr/share/apps/marble/data/maps/earth/citylights/ /home/tackat/.marble/data/maps/earth/mymap
Then you just need to rename the citylights.dgml-file (e.g. to "mymap.dgml") and load it with a text editor. After adjusting the 4-5 values inside the xml file you are almost done and you just need to provide a random icon (preferably at a size of 128x128) and the basemap. The basemap needs to be provided in a special, but very commmon and simple format, called Equirectangular Projection or Plate Carrée. Entering this term into your favorite internet search engine will likely return suitable images for testing. You'll even discover that panoramic photography gets stored in this format - so Marble could even qualify as a panoramic image viewer!
Once you are done you should (re)start Marble to detect the new map. If everything is ok there should be a new map available in the "Map View" listview labeled with the name that you have chosen. Once you select it Marble will start creating the needed tiles.
It needs to be said that this way of creating maps is only suitable for "small" maps as there is a limitation: Automatically Marble can only create tiles from base images that measure up to approximately 10800x5400 pixel. If you want to create tiles from larger images then you are on your own: You need to find a suitable tool or you need to create a script that will create the tiles for you. In this case make sure that you adhere to the naming scheme of directories and tiles (note that tile rows and columns need to get specified in 6-digit format):
{marble-data-base-url}/maps/earth/{theme}/{level}/{row}/{row}_{column}.jpg
While we are using 675x675 pixels as a tile format you should be able to use other tile sizes as well as long as you stick to the fixed size for the whole map theme.
If you have a Marble version >= 0.5.1 installed then you can even create a custom legend, too:
- Either you provide your very own HTML document with the file name "legend.html" in the map's directory. If you do so you can add checkboxes like in the original legend. Just have a look at the global "legend.html" file in the system directory's marble/data directory ( e.g. /usr/share/apps/marble/data/legend/legend.html ).
- Or you just extend the "template" by providing additional legend items. You can do so by adding a legend section to your own .dgml file. Look into the "Atlas" theme's srtm.dgml file to see how it's done. Usually the file is located inside /usr/share/apps/marble/data/maps/earth/srtm/srtm.dgml.
In the next part I'll cover a topic that outlines a few pretty unique internal features of Marble.
Until then I hope that you have fun creating your own maps! Of course I'd be happy about any screenshots or links to actual new maps sent to tackat@kde.org by mail. For help or questions you can join us on IRC ( irc.kde.org, #kde-edu ) or send a mail to our mailing list.
Marble Junior Jobs
Given that Marble is a globe we have a pretty good chance for reaching world domination. However we need your help in terms of patches to accomplish this aim. If you plan to look into Marble's code here are a few easy junior jobs that you might want to start with: First you need to spend 10 minutes to get Marble from the sources and to compile it. You need to check out Marble "trunk". Once that is done you can take the plunge:
- Category EASY: The view shown in the screen shot above shows a debug mode which displays Marble's texture filenames and the level on the globe. This is pretty handy for debugging. However right now this feature is only available by manually changing the source code in line 118 inside marble/src/lib/TextureTile.cpp to:
bool tileIdVisible = true; if(tileIdVisible) m_painter.paintTileId(theme);
Your job would be to either enhance qtmain.cpp or kdemain.cpp to provide a command line option for this feature ( I'd suggest "--texture-id" ). - Category MEDIUM: Currently Marble creates tiles from the install-map at runtime during its first use. However it would be great if we could easily provide prebuilt tiles in the Marble package. For this we need a command-line tool which would get executed at compile time if the data hasn't been tiled already. The tool should be based on the very same TileCreator class that gets used by Marble internally. There is some initial code in marble/src/tilecreator however it's far from done as it still needs some love.