v2 - also removes points with the same coordinates as the previous
point. I know that this also gets done by the DP filter but it's very
easy to do while rounding the coordinates and it does shrink the number
of points to be processed by subsequent filters. This version of the
patch should produce the same map as v1 of the patch.
Unless anyone has any problems with this patch, I intend to commit it
in a few days as I think the line gap-filling is worthwhile.
-------
Having filled some gaps with that last little patch, I was wondering
why I still had quite a few gaps when zoomed out. Obviously, the coords
weren't being rounded to nearest given the zoom level. So, the
attached patch does that rounding and, lo and behold, even more gaps
have disappeared.
Please give it a go, especially for maps that cross the equator/day
line where the coords flip signs. Sure to be buggy but it's looking
quite promising.
BTW - this patch does not contain the last patch but they probably
should be used together.
Mark
diff --git a/src/uk/me/parabola/mkgmap/build/MapBuilder.java b/src/uk/me/parabola/mkgmap/build/MapBuilder.java
index 3c2eb0f..7b7807f 100644
--- a/src/uk/me/parabola/mkgmap/build/MapBuilder.java
+++ b/src/uk/me/parabola/mkgmap/build/MapBuilder.java
@@ -61,6 +61,7 @@ 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.RoundCoordsFilter;
import uk.me.parabola.mkgmap.filters.SizeFilter;
import uk.me.parabola.mkgmap.general.LevelInfo;
import uk.me.parabola.mkgmap.general.LoadableMapDataSource;
@@ -867,6 +868,7 @@ public class MapBuilder implements Configurable {
LayerFilterChain filters = new LayerFilterChain(config);
if (enableLineCleanFilters && (res < 24)) {
+ filters.addFilter(new RoundCoordsFilter());
filters.addFilter(new SizeFilter());
filters.addFilter(new DouglasPeuckerFilter(FILTER_DISTANCE));
}
@@ -903,6 +905,7 @@ public class MapBuilder implements Configurable {
config.setResolution(res);
LayerFilterChain filters = new LayerFilterChain(config);
if (enableLineCleanFilters && (res < 24)) {
+ filters.addFilter(new RoundCoordsFilter());
filters.addFilter(new SizeFilter());
//DouglasPeucker behaves at the moment not really optimal at low zooms, but acceptable.
//Is there an similar algorithm for polygons?
diff --git a/src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java b/src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java
new file mode 100644
index 0000000..2cdb95b
--- /dev/null
+++ b/src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java
@@ -0,0 +1,75 @@
+/*
+ * 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.imgfmt.app.CoordNode;
+
+import uk.me.parabola.mkgmap.general.MapElement;
+import uk.me.parabola.mkgmap.general.MapLine;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RoundCoordsFilter 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;
+ int half = 1 << (shift - 1); // 0.5 shifted
+ int mask = ~((1 << shift) - 1); // to remove fraction bits
+
+ if(shift == 0) {
+ // do nothing
+ next.doFilter(line);
+ }
+ else {
+ // round lat/lon values to nearest for shift
+ List<Coord> newPoints = new ArrayList<Coord>(line.getPoints().size());
+ MapLine newLine = line.copy();
+ Coord lastP = null;
+ for(Coord p : line.getPoints()) {
+ int lat = (p.getLatitude() + half) & mask;
+ int lon = (p.getLongitude() + half) & mask;
+ Coord newP;
+ if(p instanceof CoordNode)
+ newP = new CoordNode(lat, lon, ((CoordNode)p).getId(), ((CoordNode)p).isBoundary());
+ else
+ newP = new Coord(lat, lon);
+ // only add the new point if it has different
+ // coordinates to the last point or if it's a
+ // CoordNode and the last point wasn't a CoordNode
+ if(lastP == null ||
+ !lastP.equals(newP) ||
+ (newP instanceof CoordNode && !(lastP instanceof CoordNode))) {
+ newPoints.add(newP);
+ lastP = newP;
+ }
+ }
+ if(newPoints.size() > 1) {
+ newLine.setPoints(newPoints);
+ next.doFilter(newLine);
+ }
+ }
+ }
+}
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev