File: rules.txt

package info (click to toggle)
mkgmap 0.0.0%2Bsvn4905-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 12,032 kB
  • sloc: java: 73,856; xml: 1,695; python: 713; sh: 240; makefile: 149; perl: 31
file content (1067 lines) | stat: -rw-r--r-- 38,167 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
// 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).

====