Hopefully, these changes will fix the bad routing directions we have
been seeing recently - please test and report success/failure.


diff --git a/src/uk/me/parabola/imgfmt/app/net/RouteNode.java b/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
index 2b8ca79..ea6651e 100644
--- a/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
+++ b/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
@@ -15,6 +15,8 @@
 package uk.me.parabola.imgfmt.app.net;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 
@@ -339,6 +341,29 @@ public class RouteNode implements Comparable<RouteNode> {
 		return false;
 	}
 
+	private static boolean rightTurnRequired(int inHeading, int outHeading, int sideHeading) {
+		// given the headings of the incoming, outgoing and side
+		// roads, decide whether a side road is to the left or the
+		// right of the main road
+
+		// side road heading must be < inverse of incoming heading
+		int a = sideHeading - (inHeading + 180);
+		while(a < -180)
+			a += 360;
+		while(a > 180)
+			a -= 360;
+		if(a > 0)
+			return false;
+
+		// side road heading must be > outgoing heading
+		a = sideHeading - outHeading;
+		while(a < -180)
+			a += 360;
+		while(a > 180)
+			a -= 360;
+		return a > 0;
+	}
+
 	private static int ATH_OUTGOING = 1;
 	private static int ATH_INCOMING = 2;
 
@@ -375,7 +400,25 @@ public class RouteNode implements Comparable<RouteNode> {
 			final int minDiffBetweenOutgoingAndOtherArcs = 45;
 			final int minDiffBetweenIncomingAndOtherArcs = 50;
 
-			for(RouteArc inArc : incomingArcs) {
+			// list of outgoing arcs discovered at this node
+			List<RouteArc> outgoingArcs = new ArrayList<RouteArc>();
+
+			// sort incoming arcs by decreasing class/speed
+			List<RouteArc> inArcs = new ArrayList<RouteArc>(incomingArcs);
+
+			Collections.sort(inArcs, new Comparator<RouteArc>() {
+					public int compare(RouteArc ra1, RouteArc ra2) {
+						int c1 = ra1.getRoadDef().getRoadClass();
+						int c2 = ra2.getRoadDef().getRoadClass();
+						if(c1 == c2)
+							return (ra2.getRoadDef().getRoadSpeed() - 
+									ra1.getRoadDef().getRoadSpeed());
+						return c2 - c1;
+					}
+				});
+
+			// look at incoming arcs in order of decreasing class/speed
+			for(RouteArc inArc : inArcs) {
 
 				if(!inArc.isForward() && inArc.getRoadDef().isOneway()) {
 					// ignore reverse arc if road is oneway
@@ -442,16 +485,27 @@ public class RouteNode implements Comparable<RouteNode> {
 						   oa.getRoadDef().getRoadSpeed() == inArcSpeed) {
 							if(outArc != null) {
 								// multiple arcs have the same road
-								// class as the incoming arc so don't
-								// use any of them as the outgoing arc
+								// class/speed as the incoming arc so
+								// don't use any of them as the
+								// outgoing arc
 								outArc = null;
 								break;
 							}
-							outArc = oa;
+							// oa has the same class/speed as inArc,
+							// now check that oa is not part of
+							// another road by matching names rather
+							// than class/speed because they could be
+							// different
+							boolean paired = false;
+							for(RouteArc z : arcs)
+								if(z != oa && possiblySameRoad(z, oa))
+									paired = true;
+							if(!paired)
+								outArc = oa;
 						}
 					}
 					if(outArc != null)
-						log.info("Matched outgoing arc " + outArc.getRoadDef() + " to " + inArc.getRoadDef() + " using road class (" + inArcClass + ") and speed (" + inArcSpeed + ")"); 
+						log.info("Matched outgoing arc " + outArc.getRoadDef() + " to " + inArc.getRoadDef() + " using road class (" + inArcClass + ") and speed (" + inArcSpeed + ") at " + coord.toOSMURL()); 
 				}
 
 				// if we did not find the outgoing arc, give up with
@@ -460,6 +514,10 @@ public class RouteNode implements Comparable<RouteNode> {
 					//log.info("Can't continue road " + inArc.getRoadDef() + " at " + coord.toOSMURL());
 					continue;
 				}
+
+				// remember that this arc is an outgoing arc
+				outgoingArcs.add(outArc);
+
 				int outHeading = outArc.getInitialHeading();
 				int mainHeadingDelta = outHeading - inHeading;
 				while(mainHeadingDelta > 180)
@@ -507,6 +565,13 @@ public class RouteNode implements Comparable<RouteNode> {
 						continue;
 					}
 
+					if(outgoingArcs.contains(otherArc)) {
+						// this arc was previously matched as an
+						// outgoing arc so we don't want to change its
+						// heading now
+						continue;
+					}
+
 					int otherHeading = otherArc.getInitialHeading();
 					int outToOtherDelta = otherHeading - outHeading;
 					while(outToOtherDelta > 180)
@@ -520,13 +585,13 @@ public class RouteNode implements Comparable<RouteNode> {
 						inToOtherDelta += 360;
 
 					int newHeading = otherHeading;
-					if(outToOtherDelta > 0) {
+					if(rightTurnRequired(inHeading, outHeading, otherHeading)) {
 						// side road to the right
 						if((mask & ATH_OUTGOING) != 0 &&
-						   outToOtherDelta < minDiffBetweenOutgoingAndOtherArcs)
+						   Math.abs(outToOtherDelta) < minDiffBetweenOutgoingAndOtherArcs)
 							newHeading = outHeading + minDiffBetweenOutgoingAndOtherArcs;
 						if((mask & ATH_INCOMING) != 0 &&
-						   inToOtherDelta < minDiffBetweenIncomingAndOtherArcs) {
+						   Math.abs(inToOtherDelta) < minDiffBetweenIncomingAndOtherArcs) {
 							int nh = inHeading + minDiffBetweenIncomingAndOtherArcs;
 							if(nh > newHeading)
 								newHeading = nh;
@@ -535,13 +600,13 @@ public class RouteNode implements Comparable<RouteNode> {
 						if(newHeading > 180)
 							newHeading -= 360;
 					}
-					else if(outToOtherDelta < 0) {
+					else {
 						// side road to the left
 						if((mask & ATH_OUTGOING) != 0 &&
-						   outToOtherDelta > -minDiffBetweenOutgoingAndOtherArcs)
+						   Math.abs(outToOtherDelta) < minDiffBetweenOutgoingAndOtherArcs)
 							newHeading = outHeading - minDiffBetweenOutgoingAndOtherArcs;
 						if((mask & ATH_INCOMING) != 0 &&
-						   inToOtherDelta > -minDiffBetweenIncomingAndOtherArcs) {
+						   Math.abs(inToOtherDelta) < minDiffBetweenIncomingAndOtherArcs) {
 							int nh = inHeading - minDiffBetweenIncomingAndOtherArcs;
 							if(nh < newHeading)
 								newHeading = nh;
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to