v2 - further fixes
Carlos, this still gives you an extra "turn left onto Calle Osa
Mayor" and I know what's happening there but can't fix it - how
about the other problems you were seeing? better/worse?
--------
Hopefully, these changes will fix the bad routing directions we have
been seeing recently - please test and report success/failure.
diff --git a/src/uk/me/parabola/imgfmt/app/net/RouteNode.java b/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
index 2b8ca79..e86f2de 100644
--- a/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
+++ b/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
@@ -15,6 +15,8 @@
package uk.me.parabola.imgfmt.app.net;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
@@ -298,6 +300,12 @@ public class RouteNode implements Comparable<RouteNode> {
RoadDef rda = raa.getRoadDef();
RoadDef rdb = rab.getRoadDef();
+
+ if(rda.getId() == rdb.getId()) {
+ // roads have the same (OSM) id
+ return true;
+ }
+
boolean bothArcsNamed = false;
for(Label laba : rda.getLabels()) {
if(laba != null && laba.getOffset() != 0) {
@@ -339,6 +347,26 @@ public class RouteNode implements Comparable<RouteNode> {
return false;
}
+ private static boolean rightTurnRequired(int inHeading, int outHeading, int sideHeading) {
+ // given the headings of the incoming, outgoing and side
+ // roads, decide whether a side road is to the left or the
+ // right of the main road
+
+ outHeading -= inHeading;
+ while(outHeading < -180)
+ outHeading += 360;
+ while(outHeading > 180)
+ outHeading -= 360;
+
+ sideHeading -= inHeading;
+ while(sideHeading < -180)
+ sideHeading += 360;
+ while(sideHeading > 180)
+ sideHeading -= 360;
+
+ return sideHeading > outHeading;
+ }
+
private static int ATH_OUTGOING = 1;
private static int ATH_INCOMING = 2;
@@ -375,9 +403,29 @@ public class RouteNode implements Comparable<RouteNode> {
final int minDiffBetweenOutgoingAndOtherArcs = 45;
final int minDiffBetweenIncomingAndOtherArcs = 50;
- for(RouteArc inArc : incomingArcs) {
+ // list of outgoing arcs discovered at this node
+ List<RouteArc> outgoingArcs = new ArrayList<RouteArc>();
+
+ // sort incoming arcs by decreasing class/speed
+ List<RouteArc> inArcs = new ArrayList<RouteArc>(incomingArcs);
+
+ Collections.sort(inArcs, new Comparator<RouteArc>() {
+ public int compare(RouteArc ra1, RouteArc ra2) {
+ int c1 = ra1.getRoadDef().getRoadClass();
+ int c2 = ra2.getRoadDef().getRoadClass();
+ if(c1 == c2)
+ return (ra2.getRoadDef().getRoadSpeed() -
+ ra1.getRoadDef().getRoadSpeed());
+ return c2 - c1;
+ }
+ });
+
+ // look at incoming arcs in order of decreasing class/speed
+ for(RouteArc inArc : inArcs) {
+
+ RoadDef inRoadDef = inArc.getRoadDef();
- if(!inArc.isForward() && inArc.getRoadDef().isOneway()) {
+ if(!inArc.isForward() && inRoadDef.isOneway()) {
// ignore reverse arc if road is oneway
continue;
}
@@ -392,7 +440,7 @@ public class RouteNode implements Comparable<RouteNode> {
for(RouteArc[] pair : throughRoutes) {
if(pair[0] == inArc) {
outArc = pair[1];
- log.info("Found through route from " + inArc.getRoadDef() + " to " + outArc.getRoadDef());
+ log.info("Found through route from " + inRoadDef + " to " + outArc.getRoadDef());
break;
}
}
@@ -405,7 +453,7 @@ public class RouteNode implements Comparable<RouteNode> {
if(oa.getDest() != inArc.getSource()) {
// this arc is not going to the same node as
// inArc came from
- if(oa.getRoadDef() == inArc.getRoadDef()) {
+ if(oa.getRoadDef() == inRoadDef) {
outArc = oa;
break;
}
@@ -415,7 +463,7 @@ public class RouteNode implements Comparable<RouteNode> {
if(outArc == null) {
// next, although the RoadDefs don't match, use
- // possiblySameRoad() to see if the road
+ // possiblySameRoad() to see if the roads' id or
// labels (names/refs) match
for(RouteArc oa : arcs) {
if(oa.getDest() != inArc.getSource()) {
@@ -430,43 +478,60 @@ public class RouteNode implements Comparable<RouteNode> {
}
}
- if(outArc == null) {
+ if(outArc == null && inRoadDef.getNumLabels() == 0) {
// last ditch attempt to find the outgoing arc -
- // try and find a single arc that has the same
- // road class and speed as the incoming arc
- int inArcClass = inArc.getRoadDef().getRoadClass();
- int inArcSpeed = inArc.getRoadDef().getRoadSpeed();
+ // try and find a single (anonymous) arc that has
+ // the same road class and speed as the incoming
+ // arc
+ int inArcClass = inRoadDef.getRoadClass();
+ int inArcSpeed = inRoadDef.getRoadSpeed();
for(RouteArc oa : arcs) {
- if(oa.getDest() != inArc.getSource() &&
+ if(oa.getRoadDef().getNumLabels() == 0 &&
+ oa.getDest() != inArc.getSource() &&
oa.getRoadDef().getRoadClass() == inArcClass &&
oa.getRoadDef().getRoadSpeed() == inArcSpeed) {
if(outArc != null) {
// multiple arcs have the same road
- // class as the incoming arc so don't
- // use any of them as the outgoing arc
+ // class/speed as the incoming arc so
+ // don't use any of them as the
+ // outgoing arc
outArc = null;
break;
}
- outArc = oa;
+ // oa has the same class/speed as inArc,
+ // now check that oa is not part of
+ // another road by matching names rather
+ // than class/speed because they could be
+ // different
+ boolean paired = false;
+ for(RouteArc z : arcs)
+ if(z != oa && possiblySameRoad(z, oa))
+ paired = true;
+ if(!paired)
+ outArc = oa;
}
}
if(outArc != null)
- log.info("Matched outgoing arc " + outArc.getRoadDef() + " to " + inArc.getRoadDef() + " using road class (" + inArcClass + ") and speed (" + inArcSpeed + ")");
+ log.info("Matched outgoing arc " + outArc.getRoadDef() + " to " + inRoadDef + " using road class (" + inArcClass + ") and speed (" + inArcSpeed + ") at " + coord.toOSMURL());
}
// if we did not find the outgoing arc, give up with
// this incoming arc
if(outArc == null) {
- //log.info("Can't continue road " + inArc.getRoadDef() + " at " + coord.toOSMURL());
+ //log.info("Can't continue road " + inRoadDef + " at " + coord.toOSMURL());
continue;
}
+
+ // remember that this arc is an outgoing arc
+ outgoingArcs.add(outArc);
+
int outHeading = outArc.getInitialHeading();
int mainHeadingDelta = outHeading - inHeading;
while(mainHeadingDelta > 180)
mainHeadingDelta -= 360;
while(mainHeadingDelta < -180)
mainHeadingDelta += 360;
- //log.info(inArc.getRoadDef() + " continues to " + outArc.getRoadDef() + " with a heading change of " + mainHeadingDelta + " at " + coord.toOSMURL());
+ //log.info(inRoadDef + " continues to " + outArc.getRoadDef() + " with a heading change of " + mainHeadingDelta + " at " + coord.toOSMURL());
if(Math.abs(mainHeadingDelta) > maxMainRoadHeadingChange) {
// if the continuation road heading change is
@@ -497,7 +562,7 @@ public class RouteNode implements Comparable<RouteNode> {
continue;
}
- if(inArc.getRoadDef().isLinkRoad() &&
+ if(inRoadDef.isLinkRoad() &&
otherArc.getRoadDef().isLinkRoad()) {
// it's a link road leaving a link road so
// leave the angle unchanged to avoid
@@ -507,6 +572,13 @@ public class RouteNode implements Comparable<RouteNode> {
continue;
}
+ if(outgoingArcs.contains(otherArc)) {
+ // this arc was previously matched as an
+ // outgoing arc so we don't want to change its
+ // heading now
+ continue;
+ }
+
int otherHeading = otherArc.getInitialHeading();
int outToOtherDelta = otherHeading - outHeading;
while(outToOtherDelta > 180)
@@ -520,13 +592,13 @@ public class RouteNode implements Comparable<RouteNode> {
inToOtherDelta += 360;
int newHeading = otherHeading;
- if(outToOtherDelta > 0) {
+ if(rightTurnRequired(inHeading, outHeading, otherHeading)) {
// side road to the right
if((mask & ATH_OUTGOING) != 0 &&
- outToOtherDelta < minDiffBetweenOutgoingAndOtherArcs)
+ Math.abs(outToOtherDelta) < minDiffBetweenOutgoingAndOtherArcs)
newHeading = outHeading + minDiffBetweenOutgoingAndOtherArcs;
if((mask & ATH_INCOMING) != 0 &&
- inToOtherDelta < minDiffBetweenIncomingAndOtherArcs) {
+ Math.abs(inToOtherDelta) < minDiffBetweenIncomingAndOtherArcs) {
int nh = inHeading + minDiffBetweenIncomingAndOtherArcs;
if(nh > newHeading)
newHeading = nh;
@@ -535,13 +607,13 @@ public class RouteNode implements Comparable<RouteNode> {
if(newHeading > 180)
newHeading -= 360;
}
- else if(outToOtherDelta < 0) {
+ else {
// side road to the left
if((mask & ATH_OUTGOING) != 0 &&
- outToOtherDelta > -minDiffBetweenOutgoingAndOtherArcs)
+ Math.abs(outToOtherDelta) < minDiffBetweenOutgoingAndOtherArcs)
newHeading = outHeading - minDiffBetweenOutgoingAndOtherArcs;
if((mask & ATH_INCOMING) != 0 &&
- inToOtherDelta > -minDiffBetweenIncomingAndOtherArcs) {
+ Math.abs(inToOtherDelta) < minDiffBetweenIncomingAndOtherArcs) {
int nh = inHeading - minDiffBetweenIncomingAndOtherArcs;
if(nh < newHeading)
newHeading = nh;
@@ -552,7 +624,7 @@ public class RouteNode implements Comparable<RouteNode> {
}
if(newHeading != otherHeading) {
otherArc.setInitialHeading(newHeading);
- log.info("Adjusting turn heading from " + otherHeading + " to " + newHeading + " at junction of " + inArc.getRoadDef() + " and " + otherArc.getRoadDef() + " at " + coord.toOSMURL());
+ log.info("Adjusting turn heading from " + otherHeading + " to " + newHeading + " at junction of " + inRoadDef + " and " + otherArc.getRoadDef() + " at " + coord.toOSMURL());
}
}
}
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev