From 4112681f006c40cc9a5d16eed4c76b760fd0e9c6 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Thu, 11 Aug 2016 23:35:04 +0200 Subject: [PATCH] Fix turn lanes #2935 --- .../osmand/router/RouteResultPreparation.java | 66 ++++++++++++++----- .../src/net/osmand/router/TurnType.java | 28 ++++++++ .../test/resources/test_turn_lanes.json | 4 +- 3 files changed, 78 insertions(+), 20 deletions(-) diff --git a/OsmAnd-java/src/net/osmand/router/RouteResultPreparation.java b/OsmAnd-java/src/net/osmand/router/RouteResultPreparation.java index 4055ccc8bb..c8f5aaf0bf 100644 --- a/OsmAnd-java/src/net/osmand/router/RouteResultPreparation.java +++ b/OsmAnd-java/src/net/osmand/router/RouteResultPreparation.java @@ -1,5 +1,6 @@ package net.osmand.router; +import gnu.trove.iterator.TIntIterator; import gnu.trove.list.array.TIntArrayList; import gnu.trove.set.hash.TIntHashSet; @@ -947,28 +948,29 @@ public class RouteResultPreparation { rawLanes[k] |= 1; } } - int tp = inferTurnFromLanes(rawLanes); + int tp = inferSlightTurnFromLanes(rawLanes, rs); if (tp != t.getValue() && tp != 0) { t = TurnType.valueOf(tp, leftSide); } } else { + boolean possiblyLeftTurn = rs.roadsOnLeft == 0; + boolean possiblyRightTurn = rs.roadsOnRight == 0; for (int k = 0; k < rawLanes.length; k++) { int turn = TurnType.getPrimaryTurn(rawLanes[k]); int sturn = TurnType.getSecondaryTurn(rawLanes[k]); boolean active = false; - if (turn == TurnType.C) { - if ((TurnType.isRightTurn(sturn) && rs.roadsOnRight == 0) - || (TurnType.isLeftTurn(sturn) && rs.roadsOnLeft == 0)) { - TurnType.setPrimaryTurn(rawLanes, k, sturn); - TurnType.setSecondaryTurn(rawLanes, k, turn); - } + // some turns go through many segments (to turn right or left) + // 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 + if((TurnType.isRightTurn(sturn) && possiblyRightTurn) || + (TurnType.isLeftTurn(sturn) && possiblyLeftTurn)) { + TurnType.setPrimaryTurn(rawLanes, k, sturn); + TurnType.setSecondaryTurn(rawLanes, k, turn); active = true; - } else if (TurnType.isRightTurn(turn) && rs.roadsOnRight == 0) { - // some turns go through many segments (to turn right or left) - // 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 + } else if((TurnType.isRightTurn(turn) && possiblyRightTurn) || + (TurnType.isLeftTurn(turn) && possiblyLeftTurn)) { active = true; - } else if (TurnType.isLeftTurn(turn) && rs.roadsOnLeft == 0) { + } else if (turn == TurnType.C) { active = true; } if (active) { @@ -1266,7 +1268,7 @@ public class RouteResultPreparation { return lanes; } - private int inferTurnFromLanes(int[] oLanes) { + private int inferSlightTurnFromLanes(int[] oLanes, RoadSplitStructure rs) { TIntHashSet possibleTurns = new TIntHashSet(); for (int i = 0; i < oLanes.length; i++) { 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 - if (possibleTurns.size() == 1) { - int infer = possibleTurns.iterator().next(); + if (infer != 0) { for(int i = 0; i < oLanes.length; i++) { if(TurnType.getSecondaryTurn(oLanes[i]) == infer) { int pt = TurnType.getPrimaryTurn(oLanes[i]); @@ -1324,10 +1356,8 @@ public class RouteResultPreparation { } } - return infer; } - - return 0; + return infer; } private boolean isMotorway(RouteSegmentResult s){ diff --git a/OsmAnd-java/src/net/osmand/router/TurnType.java b/OsmAnd-java/src/net/osmand/router/TurnType.java index 4cad6226a2..fb11977270 100644 --- a/OsmAnd-java/src/net/osmand/router/TurnType.java +++ b/OsmAnd-java/src/net/osmand/router/TurnType.java @@ -334,6 +334,34 @@ public class TurnType { 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; + } + } } diff --git a/OsmAnd-java/test/resources/test_turn_lanes.json b/OsmAnd-java/test/resources/test_turn_lanes.json index 88fc44f14f..51ee5f82c0 100644 --- a/OsmAnd-java/test/resources/test_turn_lanes.json +++ b/OsmAnd-java/test/resources/test_turn_lanes.json @@ -508,7 +508,7 @@ "longitude": 35.54365276535992 }, "expectedResults": { - "118669516": "+TSLL, С" + "118669516": "TSLL:+TSLL,С" } }, { @@ -522,7 +522,7 @@ "longitude": 35.53820788105969 }, "expectedResults": { - "118669511": "+TSLR, С" + "118669511": "TSLR:+TSLR,С" } }