This patch stops the DP filter from discarding points at either end of
a horizontal or vertical line segment (such segments are created by the
clipper and also by the polygon splitter and, of course, could occur
naturally in the OSM data but I'd guess they are relatively rare).

The benefit is that polygons lose those ugly artifacts (e.g. weird thin
triangles) that sometimes occur at tile boundaries or where they have
been split (when zooming out in mapsource).

For me, mapsource still displays the odd spurious horizontal or
vertical line but as it goes away when the screen is scrolled, I am
assuming it is a mapsource bug rather than ours.

Please try it out and report.

Mark

diff --git a/src/uk/me/parabola/mkgmap/build/MapBuilder.java b/src/uk/me/parabola/mkgmap/build/MapBuilder.java
index 1745286..8fec70b 100644
--- a/src/uk/me/parabola/mkgmap/build/MapBuilder.java
+++ b/src/uk/me/parabola/mkgmap/build/MapBuilder.java
@@ -60,6 +60,7 @@ import uk.me.parabola.mkgmap.filters.LineSplitterFilter;
 import uk.me.parabola.mkgmap.filters.LineMergeFilter;
 import uk.me.parabola.mkgmap.filters.MapFilter;
 import uk.me.parabola.mkgmap.filters.MapFilterChain;
+import uk.me.parabola.mkgmap.filters.ProtectClippedEdgesFilter;
 import uk.me.parabola.mkgmap.filters.PolygonSplitterFilter;
 import uk.me.parabola.mkgmap.filters.RemoveEmpty;
 import uk.me.parabola.mkgmap.filters.RoundCoordsFilter;
@@ -882,6 +883,7 @@ public class MapBuilder implements Configurable {
 
 		LayerFilterChain filters = new LayerFilterChain(config);
 		if (enableLineCleanFilters && (res < 24)) {
+			filters.addFilter(new ProtectClippedEdgesFilter());
 			filters.addFilter(new RoundCoordsFilter());
 			filters.addFilter(new SizeFilter());
 			if(reducePointError > 0)
@@ -920,6 +922,7 @@ public class MapBuilder implements Configurable {
 		config.setResolution(res);
 		LayerFilterChain filters = new LayerFilterChain(config);
 		if (enableLineCleanFilters && (res < 24)) {
+			filters.addFilter(new ProtectClippedEdgesFilter());
 			filters.addFilter(new RoundCoordsFilter());
 			filters.addFilter(new SizeFilter());
 			//DouglasPeucker behaves at the moment not really optimal at low zooms, but acceptable.
diff --git a/src/uk/me/parabola/mkgmap/filters/ProtectClippedEdgesFilter.java b/src/uk/me/parabola/mkgmap/filters/ProtectClippedEdgesFilter.java
new file mode 100644
index 0000000..773ae58
--- /dev/null
+++ b/src/uk/me/parabola/mkgmap/filters/ProtectClippedEdgesFilter.java
@@ -0,0 +1,69 @@
+/*
+ * 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 uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.mkgmap.general.MapElement;
+import uk.me.parabola.mkgmap.general.MapLine;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProtectClippedEdgesFilter implements MapFilter {
+
+	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 clipped edges
+
+			// the clipped edge detection test is cheap and cheerful,
+			// if neighbouring points have the same lat or lon value,
+			// the line is either horizontal or vertical and very
+			// likely to have been created as part of the clipping
+			// process or the polygon splitting process
+			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.getLongitude() == prev.getLongitude()) {
+					last.preserved(true);
+					prev.preserved(true);
+				}
+				prev = last;
+			}
+			// way has the same point at each end so make sure that if
+			// either is preserved, they both are
+			if(first.equals(last) && first.preserved() != last.preserved()) {
+				first.preserved(true);
+				last.preserved(true);
+			}
+		}
+
+		next.doFilter(line);
+	}
+}
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to