Index: src/uk/me/parabola/mkgmap/build/MapBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapBuilder.java	(revision 3686)
+++ src/uk/me/parabola/mkgmap/build/MapBuilder.java	(working copy)
@@ -22,6 +22,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Set;
 
@@ -69,7 +70,6 @@
 import uk.me.parabola.mkgmap.filters.MapFilter;
 import uk.me.parabola.mkgmap.filters.MapFilterChain;
 import uk.me.parabola.mkgmap.filters.PolygonSplitterFilter;
-import uk.me.parabola.mkgmap.filters.PreserveHorizontalAndVerticalLinesFilter;
 import uk.me.parabola.mkgmap.filters.RemoveEmpty;
 import uk.me.parabola.mkgmap.filters.RemoveObsoletePointsFilter;
 import uk.me.parabola.mkgmap.filters.RoundCoordsFilter;
@@ -1120,9 +1120,10 @@
 			shapes = mergedShapes;
 		}
 		
+		preserveHorizontalAndVerticalLines(res, shapes);
+		
 		LayerFilterChain filters = new LayerFilterChain(config);
 		if (enableLineCleanFilters && (res < 24)) {
-			filters.addFilter(new PreserveHorizontalAndVerticalLinesFilter());
 			filters.addFilter(new RoundCoordsFilter());
 			int sizefilterVal =  getMinSizePolygonForResolution(res);
 			if (sizefilterVal > 0)
@@ -1146,6 +1147,59 @@
 		}
 	}
 
+	/**
+	 * Preserve shape points which a) lie on the shape boundary or
+	 * b) which appear multiple times in the shape (excluding the start
+	 * point which should always be identical to the end point).
+	 * The preserved points are kept treated specially in the 
+	 * Line-Simplification-Filters, this should avoid artifacts like
+	 * white triangles in the sea for lower resolutions.     
+	 * @param res the current resolution
+	 * @param shapes list of shapes
+	 */
+	private void preserveHorizontalAndVerticalLines(int res, List<MapShape> shapes) {
+		if (res == 24)
+			return;
+		for (MapShape shape : shapes) {
+			if (shape.getMinResolution() > res || shape.getMaxResolution() < res)
+				continue;
+			int minLat = shape.getBounds().getMinLat();
+			int maxLat = shape.getBounds().getMaxLat();
+			int minLon = shape.getBounds().getMinLong();
+			int maxLon = shape.getBounds().getMaxLong();
+			
+			List<Coord> points = shape.getPoints();
+			int n = shape.getPoints().size();
+			IdentityHashMap<Coord, Coord> coords = new IdentityHashMap<>(n);
+			Coord first = points.get(0);
+			Coord prev = first;
+			Coord last = first;
+			for(int i = 1; i < points.size(); ++i) {
+				last = points.get(i);
+				// preserve coord instances which are used more than once,
+				// these are typically produced by the ShapeMergerFilter 
+				// to connect holes
+				if (coords.get(last) == null){
+					coords.put(last, last);
+				}
+				else {
+					if (!last.preserved()){
+						last.preserved(true);
+					}
+				}
+
+				// preserve the end points of horizontal and vertical lines that lie
+				// on the bbox of the shape. 
+				if(last.getLatitude() == prev.getLatitude() && (last.getLatitude() == minLat || last.getLatitude() == maxLat) ||
+				   last.getLongitude() == prev.getLongitude()&& (last.getLongitude() == minLon || last.getLongitude() == maxLon)){
+					last.preserved(true);
+					prev.preserved(true);
+				}
+				prev = last;
+			}
+		}
+	}
+
 	Highway makeHighway(Map map, String ref) {
 		if(getDefaultRegion(null) == null) {
 			log.warn("Highway " + ref + " has no region (define a default region to zap this warning)");
Index: src/uk/me/parabola/mkgmap/filters/DouglasPeuckerFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/DouglasPeuckerFilter.java	(revision 3686)
+++ src/uk/me/parabola/mkgmap/filters/DouglasPeuckerFilter.java	(working copy)
@@ -19,7 +19,6 @@
 import uk.me.parabola.imgfmt.app.Coord;
 import uk.me.parabola.mkgmap.general.MapElement;
 import uk.me.parabola.mkgmap.general.MapLine;
-import uk.me.parabola.mkgmap.general.MapShape;
 
 /**
  * This is a filter that smooths out lines at low resolutions. If the element
@@ -33,7 +32,6 @@
 	private final double filterDistance;
 	private double maxErrorDistance;
 	private int resolution;
-	private int level;
 
 	public DouglasPeuckerFilter(double filterDistance) {
 		this.filterDistance = filterDistance;
@@ -41,7 +39,6 @@
 
 	public void init(FilterConfig config) {
 		this.resolution = config.getResolution();
-		this.level = config.getLevel();
 		this.maxErrorDistance = filterDistance * (1<< config.getShift());
 	}
 
@@ -69,18 +66,16 @@
 		coords.addAll(points);
 		// Loop runs downwards, as the list length gets modified while running
 		int endIndex = coords.size()-1;
-		if (level == 0 || line instanceof MapShape){
-			for(int i = endIndex-1; i > 0; i--) {
-				Coord p = coords.get(i);
-				//int highwayCount = p.getHighwayCount();
+		for(int i = endIndex-1; i > 0; i--) {
+			Coord p = coords.get(i);
+			//int highwayCount = p.getHighwayCount();
 
-				// If a node in the line use the douglas peucker algorithm for upper segment
-				// TODO: Should consider only nodes connected to roads visible at current resolution.
-				if (p.preserved()) {
-					// point is "preserved", don't remove it
-					douglasPeucker(coords, i, endIndex, maxErrorDistance);
-					endIndex = i;
-				}
+			// If a node in the line use the douglas peucker algorithm for upper segment
+			// TODO: Should consider only nodes connected to roads visible at current resolution.
+			if (p.preserved()) {
+				// point is "preserved", don't remove it
+				douglasPeucker(coords, i, endIndex, maxErrorDistance);
+				endIndex = i;
 			}
 		}
 		// Simplify the rest
Index: src/uk/me/parabola/mkgmap/filters/PreserveHorizontalAndVerticalLinesFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/PreserveHorizontalAndVerticalLinesFilter.java	(revision 3686)
+++ src/uk/me/parabola/mkgmap/filters/PreserveHorizontalAndVerticalLinesFilter.java	(nonexistent)
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2007 Steve Ratcliffe
- * 
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- * 
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- * 
- */
-package uk.me.parabola.mkgmap.filters;
-
-import java.util.List;
-
-import uk.me.parabola.imgfmt.app.Coord;
-import uk.me.parabola.mkgmap.general.MapElement;
-import uk.me.parabola.mkgmap.general.MapLine;
-
-public class PreserveHorizontalAndVerticalLinesFilter implements MapFilter {
-
-	private int shift;
-
-	public void init(FilterConfig config) {
-		shift = config.getShift();
-	}
-
-	/**
-	 * @param element A map element that will be a line or a polygon.
-	 * @param next This is used to pass the possibly transformed element onward.
-	 */
-	public void doFilter(MapElement element, MapFilterChain next) {
-		MapLine line = (MapLine) element;
-
-		if(shift != 0) {
-			// preserve the end points of horizontal and vertical lines that lie
-			// on the bbox of the shape. 
-			int minLat = line.getBounds().getMinLat();
-			int maxLat = line.getBounds().getMaxLat();
-			int minLon = line.getBounds().getMinLong();
-			int maxLon = line.getBounds().getMaxLong();
-			
-			List<Coord> points = line.getPoints();
-			Coord first = points.get(0);
-			Coord prev = first;
-			Coord last = first;
-			for(int i = 1; i < points.size(); ++i) {
-				last = points.get(i);
-				if(last.getLatitude() == prev.getLatitude() && (last.getLatitude() == minLat || last.getLatitude() == maxLat) ||
-				   last.getLongitude() == prev.getLongitude()&& (last.getLongitude() == minLon || last.getLongitude() == maxLon)){
-					last.preserved(true);
-					prev.preserved(true);
-				}
-				prev = last;
-			}
-		}
-
-		next.doFilter(line);
-	}
-}
Index: src/uk/me/parabola/mkgmap/general/MapLine.java
===================================================================
--- src/uk/me/parabola/mkgmap/general/MapLine.java	(revision 3686)
+++ src/uk/me/parabola/mkgmap/general/MapLine.java	(working copy)
@@ -66,6 +66,12 @@
 		assert !points.isEmpty() : "trying to set points with zero length";
 
 		this.points = points;
+		// preserve first and last point, so that points which are shared by
+		// different ways are kept
+		if (points.size() > 0 && this instanceof MapShape == false){
+			points.get(0).preserved(true);
+			points.get(points.size()-1).preserved(true);
+		}
 		testForConsecutivePoints(points);
 	}
 	
@@ -84,13 +90,11 @@
 	public void insertPointsAtStart(List<Coord> additionalPoints) {
 		assert points.get(0).equals(additionalPoints.get(additionalPoints.size()-1));
 		testForConsecutivePoints(additionalPoints);
-		points.get(0).preserved(true);
 		points.addAll(0, additionalPoints.subList(0, additionalPoints.size()-1));
 	}
 
 	public void insertPointsAtEnd(List<Coord> additionalPoints) {
 		testForConsecutivePoints(additionalPoints);
-		additionalPoints.get(0).preserved(true);
 		points.remove(points.size()-1); 
 		points.addAll(additionalPoints);
 	}
