 Okay, my name is Radmuth. I'm from Bielefeld in Germany. I studied computer science, electric engineering and a little bit of biology there. And I've been using OpenStreetMap for a little bit over a decade now. And in my day job I work as a database support engineer for MariaDB and formally for MySQL. But that is not related to today's talk at all. So what I'm going to talk about is the MapNIC rendering library and how to use it from Python. So what MapNIC does, it is the rendering library that for example renders the map tiles you see in OpenStreetMap. But it can do a lot of other things. So it can process a lot of different input formats. It can produce a lot of different graphics formats as output. And it uses specific style information to do so. And as it is a library and not a standalone program, it also needs a little bit of extra wrapper code to really make it do what you want it to do. So first, on the input side, we can read several different map data formats like shapefiles, which is a specific geospatial file format. Or we can read geospatial data from different databases. Mostly post-GIS, but also the GIS data that MySQL MariaDB can provide. And also what spatial-enabled version of SQLite can provide. And we can natively use GeoJSON files. And also via plug-ins, we can read further file formats like the native OpenStreetMap XML format, GPX tracks, and via the GDEL library, different Raster image formats like satellite images, and stuff like that. And on the output side, we can produce PNG bitmap images in high or low color resolution. That's the usual use case for map tiles as you see them on sites like OpenStreetMap and other map sites that use OpenStreetMap data. But we can also produce JPEG, which is not the optimal format, but can give you better compression rates if file size is an issue. We can produce scalable vector graphics that you can, for example, use in Inkscape or other vector drawing programs to post-process the generated maps. Or we can, for printing, produce PDF or the classic PostScript is also still available. And as styles, we need style information to specify which input objects from the input data stream should look how in the output image. And there are two ways to do that. One is to really use the MAPNIC library functions to define a style information on the go, step by step. That's very flexible, but also takes a lot of effort. So as an alternative, we have a style file format that is a special XML format that is more compact and more easy to use, but not as flexible as if you could decide in your code depending on certain conditions which styles to use. But the typical use case is to use XML styles, and there is a rich collection of different styles for OpenStreetMap publicly available. And we can also convert some other MAP style sheet formats, especially the Carto CSS format, into the XML format that is needed by MAPNIC. So OpenStreetMap for some years now actually uses Carto CSS styles, converts these to MAPNIC XML on the fly and then renders the MAP styles with that. And as already said, MAPNIC is a library, so we need some extra code to tell it what to do. And for that, as it is a C++ library, we have the option to do that directly in C++. But that's complicated and can easily crash. So as an alternative, we have good Python bindings, and that's what I'm mostly going to talk about in the rest of the talk. And there's also now some experimental bindings for PHP 7, but these do not support the full range of MAPNIC capabilities yet. And if you want to use MAPNIC and Python together, you obviously need Python. It doesn't matter if you want to use Python version 2 or version 3, there are bindings for both. And there also go two different MAPNIC versions around still. I only used MAPNIC 3, the current one, but some Linux distributions may still come with version 2 libraries. And if you want to add additional stuff to the generated images, beyond that, what MAPNIC renders itself, you also need the Cairo bindings for Python and maybe libraries for SVG and for font handling. That's what the Pango library is. So on Counterbuntu, this would be the packages that you need. You need the Python 3 MAPNIC bindings. If you haven't installed Python 3 or MAPNIC yet, these will be installed automatically. And you may need the Pango font handling. You may, if you want to put additional SVG images on top, need the RSVG bindings and the general GTK introspection package to make the other two work. So all MAPNIC data sources like shapefiles or database bindings produce a data stream that comes as four kinds of different objects. Simple points, one-dimensional lines, two-dimensional polygons that cover areas, or predefined raster images. They may look different in the actual data source, but that is what the input API then provides to the further stages of the library. Inside MAPNIC, we have three main different kinds of objects that is layers, styles and symbolizes. The layer is what the data source provides as data. So if you use a shapefile, it's everything that is in the shapefile. If you use a database, it is what is produced by the actual database query you bind to a layer. And then we have styles. Styles can assume everything that is in a layer and decide how to actually display these data items. And we have symbolizes. Symbolizes are the things that actually do the work of painting. So the simplest type we have is the point symbolizer that either just draws a point at a certain position or it draws a given image that you can specify like a point of interest icon for shops or for gas stations or whatever you have. Then we have the line symbolizes that draw lines in different styles. So for example, if you want to draw a road, you may want to draw it in yellow and have small black lines at the side to distinguish them from the background. That's what the line symbolizer can do. Then we have the polygon symbolizer that draws and fills areas in a given color and style. And we have the raster symbolizer that just puts raster image data from the input side into the output side. And we have some more sophisticated symbolizes like the marker symbolizer can be repeated if it is used online or polygon data. There's the point. It's just a fixed position. We have a line pattern symbolizer that is similar to the marker symbolizer when we use it online. But with the marker symbolizer, the marker image is always upright. And with the line pattern symbolizer, it follows the direction of the line. So line symbolizer is used, for example, when you want to draw a one-way road which has these little one-way arrows on it. That would draw the line in certain style and then put little arrow symbols on top. We have text symbolizers to put text on the map. Usually helpful if things have names on the map. We have a special marker symbolizer called shield symbolizer that is used for highway numbers and stuff. Depending on the text in the marker, the marker size has to be extended. And it's called shield symbolizer because the highway signs on the US highways look like ancient night shields. We have polygon pattern symbolizer that is, if you want to fill a polygon, not just with a certain color but with a certain repeated pattern. Like on maps, you often have forests in green and little tree symbols in there. So you would have one symbol that has the background color and one tree in it and then it's just repeated to fill the polygon. And we have a building symbolizer that sort of draws pseudo 3D buildings by taking the building height into account. So now let's go to the bison part and start with the simplest example we can have. We just import the map link bindings. We create a map of 600 pixels wide, 300 pixels high, and we render the map to a file. File name word PNG, format PNG, and obviously there is nothing in it yet. We just get a 300x600 pixel image with transparent background. So let's add a little bit to it. First we give the map a background color, steel blue here. Then we define a polygon symbolizer. The only style information we give it is fill all the polygons you see in green. Then we have to set up a style rule that binds to the symbolizer. We have to register the style rule here under the name of countries in the map. And then we define a layer named world and that has a data source. That is a shapefile that contains all borders of our countries in the world. Then we add that layer to the map. We do a zoom all that zooms in on all the data we have on the map. So the map is exactly as large as it has to be to draw all data we specified. And again we render into a file. Now we see something. So we see all the countries in the world. And we also see the borders even though I didn't specify any border style. That's actually an artifact as the polygon symbolizer does anti-alizing on the borders. So that is what's producing the borders here. We'll turn that off in the next example. So the style rules can also filter on the input data. And now if you want to have a map, a world map that has Germany standing out. We can add... First of all we take the symbolizer from the last example and put the anti-alizing factor to zero to get rid of all these border artifacts. Which is the rule. So now we create a second symbolizer object and say this one is going to be filled in red. And we set up a second rule. And this rule gets a filter. So it filters by the expression. By the field there's the name name in the input. And the name should be Germany. And then we draw it again. And we have the map now without the border artifacts but we have Germany standing out in red. So that was the version in doing it in Python only. And let's now look at the XML version. That is much shorter. As all it does is to load the world XML file here. To zoom in on the data again and to render into the PNG file. The map XML looks like this. It starts with a map tag. We can give the background color. We have the polygon style that only fills every country in green. We have the second one with the filter for Germany that fills in red. And we have our layer that uses the style we defined above. It uses the country shape file again. And obviously or hopefully produces the same result. Now for using symbolizers in detail. I have created two simple GeoJSON files that I will use now. So instead of the shape file I used for all the borders. I now use example one GeoJSON. They only have a very simple point symbolizer that just puts a single simple point PNG image on the point position. This is the GeoJSON file for this. Just containing two points. So we get a map that doesn't really look like a map but only has two points on it. We can do the same for GeoJSON containing a line. This line also has extra property name. Which is test street here. Here we use a slightly more complicated symbolizer. So first we need a slightly more complicated rule. So first we need to use a line symbolizer. It just says paint the line in blue. And with the stroke widths of three pixels. Of three points actually. And then we use a text symbolizer that has placement line. Text should be along the line. It is given a font name. It is given a fill color. And a halo fill that we will see in the example of how that looks like. So this is also in test street. Just a blue line with the black text on it. And the halo is the slight white shadow along the letters. So that they stick a bit more out from the background. So even if the text would be painted on black background it would still be visible. And then the other symbolizers are already mentioned. Described here once again. And then finally you may want to decorate your map. So you don't only want to have the rendered result. But you also want to have a title on it. A copyright notice on it or stuff. Whatever you can think of. And for this we can combine the mapnik bindings and the kyro bindings in pyson. As mapnik can use two different render backgrounds. One is a library called AGG that is only used for high quality bitmaps. And it can use the kyro library both for bitmaps and for the vector formats. So for SVG, PDF and PostScript. And so here we do not give it a filename right away. But we first define a kyro surface that has the filename. Then we create a kyro drawing context. Then we set up our map as we did before. But now instead to writing to a file we render to the kyro context. And then we can use that context and put extra things in there. Like here a simple rectangle. So the two dots are from our geojason map rendered by mapnik. And the rectangle is from pyson kyro. We can also use that for putting extra images in our map. Like here a compass rose that just tells us where is the true north on the map. Or we can use the same for text. And so in summary we now have a solution that can render as a base map like here. We could put a lines title on top. We could put a copyright notice on the bottom. And this special case is a neighborhood map of my area where I live. It's not very well visible but there are extra markers here on the map. These markers have numbers and correspond to the list on the right. So if you look for the nearest Krankenhaus or the nearest hospital. You know it is in square f9. Or if you see the marker here and want to know what it is. If you could see the number in here it would be a 3. And you could look it up on the index on the right to find what is marker 3. And there is also a javascript front end for that. So you can produce this kind of map as pdf yourself on the URL above. And actually this all stems from a solution called Maposmatic. That is also a web front end for creating maps. And from which I got all the knowledge for this. And that is used to either print single page large format pdfs with the speed index here on the side. Or you can also use it using the pdf context in Cairo to produce multi-page pdf maps. Like here are the first pages of a little Atlas putlet. So you have a title page to see which area is on which detail page. And then there are 16 detail pages behind this that form an actually little town atlas. So what I learned working on this is code wise it turned out to be easier than I thought. At least as long as you use XML styles and not the programmatic styles. There is always the devil in the details and in the styles. It never looks like you want to in the first try. It is a very flexible solution if you want to mix map data and custom render data. Custom image decorations. And unfortunately what I also found is the documentation of MapNIC and MapNIC Python bindings is not optimal. Okay. Thank you. I also have two sample prints in here but I think we ran out of time. So if you want to see them, you can do that outside. Any quick questions? Yes. I left that out because the time slot was too short. I have conversion code for converting pixel coordinates into map coordinates and the other way around using the MapNIC map object. One more maybe? Okay. Okay. Outside.