This version should do the same as v3 as far as the bug fix is concerned but I have cleaned things up a little so please test this version if possible.
Thanks, Mark
diff --git a/src/uk/me/parabola/imgfmt/app/Area.java b/src/uk/me/parabola/imgfmt/app/Area.java index 13b0ee4..9279b40 100644 --- a/src/uk/me/parabola/imgfmt/app/Area.java +++ b/src/uk/me/parabola/imgfmt/app/Area.java @@ -149,19 +149,30 @@ public class Area { } public boolean contains(Coord co) { + // return true if co is inside the Area (it may touch the + // boundary) return co.getLatitude() >= minLat && co.getLatitude() <= maxLat && co.getLongitude() >= minLong && co.getLongitude() <= maxLong; } + public boolean insideBoundary(Coord co) { + // return true if co is inside the Area and doesn't touch the + // boundary + return co.getLatitude() > minLat + && co.getLatitude() < maxLat + && co.getLongitude() > minLong + && co.getLongitude() < maxLong; + } + public boolean isEmpty() { return minLat >= maxLat || minLong >= maxLong; } - public boolean allInside(List<Coord> coords) { + public boolean allInsideBoundary(List<Coord> coords) { for (Coord co : coords) { - if (!contains(co)) + if (!insideBoundary(co)) return false; } return true; diff --git a/src/uk/me/parabola/imgfmt/app/Coord.java b/src/uk/me/parabola/imgfmt/app/Coord.java index 54cdc5f..bc84197 100644 --- a/src/uk/me/parabola/imgfmt/app/Coord.java +++ b/src/uk/me/parabola/imgfmt/app/Coord.java @@ -36,7 +36,8 @@ import uk.me.parabola.imgfmt.Utils; public class Coord implements Comparable<Coord> { private final int latitude; private final int longitude; - private int highwayCount; // number of highways that use this point + private byte highwayCount; // number of highways that use this point + private boolean onBoundary; // true if point lies on a boundary /** * Construct from co-ordinates that are already in map-units. @@ -75,7 +76,17 @@ public class Coord implements Comparable<Coord> { } public void incHighwayCount() { - ++highwayCount; + // don't let it wrap + if(highwayCount < Byte.MAX_VALUE) + ++highwayCount; + } + + public boolean getOnBoundary() { + return onBoundary; + } + + public void setOnBoundary(boolean onBoundary) { + this.onBoundary = onBoundary; } public int hashCode() { diff --git a/src/uk/me/parabola/mkgmap/general/LineClipper.java b/src/uk/me/parabola/mkgmap/general/LineClipper.java index 55aa51d..7423c3c 100644 --- a/src/uk/me/parabola/mkgmap/general/LineClipper.java +++ b/src/uk/me/parabola/mkgmap/general/LineClipper.java @@ -44,7 +44,7 @@ public class LineClipper { // If all the points are inside the box then we just return null // to show that nothing was done and the line can be used. This // is expected to be the normal case. - if (a == null || a.allInside(coords)) + if (a == null || a.allInsideBoundary(coords)) return null; class LineCollector { @@ -135,11 +135,56 @@ public class LineClipper { assert t[1] <= 1; double d = 0.5; - if (t[0] > 0) + Coord orig0 = ends[0]; + Coord orig1 = ends[1]; + if (t[0] > 0) { + // line is clipped so create the new end point and mark it + // as a boundary node ends[0] = new Coord((int) (y0 + t[0] * dy + d), (int) (x0 + t[0] * dx + d)); + ends[0].setOnBoundary(true); + } + else if(!a.insideBoundary(ends[0])) { + // point lies on the boundary so it's a boundary node + ends[0].setOnBoundary(true); + } - if (t[1] < 1) + if (t[1] < 1) { + // line is clipped so create the new end point and mark it + // as a boundary node ends[1] = new Coord((int)(y0 + t[1] * dy + d), (int) (x0 + t[1] * dx + d)); + ends[1].setOnBoundary(true); + } + else if(!a.insideBoundary(ends[1])) { + // point lies on the boundary so it's a boundary node + ends[1].setOnBoundary(true); + } + + // zero length segments can be created if one point lies on + // the boundary and the other is outside of the area + if(ends[0].equals(ends[1])) { + // throw away zero length segments + return null; + } + + // these last two tests catch the situation where the new point + // on the clipped line is so close to the original point that + // they have the same coordinates - in which case we need to use + // the original point so it maintains its identity + + if(ends[0] != orig0 && ends[0].equals(orig0)) { + // new Coord has same coordinates as original so use the + // original Coord and flag it as a boundary node + orig0.setOnBoundary(true); + ends[0] = orig0; + } + + if(ends[1] != orig1 && ends[1].equals(orig1)) { + // new Coord has same coordinates as original so use the + // original Coord and flag it as a boundary node + orig1.setOnBoundary(true); + ends[1] = orig1; + } + return ends; } diff --git a/src/uk/me/parabola/mkgmap/general/RoadNetwork.java b/src/uk/me/parabola/mkgmap/general/RoadNetwork.java index 9bc6b83..5b8d8db 100644 --- a/src/uk/me/parabola/mkgmap/general/RoadNetwork.java +++ b/src/uk/me/parabola/mkgmap/general/RoadNetwork.java @@ -103,6 +103,9 @@ public class RoadNetwork { if(node1 == node2) log.error("Road " + road.getRoadDef().getName() + " (OSM id " + road.getRoadDef().getId() + ") contains consecutive identical nodes - routing will be broken"); + else if(arcLength == 0) { + log.error("Road " + road.getRoadDef().getName() + " (OSM id " + road.getRoadDef().getId() + ") contains zero length arc"); + } // Create forward arc from node1 to node2 Coord bearing = coordList.get(lastIndex + 1); diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java index aa5bab1..1b84766 100644 --- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java +++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java @@ -68,7 +68,6 @@ public class StyledConverter implements OsmConverter { private Clipper clipper = Clipper.NULL_CLIPPER; private Area bbox; - private Set<Coord> boundaryCoords = new HashSet<Coord>(); // restrictions associates lists of turn restrictions with the // Coord corresponding to the restrictions' 'via' node @@ -432,7 +431,6 @@ public class StyledConverter implements OsmConverter { if(bbox != null) { List<List<Coord>> lineSegs = LineClipper.clip(bbox, way.getPoints()); - boundaryCoords = new HashSet<Coord>(); if (lineSegs != null) { @@ -444,8 +442,9 @@ public class StyledConverter implements OsmConverter { nWay.copyTags(way); for(Coord co : lco) { nWay.addPoint(co); - if(co.getHighwayCount() == 0) { - boundaryCoords.add(co); + if(co.getOnBoundary()) { + // this point lies on a boundary + // make sure it becomes a node co.incHighwayCount(); } } @@ -723,7 +722,7 @@ public class StyledConverter implements OsmConverter { hasInternalNodes = true; Coord coord = points.get(n); Integer nodeId = nodeIdMap.get(coord); - boolean boundary = boundaryCoords.contains(coord); + boolean boundary = coord.getOnBoundary(); if(boundary) { log.info("Way " + debugWayName + "'s point #" + n + " at " + points.get(n).toDegreeString() + " is a boundary node"); }
_______________________________________________ mkgmap-dev mailing list mkgmap-dev@lists.mkgmap.org.uk http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev