diff --git a/src/uk/me/parabola/imgfmt/app/net/RouteNode.java b/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
index 45d6010..1e67c1e 100644
--- a/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
+++ b/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
@@ -67,6 +67,7 @@ public class RouteNode implements Comparable<RouteNode> {
 	private final CoordNode coord;
 	private char latOff;
 	private char lonOff;
+	private List<RouteArc[]> throughRoutes;
 
 	// this is for setting destination class on arcs
 	// we're taking the maximum of roads this node is
@@ -395,17 +396,31 @@ public class RouteNode implements Comparable<RouteNode> {
 				// determine the outgoing arc that is likely to be the
 				// same road as the incoming arc
 				RouteArc outArc = null;
-				for(RouteArc oa : arcs) {
-					if(oa.getDest() != inArc.getSource()) {
-						// this arc is not going to the same node as
-						// inArc came from
-						if((oa.isForward() || !oa.getRoadDef().isOneway()) &&
-						   possiblySameRoad(inArc, oa)) {
-							outArc = oa;
+
+				if(throughRoutes != null) {
+					for(RouteArc[] pair : throughRoutes) {
+						if(pair[0] == inArc) {
+							outArc = pair[1];
+							log.info("Found through route from " + inArc.getRoadDef() + " to " + outArc.getRoadDef());
 							break;
 						}
 					}
 				}
+
+				if(outArc == null) {
+					for(RouteArc oa : arcs) {
+						if(oa.getDest() != inArc.getSource()) {
+							// this arc is not going to the same node as
+							// inArc came from
+							if((oa.isForward() || !oa.getRoadDef().isOneway()) &&
+							   possiblySameRoad(inArc, oa)) {
+								outArc = oa;
+								break;
+							}
+						}
+					}
+				}
+
 				// if we did not find the outgoing arc, give up with
 				// this incoming arc
 				if(outArc == null) {
@@ -449,11 +464,16 @@ public class RouteNode implements Comparable<RouteNode> {
 						continue;
 					}
 
+					/* mb - I think this will have to go because it
+					 * will stop the through routes working (and I
+					 * can't remember why it's here anyway!)
+
 					if(possiblySameRoad(inArc, otherArc) ||
 					   possiblySameRoad(outArc, otherArc)) {
 						// not obviously a different road so give up
 						continue;
 					}
+					*/
 
 					if(inArc.getRoadDef().isLinkRoad() &&
 					   otherArc.getRoadDef().isLinkRoad()) {
@@ -732,4 +752,23 @@ public class RouteNode implements Comparable<RouteNode> {
 			}
 		}
 	}
+
+	public void addThroughRoute(long roadIdA, long roadIdB) {
+		if(throughRoutes == null)
+			throughRoutes = new ArrayList<RouteArc[]>();
+		for(RouteArc arc1 : incomingArcs) {
+			if(arc1.getRoadDef().getId() == roadIdA) {
+				for(RouteArc arc2 : arcs) {
+					if(arc2.getRoadDef().getId() == roadIdB)
+						throughRoutes.add(new RouteArc[] { arc1, arc2 });
+				}
+			}
+			else if(arc1.getRoadDef().getId() == roadIdB) {
+				for(RouteArc arc2 : arcs) {
+					if(arc2.getRoadDef().getId() == roadIdA)
+						throughRoutes.add(new RouteArc[] { arc1, arc2 });
+				}
+			}
+		}
+	}
 }
diff --git a/src/uk/me/parabola/mkgmap/general/MapCollector.java b/src/uk/me/parabola/mkgmap/general/MapCollector.java
index 07b32d9..6ca5bac 100644
--- a/src/uk/me/parabola/mkgmap/general/MapCollector.java
+++ b/src/uk/me/parabola/mkgmap/general/MapCollector.java
@@ -73,4 +73,10 @@ public interface MapCollector {
 	 * @param exceptMask For exceptions eg. no-left-turn except for buses.
 	 */
 	public void addRestriction(CoordNode fromNode, CoordNode toNode, CoordNode viaNode, byte exceptMask);
+
+	/**
+	 * Add a through route to the map. 
+	 *
+	 */
+	public void addThroughRoute(long junctionNodeId, long roadIdA, long roadIdB);
 }
diff --git a/src/uk/me/parabola/mkgmap/general/MapDetails.java b/src/uk/me/parabola/mkgmap/general/MapDetails.java
index a5707c5..30e638a 100644
--- a/src/uk/me/parabola/mkgmap/general/MapDetails.java
+++ b/src/uk/me/parabola/mkgmap/general/MapDetails.java
@@ -119,6 +119,10 @@ public class MapDetails implements MapCollector, MapDataSource {
 		roadNetwork.addRestriction(fromNode, toNode, viaNode, exceptMask);
 	}
 
+	public void addThroughRoute(long junctionNodeId, long roadIdA, long roadIdB) {
+		roadNetwork.addThroughRoute(junctionNodeId, roadIdA, roadIdB);
+	}
+
 	/**
 	 * Add the given point to the total bounds for the map.
 	 *
diff --git a/src/uk/me/parabola/mkgmap/general/RoadNetwork.java b/src/uk/me/parabola/mkgmap/general/RoadNetwork.java
index 6be2d0c..2740665 100644
--- a/src/uk/me/parabola/mkgmap/general/RoadNetwork.java
+++ b/src/uk/me/parabola/mkgmap/general/RoadNetwork.java
@@ -285,4 +285,10 @@ public class RoadNetwork {
 		vn.addRestriction(new RouteRestriction(fa, ta, exceptMask));
     }
 
+	public void addThroughRoute(long junctionNodeId, long roadIdA, long roadIdB) {
+		RouteNode node = nodes.get(junctionNodeId);
+		assert node != null :  "Can't find node with id " + junctionNodeId;
+
+		node.addThroughRoute(roadIdA, roadIdB);
+	}
 }
diff --git a/src/uk/me/parabola/mkgmap/main/StyleTester.java b/src/uk/me/parabola/mkgmap/main/StyleTester.java
index 998b195..cf994ae 100644
--- a/src/uk/me/parabola/mkgmap/main/StyleTester.java
+++ b/src/uk/me/parabola/mkgmap/main/StyleTester.java
@@ -713,6 +713,9 @@ public class StyleTester implements OsmConverter {
 
 		public void addRestriction(CoordNode fromNode, CoordNode toNode, CoordNode viaNode, byte exceptMask) {
 		}
+
+		public void addThroughRoute(long junctionNodeId, long roadIdA, long roadIdB) {
+		}
 	}
 
 	/**
@@ -753,6 +756,9 @@ public class StyleTester implements OsmConverter {
 		public void addRestriction(CoordNode fromNode, CoordNode toNode, CoordNode viaNode, byte exceptMask) {
 		}
 
+		public void addThroughRoute(long junctionNodeId, long roadIdA, long roadIdB) {
+		}
+
 		public long getStart() {
 			return start;
 		}
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
index 784f238..67e0f3d 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
@@ -22,6 +22,7 @@ import java.util.HashMap;
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.regex.Pattern;
 
@@ -80,6 +81,8 @@ public class StyledConverter implements OsmConverter {
 	// Coord corresponding to the restrictions' 'via' node
 	private final Map<Coord, List<RestrictionRelation>> restrictions = new IdentityHashMap<Coord, List<RestrictionRelation>>();
 
+	private final List<Relation> throughRouteRelations = new ArrayList<Relation>();
+
 	// originalWay associates Ways that have been created due to
 	// splitting or clipping with the Ways that they were derived
 	// from
@@ -386,6 +389,43 @@ public class StyledConverter implements OsmConverter {
 				rr.addRestriction(collector);
 			}
 		}
+
+		for(Relation relation : throughRouteRelations) {
+			Node node = null;
+			Way w1 = null;
+			Way w2 = null;
+			for(Map.Entry<String,Element> member : relation.getElements()) {
+				if("junction".equals(member.getKey())) {
+					if(member.getValue() instanceof Node)
+						node = (Node)member.getValue();
+					else
+						log.error("Through route relation " + relation.toBrowseURL() + " 'junction' member is not a node");
+				}
+				else if(member.getValue() instanceof Way) {
+					Way w = (Way)member.getValue();
+					if(w1 == null)
+						w1 = w;
+					else if(w2 == null)
+						w2 = w;
+					else
+						log.error("Through route relation " + relation.toBrowseURL() + " has more than 2 ways");
+				}
+			}
+			Integer nodeId = null;
+			if(node == null)
+				log.error("Through route relation " + relation.toBrowseURL() + " is missing a 'junction' node");
+			else {
+				nodeId = nodeIdMap.get(node.getLocation());
+				if(nodeId == null)
+					log.error("Through route relation " + relation.toBrowseURL() + " junction node is not a routing node");
+			}
+			if(w1 == null || w2 == null)
+				log.error("Through route relation " + relation.toBrowseURL() + " should have 2 ways that meet at the junction node");
+			if(nodeId != null && w1 != null && w2 != null) {
+				log.info("Adding through route for ways " + w1.toBrowseURL() + " and " + w2.toBrowseURL() + " at " + node.getLocation().toOSMURL()); 
+				collector.addThroughRoute(nodeId, w1.getId(), w2.getId());
+			}
+		}
 	}
 
 	/**
@@ -411,6 +451,9 @@ public class StyledConverter implements OsmConverter {
 				lrr.add(rr);
 			}
 		}
+		else if("through_route".equals(relation.getTag("type"))) {
+			throughRouteRelations.add(relation);
+		}
 	}
 
 	private void addLine(Way way, GType gt) {
diff --git a/src/uk/me/parabola/mkgmap/reader/overview/OverviewMapDataSource.java b/src/uk/me/parabola/mkgmap/reader/overview/OverviewMapDataSource.java
index dd5a54e..2d6e541 100644
--- a/src/uk/me/parabola/mkgmap/reader/overview/OverviewMapDataSource.java
+++ b/src/uk/me/parabola/mkgmap/reader/overview/OverviewMapDataSource.java
@@ -144,6 +144,10 @@ public class OverviewMapDataSource extends MapperBasedMapDataSource
 		getRoadNetwork().addRestriction(fromNode, toNode, viaNode, exceptMask);
 	}
 
+	public void addThroughRoute(long junctionNodeId, long roadIdA, long roadIdB) {
+		getRoadNetwork().addThroughRoute(junctionNodeId, roadIdA, roadIdB);
+	}
+
 	public int getShift() {
 		return 24 - (topBits - 1);
 	}
