Index: src/uk/me/parabola/imgfmt/app/net/RoadNetwork.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/net/RoadNetwork.java	(revision 4298)
+++ src/uk/me/parabola/imgfmt/app/net/RoadNetwork.java	(working copy)
@@ -29,6 +29,7 @@
 import uk.me.parabola.imgfmt.app.Coord;
 import uk.me.parabola.imgfmt.app.CoordNode;
 import uk.me.parabola.log.Logger;
+import uk.me.parabola.mkgmap.reader.osm.RestrictionRelation;
 import uk.me.parabola.util.EnhancedProperties;
 
 /**
@@ -397,14 +398,11 @@
 			// We can have multiple arcs with different RoadDef objects that refer to the same 
 			// OSM way id. The direction indicator tells us what arc is probably meant.
 			List<RouteArc> possibleToArcs = lastViaNode.getDirectArcsOnWay(grr.getToWayId());
+			log.info(sourceDesc, "found", possibleToArcs.size(), "candidates for to-arc");
 			RouteArc fromArc = fromArcs.get(0);
 
-			boolean ignoreAngle = false;
-			if (fromArc.getLengthInMeter() <= 0.0001)
-				ignoreAngle = true;
-			if (grr.getDirIndicator() == '?')
-				ignoreAngle = true;
-			log.info(sourceDesc, "found", possibleToArcs.size(), "candidates for to-arc");
+			boolean ignoreAngle = fromArc.getLengthInMeter() <= 0.0001
+					|| grr.getDirIndicator() == RestrictionRelation.DIR_INDICATOR_IGNORE;
 
 			// group the available arcs by angle 
 			Map<Integer, List<RouteArc>> angleMap = new TreeMap<>();
@@ -704,7 +702,7 @@
 			if (angle > -87 && angle < 87)
 				return true;
 			break;
-		case '?':
+		case RestrictionRelation.DIR_INDICATOR_IGNORE:
 			return true;
 		}
 		return false;
Index: src/uk/me/parabola/mkgmap/reader/osm/RestrictionRelation.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/RestrictionRelation.java	(revision 4298)
+++ src/uk/me/parabola/mkgmap/reader/osm/RestrictionRelation.java	(working copy)
@@ -42,6 +42,9 @@
  */
 public class RestrictionRelation extends Relation {
     private static final Logger log = Logger.getLogger(RestrictionRelation.class);
+    
+    /** no direction indicator available or it should be ignored */
+    public static final char DIR_INDICATOR_IGNORE = '?';
 
     private List<Long> fromWayIds = new ArrayList<>(2);
     private List<Long> toWayIds = new ArrayList<>(2);
@@ -57,11 +60,11 @@
     private boolean evalWasCalled;
     
 	// These tags are not loaded by default but if they exist issue a warning
-	private final static String[] unsupportedTags = { "day_on", "day_off", "hour_on", "hour_off" };
+	private static final String[] unsupportedTags = { "day_on", "day_off", "hour_on", "hour_off" };
 	
-	private final static byte DEFAULT_EXCEPT_MASK = AccessTagsAndBits.FOOT  | AccessTagsAndBits.EMERGENCY;
+	private static final byte DEFAULT_EXCEPT_MASK = AccessTagsAndBits.FOOT  | AccessTagsAndBits.EMERGENCY;
 	
-	private final static List<String> supportedRestrictions = Arrays.asList(
+	private static final List<String> supportedRestrictions = Arrays.asList(
 		"no_right_turn", "no_left_turn", "no_u_turn", "no_straight_on", 
 		"only_right_turn", "only_left_turn", "only_straight_on", 
 		"no_entry", "no_exit"	     
@@ -166,7 +169,7 @@
 		} else if (dirInfo.length() == 1){
 			dirIndicator = dirInfo.charAt(0);
 		} else 
-			dirIndicator = '?';
+			dirIndicator = DIR_INDICATOR_IGNORE;
 		
 		String type = getTag("type");
 		if (type.startsWith("restriction:")){
@@ -329,8 +332,8 @@
 					log.warn(messagePrefix,"way",way.toBrowseURL(),"has less than 2 points, restriction is ignored");
 					valid = false;
 				} else {
-					if (way.getPoints().get(0) == way.getPoints().get(way.getPoints().size()-1)){
-						if (ways == toWays && dirIndicator != '?')
+					if (way.hasIdenticalEndPoints()) {
+						if (ways == toWays && dirIndicator != DIR_INDICATOR_IGNORE)
 							continue; // we try to determine the correct part in RoadNetwork 
 						log.warn(messagePrefix, "way", way.toBrowseURL(), "starts and ends at same node, don't know which one to use");
 						valid = false;
@@ -411,9 +414,6 @@
 				valid = false;
 			} 
 		}
-		if (valid && !viaWays.isEmpty() && restriction.startsWith("only")){
-			log.warn(messagePrefix, "check: 'via' way(s) are used in",restriction,"restriction");
-		}
 		if (valid){
 			// make sure that via way(s) don't appear in the from or to lists 
 			for (Way w: viaWays){
@@ -513,28 +513,28 @@
 		if (!valid)
 			return;
 	    List<CoordNode> viaNodes = new ArrayList<>();
-		for (Coord v: viaPoints){
+		for (Coord v : viaPoints) {
 			CoordNode vn = nodeIdMap.get(v);
-			if (vn == null){
-				log.warn(messagePrefix,"via node is not a routing node, restriction relation is ignored");
+			if (vn == null) {
+				log.warn(messagePrefix, "via node is not a routing node, restriction relation is ignored");
 				return;
 			}
 			viaNodes.add(vn);
 		}
 
-		if (viaNodes.size() > 6){
-			log.warn(messagePrefix,"has more than 6 via nodes, this is not supported");
+		if (viaNodes.size() > 6) {
+			log.warn(messagePrefix, "has more than 6 via nodes, this is not supported");
 			return;
 		}
-		if(restriction == null){
+		if (restriction == null) {
 			log.error("internal error: can't add valid restriction relation", this.getId(), "type", restriction);
 			return;
 		}
 		int addedRestrictions = 0;
 		GeneralRouteRestriction grr;
-		if(restriction.startsWith("no_")){
-			for (long fromWayId : fromWayIds){
-				for (long toWayId : toWayIds){
+		if (restriction.startsWith("no_")) {
+			for (long fromWayId : fromWayIds) {
+				for (long toWayId : toWayIds) {
 					grr = new GeneralRouteRestriction("not", exceptMask, messagePrefix);
 					grr.setFromWayId(fromWayId);
 					grr.setToWayId(toWayId);
@@ -545,21 +545,30 @@
 				}
 			}
 			if (log.isInfoEnabled())
-				log.info(messagePrefix, restriction, "translated to",addedRestrictions,"img file restrictions");
-		}
-		else if(restriction.startsWith("only_")){
-			grr = new GeneralRouteRestriction("only", exceptMask, messagePrefix);
-			grr.setFromWayId(fromWayIds.get(0));
-			grr.setToWayId(toWayIds.get(0));
-			grr.setViaNodes(viaNodes);
-			grr.setViaWayIds(viaWayIds);
-			grr.setDirIndicator(dirIndicator);
-			int numAdded = collector.addRestriction(grr);
-			if (numAdded > 0)
-				log.info(messagePrefix, restriction, "added - allows routing to way", toWayIds.get(0));
-
-		}
-		else {
+				log.info(messagePrefix, restriction, "translated to", addedRestrictions, "img file restrictions");
+		} else if (restriction.startsWith("only_")) {
+			char usedDirIndicator = dirIndicator;
+			while (true) {
+				grr = new GeneralRouteRestriction("only", exceptMask, messagePrefix);
+				grr.setFromWayId(fromWayIds.get(0));
+				grr.setToWayId(toWayIds.get(0));
+				grr.setViaNodes(viaNodes);
+				grr.setViaWayIds(viaWayIds);
+				grr.setDirIndicator(usedDirIndicator);
+				int numAdded = collector.addRestriction(grr);
+				if (numAdded > 0)
+					log.info(messagePrefix, restriction, "added - allows routing to way", toWayIds.get(0));
+				if (viaNodes.size() <= 1 || viaWayIds.isEmpty())
+					break;
+				// handle only restriction with via way(s)
+				// see http://gis.19327.n8.nabble.com/Turn-Restrictions-using-three-ways-design-guide-for-OSM-mappers-tp5949183.html
+				// change last via way to "to" way and add more restrictions 
+				viaNodes.remove(viaNodes.size() - 1);
+				toWayIds.clear();
+				toWayIds.add(viaWayIds.remove(viaWayIds.size() - 1));
+				usedDirIndicator = DIR_INDICATOR_IGNORE;
+			}
+		} else {
 			log.error("mkgmap internal error: unknown restriction", restriction);
 		}
 	}
