Attached is something to play with over Easter :-)

The process-destination option now uses the same splitting algorithm like the process-exits option. An additional mkgmap:dest_hint=true is added to each _link with destination set.

Please have a look at the changed lines file how to give appropriate names using the destination tag.

The advantage is that also destinations within big motorway junctions are given at the right place.

Have fun!
WanMil
Index: resources/styles/default/lines
===================================================================
--- resources/styles/default/lines	(revision 2540)
+++ resources/styles/default/lines	(working copy)
@@ -14,10 +14,6 @@
 aeroway=runway [0x27 resolution 20]
 aeroway=taxiway [0x27 resolution 24]
 
-# Set the routing direction
-(highway=motorway|highway=trunk ) & ref=* & destination=* { add mkgmap:display_name =
-'${ref|subst: =>}(${destination|subst:;=> |subst:/=> })' }
-
 # Remove access=yes from highways.
 highway=* & (access=yes|access=permissive|access=designated|access=official) { delete access }
 # Translate motor_vehicle and vehicle access rules.
@@ -42,13 +38,35 @@
 
 # Set highway names to include the reference if there is one
 highway=motorway {name '${ref|highway-symbol:hbox} ${name}' | '${ref|highway-symbol:hbox}' | '${name}' }
-(highway=motorway_link | highway=trunk_link) & mkgmap:exit_hint=true 
+
+(highway=motorway_link | highway=trunk_link) & mkgmap:exit_hint=true & mkgmap:dest_hint=true
+  { delete mkgmap:display_name; 
+    name '${destionation:ref|subst: =>} ${destination|subst:;=> |subst:/=> }' | 
+         '${ref|subst: =>} ${destination|subst:;=> |subst:/=> }' | 
+         '${destination|subst:;=> |subst:/=> }' |
+         'Exit ${mkgmap:exit_hint_ref} ${mkgmap:exit_hint_name}' | 
+         'Exit ${mkgmap:exit_hint_ref} ${mkgmap:exit_hint_exit_to}' | 
+         'Exit ${mkgmap:exit_hint_exit_to}' |
+         'Exit ${mkgmap:exit_hint_name}' |
+         'Exit ${mkgmap:exit_hint_ref}'
+       }
+
+(highway=motorway_link | highway=trunk_link) & mkgmap:exit_hint!=* & mkgmap:dest_hint=true
+  { delete mkgmap:display_name; 
+    name '${destionation:ref|subst: =>} ${destination|subst:;=> |subst:/=> }' |
+         '${ref|subst: =>} ${destination|subst:;=> |subst:/=> }' | 
+         '${destination|subst:;=> |subst:/=> }'
+       }
+
+(highway=motorway_link | highway=trunk_link) & mkgmap:exit_hint=true & mkgmap:dest_hint!=*
   { delete mkgmap:display_name; 
     name 'Exit ${mkgmap:exit_hint_ref} ${mkgmap:exit_hint_name}' | 
          'Exit ${mkgmap:exit_hint_ref} ${mkgmap:exit_hint_exit_to}' | 
          'Exit ${mkgmap:exit_hint_exit_to}' |
          'Exit ${mkgmap:exit_hint_name}' |
-         'Exit ${mkgmap:exit_hint_ref}' }
+         'Exit ${mkgmap:exit_hint_ref}'
+       }
+              
 highway=trunk {name '${ref|highway-symbol:hbox} ${name}' | '${ref|highway-symbol:hbox}' | '${name}'; add mkgmap:display_name = '${name} (${ref})' }
 highway=primary {name '${ref|highway-symbol:box} ${name}' | '${ref|highway-symbol:box}' | '${name}'; add mkgmap:display_name = '${name} (${ref})' }
 highway=secondary | highway=tertiary {name '${ref|highway-symbol:oval} ${name}' | '${ref|highway-symbol:oval}' | '${name}'; add mkgmap:display_name = '${name} (${ref})' }
@@ -108,11 +126,11 @@
 
 # Ways sorted roughly by descending order of class
 highway=motorway {add oneway = yes; add bicycle = no; add foot = no } [0x01 road_class=4 road_speed=7 resolution 16]
-highway=motorway_link & mkgmap:exit_hint=true { add oneway = yes; add bicycle = no; add foot = no; } [0x01 road_class=3 road_speed=2 resolution 20]
+highway=motorway_link & (mkgmap:exit_hint=true | mkgmap:dest_hint=true) { add oneway = yes; add bicycle = no; add foot = no; } [0x06 road_class=3 road_speed=2 resolution 20]
 highway=motorway_link {add oneway = yes; add bicycle = no; add foot = no } [0x09 road_class=3 road_speed=2 resolution 20]
 highway=* & motorroad=yes {add bicycle = no; add foot = no}
 highway=trunk [0x02 road_class=4 road_speed=5 resolution 18]
-highway=trunk_link & mkgmap:exit_hint=true [0x02 road_class=3 road_speed=2 resolution 20]
+highway=trunk_link & (mkgmap:exit_hint=true | mkgmap:dest_hint=true) [0x06 road_class=3 road_speed=2 resolution 20]
 highway=trunk_link [0x09 road_class=3 road_speed=2 resolution 20]
 highway=* & highway!=proposed & motorroad=yes [0x02 road_class=4 road_speed=4 resolution 18]
 highway=primary [0x03 road_class=3 road_speed=4 resolution 19]
Index: src/uk/me/parabola/mkgmap/reader/osm/LinkDestinationHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/LinkDestinationHook.java	(revision 2540)
+++ src/uk/me/parabola/mkgmap/reader/osm/LinkDestinationHook.java	(working copy)
@@ -17,10 +17,11 @@
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.IdentityHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Queue;
 import java.util.Set;
@@ -44,7 +45,7 @@
 	/** Maps which ways can be driven from a given Coord */
 	private IdentityHashMap<Coord, Set<Way>> adjacentWays = new IdentityHashMap<Coord, Set<Way>>();
 	/** Contains all _link ways that have to be processed */
-	private Queue<Way> destinationLinkWays = new ArrayDeque<Way>();
+	private Map<Long, Way> destinationLinkWays = new HashMap<Long, Way>();
 
 	private HashSet<String> tagValues = new HashSet<String>(Arrays.asList(
 			"motorway_link", "trunk_link"));
@@ -53,7 +54,6 @@
 
 	/** Maps which nodes contains to which ways */ 
 	private IdentityHashMap<Coord, Set<Way>> wayNodes = new IdentityHashMap<Coord, Set<Way>>();
-	private boolean onlyMotorwayExitHint;
 	
 	private boolean processDestinations;
 	private boolean processExits;
@@ -61,7 +61,6 @@
 	public boolean init(ElementSaver saver, EnhancedProperties props) {
 		this.saver = saver;
 		nameTags = LocatorUtil.getNameTags(props);
-		onlyMotorwayExitHint = props.containsKey("all-exit-hints") == false;
 		processDestinations = props.containsKey("process-destination");
 		processExits = props.containsKey("process-exits");
 		return processDestinations || processExits;
@@ -114,103 +113,7 @@
 				// put it the list of ways that have to be processed
 				if (tagValues.contains(highwayTag)
 						&& w.getTag("destination") != null) {
-					destinationLinkWays.add(w);
-				}
-			}
-		}
-	}
-	
-	/**
-	 * Copies the destination tags of all motorway_link and trunk_link ways to the adjacent ways.
-	 */
-	private void processDestinations() {
-		// process all links with a destination tag
-		// while checking new ways can be added to the list
-		while (destinationLinkWays.isEmpty() == false) {
-			Way link = destinationLinkWays.poll();
-
-			if (isNotOneway(link)) {
-				// non oneway links cannot be handled. The destination tag is probably wrong.
-				if (log.isInfoEnabled())
-					log.info("Link is not oneway. Do not handle it.", link);
-				continue;
-			}
-
-			// get the last point of the link to retrieve all connected ways
-			Coord connectPoint = link.getPoints().get(link.getPoints().size() - 1);
-			if (isOnewayOppositeDirection(link)) {
-				// for reverse oneway ways it's the first point
-				connectPoint = link.getPoints().get(0);
-			}
-
-			String destinationTag = link.getTag("destination");
-			
-			Set<Way> connectedWays = adjacentWays.get(connectPoint);
-			if (connectedWays == null) {
-				connectedWays = Collections.emptySet();
-			} else {
-				connectedWays = new HashSet<Way>(connectedWays);
-			}
-			connectedWays.remove(link);
-
-			if (log.isInfoEnabled())
-				log.info("Link", link);
-			for (Way connection : connectedWays) {
-				if (connection.getTag("destination") != null) {
-					if (log.isInfoEnabled())
-						log.info("Way already has destionation tag", connection);
-					continue;
-				}
-				if (log.isInfoEnabled())
-					log.info("-", connection);
-
-				// check if the connected way can have an unambiguous direction
-				// => it must not have more than one further connections
-				boolean oneDestination = true;
-				List<Coord> pointsToCheck;
-				if (isOnewayInDirection(connection)) {
-					pointsToCheck = connection.getPoints();
-				} else if (isOnewayOppositeDirection(connection)) {
-					pointsToCheck = new ArrayList<Coord>(
-							connection.getPoints());
-					Collections.reverse(pointsToCheck);
-				} else {
-					pointsToCheck = Collections.emptyList();
-					if (log.isInfoEnabled())
-						log.info("Way is not oneway - do not add destination", connection);
-					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(connectPoint)) {
-						break;
-					}
-					Set<Way> furtherConnects = adjacentWays.get(c);
-					for (Way fc : furtherConnects) {
-						String fcDest = fc.getTag("destination");
-						if (fcDest != null
-								&& destinationTag.equals(fcDest) == false) {
-							if (log.isInfoEnabled())
-								log.info("Ambiguous destination:", destinationTag, "!=", fcDest);
-							oneDestination = false;
-							break;
-						}
-					}
-					if (oneDestination == false) {
-						break;
-					}
-				}
-
-				if (oneDestination) {
-					if (log.isInfoEnabled())
-						log.info("Add destination=" + destinationTag, "to", connection);
-					connection.addTag("destination", destinationTag);
-
-					if (tagValues.contains(connection.getTag("highway"))) {
-						// it is a link so process that way too
-						destinationLinkWays.add(connection);
-					}
+					destinationLinkWays.put(w.getId(), w);
 				}
 			}
 		}
@@ -416,7 +319,7 @@
 	 * naming of this middle way can be assigned from mkgmap:exit_hint_ref and
 	 * mkgmap:exit_hint_name.
 	 */
-	private void createExitHints() {
+	private void processWays() {
 		// collect all nodes of highway=motorway/trunk ways so that we can check if an exit node
 		// belongs to a motorway/trunk or is a "subexit" within a motorway/trunk junction
 		Set<Coord> motorwayCoords = new HashSet<Coord>();
@@ -431,6 +334,42 @@
 			}
 		}	
 		
+		
+		// remove the adjacent links from the destinationLinkWays list
+		// to avoid duplicate dest_hints
+		Queue<Way> linksWithDestination = new ArrayDeque<Way>();
+		linksWithDestination.addAll(destinationLinkWays.values());
+		log.debug(destinationLinkWays.size(),"links with destination tag");
+		while (linksWithDestination.isEmpty()== false) {
+			Way linkWay = linksWithDestination.poll();
+			String destination = linkWay.getTag("destination");
+
+			log.debug("Check way",linkWay.getId(),linkWay.toTagString());
+			
+			// Retrieve all adjacent ways of the current link
+			Coord c = linkWay.getPoints().get(linkWay.getPoints().size()-1);
+			if (isOnewayOppositeDirection(linkWay)) {
+				c = linkWay.getPoints().get(0);
+			}
+			
+			Set<Way> nextWays = adjacentWays.get(c);
+			if (nextWays != null) {
+				for (Way connectedWay : nextWays) {
+					String nextDest = connectedWay.getTag("destination");
+					log.debug("Followed by",connectedWay.getId(),connectedWay.toTagString());
+
+					if (connectedWay.equals(linkWay) == false && connectedWay.getTag("highway").endsWith("_link")
+							&& destination.equals(nextDest)) {
+						// do not use this way because there is another link before that with the same destination
+						destinationLinkWays.remove(connectedWay.getId());
+						log.debug("Removed",connectedWay.getId(),connectedWay.toTagString());
+					}
+				}
+			}
+		}
+		log.debug(destinationLinkWays.size(),"links with destination tag after cleanup");
+		
+		if (processExits)
 		// get all nodes tagged with highway=motorway_junction
 		for (Node exitNode : saver.getNodes().values()) {
 			if (isTaggedAsExit(exitNode) && saver.getBoundingBox().contains(exitNode.getLocation())) {
@@ -438,8 +377,8 @@
 				boolean isMotorwayExit = motorwayCoords.contains(exitNode.getLocation());
 				boolean isTrunkExit = trunkCoords.contains(exitNode.getLocation());
 				boolean isHighwayExit = isMotorwayExit || isTrunkExit;
-				// use exits only if they are located on a motorway
-				if (onlyMotorwayExitHint && isHighwayExit == false) {
+				// use exits only if they are located on a motorway or trunk
+				if (isHighwayExit == false) {
 					if (log.isDebugEnabled())
 						log.debug("Skip non highway exit:", exitNode.toBrowseURL(), exitNode.toTagString());
 					continue;
@@ -466,6 +405,7 @@
 				
 				// use link ways only
 				for (Way w : exitWays) {
+					destinationLinkWays.remove(w.getId());
 					String highwayLinkTag = w.getTag("highway");
 					if (highwayLinkTag.endsWith("_link")) {
 						log.debug("Try to cut",highwayLinkTag, w, "into three parts for giving hint to exit", exitNode);
@@ -490,6 +430,9 @@
 						} else {
 							hintWay.addTag("mkgmap:exit_hint", "true");
 							
+							if (processDestinations && hintWay.getTag("destination") != null) {
+								hintWay.addTag("mkgmap:dest_hint", "true");
+							}
 							if (exitNode.getTag("ref") != null)
 								hintWay.addTag("mkgmap:exit_hint_ref", exitNode.getTag("ref"));
 							if (exitNode.getTag("exit_to") != null)
@@ -504,6 +447,41 @@
 				}
 			}
 		}
+		
+		if (processDestinations)
+		// use link ways only
+		while (destinationLinkWays.isEmpty() == false) {
+			Way w = destinationLinkWays.values().iterator().next();
+			destinationLinkWays.remove(w.getId());
+			String highwayLinkTag = w.getTag("highway");
+			if (highwayLinkTag.endsWith("_link")) {
+				log.debug("Try to cut",highwayLinkTag, w, "into three parts for giving hint");
+
+				// now create three parts:
+				// wayPart1: 10m having the original tags only
+				// hintWay: 10m having the original tags plus the mkgmap:exit_hint* tags
+				// w: the rest of the original way 
+				
+				Way wayPart1 = cutoffWay(w,10.0, null, null);
+				if (wayPart1 == null) {
+					log.info("Way", w, "is too short to cut at least 10m from it. Cannot create exit hint.");
+					continue;
+				} else {
+					if (log.isDebugEnabled())
+						log.debug("Cut off way", wayPart1, wayPart1.toTagString());
+				}
+				
+				Way hintWay = cutoffWay(w,10.0, null, null);
+				if (hintWay == null) {
+					log.info("Way", w, "is too short to cut at least 20m from it. Cannot create exit hint.");
+				} else {
+					hintWay.addTag("mkgmap:dest_hint", "true");
+					
+					if (log.isInfoEnabled())
+						log.info("Cut off exit hint way", hintWay, hintWay.toTagString());
+				}
+			}
+		}
 	}
 	
 	/**
@@ -552,10 +530,10 @@
 
 		retrieveWays();
 		
-		if (processDestinations)
-			processDestinations();
-		if (processExits)
-			createExitHints();
+//		if (processDestinations)
+//			processDestinations();
+		if (processExits || processDestinations)
+			processWays();
 		
 		cleanup();
 
@@ -591,15 +569,4 @@
 		return "-1".equals(w.getTag("oneway"));
 	}
 
-	/**
-	 * Retrieves if the given way is not oneway.
-	 * @param w the way
-	 * @return <code>true</code> way is not oneway
-	 */
-	private boolean isNotOneway(Way w) {
-		return "no".equals(w.getTag("oneway")) || 
-				(isOnewayInDirection(w) == false
-				 && isOnewayOppositeDirection(w) == false);
-	}
-
 }
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://lists.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to