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
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev