diff --git a/src/uk/me/parabola/imgfmt/app/Coord.java b/src/uk/me/parabola/imgfmt/app/Coord.java
index 6a15fce..186ea86 100644
--- a/src/uk/me/parabola/imgfmt/app/Coord.java
+++ b/src/uk/me/parabola/imgfmt/app/Coord.java
@@ -77,10 +77,15 @@ public class Coord implements Comparable<Coord> {
 		return highwayCount;
 	}
 
-	public void incHighwayCount() {
+	public Coord incHighwayCount() {
 		// don't let it wrap
 		if(highwayCount < Byte.MAX_VALUE)
 			++highwayCount;
+		return this;
+	}
+
+	public void zeroHighwayCount() {
+		highwayCount = 0;
 	}
 
 	public boolean getOnBoundary() {
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
index abc8941..44a337c 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
@@ -94,14 +94,19 @@ public class StyledConverter implements OsmConverter {
 
 	private final int MAX_POINTS_IN_ARC = MAX_POINTS_IN_WAY;
 
-	private final int MAX_NODES_IN_WAY = 64; // possibly could be increased
+	private final int MAX_NODES_IN_WAY = MAX_POINTS_IN_WAY;
 
 	private final double MIN_DISTANCE_BETWEEN_NODES = 5.5;
 
 	// nodeIdMap maps a Coord into a nodeId
 	private final Map<Coord, Integer> nodeIdMap = new IdentityHashMap<Coord, Integer>();
 	private int nextNodeId = 1;
-	
+
+	private List<Way> routableWays = new ArrayList<Way>(10000);
+	private List<Way> allWays = new ArrayList<Way>(10000);
+	private List<GType> allTypes = new ArrayList<GType>(10000);
+	private int[] nodeCounts = new int[MAX_NODES_IN_WAY + 1];
+
 	private final Rule wayRules;
 	private final Rule nodeRules;
 	private final Rule relationRules;
@@ -252,6 +257,55 @@ public class StyledConverter implements OsmConverter {
 	 * @param way The OSM way.
 	 */
 	public void convertWay(Way way) {
+
+		// way being null signals that all ways have now been passed
+		if(way == null) {
+			// to minimise the number of routing nodes created, we
+			// need to recalculate the highway counts as some will be
+			// too large due to the fact that a routable way has
+			// shared points with some non-routable feature (line or
+			// shape)
+			log.info("Zeroing highway counts in " + routableWays.size() + " routable ways");
+			for(Way w : routableWays)
+				for(Coord p : w.getPoints())
+					p.zeroHighwayCount();
+
+			log.info("Updating highway counts");
+			for(Way w : routableWays) {
+				if(!w.isBoolTag("mkgmap:synthesised"))
+					for(Coord p : w.getPoints())
+						p.incHighwayCount();
+			}
+			log.info("Processing ways");
+			for(int i = 0; i < allWays.size(); ++i) {
+				Way wi = allWays.get(i);
+				GType ti = allTypes.get(i);
+				if (ti.getFeatureKind() == GType.POLYLINE) {
+					if(ti.isRoad() &&
+					   !MapElement.hasExtendedType(ti.getType())) {
+						addRoad(wi, ti);
+					}
+					else
+						addLine(wi, ti);
+				}
+				else
+					addShape(wi, ti);
+			}
+
+			log.info("Node statistics - " + routableWays.size() + " ways");
+			for(int i = 0; i <= MAX_NODES_IN_WAY; ++i) {
+				int nc = nodeCounts[i];
+				if(nc > 0)
+					log.info("" + nc + " way(s) have " + i + " nodes");
+			}
+
+			routableWays = null;
+			allWays = null;
+			allTypes = null;
+
+			return;
+		}
+
 		if (way.getPoints().size() < 2)
 			return;
 
@@ -262,15 +316,13 @@ public class StyledConverter implements OsmConverter {
 			if(foundType == null)
 				return;
 
-			if (foundType.getFeatureKind() == GType.POLYLINE) {
-				if(foundType.isRoad() &&
-				   !MapElement.hasExtendedType(foundType.getType()))
-					addRoad(way, foundType);
-				else
-					addLine(way, foundType);
-			}
-			else
-				addShape(way, foundType);
+			// remember way and foundType so it can be processed later
+			// after the highway counts have been recalculated
+			allWays.add(way);
+			allTypes.add(foundType);
+			if (foundType.isRoad() &&
+				!MapElement.hasExtendedType(foundType.getType()))
+				routableWays.add(way);
 		}
 		else {
 			preConvertRules(way);
@@ -282,14 +334,13 @@ public class StyledConverter implements OsmConverter {
 
 				postConvertRules(way, foundType);
 
-				if (foundType.getFeatureKind() == GType.POLYLINE) {
-					if(foundType.isRoad())
-						addRoad(way, foundType);
-					else
-						addLine(way, foundType);
-				}
-				else
-					addShape(way, foundType);
+				// remember way and foundType so it can be processed later
+				// after the highway counts have been recalculated
+				allWays.add(way);
+				allTypes.add(foundType);
+				if (foundType.isRoad() &&
+					!MapElement.hasExtendedType(foundType.getType()))
+					routableWays.add(way);
 			} while (!foundType.isFinal());
 		}
 	}
@@ -584,6 +635,8 @@ public class StyledConverter implements OsmConverter {
 
 	void addRoad(Way way, GType gt) {
 
+		log.info("Adding road " + way.toBrowseURL() + " with type 0x" + Integer.toHexString(gt.getType()));
+
 		String oneWay = way.getTag("oneway");
 		if("-1".equals(oneWay) || "reverse".equals(oneWay)) {
 			// it's a oneway street in the reverse direction
@@ -788,6 +841,7 @@ public class StyledConverter implements OsmConverter {
 								// insert a new point after the POI to
 								// make a short stub segment
 								p1 = p.makeBetweenPoint(p1, stubSegmentLength / dist);
+								p1.incHighwayCount();
 								points.add(i + 1, p1);
 							}
 
@@ -846,6 +900,7 @@ public class StyledConverter implements OsmConverter {
 								// insert a new point to make a short
 								// stub segment
 								p1 = p1.makeBetweenPoint(p, stubSegmentLength / dist);
+								p1.incHighwayCount();
 								points.add(i + 1, p1);
 								// as p1 is now no longer a CoordPOI,
 								// the split below will be deferred
@@ -886,6 +941,15 @@ public class StyledConverter implements OsmConverter {
 					nWay.copyTags(way);
 					for(Coord co : lco) {
 						nWay.addPoint(co);
+						if(co.getHighwayCount() == 0) {
+							// either the point is in a synthesised
+							// way or it was added by the clipper
+							// (which should not happen if the ways
+							// were "soft clipped" earlier).
+							if(false && !way.isBoolTag("mkgmap:synthesised"))
+								log.warn("Clipper added point at " + co.toOSMURL());
+							co.incHighwayCount();
+						}
 						if(co.getOnBoundary()) {
 							// this point lies on a boundary
 							// make sure it becomes a node
@@ -1057,7 +1121,7 @@ public class StyledConverter implements OsmConverter {
 			name = "";
 		else
 			name += " ";
-		return name + "(OSM id " + way.getId() + ")";
+		return name + "(" + way.toBrowseURL() + ")";
 	}
 
 	void addRoadWithoutLoops(Way way, GType gt) {
@@ -1221,6 +1285,8 @@ public class StyledConverter implements OsmConverter {
 				}
 			}
 
+			assert p.getHighwayCount() > 0 : "Point " + i + " in way " + debugWayName + " has zero highway count at " + p.toOSMURL() + " (way has " + points.size() + " points)";
+
 			if(p.getHighwayCount() > 1) {
 				// this point is a node connecting highways
 				Integer nodeId = nodeIdMap.get(p);
@@ -1417,6 +1483,14 @@ public class StyledConverter implements OsmConverter {
 		int numNodes = nodeIndices.size();
 		road.setNumNodes(numNodes);
 
+		++nodeCounts[numNodes];
+
+		if(numNodes > 0.9 * points.size()) {
+			String message = "Way " + debugWayName + " has " + points.size() + " points and " + (100 * numNodes / points.size()) + "% of those are nodes, perhaps it overlaps another way?";
+			if(points.size() > 10)
+				log.info(message);
+		}
+
 		if(numNodes > 0) {
 			// replace Coords that are nodes with CoordNodes
 			boolean hasInternalNodes = false;
@@ -1435,6 +1509,7 @@ public class StyledConverter implements OsmConverter {
 				}
 
 				CoordNode thisCoordNode = new CoordNode(coord.getLatitude(), coord.getLongitude(), nodeId, boundary);
+				thisCoordNode.incHighwayCount();
 				points.set(n, thisCoordNode);
 
 				// see if this node plays a role in any turn
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java b/src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
index e2f3c64..95882ca 100644
--- a/src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
+++ b/src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
@@ -136,12 +136,12 @@ public class MultiPolygonRelation extends Relation {
 			int iLon = inList.get(in).getLongitude();
 			if (Math.abs(oLat - iLat) > Math.abs(oLon - iLon)) {
 				int delta = (oLon > iLon)? -1 : 1;
-				outList.add(index++, new Coord(iLat + delta, iLon));
-				outList.add(index, new Coord(oLat + delta, oLon));
+				outList.add(index++, new Coord(iLat + delta, iLon).incHighwayCount());
+				outList.add(index, new Coord(oLat + delta, oLon).incHighwayCount());
 			} else{
 				int delta = (oLat > iLat)? 1 : -1;
-				outList.add(index++, new Coord(iLat, iLon + delta));
-				outList.add(index, new Coord(oLat, oLon + delta));
+				outList.add(index++, new Coord(iLat, iLon + delta).incHighwayCount());
+				outList.add(index, new Coord(oLat, oLon + delta).incHighwayCount());
 			}
 		}
 	}
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java b/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
index 57a6ae1..0f5466d 100644
--- a/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
+++ b/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
@@ -559,6 +559,9 @@ class Osm5XmlHandler extends DefaultHandler {
 		for (Way w: wayMap.values())
 			converter.convertWay(w);
 
+		// signal converter that all ways have been passed
+		converter.convertWay(null);
+
 		wayMap = null;
 
 		RoadNetwork roadNetwork = mapper.getRoadNetwork();
