On the Finnish forum, the senior mapper alv pointed out that the left:*, right:* names for boundary=administrative ways are being made obsolete by boundary relations. I agree with him that boundary relations are the better option, especially with regards to localization. mkgmap can replace name with some other tag, such as name:sv for Swedish, but it would be difficult to have it replace a family of left:*, right:* tags with left:*:sv, right:*:sv.
So, I tried to define a relations rule that would generate a space-separated list of names for a boundary line. For example, the boundary=administrative line http://www.openstreetmap.org/browse/way/38589207 that belongs to the relations of the city borders Vantaa and Helsinki and to the Helsinki suburban borders Tapulikaupunki and Suutarila should get all these names, "Vantaa/Helsinki/Tapulikaupunki/Suutarila", in some order. What happens is that it will get just one of the names, "Suutarila" in my test run: In the relations file, I had this, trying to append each relation name to the mkgmap:boundary_name attribute of each relation member: (type=boundary | type=multipolygon) & boundary=administrative & name=* { echo '${name}'; apply { set mkgmap:boundary_name='${mkgmap:boundary_name}/${name}' | '${name}'; echo '${mkgmap:boundary_name}' } } The problem is that within apply{}, the variable substitutions on the right-hand-side of the "set" and "add" action always refer to the tags of the relation, not to the relation member. Thus, mkgmap:boundary_name will always be empty, and only one relation name will be copied to it. One possible solution is to have a special form of apply{} where SubAction.performOnSubElements(Relation rel) does not invoke addTagAction.setValueTags(rel). A patch that introduces the action apply_local{} is attached. An alternative solution would be to have a special form of variable substitution that refers to the tags of the element itself. One simple way of implementing that could be to introduce the keywords set_local and add_local and add another boolean parameter to AddTagAction that would imply valueTags == null. Yet another solution would be to have a special syntax of variable substitution that would bypass the valueTags, say, $(var) instead of ${var}: (type=boundary | type=multipolygon) & boundary=administrative & name=* { apply { set mkgmap:boundary_name='$(mkgmap:boundary_name)/${name}' | '${name}'; } } Best regards, Marko
Index: src/uk/me/parabola/mkgmap/osmstyle/actions/ActionReader.java =================================================================== --- src/uk/me/parabola/mkgmap/osmstyle/actions/ActionReader.java (revision 1436) +++ src/uk/me/parabola/mkgmap/osmstyle/actions/ActionReader.java (working copy) @@ -55,7 +55,9 @@ public class ActionReader { } else if ("add".equals(cmd)) { actions.add(readTagValue(false)); } else if ("apply".equals(cmd)) { - actions.add(readAllCmd()); + actions.add(readAllCmd(true)); + } else if ("apply_local".equals(cmd)) { + actions.add(readAllCmd(false)); } else if ("name".equals(cmd)) { actions.add(readNameCmd()); } else if ("delete".equals(cmd)) { @@ -81,7 +83,7 @@ public class ActionReader { return actions; } - private Action readAllCmd() { + private Action readAllCmd(boolean setValueTags) { String role = null; if (scanner.checkToken("role")) { scanner.nextToken(); @@ -90,7 +92,7 @@ public class ActionReader { throw new SyntaxException(scanner, "Expecting '=' after role keyword"); role = scanner.nextWord(); } - SubAction subAction = new SubAction(role); + SubAction subAction = new SubAction(role, setValueTags); List<Action> actionList = readActions(); for (Action a : actionList) Index: src/uk/me/parabola/mkgmap/osmstyle/actions/SubAction.java =================================================================== --- src/uk/me/parabola/mkgmap/osmstyle/actions/SubAction.java (revision 1436) +++ src/uk/me/parabola/mkgmap/osmstyle/actions/SubAction.java (working copy) @@ -35,9 +35,11 @@ import uk.me.parabola.mkgmap.reader.osm. public class SubAction implements Action { private final List<Action> actionList = new ArrayList<Action>(); private final String role; + private final boolean setValueTags; - public SubAction(String role) { + public SubAction(String role, boolean setValueTags) { this.role = role; + this.setValueTags = setValueTags; } public void perform(Element el) { @@ -51,7 +53,7 @@ public class SubAction implements Action for (Element el : elements) { if (role == null || role.equals(roles.get(el))) { for (Action a : actionList) { - if (a instanceof AddTagAction) + if (setValueTags && a instanceof AddTagAction) ((AddTagAction) a).setValueTags(rel); a.perform(el); } @@ -67,7 +69,8 @@ public class SubAction implements Action Formatter fmt = new Formatter(); if (role != null) fmt.format("role=%s ", role); - fmt.format("apply {"); + fmt.format(setValueTags ? "apply" : "apply_local"); + fmt.format(" {"); for (Iterator<Action> it = actionList.iterator(); it.hasNext();) { Action a = it.next(); Index: resources/styles/default/relations =================================================================== --- resources/styles/default/relations (revision 1436) +++ resources/styles/default/relations (working copy) @@ -1,7 +1,27 @@ - -# -# You can have rules for relations. Usually you will set tags on the -# elements that make up the relation. +# ------------------------------------------------------------------- +# This is the default mkgmap style file for applying rules on +# OSM relations. Usually you will set tags on the +# elements that make up the relation, and the tags will be +# processed by the rules defined in the "points" or "lines" files. # +# Any line prefaced with # is a comment and will not be applied. +# Each line is a rule, of the generalised format: +# OSM_tag(s)_to_match [Garmin_type_code resolution] +# See http://wiki.openstreetmap.org/wiki/Mkgmap/help/style_rules +# and http://wiki.openstreetmap.org/wiki/Mkgmap/help/Custom_styles +# for more information. + # eg. type=route & route=bus { apply { set route=bus; add rn='${route_no}' ; }} # + +(type=boundary | type=multipolygon) & boundary=administrative & name=* +{ apply + { + set mkgmap:name='${name}' + } + apply_local + { + set mkgmap:boundary_name='${mkgmap:boundary_name}/${mkgmap:name}' | '${mkgmap:name}'; + delete mkgmap:name; + } +} Index: resources/styles/default/lines =================================================================== --- resources/styles/default/lines (revision 1436) +++ resources/styles/default/lines (working copy) @@ -113,7 +113,7 @@ man_made=pipeline {name '${operator}'} [ # The following boundary styles are after the highway rules because ways # are frequently tagged with both and we want the highway to take priority. boundary=administrative -{ name +{ name '${mkgmap:boundary_name}' | '${left:country}/${right:country}' | '${left:state}/${right:state}' | '${left:district}/${right:district}' |
_______________________________________________ mkgmap-dev mailing list mkgmap-dev@lists.mkgmap.org.uk http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev