Rev 4651 | Blame | Compare with Previous | Last modification | View Log | RSS feed
// Set default source language
:language: mkgmap
[[RULES]]
= Style rules =
Rules allow you to take a map feature in the OSM format, which uses a set of tags to describe the feature into the format required by Garmin maps, where features are identified by a number.
The rules for converting points, lines and polygons are held in
correspondingly named files, as described in <<FILES,the structure of a style>>.
Each file contains a number of rules. Rules test the values of the tags of an OSM node, way or relation.
They also select a specific Garmin type based on the result of those tests and set mkgmap internal tags (+mkgmap:*+) to assign specific attributes to a map element.
== Introduction ==
Each rule starts off with an expression to test the value of one or more
tags.
A rule is made up of two or three parts.
The three possible parts are:
* The first part is *required*: this is a set of <<Tag_tests,tests>> that are performed on the tags of the item to be converted.
* The second part is the <<Action_block,action block>> that can be used to do things with the tags of objects that match the tests and is contained in curly braces `{...}`.
* The third part is the <<Element_type,element type definition>> and sets
the Garmin type and sometimes other parameters that will be used if the tests match. This part is contained
in square brackets `[...]`.
If you want to add two or more different map elements you can do this with repeated square brackets following one expression `[...]`
Here is an example of a rule containing all three sections:
[source]
----
natural=cliff { name '${name} cliff' | 'cliff' } [0x10501 resolution 22]
----
* The tests section is +natural=cliff+
* The action block is `{ name '${name} cliff' | 'cliff' }`
* The element type definition is +[0x10501 resolution 22]+
As a general point, space and newlines don't matter. There is no need to
have rules all on the same line, and you can spread them out over several
lines and add extra spaces wherever you like if it helps to make them
easier to read.
.Example with lots of extra space and newlines
[source]
----
natural=cliff
{
name '${name} cliff'
| 'cliff'
}
[
0x10501
resolution 22
]
----
.Example with all unneeded spaces removed
[source]
natural=cliff{name'${name} cliff'|"cliff"}[0x10501 resolution 22]
=== Tag and text values ===
Tag names and vales are often single words consisting of letters and
perhaps digits.
If however a value (or tag, although that is less common) contains a
space or punctuation character then the whole value must be enclosed in
quotation marks. You can use either single quotes (+'+) or
double quotes (+"+).
If your text contains a quote then you must use the other kind
of quote around the value.
[source]
----
highway=primary
"highway"="primary" # quotes not needed, but do no harm
name='Main Street' # quotes needed to keep 'Main Street' as one thing
name="Ten O'Clock Tavern" # Double quotes used because text contains single quotes
----
[[Tag_tests]]
== Tag tests ==
The most common test is that a particular OSM tag has a given value.
So for example if we have
[source]
highway=motorway
This means that we look up the highway tag in the OSM input file and if it exists and has the value
'motorway' then this test has matched.
You can also compare numeric quantities:
[source]
----
population > 10000
lanes >= 2
population < 10000000
----
Respectively, these mean: a population greater than ten thousand, a road with at least two lanes
and a population less than one million.
You may also use regular expressions:
[source]
ele ~ '\d*00'
This checks whether ele is a multiple of 100.
=== Allowed operations
The following table describes the operations that may be used.
.Full list of operations
[width="80%",cols="1,4",frame="topbot",grid="rows",options="header"]
|====
|Operation | description and examples
| tag=value | This matches when a tag has the given value.
| tag!=value | This is true when the tag does not have the given value,
or the tag is not present at all.
|tag=* | Matches when the tag exists, regardless of its value.
|tag!=* | Matches when the tag does _not_ exist.
|tag < value |
Matches when the tag when converted as a number is less than the given value.
If the value is not numeric then this is always false. This is also the case if
value contains a unit. Conversion for the maxspeed tag can be done with
the maxspeedkmh() and maxspeedmph() function (see <<Functions,Functions>>).
|tag \<= value,
tag > value,
tag >= value |
As above, for less than or equal, greater than and greater than or equal.
|tag ~ REGEX| This is true when the value of the tag matches the given
regular expression.
The http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html[Java regular expression]
syntax is recognised.
For example `name ~ '.*[Ll]ane'` would match every name that ended in
'Lane' or 'lane'.
| ! (expr) |
The 'not' operator ('!') reverses the truth of the expression following.
That expression must be in parentheses.
|====
=== Combining tag tests ===
Although it is possible to convert many OSM nodes and ways just using one
tag, it is also often necessary to use more than one.
For example, say you want to take roads that are tagged both as
+highway=unclassified+ and +lanes>2+ differently to roads that are
just +highway=unclassified+. In this type of case, you might create two
separate rules as follows:
[source]
----
highway=unclassified & lanes>2 [0x06]
highway=unclassified [0x05]
----
This means that roads that are unclassified and have more than two lanes
would use Garmin element type 0x06, whereas unclassified
roads without a lanes tag, or where it is less or equal than 2
would use type 0x05.
It is important to note that the order of the rules is important here. The rules are
matched in the order that they occur in the style file and mkgmap stops trying to apply them after
the first one that matches.
If you had the rules above in the reverse order, then the
+highway=unclassified+ rule would match first to any OSM way with that tag/key pair,
and the second rule would never get applied.
Therefore, in general you want the most specific rules first and simpler, more
general rules later on to catch the cases that are not caught by the more
complex rules.
You can also combine alternatives into the one rule using a logical or, represented
with a pipe (|) symbol. For example
[source]
highway=footway | highway=path [0x07]
This means if the road has either the *highway=footway* tag or the
*highway=path* tags (or both), then the condition matches and mkgmap would
use type 0x07 for the map. This works exactly the same as if you had written
two separate rules - one for footway and one for path - and indeed is converted
to two separate rules internally when mkgmap runs.
You are not limited to two tests for a given rule... you can combine and group tests
in almost whatever way you like.
So for a slightly forced example the following would be possible:
[source]
place=town & (population > 1000000 | capital=true) | place=city
This would match if there was a +place+ tag which had the value +town+
and either the population was over a million or it was tagged a capital,
or there was a +place+ tag with the value +city+.
[NOTE]
There used to be some restrictions on the kind of expression you could
use. Now the only restriction is you must have at least one test that
depends on a tag existing. So you cannot match on everything, regardless
of tags, or test for an object that does _not_ have a tag.
=== Comparing the values of two tags ===
Sometimes you may want to compare the values of two tags, rather than
the value of one tag with a fixed value.
Use a dollar sign to indicate that you want the tag value.
[source]
----
# If you had the following tags:
# name=Fford-y-Mor
# name:en=Terrace Road
# name:cy=Fford-y-Mor
name = $name:cy { } # this would match
name = $name:en { } # and this would not
----
This tests if the value of the +name+ tag is the same as the welsh name
tag (+name:cy+)
It is worth noting that the normal case
[source]
----
highway=primary
----
is exactly the same as
[source]
----
$highway=primary
----
[[Functions]]
=== Functions ===
Functions calculate a specific property of an OSM element.
.Style functions
[width="100%",cols="5,1,1,1,11",options="header"]
|=====
|Function |Node |Way |Rel. |Description
|length() | | x | x |
Calculates the length in m. For relations its the sum of all member length (including sub relations).
|area_size() | | x | |
Calculates area size in (garmin units)^2^. A non closed way has an area_size() of 0. In case a polygon is an outer part
of a multipolygon the whole area size of all outer multipolygon parts is returned.
The size of one (garmin unit)^2^ in m^2^ varies depending on the latitude. Sample values:
5.71 m^2^ at latitude 0°
4.03 m^2^ at (\+-)45°
2.85 m^2^ at (\+-)60°
0.5 m^2^ at (+-)85°
|is_complete() | | x | |
+true+ if all nodes of a way are contained in the tile. +false+ if some nodes of the way are missing in the tile.
|is_closed() | | x | |
+true+ the way is closed (start and end point are the same). +false+ the way is not closed and cannot be processed as polygon.
|maxspeedkmh() | | x | |
Retrieves the value of the 'maxspeed' tag converted to km/h.
|maxspeedmph() | | x | |
Retrieves the value of the 'maxspeed' tag converted to mph.
|type() | x | x | x |
Retrieves the type of the OSM element: 'node', 'way', 'relation'.
|osmid() | x | x | x |
Retrieves the id of the OSM element. This can be useful for style debugging purposes. Note that due to internal changes like merging, cutting etc.
some element ids are changed and some have a faked id > 4611686018427387904.
|is_in(*tag*,*value*,*method*) | x | x | |
+true+ if the element is in polygon(s) having the specified *tag*=*value* according to the *method*, +false+ otherwise.
*value* can be \'\*' which matches any polgon having *tag*.
The methods available depend on the Style section:
polygons:
*all* - all of the closed 'way' is within the polygon(s).
*any* - some is within.
points:
*in* - the 'node' is within a polygon.
*in_or_on* - it is within or on the edge.
*on* - it is on the edge.
lines:
*all* - part of the 'way' is within the polygon(s), none is outside; it might touch an edge.
*all_in_or_on* - none is outside.
*on* - it runs along the edge.
*any* - part is within.
*none* - part is outside, none is inside.
A common case is a line outside the polygon that runs to the edge, joining a line that is inside.
The method to match an outside line (*none*) allows part to be on the edge,
likewise, the method to match an inside line (*all*) allows part to be on the edge.
Compared to *all*, the method *all_in_or_on* additionally matches lines which are only on the edge of the polygon.
|is_drive_on_left() | | x | |
+true+ the element is in a drive_on_left country. +false+ the element is not a drive_on_left country or the information given
in the tags mkgmap:admin_level2 and mkgmap:country could not be used to retrieve the information.
|====
The following rule matches for all service ways longer than 50m.
[source]
highway=service & length()>50
[[Action_block]]
== Action block ==
An action block is enclosed in braces +{ ... }+ and contains one or more
statements that can alter the element being displayed; multiple
statements are separated by `;' symbol. When there is an action block, the
<<Element_type,element type definition>> is optional, but if used it must
come after the action block.
A list of all the command that can be used in the action block follows.
In the examples you will see notation of the form `${name}`, this is how
tag values can be substituted into strings, in a similar way to many
computer languages. For full details see
the section on <<VARS,variable substitution>>.
=== add ===
The add command adds a tag if it does not already exist.
This is often used if you want to set the value of a tag as a default but
do not want to overwrite any existing tag.
For example, motorways are one way by default so we need to add the
+oneway=yes+ tag in the style so that is treated as one way by the
device. But there are some stretches of motorway that are one-way and
these will be tagged as +oneway=no+. If we used +set+ then that tagging
would be lost, so we use +add+.
[source]
highway=motorway { add oneway=yes }
The other use is in in relations with the 'apply' command.
All the same you can set any tag you want, it might be useful so you can match
on it elsewhere in the rules.
You can also use substitutions.
[source]
{add name='${ele}'; add name='${ref}';}
These two commands would set the 'name' tag to the value of the 'ele' tag if it exists, or to the value of the 'ref' tag if that exists.
You can also give a list of alternative expressions separated with a
vertical bar in the same way as on the name command. The first
one that is fully defined will be used.
[source]
{add key123 = '${name:en}' | '${name}'; }
If 'key123' is not set it will set 'key123' to the value of the 'name:en' tag if it exists and to the 'name' tag if not.
=== set ===
The 'set' command is just like the 'add' command, except that it sets the
tag, replacing any existing value it had.
=== delete ===
The delete command deletes a tag.
[source]
{ delete key123 }
=== deletealltags ===
The deletealltags command deletes all tags. Usually this stops all further processing of the element.
[source]
{ deletealltags }
=== addlabel ===
Each item in the Garmin map can have up to four labels. Usually only the first label is displayed.
On some Garmin units the second label is used for routing instructions. The third
and fourth label are known to be used for address search only. The four labels can be assigned
by setting the tags +mkgmap:label:n+ where n is a number between 1 and 4.
The addlabel command assigns the first empty +mkgmap:label:n+ tag with the given value.
[source]
{addlabel '${name} (${ref})' | '${ref}' | '${name}'}
If both the +name+ and +ref+ tags are are set, then the first alternative would be
completed and the resulting label might be _Main St (A1)_.
If just +name+ was set, then the first two alternatives can not be fully
substituted and so are ignored, leaving the last alternative +'${name}'+
and so the final label might in that case be _Main St_.
Highway shields can be used in the first label only. You can use the notation
+${tagname|highway-symbol:box}+.
Valid symbols are +interstate+, +shield+, +round+, +hbox+, +box+ and
+oval+. The appropriate kind of highway shield will be added to the value
of +tagname+. The exact result of the way it looks is dependent on where
you view the map.
=== name ===
This sets the first label of the element but only if it is not already set.
This is a helper action. The same effect can be produced with different notations
as it is shown in the following example where all three lines have the same effect.
[source]
----
{name '${name} (${ref})' | '${ref}' | '${name}'}
{add mkgmap:label:1='${name} (${ref})' | '${ref}' | '${name}'}
mkgmap:label:1!=* {set mkgmap:label:1='${name} (${ref})' | '${ref}' | '${name}'}
----
=== addaccess ===
The "addaccess" action sets all unset mkgmap access restriction tags to the given value.
This is a helper action to avoid long action blocks.
[source]
----
{ addaccess 'no' }
----
is the same as
[source]
----
{
add mkgmap:foot=no;
add mkgmap:bicycle=no;
add mkgmap:car=no;
add mkgmap:taxi=no;
add mkgmap:truck=no;
add mkgmap:bus=no;
add mkgmap:emergency=no;
add mkgmap:delivery=no
}
----
=== setaccess ===
The "setaccess" action sets all mkgmap access restriction tags to the given value no matter if
they already have a value or not. This is a helper action to avoid long action blocks.
[source]
----
{ setaccess 'no' }
----
is the same as
[source]
----
{
set mkgmap:foot=no;
set mkgmap:bicycle=no;
set mkgmap:car=no;
set mkgmap:taxi=no;
set mkgmap:truck=no;
set mkgmap:bus=no;
set mkgmap:emergency=no;
set mkgmap:delivery=no
}
----
=== apply ===
The "apply" action only makes sense in relations. Say you have a
relation marking a bus route, but none of the ways that are in the
relation have any special tags to indicate that they form part of that
bus route, and you want to be able to tell from looking at the map which
buses go where. You can write a rule in the *relations file* such as:
[source]
----
type=route & route=bus {
apply {
set route=bus;
set route_ref='${route_ref}';
}
}
----
Then in the *lines file* you will need to write a rule to match _route=bus_.
All the relation rules are run before any others so that this works.
The substitution `${route_ref}` takes the value of the tag on the *relation* and applies
it to each of the ways in the relation.
The substitution `$(route_ref)` (with parenthesis, rather than curly
braces) can be used for accessing the value of the tag on
the actually processed *member* of the relation, e.g.
[source]
----
type=route & route=bus {
apply {
set route=bus;
set name='$(name) ${route_ref}';
}
}
----
The "apply" action can be limited to members with a special role by adding
_role=rolevalue_ after the _apply_ keyword.
[source]
----
type=route & route=bus {
apply role=forward {
set route=bus;
set name='$(name) ${route_ref}';
}
}
----
=== apply_once ===
The apply_once action is like +apply+, but it will apply the action once
per relation member. A round-trip route relation may include the same
ways multiple times, unless all member ways have been defined as parallel
one way streets.
=== apply_first ===
The apply_first action is like +apply+, but it will apply the action only to the
first relation member as appearing in the input file. In combination with the
--add-pois-to-lines option this might be used with route relations to mark the
beginning of a route, presuming that the relation is complete and ordered so
that the first member is the start of the route.
=== echo ===
The echo action prints the element id plus a text to stderr or to where directed by
a logging configuration file. This can be used for quality checks and debugging
purposes. When using a logging configuration file, the messages are logged
with custom level ECHO (1200).
[source]
highway=motorway_link & oneway!=* { echo "motorway_link without oneway tag" }
=== echotags ===
The echotags action prints the element id, all tags and values plus a text to stderr
or to where directed by a logging configuration file. This can be used for style
debugging purposes. When using a logging configuration file, the messages are
logged with custom level ECHO (1200).
[source]
highway=living_street { echotags "This is a living_street" }
[[VARS]]
== Variables
You can substitute the value of tags within strings in an action.
A dollar sign (+$+) introduces the substitution followed by the tag name
surrounded by curly braces like so `${name}`.
The most obvious use for variables is in setting the name of the element.
You are able to use any combination of tags to make the name from.
Here we name a fuel station by its brand and the operator in parentheses following.
[source]
amenity=fuel { name '${brand} (${operator})' } [ 0x2f01 ]
If the operator tag was not set, then the name would not be set because *all*
substitutions in a string must exist for the result to be valid.
This is why the "name" command takes a list of possibilities, if operator
was simply replaced with a blank, then you would have an empty pair of parentheses.
So you would fix the previous rule by adding another name option.
[source]
----
amenity=fuel
{ name '${brand} (${operator})' | '${brand}' }
[ 0x2f01 ]
----
If only the brand tag exists, then the first option will be skipped and the second
will be used.
=== Variable filters
The value of a variable can be modified by 'filters'.
The value of the tag can be transformed in various ways before being
substituted.
A filter is added by adding a vertical bar symbol "|" after the tag name, followed
by the filter name, then a colon ":" and an argument. If there is more than
one argument required then they are usually separated by colons too, but
that is not a rule.
+${tagname|filter:"arg1:arg2"}+
You can apply as many filter expressions to a substitution as you like.
+${tagname|filter1:"f1Args"|filter2:"f2Args"}+
For backward compatibility, most argument strings
do not actually need to be quoted, however we would recommend that you
do for clarity. If you need a pipe symbol or a closing curly backet,
then you must use quotes.
include::rules-filters.txt[]
include::internal-tags.txt[]
[[Element_type]]
== Element type definition ==
As noted above this is contained in square brackets and if used must be the *last part of the rule*.
The first and only mandatory part of this section is the Garmin type code
which must always be written in hexadecimal. Following this the element
type definition rule can contain a number of optional keywords and
values.
=== level ===
This is the highest zoom level that this element should appear at (like
EndLevel in the mp format). The lower the level the detailed the view.
The most detailed, most zoomed in, level is level 0. A map will usually
have between three and five levels. If the level for an object is not
given then it defaults to 0 and so the specified feature will only appear
at the most detailed level.
In the following example, we set highways to appear from zoom level 4 down to zoom level 0:
[source]
-----
highway=motorway [0x01 level 4]
-----
[WARNING]
--
You can use +level+ to place elements into the layers of the map that you
want but you can't force the device to actually display them.
Some pieces of software (such as QLandkarteGT, I believe) will honour
your selections, but actual GPS devices have their own ideas about
which POI's can be shown at which resolutions.
--
.Level ranges
You can also give a range (e.g. 1-3) and the map will then contain the
object only between the specified levels.
[source]
----
highway=motorway [0x01 level 3-5]
-----
In this example, motorways will appear at zoom level 5, which is most
zoomed out, and continue to be visible until zoom level 3, which is
moderately zoomed in, and then will not be shown in zoom levels 2, 1 and
0 (most zoomed-in).
[TIP]
Of course you are unlikely to want a feature to disappear as you zoom in,
but this can be used for interesting effects where a different
representation takes over at the lower zoom levels. For example a
building may be a point at high levels and then become a polygon at lower
levels.
=== resolution ===
This is an alternative way of specifying the zoom level at which an
object appears. It is specified as a number from 1-24, which corresponds
to one of the zoom levels that Garmin hardware recognises. You should
not use resolution if you have used level as they achieve the same
outcome.
In either case, the mapping between level and resolution is given in the
options style file, where you will see something like this:
-----
# The levels specification for this style
#
levels = 0:24, 1:23, 2:22, 3:20, 4:18, 5:16
-----
This sets level zero equal to resolution 24, level 1 to resolution 23 and so on.
Although the default style uses +resolution+ rather than +level+ it is on
the whole much easier to use +level+ as it is immediately clear where the
element will end up. If you use a +resolution+ that is `between' two
levels for example it will only show up in the lower one.
.Resolution ranges
Just as with levels, you can specify a range of resolutions at which an
object should appear. Here is an example.
[source]
----
highway=residential [0x06 resolution 16-22 continue]
highway=residential [0x07 resolution 23-24]
----
This example creates roads of type 0x06 between resolutions 16 and
22, then roads of type 0x07 between resolutions 23 and 24. This
example makes use of the continue statement, which is discussed in more
detail below.
[TIP]
Since 24 is the default upper bound for a range, that second range could
just have been written as the single number `23'.
=== default_name ===
If the element has not already had a name defined elsewhere in the rule,
it will be given the name specified by +default_name+. This might be
useful for things that usually don't have names and don't have a
recognisable separate Garmin symbol. You could give a default name of
`bus stop' for example and all bus stops that didn't have their own name
would now be labelled as such.
[TIP]
Be careful to use this sparingly and not overwhelm the map or the search.
=== road_class ===
Setting this makes the line a "road" and it will be routable and can be
part of an address search.
It gives the class of the road where class 4 is used for major roads that
connect different parts of the country, class 3 is used for roads that
connect different regions, down to class 0 which is used for residential
streets and other roads that you would only use for local travel.
It is important for routing to work well that most roads have lower classes and
there are fewer and fewer roads in each of the higher classes.
Also, the class of connector roads (links, roundabouts, ramps) matches
the class of the highest class of roads being connected.
.Road classes
[width="40%",frame="topbot",grid="rows",cols="<1,<4",options="header"]
|=====
| Class | Used as
| 4 | Major HW/Ramp
| 3 | Principal HW
| 2 | Arterial St / Other HW
| 1 | Minor or Service road
| 0 | Residential Street / Unpaved road / Trail
|=====
=== road_speed ===
This keyword is used along with +road_class+ to indicate that the line is
a "road" that can be used for routing and for address searches.
It is an indication of how fast traffic on the road is. 0 is the slowest and 7 the fastest.
This is *not* a speed limit and does not activate the maximum speed
symbol on the newer Garmin car navigation systems.
The speed limits that Garmin knows are shown in the following table:
.Road Speeds
[width="40%",frame="topbot",grid="rows",cols="<1,<2",options="header"]
|======
| road_speed | highest speed
| 7 | No speed limit
| 6 | 70 mph / 110 kmh
| 5 | 60 mph / 90 kmh
| 4 | 50 mph / 80 kmh
| 3 | 35 mph / 60 kmh
| 2 | 25 mph / 40 kmh
| 1 | 15 mph / 20 kmh
| 0 | 3 mph / 5 kmh
|======
=== continue ===
As discussed above, style rules are matched in the order that they occur
in the style file. By default, for any given OSM object mkgmap will try
each rule in turn until one rule wth a _element type definition_ matches;
it will then stop trying to match further rules against the current OSM
object. If the rule only has an _action block_ mkgmap will continue to
find other matches.
However, if you add a _continue_ statement to the definition block of a
rule, mkgmap will not stop processing the object but will instead carry
on trying to match subsequent rules until it either runs out of rules or
finds a matching rule that does not include a _continue_ statement.
This feature is used when you want more than one symbol to result from
a single OSM element. This could be for clever effects created by
stacking two lines on top of each other.
For example if you want to mark a bridge in a distinctive way you
could match on +bridge=yes+, you would then almost always use +continue+ so
that the +highway+ tag could be matched later. If you failed to do this
then there might be a break in the road for routing purposes.
Note that when using the _continue_ statement, the action block
of the rule (if there is one) will only be applied _within this rule_ and
not during any following rule matches. Use the _continue with_actions_
statement if you want to change this behaviour (see next section).
=== continue with_actions ===
The with_actions statement modifies the continue behaviour in such a way,
that the action block of this rule is also applied, when this element is
checked for additional conversions.
.Example of a full element type definition
[source]
----
[0x2 road_class=3 road_speed=5 level 2
default_name 'example street' continue with_actions]
----
== Including files ==
Its often convenient to split a file into smaller parts or to use the
same rules in two different files. In these cases you can include
one rule file within another.
[source]
include "inc/common";
Here some common rules have been included in a rule file from a directory
called "inc" within the style. Note that the line ends in a semi-colon
which is easy to forget.
[NOTE]
--
The included files don't have to be located within the style and can be
anywhere else.
--
When you include a file, the effect is exactly as if you had replaced the
include line with the contents of the file. An +include+ directive can
occur anywhere that a rule could start, and it is possible to include
another file from with in the file that is included.
.Including from another style
It is also possible to include a file from another style.
To do this you simply add +from stylename+ to the end of the include
statement.
[source]
include "points" from default;
That will include the +points+ file from the default style. This might be
useful if you want to only change a few things about the default style.
== Finalize section ==
The points, lines and polygons style files can have a finalize section at the end
of the style file. It starts with the line +<finalize>+.
The finalize section contains actions only and must not have an element type definition.
Its rules are executed each time an element type definition in the style file matches.
The finalize section is often useful to set the mkgmap internal tags.
.Finalize section in the lines file with access handling
====
Two elements tagged with
Way 1: highway=motorway, ref=A1
Way 2: highway=service, name=Main Road, access=no, foot=yes, bicycle=yes
using the lines file
[source]
----
highway=motorway [0x01 road_class=4 road_speed=7 resolution 15]
highway=service [0x07 road_class=0 road_speed=1 resolution 24]
<finalize>
highway=* { name '${name} (${ref})' | '${name}' | '${ref}' }
highway=motorway { add bicycle=no; add foot=no }
bicycle=* { add mkgmap:bicycle='${bicycle}' }
foot=* { add mkgmap:foot='${foot}' }
access=* { addaccess '${access}' }
----
will result in
Way 1: highway=motorway, ref=A1, mkgmap:label:1=A1, mkgmap:foot=no,
mkgmap:bicycle=no
Road 1 in Garmin map: Type 0x01, Name 'A1', no access for bicycle and foot
Way 2: highway=service, name=Main Road, access=no, foot=yes, bicycle=yes,
mkgmap:label:1=Main Road, mkgmap:foot=yes, mkgmap:bicycle=yes,
mkgmap:car=no, mkgmap:truck=no, mkgmap:bus=no, ...
Road 2 in Garmin map: Type 0x07, Name 'Main Road', no access for all vehicle
types except bicycle and foot
====
[NOTE]
Actions in the finalize section are not persistent in terms of the +continue+ or
+continue with_actions+ statement
== Style syntax extension if then else ==
To avoid the repetition of expressions you can use the following syntax:
if (<<Tag_tests,tests>>) then
i-rule(s)
end
or
if (<<Tag_tests,tests>>) then
rule(s)
else
e-rules(s)
end
[NOTE]
Rules within +if+ and +end+ must be written with an expression.
The shortest valid expression is a pair of round brackets +()+.
So, instead of
[source]
----
boundary=administrative { name '${mkgmap:boundary_name}' }
boundary=administrative & admin_level<3 [0x1e resolution 12]
boundary=administrative & admin_level<5 [0x1d resolution 19]
boundary=administrative & admin_level<7 [0x1c resolution 21]
boundary=administrative & admin_level<9 [0x1c resolution 22]
boundary=administrative [0x1c resolution 22]
----
you may write
[source]
----
if (boundary=administrative) then
() { name '${mkgmap:boundary_name}' }
admin_level<3 [0x1e resolution 12]
admin_level<5 [0x1d resolution 19]
admin_level<7 [0x1c resolution 21]
admin_level<9 [0x1c resolution 22]
() [0x1c resolution 22]
end
----
If statements may also be nested and you can also use them in combination
with the include statement.
[source]
----
if (mkgmap:option:routing=car) then
include "inc/car-rules";
end
if (mkgmap:option:routing=bicycle) then
include "inc/cycle-rules";
end
----
== Troubleshooting ==
For each node/way/relation, mkgmap goes through the tags exactly once in
order from the top of the file downward.
For each rule that matches, any action block will be run.
As soon as a rule that ends with a type definition is found then
processing stops and that is the Garmin symbol that is produced.
The only exception is if the Type Definition contains the
+continue+ statement. In that case _mkgmap_ will continue
looking for further matches.
* Where possible always have the same tag on the left. This will make things more predictable.
* Always set made-up tag names if you want to also match on them later, rather than setting tags that might be used already.
* Use the +echo+ and +echotags+ actions to understand what's going on during style processing.
== Some examples ==
The following are some examples of style rules, with explanations of what they do.
=== Simple examples ===
In the majority of cases everything is very simple. Say you want roads that are tagged as *highway=motorway* to have the Garmin type 0x01 ("motorway") and for it to appear up until the zoom level 3.
Then you would write the following rule.
[source]
----
highway=motorway [0x01 level 3]
----
Nodes that have an id and a subid are referenced by concatenating both ids.
[source]
----
amenity=bank [0x2f06 level 3]
----
This will be explained in more detail in the following sections along
with how to use more than one tag to make the choice.
For a roundabout you may want to use the special Garmin type 0xc in combination with an overlaying way
that shows the road importance. You can do this with two rules like this
[source]
----
junction=roundabout & (highway=tertiary | highway=tertiary_link)
[0x0c road_class=1 road_speed=1 resolution 24 continue]
junction=roundabout & (highway=tertiary | highway=tertiary_link)
[0x10804 resolution 21]
----
or shorter with one rule that has two type definitions
[source]
----
junction=roundabout & (highway=tertiary | highway=tertiary_link)
[0x0c road_class=1 road_speed=1 resolution 24] [0x10804 resolution 21]
----
=== More involved examples ===
A few tips and tricks showing how the rules can be used to
create almost any effect.
.Internet cafes
====
[source]
amenity=cafe & internet_access=wlan {name '${name} (wifi)'} [0x2a14 resolution 23]
====
Checks to see if an OSM object has both the amenity=cafe and internet_access=wlan key/tag pairs.
If name=Joe's Coffee Shop, then the Garmin object will be named _Joe's Coffee Shop (wifi)_.
The Garmin object used will be 0x2a14 and the object will only appear at resolutions 23 and 24
.Guideposts
====
[source]
information=guidepost
{ name '${name} - ${operator} - ${description} '
| '${name} - ${description}'
| '${name}'
| '${description}'
| '${operator}'
| '${ref}'
}
[0x4c02 resolution 23 default_name 'Infopost']
Checks to see if an OSM object has the information=guidepost key/tag pair.
If so then the name will be set depending on the available +name+,
+operator+ and +description+ tags as follows.
1. If for example we have the tags `name="Route 7"`, `operator="Kizomba
National Parks"` and `description="Trail signpost"`, then the Garmin object will be named
_Route 7 - Kizomba National Parks - Trail signpost_.
2. If the OSM object just has the +name+ and +description+ tags set, the Garmin object will be named _Route 7 - Trail signpost_
3. If just the +name+ tag is available, the Garmin object will be named _Route 7_
4. If just the +description+ tag is available, the Garmin object will be named _Trail signpost_;
5. and if just the +operator+ tag is available, the Garmin object will be named _Kizomba National Parks_.
The Garmin object used will be 0x4c02 and will only appear at resolutions 23 and 24
====
.Car sales rooms
====
[source]
shop=car {name '${name} (${operator})' | '${name}' |'${operator}'} [0x2f07 resolution 23]
If name="Alice's Car Salesroom" and operator=Nissan, the Garmin object
will be named _Alice's Car Salesroom (Nissan)_
====
.Opening hours in postcode field
====
This is a trick to get opening hours to show up in the postcode field of
a POI. Tricks like this can enhance the map for certain uses, but of
course may prevent the proper use of the postcode field.
[source]
opening_hours=* {set addr:postcode = '${addr:postcode} open ${opening_hours}'
| 'open ${opening_hours}'}
For _any_ OSM object which has the opening_hours key set to a value, this
sets the postcode to include the opening hours. For example, if
addr:postcode=90210, addr:street=Alya Street, addr:city=Lagos and
addr:housenumber=7 and opening_hours=09.00-17.00, the address field of
the Garmin POI will be _7, Alya Street, Lagos, 90210 open 09.00-17.00_.
====
.Mountain Passes depending on the way they belong to
====
[source]
mkgmap:from-node:mountain_pass=yes & highway=* & highway!=path & highway!=track
{set mkgmap:label:1='${mkgmap:from-node:name}'} [0x5208 resolution 24-14]
Note: This only works if you activated --add-pois-to-lines.
When you activate this option, all points of a line (a way in OpenStreetMap) generate a point.
Those points attributes are those from OpenStreetMap's way. The specific node's
attributes are set as mkgmap:from-node:attribute_name. For instance, here,
all points from a way are available to a "points" rule. We're looking for
mountain passes, but only if they can be reached by something else than a path
or a track. So we match all points that belong to a way that's not a path or a
track, and where the original point is tagged as a mountain pass.
Please note that if the point is part of several ways, you'll get duplicates
(you could use --nearby-poi-rules to solve this).
====