Index: src/uk/me/parabola/mkgmap/build/MapBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapBuilder.java	(revision 3683)
+++ src/uk/me/parabola/mkgmap/build/MapBuilder.java	(working copy)
@@ -21,7 +21,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Set;
 
@@ -69,7 +71,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 +1121,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 +1148,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/PreserveHorizontalAndVerticalLinesFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/PreserveHorizontalAndVerticalLinesFilter.java	(revision 3683)
+++ 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);
-	}
-}
