Hi,
attached is a patch that implements the proposed completion of the
destination tag.
It can be enabled with the --enable-destination-completion
The code logs which ways are additionally tagged with destionation and
which are skipped:
uk.me.parabola.mkgmap.reader.osm.LinkDestinationHook.level=INFO
Please give it a try. Maybe someone find some additional useful rules
how to complete the destination tag.
At the moment only a "forward" completion is performed, i.e. for all
*_link ways the destination tag is copied to all connected ways in
driving direction. This is not done if the connected way has itself
multiple connections.
WanMil
Hi,
I added following lines to my style file in order to display the
"destination"-Tag on motorway-junctions:
----------
# Set the routing direction
(highway=motorway|highway=motorway_link) & destination=* { add
display_name = '${ref} (${destination})' }
(highway=trunk|highway=trunk_link) & destination=* { add
display_name = '${ref} (${destination})' }
# Set highway names to include the reference if there is one
----------
This works well (see pictures [2] and [3]), but:
When using the Garmin Types 0x08 and 0x09 (Ramp), Garmin is
evaluating the first way behind all the _link ways.
This is not what is stated in the wiki [1]. In most cases,
only the _link ways are tagged.
So the idea is a new mkgmap option --process-destination
which does following pre-processing:
For all _link ways which have a destination-Tag copy the
tag to the following non-link way (motorway or trunk).
Chris
[1] http://wiki.openstreetmap.org/wiki/Key:destination
[2] http://up.picr.de/11670098jg.png
[3] http://up.picr.de/11670102jj.png
Index: src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java (revision 2371)
+++ src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java (working copy)
@@ -59,6 +59,7 @@
new LocationHook(),
new RelationStyleHook(),
new POIGeneratorHook(),
+ new LinkDestinationHook(),
};
protected OsmConverter converter;
private final Set<String> usedTags = new HashSet<String>();
Index: src/uk/me/parabola/mkgmap/reader/osm/LinkDestinationHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/LinkDestinationHook.java (revision 0)
+++ src/uk/me/parabola/mkgmap/reader/osm/LinkDestinationHook.java (revision 0)
@@ -0,0 +1,176 @@
+package uk.me.parabola.mkgmap.reader.osm;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
+
+import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.log.Logger;
+import uk.me.parabola.util.EnhancedProperties;
+
+public class LinkDestinationHook extends OsmReadingHooksAdaptor {
+ private static final Logger log = Logger
+ .getLogger(LinkDestinationHook.class);
+
+ private ElementSaver saver;
+
+ private IdentityHashMap<Coord, Set<Way>> pointToWays = new IdentityHashMap<Coord, Set<Way>>();
+ private Queue<Way> destinationLinkWays = new ArrayDeque<Way>();
+
+ private HashSet<String> tagValues = new HashSet<String>(Arrays.asList(
+ "motorway_link", "trunk_link"));
+
+ public boolean init(ElementSaver saver, EnhancedProperties props) {
+ this.saver = saver;
+ return props.containsKey("enable-destination-completion");
+ }
+
+ private void retrieveWays() {
+ for (Way w : saver.getWays().values()) {
+ String highwayTag = w.getTag("highway");
+ if (highwayTag != null) {
+ List<Coord> points;
+ if (isOnewayInDirection(w)) {
+ points = w.getPoints().subList(0, w.getPoints().size() - 1);
+ } else if (isOnewayReverseDirection(w)) {
+ points = w.getPoints().subList(1, w.getPoints().size());
+ } else {
+ points = w.getPoints();
+ }
+ for (Coord c : points) {
+ Set<Way> ways = pointToWays.get(c);
+ if (ways == null) {
+ ways = new HashSet<Way>(4);
+ pointToWays.put(c, ways);
+ }
+ ways.add(w);
+ }
+
+ if (tagValues.contains(highwayTag)
+ && w.getTag("destination") != null) {
+ destinationLinkWays.add(w);
+ }
+ }
+ }
+ }
+
+ private void cleanup() {
+ pointToWays = null;
+ destinationLinkWays = null;
+ tagValues = null;
+ saver = null;
+ }
+
+ public void end() {
+ log.info("Start LinkDestinationHook");
+
+ retrieveWays();
+
+ while (destinationLinkWays.isEmpty() == false) {
+ Way link = destinationLinkWays.poll();
+
+ if (isNotOneway(link)) {
+ log.info("Link is not oneway. Do not handle it. ", link);
+ continue;
+ }
+
+ Coord endPoint = link.getPoints().get(link.getPoints().size() - 1);
+ if (isOnewayReverseDirection(link)) {
+ endPoint = link.getPoints().get(0);
+ }
+
+ String destinationTag = link.getTag("destination");
+ Set<Way> ws = pointToWays.get(endPoint);
+ Set<Way> connectedWays = (ws == null ? Collections.<Way> emptySet()
+ : new HashSet<Way>(ws));
+ connectedWays.remove(link);
+
+ log.info("Link", link);
+ for (Way connectedWay : connectedWays) {
+ if (connectedWay.getTag("destination") != null) {
+ log.info("Way already has destionation tag", connectedWay);
+ continue;
+ }
+ log.info("-", connectedWay);
+
+ boolean oneDestination = true;
+ List<Coord> pointsToCheck;
+ if (isOnewayInDirection(connectedWay)) {
+ pointsToCheck = connectedWay.getPoints();
+ } else if (isOnewayReverseDirection(connectedWay)) {
+ pointsToCheck = new ArrayList<Coord>(
+ connectedWay.getPoints());
+ Collections.reverse(pointsToCheck);
+ } else {
+ pointsToCheck = Collections.emptyList();
+ log.info("Way is not oneway - do not add destination",
+ connectedWay);
+ oneDestination = false;
+ }
+ // check if the target way has an unambiguous destination
+ // so it has no other connections to other destinations
+ for (Coord c : pointsToCheck) {
+ if (c.equals(endPoint)) {
+ break;
+ }
+ Set<Way> furtherConnects = pointToWays.get(c);
+ for (Way fc : furtherConnects) {
+ String fcDest = fc.getTag("destionation");
+ if (fcDest != null
+ && destinationTag.equals(fcDest) == false) {
+ log.info("Ambiguous destination:", destinationTag,
+ "!=", fcDest);
+ oneDestination = false;
+ break;
+ }
+ }
+ if (oneDestination == false) {
+ break;
+ }
+ }
+
+ if (oneDestination) {
+ log.info("Add destination=" + destinationTag + " to",
+ connectedWay);
+ connectedWay.addTag("destination", destinationTag);
+
+ if (tagValues.contains(connectedWay.getTag("highway"))) {
+ destinationLinkWays.add(connectedWay);
+ }
+ }
+
+ }
+
+ }
+
+ cleanup();
+ }
+
+ private boolean isOnewayInDirection(Way w) {
+ if (w.isBoolTag("oneway")) {
+ return true;
+ }
+ String onewayTag = w.getTag("oneway");
+ String highwayTag = w.getTag("highway");
+ if (onewayTag == null && highwayTag != null
+ && highwayTag.endsWith("_link")) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isOnewayReverseDirection(Way w) {
+ return "-1".equals(w.getTag("oneway"));
+ }
+
+ private boolean isNotOneway(Way w) {
+ return isOnewayInDirection(w) == false
+ && isOnewayReverseDirection(w) == false;
+ }
+}
Index: resources/styles/default/lines
===================================================================
--- resources/styles/default/lines (revision 2371)
+++ resources/styles/default/lines (working copy)
@@ -13,6 +13,12 @@
aeroway=runway [0x27 resolution 20]
aeroway=taxiway [0x27 resolution 24]
+# Set the routing direction
+(highway=motorway|highway=motorway_link) & destination=* { add
+display_name = '${ref} (${destination})' }
+(highway=trunk|highway=trunk_link) & destination=* { add
+display_name = '${ref} (${destination})' }
+
# Remove access=yes from highways.
highway=* & (access=yes|access=permissive|access=designated|access=official) { delete access }
# Translate motor_vehicle and vehicle access rules.
Index: resources/help/en/options
===================================================================
--- resources/help/en/options (revision 2371)
+++ resources/help/en/options (working copy)
@@ -559,5 +559,7 @@
filling of missing information could be enabled using the
"location-autofill" option.
+--enable-destination-completion
+
--verbose
Makes some operations more verbose. Mostly used with --list-styles.
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev