Reimplement turn:lanes merge

This commit is contained in:
Victor Shcherb 2015-01-13 10:25:56 +01:00
parent 27e1015386
commit 80bbf423ca
2 changed files with 123 additions and 65 deletions

View file

@ -44,6 +44,8 @@ public class RouteResultPreparation {
calculateTimeSpeed(ctx, result); calculateTimeSpeed(ctx, result);
addTurnInfo(ctx.leftSideNavigation, result); addTurnInfo(ctx.leftSideNavigation, result);
determineTurnsToMerge(ctx.leftSideNavigation, result);
addTurnInfoDescriptions(result);
return result; return result;
} }
@ -331,8 +333,6 @@ public class RouteResultPreparation {
private void addTurnInfo(boolean leftside, List<RouteSegmentResult> result) { private void addTurnInfo(boolean leftside, List<RouteSegmentResult> result) {
int prevSegment = -1;
float dist = 0;
int next = 1; int next = 1;
for (int i = 0; i <= result.size(); i = next) { for (int i = 0; i <= result.size(); i = next) {
TurnType t = null; TurnType t = null;
@ -341,47 +341,31 @@ public class RouteResultPreparation {
t = getTurnInfo(result, i, leftside); t = getTurnInfo(result, i, leftside);
// justify turn // justify turn
if(t != null && i < result.size() - 1) { if(t != null && i < result.size() - 1) {
boolean tl = TurnType.TL == t.getValue(); TurnType jt = justifyUTurn(leftside, result, i, t);
boolean tr = TurnType.TR == t.getValue(); if(jt != null) {
if(tl || tr) { t = jt;
TurnType tnext = getTurnInfo(result, i + 1, leftside); next = i + 2;
if (tnext != null && result.get(i).getDistance() < 35) { //
boolean ut = true;
if (i > 0) {
double uTurn = MapUtils.degreesDiff(result.get(i - 1).getBearingEnd(), result
.get(i + 1).getBearingBegin());
if (Math.abs(uTurn) < 120) {
ut = false;
}
}
String highway = result.get(i).getObject().getHighway();
if(highway == null || highway.endsWith("track") || highway.endsWith("services") || highway.endsWith("service")
|| highway.endsWith("path")) {
ut = false;
}
if (ut) {
if (tl && TurnType.TL == tnext.getValue()) {
next = i + 2;
t = TurnType.valueOf(TurnType.TU, false);
} else if (tr && TurnType.TR == tnext.getValue()) {
next = i + 2;
t = TurnType.valueOf(TurnType.TU, true);
}
}
}
} }
} }
result.get(i).setTurnType(t); result.get(i).setTurnType(t);
} }
if (t != null || i == result.size()) { }
}
protected void addTurnInfoDescriptions(List<RouteSegmentResult> result) {
int prevSegment = -1;
float dist = 0;
for (int i = 0; i <= result.size(); i++) {
if (i == result.size() || result.get(i).getTurnType() != null) {
if (prevSegment >= 0) { if (prevSegment >= 0) {
String turn = result.get(prevSegment).getTurnType().toString(); String turn = result.get(prevSegment).getTurnType().toString();
if (result.get(prevSegment).getTurnType().getLanes() != null) { if (result.get(prevSegment).getTurnType().getLanes() != null) {
turn += Arrays.toString(result.get(prevSegment).getTurnType().getLanes()); turn += Arrays.toString(result.get(prevSegment).getTurnType().getLanes());
} }
result.get(prevSegment).setDescription(turn + MessageFormat.format(" and go {0,number,#.##} meters", dist)); result.get(prevSegment).setDescription(
if(result.get(prevSegment).getTurnType().isSkipToSpeak()) { turn + MessageFormat.format(" and go {0,number,#.##} meters", dist));
result.get(prevSegment).setDescription("-*"+result.get(prevSegment).getDescription()); if (result.get(prevSegment).getTurnType().isSkipToSpeak()) {
result.get(prevSegment).setDescription("-*" + result.get(prevSegment).getDescription());
} }
} }
prevSegment = i; prevSegment = i;
@ -391,8 +375,37 @@ public class RouteResultPreparation {
dist += result.get(i).getDistance(); dist += result.get(i).getDistance();
} }
} }
}
determineTurnsToMerge(leftside, result); protected TurnType justifyUTurn(boolean leftside, List<RouteSegmentResult> result, int i, TurnType t) {
boolean tl = TurnType.TL == t.getValue();
boolean tr = TurnType.TR == t.getValue();
if(tl || tr) {
TurnType tnext = getTurnInfo(result, i + 1, leftside);
if (tnext != null && result.get(i).getDistance() < 35) { //
boolean ut = true;
if (i > 0) {
double uTurn = MapUtils.degreesDiff(result.get(i - 1).getBearingEnd(), result
.get(i + 1).getBearingBegin());
if (Math.abs(uTurn) < 120) {
ut = false;
}
}
String highway = result.get(i).getObject().getHighway();
if(highway == null || highway.endsWith("track") || highway.endsWith("services") || highway.endsWith("service")
|| highway.endsWith("path")) {
ut = false;
}
if (ut) {
if (tl && TurnType.TL == tnext.getValue()) {
return TurnType.valueOf(TurnType.TU, false);
} else if (tr && TurnType.TR == tnext.getValue()) {
return TurnType.valueOf(TurnType.TU, true);
}
}
}
}
return null;
} }
private void determineTurnsToMerge(boolean leftside, List<RouteSegmentResult> result) { private void determineTurnsToMerge(boolean leftside, List<RouteSegmentResult> result) {
@ -421,8 +434,15 @@ public class RouteResultPreparation {
} }
// Only allow slight turns that are nearby to be merged. // Only allow slight turns that are nearby to be merged.
if (currentSegment.getDistance() < 60 && nextTurn.getLanes().length <= currentTurn.getLanes().length // [disabled cause it is valuable for two consequent sharp turns as well]
&& TurnType.isSlightTurn(currentTurn.getValue())) { // the distance could be longer on highways and shorter in city
String hw = currentSegment.getObject().getHighway();
double mergeDistance = 200;
if(hw != null && (hw.startsWith("trunk") || hw.startsWith("motorway"))) {
mergeDistance = 400;
}
if (currentSegment.getDistance() < mergeDistance/*
&& TurnType.isSlightTurn(currentTurn.getValue())*/) {
mergeTurnLanes(leftside, currentSegment, nextSegment); mergeTurnLanes(leftside, currentSegment, nextSegment);
} }
} }
@ -435,36 +455,75 @@ public class RouteResultPreparation {
&& TurnType.getPrimaryTurn(nextTurn.getLanes()[0]) != 0; && TurnType.getPrimaryTurn(nextTurn.getLanes()[0]) != 0;
if (isUsingTurnLanes) { if (isUsingTurnLanes) {
int[] lanes = new int[currentTurn.getLanes().length]; int[] lanes = new int[currentTurn.getLanes().length];
// Unset the allowed lane bit int activeIndex = -1;
for (int i = 0; i < lanes.length; i++) { int activeLen = 0;
lanes[i] = currentTurn.getLanes()[i] & ~1; // define enabled lanes
} for(int i = 0; i < lanes.length; i++) {
int ln = currentTurn.getLanes()[i];
// Find the first lane that matches (based on the turn being taken), and how many lanes match lanes[i] = ln & ~1;
int matchingIndex = 0; if((ln & 1) > 0) {
int maxMatchedLanes = 0; if(activeIndex == -1) {
for (int i = 0; i < lanes.length; i++) { activeIndex = i;
int matchedLanes = 0; activeLen++;
for (int j = 0; j < nextTurn.getLanes().length - i; j++) {
if (TurnType.getPrimaryTurn(nextTurn.getLanes()[j])
== TurnType.getPrimaryTurn(currentTurn.getLanes()[i + j])) {
matchedLanes++;
} else { } else {
break; activeLen++;
} }
} }
if (matchedLanes > maxMatchedLanes) { }
matchingIndex = i; if(activeLen < 2) {
maxMatchedLanes = matchedLanes; return;
}
int targetActiveIndex = -1;
int targetActiveLen = 0;
int[] nextLanes = nextTurn.getLanes();
for(int i = 0; i < nextLanes.length; i++) {
int ln = nextLanes[i];
if((ln & 1) > 0) {
if(targetActiveIndex == -1) {
targetActiveIndex = i;
targetActiveLen++;
} else {
targetActiveLen++;
}
} }
} }
if (maxMatchedLanes <= 1) { if(targetActiveIndex == -1) {
return;
}
boolean changed = false;
// next turn is left
if(targetActiveIndex == 0) {
// let only the most left lanes be enabled
if(targetActiveLen <= activeLen) {
activeLen = targetActiveLen;
changed = true;
}
} else if(targetActiveIndex + targetActiveLen == nextLanes.length) {
// next turn is right
// let only the most right lanes be enabled
if(targetActiveLen <= activeLen) {
activeIndex += (activeLen - targetActiveLen);
changed = true;
}
} else {
// next turn is get through (take out the left and the right turn)
if(nextLanes.length >= activeLen) {
float ratio = (nextLanes.length / (float)activeLen);
activeLen = (int) Math.ceil(targetActiveLen * ratio);
activeIndex = (int) Math.floor(targetActiveIndex / ratio);
changed = true;
}
}
if(!changed) {
return; 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++) { // set the allowed lane bit
lanes[i] |= nextTurn.getLanes()[i - matchingIndex] & 1; for (int i = 0; i < lanes.length; i++) {
if(i >= activeIndex && i < activeIndex + activeLen) {
lanes[i] |= 1;
}
} }
currentTurn.setLanes(lanes); currentTurn.setLanes(lanes);
int turn = inferTurnFromLanes(lanes); int turn = inferTurnFromLanes(lanes);

View file

@ -45,7 +45,6 @@ import net.osmand.plus.R;
import net.osmand.plus.SQLiteTileSource; import net.osmand.plus.SQLiteTileSource;
import net.osmand.plus.SearchByNameFilter; import net.osmand.plus.SearchByNameFilter;
import net.osmand.plus.Version; import net.osmand.plus.Version;
import net.osmand.plus.download.BaseDownloadActivity;
import net.osmand.plus.render.MapRenderRepositories; import net.osmand.plus.render.MapRenderRepositories;
import net.osmand.plus.render.NativeOsmandLibrary; import net.osmand.plus.render.NativeOsmandLibrary;
import net.osmand.plus.resources.AsyncLoadingThread.MapLoadRequest; import net.osmand.plus.resources.AsyncLoadingThread.MapLoadRequest;