Index: src/uk/me/parabola/imgfmt/app/Coord.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/Coord.java	(revision 2907)
+++ src/uk/me/parabola/imgfmt/app/Coord.java	(working copy)
@@ -38,6 +38,7 @@
 	private final static byte REPLACED_MASK = 0x04;  // bit in flags is true if point was replaced 
 	private final static byte TREAT_AS_NODE_MASK = 0x08; // bit in flags is true if point should be treated as a node
 	private final static byte FIXME_NODE_MASK = 0x10; // bit in flags is true if a node with this coords has a fixme tag
+	private final static byte VIA_NODE_MASK = 0x40; // bit in flags is true if a node with this coords is the via node of a RestrictionRelation
 	private final int latitude;
 	private final int longitude;
 	private byte highwayCount; // number of highways that use this point
@@ -181,6 +182,23 @@
 			this.flags &= ~FIXME_NODE_MASK; 
 	}
 	
+	/**
+	 * @return true if this coordinate belong to a via node of a restriction relation
+	 */
+	public boolean isViaNodeOfRestriction() {
+		return (flags & VIA_NODE_MASK) != 0;
+	}
+
+	/**
+	 * @param b true: Mark the coordinate as  via node of a restriction relation
+	 */
+	public void setViaNodeOfRestriction(boolean b) {
+		if (b) 
+			this.flags |= VIA_NODE_MASK;
+		else 
+			this.flags &= ~VIA_NODE_MASK; 
+	}
+	
 	public int hashCode() {
 		// Use a factor for latitude to span over the whole integer range:
 		// max lat: 4194304
Index: src/uk/me/parabola/imgfmt/app/net/RouteRestriction.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/net/RouteRestriction.java	(revision 2907)
+++ src/uk/me/parabola/imgfmt/app/net/RouteRestriction.java	(working copy)
@@ -59,6 +59,9 @@
 	// mask that specifies which vehicle types the restriction doesn't apply to
 	private final byte exceptMask;
 
+	private final boolean exceptPedestrian;
+	private final boolean exceptEmergency;
+
 	public final static byte EXCEPT_CAR      = 0x01;
 	public final static byte EXCEPT_BUS      = 0x02;
 	public final static byte EXCEPT_TAXI     = 0x04;
@@ -65,6 +68,11 @@
 	public final static byte EXCEPT_DELIVERY = 0x10;
 	public final static byte EXCEPT_BICYCLE  = 0x20;
 	public final static byte EXCEPT_TRUCK    = 0x40;
+	
+	// additional flags that can be passed via exceptMask  
+	public final static byte EXCEPT_FOOT     = 0x08; // not written as such
+	public final static byte EXCEPT_EMERGENCY = (byte)0x80; // not written as such
+	private final static byte SPECIAL_EXCEPTION_MASK = ~(EXCEPT_FOOT|EXCEPT_EMERGENCY);
 
 	/**
 	 * Create a route restriction.
@@ -76,7 +84,9 @@
 		assert from.getSource().equals(to.getSource()) : "arcs in restriction don't meet";
 		this.from = from;
 		this.to = to;
-		this.exceptMask = exceptMask;
+		this.exceptMask = (byte)(exceptMask & SPECIAL_EXCEPTION_MASK); 
+		this.exceptPedestrian = (exceptMask & EXCEPT_FOOT) != 0;
+		this.exceptEmergency  = (exceptMask & EXCEPT_EMERGENCY) != 0;
 	}
 
 	private int calcOffset(RouteNode node, int tableOffset) {
@@ -94,7 +104,12 @@
 	 */
 	public void write(ImgFileWriter writer, int tableOffset) {
 		int header = HEADER;
-
+		
+		if (exceptPedestrian)
+			header |= 0x0200;
+		if (exceptEmergency)
+			header |= 0x0400;
+		
 		if(exceptMask != 0)
 			header |= 0x0800;
 
Index: src/uk/me/parabola/mkgmap/general/RoadNetwork.java
===================================================================
--- src/uk/me/parabola/mkgmap/general/RoadNetwork.java	(revision 2907)
+++ src/uk/me/parabola/mkgmap/general/RoadNetwork.java	(working copy)
@@ -278,9 +278,18 @@
 
 		assert fa != null : "can't locate arc from 'via' node to 'from' node";
 		assert ta != null : "can't locate arc from 'via' node to 'to' node";
-
+		if(!ta.isForward() && ta.getRoadDef().isOneway()) {
+			// the route restriction connects to the "wrong" end of a oneway
+			if ((exceptMask & RouteRestriction.EXCEPT_FOOT) != 0){
+				// pedestrians are allowed
+				log.info("restriction via "+viaNode.getId() + " to " + fromNode.getId() + " ignored because to-arc is wrong direction in oneway ");
+				return;
+			} else {
+				log.info("restriction via "+viaNode.getId() + " to " + fromNode.getId() + " added although to-arc is wrong direction in oneway, but restriction also excludes pedestrians.");
+			}
+		}
 		vn.addRestriction(new RouteRestriction(fa, ta, exceptMask));
-    }
+	}
 
 	public void addThroughRoute(long junctionNodeId, long roadIdA, long roadIdB) {
 		RouteNode node = nodes.get(junctionNodeId);
Index: src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(revision 2907)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(working copy)
@@ -22,8 +22,11 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.logging.Level;
 
 import uk.me.parabola.imgfmt.app.Area;
@@ -32,6 +35,7 @@
 import uk.me.parabola.imgfmt.app.Exit;
 import uk.me.parabola.imgfmt.app.Label;
 import uk.me.parabola.imgfmt.app.net.NODHeader;
+import uk.me.parabola.imgfmt.app.net.RouteRestriction;
 import uk.me.parabola.imgfmt.app.trergn.ExtTypeAttributes;
 import uk.me.parabola.imgfmt.app.trergn.MapObject;
 import uk.me.parabola.log.Logger;
@@ -85,6 +89,8 @@
 	// restrictions associates lists of turn restrictions with the
 	// Coord corresponding to the restrictions' 'via' node
 	private final Map<Coord, List<RestrictionRelation>> restrictions = new IdentityHashMap<Coord, List<RestrictionRelation>>();
+	
+	private Map<Node, List<Way>> poiRestrictions = new LinkedHashMap<Node, List<Way>>();
 
 	private final List<Relation> throughRouteRelations = new ArrayList<Relation>();
 
@@ -500,6 +506,9 @@
 		roadTypes = null;
 		
 		housenumberGenerator.generate(lineAdder);
+
+		createRouteRestrictionsFromPOI();
+		poiRestrictions = null;
 		
 		Collection<List<RestrictionRelation>> lists = restrictions.values();
 		for (List<RestrictionRelation> l : lists) {
@@ -558,6 +567,93 @@
 	}
 
 	/**
+	 * If POI changes access restrictions (e.g. bollards), create corresponding
+	 * route restrictions so that only allowed vehicles/pedestrians are routed
+	 * through this point.
+	 */
+	private void createRouteRestrictionsFromPOI() {
+		Iterator<Entry<Node, List<Way>>> iter = poiRestrictions.entrySet().iterator();
+		while (iter.hasNext()){
+			Entry<Node, List<Way>> entry = iter.next();
+			Node node = entry.getKey();
+			Coord p = node.getLocation();
+			// list of ways that are connected to the poi
+			List<Way> wayList = entry.getValue();
+			boolean[] nodeNoAccess = getNoAccess(node);
+			byte exceptMask = 0;
+			// exclude allowed vehicles/pedestrians from restriction
+			if (nodeNoAccess[RoadNetwork.NO_BIKE] == false)
+				exceptMask |= RouteRestriction.EXCEPT_BICYCLE;
+			if (nodeNoAccess[RoadNetwork.NO_BUS] == false)
+				exceptMask |= RouteRestriction.EXCEPT_BUS;
+			if (nodeNoAccess[RoadNetwork.NO_CAR] == false)
+				exceptMask |= RouteRestriction.EXCEPT_CAR;
+			if (nodeNoAccess[RoadNetwork.NO_DELIVERY] == false)
+				exceptMask |= RouteRestriction.EXCEPT_DELIVERY;
+			if (nodeNoAccess[RoadNetwork.NO_TAXI] == false)
+				exceptMask |= RouteRestriction.EXCEPT_TAXI;
+			if (nodeNoAccess[RoadNetwork.NO_TRUCK] == false)
+				exceptMask |= RouteRestriction.EXCEPT_TRUCK;
+			if (nodeNoAccess[RoadNetwork.NO_FOOT] == false)
+				exceptMask |= RouteRestriction.EXCEPT_FOOT;
+			if (nodeNoAccess[RoadNetwork.NO_EMERGENCY] == false)
+				exceptMask |= RouteRestriction.EXCEPT_EMERGENCY;
+
+			Map<Long,CoordNode> otherNodeIds = new LinkedHashMap<Long, CoordNode>();
+			CoordNode viaNode = null;
+			boolean viaIsUnique = true;
+			for (Way way:wayList){
+				CoordNode lastNode = null;
+				for (Coord co: way.getPoints()){
+					// not 100% fail safe: points may have been replaced before
+					if (co instanceof CoordNode == false)
+						continue;
+					CoordNode cn = (CoordNode) co;
+					if (p.equals(cn)){
+						if (viaNode == null)
+							viaNode = cn;
+						else if (viaNode != cn){
+							log.error("Found multiple points with equal coords as CoordPOI at " + p.toOSMURL());
+							viaIsUnique = false;
+						}
+						if (lastNode != null)
+							otherNodeIds.put(lastNode.getId(),lastNode);
+					} else {
+						if (p.equals(lastNode))
+							otherNodeIds.put(cn.getId(),cn);
+					}
+					lastNode = cn;
+				}
+			}
+			if (viaNode == null){
+				log.error("Did not find CoordPOI node at " + p.toOSMURL() + " in ways " + wayList);
+				continue;
+			}
+			if (viaIsUnique == false){
+				log.error("Found multiple points with equal coords as CoordPOI at " + p.toOSMURL());
+				continue;
+			}
+			if (otherNodeIds.size() < 2){
+				log.info("Access restriction in POI node " + node.toBrowseURL() + " was ignored, has no effect on any connected way");
+				continue;
+			}
+			List<CoordNode> otherNodesUniqe = new ArrayList<CoordNode>(otherNodeIds.values());
+			for (int i = 0; i < otherNodesUniqe.size(); i++){
+				CoordNode from = (CoordNode) otherNodesUniqe.get(i);
+				for (int j = i+1; j < otherNodesUniqe.size(); j++){
+					CoordNode to = (CoordNode) otherNodesUniqe.get(j);
+					if (to.getId() != viaNode.getId() && from.getId() != viaNode.getId()){
+						collector.addRestriction(from, to, viaNode, exceptMask);
+						collector.addRestriction(to, from, viaNode, exceptMask);
+						log.info("created route restriction from poi for node " + node.toBrowseURL());
+					}
+				}
+			}
+		}
+	}
+
+
+	/**
 	 * Run the rules for this relation.  As this is not an end object, then
 	 * the only useful rules are action rules that set tags on the contained
 	 * ways or nodes.  Every rule should probably start with 'type=".."'.
@@ -581,7 +677,9 @@
 				List<RestrictionRelation> lrr = restrictions.get(rr.getViaCoord());
 				if(lrr == null) {
 					lrr = new ArrayList<RestrictionRelation>();
-					restrictions.put(rr.getViaCoord(), lrr);
+					Coord via = rr.getViaCoord();
+					via.setViaNodeOfRestriction(true);
+					restrictions.put(via, lrr);
 				}
 				lrr.add(rr);
 			}
@@ -750,6 +848,21 @@
 		}
 	}
 
+	private boolean[] getNoAccess(Element osmElement){
+		boolean[] noAccess = new boolean[RoadNetwork.NO_MAX];
+		noAccess[RoadNetwork.NO_EMERGENCY] = osmElement.isNotBoolTag("mkgmap:emergency");
+		noAccess[RoadNetwork.NO_DELIVERY] = osmElement.isNotBoolTag("mkgmap:delivery");
+		noAccess[RoadNetwork.NO_CAR] = osmElement.isNotBoolTag("mkgmap:car");
+		noAccess[RoadNetwork.NO_BUS] = osmElement.isNotBoolTag("mkgmap:bus");
+		noAccess[RoadNetwork.NO_TAXI] = osmElement.isNotBoolTag("mkgmap:taxi");
+		noAccess[RoadNetwork.NO_FOOT] = osmElement.isNotBoolTag("mkgmap:foot");
+		noAccess[RoadNetwork.NO_BIKE] = osmElement.isNotBoolTag("mkgmap:bicycle");
+		noAccess[RoadNetwork.NO_TRUCK] = osmElement.isNotBoolTag("mkgmap:truck");
+		// carpool is special => the default is no/unset and the flag is set only if mkgmap:carpool is set to yes
+		noAccess[RoadNetwork.NO_CARPOOL] = osmElement.isBoolTag("mkgmap:carpool");
+		return noAccess;
+	}
+	
 	private boolean hasAccessRestriction(Element osmElement) {
 		for (String tag : ACCESS_TAGS) {
 			if (osmElement.isNotBoolTag(tag)) {
@@ -781,6 +894,8 @@
 			if("roundabout".equals(way.getTag("junction")))
 				log.warn("Roundabout " + way.getId() + " has reverse oneway tag (" + way.getPoints().get(0).toOSMURL() + ")");
 		}
+		
+		addNodesForRestrictions(way);
 
 		if("roundabout".equals(way.getTag("junction"))) {
 			List<Coord> points = way.getPoints();
@@ -849,13 +964,16 @@
 		}
 
 		// process any Coords that have a POI associated with them
+		final double stubSegmentLength = 25; // metres
 		String wayPOI = way.getTag(WAY_POI_NODE_IDS);
 		if (wayPOI != null) {
 			List<Coord> points = way.getPoints();
-
+			
 			// look for POIs that modify the way's road class or speed
-			// this could be e.g. highway=traffic_signals that reduces the
-			// road speed to cause a short increase of traveling time
+			// or contain access restrictions
+			// This could be e.g. highway=traffic_signals that reduces the
+			// road speed to cause a short increase of travelling time
+			// or a barrier
 			for(int i = 0; i < points.size(); ++i) {
 				Coord p = points.get(i);
 				if (p instanceof CoordPOI && ((CoordPOI) p).isUsed()) {
@@ -863,16 +981,45 @@
 					Node node = cp.getNode();
 					if (wayPOI.contains("["+node.getId()+"]")){
 						log.debug("POI",node.getId(),"changes way",way.getId());
+
+						// make sure that we create nodes for all POI that 
+						// are converted to RouteRestrictions
+						if(p.getHighwayCount() < 2 && cp.getConvertToViaInRouteRestriction() && (i != 0 && i != points.size()-1))
+							p.incHighwayCount();
+						
 						String roadClass = node.getTag("mkgmap:road-class");
 						String roadSpeed = node.getTag("mkgmap:road-speed");
 						if(roadClass != null || roadSpeed != null) {
-							// if the way has more than one point
-							// following this one, split the way at the
-							// next point to limit the size of the
-							// affected region
-							if((i + 2) < points.size() &&
-									safeToSplitWay(points, i + 1, i, points.size() - 1)) {
-								Way tail = splitWayAt(way, i + 1);
+							// find good split point after POI
+							Coord splitPoint;
+							double segmentLength = 0;
+							int splitPos = i+1;
+							while( splitPos+1 < points.size()){
+								splitPoint = points.get(splitPos);
+								segmentLength += splitPoint.distance(points.get(splitPos - 1));
+								System.out.println("segment length " + segmentLength);
+								if (splitPoint.getHighwayCount() > 1
+										|| segmentLength > stubSegmentLength - 5)
+									break;
+								splitPos++;
+							}
+							if (segmentLength > stubSegmentLength + 10){
+								// insert a new point after the POI to
+								// make a short stub segment
+								splitPoint = points.get(splitPos);
+								Coord prev = points.get(splitPos-1);
+								double dist = splitPoint.distance(prev);
+								double neededLength = stubSegmentLength - (segmentLength - dist);
+								
+								splitPoint = prev.makeBetweenPoint(splitPoint, neededLength / dist);
+								double newDist = splitPoint.distance(prev);
+								segmentLength += newDist - dist;
+								splitPoint.incHighwayCount();
+								points.add(splitPos, splitPoint);
+							}
+							if((splitPos + 1) < points.size() &&
+									safeToSplitWay(points, splitPos, i, points.size() - 1)) {
+								Way tail = splitWayAt(way, splitPos);
 								// recursively process tail of way
 								addRoad(tail, gt);
 							}
@@ -907,135 +1054,49 @@
 				// the affected region
 				if (i > 0 && (i + 1) < points.size()
 						&& points.get(i + 1) instanceof CoordPOI) {
+					
 					CoordPOI cp = (CoordPOI) points.get(i + 1);
 					Node node = cp.getNode();
 					if (cp.isUsed() && wayPOI.contains("["+node.getId()+"]")){
 						if (node.getTag("mkgmap:road-class") != null
 								|| node.getTag("mkgmap:road-speed") != null) {
-							if (safeToSplitWay(points, i, i - 1,
-									points.size() - 1)) {
-								Way tail = splitWayAt(way, i);
-								// recursively process tail of way
-								addRoad(tail, gt);
+							// find good split point before POI
+							double segmentLength = 0;
+							int splitPos = i;
+							Coord splitPoint;
+							while( splitPos > 0){
+								splitPoint = points.get(splitPos);
+								segmentLength += splitPoint.distance(points.get(splitPos + 1));
+								System.out.println("segment length " + segmentLength);
+								if (splitPoint.getHighwayCount() >= 2
+										|| segmentLength > stubSegmentLength - 5)
+									break;
+								--splitPos;			
 							}
-						}
-					}
-				}
-			}
-
-			// now look for POIs that have an access restriction defined -
-			// if they do, copy the access permissions to the way -
-			// what we want to achieve is modifying the way's access
-			// permissions where it passes through the POI without
-			// affecting the rest of the way too much - to that end we
-			// split the way before and after the POI - if necessary,
-			// extra points are inserted before and after the POI to
-			// limit the size of the affected region
-
-			final double stubSegmentLength = 25; // metres
-			for(int i = 0; i < points.size(); ++i) {
-				Coord p = points.get(i);
-				// check if this POI modifies access and if so, split
-				// the way at the following point (if any) and then
-				// copy its access restrictions to the way
-				if (p instanceof CoordPOI && ((CoordPOI) p).isUsed()) {
-					CoordPOI cp = (CoordPOI) p;
-					Node node = cp.getNode();
-					if (hasAccessRestriction(node) && wayPOI.contains("["+node.getId()+"]")){
-						// if this or the next point are not the last
-						// points in the way, split at the next point
-						// taking care not to produce a short arc
-						if((i + 1) < points.size()) {
-							Coord p1 = points.get(i + 1);
-							// check if the next point is further away
-							// than we would like
-							double dist = p.distance(p1);
-							if(dist >= (2 * stubSegmentLength)) {
-								// insert a new point after the POI to
+							if (segmentLength > stubSegmentLength + 10){
+								// insert a new point before the POI to
 								// make a short stub segment
-								p1 = p.makeBetweenPoint(p1, stubSegmentLength / dist);
-								p1.incHighwayCount();
-								points.add(i + 1, p1);
+								splitPoint = points.get(splitPos);
+								Coord prev = points.get(splitPos+1);
+								double dist = splitPoint.distance(prev);
+								double neededLength = stubSegmentLength - (segmentLength - dist);
+								splitPoint = prev.makeBetweenPoint(splitPoint, neededLength / dist);
+								segmentLength += splitPoint.distance(prev) - dist;
+								splitPoint.incHighwayCount();
+								splitPos++;
+								points.add(splitPos, splitPoint);
 							}
-
-							// now split the way at the next point to
-							// limit the region that has restricted
-							// access
-							if((i+2 < points.size() && 
-									safeToSplitWay(points, i+1, 0, points.size()-1))) {
-								Way tail = splitWayAt(way, i + 1);
+							if(splitPos > 0 &&
+									safeToSplitWay(points, splitPos, 0, points.size()-1)) {
+								Way tail = splitWayAt(way, splitPos);
 								// recursively process tail of way
 								addRoad(tail, gt);
 							}
 						}
-
-						// make the POI a node so that the region with
-						// restricted access is split into two as far
-						// as routing is concerned - this should stop
-						// routing across the POI when the start point
-						// is within the restricted region and the
-						// destination point is outside of the
-						// restricted region on the other side of the
-						// POI
-
-						// however, this still doesn't stop routing
-						// across the POI when both the start and end
-						// points are either side of the POI and both
-						// are in the restricted region
-						if (p.getHighwayCount() < 2){
-							if (i == 0|| i == points.size()-1 ||
-									safeToSplitWay(points, i, 0, points.size()-1))
-								p.incHighwayCount();
-							else {
-								points.set(i,new Coord(p.getLatitude(),p.getLongitude()));
-								points.get(i).incHighwayCount();
-							}
-						}
-
-						// copy all of the POI's access restrictions
-						// to the way segment
-						for (String accessTag : ACCESS_TAGS) {
-							if(node.isNotBoolTag(accessTag))
-								way.addTag(accessTag, "no");
-							
-						}
 					}
 				}
+			}
 
-				// check if the next point modifies access and if so,
-				// split the way either here or at a new point that's
-				// closer to the POI taking care not to introduce a
-				// short arc
-				if((i + 1) < points.size()) {
-					Coord p1 = points.get(i + 1);
-					if (p1 instanceof CoordPOI && ((CoordPOI) p1).isUsed()) {
-						CoordPOI cp = (CoordPOI) p1;
-						Node node = cp.getNode();
-						if (hasAccessRestriction(node) && wayPOI.contains("["+node.getId()+"]")){
-							// check if this point is further away
-							// from the POI than we would like
-							double dist = p.distance(p1);
-							if(dist >= (2 * stubSegmentLength)) {
-								// insert a new point to make a short
-								// stub segment
-								p1 = p1.makeBetweenPoint(p, stubSegmentLength / dist);
-								p1.incHighwayCount();
-								points.add(i + 1, p1);
-								continue;
-							}
-
-							// now split the way here if it is not the
-							// first point in the way
-							if(i > 0 &&
-							   safeToSplitWay(points, i, 0, points.size() - 1)) {
-								Way tail = splitWayAt(way, i);
-								// recursively process tail of road
-								addRoad(tail, gt);
-							}
-						}
-					}
-				}
-			}
 		}
 
 		// if there is a bounding box, clip the way with it
@@ -1076,6 +1137,81 @@
 		}
 	}
 
+	/**
+	 * Detect the case that two nodes are connected with 
+	 * different road segments and at least one node
+	 * is the via node of an "only-xxx" restriction.
+	 * If that is the case, make sure that there is
+	 * a node between them. If not, add it or change 
+	 * an existing point to a node by incrementing the highway
+	 * count.
+	 * Without this trick, only-restrictions might be ignored.
+	 * 
+	 * @param way the road
+	 */
+	private void addNodesForRestrictions(Way way) {
+		List<Coord> points = way.getPoints();
+		// loop downwards as we may add points
+		Coord lastNode = null;
+		int lastNodePos = -1;
+		for (int i = points.size() - 1; i >= 0; i--) {
+			Coord p1 = points.get(i);
+			if (p1.getHighwayCount() > 1){
+				if (lastNode != null){
+					if (lastNode.isViaNodeOfRestriction() && p1.isViaNodeOfRestriction()
+							|| (i == 0 && lastNodePos == points.size()-1 && (lastNode.isViaNodeOfRestriction() || p1.isViaNodeOfRestriction()))){
+						boolean addNode = false;
+						Coord[] testCoords = { p1, lastNode };
+						for (int k = 0; k < 2; k++){
+							if (testCoords[k].isViaNodeOfRestriction() == false)
+								continue;
+							List<RestrictionRelation> lrr = restrictions.get(testCoords[k]);
+							Coord test = k==0 ? testCoords[1]:testCoords[0];
+							for (RestrictionRelation rr : lrr) {
+								if (rr.isOnlyXXXRestriction() == false || rr.getFromWay() == way || rr.getToWay() == way)
+									continue;
+								// check if our way shares a point with either the to or from way
+								// we have to use Coord.equals() here because some
+								// points may already be CoordNodes while others are not
+								for (Coord co: rr.getToWay().getPoints()){
+									if (co.equals(test)){
+										addNode = true;
+										break;
+									}
+								}
+								for (Coord co: rr.getFromWay().getPoints()){
+									if (co.equals(test)){
+										addNode = true;
+										break;
+									}
+								}
+							}
+						}
+						if (addNode == false)
+							continue;
+						Coord co = null;
+						if (lastNodePos-i == 1){
+							if (p1.distance(lastNode) > 2 * minimumArcLength){
+								// create new point
+								co = lastNode.makeBetweenPoint(p1, 0.5);
+								co.incHighwayCount();
+								log.info("adding node in way ", way.toBrowseURL(), " to have node between two via points at " , co.toOSMURL());
+								points.add(lastNodePos,co);
+							}
+						} else {
+							co = points.get(i+1);
+							log.info("changing point to node in way " , way.toBrowseURL() , " to have node between two via points at " , co.toOSMURL());
+						}
+						if (co != null)
+							co.incHighwayCount();
+					}
+				}
+				lastNode = p1;
+				lastNodePos = i;
+			}
+		}
+	}
+
 	private void addRoadAfterSplittingLoops(Way way, GType gt) {
 		// make sure the way has nodes at each end
 		way.getPoints().get(0).incHighwayCount();
@@ -1324,7 +1460,24 @@
 					coordNode = new CoordNode(p.getLatitude(), p.getLongitude(), nextNodeId++, p.getOnBoundary());
 					nodeIdMap.put(p, coordNode);
 				}
-
+				if (p instanceof CoordPOI){
+					CoordPOI cp = (CoordPOI) p;
+					if (cp.getConvertToViaInRouteRestriction()){
+						String wayPOI = way.getTag(WAY_POI_NODE_IDS);
+						if (wayPOI != null && wayPOI.contains("[" + cp.getNode().getId() + "]")){
+							boolean[] nodeNoAccess = getNoAccess(cp.getNode());
+							boolean[] wayNoAccess = getNoAccess(way);
+							if (Arrays.equals(nodeNoAccess, wayNoAccess) == false){
+								List<Way> wayList = poiRestrictions.get(cp.getNode());
+								if (wayList == null){
+									wayList = new ArrayList<Way>(4);
+									poiRestrictions.put(cp.getNode(), wayList);
+								}
+								wayList.add(way);
+							}
+						}
+					}
+				}
 				// add this index to node Indexes (should not already be there)
 				assert !nodeIndices.contains(i) : debugWayName + " has multiple nodes for point " + i + " new node is " + p.toOSMURL();
 				nodeIndices.add(i);
@@ -1392,20 +1545,8 @@
 			road.setOneway();
 			road.doDeadEndCheck(!way.isNotBoolTag("mkgmap:dead-end-check"));
 		}
-
-		boolean[] noAccess = new boolean[RoadNetwork.NO_MAX];
-		noAccess[RoadNetwork.NO_EMERGENCY] = way.isNotBoolTag("mkgmap:emergency");
-		noAccess[RoadNetwork.NO_DELIVERY] = way.isNotBoolTag("mkgmap:delivery");
-		noAccess[RoadNetwork.NO_CAR] = way.isNotBoolTag("mkgmap:car");
-		noAccess[RoadNetwork.NO_BUS] = way.isNotBoolTag("mkgmap:bus");
-		noAccess[RoadNetwork.NO_TAXI] = way.isNotBoolTag("mkgmap:taxi");
-		noAccess[RoadNetwork.NO_FOOT] = way.isNotBoolTag("mkgmap:foot");
-		noAccess[RoadNetwork.NO_BIKE] = way.isNotBoolTag("mkgmap:bicycle");
-		noAccess[RoadNetwork.NO_TRUCK] = way.isNotBoolTag("mkgmap:truck");
-		// carpool is special => the default is no/unset and the flag is set only if mkgmap:carpool is set to yes
-		noAccess[RoadNetwork.NO_CARPOOL] = way.isBoolTag("mkgmap:carpool");
 		
-		road.setAccess(noAccess);
+		road.setAccess(getNoAccess(way));
 
 		if (way.isNotBoolTag("mkgmap:throughroute")) 
 			road.setNoThroughRouting();
@@ -1460,8 +1601,12 @@
 						}
 					}
 				}
-
-				List<RestrictionRelation> theseRestrictions = restrictions.get(coord);
+				
+				List<RestrictionRelation> theseRestrictions;
+				if (coord.isViaNodeOfRestriction())
+					theseRestrictions = restrictions.get(coord);
+				else
+					theseRestrictions = null;
 				if(theseRestrictions != null) {
 					// this node is the location of one or more
 					// restrictions
@@ -1470,7 +1615,7 @@
 						if(rr.getToWay().getId() == way.getId()) {
 							if(lastCoordNode != null)
 								rr.setToNode(lastCoordNode);
-						}
+							}
 						else if(rr.getFromWay().getId() == way.getId()) {
 							if(lastCoordNode != null)
 								rr.setFromNode(lastCoordNode);
@@ -1477,9 +1622,9 @@
 						}
 						else if(lastCoordNode != null) {
 							rr.addOtherNode(lastCoordNode);
-						}
 					}
 				}
+				}
 
 				lastRestrictions = theseRestrictions;
 				lastCoordNode = thisCoordNode;
@@ -1728,8 +1873,7 @@
 				continue;
 			if ("true".equals(way.getTag("mkgmap:way-has-pois"))) {
 				String wayPOI = "";
-				boolean isFootWay = isFootOnlyAccess(way); 
-				// check if the way is for pedestrians only 
+				
 				List<Coord> points = way.getPoints();
 				int numPoints = points.size();
 				for (int i = 0;i < numPoints; i++) {
@@ -1737,14 +1881,36 @@
 					if (p instanceof CoordPOI){
 						CoordPOI cp = (CoordPOI) p;
 						Node node = cp.getNode();
-						if (!isFootWay){
-							if(hasAccessRestriction(node) || 
-									node.getTag("mkgmap:road-class") != null ||
-									node.getTag("mkgmap:road-speed") != null){
-								wayPOI += "["+ node.getId()+"]"; 
-								cp.setUsed(true);
+						boolean usedInThisWay = false;
+						if (node.getTag("mkgmap:road-class") != null
+								|| node.getTag("mkgmap:road-speed") != null ) {
+							if (isFootOnlyAccess(way) == false)
+								usedInThisWay = true;
+						}
+						if(hasAccessRestriction(node)){
+							// barriers etc. 
+							boolean nodeIsMoreRestrictive = false;
+							for (String tag : ACCESS_TAGS) {
+								if (node.isNotBoolTag(tag) && way.isNotBoolTag(tag) == false) {
+									nodeIsMoreRestrictive = true;
+									break;
+								}
 							}
+							if (nodeIsMoreRestrictive){
+								if (p.getHighwayCount() >= 2 || (i != 0 && i != numPoints-1)){
+									usedInThisWay = true;
+									cp.setConvertToViaInRouteRestriction(true);
+								}
+								else {
+									log.info("POI node " + node.getId() + " with access restriction is ignored, it is not connected to other routable ways");
+								}
+							} else 
+								log.info("Access restriction in POI node " + node.toBrowseURL() + " was ignored for way " + way.toBrowseURL());
 						}
+						if (usedInThisWay){
+							cp.setUsed(true);
+							wayPOI += "["+ node.getId()+"]";
+						}
 					}
 				}
 				if (wayPOI.isEmpty()) {
@@ -1756,6 +1922,7 @@
 				}
 			}
 		}
+		
 	}
 
 	/**
@@ -1784,7 +1951,7 @@
 					// between roads at this time - so for the purposes
 					// of short arc removal, consider it to be a node
 					// if it is on a boundary it will become a node later
-					if (p.getHighwayCount() > 1 || p instanceof CoordPOI || p.getOnBoundary())
+					if (p.getHighwayCount() > 1 || (p instanceof CoordPOI && ((CoordPOI)p).isUsed())|| p.getOnBoundary())
 						p.setTreatAsNode(true);
 					// remove equal points
 					if (p.equals(prev)) {
@@ -1840,7 +2007,6 @@
 				int previousNodeIndex = 0; // first point will be a node
 				Coord previousPoint = points.get(0);
 				double arcLength = 0;
-
 				for (int i = 0; i < points.size(); ++i) {
 					Coord p = points.get(i);
 
@@ -1986,10 +2152,14 @@
 
 					// do the merge
 					++numNodesMerged;
-					if (p.getOnBoundary()) {
-						// current point is a boundary node so we need
+					if (p.getOnBoundary() || p.isViaNodeOfRestriction() && previousNode.getOnBoundary() == false) {
+						// current point is a boundary node or part of 
+						// a restriction relation so we need
 						// to merge the previous node into this node
 						replacements.put(previousNode, p);
+						if (previousNode.isViaNodeOfRestriction())
+							log.warn("via point is replaced at " + previousNode.toOSMURL());
+
 						previousNode.setReplaced(true);
 						p.setTreatAsNode(true);
 						// remove the preceding point(s) back to and
@@ -2001,6 +2171,8 @@
 						// current point is not on a boundary so merge
 						// this node into the previous one
 						replacements.put(p, previousNode);
+						if (p.isViaNodeOfRestriction())
+							log.warn("via point is replaced at " + p.toOSMURL());
 						p.setReplaced(true);
 						previousNode.setTreatAsNode(true);
 						// reset previous point to be the previous
Index: src/uk/me/parabola/mkgmap/reader/osm/CoordPOI.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/CoordPOI.java	(revision 2907)
+++ src/uk/me/parabola/mkgmap/reader/osm/CoordPOI.java	(working copy)
@@ -26,6 +26,7 @@
 public class CoordPOI extends Coord {
 	private Node node;
 	private boolean used;
+	private boolean convertToViaInRouteRestriction;
 
 	/**
 	 * Construct from co-ordinates that are already in map-units.
@@ -37,6 +38,7 @@
 		super(latitude, longitude);
 	}
 
+	
 	public Node getNode() {
 		return node;
 	}
@@ -51,4 +53,19 @@
 	public boolean isUsed() {
 		return used;
 	}
+
+	/** 
+	 * @param b true means: Convert the access restriction coded in the node to a via
+	 * node in an route restriction. 
+	 */
+	public void setConvertToViaInRouteRestriction(boolean b) {
+		this.convertToViaInRouteRestriction = b;
+	}
+	
+	/**
+	 * @return true if the node should be converted 
+	 */
+	public boolean getConvertToViaInRouteRestriction(){
+		return convertToViaInRouteRestriction;
+	}
 }
Index: src/uk/me/parabola/mkgmap/reader/osm/RestrictionRelation.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/RestrictionRelation.java	(revision 2907)
+++ src/uk/me/parabola/mkgmap/reader/osm/RestrictionRelation.java	(working copy)
@@ -141,6 +141,7 @@
 			}
 		}
 
+		exceptMask = RouteRestriction.EXCEPT_FOOT | RouteRestriction.EXCEPT_EMERGENCY; 
 		String except = getTag("except");
 		if(except != null) {
 			for(String e : except.split("[,;]")) { // be nice
@@ -300,12 +301,13 @@
 			if(restriction.startsWith("only_turn"))
 				log.warn(messagePrefix + "has bad type '" + restriction + "' it should be of the form only_X_turn rather than only_turn_X - I added the restriction anyway - allows routing to way " + toWay.toBrowseURL());
 			log.info(messagePrefix + restriction + " added - allows routing to way " + toWay.toBrowseURL());
-			HashSet<CoordNode> otherNodesUnique = new HashSet<CoordNode>(otherNodes);	
+			HashSet<CoordNode> otherNodesUnique = new HashSet<CoordNode>(otherNodes);
 			for(CoordNode otherNode : otherNodesUnique) {
-				if (!otherNode.equals(fromNode) && !otherNode.equals(toNode)) {
+				if (otherNode.getId() != fromNode.getId() && otherNode.getId() != toNode.getId()) {
 					log.info(messagePrefix + restriction + "  blocks routing to node " + otherNode.toOSMURL());
 					collector.addRestriction(fromNode, otherNode, viaNode, exceptMask);
-				}
+				} else 
+					log.error(messagePrefix + restriction + " was ignored because from or via was identical to calculated to-node");
 			}
 		}
 		else {
@@ -322,4 +324,8 @@
 	public String toString() {
 		return "[restriction = " + restriction + ", from = " + fromWay.toBrowseURL() + ", to = " + toWay.toBrowseURL() + ", via = " + viaCoord.toOSMURL() + "]";
 	}
+	
+	public boolean isOnlyXXXRestriction(){
+		return restriction.startsWith("only");
+	}
 }
Index: src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java	(revision 2907)
+++ src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java	(working copy)
@@ -824,7 +824,7 @@
                 if ("1".equals(params[i])) {
                     switch(i) {
 					case 0:
-						// Mask is not known for Emergency.
+						exceptMask |= RouteRestriction.EXCEPT_EMERGENCY;
 						break;
 					case 1:
 						exceptMask |= RouteRestriction.EXCEPT_DELIVERY;
@@ -839,7 +839,7 @@
 						exceptMask |= RouteRestriction.EXCEPT_TAXI;
 						break;
 					case 5:
-						// Mask is not known for Pedestrian.
+						exceptMask |= RouteRestriction.EXCEPT_FOOT;
 						break;
 					case 6:
 						exceptMask |= RouteRestriction.EXCEPT_BICYCLE;
Index: test/func/route/SimpleRouteTest.java
===================================================================
--- test/func/route/SimpleRouteTest.java	(revision 2907)
+++ test/func/route/SimpleRouteTest.java	(working copy)
@@ -58,7 +58,7 @@
 			} else if (ext.equals("TRE")) {
 				count++;
 				// Size varies depending on svn modified status
-				assertThat("TRE size", size, new RangeMatcher(1477, 2));
+				assertThat("TRE size", size, new RangeMatcher(1479, 2));
 			} else if (ext.equals("LBL")) {
 				count++;
 				assertEquals("LBL size", 28730, size);
