The good news is that this should now no longer falsely complain about
a flare road being the wrong direction when that flare road pair are
the only roads connected to a given roundabout.

The bad news is that it will now find more bad flare roads than it did
before - and you thought you had fixed them all!


diff --git a/src/uk/me/parabola/imgfmt/app/net/RouteNode.java b/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
index c01f7a9..f33496b 100644
--- a/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
+++ b/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
@@ -602,6 +602,31 @@ public class RouteNode implements Comparable<RouteNode> {
 		}
 	}
 
+	// determine "distance" between two nodes on a roundabout
+	private int roundaboutSegmentLength(final RouteNode n1, final RouteNode n2) {
+		List<RouteNode> seen = new ArrayList<RouteNode>();
+		int len = 0;
+		RouteNode n = n1;
+		for(;;) {
+			seen.add(n);
+			for(RouteArc a : n.arcs) {
+				if(a.isForward() &&
+				   a.getRoadDef().isRoundabout() &&
+				   !a.getRoadDef().isSynthesised()) {
+					len += a.getLength();
+					n = a.getDest();
+					if(n == n2)
+						return len;
+					break;
+				}
+			}
+			if(seen.contains(n)) {
+				// looped around without finding n2 - weird
+				return Integer.MAX_VALUE;
+			}
+		}
+	}
+
 	// sanity check roundabout flare roads - the flare roads connect a
 	// two-way road to a roundabout using short one-way segments so
 	// the resulting sub-junction looks like a triangle with two
@@ -614,12 +639,54 @@ public class RouteNode implements Comparable<RouteNode> {
 			// roundabout
 			if(!r.isForward() || !r.getRoadDef().isRoundabout() || r.getRoadDef().isSynthesised())
 				continue;
-			// now try and find the two arcs that make up the
-			// triangular "flare" connected to both ends of r
+			// follow the arc to find the first node that connects the
+			// roundabout to a non-roundabout segment
 			RouteNode nb = r.getDest();
+			for(;;) {
+				boolean connectsToNonRoundaboutSegment = false;
+				RouteArc nextRoundaboutArc = null;
+				for(RouteArc nba : nb.arcs) {
+					if(!nba.getRoadDef().isSynthesised()) {
+						if(nba.getRoadDef().isRoundabout()) {
+							if(nba.isForward())
+								nextRoundaboutArc = nba;
+						}
+						else
+							connectsToNonRoundaboutSegment = true;
+					}
+				}
+
+				if(nb == this) {
+					// looped back to start - give up
+					if(!connectsToNonRoundaboutSegment) {
+						// FIXME - stop this warning griping about
+						// roundabouts whose ways are tagged
+						// highway=construction
+
+						// log.warn("Roundabout " + r.getRoadDef() + " is not connected to any ways at " + coord.toOSMURL());
+					}
+					nb = null;
+					break;
+				}
+
+				if(connectsToNonRoundaboutSegment || nextRoundaboutArc == null)
+					break;
+
+				nb = nextRoundaboutArc.getDest();
+			}
+
+			if(nb == null) {
+				// something weird about this roundabout, forget it
+				continue;
+			}
+
+			// now try and find the two arcs that make up the
+			// triangular "flare" connected to both ends of the
+			// roundabout segment
 			for(RouteArc fa : arcs) {
 				if(!fa.getRoadDef().doFlareCheck())
 					continue;
+
 				for(RouteArc fb : nb.arcs) {
 					if(!fb.getRoadDef().doFlareCheck())
 						continue;
@@ -627,32 +694,24 @@ public class RouteNode implements Comparable<RouteNode> {
 						// found the 3rd point of the triangle that
 						// should be connecting the two flare roads
 
-						// first, special test for roundabouts that
-						// have a single flare and no other
-						// connections - only check the flare for the
-						// shorter of the two roundabout segments
-
-						boolean isShortest = true;
-						for(RouteArc rb : nb.arcs) {
-							if(rb.getDest() == this &&
-							   rb.isForward() &&
-							   rb.getRoadDef().isRoundabout()) {
-								isShortest = r.getLength() < rb.getLength();
-								break;
-							}
-						}
+						// first, special test required to cope with
+						// roundabouts that have a single flare and no
+						// other connections - only check the flare
+						// for the shorter of the two roundabout
+						// segments
 
-						if(!isShortest)
+						if(roundaboutSegmentLength(this, nb) >=
+						   roundaboutSegmentLength(nb, this))
 							continue;
 
 						if(maxFlareLengthRatio > 0) {
 							// if both of the flare roads are much
-							// longer than the length of r, they are
-							// probably not flare roads at all but
-							// just two roads that meet up - so ignore
-							// them
-							final int maxFlareLength = r.getLength() * maxFlareLengthRatio;
-							if(r.getLength() > 0 &&
+							// longer than the length of the
+							// roundabout segment, they are probably
+							// not flare roads at all but just two
+							// roads that meet up - so ignore them
+							final int maxFlareLength = roundaboutSegmentLength(this, nb) * maxFlareLengthRatio;
+							if(maxFlareLength > 0 &&
 							   fa.getLength() > maxFlareLength &&
 							   fb.getLength() > maxFlareLength) {
 								continue;
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to