Index: src/uk/me/parabola/mkgmap/filters/ShapeMergeFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/ShapeMergeFilter.java	(revision 3429)
+++ src/uk/me/parabola/mkgmap/filters/ShapeMergeFilter.java	(working copy)
@@ -28,6 +28,7 @@
 import uk.me.parabola.mkgmap.osmstyle.WrongAngleFixer;
 import uk.me.parabola.mkgmap.reader.osm.FakeIdGenerator;
 import uk.me.parabola.mkgmap.reader.osm.GType;
+import uk.me.parabola.util.EnhancedProperties;
 import uk.me.parabola.util.MultiHashMap;
 
 
@@ -40,7 +41,8 @@
 public class ShapeMergeFilter{
 	private static final Logger log = Logger.getLogger(ShapeMergeFilter.class);
 	private final int resolution;
-	private final ShapeHelper dupShape = new ShapeHelper(new ArrayList<Coord>(0)); 
+	private final ShapeHelper dupShape = new ShapeHelper(new ArrayList<Coord>(0));
+	private final WrongAngleFixer wrongAngleFixer = new WrongAngleFixer(null, new EnhancedProperties());
 
 	public ShapeMergeFilter(int resolution) {
 		this.resolution = resolution;
@@ -120,7 +122,7 @@
 						assert sh.getPoints().get(0) == sh.getPoints().get(sh.getPoints().size()-1);
 						if (sh.id == 0){
 							// this shape is the result of a merge
-							List<Coord> optimizedPoints = WrongAngleFixer.fixAnglesInShape(sh.getPoints());
+							List<Coord> optimizedPoints = wrongAngleFixer.fixAnglesInShape(sh.getPoints());
 							if (optimizedPoints.isEmpty())
 								continue;
 							newShape.setPoints(optimizedPoints);
Index: src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(revision 3429)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(working copy)
@@ -197,7 +197,7 @@
 		// undocumented option - usually used for debugging only
 		mergeRoads = props.getProperty("no-mergeroads", false) == false;
 
-		wrongAngleFixer = new WrongAngleFixer(bbox);
+		wrongAngleFixer = new WrongAngleFixer(bbox,props);
 	}
 
 	/** One type result for ways to avoid recreating one for each way. */ 
Index: src/uk/me/parabola/mkgmap/osmstyle/WrongAngleFixer.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/WrongAngleFixer.java	(revision 3429)
+++ src/uk/me/parabola/mkgmap/osmstyle/WrongAngleFixer.java	(working copy)
@@ -30,6 +30,7 @@
 import uk.me.parabola.mkgmap.reader.osm.Node;
 import uk.me.parabola.mkgmap.reader.osm.RestrictionRelation;
 import uk.me.parabola.mkgmap.reader.osm.Way;
+import uk.me.parabola.util.EnhancedProperties;
 //import uk.me.parabola.splitter.O5mMapWriter;
 import uk.me.parabola.util.GpxCreator;
 
@@ -51,9 +52,9 @@
 public class WrongAngleFixer {
 	private static final Logger log = Logger.getLogger(WrongAngleFixer.class);
 
-	static private final double MAX_BEARING_ERROR = 15;
-	static private final double MAX_BEARING_ERROR_HALF = MAX_BEARING_ERROR / 2;
-	static private final double MAX_DIFF_ANGLE_STRAIGHT_LINE = 3;
+//	static private final double MAX_BEARING_ERROR = 15;
+//	static private final double MAX_BEARING_ERROR_HALF = MAX_BEARING_ERROR / 2;
+//	static private final double MAX_DIFF_ANGLE_STRAIGHT_LINE = 3;
 	
 	private final Area bbox;
 	private final String gpxPath = null;
@@ -60,9 +61,19 @@
 	static final int MODE_ROADS = 0;
 	static final int MODE_LINES = 1;
 	private int mode = MODE_ROADS;
+	private final double maxBearingError;
+	private final double maxBearingErrorHalf;
+	private final double maxDiffAngleStraigtLine;
+	private final double maxErrorPercentage;
 	
-	public WrongAngleFixer(Area bbox) {
+	
+	public WrongAngleFixer(Area bbox, EnhancedProperties props) {
 		this.bbox = bbox;
+		maxBearingError = props.getProperty("waf-max-bearing-error", 15);  
+		maxDiffAngleStraigtLine = props.getProperty("waf-max-angle", 3);
+		int percentage = props.getProperty("waf-max-error-percentage", 100);
+		maxErrorPercentage = (double) percentage / 100.0;
+		maxBearingErrorHalf = maxBearingError / 2;
 	}
 
 	/**
@@ -240,7 +251,7 @@
 						if (pass == 1 && p.equals(prev) == false)
 							hasNonEqualPoints = true;
 						double err = calcBearingError(p,prev);
-						if (err >= MAX_BEARING_ERROR){
+						if (err >= maxBearingError){
 							// bearing error is big
 							p.setPartOfBadAngle(true);
 							prev.setPartOfBadAngle(true);
@@ -593,7 +604,7 @@
 				
 				boolean keepThis = true;
 				double realAngle = Utils.getAngle(c1, cm, c2);
-				if (Math.abs(realAngle) < MAX_DIFF_ANGLE_STRAIGHT_LINE){ 
+				if (Math.abs(realAngle) < maxDiffAngleStraigtLine){ 
 					double distance = cm.distToLineSegment(c1, c2);
 					if (distance >= maxErrorDistance){
 						modifiedPoints.add(cm);
@@ -611,7 +622,7 @@
 							// we can remove the point
 							keepThis = false;
 						}
-					} else if (Math.abs(realAngle-displayedAngle) > 2 * Math.abs(realAngle) && Math.abs(realAngle) < MAX_BEARING_ERROR_HALF){
+					} else if (Math.abs(realAngle-displayedAngle) > 2 * Math.abs(realAngle) && Math.abs(realAngle) < maxBearingErrorHalf){
 						// displayed angle is much sharper than wanted, straight line is closer to real angle
 						keepThis = false;
 					}
@@ -831,7 +842,7 @@
 				if (n == null)
 					continue; // skip removed neighbours
 				double err = calcBearingError(c, n);
-				if (err >= MAX_BEARING_ERROR)
+				if (err >= maxBearingError)
 					return false;
 			}
 			return true;
@@ -881,7 +892,7 @@
 					worstNP = n;
 				}
 			}
-			if (initialMaxError < MAX_BEARING_ERROR)
+			if (initialMaxError < maxBearingError)
 				return false;
 			double removeErr = calcRemoveError(replacements);
 			if (removeErr == 0){
@@ -925,12 +936,12 @@
 				}
 			}
 			
-			if (bestReplErr < MAX_BEARING_ERROR){
+			if (bestReplErr < maxBearingError){
 //				String msg = "_good"; 
-				if (removeErr < bestReplErr && initialMaxError - removeErr >= MAX_BEARING_ERROR_HALF && removeErr < MAX_BEARING_ERROR_HALF){
+				if (removeErr < bestReplErr && initialMaxError - removeErr >= maxBearingErrorHalf && removeErr < maxBearingErrorHalf){
 					bestCenterReplacement = null;
 //					createGPX(gpxPath+id+"_rem_pref", replacements);
-				} else if (initialMaxError - bestReplErr < MAX_BEARING_ERROR_HALF || bestReplErr > MAX_BEARING_ERROR_HALF){
+				} else if (initialMaxError - bestReplErr < maxBearingErrorHalf || bestReplErr > maxBearingErrorHalf){
 //					msg = "_rather_good";
 				}
 				if (bestCenterReplacement != null){
@@ -957,7 +968,7 @@
 					bestCenterReplacement = null;
 				}
 			}
-			if (removeErr < MAX_BEARING_ERROR){
+			if (removeErr < maxBearingError){
 //				createGPX(gpxPath+id+"_rem", replacements);
 				currentCenter.setRemove(true);
 				return true;
@@ -972,7 +983,7 @@
 				return tryMerge(forceMerge, initialMaxError, worstNeighbour, replacements);
 			if (bestCenterReplacement != null){
 				double replImprovement = initialMaxError - bestReplErr;
-				if (replImprovement < MAX_BEARING_ERROR)
+				if (replImprovement < maxBearingError)
 					return false;
 				replaceCoord(currentCenter, bestCenterReplacement, replacements);
 				if (bestNeighbourReplacement != null){
@@ -1043,9 +1054,9 @@
 				if (err == Double.MAX_VALUE && initialMaxError == Double.MAX_VALUE){
 					log.warn("still equal neighbour after merge",c.toOSMURL());
 				} else { 
-					if (err >= MAX_BEARING_ERROR)
+					if (err >= maxBearingError)
 						return false;
-					if (initialMaxError - err < MAX_BEARING_ERROR_HALF && err > MAX_BEARING_ERROR_HALF){
+					if (initialMaxError - err < maxBearingErrorHalf && err > maxBearingErrorHalf){
 						return false; // improvement too small
 					}
 				}
@@ -1347,9 +1358,10 @@
 	 * @param p0
 	 * @return
 	 */
-	private static double calcMaxErrorDistance(Coord p0){
+	private double calcMaxErrorDistance(Coord p0){
 		Coord test = new Coord(p0.getLatitude(),p0.getLongitude()+1);
 		double lonErr = p0.getDisplayedCoord().distance(test) / 2;
+		lonErr *= maxErrorPercentage * lonErr / 100.0;
 		return lonErr;
 	}
 
@@ -1360,7 +1372,7 @@
 	 * @param points list of coordinates that form a shape
 	 * @return reduced list 
 	 */
-	public static List<Coord> fixAnglesInShape(List<Coord> points) {
+	public List<Coord> fixAnglesInShape(List<Coord> points) {
 		List<Coord> modifiedPoints = new ArrayList<>(points.size());
 		double maxErrorDistance = calcMaxErrorDistance(points.get(0));
 		
@@ -1389,7 +1401,7 @@
 				continue;
 			}
 			double realAngle = Utils.getAngle(c1, cm, c2);
-			if (Math.abs(realAngle) < MAX_DIFF_ANGLE_STRAIGHT_LINE){ 
+			if (Math.abs(realAngle) < maxDiffAngleStraigtLine){ 
 				double distance = cm.distToLineSegment(c1, c2);
 				if (distance < maxErrorDistance)
 					continue;
