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

Reply via email to