Merge pull request #742 from afischerdev/new-voicehints

New voicehints for motorway exit
This commit is contained in:
afischerdev 2024-12-14 10:25:31 +01:00 committed by GitHub
commit 625ff0c53f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 187 additions and 49 deletions

View File

@ -49,7 +49,7 @@ public class FormatGpx extends Formatter {
sb.append("<!-- cmd idx lon lat d2next geometry -->\n"); sb.append("<!-- cmd idx lon lat d2next geometry -->\n");
sb.append("<!-- $turn-instruction-start$\n"); sb.append("<!-- $turn-instruction-start$\n");
for (VoiceHint hint : t.voiceHints.list) { for (VoiceHint hint : t.voiceHints.list) {
sb.append(String.format(" $turn$%6s;%6d;%10s;%10s;%6d;%s$\n", hint.getCommandString(), hint.indexInTrack, sb.append(String.format(" $turn$%6s;%6d;%10s;%10s;%6d;%s$\n", hint.getCommandString(turnInstructionMode), hint.indexInTrack,
formatILon(hint.ilon), formatILat(hint.ilat), (int) (hint.distanceToNext), hint.formatGeometry())); formatILon(hint.ilon), formatILat(hint.ilat), (int) (hint.distanceToNext), hint.formatGeometry()));
} }
sb.append(" $turn-instruction-end$ -->\n"); sb.append(" $turn-instruction-end$ -->\n");
@ -121,7 +121,7 @@ public class FormatGpx extends Formatter {
sb.append(" <rtept lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"") sb.append(" <rtept lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
.append(formatILon(hint.ilon)).append("\">\n") .append(formatILon(hint.ilon)).append("\">\n")
.append(" <desc>") .append(" <desc>")
.append(turnInstructionMode == 3 ? hint.getMessageString() : hint.getCruiserMessageString()) .append(turnInstructionMode == 3 ? hint.getMessageString(turnInstructionMode) : hint.getCruiserMessageString())
.append("</desc>\n <extensions>\n"); .append("</desc>\n <extensions>\n");
rteTime = t.getVoiceHintTime(i + 1); rteTime = t.getVoiceHintTime(i + 1);
@ -132,7 +132,7 @@ public class FormatGpx extends Formatter {
lastRteTime = rteTime; lastRteTime = rteTime;
} }
sb.append(" <turn>") sb.append(" <turn>")
.append(turnInstructionMode == 3 ? hint.getCommandString() : hint.getCruiserCommandString()) .append(turnInstructionMode == 3 ? hint.getCommandString(turnInstructionMode) : hint.getCruiserCommandString())
.append("</turn>\n <turn-angle>").append("" + (int) hint.angle) .append("</turn>\n <turn-angle>").append("" + (int) hint.angle)
.append("</turn-angle>\n <offset>").append("" + hint.indexInTrack).append("</offset>\n </extensions>\n </rtept>\n"); .append("</turn-angle>\n <offset>").append("" + hint.indexInTrack).append("</offset>\n </extensions>\n </rtept>\n");
} }
@ -154,7 +154,7 @@ public class FormatGpx extends Formatter {
.append(formatILat(hint.ilat)).append("\">") .append(formatILat(hint.ilat)).append("\">")
.append(hint.selev == Short.MIN_VALUE ? "" : "<ele>" + (hint.selev / 4.) + "</ele>") .append(hint.selev == Short.MIN_VALUE ? "" : "<ele>" + (hint.selev / 4.) + "</ele>")
.append("<name>") .append("<name>")
.append(hint.getMessageString()) .append(hint.getMessageString(turnInstructionMode))
.append("</name>") .append("</name>")
.append("<extensions><locus:rteDistance>").append("" + hint.distanceToNext).append("</locus:rteDistance>"); .append("<extensions><locus:rteDistance>").append("" + hint.distanceToNext).append("</locus:rteDistance>");
float rteTime = t.getVoiceHintTime(i + 1); float rteTime = t.getVoiceHintTime(i + 1);
@ -173,9 +173,9 @@ public class FormatGpx extends Formatter {
for (VoiceHint hint : t.voiceHints.list) { for (VoiceHint hint : t.voiceHints.list) {
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"") sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
.append(formatILat(hint.ilat)).append("\">") .append(formatILat(hint.ilat)).append("\">")
.append("<name>").append(hint.getMessageString()).append("</name>") .append("<name>").append(hint.getMessageString(turnInstructionMode)).append("</name>")
.append("<sym>").append(hint.getSymbolString().toLowerCase()).append("</sym>") .append("<sym>").append(hint.getSymbolString(turnInstructionMode).toLowerCase()).append("</sym>")
.append("<type>").append(hint.getSymbolString()).append("</type>") .append("<type>").append(hint.getSymbolString(turnInstructionMode)).append("</type>")
.append("</wpt>\n"); .append("</wpt>\n");
} }
} }
@ -270,7 +270,7 @@ public class FormatGpx extends Formatter {
sele += "<name>" + mwpt.name + "</name>"; sele += "<name>" + mwpt.name + "</name>";
} }
sele += "<desc>" + hint.getCruiserMessageString() + "</desc>"; sele += "<desc>" + hint.getCruiserMessageString() + "</desc>";
sele += "<sym>" + hint.getCommandString(hint.cmd) + "</sym>"; sele += "<sym>" + hint.getCommandString(hint.cmd, turnInstructionMode) + "</sym>";
if (mwpt != null) { if (mwpt != null) {
sele += "<type>Via</type>"; sele += "<type>Via</type>";
} }
@ -287,7 +287,7 @@ public class FormatGpx extends Formatter {
sele += "<brouter:speed>" + (((int) (speed * 10)) / 10.f) + "</brouter:speed>"; sele += "<brouter:speed>" + (((int) (speed * 10)) / 10.f) + "</brouter:speed>";
} }
sele += "<brouter:voicehint>" + hint.getCommandString() + ";" + (int) (hint.distanceToNext) + "," + hint.formatGeometry() + "</brouter:voicehint>"; sele += "<brouter:voicehint>" + hint.getCommandString(turnInstructionMode) + ";" + (int) (hint.distanceToNext) + "," + hint.formatGeometry() + "</brouter:voicehint>";
if (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway)) { if (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway)) {
sele += "<brouter:way>" + n.message.wayKeyValues + "</brouter:way>"; sele += "<brouter:way>" + n.message.wayKeyValues + "</brouter:way>";
lastway = n.message.wayKeyValues; lastway = n.message.wayKeyValues;

View File

@ -41,13 +41,13 @@ public class FormatJson extends Formatter {
for (VoiceHint hint : t.voiceHints.list) { for (VoiceHint hint : t.voiceHints.list) {
sb.append(" ["); sb.append(" [");
sb.append(hint.indexInTrack); sb.append(hint.indexInTrack);
sb.append(',').append(hint.getJsonCommandIndex()); sb.append(',').append(hint.getJsonCommandIndex(turnInstructionMode));
sb.append(',').append(hint.getExitNumber()); sb.append(',').append(hint.getExitNumber());
sb.append(',').append(hint.distanceToNext); sb.append(',').append(hint.distanceToNext);
sb.append(',').append((int) hint.angle); sb.append(',').append((int) hint.angle);
// not always include geometry because longer and only needed for comment style // not always include geometry because longer and only needed for comment style
if (turnInstructionMode == 4) { // comment style if (turnInstructionMode == 4 || turnInstructionMode == 9) { // comment style
sb.append(",\"").append(hint.formatGeometry()).append("\""); sb.append(",\"").append(hint.formatGeometry()).append("\"");
} }
@ -122,7 +122,7 @@ public class FormatJson extends Formatter {
.append(sele).append("],\n"); .append(sele).append("],\n");
nn = n; nn = n;
} }
if (t.nodes != null && !t.nodes.isEmpty()) sb.deleteCharAt(sb.lastIndexOf(",")); sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(" ]\n"); sb.append(" ]\n");
sb.append(" }\n"); sb.append(" }\n");

View File

@ -469,6 +469,17 @@ public final class OsmTrack {
List<VoiceHint> inputs = new ArrayList<>(); List<VoiceHint> inputs = new ArrayList<>();
while (node != null) { while (node != null) {
if (node.origin != null) { if (node.origin != null) {
if (nodeNr == nodes.size() - 1) {
VoiceHint input = new VoiceHint();
inputs.add(0, input);
input.ilat = node.getILat();
input.ilon = node.getILon();
input.selev = node.getSElev();
input.goodWay = node.message;
input.oldWay = node.message;
input.indexInTrack = nodes.size() - 1;
input.cmd = VoiceHint.END;
}
VoiceHint input = new VoiceHint(); VoiceHint input = new VoiceHint();
inputs.add(input); inputs.add(input);
input.ilat = node.origin.getILat(); input.ilat = node.origin.getILat();

View File

@ -36,12 +36,14 @@ public class RoutingEngine extends Thread {
private boolean finished = false; private boolean finished = false;
protected List<OsmNodeNamed> waypoints = null; protected List<OsmNodeNamed> waypoints = null;
List<OsmNodeNamed> extraWaypoints = null;
protected List<MatchedWaypoint> matchedWaypoints; protected List<MatchedWaypoint> matchedWaypoints;
private int linksProcessed = 0; private int linksProcessed = 0;
private int nodeLimit; // used for target island search private int nodeLimit; // used for target island search
private int MAXNODES_ISLAND_CHECK = 500; private int MAXNODES_ISLAND_CHECK = 500;
private OsmNodePairSet islandNodePairs = new OsmNodePairSet(MAXNODES_ISLAND_CHECK); private OsmNodePairSet islandNodePairs = new OsmNodePairSet(MAXNODES_ISLAND_CHECK);
private boolean useNodePoints = false; // use the start/end nodes instead of crosspoint
private int engineMode = 0; private int engineMode = 0;
@ -548,6 +550,20 @@ public class RoutingEngine extends Thread {
try { try {
return tryFindTrack(refTracks, lastTracks); return tryFindTrack(refTracks, lastTracks);
} catch (RoutingIslandException rie) { } catch (RoutingIslandException rie) {
if (routingContext.useDynamicDistance) {
useNodePoints = true;
boolean useNodeOne = true;
if (extraWaypoints != null) useNodeOne = false;
extraWaypoints = new ArrayList<>();
for (MatchedWaypoint mwp : matchedWaypoints) {
if (mwp.name.contains("_add")) {
OsmNodeNamed wp = new OsmNodeNamed(useNodeOne ? mwp.node1 : mwp.node1);
wp.name = mwp.name;
wp.direct = mwp.direct;
extraWaypoints.add(wp);
}
}
}
islandNodePairs.freezeTempPairs(); islandNodePairs.freezeTempPairs();
nodesCache.clean(true); nodesCache.clean(true);
matchedWaypoints = null; matchedWaypoints = null;
@ -560,6 +576,26 @@ public class RoutingEngine extends Thread {
int nUnmatched = waypoints.size(); int nUnmatched = waypoints.size();
boolean hasDirectRouting = false; boolean hasDirectRouting = false;
if (useNodePoints && extraWaypoints != null) {
// add extra waypoints from the last broken round
for (OsmNodeNamed wp : extraWaypoints) {
if (wp.direct) hasDirectRouting = true;
if (wp.name.startsWith("from")) {
waypoints.add(1, wp);
waypoints.get(0).direct = true;
nUnmatched++;
} else {
waypoints.add(waypoints.size()-1, wp);
waypoints.get(waypoints.size()-2).direct = true;
nUnmatched++;
}
}
}
if (lastTracks.length < waypoints.size()-1) {
refTracks = new OsmTrack[waypoints.size()-1]; // used ways for alternatives
lastTracks = new OsmTrack[waypoints.size()-1];
hasDirectRouting = true;
}
for (OsmNodeNamed wp : waypoints) { for (OsmNodeNamed wp : waypoints) {
if (hasInfo()) logInfo("wp=" + wp + (wp.direct ? " direct" : "")); if (hasInfo()) logInfo("wp=" + wp + (wp.direct ? " direct" : ""));
if (wp.direct) hasDirectRouting = true; if (wp.direct) hasDirectRouting = true;
@ -592,8 +628,8 @@ public class RoutingEngine extends Thread {
int startSize = matchedWaypoints.size(); int startSize = matchedWaypoints.size();
matchWaypointsToNodes(matchedWaypoints); matchWaypointsToNodes(matchedWaypoints);
if (startSize < matchedWaypoints.size()) { if (startSize < matchedWaypoints.size()) {
refTracks = new OsmTrack[matchedWaypoints.size()]; // used ways for alternatives refTracks = new OsmTrack[matchedWaypoints.size()-1]; // used ways for alternatives
lastTracks = new OsmTrack[matchedWaypoints.size()]; lastTracks = new OsmTrack[matchedWaypoints.size()-1];
hasDirectRouting = true; hasDirectRouting = true;
} }
@ -624,9 +660,9 @@ public class RoutingEngine extends Thread {
matchedWaypoints.add(nearbyTrack.endPoint); matchedWaypoints.add(nearbyTrack.endPoint);
} }
} else { } else {
if (lastTracks.length < matchedWaypoints.size()) { if (lastTracks.length < matchedWaypoints.size()-1) {
refTracks = new OsmTrack[matchedWaypoints.size()]; // used ways for alternatives refTracks = new OsmTrack[matchedWaypoints.size()-1]; // used ways for alternatives
lastTracks = new OsmTrack[matchedWaypoints.size()]; lastTracks = new OsmTrack[matchedWaypoints.size()-1];
hasDirectRouting = true; hasDirectRouting = true;
} }
} }

View File

@ -26,6 +26,10 @@ public class VoiceHint {
static final int RNLB = 14; // Roundabout left static final int RNLB = 14; // Roundabout left
static final int TU = 15; // 180 degree u-turn static final int TU = 15; // 180 degree u-turn
static final int BL = 16; // Beeline routing static final int BL = 16; // Beeline routing
static final int EL = 17; // exit left
static final int ER = 18; // exit right
static final int END = 100; // end point
int ilon; int ilon;
int ilat; int ilat;
@ -65,7 +69,7 @@ public class VoiceHint {
badWays.add(badWay); badWays.add(badWay);
} }
public int getJsonCommandIndex() { public int getJsonCommandIndex(int timode) {
switch (cmd) { switch (cmd) {
case TLU: case TLU:
return 10; return 10;
@ -97,6 +101,10 @@ public class VoiceHint {
return 14; return 14;
case BL: case BL:
return 16; return 16;
case EL:
return timode == 2 || timode == 9 ? 17 : 8;
case ER:
return timode == 2 || timode == 9 ? 18 : 9;
case OFFR: case OFFR:
return 12; return 12;
default: default:
@ -111,7 +119,7 @@ public class VoiceHint {
/* /*
* used by comment style, osmand style * used by comment style, osmand style
*/ */
public String getCommandString() { public String getCommandString(int timode) {
switch (cmd) { switch (cmd) {
case TLU: case TLU:
return "TU"; // should be changed to TLU when osmand uses new voice hint constants return "TU"; // should be changed to TLU when osmand uses new voice hint constants
@ -143,8 +151,14 @@ public class VoiceHint {
return "RNLB" + (-roundaboutExit); return "RNLB" + (-roundaboutExit);
case BL: case BL:
return "BL"; return "BL";
case EL:
return timode == 2 || timode == 9 ? "EL" : "KL";
case ER:
return timode == 2 || timode == 9 ? "ER" : "KR";
case OFFR: case OFFR:
return "OFFR"; return "OFFR";
case END:
return "END";
default: default:
throw new IllegalArgumentException("unknown command: " + cmd); throw new IllegalArgumentException("unknown command: " + cmd);
} }
@ -153,7 +167,7 @@ public class VoiceHint {
/* /*
* used by trkpt/sym style * used by trkpt/sym style
*/ */
public String getCommandString(int c) { public String getCommandString(int c, int timode) {
switch (c) { switch (c) {
case TLU: case TLU:
return "TLU"; return "TLU";
@ -185,6 +199,10 @@ public class VoiceHint {
return "RNLB" + (-roundaboutExit); return "RNLB" + (-roundaboutExit);
case BL: case BL:
return "BL"; return "BL";
case EL:
return timode == 2 || timode == 9 ? "EL" : "KL";
case ER:
return timode == 2 || timode == 9 ? "ER" : "KR";
case OFFR: case OFFR:
return "OFFR"; return "OFFR";
default: default:
@ -195,7 +213,7 @@ public class VoiceHint {
/* /*
* used by gpsies style * used by gpsies style
*/ */
public String getSymbolString() { public String getSymbolString(int timode) {
switch (cmd) { switch (cmd) {
case TLU: case TLU:
return "TU"; return "TU";
@ -227,6 +245,10 @@ public class VoiceHint {
return "RNLB" + (-roundaboutExit); return "RNLB" + (-roundaboutExit);
case BL: case BL:
return "BL"; return "BL";
case EL:
return timode == 2 || timode == 9 ? "EL" : "KL";
case ER:
return timode == 2 || timode == 9 ? "ER" : "KR";
case OFFR: case OFFR:
return "OFFR"; return "OFFR";
default: default:
@ -269,6 +291,10 @@ public class VoiceHint {
return "roundabout_e" + (-roundaboutExit); return "roundabout_e" + (-roundaboutExit);
case BL: case BL:
return "beeline"; return "beeline";
case EL:
return "exit_left";
case ER:
return "exit_right";
default: default:
throw new IllegalArgumentException("unknown command: " + cmd); throw new IllegalArgumentException("unknown command: " + cmd);
} }
@ -277,7 +303,7 @@ public class VoiceHint {
/* /*
* used by osmand style * used by osmand style
*/ */
public String getMessageString() { public String getMessageString(int timode) {
switch (cmd) { switch (cmd) {
case TLU: case TLU:
return "u-turn"; // should be changed to u-turn-left when osmand uses new voice hint constants return "u-turn"; // should be changed to u-turn-left when osmand uses new voice hint constants
@ -307,6 +333,10 @@ public class VoiceHint {
return "Take exit " + roundaboutExit; return "Take exit " + roundaboutExit;
case RNLB: case RNLB:
return "Take exit " + (-roundaboutExit); return "Take exit " + (-roundaboutExit);
case EL:
return timode == 2 || timode == 9 ? "exit left" : "keep left";
case ER:
return timode == 2 || timode == 9 ? "exit right" : "keep right";
default: default:
throw new IllegalArgumentException("unknown command: " + cmd); throw new IllegalArgumentException("unknown command: " + cmd);
} }
@ -345,6 +375,10 @@ public class VoiceHint {
return 26 + roundaboutExit; return 26 + roundaboutExit;
case RNLB: case RNLB:
return 26 - roundaboutExit; return 26 - roundaboutExit;
case EL:
return 9;
case ER:
return 10;
default: default:
throw new IllegalArgumentException("unknown command: " + cmd); throw new IllegalArgumentException("unknown command: " + cmd);
} }
@ -383,6 +417,10 @@ public class VoiceHint {
return 1008 + roundaboutExit; return 1008 + roundaboutExit;
case RNLB: case RNLB:
return 1008 + roundaboutExit; return 1008 + roundaboutExit;
case EL:
return 1015;
case ER:
return 1014;
default: default:
throw new IllegalArgumentException("unknown command: " + cmd); throw new IllegalArgumentException("unknown command: " + cmd);
} }
@ -423,6 +461,10 @@ public class VoiceHint {
return "RNLB" + (-roundaboutExit); return "RNLB" + (-roundaboutExit);
case BL: case BL:
return "BL"; return "BL";
case EL:
return "EL";
case ER:
return "ER";
case OFFR: case OFFR:
return "OFFR"; return "OFFR";
default: default:
@ -465,6 +507,10 @@ public class VoiceHint {
return "take exit " + (-roundaboutExit); return "take exit " + (-roundaboutExit);
case BL: case BL:
return "beeline"; return "beeline";
case EL:
return "exit left";
case ER:
return "exit right";
case OFFR: case OFFR:
return "offroad"; return "offroad";
default: default:

View File

@ -29,7 +29,7 @@ public final class VoiceHintProcessor {
float angle = 0.f; float angle = 0.f;
while (offset >= 0 && distance < range) { while (offset >= 0 && distance < range) {
VoiceHint input = inputs.get(offset--); VoiceHint input = inputs.get(offset--);
if (input.turnAngleConsumed) { if (input.turnAngleConsumed || input.cmd == VoiceHint.BL || input.cmd == VoiceHint.END) {
break; break;
} }
angle += input.goodWay.turnangle; angle += input.goodWay.turnangle;
@ -72,8 +72,10 @@ public final class VoiceHintProcessor {
results.add(input); results.add(input);
continue; continue;
} }
float turnAngle = input.goodWay.turnangle; float turnAngle = input.goodWay.turnangle;
distance += input.goodWay.linkdist; if (hintIdx != 0) distance += input.goodWay.linkdist;
// System.out.println("range " + distance);
int currentPrio = input.goodWay.getPrio(); int currentPrio = input.goodWay.getPrio();
int oldPrio = input.oldWay.getPrio(); int oldPrio = input.oldWay.getPrio();
int minPrio = Math.min(oldPrio, currentPrio); int minPrio = Math.min(oldPrio, currentPrio);
@ -119,7 +121,7 @@ public final class VoiceHintProcessor {
float tmpangle = 0; float tmpangle = 0;
VoiceHint tmpRndAbt = new VoiceHint(); VoiceHint tmpRndAbt = new VoiceHint();
tmpRndAbt.badWays = new ArrayList<>(); tmpRndAbt.badWays = new ArrayList<>();
for (int i = hintIdx-1; i > roundaboudStartIdx; i--) { for (int i = hintIdx - 1; i > roundaboudStartIdx; i--) {
VoiceHint vh = inputs.get(i); VoiceHint vh = inputs.get(i);
tmpangle += inputs.get(i).goodWay.turnangle; tmpangle += inputs.get(i).goodWay.turnangle;
if (vh.badWays != null) { if (vh.badWays != null) {
@ -172,12 +174,14 @@ public final class VoiceHintProcessor {
} }
if (badWay.isBadOneway()) { if (badWay.isBadOneway()) {
if (minAbsAngeRaw == 180f) minAbsAngeRaw = turnAngle; // disable hasSomethingMoreStraight if (minAbsAngeRaw == 180f)
minAbsAngeRaw = turnAngle; // disable hasSomethingMoreStraight
continue; // ignore wrong oneways continue; // ignore wrong oneways
} }
if (Math.abs(badTurn) - Math.abs(turnAngle) > 80.f) { if (Math.abs(badTurn) - Math.abs(turnAngle) > 80.f) {
if (minAbsAngeRaw == 180f) minAbsAngeRaw = turnAngle; // disable hasSomethingMoreStraight if (minAbsAngeRaw == 180f)
minAbsAngeRaw = turnAngle; // disable hasSomethingMoreStraight
continue; // ways from the back should not trigger a slight turn continue; // ways from the back should not trigger a slight turn
} }
@ -251,6 +255,10 @@ public final class VoiceHintProcessor {
if (hint.cmd == 0) { if (hint.cmd == 0) {
hint.calcCommand(); hint.calcCommand();
} }
if (hint.cmd == VoiceHint.END) {
results2.add(hint);
continue;
}
if (!(hint.needsRealTurn && (hint.cmd == VoiceHint.C || hint.cmd == VoiceHint.BL))) { if (!(hint.needsRealTurn && (hint.cmd == VoiceHint.C || hint.cmd == VoiceHint.BL))) {
double dist = hint.distanceToNext; double dist = hint.distanceToNext;
// sum up other hints within the catching range (e.g. 40m) // sum up other hints within the catching range (e.g. 40m)
@ -300,10 +308,12 @@ public final class VoiceHintProcessor {
} }
if (nextInput == null) { if (nextInput == null) {
if ((input.cmd == VoiceHint.C || if (input.cmd == VoiceHint.END) {
input.cmd == VoiceHint.KR || continue;
input.cmd == VoiceHint.KL) } else if ((input.cmd == VoiceHint.C ||
&& !input.goodWay.isLinktType()) { input.cmd == VoiceHint.KR ||
input.cmd == VoiceHint.KL)
&& !input.goodWay.isLinktType()) {
if (input.goodWay.getPrio() < input.maxBadPrio && (inputLastSaved != null && inputLastSaved.distanceToNext > catchingRange)) { if (input.goodWay.getPrio() < input.maxBadPrio && (inputLastSaved != null && inputLastSaved.distanceToNext > catchingRange)) {
results.add(input); results.add(input);
} else { } else {
@ -318,14 +328,14 @@ public final class VoiceHintProcessor {
} else { } else {
if ((inputLastSaved != null && inputLastSaved.distanceToNext > catchingRange) || input.distanceToNext > catchingRange) { if ((inputLastSaved != null && inputLastSaved.distanceToNext > catchingRange) || input.distanceToNext > catchingRange) {
if ((input.cmd == VoiceHint.C || if ((input.cmd == VoiceHint.C ||
input.cmd == VoiceHint.KR || input.cmd == VoiceHint.KR ||
input.cmd == VoiceHint.KL) input.cmd == VoiceHint.KL)
&& !input.goodWay.isLinktType()) { && !input.goodWay.isLinktType()) {
if (((Math.abs(input.lowerBadWayAngle) < 35.f || if (((Math.abs(input.lowerBadWayAngle) < 35.f ||
input.higherBadWayAngle < 35.f) input.higherBadWayAngle < 35.f)
|| input.goodWay.getPrio() < input.maxBadPrio) || input.goodWay.getPrio() < input.maxBadPrio)
&& (inputLastSaved != null && inputLastSaved.distanceToNext > minRange) && (inputLastSaved != null && inputLastSaved.distanceToNext > minRange)
&& (input.distanceToNext > minRange)) { && (input.distanceToNext > minRange)) {
// add only on prio // add only on prio
results.add(input); results.add(input);
inputLastSaved = input; inputLastSaved = input;
@ -334,14 +344,25 @@ public final class VoiceHintProcessor {
inputLastSaved.distanceToNext += input.distanceToNext; inputLastSaved.distanceToNext += input.distanceToNext;
} }
} }
} else if ((input.goodWay.getPrio() == 29 && input.maxBadPrio == 30) &&
checkForNextNoneMotorway(inputs, hintIdx, 3)
) {
// leave motorway
if (input.cmd == VoiceHint.KR || input.cmd == VoiceHint.TSLR) {
input.cmd = VoiceHint.ER;
} else if (input.cmd == VoiceHint.KL || input.cmd == VoiceHint.TSLL) {
input.cmd = VoiceHint.EL;
}
results.add(input);
inputLastSaved = input;
} else { } else {
// add all others // add all others
// ignore motorway / primary continue // ignore motorway / primary continue
if (((input.goodWay.getPrio() != 28) && if (((input.goodWay.getPrio() != 28) &&
(input.goodWay.getPrio() != 30) && (input.goodWay.getPrio() != 30) &&
(input.goodWay.getPrio() != 26)) (input.goodWay.getPrio() != 26))
|| input.isRoundabout() || input.isRoundabout()
|| Math.abs(input.angle) > 21.f) { || Math.abs(input.angle) > 21.f) {
results.add(input); results.add(input);
inputLastSaved = input; inputLastSaved = input;
} else { } else {
@ -360,20 +381,20 @@ public final class VoiceHintProcessor {
angles += nextInput.angle; angles += nextInput.angle;
if ((input.cmd == VoiceHint.C || if ((input.cmd == VoiceHint.C ||
input.cmd == VoiceHint.KR || input.cmd == VoiceHint.KR ||
input.cmd == VoiceHint.KL) input.cmd == VoiceHint.KL)
&& !input.goodWay.isLinktType()) { && !input.goodWay.isLinktType()) {
if (input.goodWay.getPrio() < input.maxBadPrio) { if (input.goodWay.getPrio() < input.maxBadPrio) {
if (inputLastSaved != null && inputLastSaved.cmd != VoiceHint.C if (inputLastSaved != null && inputLastSaved.cmd != VoiceHint.C
&& (inputLastSaved != null && inputLastSaved.distanceToNext > minRange) && (inputLastSaved != null && inputLastSaved.distanceToNext > minRange)
&& transportMode != VoiceHintList.TRANS_MODE_CAR) { && transportMode != VoiceHintList.TRANS_MODE_CAR) {
// add when straight and not linktype // add when straight and not linktype
// and last vh not straight // and last vh not straight
save = true; save = true;
// remove when next straight and not linktype // remove when next straight and not linktype
if (nextInput != null && if (nextInput != null &&
nextInput.cmd == VoiceHint.C && nextInput.cmd == VoiceHint.C &&
!nextInput.goodWay.isLinktType()) { !nextInput.goodWay.isLinktType()) {
input.distanceToNext += nextInput.distanceToNext; input.distanceToNext += nextInput.distanceToNext;
hintIdx++; hintIdx++;
} }
@ -384,6 +405,14 @@ public final class VoiceHintProcessor {
inputLastSaved.distanceToNext += input.distanceToNext; inputLastSaved.distanceToNext += input.distanceToNext;
} }
} }
} else if ((input.goodWay.getPrio() == 29 && input.maxBadPrio == 30)) {
// leave motorway
if (input.cmd == VoiceHint.KR || input.cmd == VoiceHint.TSLR) {
input.cmd = VoiceHint.ER;
} else if (input.cmd == VoiceHint.KL || input.cmd == VoiceHint.TSLL) {
input.cmd = VoiceHint.EL;
}
save = true;
} else if (VoiceHint.is180DegAngle(input.angle)) { } else if (VoiceHint.is180DegAngle(input.angle)) {
// add u-turn, 180 degree // add u-turn, 180 degree
save = true; save = true;
@ -425,9 +454,22 @@ public final class VoiceHintProcessor {
} }
inputLast = input; inputLast = input;
} }
if (results.size() > 0) {
// don't use END tag
if (results.get(results.size()-1).cmd == VoiceHint.END) results.remove(results.size()-1);
}
return results; return results;
} }
boolean checkForNextNoneMotorway(List<VoiceHint> inputs, int offset, int testsize) {
for (int i = 1; i < testsize + 1 && offset + i < inputs.size(); i++) {
int prio = inputs.get(offset + i).goodWay.getPrio();
if (prio < 29) return true;
if (prio == 30) return false;
}
return false;
}
} }

View File

@ -25,6 +25,7 @@ And there are other rules
* merge two hints when near to each other - e.g. left, left to u-turn left * merge two hints when near to each other - e.g. left, left to u-turn left
* marker when highway exit and continue nearly same direction * marker when highway exit and continue nearly same direction
* beeline goes direct from via to via point * beeline goes direct from via to via point
* junction on motorway via motorway_link and next way less then motorway_link is a motorway exit
There are some variables in the profiles that affect on the voice hint generation: There are some variables in the profiles that affect on the voice hint generation:
* considerTurnRestrictions - * considerTurnRestrictions -
@ -51,4 +52,6 @@ Voice hint variables
| RNDB | roundabout | | RNDB | roundabout |
| RNLB | roundabout left | | RNLB | roundabout left |
| BL | beeline routing | | BL | beeline routing |
| EL | exit left |
| ER | exit right |