Implement merging nearby turns together.
When there are multiple turns near each other (< 60m), set the lanes that are allowed on earlier turns such that staying on that lane will carry you through the other turns. For a standard left/right turn at a traffic light at two one-way roads (dual carriageway), this means that the left and right turns are correctly highlighted.
This commit is contained in:
parent
97f26503bb
commit
e1b7f13b5c
1 changed files with 105 additions and 4 deletions
|
@ -389,6 +389,76 @@ public class RouteResultPreparation {
|
||||||
dist += result.get(i).getDistance();
|
dist += result.get(i).getDistance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = result.size() - 2; i >= 0; i--) {
|
||||||
|
RouteSegmentResult currentSegment = result.get(i);
|
||||||
|
RouteSegmentResult nextSegment = null;
|
||||||
|
|
||||||
|
// We need to get the next segment that has a turn and lanes attached.
|
||||||
|
for (int j = i + 1; j < result.size(); j++) {
|
||||||
|
RouteSegmentResult possibleSegment = result.get(j);
|
||||||
|
if (possibleSegment.getTurnType() != null && possibleSegment.getTurnType().getLanes() != null) {
|
||||||
|
nextSegment = possibleSegment;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentSegment.getTurnType() == null || currentSegment.getTurnType().getLanes() == null
|
||||||
|
|| nextSegment == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only allow slight turns that are nearby to be merged.
|
||||||
|
if (currentSegment.getDistance() < 60 && nextSegment.getTurnType().getLanes().length <= currentSegment.getTurnType().getLanes().length
|
||||||
|
&& (currentSegment.getTurnType().getValue() == TurnType.C
|
||||||
|
|| currentSegment.getTurnType().getValue() == TurnType.TSLL
|
||||||
|
|| currentSegment.getTurnType().getValue() == TurnType.TSLR
|
||||||
|
|| currentSegment.getTurnType().getValue() == TurnType.KL
|
||||||
|
|| currentSegment.getTurnType().getValue() == TurnType.KR)) {
|
||||||
|
mergeTurnLanes(leftside, currentSegment, nextSegment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mergeTurnLanes(boolean leftSide, RouteSegmentResult currentSegment, RouteSegmentResult nextSegment) {
|
||||||
|
boolean isUsingTurnLanes = TurnType.getPrimaryTurn(currentSegment.getTurnType().getLanes()[0]) != 0
|
||||||
|
&& TurnType.getPrimaryTurn(nextSegment.getTurnType().getLanes()[0]) != 0;
|
||||||
|
if (isUsingTurnLanes) {
|
||||||
|
int[] lanes = new int[currentSegment.getTurnType().getLanes().length];
|
||||||
|
// Unset the allowed lane bit
|
||||||
|
for (int i = 0; i < lanes.length; i++) {
|
||||||
|
lanes[i] = currentSegment.getTurnType().getLanes()[i] & ~1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the first lane that matches (based on the turn being taken), and how many lanes match
|
||||||
|
int matchingIndex = 0;
|
||||||
|
int maxMatchedLanes = 0;
|
||||||
|
for (int i = 0; i < lanes.length; i++) {
|
||||||
|
int matchedLanes = 0;
|
||||||
|
for (int j = 0; j < nextSegment.getTurnType().getLanes().length - i; j++) {
|
||||||
|
if (TurnType.getPrimaryTurn(nextSegment.getTurnType().getLanes()[j])
|
||||||
|
== TurnType.getPrimaryTurn(currentSegment.getTurnType().getLanes()[i + j])) {
|
||||||
|
matchedLanes++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matchedLanes > maxMatchedLanes) {
|
||||||
|
matchingIndex = i;
|
||||||
|
maxMatchedLanes = matchedLanes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxMatchedLanes <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the allowed bit from the next segment's lanes to the current segment's matching lanes
|
||||||
|
for (int i = matchingIndex; i - matchingIndex < nextSegment.getTurnType().getLanes().length; i++) {
|
||||||
|
lanes[i] |= nextSegment.getTurnType().getLanes()[i - matchingIndex] & 1;
|
||||||
|
}
|
||||||
|
currentSegment.getTurnType().setLanes(lanes);
|
||||||
|
currentSegment.setTurnType(inferTurnFromLanes(currentSegment.getTurnType(), leftSide));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int MAX_SPEAK_PRIORITY = 5;
|
private static final int MAX_SPEAK_PRIORITY = 5;
|
||||||
|
@ -566,6 +636,7 @@ public class RouteResultPreparation {
|
||||||
int right = 0;
|
int right = 0;
|
||||||
boolean speak = false;
|
boolean speak = false;
|
||||||
int speakPriority = Math.max(highwaySpeakPriority(prevSegm.getObject().getHighway()), highwaySpeakPriority(currentSegm.getObject().getHighway()));
|
int speakPriority = Math.max(highwaySpeakPriority(prevSegm.getObject().getHighway()), highwaySpeakPriority(currentSegm.getObject().getHighway()));
|
||||||
|
boolean otherRoutesExist = false;
|
||||||
if (attachedRoutes != null) {
|
if (attachedRoutes != null) {
|
||||||
for (RouteSegmentResult attached : attachedRoutes) {
|
for (RouteSegmentResult attached : attachedRoutes) {
|
||||||
double ex = MapUtils.degreesDiff(attached.getBearingBegin(), currentSegm.getBearingBegin());
|
double ex = MapUtils.degreesDiff(attached.getBearingBegin(), currentSegm.getBearingBegin());
|
||||||
|
@ -596,6 +667,9 @@ public class RouteResultPreparation {
|
||||||
left += lns;
|
left += lns;
|
||||||
}
|
}
|
||||||
speak = speak || rsSpeakPriority <= speakPriority;
|
speak = speak || rsSpeakPriority <= speakPriority;
|
||||||
|
} else if (mpi >= TURN_DEGREE_MIN) {
|
||||||
|
// Indicate that there are other turns at this intersection, and displaying the lanes may be helpful here.
|
||||||
|
otherRoutesExist = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -631,13 +705,40 @@ public class RouteResultPreparation {
|
||||||
|
|
||||||
double devation = Math.abs(MapUtils.degreesDiff(prevSegm.getBearingEnd(), currentSegm.getBearingBegin()));
|
double devation = Math.abs(MapUtils.degreesDiff(prevSegm.getBearingEnd(), currentSegm.getBearingBegin()));
|
||||||
boolean makeSlightTurn = devation > 5 && (!isMotorway(prevSegm) || !isMotorway(currentSegm));
|
boolean makeSlightTurn = devation > 5 && (!isMotorway(prevSegm) || !isMotorway(currentSegm));
|
||||||
if (kl) {
|
if (kl && kr) {
|
||||||
|
t = TurnType.valueOf(TurnType.C, leftSide);
|
||||||
|
t.setSkipToSpeak(!speak);
|
||||||
|
} else if (kl) {
|
||||||
t = TurnType.valueOf(makeSlightTurn ? TurnType.TSLL : TurnType.KL, leftSide);
|
t = TurnType.valueOf(makeSlightTurn ? TurnType.TSLL : TurnType.KL, leftSide);
|
||||||
t.setSkipToSpeak(!speak);
|
t.setSkipToSpeak(!speak);
|
||||||
}
|
} else if (kr) {
|
||||||
if (kr) {
|
|
||||||
t = TurnType.valueOf(makeSlightTurn ? TurnType.TSLR : TurnType.KR, leftSide);
|
t = TurnType.valueOf(makeSlightTurn ? TurnType.TSLR : TurnType.KR, leftSide);
|
||||||
t.setSkipToSpeak(!speak);
|
t.setSkipToSpeak(!speak);
|
||||||
|
} else if (otherRoutesExist && getTurnLanesString(prevSegm) != null) {
|
||||||
|
// Maybe going straight at a 90-degree intersection
|
||||||
|
t = TurnType.valueOf(TurnType.C, leftSide);
|
||||||
|
t.setSkipToSpeak(true);
|
||||||
|
|
||||||
|
// When going straight, the lanes have to be calculated from the previous segment, not the current/next segment.
|
||||||
|
int prevLanes = prevSegm.getObject().getLanes();
|
||||||
|
if (prevSegm.getObject().getOneway() == 0) {
|
||||||
|
prevLanes = countLanes(prevSegm, prevLanes);
|
||||||
|
}
|
||||||
|
if (prevLanes <= 0) {
|
||||||
|
prevLanes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.setLanes(new int[prevLanes]);
|
||||||
|
t = attachTurnLanesData(leftSide, prevSegm, t);
|
||||||
|
|
||||||
|
// Manually set the allowed lanes based on the turn type
|
||||||
|
for (int i = 0; i < t.getLanes().length; i++) {
|
||||||
|
if (TurnType.getPrimaryTurn(t.getLanes()[i]) == TurnType.C) {
|
||||||
|
t.getLanes()[i] |= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
if (t != null && lanes != null) {
|
if (t != null && lanes != null) {
|
||||||
t.setLanes(lanes);
|
t.setLanes(lanes);
|
||||||
|
|
Loading…
Reference in a new issue