Hi Felix,
are you a night worker or do you live in another timezone? :-)
I wanted to apply it but I get "The chunk size did not match the
number of added/removed lines!"
Is there possibly something wrong with Patch V8?
Yes, I have seen some minor changes in the patch, which should not be
included, so I modified it by hand. Seems to be no good idea. Attached
the corrected patch.
Please note: The patch should work as far it is implemented now. But I
have some more ideas for the dp filter, which would need some rework of
the base classes, for which I have not the time at the moment. It should
be clearly an improvement, but shows not its full potential at the moment.
Index: src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java (Revision 1404)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java (Arbeitskopie)
@@ -55,6 +55,7 @@
import uk.me.parabola.mkgmap.reader.osm.Rule;
import uk.me.parabola.mkgmap.reader.osm.Style;
import uk.me.parabola.mkgmap.reader.osm.Way;
+import uk.me.parabola.util.EnhancedProperties;
import uk.me.parabola.mkgmap.reader.polish.PolishMapDataSource;
/**
@@ -143,7 +144,7 @@
}
};
- public StyledConverter(Style style, MapCollector collector, Properties props) {
+ public StyledConverter(Style style, MapCollector collector, EnhancedProperties props) {
this.collector = collector;
nameTagList = style.getNameTagList();
Index: src/uk/me/parabola/mkgmap/build/MapBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapBuilder.java (Revision 1404)
+++ src/uk/me/parabola/mkgmap/build/MapBuilder.java (Arbeitskopie)
@@ -57,6 +57,7 @@
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.LineMergeFilter;
import uk.me.parabola.mkgmap.filters.MapFilter;
import uk.me.parabola.mkgmap.filters.MapFilterChain;
import uk.me.parabola.mkgmap.filters.PolygonSplitterFilter;
@@ -107,6 +108,10 @@
private String countryAbbr = "ABC";
private String regionName;
private String regionAbbr;
+
+ private double reducePointError;
+ private boolean mergeLines;
+
private int locationAutofillLevel;
private boolean poiAddresses = true;
private int poiDisplayFlags;
@@ -126,6 +131,8 @@
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);
+ mergeLines = props.containsKey("merge-lines");
makePOIIndex = props.getProperty("make-poi-index", false);
@@ -866,11 +873,19 @@
FilterConfig config = new FilterConfig();
config.setResolution(res);
+
+ //TODO: Maybe this is the wrong place to do merging.
+ // Maybe more efficient if merging before creating subdivisions.
+ if (mergeLines && res < 24) {
+ LineMergeFilter merger = new LineMergeFilter();
+ lines = merger.merge(lines);
+ }
+
LayerFilterChain filters = new LayerFilterChain(config);
if (enableLineCleanFilters && (res < 24)) {
filters.addFilter(new RoundCoordsFilter());
filters.addFilter(new SizeFilter());
- filters.addFilter(new DouglasPeuckerFilter(FILTER_DISTANCE));
+ filters.addFilter(new DouglasPeuckerFilter(reducePointError));
}
filters.addFilter(new LineSplitterFilter());
filters.addFilter(new RemoveEmpty());
@@ -909,7 +924,7 @@
filters.addFilter(new SizeFilter());
//DouglasPeucker behaves at the moment not really optimal at low zooms, but acceptable.
//Is there an similar algorithm for polygons?
- filters.addFilter(new DouglasPeuckerFilter(FILTER_DISTANCE));
+ filters.addFilter(new DouglasPeuckerFilter(reducePointError));
}
filters.addFilter(new PolygonSplitterFilter());
filters.addFilter(new RemoveEmpty());
Index: src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5MapDataSource.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5MapDataSource.java (Revision 1404)
+++ src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5MapDataSource.java (Arbeitskopie)
@@ -32,6 +32,7 @@
import uk.me.parabola.mkgmap.osmstyle.eval.SyntaxException;
import uk.me.parabola.mkgmap.reader.osm.OsmConverter;
import uk.me.parabola.mkgmap.reader.osm.Style;
+import uk.me.parabola.util.EnhancedProperties;
import org.xml.sax.SAXException;
@@ -104,7 +105,7 @@
*/
private OsmConverter createStyler() {
- Properties props = getConfig();
+ EnhancedProperties props = getConfig();
String loc = props.getProperty("style-file");
if (loc == null)
loc = props.getProperty("map-features");
Index: src/uk/me/parabola/mkgmap/filters/LineMergeFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/LineMergeFilter.java (Revision 0)
+++ src/uk/me/parabola/mkgmap/filters/LineMergeFilter.java (Revision 0)
@@ -0,0 +1,110 @@
+package uk.me.parabola.mkgmap.filters;
+
+import java.util.List;
+import java.util.ArrayList;
+import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.log.Logger;
+import uk.me.parabola.mkgmap.general.MapLine;
+import uk.me.parabola.util.MultiHashMap;
+
+
+
+public class LineMergeFilter{
+ private static final Logger log = Logger.getLogger(LineMergeFilter.class);
+
+ List<MapLine> linesMerged;
+ MultiHashMap<Coord, MapLine> startPoints = new MultiHashMap<Coord, MapLine>();
+ MultiHashMap<Coord, MapLine> endPoints = new MultiHashMap<Coord, MapLine>();
+
+ public LineMergeFilter() {}
+
+ private void addLine(MapLine line) {
+ linesMerged.add(line);
+ List<Coord> points = line.getPoints();
+ startPoints.add(points.get(0), line);
+ endPoints.add(points.get(points.size()-1), line);
+ }
+
+ private void mergeLines(MapLine line1, MapLine line2) {
+ // Removes the first line,
+ // Merges the points in the second one
+ List<Coord> points1 = line1.getPoints();
+ List<Coord> points2 = line2.getPoints();
+ startPoints.remove(points1.get(0), line1);
+ endPoints.remove(points1.get(points1.size()-1), line1);
+ startPoints.remove(points2.get(0), line2);
+ startPoints.add(points1.get(0), line2);
+ line2.insertPointsAtStart(points1);
+ linesMerged.remove(line1);
+ }
+
+ private void addPointsAtStart(MapLine line, List<Coord> additionalPoints) {
+ log.info("merged lines before " + line.getName());
+ List<Coord> points = line.getPoints();
+ startPoints.remove(points.get(0), line);
+ line.insertPointsAtStart(additionalPoints);
+ startPoints.add(points.get(0), line);
+ }
+
+ private void addPointsAtEnd(MapLine line, List<Coord> additionalPoints) {
+ log.info("merged lines after " + line.getName());
+ List<Coord> points = line.getPoints();
+ endPoints.remove(points.get(points.size()-1), line);
+ line.insertPointsAtEnd(additionalPoints);
+ endPoints.add(points.get(points.size()-1), line);
+ }
+
+ public List<MapLine> merge(List<MapLine> lines) {
+ linesMerged = new ArrayList<MapLine>(lines.size()); //better use LinkedList??
+ for (MapLine line : lines) {
+ boolean isMerged = false;
+ List<Coord> points = line.getPoints();
+ Coord start = points.get(0);
+ Coord end = points.get(points.size()-1);
+
+ // Search for start point in hashlist
+ // (can the end of current line connected to an existing line?)
+ for (MapLine line2 : startPoints.get(end)) {
+ if (line.isSimilar(line2)) {
+ addPointsAtStart(line2, points);
+ // Search for endpoint in hashlist
+ // (if the other end (=start of line =start of line2) could be connected to an existing line,
+ // both lines has to be merged and one of them dropped)
+ for (MapLine line1 : endPoints.get(start)) {
+ if (line2.isSimilar(line1)
+ && !line2.equals(line1)) // don't make a closed loop a double loop
+ {
+ mergeLines(line1, line2);
+ break;
+ }
+ }
+ isMerged = true;
+ break;
+ }
+ }
+ if (isMerged)
+ continue;
+
+ // Search for endpoint in hashlist
+ // (can the start of current line connected to an existing line?)
+ for (MapLine line2 : endPoints.get(start)) {
+ if (line.isSimilar(line2)) {
+ addPointsAtEnd(line2, points);
+ isMerged = true;
+ break;
+ }
+ }
+ if (isMerged)
+ continue;
+
+ // No matching, create a copy of line
+ MapLine l = line.copy();
+ List<Coord> p = new ArrayList<Coord>(line.getPoints()); //use better LinkedList for performance?
+ l.setPoints(p);
+ addLine(l);
+ }
+ return linesMerged;
+ }
+
+}
+
Index: src/uk/me/parabola/mkgmap/general/MapLine.java
===================================================================
--- src/uk/me/parabola/mkgmap/general/MapLine.java (Revision 1404)
+++ src/uk/me/parabola/mkgmap/general/MapLine.java (Arbeitskopie)
@@ -59,8 +59,13 @@
if (this.points != null)
log.warn("overwriting points");
assert points != null : "trying to set null points";
+ assert points.size() != 0 : "trying to set points with zero length";
this.points = points;
+ testForConsecutivePoints(points);
+ }
+
+ public void testForConsecutivePoints(List<Coord> points) {
Coord last = null;
for (Coord co : points) {
if (last != null && last.equals(co))
@@ -72,6 +77,18 @@
}
}
+ public void insertPointsAtStart(List<Coord> additionalPoints) {
+ testForConsecutivePoints(additionalPoints);
+ points.addAll(0, additionalPoints);
+ points.remove(additionalPoints.size()-1); //End node exists now twice
+ }
+
+ public void insertPointsAtEnd(List<Coord> additionalPoints) {
+ testForConsecutivePoints(additionalPoints);
+ points.remove(points.size()-1);
+ points.addAll(additionalPoints);
+ }
+
public boolean isDirection() {
return direction;
}
Index: src/uk/me/parabola/mkgmap/general/MapElement.java
===================================================================
--- src/uk/me/parabola/mkgmap/general/MapElement.java (Revision 1404)
+++ src/uk/me/parabola/mkgmap/general/MapElement.java (Arbeitskopie)
@@ -167,6 +167,24 @@
this.type = type;
}
+ public boolean isSimilar(MapElement other) {
+ if (this.minResolution != other.minResolution)
+ return false;
+ if (this.maxResolution != other.maxResolution)
+ return false;
+ if (this.type != other.type)
+ return false;
+
+ String thisName = getName();
+ String otherName = other.getName();
+
+ if (thisName == null && otherName == null)
+ return true;
+ if (thisName!=null && otherName!=null && thisName.equals(otherName))
+ return true;
+ return false;
+ }
+
public boolean hasExtendedType() {
return hasExtendedType(type);
}
Index: src/uk/me/parabola/util/MultiHashMap.java
===================================================================
--- src/uk/me/parabola/util/MultiHashMap.java (Revision 0)
+++ src/uk/me/parabola/util/MultiHashMap.java (Revision 0)
@@ -0,0 +1,59 @@
+package uk.me.parabola.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+
+public class MultiHashMap<K,V> extends HashMap<K,List<V>> {
+
+ /**
+ * the empty list to be returned when there is key without values.
+ */
+ private List<V> emptyList = Collections.unmodifiableList(new ArrayList<V>(0));
+
+ /**
+ * Returns the list of values associated with the given key.
+ *
+ * @param o the key to get the values for.
+ * @return a list of values for the given keys or the empty list of no such
+ * value exist.
+ */
+ public List<V> get(K key) {
+ List<V> result = super.get(key);
+ return result == null ? emptyList : result;
+ }
+
+
+ public V add(K key, V value )
+ {
+
+ List<V> values = super.get(key);
+ if (values == null ) {
+ values = new LinkedList<V>();
+ super.put( key, values );
+ }
+
+ boolean results = values.add(value);
+
+ return ( results ? value : null );
+ }
+
+ public V remove(K key, V value )
+ {
+
+ List<V> values = super.get(key);
+ if (values == null )
+ return null;
+
+ values.remove(value);
+
+ if (values.size() == 0)
+ super.remove(values);
+
+ return value;
+ }
+}
+
Index: resources/help/en/options
===================================================================
--- resources/help/en/options (Revision 1404)
+++ resources/help/en/options (Arbeitskopie)
@@ -156,6 +156,21 @@
number is 63240000.
+Optimization options:
+
+--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.
+ Recommended setting is 10, this should lead to only small differences
+ (Default is 2.6, which should lead to invisible changes)
+
+--merge-lines
+ Try to merge lines. This helps the simplify filter to straighten out
+ longer chunks at lower zoom levels. Decreases file size more.
+ Increases paint speed at low zoom levels
+
Miscellaneous options:
--max-jobs[=number]
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev