Rendering Rules Introduction

Contents

What Are Rendering Rules?

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.

Why Separate Features?

Some people may be wondering why introduce separate feature specification when the stuff is already specified using OSM tags. There are several reasons why:

  1. It is true that Maperitive currently works mainly on OSM data. But that will not be the case in the future. You can already use other types of geographical data in Maperitive rendering rules: relief contours. And there will be other things you will be able to render: for example GPS tracks and routes, relief maps etc.
  2. Feature naming can be used to target a particular rule on a group of several related features.
  3. The way things are tagged in OSM. Let's face it: OSM mappers are a pretty liberal bunch. You can tag things anyway you like. And so can anyone else. So certain geographical features which are very similar get tagged differently, based on personal and even regional taste. Some people like to use highway=footway, while some like highway=path. And there are some which don't care for the difference, but want to draw a hiking map which shows hiking paths. So they create a feature called hiking path in their rules and they specify the hiking path is both a footway and a path.
  4. Rules importing: in future you will be able to use other rendering rules within your rendering rules. This means that you could have a definition of all of the features you're interested in in one place and then reuse these definitions for various rendering rules (hiking, driving, etc). These could even be stored on the web and shared among many people.

Defining Features

Types Of Features

First we define what we want to show on the map by specifying a list of features. There are three types of features:

  1. Point feature: this is something that's defined by a single point in space. Mountain peak is a good example of a point feature. In OSM, a point features is defined by tagging an OSM node.
  2. Line feature: something defined by a list of connected points in space. A typical example of a line feature is a road. In OSM, line features are defined with OSM ways.
  3. Area feature: also defined by a list of connected points in space, but the points have to define a closed polygon. A forest is an example of an area feature. In OSM, area features are defined using OSM ways which define a polygon.

Feature Specification

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:

features

Then we say we want to specify point features:

	points

We then specify a single point feature:

		mountain peak : natural=peak

After that, we go on specifying a line feature and an area feature.

NOTE: The indentation when writing rules is important.

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

natural=peak

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.

More Complex Specifications

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.

Writing Rules

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):

rules

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.

Rule Processing

"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 ;) ).

if Command

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:

  1. hard hiking path
  2. medium hiking path
  3. easy hiking path

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.

stop Command

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.

for Command

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.

Conclusion

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.

See also: