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

Reply via email to