Index: src/uk/me/parabola/mkgmap/osmstyle/RoadMerger.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/RoadMerger.java	(revision 4694)
+++ src/uk/me/parabola/mkgmap/osmstyle/RoadMerger.java	(working copy)
@@ -22,6 +22,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import uk.me.parabola.imgfmt.Utils;
 import uk.me.parabola.imgfmt.app.Coord;
@@ -125,13 +126,23 @@
 	private void mergeRoads(ConvertedWay road1, ConvertedWay road2) {
 		// Removes the second line,
 		// Merges the points in the first one
+		Coord mergePoint = road1.getWay().getLastPoint(); // we always add to end of road1
+		startPoints.removeMapping(road2.getWay().getFirstPoint(), road2);
+		endPoints.removeMapping(road2.getWay().getLastPoint(), road2);
+		endPoints.removeMapping(mergePoint, road1);
+		
 		List<Coord> points2 = road2.getWay().getPoints();
-		Coord mergePoint = points2.get(0);
-		Coord endPoint= points2.get(points2.size()-1);
+		Coord endPoint= road2.getWay().getLastPoint();
+		if (endPoint == mergePoint) {
+			endPoint= points2.get(0);
+			points2 = new ArrayList<>(points2);
+			Collections.reverse(points2);
+			if (log.isDebugEnabled()) {
+				log.debug("merged road " + road2.getWay().getId() + " reversed at " + mergePoint + " with end of "
+						+ road1.getWay().getId());
+			}
+		}
 		
-		startPoints.removeMapping(mergePoint, road2);
-		endPoints.removeMapping(endPoint, road2);
-		endPoints.removeMapping(mergePoint, road1);
 
 		road1.getPoints().addAll(points2.subList(1, points2.size()));
 		endPoints.add(endPoint, road1);
@@ -165,13 +176,10 @@
 	public List<ConvertedWay>  merge(List<ConvertedWay> convertedWays,
 			List<RestrictionRelation> restrictions) {
 		List<ConvertedWay> result = new ArrayList<>();
-		List<ConvertedWay> roadsToMerge = new ArrayList<>(convertedWays.size());
-		for (int i = 0; i < convertedWays.size(); i++) {
-			ConvertedWay cw = convertedWays.get(i);
-			if (cw.isValid() && cw.isRoad())
-				roadsToMerge.add(cw);
-		}
-
+		List<ConvertedWay> roadsToMerge = convertedWays.stream()
+				.filter(cw -> cw.isValid() && cw.isRoad())
+				.collect(Collectors.toList());
+		
 		int noRoadsBeforeMerge = roadsToMerge.size();
 		int numMerges = 0;
 		
@@ -212,12 +220,6 @@
 			// get all roads that end with the merge point
 			List<ConvertedWay> endRoads = endPoints.get(mergePoint);
 			
-			if (endRoads.isEmpty() || startRoads.isEmpty()) {
-				// this might happen if another merge operation changed endPoints and/or startPoints
-				mergeCompletedPoints.add(mergePoint);
-				continue;
-			}
-			
 			// go through all combinations and test which combination is the best
 			double bestAngle = Double.MAX_VALUE;
 			ConvertedWay mergeRoad1 = null;
@@ -231,32 +233,34 @@
 				}
 				
 				List<Coord> points1 = road1.getPoints();
-				
-				// go through all candidates to merge
-				for (ConvertedWay road2 : startRoads) {
-					
-					// the second road is merged into the first road
-					// so only the id of the first road is kept
-					// This also means that the second road must not have a restriction on 
-					// both start and end point
-					if (hasRestriction(mergePoint, road2.getWay())
-							|| hasRestriction(road2.getWay().getLastPoint(), road2.getWay())) {
-						continue;
+				for (List<ConvertedWay> candidates : Arrays.asList(startRoads, endRoads)) {
+					// go through all candidates to merge 
+					for (ConvertedWay road2 : candidates) {
+						
+						// the second road is merged into the first road
+						// so only the id of the first road is kept
+						// This also means that the second road must not have a restriction on 
+						// both start and end point
+						if (road1 == road2 || 
+								hasRestriction(mergePoint, road2.getWay())
+								|| hasRestriction(road2.getWay().getLastPoint(), road2.getWay())) {
+							continue;
+						}
+						
+						// check if both roads can be merged
+						if (isMergeable(mergePoint, road1, road2)){
+							// yes they might be merged
+							// calculate the angle between them 
+							// if there is more then one road to merge the one with the lowest angle is merged 
+							double angle = Math.abs(Utils.getAngle(points1.get(points1.size()-2), mergePoint, road2.getPoints().get(1)));
+							log.debug("Road",road1.getWay().getId(),"and road",road2.getWay().getId(),"are mergeable with angle",angle);
+							if (angle < bestAngle) {
+								mergeRoad1 = road1;
+								mergeRoad2 = road2;
+								bestAngle = angle;
+							} 
+						}
 					}
-					
-					// check if both roads can be merged
-					if (isMergeable(mergePoint, road1, road2)){
-						// yes they might be merged
-						// calculate the angle between them 
-						// if there is more then one road to merge the one with the lowest angle is merged 
-						double angle = Math.abs(Utils.getAngle(points1.get(points1.size()-2), mergePoint, road2.getPoints().get(1)));
-						log.debug("Road",road1.getWay().getId(),"and road",road2.getWay().getId(),"are mergeable with angle",angle);
-						if (angle < bestAngle) {
-							mergeRoad1 = road1;
-							mergeRoad2 = road2;
-							bestAngle = angle;
-						} 
-					}
 				}
 			}
 			
@@ -291,7 +295,7 @@
 	}
 
 	/**
-	 * Checks if the given {@code otherRoad} can be merged with this road at 
+	 * Checks if the first road can be merged with the 2nd road at 
 	 * the given {@code mergePoint}.
 	 * @param mergePoint the coord where this road and otherRoad might be merged
 	 * @param road1 1st road instance
@@ -300,6 +304,9 @@
 	 * 	{@code false} the roads cannot be merged at {@code mergePoint}
 	 */
 	private static boolean isMergeable(Coord mergePoint, ConvertedWay road1, ConvertedWay road2) {
+		if(road1 == road2)
+			return false;
+		
 		// check if basic road attributes match
 		if (road1.getRoadClass() != road2.getRoadClass() || road1.getRoadSpeed() != road2.getRoadSpeed()) {
 			return false;
