Index: build.xml
===================================================================
--- build.xml	(revision 3683)
+++ build.xml	(working copy)
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <!--
-		File: build.xml 
+		File: build.xml xxx 
 		
 		Copyright (C) 2006, 2012 mkgmap contributors
 		
@@ -237,7 +237,7 @@
 		<javac srcdir="${src}" destdir="${build.classes}" encoding="utf-8" debug="true" includeantruntime="false">
 			<include name="**/*.java" />
 			<classpath refid="main"/>
-			<exclude name="**/optional/*.java"/>
+			<exclude name="**/dem/optional/*.java"/>
 		</javac>
 	</target>
 
Index: resources/styles/default/polygons
===================================================================
--- resources/styles/default/polygons	(revision 3683)
+++ resources/styles/default/polygons	(working copy)
@@ -49,7 +49,7 @@
 leisure=water_park [0x09 resolution 21]
 
 place=village [0x03 resolution 19]
-place=island & name=* [0x53 resolution 19]
+place=island & name=* & area_size() < 1000000 & !(natural=coastline) [0x53 resolution 19]
 place=islet & name=* [0x53 resolution 20]
 
 shop=* [0x08 resolution 22]
Index: src/uk/me/parabola/imgfmt/app/CoordNode.java
===================================================================
--- src/uk/me/parabola/imgfmt/app/CoordNode.java	(revision 3683)
+++ src/uk/me/parabola/imgfmt/app/CoordNode.java	(working copy)
@@ -49,6 +49,13 @@
 		preserved(true);
 		
 	}
+	
+	@Override 
+	public boolean preserved() {
+		assert super.preserved() : "CoordNode with unset preserved flag";
+		return true;
+	};
+
 	public int getId() {
 		return id;
 	}
Index: src/uk/me/parabola/mkgmap/build/LayerFilterChain.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/LayerFilterChain.java	(revision 3683)
+++ src/uk/me/parabola/mkgmap/build/LayerFilterChain.java	(working copy)
@@ -21,6 +21,8 @@
 import uk.me.parabola.mkgmap.filters.MapFilter;
 import uk.me.parabola.mkgmap.filters.MapFilterChain;
 import uk.me.parabola.mkgmap.general.MapElement;
+import uk.me.parabola.mkgmap.general.MapShape;
+import uk.me.parabola.util.GpxCreator;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -55,6 +57,12 @@
 		
 		MapFilter f = filters.get(position++);
 		f.doFilter(element, this);
+//		if (element instanceof MapShape){
+//			MapShape s = (MapShape) element;
+//			if (s.getOsmid() == 4611686018427481442L){
+//				GpxCreator.createGpx("e:/ld/filter_" + s.getOsmid() + "_" + config.getShift() + "_" + position, s.getPoints());
+//			}
+//		}
 		// maintain chain position for repeated calls in the split filters 
 		position--; 
 	}
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;
@@ -1119,10 +1120,26 @@
 			List<MapShape> mergedShapes = shapeMergeFilter.merge(shapes);
 			shapes = mergedShapes;
 		}
+		if (shapes.size() > 1) {
+			final IdentityHashMap<MapShape, Long> sizeMap = new IdentityHashMap<>(shapes.size());
+			for (MapShape s : shapes){
+				long areaSize = Math.abs(ShapeMergeFilter.calcAreaSizeTestVal(s.getPoints()));
+				sizeMap.put(s, areaSize);
+			}
+			// sort so that the shape with the largest area is processed first
+			Collections.sort(shapes, new Comparator<MapShape>() {
+				public int compare(MapShape s1, MapShape s2) {
+					long a1 = sizeMap.get(s1);
+					long a2 = sizeMap.get(s2);
+					return Long.compare(a2, a1);
+				}
+			});
+		} 		
 		
+		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)
@@ -1134,7 +1151,8 @@
 		}
 		filters.addFilter(new PolygonSplitterFilter());
 		filters.addFilter(new RemoveEmpty());
-		filters.addFilter(new RemoveObsoletePointsFilter());
+		if (!OverviewBuilder.isOverviewImg(map.getFilename()))
+			filters.addFilter(new RemoveObsoletePointsFilter());
 		filters.addFilter(new LinePreparerFilter(div));
 		filters.addFilter(new ShapeAddFilter(div, map));
 
@@ -1146,6 +1164,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);
-	}
-}
Index: src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java	(revision 3683)
+++ src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java	(working copy)
@@ -20,11 +20,14 @@
 import uk.me.parabola.imgfmt.app.CoordNode;
 import uk.me.parabola.mkgmap.general.MapElement;
 import uk.me.parabola.mkgmap.general.MapLine;
+import uk.me.parabola.mkgmap.general.MapShape;
+import uk.me.parabola.util.GpxCreator;
 
 public class RoundCoordsFilter implements MapFilter {
 
 	private int shift;
 	private boolean checkRouting;
+	private boolean debug;
 
 	public void init(FilterConfig config) {
 		shift = config.getShift();
@@ -47,7 +50,10 @@
 		}
 		else {
 			// round lat/lon values to nearest for shift
-			List<Coord> newPoints = new ArrayList<Coord>(line.getPoints().size());
+			List<Coord> newPoints = new ArrayList<>(line.getPoints().size());
+			
+			List<Coord> origPreserved = null;
+			if (debug) origPreserved = new ArrayList<>();
 			Coord lastP = null;
 			for(Coord p : line.getPoints()) {
 				int lat = (p.getLatitude() + half) & mask;
@@ -59,6 +65,8 @@
 				else
 					newP = new Coord(lat, lon);
 				newP.preserved(p.preserved());
+				if (debug && p.preserved())
+					origPreserved.add(p);
 
 				// only add the new point if it has different
 				// coordinates to the last point or if it's a
@@ -79,6 +87,15 @@
 				}
 			}
 			if(newPoints.size() > 1) {
+				if (debug){
+					if (line instanceof MapShape){
+						MapShape s = (MapShape) line;
+						if (s.getOsmid() == 4611686018427481442L && shift == 4 && s.getType() == 0x17){
+							GpxCreator.createGpx("e:/ld/os_" + s.getOsmid() + "_" + shift, line.getPoints(),origPreserved);
+							GpxCreator.createGpx("e:/ld/rs_" + s.getOsmid() + "_" + shift, newPoints);
+						}
+					}
+				}
 				MapLine newLine = line.copy();
 				newLine.setPoints(newPoints);
 				next.doFilter(newLine);
Index: src/uk/me/parabola/mkgmap/filters/ShapeMergeFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/ShapeMergeFilter.java	(revision 3683)
+++ 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.GpxCreator;
 import uk.me.parabola.util.MultiHashMap;
 
 
@@ -187,7 +188,7 @@
 	 * if both shapes describe the same area. 
 	 */
 	private ShapeHelper tryMerge(ShapeHelper sh1, ShapeHelper sh2, int type) {
-		
+//		final Area ta = new Area(53.27791929244995,-6.727087497711182,53.28920602798462,-6.710522174835205);
 		// both clockwise or both ccw ?
 		boolean sameDir = sh1.areaTestVal > 0 && sh2.areaTestVal > 0 || sh1.areaTestVal < 0 && sh2.areaTestVal < 0;
 		
@@ -229,6 +230,12 @@
 		}
 		ShapeHelper shm = null;
 		if (merged != null){
+//			if (resolution == 20 && type == 0x17 && ta.contains(sh1.getBounds()) && ta.contains(sh2.getBounds())){
+//				GpxCreator.createGpx("e:/ld/sh1_" + sh1.id, points1);
+//				GpxCreator.createGpx("e:/ld/sh2_" + sh2.id, points2);
+//				GpxCreator.createGpx("e:/ld/mer", merged);
+//				long dd = 4;
+//			}
 			shm = new ShapeHelper(merged);
 			if (Math.abs(shm.areaTestVal) != Math.abs(sh1.areaTestVal) + Math.abs(sh2.areaTestVal)){
 				log.warn("merging shapes skipped for shapes near", points1.get(sh1PositionsToCheck.getInt(0)).toOSMURL(), 
@@ -318,7 +325,7 @@
 		int length = 0;
 		int start = -1;
 		int n1 = sh1PositionsToCheck.size();
-		
+//		IntArrayList sequenceLengths = new IntArrayList();
 		assert sh2PositionsToCheck.size() == n1;
 		boolean inSequence = false;
 		for (int i = 0; i+1 < n1; i++){
@@ -341,6 +348,9 @@
 				inSequence = false;
 			}
 			if (!inSequence){
+//				if (start >= 0){
+//					sequenceLengths.add(length);
+//				}
 				if (length > longestSequence){
 					longestSequence = length;
 					startOfLongestSequence = start;
@@ -349,6 +359,9 @@
 				start = -1;
 			}
 		}
+//		if (start >= 0){
+//			sequenceLengths.add(length);
+//		}
 		if (length > longestSequence){
 			longestSequence = length;
 			startOfLongestSequence = start;
@@ -373,6 +386,14 @@
 			else if (s2Pos+1 >= s2Size)
 				s2Pos = 0;
 		}
+//		if (resolution < 24 && sequenceLengths.size() > 1){
+//			System.out.println(resolution + " " + sequenceLengths);
+//			GpxCreator.createGpx("e:/ld/s1", points1);
+//			GpxCreator.createGpx("e:/ld/s2", points2);
+//			GpxCreator.createGpx("e:/ld/merged", merged);
+//			long dd = 4;
+//		}
+		
 //		if (merged.get(0).equals(new Coord(2438126,342573))){
 //			GpxCreator.createGpx("e:/ld/s1", points1);
 //			GpxCreator.createGpx("e:/ld/s2", points2);
