Maperitive rendering rules specify what gets drawn on the map and how it gets drawn. You start writing rules by specifying features. A feature could be a forest, a motorway, a bench. This answers the "what?" part. After that, you specify the actual rules for these features. This answers the "how?" part.
Rules are specified in a simple text file and can be edited with a text editor.
Some people may be wondering why introduce separate feature specification when the stuff is already specified using OSM tags. There are several reasons why:
First we define what we want to show on the map by specifying a list of features. There are three types of features:
Let's say we want to produce a simple hiking map which shows three different features: mountain peaks, hiking paths and forests (I know, this isn't a very useful map, but let's keep it simple for now). I would open a new text file and write the following text in it:
features points mountain peak : natural=peak lines hiking path : highway=footway areas forest : landuse=forest OR natural=wood
What did we do here? We started by indicating we are specifying features:
Then we say we want to specify point features:
We then specify a single point feature:
mountain peak : natural=peak
After that, we go on specifying a line feature and an area feature.
Now let's see how each feature is defined. Let's get back to the mountain peak:
mountain peak : natural=peak
The first part (before the colon (':')) defines the feature name. Obviously, feature names are used to describe to you (or other users of your rules) what the feature represents. In our case, we have a mountain peak. They also uniquely identify a feature within the rendering rules, so it is important that each feature name should be unique (i.e. no two features should share the same name).
The second part (after the colon) defines what the feature covers. In our case we are targeting mountain peaks in OSM data, which in OSM is usually defined as an OSM node tagged with a key called natural with a value peak. That's why we say
One thing to note here is that we didn't have to explicitly say we are only interested in OSM nodes. Maperitive knows that from the fact that this feature is a point feature. The same logic goes for other types of features: area features will (by default) target only OSM ways which enclose a polygon. Even if an OSM way is tagged the same, it will be ignored by Maperitive if it doesn't define a closed area.
If you take a look at the specification for the forest feature
forest : landuse=forest OR natural=wood
you will notice that the feature actually covers two separate OSM features: landuse=forest and natural=wood. This is an example of slightly more complex feature specification. For more information about specifying features, see Querying Data section.
Once we have specified which features we want to show on our map, we can go and specify rules which will tell Maperitive how to render these features.
We have to mark the part of the file where the rules are by specifying the rules section (just like we did for the features section before):
Let's write a rule for rendering hiking paths as thick red lines. We start the rule by indicating what feature (or features) it is intended for:
target : hiking path
target marks the start of a rule definition. After the colon we specify the name of the feature we want to draw (this is called feature selection, see Feature Selectors for more).
We defined hiking paths as line features, which is obvious. Maperitive will thus render lines (polylines, to be more precise) for all hiking paths it can find. In order to tell Maperitive how these lines should appear, we must use the define command within the rule definition:
define line-color : red line-width : 3
The define command is used to set the value of one or more rendering properties (see Rendering Properties (TODO) for more info about all the rendering properties Maperitive provides). In our case we set the line color to red and the line width to 3 pixels.
Now we need to tell Maperitive to draw something:
draw : line
The draw command instructs Maperitive to do the drawing. The "line" text tells it to draw lines (what a surprise, eh?). In Maperitive's jargon this is called a symbol. There are other symbols supported: fill, icon, text and contour, and there will be more in the future. For more information about this topic, see Map Symbols.
So now we have one rule specified:
target : hiking path define line-color : red line-width : 3 draw : line
It will draw thin red lines for every OSM way tagged highway=footway.
"define" and "draw" are Rule Commands (TODO). The above rule is processed in linear fashion. Firstly, the properties will be set to defined values and then the lines will be drawn using the style we defined. There are other rule commands which enable conditional flow of rule processing. Let's change the rule somewhat:
target : *hiking path define line-width : 3 if : hard hiking path define line-color : red else define line-color : blue draw : line
What's going on here? Don't worry if it looks intimidating at first, once you understand the concept, it should be easy to follow (I hope, otherwise I failed with this design ;) ).
What I did here is to insert a couple of new commands in the rule: "if" and "else". I also changed the target of the rule. It now targets not only the "hiking path" feature, but any feature that has a name that ends with "hiking path". So let's for the sake of argument say we have three types of hiking paths:
What would this rule do? Let's start with the first command:
define line-width : 3
We learned earlier what this command will set the line width to 3 pixels. Notice the line color has not been set? We'll see later why.
Ok, to the next command:
if : hard hiking path define line-color : red
"if" command is a conditional command. It has a nested inner block which is executed only for feature(s) specified by the "if" argument. In our case the if command works on hard hiking paths only! The inner block I mentioned is in our case another "define" command:
define line-color : red
So basically, I told Maperitive to use the red line for hard hiking paths. "if" can be followed with the "else" command, which covers all other alternatives:
else define line-color : blue
I hope you can figure out yourself what this does. Yes, it specifies a blue line for all the other features (in our case for medium and easy hiking paths).
The last command is familiar:
draw : line
It draws lines. Red lines for hard and blue ones for other kinds of hiking paths.
You handle have several alternatives using the "elseif" command:
target : *hiking path define line-width : 3 if : hard hiking path define line-color : red elseif : medium hiking path define line-color : green else define line-color : blue draw : line
In this case the medium hiking path will have its own green color. The blue color will be reserved for easy hiking paths only.
You can also tell Maperitive not to render something. Let's say we only wanted to render hard and medium hiking paths:
target : *hiking path define line-width : 3 if : hard hiking path define line-color : red elseif : medium hiking path define line-color : green else stop draw : line
the "stop" command we used inside the "else" block forces stopping of processing of the rule.
Even though we specified a feature based on some of its properties, there is still a way to separate the feature into subfeatures which can be drawn differently. This is done using the "for" command. For example:
target : *hiking path for : trailblazed=yes define line-width : 5 else define line-width : 3 if : hard hiking path define line-color : red elseif : medium hiking path define line-color : green else define line-color : blue draw : line
At the beginning of the rule we speficied this:
for : trailblazed=yes define line-width : 5 else define line-width : 3
Basically, we instructed Maperitive to render trailblazed hiking paths thicker than those which do not have any trailblazes. "for" command accepts a spatial condition (see Querying Data) and "forks" (divides) the execution of the rule into two separate paths: one for hiking paths with OSM tag trailblazed=yes and one for those without this tag. Each of these paths will then continue processing the rest of the rule commands which specify the color of the line. So we end up with a combination of two line thicknesses and three line colors, which totals in six different line styles, based on how each OSM way is tagged.
"for" command can also be paired with one or more "elsefor" commands like:
target : *road define line-color : yellow border-color : black border-style : solid border-width : 40% for : bridge=yes define border-width : 120% elsefor : tunnel=yes define border-style : dash draw : line
will draw yellow roads. When the road crosses a bridge, it will be drawn with thicker border. When the road goes to a tunnel, its border will be drawn with a dash.
This page gives a quick overview of the main capabilities of Maperitive rendering rules. For more detail about how rules are processed and how Maperitive calculates logical paths, see Rendering Rules Advanced.