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

Reply via email to