Index: src/uk/me/parabola/mkgmap/build/MapBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapBuilder.java	(Revision 940)
+++ src/uk/me/parabola/mkgmap/build/MapBuilder.java	(Arbeitskopie)
@@ -49,12 +49,14 @@
 import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.Version;
 import uk.me.parabola.mkgmap.filters.BaseFilter;
+import uk.me.parabola.mkgmap.filters.DouglasPeuckerFilter;
 import uk.me.parabola.mkgmap.filters.FilterConfig;
 import uk.me.parabola.mkgmap.filters.LineSplitterFilter;
 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.RemoveEmpty;
+import uk.me.parabola.mkgmap.filters.SizeFilter;
 import uk.me.parabola.mkgmap.filters.SmoothingFilter;
 import uk.me.parabola.mkgmap.general.LevelInfo;
 import uk.me.parabola.mkgmap.general.LoadableMapDataSource;
@@ -93,6 +95,7 @@
 	private String countryAbbr = "GBR";
 	private String regionName;
 	private String regionAbbr;
+	private double reducePointError;
 
 	public MapBuilder() {
 		regionName = null;
@@ -103,6 +106,7 @@
 		countryAbbr = props.getProperty("country-abbr", countryAbbr);
 		regionName = props.getProperty("region-name", null);
 		regionAbbr = props.getProperty("region-abbr", null);
+		reducePointError = props.getProperty("reduce-point-density", 2.6);
 	}
 
 	/**
@@ -497,7 +501,9 @@
 		config.setResolution(res);
 
 		LayerFilterChain filters = new LayerFilterChain(config);
-		filters.addFilter(new SmoothingFilter());
+		filters.addFilter(new SizeFilter());
+//		filters.addFilter(new SmoothingFilter());
+		filters.addFilter(new DouglasPeuckerFilter(reducePointError));
 		filters.addFilter(new LineSplitterFilter());
 		filters.addFilter(new RemoveEmpty());
 		filters.addFilter(new LineAddFilter(div, map, doRoads));
@@ -530,7 +536,10 @@
 		FilterConfig config = new FilterConfig();
 		config.setResolution(res);
 		LayerFilterChain filters = new LayerFilterChain(config);
-		filters.addFilter(new SmoothingFilter());
+		filters.addFilter(new SizeFilter());
+//		filters.addFilter(new SmoothingFilter());
+//DouglasPeucker behaves at the moment not optimal at low zooms, will need further work
+		filters.addFilter(new DouglasPeuckerFilter(reducePointError));
 		filters.addFilter(new PolygonSplitterFilter());
 		filters.addFilter(new RemoveEmpty());
 		filters.addFilter(new ShapeAddFilter(div, map));
Index: src/uk/me/parabola/mkgmap/filters/SizeFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/SizeFilter.java	(Revision 0)
+++ src/uk/me/parabola/mkgmap/filters/SizeFilter.java	(Revision 0)
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ * 
+ * 
+ * Author: Steve Ratcliffe
+ * Create date: Dec 1, 2007
+ */
+package uk.me.parabola.mkgmap.filters;
+
+import java.util.ArrayList;
+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;
+
+/**
+ * This is a filter that dismisses elements too small for the current resolution
+ */
+public class SizeFilter implements MapFilter {
+
+	// Minsize==1 may cause small holes in QLandkarte, but does not at etrex!
+	private static final int MIN_SIZE = 0;	// Drop elements smaller than one unit
+
+	private int minSize;
+
+	public void init(FilterConfig config) {
+		minSize = MIN_SIZE * (1<<config.getShift());
+	}
+
+	/**
+	 * This applies to both lines and polygons. 
+	 * Elements too small for current resolution will be dropped.
+	 *
+	 * @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;
+
+		// Drop things that are too small to get displayed
+		if (line.getBounds().getMaxDimention() < minSize)
+			return;
+
+		next.doFilter(line);
+	}
+}

Eigenschafts��nderungen: src/uk/me/parabola/mkgmap/filters/SizeFilter.java
___________________________________________________________________
Hinzugef��gt: svn:executable
   + *

Index: src/uk/me/parabola/mkgmap/filters/DouglasPeuckerFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/DouglasPeuckerFilter.java	(Revision 0)
+++ src/uk/me/parabola/mkgmap/filters/DouglasPeuckerFilter.java	(Revision 0)
@@ -0,0 +1,153 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.imgfmt.app.CoordNode;
+import uk.me.parabola.mkgmap.general.MapElement;
+import uk.me.parabola.mkgmap.general.MapLine;
+
+/**
+ * This is a filter that smooths out lines at low resolutions. If the element
+ * has no size at all at the given resolution, then it is not passed on down
+ * the chain at all is excluded from the map at that resolution.
+ */
+public class DouglasPeuckerFilter implements MapFilter {
+
+	private static final double ERROR_DISTANCE = 5.4 / 2;	//One unit is 5.4 m, so error dist is 2.6m
+															//Can be increased more, but may lead to artifacts on T-crossings
+
+	private double filterDistance;
+	private double maxErrorDistance;
+
+	public DouglasPeuckerFilter(double filterDistance) {
+		this.filterDistance = filterDistance;
+	}
+		
+
+	public void init(FilterConfig config) {
+		int shift = config.getShift();
+		this.maxErrorDistance = filterDistance * (1<<shift);
+	}
+
+	/**
+	 * This applies to both lines and polygons.  We are going to smooth out
+	 * the points in the line so that you do not get jaggies. 
+	 *
+	 * @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;
+
+		List<Coord> points = line.getPoints();
+		int n = points.size()-1;
+
+		// Create a new list to rewrite the points into. Don't alter the original one
+		List<Coord> coords = new ArrayList<Coord>(n);
+		coords.addAll(points);
+
+		// If the first point is identic with the last one (a polygon), drop it
+		// Otherwise douglasPeucker will not work!
+		while ((n > 0) && coords.get(0).equals(coords.get(n))) {
+			coords.remove(n);
+			n--;
+		}
+
+//#if (Node version)
+//Dont touch Coords, which are nodes. 
+//So points at croosings will not be moved
+		// For now simplify all points, which are not nodes
+		// and no start and no end point
+		// Loop runs downwards, as the list length gets modified while running
+		int endIndex = coords.size()-1;
+		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 instanceof CoordNode) {
+				douglasPeucker(coords, i, endIndex, maxErrorDistance);
+				endIndex = i;
+				i--;
+			}
+		}
+		// Simplify the rest
+		douglasPeucker(coords, 0, endIndex, maxErrorDistance);
+
+//#else Straight version
+//Do the douglasPeucker on the whole line. 
+//Deletes more points, but may lead to incorrect diplay of crossings at given high error distances 
+/*		
+		douglasPeucker(coords, 0, n, maxErrorDistance);
+	*/	
+//#endif
+		MapLine newline = line.copy();
+
+		newline.setPoints(coords);
+		next.doFilter(newline);
+	}
+
+	/**
+	 * Reduces point density by Douglas-Peucker algorithm
+	 *
+	 * @param points The list of points to simplify.
+	 * @param startIndex First index of segment. The point with this index will not be changed
+	 * @param endIndex Last index of segment. The point with this index will not be changed
+	 * @param allowedError Maximal allowed error to be introduced by simplification. 
+	 * returns number of removed points.
+	 */
+	public void douglasPeucker(List<Coord> points, int startIndex, int endIndex, double allowedError) 
+	{
+		if (startIndex >= endIndex)
+			return;
+
+		double maxDistance = 0;		//Highest distance	
+		int maxIndex = endIndex;	//Index of highest distance
+
+		Coord a = points.get(startIndex);
+		Coord b = points.get(endIndex);
+		double ab = a.distance(b);
+
+		// Find point with highest distance.
+		// Loop runs downwards, as the list length gets modified while running
+		for(int i = endIndex-1; i > startIndex; i--) {
+			Coord p = points.get(i);
+			double ap = p.distance(a);
+			double bp = p.distance(b);
+			double abpa = (ab+ap+bp)/2;
+			double distance = 2 * Math.sqrt(abpa * (abpa-ab) * (abpa-ap) * (abpa-bp)) / ab;
+			if (distance > maxDistance) {
+				maxDistance = distance;
+				maxIndex = i;
+			}
+		}
+		if (maxDistance > allowedError) {
+			// Call recursive for both parts
+			douglasPeucker(points, maxIndex, endIndex, allowedError);		
+			douglasPeucker(points, startIndex, maxIndex, allowedError);		
+		}
+		else {
+			// All points in tolerance, delete all of them.
+			for(int i = endIndex-1; i > startIndex; i--) {
+				points.remove(i);
+			}
+		}
+	}
+
+}

Eigenschafts��nderungen: src/uk/me/parabola/mkgmap/filters/DouglasPeuckerFilter.java
___________________________________________________________________
Hinzugef��gt: svn:executable
   + *

Index: src/uk/me/parabola/mkgmap/filters/SmoothingFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/SmoothingFilter.java	(Revision 940)
+++ src/uk/me/parabola/mkgmap/filters/SmoothingFilter.java	(Arbeitskopie)
@@ -68,10 +68,6 @@
 			return;
 		}
 
-		// Drop things that are too small.
-		if (line.getBounds().getMaxDimention() < MIN_SIZE)
-			return;
-
 		// If the line is not very long then just let it through.  This is done
 		// mainly for the background polygons.
 		List<Coord> points = line.getPoints();
Index: resources/help/en/options
===================================================================
--- resources/help/en/options	(Revision 940)
+++ resources/help/en/options	(Arbeitskopie)
@@ -76,6 +76,14 @@
 	in the device. See customisation help. The default is the equivalent
 	of: "0=24, 1=22, 2=21, 3=19, 4=18, 5=16" although this may change. 
 
+--reduce-point-density=num
+	Simplifies the ways with the douglas peucker algorithm.
+	num is the maximal allowed error distance, by which the resulting
+	way may differ from the original one.
+	This distance gets shifted with lower zoom levels. 
+	Recomended setting is 10, this should lead to only small differences
+	(Default is 2.6, which should lead to invisible changes) 
+
 --name-tag-list
 	Get the tag that will be used to supply the name.  Useful for language
 	variations.  You can supply a list and the first one will be used.
