Merge pull request #952 from saiarcot895/merge-turn-lanes
Implement merging nearby turns together.
This commit is contained in:
commit
a2c041274b
2 changed files with 117 additions and 5 deletions
|
@ -42,7 +42,7 @@ public class RouteResultPreparation {
|
|||
splitRoadsAndAttachRoadSegments(ctx, result);
|
||||
// calculate time
|
||||
calculateTimeSpeed(ctx, result);
|
||||
|
||||
|
||||
addTurnInfo(ctx.leftSideNavigation, result);
|
||||
return result;
|
||||
}
|
||||
|
@ -391,6 +391,90 @@ public class RouteResultPreparation {
|
|||
dist += result.get(i).getDistance();
|
||||
}
|
||||
}
|
||||
|
||||
determineTurnsToMerge(leftside, result);
|
||||
}
|
||||
|
||||
private void determineTurnsToMerge(boolean leftside, List<RouteSegmentResult> result) {
|
||||
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 (nextSegment == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TurnType currentTurn = currentSegment.getTurnType();
|
||||
TurnType nextTurn = nextSegment.getTurnType();
|
||||
|
||||
if (currentTurn == null || currentTurn.getLanes() == null || nextTurn == null || nextTurn.getLanes() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only allow slight turns that are nearby to be merged.
|
||||
if (currentSegment.getDistance() < 60 && nextTurn.getLanes().length <= currentTurn.getLanes().length
|
||||
&& TurnType.isSlightTurn(currentTurn.getValue())) {
|
||||
mergeTurnLanes(leftside, currentSegment, nextSegment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeTurnLanes(boolean leftSide, RouteSegmentResult currentSegment, RouteSegmentResult nextSegment) {
|
||||
TurnType currentTurn = currentSegment.getTurnType();
|
||||
TurnType nextTurn = nextSegment.getTurnType();
|
||||
boolean isUsingTurnLanes = TurnType.getPrimaryTurn(currentTurn.getLanes()[0]) != 0
|
||||
&& TurnType.getPrimaryTurn(nextTurn.getLanes()[0]) != 0;
|
||||
if (isUsingTurnLanes) {
|
||||
int[] lanes = new int[currentTurn.getLanes().length];
|
||||
// Unset the allowed lane bit
|
||||
for (int i = 0; i < lanes.length; i++) {
|
||||
lanes[i] = currentTurn.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 < nextTurn.getLanes().length - i; j++) {
|
||||
if (TurnType.getPrimaryTurn(nextTurn.getLanes()[j])
|
||||
== TurnType.getPrimaryTurn(currentTurn.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 < nextTurn.getLanes().length; i++) {
|
||||
lanes[i] |= nextTurn.getLanes()[i - matchingIndex] & 1;
|
||||
}
|
||||
currentTurn.setLanes(lanes);
|
||||
int turn = inferTurnFromLanes(lanes);
|
||||
if (turn != 0 && turn != currentTurn.getValue()) {
|
||||
TurnType newTurnType = TurnType.valueOf(turn, leftSide);
|
||||
newTurnType.setLanes(lanes);
|
||||
newTurnType.setSkipToSpeak(currentTurn.isSkipToSpeak());
|
||||
currentSegment.setTurnType(newTurnType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final int MAX_SPEAK_PRIORITY = 5;
|
||||
|
@ -563,6 +647,7 @@ public class RouteResultPreparation {
|
|||
int right = 0;
|
||||
boolean speak = false;
|
||||
int speakPriority = Math.max(highwaySpeakPriority(prevSegm.getObject().getHighway()), highwaySpeakPriority(currentSegm.getObject().getHighway()));
|
||||
boolean otherRoutesExist = false;
|
||||
if (attachedRoutes != null) {
|
||||
for (RouteSegmentResult attached : attachedRoutes) {
|
||||
double ex = MapUtils.degreesDiff(attached.getBearingBegin(), currentSegm.getBearingBegin());
|
||||
|
@ -577,6 +662,9 @@ public class RouteResultPreparation {
|
|||
kr = true;
|
||||
left += countLanesMinOne(attached);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -603,13 +691,33 @@ public class RouteResultPreparation {
|
|||
|
||||
double devation = Math.abs(MapUtils.degreesDiff(prevSegm.getBearingEnd(), currentSegm.getBearingBegin()));
|
||||
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.setSkipToSpeak(!speak);
|
||||
}
|
||||
if (kr) {
|
||||
} else if (kr) {
|
||||
t = TurnType.valueOf(makeSlightTurn ? TurnType.TSLR : TurnType.KR, leftSide);
|
||||
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 = countLanesMinOne(prevSegm);
|
||||
|
||||
t.setLanes(attachTurnLanesData(prevSegm, new int[prevLanes]));
|
||||
|
||||
// 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) {
|
||||
int[] calcLanes = attachTurnLanesData(prevSegm, lanes);
|
||||
|
|
|
@ -253,4 +253,8 @@ public class TurnType {
|
|||
public static boolean isRightTurn(int type) {
|
||||
return type == TR || type == TSHR || type == TSLR;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSlightTurn(int type) {
|
||||
return type == TSLL || type == TSLR || type == C || type == KL || type == KR;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue