Hi Gerd
I was trying to diagnose a problem with a repeating points in polylines
as reported by GPSMapEdit and found a problem in
RemoveObsoletePointsFilter where it duplicates a point.
Also in this and/or RoundCoordsFilter I've made some changes:
1/ stop the chain when polygons get too small
2/ keep polygons closed with the same first/last point
3/ slight logic tidy-up
4/ add a couple of debug lines to be consistent
Patch attached.
Actually these didn't make any difference to the repeating points
problem. This happens when there are enough unused bits in the last
byte of the polyline bitsteam to represent an extra point. I can't see
any good way of stopping this.
Ticker
Index: src/uk/me/parabola/mkgmap/filters/RemoveObsoletePointsFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/RemoveObsoletePointsFilter.java (revision 4616)
+++ src/uk/me/parabola/mkgmap/filters/RemoveObsoletePointsFilter.java (working copy)
@@ -29,8 +29,6 @@
*/
public class RemoveObsoletePointsFilter implements MapFilter {
private static final Logger log = Logger.getLogger(RemoveObsoletePointsFilter.class);
-
- final Coord[] areaTest = new Coord[3];
private boolean checkPreserved;
@@ -48,18 +46,12 @@
MapLine line = (MapLine) element;
List<Coord> points = line.getPoints();
int numPoints = points.size();
- if (numPoints <= 1){
- return;
- }
- int requiredPoints = (line instanceof MapShape ) ? 4:2;
+ int requiredPoints = (line instanceof MapShape) ? 4 : 2;
List<Coord> newPoints = new ArrayList<>(numPoints);
while (true){
boolean removedSpike = false;
- numPoints = points.size();
-
-
- Coord lastP = points.get(0);
- newPoints.add(lastP);
+ Coord lastP;
+ newPoints.add(points.get(0));
for (int i = 1; i < numPoints; i++) {
Coord newP = points.get(i);
int last = newPoints.size()-1;
@@ -72,6 +64,7 @@
continue;
} else if (!lastP.preserved()){
newPoints.set(last, newP); // replace last
+ continue;
}
} else {
continue;
@@ -104,36 +97,45 @@
newPoints.add(newP);
}
- if (!removedSpike || newPoints.size() < requiredPoints)
+ numPoints = newPoints.size();
+ if (numPoints < requiredPoints)
+ return;
+ if (!removedSpike)
break;
points = newPoints;
- newPoints = new ArrayList<>(points.size());
+ newPoints = new ArrayList<>(numPoints);
}
if (line instanceof MapShape){
// Check special cases caused by the fact that the first and last point
// in a shape are identical.
- while (newPoints.size() > 3){
- int nPoints = newPoints.size();
- switch(Utils.isStraight(newPoints.get(newPoints.size()-2), newPoints.get(0), newPoints.get(1))){
+ isStraightCheck:
+ while (true) {
+ switch (Utils.isStraight(newPoints.get(numPoints-2), newPoints.get(0), newPoints.get(1))) {
case Utils.STRAIGHT_SPIKE:
+ log.debug("removing closing spike");
+ --numPoints;
newPoints.remove(0);
- newPoints.set(newPoints.size()-1, newPoints.get(0));
- if (newPoints.get(newPoints.size()-2).equals(newPoints.get(newPoints.size()-1)))
- newPoints.remove(newPoints.size()-1);
+ newPoints.set(numPoints-1, newPoints.get(0));
+ if (newPoints.get(numPoints-2).equals(newPoints.get(numPoints-1))) {
+ newPoints.remove(numPoints-2); // keep the identical closing point
+ --numPoints;
+ }
break;
case Utils.STRICTLY_STRAIGHT:
- newPoints.remove(newPoints.size()-1);
- newPoints.set(0, newPoints.get(newPoints.size()-1));
+ log.debug("removing straight line across closing");
+ --numPoints;
+ newPoints.remove(numPoints);
+ newPoints.set(0, newPoints.get(numPoints-1));
break;
+ default:
+ break isStraightCheck;
}
- if (nPoints == newPoints.size())
- break;
+ if (numPoints < requiredPoints)
+ return;
}
}
-
- if (newPoints.size() != line.getPoints().size()){
- if (line instanceof MapShape && newPoints.size() <= 3 || newPoints.size() <= 1)
- return;
+
+ if (numPoints != line.getPoints().size()) {
MapLine newLine = line.copy();
newLine.setPoints(newPoints);
next.doFilter(newLine);
Index: src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java (revision 4616)
+++ src/uk/me/parabola/mkgmap/filters/RoundCoordsFilter.java (working copy)
@@ -18,11 +18,14 @@
import uk.me.parabola.imgfmt.app.Coord;
import uk.me.parabola.imgfmt.app.CoordNode;
+import uk.me.parabola.log.Logger;
import uk.me.parabola.mkgmap.general.MapElement;
import uk.me.parabola.mkgmap.general.MapLine;
import uk.me.parabola.mkgmap.general.MapRoad;
+import uk.me.parabola.mkgmap.general.MapShape;
public class RoundCoordsFilter implements MapFilter {
+ private static final Logger log = Logger.getLogger(RoundCoordsFilter.class);
private int shift;
private boolean keepNodes;
@@ -31,8 +34,8 @@
@Override
public void init(FilterConfig config) {
shift = config.getShift();
- keepNodes = config.getLevel() == 0 && config.hasNet();
level = config.getLevel();
+ keepNodes = level == 0 && config.hasNet();
}
/**
@@ -41,12 +44,11 @@
*/
@Override
public void doFilter(MapElement element, MapFilterChain next) {
- MapLine line = (MapLine) element;
- if(shift == 0) {
+ if (shift == 0) {
// do nothing
- next.doFilter(line);
- }
- else {
+ next.doFilter(element);
+ } else {
+ MapLine line = (MapLine) element;
int half = 1 << (shift - 1); // 0.5 shifted
int mask = ~((1 << shift) - 1); // to remove fraction bits
@@ -64,9 +66,9 @@
int lon = (p.getLongitude() + half) & mask;
Coord newP;
- if(p instanceof CoordNode && keepNodes)
+ if (p instanceof CoordNode && keepNodes) {
newP = new CoordNode(lat, lon, p.getId(), p.getOnBoundary(), p.getOnCountryBorder());
- else {
+ } else {
newP = new Coord(lat, lon);
newP.preserved(p.preserved());
newP.setNumberNode(hasNumbers && p.isNumberNode());
@@ -87,7 +89,10 @@
lastP.preserved(true);
}
}
- if(newPoints.size() > 1) {
+ int numPoints = newPoints.size();
+ if (numPoints >= (line instanceof MapShape ? 4 : 2)) {
+ if (newPoints.get(0).equals(newPoints.get(numPoints-1)))
+ newPoints.set(numPoints-1, newPoints.get(0)); // keep closed
MapLine newLine = line.copy();
newLine.setPoints(newPoints);
next.doFilter(newLine);
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev