Index: src/uk/me/parabola/mkgmap/build/MapBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapBuilder.java	(revision 4687)
+++ src/uk/me/parabola/mkgmap/build/MapBuilder.java	(working copy)
@@ -1186,22 +1186,37 @@
 			lines = merger.merge(lines, res);
 		}
 		
-		LayerFilterChain filters = new LayerFilterChain(config);
+		LayerFilterChain normalFilters = new LayerFilterChain(config);
+		LayerFilterChain contourFilters = new LayerFilterChain(config);
 		if (enableLineCleanFilters && (res < 24)) {
-			filters.addFilter(new RoundCoordsFilter());
-			filters.addFilter(new SizeFilter(MIN_SIZE_LINE));
-			if(reducePointError > 0)
-				filters.addFilter(new DouglasPeuckerFilter(reducePointError));
+			MapFilter rounder = new RoundCoordsFilter();
+			MapFilter sizeFilter = new SizeFilter(MIN_SIZE_LINE);
+			normalFilters.addFilter(rounder);
+			normalFilters.addFilter(sizeFilter);
+			if(reducePointError > 0) {
+				DouglasPeuckerFilter dp = new DouglasPeuckerFilter(reducePointError);
+				normalFilters.addFilter(dp);
+				contourFilters.addFilter(dp);
+			}
+			contourFilters.addFilter(rounder);
+			contourFilters.addFilter(sizeFilter);
 		}
-		filters.addFilter(new LineSplitterFilter());
-		filters.addFilter(new RemoveEmpty());
-		filters.addFilter(new RemoveObsoletePointsFilter());
-		filters.addFilter(new LinePreparerFilter(div));
-		filters.addFilter(new LineAddFilter(div, map));
+		for (MapFilter filter : Arrays.asList(
+				new LineSplitterFilter(), 
+				new RemoveEmpty(),
+				new RemoveObsoletePointsFilter(), 
+				new LinePreparerFilter(div), 
+				new LineAddFilter(div, map))) {
+			normalFilters.addFilter(filter);
+			contourFilters.addFilter(filter);
+		}
 		
 		for (MapLine line : lines) {
 			if (line.getMinResolution() <= res) {
-				filters.startFilter(line);
+				if (GType.isContourLine(line)) 
+					contourFilters.startFilter(line);
+				else 
+					normalFilters.startFilter(line);
 			}
 		}
 	}
Index: src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java	(revision 4687)
+++ src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java	(working copy)
@@ -21,6 +21,7 @@
 import uk.me.parabola.mkgmap.general.MapElement;
 import uk.me.parabola.mkgmap.general.MapLine;
 import uk.me.parabola.mkgmap.general.MapRoad;
+import uk.me.parabola.mkgmap.reader.osm.GType;
 
 public class RoundCoordsFilter implements MapFilter {
 
@@ -46,29 +47,80 @@
 			next.doFilter(element);
 		} else {
 			MapLine line = (MapLine) element;
+			int full = 1 << shift;
 			int half = 1 << (shift - 1);	// 0.5 shifted
 			int mask = ~((1 << shift) - 1); // to remove fraction bits
 			
 			// round lat/lon values to nearest for shift
 			List<Coord> newPoints = new ArrayList<>(line.getPoints().size());
+
+			List<Coord> coords = line.getPoints();
+			int endIndex = coords.size() -1;
+
 			Coord lastP = null;
 			boolean hasNumbers = level == 0 && line.isRoad() && ((MapRoad) line).getRoadDef().hasHouseNumbers();
-			for(Coord p : line.getPoints()) {
+			boolean isContourLine = GType.isContourLine(line);
+			for(int i = 0; i <= endIndex; i++) {
+				Coord p = coords.get(i);
 				if (level > 0 && p.isAddedNumberNode()) {
 					// ignore nodes added by housenumber processing for levels > 0   
 					continue;
 				}
-				
-				int lat = (p.getLatitude() + half) & mask;
-				int lon = (p.getLongitude() + half) & mask;
+
 				Coord newP;
-				
 				if (p instanceof CoordNode && keepNodes) {
+					int lat = (p.getLatitude() + half) & mask;
+					int lon = (p.getLongitude() + half) & mask;
 					newP = new CoordNode(lat, lon, p.getId(), p.getOnBoundary(), p.getOnCountryBorder());
-				} else {
+				} else if (!isContourLine || i == 0 || i == endIndex) {
+					int lat = (p.getLatitude() + half) & mask;
+					int lon = (p.getLongitude() + half) & mask;
 					newP = new Coord(lat, lon);
 					newP.preserved(p.preserved());
 					newP.setNumberNode(hasNumbers && p.isNumberNode());
+				} else { // find best match, used only with contour lines so far
+					Coord a = coords.get(i -1);
+					Coord b = coords.get(i +1);
+
+					// point 0,0
+					int lat = p.getLatitude() & mask;
+					int lon = p.getLongitude() & mask;
+					newP = new Coord(lat, lon);
+					double distance = sumDistToSegments(newP, p, a, b);
+
+					Coord testP;
+					double testDistance;
+
+					// point 0,1
+					lon = (p.getLongitude() + full) & mask;
+					testP = new Coord(lat, lon);
+					testDistance = sumDistToSegments(testP, p, a, b);
+					if (testDistance < distance) {
+						distance = testDistance;
+						newP = testP;
+					}
+
+					// point 1,1
+					lat = (p.getLatitude() + full) & mask;
+					testP = new Coord(lat, lon);
+					testDistance = sumDistToSegments(testP, p, a, b);
+					if (testDistance < distance) {
+						distance = testDistance;
+						newP = testP;
+					}
+
+					// point 1,0
+					lon = p.getLongitude() & mask;
+					testP = new Coord(lat, lon);
+					testDistance = sumDistToSegments(testP, p, a, b);
+					if (testDistance < distance) {
+						distance = testDistance;
+						newP = testP;
+					}
+
+					newP.preserved(p.preserved());
+					newP.setNumberNode(hasNumbers && p.isNumberNode());
+
 				}
 				
 				// only add the new point if it has different
@@ -93,4 +145,8 @@
 			}
 		}
 	}
+	
+	private static double sumDistToSegments(Coord testP, Coord mid, Coord before, Coord after) {
+		return testP.shortestDistToLineSegment(before, mid) + testP.shortestDistToLineSegment(mid, after);
+	}
 }
Index: src/uk/me/parabola/mkgmap/reader/osm/GType.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/GType.java	(revision 4687)
+++ src/uk/me/parabola/mkgmap/reader/osm/GType.java	(working copy)
@@ -21,7 +21,9 @@
 import uk.me.parabola.imgfmt.ExitException;
 import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.general.LevelInfo;
+import uk.me.parabola.mkgmap.general.MapLine;
 import uk.me.parabola.mkgmap.general.MapPoint;
+import uk.me.parabola.mkgmap.general.MapShape;
 
 /**
  * Holds the garmin type of an element and all the information that
@@ -272,5 +274,9 @@
 		String s = String.format("%x", type);
 		return (s.length() % 2 != 0 ? "0x0":"0x") + s;
 	}
+
+	public static boolean isContourLine(MapLine line) {
+		return line.getType() >= 0x20 && line.getType() <= 0x22 && !(line instanceof MapShape);
+	}
 	
 }
Index: src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java	(revision 4687)
+++ src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java	(working copy)
@@ -466,9 +466,7 @@
 			extractResolution(name);
 			addLineString(value, false);
 			// If it is a contour line, then fix the elevation if required.
-			if ((polyline.getType() == 0x20) ||
-			    (polyline.getType() == 0x21) ||
-			    (polyline.getType() == 0x22)) {
+			if (GType.isContourLine(polyline)) {
 				fixElevation();
 			}
 		} else if ("RoadID".equals(name)) {
