change output rules

This commit is contained in:
afischerdev 2023-02-26 13:02:39 +01:00
parent 7edc35009f
commit 7434c12b31
3 changed files with 254 additions and 38 deletions

View file

@ -21,9 +21,13 @@ import java.io.InputStreamReader;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import btools.mapaccess.MatchedWaypoint;
import btools.mapaccess.OsmPos;
@ -45,6 +49,9 @@ public final class OsmTrack {
public boolean showspeed;
public boolean showSpeedProfile;
public boolean showTime;
public Map<String, String> params;
public List<OsmNodeNamed> pois = new ArrayList<OsmNodeNamed>();
@ -414,12 +421,14 @@ public final class OsmTrack {
int turnInstructionMode = voiceHints != null ? voiceHints.turnInstructionMode : 0;
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
for (int i = messageList.size() - 1; i >= 0; i--) {
String message = messageList.get(i);
if (i < messageList.size() - 1)
message = "(alt-index " + i + ": " + message + " )";
if (message != null)
sb.append("<!-- ").append(message).append(" -->\n");
if (turnInstructionMode != 9) {
for (int i = messageList.size() - 1; i >= 0; i--) {
String message = messageList.get(i);
if (i < messageList.size() - 1)
message = "(alt-index " + i + ": " + message + " )";
if (message != null)
sb.append("<!-- ").append(message).append(" -->\n");
}
}
if (turnInstructionMode == 4) // comment style
@ -436,8 +445,10 @@ public final class OsmTrack {
sb.append("<gpx \n");
sb.append(" xmlns=\"http://www.topografix.com/GPX/1/1\" \n");
sb.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n");
if (turnInstructionMode == 2) // locus style
{
if (turnInstructionMode == 9) { // BRouter style
sb.append(" xmlns:brouter=\"Not yet documented\" \n");
}
if (turnInstructionMode == 7) { // old locus style
sb.append(" xmlns:locus=\"http://www.locusmap.eu\" \n");
}
sb.append(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" \n");
@ -447,32 +458,61 @@ public final class OsmTrack {
} else {
sb.append(" creator=\"BRouter-" + version + "\" version=\"1.1\">\n");
}
if (turnInstructionMode == 3) // osmand style
if (turnInstructionMode == 9) {
sb.append(" <metadata>\n");
sb.append(" <name>").append(name).append("</name>\n");
sb.append(" <extensions>\n");
sb.append(" <brouter:info>").append(messageList.get(0)).append("</brouter:info>\n");
if (params != null && params.size() > 0) {
sb.append(" <brouter:params><![CDATA[");
int i = 0;
for (Map.Entry<String, String> e : params.entrySet()) {
if (i++ != 0) sb.append("&");
sb.append(e.getKey()).append("=").append(e.getValue());
}
sb.append("]]></brouter:params>\n");
}
sb.append(" </extensions>\n");
sb.append(" </metadata>\n");
}
if (turnInstructionMode == 3 || turnInstructionMode == 8) // osmand style, cruiser
{
float lastRteTime = 0;
sb.append(" <rte>\n");
sb.append(" <rtept lat=\"").append(formatILat(nodes.get(0).getILat())).append("\" lon=\"")
.append(formatILon(nodes.get(0).getILon())).append("\">\n")
.append(" <desc>start</desc>\n <extensions>\n");
float rteTime = getVoiceHintTime(0);
if (rteTime != lastRteTime) // add timing only if available
StringBuffer first = new StringBuffer();
// define start point
{
double t = rteTime - lastRteTime;
sb.append(" <time>").append("" + (int) (t + 0.5)).append("</time>\n");
lastRteTime = rteTime;
first.append(" <rtept lat=\"").append(formatILat(nodes.get(0).getILat())).append("\" lon=\"")
.append(formatILon(nodes.get(0).getILon())).append("\">\n")
.append(" <desc>start</desc>\n <extensions>\n");
if (rteTime != lastRteTime) // add timing only if available
{
double t = rteTime - lastRteTime;
first.append(" <time>").append("" + (int) (t + 0.5)).append("</time>\n");
lastRteTime = rteTime;
}
first.append(" <offset>0</offset>\n </extensions>\n </rtept>\n");
}
if (turnInstructionMode == 8) {
if (matchedWaypoints.get(0).direct && voiceHints.list.get(0).indexInTrack == 0) {
// has a voice hint do nothing, voice hint will do
} else {
sb.append(first.toString());
}
} else {
sb.append(first.toString());
}
sb.append(" <offset>0</offset>\n </extensions>\n </rtept>\n");
for (int i = 0; i < voiceHints.list.size(); i++) {
VoiceHint hint = voiceHints.list.get(i);
sb.append(" <rtept lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
.append(formatILon(hint.ilon)).append("\">\n")
.append(" <desc>").append(hint.getMessageString()).append("</desc>\n <extensions>\n");
.append(" <desc>")
.append(turnInstructionMode == 3 ? hint.getMessageString() : hint.getCruiserMessageString())
.append("</desc>\n <extensions>\n");
rteTime = getVoiceHintTime(i + 1);
@ -482,7 +522,9 @@ public final class OsmTrack {
sb.append(" <time>").append("" + (int) (t + 0.5)).append("</time>\n");
lastRteTime = rteTime;
}
sb.append(" <turn>").append(hint.getCommandString()).append("</turn>\n <turn-angle>").append("" + (int) hint.angle)
sb.append(" <turn>")
.append(turnInstructionMode == 3 ? hint.getCommandString() : hint.getCruiserCommandString())
.append("</turn>\n <turn-angle>").append("" + (int) hint.angle)
.append("</turn-angle>\n <offset>").append("" + hint.indexInTrack).append("</offset>\n </extensions>\n </rtept>\n");
}
sb.append(" <rtept lat=\"").append(formatILat(nodes.get(nodes.size() - 1).getILat())).append("\" lon=\"")
@ -494,7 +536,7 @@ public final class OsmTrack {
sb.append("</rte>\n");
}
if (turnInstructionMode == 2) // locus style
if (turnInstructionMode == 7) // old locus style
{
float lastRteTime = getVoiceHintTime(0);
@ -537,12 +579,12 @@ public final class OsmTrack {
.append(formatILon(hint.ilon)).append("\">")
.append(hint.selev == Short.MIN_VALUE ? "" : "<ele>" + (hint.selev / 4.) + "</ele>")
.append("<extensions>\n" +
"<om:oruxmapsextensions xmlns:om=\"http://www.oruxmaps.com/oruxmapsextensions/1/0\">\n" +
"<om:ext type=\"ICON\" subtype=\"0\">").append("" + hint.getOruxAction())
" <om:oruxmapsextensions xmlns:om=\"http://www.oruxmaps.com/oruxmapsextensions/1/0\">\n" +
" <om:ext type=\"ICON\" subtype=\"0\">").append("" + hint.getOruxAction())
.append("</om:ext>\n" +
"</om:oruxmapsextensions>\n" +
"</extensions>\n" +
"</wpt>");
" </om:oruxmapsextensions>\n" +
" </extensions>\n" +
" </wpt>\n");
}
}
@ -571,13 +613,14 @@ public final class OsmTrack {
}
}
sb.append(" <trk>\n");
sb.append(" <name>").append(name).append("</name>\n");
if (turnInstructionMode == 1) // trkpt/sym style
{
if (turnInstructionMode == 9) { // brouter style
sb.append(" <src>").append(name).append("</src>\n");
sb.append(" <type>").append(voiceHints.getTransportMode()).append("</type>\n");
} else {
sb.append(" <name>").append(name).append("</name>\n");
}
if (turnInstructionMode == 2) {
if (turnInstructionMode == 7) {
sb.append(" <extensions>\n");
sb.append(" <locus:rteComputeType>").append("" + voiceHints.getLocusRouteType()).append("</locus:rteComputeType>\n");
sb.append(" <locus:rteSimpleRoundabouts>1</locus:rteSimpleRoundabouts>\n");
@ -585,20 +628,168 @@ public final class OsmTrack {
}
sb.append(" <trkseg>\n");
String lastway = "";
boolean bNextDirect = false;
OsmPathElement nn = null;
String aSpeed;
for (int idx = 0; idx < nodes.size(); idx++) {
OsmPathElement n = nodes.get(idx);
String sele = n.getSElev() == Short.MIN_VALUE ? "" : "<ele>" + n.getElev() + "</ele>";
if (turnInstructionMode == 1) // trkpt/sym style
VoiceHint hint = getVoiceHint(idx);
MatchedWaypoint mwpt = getMatchedWaypoint(idx);
if (showTime) {
sele += "<time>" + getFormattedTime3(n.getTime()) + "</time>";
}
boolean bNeedHeader = false;
if (turnInstructionMode == 9 || turnInstructionMode == 2) // trkpt/sym style // locus style new
{
for (VoiceHint hint : voiceHints.list) {
if (hint.indexInTrack == idx) {
sele += "<sym>" + hint.getCommandString() + "</sym>";
if (hint != null) {
if (turnInstructionMode == 9) {
if (mwpt != null && !mwpt.name.startsWith("via")) {
sele += "<name>" + mwpt.name + "</name>";
}
sele += "<desc>" + hint.getMessageString() + "</desc>";
sele += "<sym>" + hint.getCommandString(hint.cmd) + "</sym>";
sele += "<extensions>";
if (showspeed) {
double speed = 0;
if (nn != null) {
int dist = n.calcDistance(nn);
float dt = n.getTime() - nn.getTime();
if (dt != 0.f) {
speed = ((3.6f * dist) / dt + 0.5);
}
}
sele += "<brouter:speed>" + (((int) (speed * 10)) / 10.f) + "</brouter:speed>";
}
sele += "<brouter:voicehint>" + hint.getCommandString() + ";" + (int) (hint.distanceToNext) + "," + hint.formatGeometry() + "</brouter:voicehint>";
if (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway)) {
sele += "<brouter:way>" + n.message.wayKeyValues + "</brouter:way>";
lastway = n.message.wayKeyValues;
}
if (n.message != null && n.message.nodeKeyValues != null) {
sele += "<brouter:node>" + n.message.nodeKeyValues + "</brouter:node>";
}
sele += "</extensions>";
} else if (turnInstructionMode == 2) {
sele += "<sym>" + hint.getLocusSymbolString() + "</sym>";
}
}
if (idx == 0) {
if (turnInstructionMode == 2) {
int pos = sele.indexOf("<sym");
if (pos != -1) {
sele = sele.substring(0, pos);
}
if (mwpt != null && !mwpt.name.startsWith("from"))
sele += "<name>" + mwpt.name + "</name>";
if (mwpt != null && mwpt.direct) {
bNextDirect = true;
}
sele += "<sym>pass_place</sym>";
sele += "<type>Via</type>";
} else {
if (mwpt != null && mwpt.direct) {
sele += "<desc>beeline</desc>";
} else {
sele += "<desc>start</desc>";
}
sele += "<type>Via</type>";
}
} else if (idx == nodes.size() - 1) {
if (turnInstructionMode == 2) {
int pos = sele.indexOf("<sym");
if (pos != -1) {
sele = sele.substring(0, pos);
}
if (mwpt != null && mwpt.name != null && !mwpt.name.startsWith("to"))
sele += "<name>" + mwpt.name + "</name>";
if (bNextDirect) {
sele += "<src>beeline</src>";
}
sele += "<sym>pass_place</sym>";
sele += "<type>Via</type>";
} else {
sele += "<desc>end</desc>";
sele += "<type>Via</type>";
}
} else if (turnInstructionMode == 2) {
if (mwpt != null) {
if (sele.contains("sym") &&
!sele.contains("name") &&
!mwpt.name.startsWith("via")) {
int pos = sele.indexOf("<sym");
if (pos != -1)
sele = sele.substring(0, pos) + "<name>" + mwpt.name + "</name>" + sele.substring(pos) + "<type>Via</type>";
} else if (sele.contains("sym") && mwpt.name.startsWith("via")) {
sele += "<type>Via</type>";
} else if (mwpt.direct && bNextDirect) {
sele += "<src>beeline</src><sym>pass_place</sym><type>Shaping</type>";
bNextDirect = true;
} else if (mwpt.direct) {
sele += "<sym>pass_place</sym><type>Shaping</type>";
bNextDirect = true;
} else if (mwpt.name.startsWith("via")) {
if (bNextDirect) {
sele += "<src>beeline</src><sym>pass_place</sym><type>Shaping</type>";
} else {
sele += "<sym>pass_place</sym><type>Shaping</type>";
}
bNextDirect = false;
} else {
sele += "<name>" + mwpt.name + "</name>";
sele += "<sym>pass_place</sym><type>Via</type>";
}
}
} else if (turnInstructionMode == 9) {
if (mwpt != null && hint == null) {
if (mwpt.direct) {
// bNextDirect = true;
sele += "<desc>beeline</desc>";
} else {
sele += "<desc>" + mwpt.name + "</desc>";
}
sele += "<type>Via</type>";
bNextDirect = false;
}
}
if (turnInstructionMode == 9 && hint == null) {
bNeedHeader = (showspeed || (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway))) ||
(n.message != null && n.message.nodeKeyValues != null);
if (bNeedHeader) {
sele += "<extensions>";
if (showspeed) {
double speed = 0;
if (nn != null) {
int dist = n.calcDistance(nn);
float dt = n.getTime() - nn.getTime();
if (dt != 0.f) {
speed = ((3.6f * dist) / dt + 0.5);
}
}
sele += "<brouter:speed>" + (((int) (speed * 10)) / 10.f) + "</brouter:speed>";
}
if (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway)) {
sele += "<brouter:way>" + n.message.wayKeyValues + "</brouter:way>";
lastway = n.message.wayKeyValues;
}
if (n.message != null && n.message.nodeKeyValues != null) {
sele += "<brouter:node>" + n.message.nodeKeyValues + "</brouter:node>";
}
sele += "</extensions>";
}
}
}
sb.append(" <trkpt lon=\"").append(formatILon(n.getILon())).append("\" lat=\"")
.append(formatILat(n.getILat())).append("\">").append(sele).append("</trkpt>\n");
nn = n;
}
sb.append(" </trkseg>\n");
@ -921,6 +1112,18 @@ public final class OsmTrack {
return time;
}
SimpleDateFormat TIMESTAMP_FORMAT;
public String getFormattedTime3(float time) {
if (TIMESTAMP_FORMAT == null) {
TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
TIMESTAMP_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
}
// yyyy-mm-ddThh:mm:ss.SSSZ
Date d = new Date((long) (time * 1000f));
return TIMESTAMP_FORMAT.format(d);
}
public String getFormattedEnergy() {
return format1(energy / 3600000.) + "kwh";
}
@ -1060,6 +1263,14 @@ public final class OsmTrack {
input.indexInTrack = --nodeNr;
input.goodWay = node.message;
input.oldWay = node.origin.message == null ? node.message : node.origin.message;
if (rc.turnInstructionMode == 8) {
MatchedWaypoint mwpt = getMatchedWaypoint(nodeNr);
if (mwpt != null && mwpt.direct) {
input.cmd = VoiceHint.BL;
input.angle = (float) node.message.turnangle;
input.distanceToNext = node.calcDistance(node.origin);
}
}
OsmPathElementHolder detours = detourMap.get(node.origin.getIdFromPos());
if (nodeNr >= 0 && detours != null) {
OsmPathElementHolder h = detours;
@ -1081,8 +1292,8 @@ public final class OsmTrack {
List<VoiceHint> results = vproc.process(inputs);
double minDistance = getMinDistance();
List < VoiceHint > resultsLast = vproc.postProcess(results, rc.turnInstructionCatchingRange, minDistance);
for (VoiceHint hint: resultsLast) {
List<VoiceHint> resultsLast = vproc.postProcess(results, rc.turnInstructionCatchingRange, minDistance);
for (VoiceHint hint : resultsLast) {
voiceHints.list.add(hint);
}

View file

@ -171,6 +171,7 @@ public final class RoutingContext {
showspeed = 0.f != expctxGlobal.getVariableValue("showspeed", 0.f);
showSpeedProfile = 0.f != expctxGlobal.getVariableValue("showSpeedProfile", 0.f);
inverseRouting = 0.f != expctxGlobal.getVariableValue("inverseRouting", 0.f);
showTime = 0.f != expctxGlobal.getVariableValue("showtime", 0.f);
int tiMode = (int) expctxGlobal.getVariableValue("turnInstructionMode", 0.f);
if (tiMode != 1) // automatic selection from coordinate source
@ -233,6 +234,7 @@ public final class RoutingContext {
public boolean showspeed;
public boolean showSpeedProfile;
public boolean inverseRouting;
public boolean showTime;
public OsmPrePath firstPrePath;

View file

@ -511,6 +511,9 @@ public class RoutingEngine extends Thread {
totaltrack.processVoiceHints(routingContext);
totaltrack.prepareSpeedProfile(routingContext);
totaltrack.showTime = routingContext.showTime;
totaltrack.params = routingContext.keyValues;
if (routingContext.poipoints != null)
totaltrack.pois = routingContext.poipoints;
totaltrack.matchedWaypoints = matchedWaypoints;