Fix turn lanes #2935

This commit is contained in:
Victor Shcherb 2016-08-11 23:35:04 +02:00
parent 71fb0f8df5
commit 4112681f00
3 changed files with 78 additions and 20 deletions

View file

@ -1,5 +1,6 @@
package net.osmand.router; package net.osmand.router;
import gnu.trove.iterator.TIntIterator;
import gnu.trove.list.array.TIntArrayList; import gnu.trove.list.array.TIntArrayList;
import gnu.trove.set.hash.TIntHashSet; import gnu.trove.set.hash.TIntHashSet;
@ -947,28 +948,29 @@ public class RouteResultPreparation {
rawLanes[k] |= 1; rawLanes[k] |= 1;
} }
} }
int tp = inferTurnFromLanes(rawLanes); int tp = inferSlightTurnFromLanes(rawLanes, rs);
if (tp != t.getValue() && tp != 0) { if (tp != t.getValue() && tp != 0) {
t = TurnType.valueOf(tp, leftSide); t = TurnType.valueOf(tp, leftSide);
} }
} else { } else {
boolean possiblyLeftTurn = rs.roadsOnLeft == 0;
boolean possiblyRightTurn = rs.roadsOnRight == 0;
for (int k = 0; k < rawLanes.length; k++) { for (int k = 0; k < rawLanes.length; k++) {
int turn = TurnType.getPrimaryTurn(rawLanes[k]); int turn = TurnType.getPrimaryTurn(rawLanes[k]);
int sturn = TurnType.getSecondaryTurn(rawLanes[k]); int sturn = TurnType.getSecondaryTurn(rawLanes[k]);
boolean active = false; boolean active = false;
if (turn == TurnType.C) { // some turns go through many segments (to turn right or left)
if ((TurnType.isRightTurn(sturn) && rs.roadsOnRight == 0) // so on one first segment the lane could be available and may be only 1 possible
|| (TurnType.isLeftTurn(sturn) && rs.roadsOnLeft == 0)) { // all undesired lanes will be disabled through the 2nd pass
TurnType.setPrimaryTurn(rawLanes, k, sturn); if((TurnType.isRightTurn(sturn) && possiblyRightTurn) ||
TurnType.setSecondaryTurn(rawLanes, k, turn); (TurnType.isLeftTurn(sturn) && possiblyLeftTurn)) {
} TurnType.setPrimaryTurn(rawLanes, k, sturn);
TurnType.setSecondaryTurn(rawLanes, k, turn);
active = true; active = true;
} else if (TurnType.isRightTurn(turn) && rs.roadsOnRight == 0) { } else if((TurnType.isRightTurn(turn) && possiblyRightTurn) ||
// some turns go through many segments (to turn right or left) (TurnType.isLeftTurn(turn) && possiblyLeftTurn)) {
// so on one first segment the lane could be available and may be only 1 possible
// all undesired lanes will be disabled through the 2nd pass
active = true; active = true;
} else if (TurnType.isLeftTurn(turn) && rs.roadsOnLeft == 0) { } else if (turn == TurnType.C) {
active = true; active = true;
} }
if (active) { if (active) {
@ -1266,7 +1268,7 @@ public class RouteResultPreparation {
return lanes; return lanes;
} }
private int inferTurnFromLanes(int[] oLanes) { private int inferSlightTurnFromLanes(int[] oLanes, RoadSplitStructure rs) {
TIntHashSet possibleTurns = new TIntHashSet(); TIntHashSet possibleTurns = new TIntHashSet();
for (int i = 0; i < oLanes.length; i++) { for (int i = 0; i < oLanes.length; i++) {
if ((oLanes[i] & 1) == 0) { if ((oLanes[i] & 1) == 0) {
@ -1310,10 +1312,40 @@ public class RouteResultPreparation {
} }
} }
} }
// remove all non-slight turns
if(possibleTurns.size() > 1) {
TIntIterator it = possibleTurns.iterator();
while(it.hasNext()) {
int nxt = it.next();
if(!TurnType.isSlightTurn(nxt)) {
it.remove();
}
}
}
int infer = 0;
if (possibleTurns.size() == 1) {
infer = possibleTurns.iterator().next();
} else if (possibleTurns.size() > 1) {
if (rs.keepLeft && rs.keepRight && possibleTurns.contains(TurnType.C)) {
infer = TurnType.C;
} else if (rs.keepLeft || rs.keepRight) {
TIntIterator it = possibleTurns.iterator();
infer = it.next();
while(it.hasNext()) {
int next = it.next();
int orderInfer = TurnType.orderFromLeftToRight(infer);
int orderNext = TurnType.orderFromLeftToRight(next) ;
if(rs.keepLeft && orderNext < orderInfer) {
infer = next;
} else if(rs.keepRight && orderNext > orderInfer) {
infer = next;
}
}
}
}
// Checking to see that there is only one unique turn // Checking to see that there is only one unique turn
if (possibleTurns.size() == 1) { if (infer != 0) {
int infer = possibleTurns.iterator().next();
for(int i = 0; i < oLanes.length; i++) { for(int i = 0; i < oLanes.length; i++) {
if(TurnType.getSecondaryTurn(oLanes[i]) == infer) { if(TurnType.getSecondaryTurn(oLanes[i]) == infer) {
int pt = TurnType.getPrimaryTurn(oLanes[i]); int pt = TurnType.getPrimaryTurn(oLanes[i]);
@ -1324,10 +1356,8 @@ public class RouteResultPreparation {
} }
} }
return infer;
} }
return infer;
return 0;
} }
private boolean isMotorway(RouteSegmentResult s){ private boolean isMotorway(RouteSegmentResult s){

View file

@ -334,6 +334,34 @@ public class TurnType {
set.add(pt); set.add(pt);
} }
} }
public static int orderFromLeftToRight(int type) {
switch(type) {
case TU:
return -5;
case TSHL:
return -4;
case TL:
return -3;
case TSLL:
return -2;
case KL:
return -1;
case TRU:
return 5;
case TSHR:
return 4;
case TR:
return 3;
case TSLR:
return 2;
case KR:
return 1;
default:
return 0;
}
}
} }

View file

@ -508,7 +508,7 @@
"longitude": 35.54365276535992 "longitude": 35.54365276535992
}, },
"expectedResults": { "expectedResults": {
"118669516": "+TSLL, С" "118669516": "TSLL:+TSLL,С"
} }
}, },
{ {
@ -522,7 +522,7 @@
"longitude": 35.53820788105969 "longitude": 35.53820788105969
}, },
"expectedResults": { "expectedResults": {
"118669511": "+TSLR, С" "118669511": "TSLR:+TSLR,С"
} }
} }