Merge branch 'abrensch:master' into master

This commit is contained in:
Joachim Lengacher 2024-01-16 09:44:32 +01:00 committed by GitHub
commit 58dc4afa1e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 2337 additions and 1093 deletions

View file

@ -0,0 +1,43 @@
package btools.router;
import java.io.BufferedWriter;
import java.io.StringWriter;
public class FormatCsv extends Formatter {
public FormatCsv(RoutingContext rc) {
super(rc);
}
@Override
public String format(OsmTrack t) {
try {
StringWriter sw = new StringWriter();
BufferedWriter bw = new BufferedWriter(sw);
writeMessages(bw, t);
return sw.toString();
} catch (Exception ex) {
return "Error: " + ex.getMessage();
}
}
public void writeMessages(BufferedWriter bw, OsmTrack t) throws Exception {
dumpLine(bw, MESSAGES_HEADER);
for (String m : t.aggregateMessages()) {
dumpLine(bw, m);
}
if (bw != null)
bw.close();
}
private void dumpLine(BufferedWriter bw, String s) throws Exception {
if (bw == null) {
System.out.println(s);
} else {
bw.write(s);
bw.write("\n");
}
}
}

View file

@ -0,0 +1,532 @@
package btools.router;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.Map;
import btools.mapaccess.MatchedWaypoint;
import btools.util.StringUtils;
public class FormatGpx extends Formatter {
public FormatGpx(RoutingContext rc) {
super(rc);
}
@Override
public String format(OsmTrack t) {
try {
StringWriter sw = new StringWriter(8192);
BufferedWriter bw = new BufferedWriter(sw);
formatAsGpx(bw, t);
bw.close();
return sw.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String formatAsGpx(BufferedWriter sb, OsmTrack t) throws IOException {
int turnInstructionMode = t.voiceHints != null ? t.voiceHints.turnInstructionMode : 0;
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
if (turnInstructionMode != 9) {
for (int i = t.messageList.size() - 1; i >= 0; i--) {
String message = t.messageList.get(i);
if (i < t.messageList.size() - 1)
message = "(alt-index " + i + ": " + message + " )";
if (message != null)
sb.append("<!-- ").append(message).append(" -->\n");
}
}
if (turnInstructionMode == 4) { // comment style
sb.append("<!-- $transport-mode$").append(t.voiceHints.getTransportMode()).append("$ -->\n");
sb.append("<!-- cmd idx lon lat d2next geometry -->\n");
sb.append("<!-- $turn-instruction-start$\n");
for (VoiceHint hint : t.voiceHints.list) {
sb.append(String.format(" $turn$%6s;%6d;%10s;%10s;%6d;%s$\n", hint.getCommandString(), hint.indexInTrack,
formatILon(hint.ilon), formatILat(hint.ilat), (int) (hint.distanceToNext), hint.formatGeometry()));
}
sb.append(" $turn-instruction-end$ -->\n");
}
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 == 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");
if (turnInstructionMode == 3) {
sb.append(" creator=\"OsmAndRouter\" version=\"1.1\">\n");
} else {
sb.append(" creator=\"BRouter-" + t.version + "\" version=\"1.1\">\n");
}
if (turnInstructionMode == 9) {
sb.append(" <metadata>\n");
sb.append(" <name>").append(t.name).append("</name>\n");
sb.append(" <extensions>\n");
sb.append(" <brouter:info>").append(t.messageList.get(0)).append("</brouter:info>\n");
if (t.params != null && t.params.size() > 0) {
sb.append(" <brouter:params><![CDATA[");
int i = 0;
for (Map.Entry<String, String> e : t.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");
float rteTime = t.getVoiceHintTime(0);
StringBuffer first = new StringBuffer();
// define start point
{
first.append(" <rtept lat=\"").append(formatILat(t.nodes.get(0).getILat())).append("\" lon=\"")
.append(formatILon(t.nodes.get(0).getILon())).append("\">\n")
.append(" <desc>start</desc>\n <extensions>\n");
if (rteTime != lastRteTime) { // add timing only if available
double ti = rteTime - lastRteTime;
first.append(" <time>").append("" + (int) (ti + 0.5)).append("</time>\n");
lastRteTime = rteTime;
}
first.append(" <offset>0</offset>\n </extensions>\n </rtept>\n");
}
if (turnInstructionMode == 8) {
if (t.matchedWaypoints.get(0).direct && t.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());
}
for (int i = 0; i < t.voiceHints.list.size(); i++) {
VoiceHint hint = t.voiceHints.list.get(i);
sb.append(" <rtept lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
.append(formatILon(hint.ilon)).append("\">\n")
.append(" <desc>")
.append(turnInstructionMode == 3 ? hint.getMessageString() : hint.getCruiserMessageString())
.append("</desc>\n <extensions>\n");
rteTime = t.getVoiceHintTime(i + 1);
if (rteTime != lastRteTime) { // add timing only if available
double ti = rteTime - lastRteTime;
sb.append(" <time>").append("" + (int) (ti + 0.5)).append("</time>\n");
lastRteTime = rteTime;
}
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(t.nodes.get(t.nodes.size() - 1).getILat())).append("\" lon=\"")
.append(formatILon(t.nodes.get(t.nodes.size() - 1).getILon())).append("\">\n")
.append(" <desc>destination</desc>\n <extensions>\n");
sb.append(" <time>0</time>\n");
sb.append(" <offset>").append("" + (t.nodes.size() - 1)).append("</offset>\n </extensions>\n </rtept>\n");
sb.append("</rte>\n");
}
if (turnInstructionMode == 7) { // old locus style
float lastRteTime = t.getVoiceHintTime(0);
for (int i = 0; i < t.voiceHints.list.size(); i++) {
VoiceHint hint = t.voiceHints.list.get(i);
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
.append(formatILat(hint.ilat)).append("\">")
.append(hint.selev == Short.MIN_VALUE ? "" : "<ele>" + (hint.selev / 4.) + "</ele>")
.append("<name>").append(hint.getMessageString()).append("</name>")
.append("<extensions><locus:rteDistance>").append("" + hint.distanceToNext).append("</locus:rteDistance>");
float rteTime = t.getVoiceHintTime(i + 1);
if (rteTime != lastRteTime) { // add timing only if available
double ti = rteTime - lastRteTime;
double speed = hint.distanceToNext / ti;
sb.append("<locus:rteTime>").append("" + ti).append("</locus:rteTime>")
.append("<locus:rteSpeed>").append("" + speed).append("</locus:rteSpeed>");
lastRteTime = rteTime;
}
sb.append("<locus:rtePointAction>").append("" + hint.getLocusAction()).append("</locus:rtePointAction></extensions>")
.append("</wpt>\n");
}
}
if (turnInstructionMode == 5) { // gpsies style
for (VoiceHint hint : t.voiceHints.list) {
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
.append(formatILat(hint.ilat)).append("\">")
.append("<name>").append(hint.getMessageString()).append("</name>")
.append("<sym>").append(hint.getSymbolString().toLowerCase()).append("</sym>")
.append("<type>").append(hint.getSymbolString()).append("</type>")
.append("</wpt>\n");
}
}
if (turnInstructionMode == 6) { // orux style
for (VoiceHint hint : t.voiceHints.list) {
sb.append(" <wpt lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
.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())
.append("</om:ext>\n" +
" </om:oruxmapsextensions>\n" +
" </extensions>\n" +
" </wpt>\n");
}
}
for (int i = 0; i <= t.pois.size() - 1; i++) {
OsmNodeNamed poi = t.pois.get(i);
sb.append(" <wpt lon=\"").append(formatILon(poi.ilon)).append("\" lat=\"")
.append(formatILat(poi.ilat)).append("\">\n")
.append(" <name>").append(StringUtils.escapeXml10(poi.name)).append("</name>\n")
.append(" </wpt>\n");
}
if (t.exportWaypoints) {
for (int i = 0; i <= t.matchedWaypoints.size() - 1; i++) {
MatchedWaypoint wt = t.matchedWaypoints.get(i);
sb.append(" <wpt lon=\"").append(formatILon(wt.waypoint.ilon)).append("\" lat=\"")
.append(formatILat(wt.waypoint.ilat)).append("\">\n")
.append(" <name>").append(StringUtils.escapeXml10(wt.name)).append("</name>\n");
if (i == 0) {
sb.append(" <type>from</type>\n");
} else if (i == t.matchedWaypoints.size() - 1) {
sb.append(" <type>to</type>\n");
} else {
sb.append(" <type>via</type>\n");
}
sb.append(" </wpt>\n");
}
}
sb.append(" <trk>\n");
if (turnInstructionMode == 9
|| turnInstructionMode == 2
|| turnInstructionMode == 8
|| turnInstructionMode == 4) { // Locus, comment, cruise, brouter style
sb.append(" <src>").append(t.name).append("</src>\n");
sb.append(" <type>").append(t.voiceHints.getTransportMode()).append("</type>\n");
} else {
sb.append(" <name>").append(t.name).append("</name>\n");
}
if (turnInstructionMode == 7) {
sb.append(" <extensions>\n");
sb.append(" <locus:rteComputeType>").append("" + t.voiceHints.getLocusRouteType()).append("</locus:rteComputeType>\n");
sb.append(" <locus:rteSimpleRoundabouts>1</locus:rteSimpleRoundabouts>\n");
sb.append(" </extensions>\n");
}
// all points
sb.append(" <trkseg>\n");
String lastway = "";
boolean bNextDirect = false;
OsmPathElement nn = null;
String aSpeed;
for (int idx = 0; idx < t.nodes.size(); idx++) {
OsmPathElement n = t.nodes.get(idx);
String sele = n.getSElev() == Short.MIN_VALUE ? "" : "<ele>" + n.getElev() + "</ele>";
VoiceHint hint = t.getVoiceHint(idx);
MatchedWaypoint mwpt = t.getMatchedWaypoint(idx);
if (t.showTime) {
sele += "<time>" + getFormattedTime3(n.getTime()) + "</time>";
}
if (turnInstructionMode == 8) {
if (mwpt != null &&
!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
sele += "<name>" + mwpt.name + "</name>";
}
}
boolean bNeedHeader = false;
if (turnInstructionMode == 9) { // trkpt/sym style
if (hint != null) {
if (mwpt != null &&
!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
sele += "<name>" + mwpt.name + "</name>";
}
sele += "<desc>" + hint.getCruiserMessageString() + "</desc>";
sele += "<sym>" + hint.getCommandString(hint.cmd) + "</sym>";
if (mwpt != null) {
sele += "<type>Via</type>";
}
sele += "<extensions>";
if (t.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>";
}
if (idx == 0 && hint == null) {
if (mwpt != null && mwpt.direct) {
sele += "<desc>beeline</desc>";
} else {
sele += "<desc>start</desc>";
}
sele += "<type>Via</type>";
} else if (idx == t.nodes.size() - 1 && hint == null) {
sele += "<desc>end</desc>";
sele += "<type>Via</type>";
} else {
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 (hint == null) {
bNeedHeader = (t.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 (t.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>";
}
}
}
if (turnInstructionMode == 2) { // locus style new
if (hint != null) {
if (mwpt != null) {
if (!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
sele += "<name>" + mwpt.name + "</name>";
}
if (mwpt.direct && bNextDirect) {
sele += "<src>" + hint.getLocusSymbolString() + "</src><sym>pass_place</sym><type>Shaping</type>";
// bNextDirect = false;
} else if (mwpt.direct) {
if (idx == 0)
sele += "<sym>pass_place</sym><type>Via</type>";
else
sele += "<sym>pass_place</sym><type>Shaping</type>";
bNextDirect = true;
} else if (bNextDirect) {
sele += "<src>beeline</src><sym>" + hint.getLocusSymbolString() + "</sym><type>Shaping</type>";
bNextDirect = false;
} else {
sele += "<sym>" + hint.getLocusSymbolString() + "</sym><type>Via</type>";
}
} else {
sele += "<sym>" + hint.getLocusSymbolString() + "</sym>";
}
} else {
if (idx == 0 && hint == null) {
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 (idx == t.nodes.size() - 1 && hint == null) {
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 {
if (mwpt != null) {
if (!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
sele += "<name>" + mwpt.name + "</name>";
}
if (mwpt.direct && bNextDirect) {
sele += "<src>beeline</src><sym>pass_place</sym><type>Shaping</type>";
} else if (mwpt.direct) {
if (idx == 0)
sele += "<sym>pass_place</sym><type>Via</type>";
else
sele += "<sym>pass_place</sym><type>Shaping</type>";
bNextDirect = true;
} else if (bNextDirect) {
sele += "<src>beeline</src><sym>pass_place</sym><type>Shaping</type>";
bNextDirect = false;
} else if (mwpt.name.startsWith("via") ||
mwpt.name.startsWith("from") ||
mwpt.name.startsWith("to")) {
if (bNextDirect) {
sele += "<src>beeline</src><sym>pass_place</sym><type>Shaping</type>";
} else {
sele += "<sym>pass_place</sym><type>Via</type>";
}
bNextDirect = false;
} else {
sele += "<name>" + mwpt.name + "</name>";
sele += "<sym>pass_place</sym><type>Via</type>";
}
}
}
}
}
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");
sb.append(" </trk>\n");
sb.append("</gpx>\n");
return sb.toString();
}
public String formatAsWaypoint(OsmNodeNamed n) {
try {
StringWriter sw = new StringWriter(8192);
BufferedWriter bw = new BufferedWriter(sw);
formatGpxHeader(bw);
formatWaypointGpx(bw, n);
formatGpxFooter(bw);
bw.close();
sw.close();
return sw.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void formatGpxHeader(BufferedWriter sb) throws IOException {
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
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");
sb.append(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" \n");
sb.append(" creator=\"BRouter-" + OsmTrack.version + "\" version=\"1.1\">\n");
}
public void formatGpxFooter(BufferedWriter sb) throws IOException {
sb.append("</gpx>\n");
}
public void formatWaypointGpx(BufferedWriter sb, OsmNodeNamed n) throws IOException {
sb.append(" <wpt lon=\"").append(formatILon(n.ilon)).append("\" lat=\"")
.append(formatILat(n.ilat)).append("\">");
if (n.getSElev() != Short.MIN_VALUE) {
sb.append("<ele>").append("" + n.getElev()).append("</ele>");
}
if (n.name != null) {
sb.append("<name>").append(StringUtils.escapeXml10(n.name)).append("</name>");
}
if (n.nodeDescription != null && rc != null) {
sb.append("<desc>").append(rc.expctxWay.getKeyValueDescription(false, n.nodeDescription)).append("</desc>");
}
sb.append("</wpt>\n");
}
public static String getWaypoint(int ilon, int ilat, String name, String desc) {
return "<wpt lon=\"" + formatILon(ilon) + "\" lat=\"" + formatILat(ilat) + "\"><name>" + name + "</name>" + (desc != null ? "<desc>" + desc + "</desc>" : "") + "</wpt>";
}
public OsmTrack read(String filename) throws Exception {
File f = new File(filename);
if (!f.exists()) {
return null;
}
OsmTrack track = new OsmTrack();
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
for (; ; ) {
String line = br.readLine();
if (line == null)
break;
int idx0 = line.indexOf("<trkpt ");
if (idx0 >= 0) {
idx0 = line.indexOf(" lon=\"");
idx0 += 6;
int idx1 = line.indexOf('"', idx0);
int ilon = (int) ((Double.parseDouble(line.substring(idx0, idx1)) + 180.) * 1000000. + 0.5);
int idx2 = line.indexOf(" lat=\"");
if (idx2 < 0)
continue;
idx2 += 6;
int idx3 = line.indexOf('"', idx2);
int ilat = (int) ((Double.parseDouble(line.substring(idx2, idx3)) + 90.) * 1000000. + 0.5);
track.nodes.add(OsmPathElement.create(ilon, ilat, (short) 0, null, false));
}
}
br.close();
return track;
}
}

View file

@ -0,0 +1,246 @@
package btools.router;
import java.io.BufferedWriter;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;
import btools.mapaccess.MatchedWaypoint;
import btools.util.StringUtils;
public class FormatJson extends Formatter {
public FormatJson(RoutingContext rc) {
super(rc);
}
@Override
public String format(OsmTrack t) {
int turnInstructionMode = t.voiceHints != null ? t.voiceHints.turnInstructionMode : 0;
StringBuilder sb = new StringBuilder(8192);
sb.append("{\n");
sb.append(" \"type\": \"FeatureCollection\",\n");
sb.append(" \"features\": [\n");
sb.append(" {\n");
sb.append(" \"type\": \"Feature\",\n");
sb.append(" \"properties\": {\n");
sb.append(" \"creator\": \"BRouter-" + t.version + "\",\n");
sb.append(" \"name\": \"").append(t.name).append("\",\n");
sb.append(" \"track-length\": \"").append(t.distance).append("\",\n");
sb.append(" \"filtered ascend\": \"").append(t.ascend).append("\",\n");
sb.append(" \"plain-ascend\": \"").append(t.plainAscend).append("\",\n");
sb.append(" \"total-time\": \"").append(t.getTotalSeconds()).append("\",\n");
sb.append(" \"total-energy\": \"").append(t.energy).append("\",\n");
sb.append(" \"cost\": \"").append(t.cost).append("\",\n");
if (t.voiceHints != null && !t.voiceHints.list.isEmpty()) {
sb.append(" \"voicehints\": [\n");
for (VoiceHint hint : t.voiceHints.list) {
sb.append(" [");
sb.append(hint.indexInTrack);
sb.append(',').append(hint.getJsonCommandIndex());
sb.append(',').append(hint.getExitNumber());
sb.append(',').append(hint.distanceToNext);
sb.append(',').append((int) hint.angle);
// not always include geometry because longer and only needed for comment style
if (turnInstructionMode == 4) { // comment style
sb.append(",\"").append(hint.formatGeometry()).append("\"");
}
sb.append("],\n");
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(" ],\n");
}
if (t.showSpeedProfile) { // set in profile
List<String> sp = t.aggregateSpeedProfile();
if (sp.size() > 0) {
sb.append(" \"speedprofile\": [\n");
for (int i = sp.size() - 1; i >= 0; i--) {
sb.append(" [").append(sp.get(i)).append(i > 0 ? "],\n" : "]\n");
}
sb.append(" ],\n");
}
}
// ... traditional message list
{
sb.append(" \"messages\": [\n");
sb.append(" [\"").append(MESSAGES_HEADER.replaceAll("\t", "\", \"")).append("\"],\n");
for (String m : t.aggregateMessages()) {
sb.append(" [\"").append(m.replaceAll("\t", "\", \"")).append("\"],\n");
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(" ],\n");
}
if (t.getTotalSeconds() > 0) {
sb.append(" \"times\": [");
DecimalFormat decimalFormat = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
decimalFormat.applyPattern("0.###");
for (OsmPathElement n : t.nodes) {
sb.append(decimalFormat.format(n.getTime())).append(",");
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append("]\n");
} else {
sb.deleteCharAt(sb.lastIndexOf(","));
}
sb.append(" },\n");
if (t.iternity != null) {
sb.append(" \"iternity\": [\n");
for (String s : t.iternity) {
sb.append(" \"").append(s).append("\",\n");
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(" ],\n");
}
sb.append(" \"geometry\": {\n");
sb.append(" \"type\": \"LineString\",\n");
sb.append(" \"coordinates\": [\n");
OsmPathElement nn = null;
for (OsmPathElement n : t.nodes) {
String sele = n.getSElev() == Short.MIN_VALUE ? "" : ", " + n.getElev();
if (t.showspeed) { // hack: show speed instead of elevation
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 = ", " + (((int) (speed * 10)) / 10.f);
}
sb.append(" [").append(formatILon(n.getILon())).append(", ").append(formatILat(n.getILat()))
.append(sele).append("],\n");
nn = n;
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(" ]\n");
sb.append(" }\n");
if (t.exportWaypoints || !t.pois.isEmpty()) {
sb.append(" },\n");
for (int i = 0; i <= t.pois.size() - 1; i++) {
OsmNodeNamed poi = t.pois.get(i);
addFeature(sb, "poi", poi.name, poi.ilat, poi.ilon);
if (i < t.matchedWaypoints.size() - 1) {
sb.append(",");
}
sb.append(" \n");
}
if (t.exportWaypoints) {
for (int i = 0; i <= t.matchedWaypoints.size() - 1; i++) {
String type;
if (i == 0) {
type = "from";
} else if (i == t.matchedWaypoints.size() - 1) {
type = "to";
} else {
type = "via";
}
MatchedWaypoint wp = t.matchedWaypoints.get(i);
addFeature(sb, type, wp.name, wp.waypoint.ilat, wp.waypoint.ilon);
if (i < t.matchedWaypoints.size() - 1) {
sb.append(",");
}
sb.append(" \n");
}
}
} else {
sb.append(" }\n");
}
sb.append(" ]\n");
sb.append("}\n");
return sb.toString();
}
private void addFeature(StringBuilder sb, String type, String name, int ilat, int ilon) {
sb.append(" {\n");
sb.append(" \"type\": \"Feature\",\n");
sb.append(" \"properties\": {\n");
sb.append(" \"name\": \"" + StringUtils.escapeJson(name) + "\",\n");
sb.append(" \"type\": \"" + type + "\"\n");
sb.append(" },\n");
sb.append(" \"geometry\": {\n");
sb.append(" \"type\": \"Point\",\n");
sb.append(" \"coordinates\": [\n");
sb.append(" " + formatILon(ilon) + ",\n");
sb.append(" " + formatILat(ilat) + "\n");
sb.append(" ]\n");
sb.append(" }\n");
sb.append(" }");
}
public String formatAsWaypoint(OsmNodeNamed n) {
try {
StringWriter sw = new StringWriter(8192);
BufferedWriter bw = new BufferedWriter(sw);
addJsonHeader(bw);
addJsonFeature(bw, "info", "wpinfo", n.ilon, n.ilat, n.getElev(), (n.nodeDescription != null ? rc.expctxWay.getKeyValueDescription(false, n.nodeDescription) : null));
addJsonFooter(bw);
bw.close();
sw.close();
return sw.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void addJsonFeature(BufferedWriter sb, String type, String name, int ilon, int ilat, double elev, String desc) {
try {
sb.append(" {\n");
sb.append(" \"type\": \"Feature\",\n");
sb.append(" \"properties\": {\n");
sb.append(" \"creator\": \"BRouter-" + OsmTrack.version + "\",\n");
sb.append(" \"name\": \"" + StringUtils.escapeJson(name) + "\",\n");
sb.append(" \"type\": \"" + type + "\"");
if (desc != null) {
sb.append(",\n \"message\": \"" + desc + "\"\n");
} else {
sb.append("\n");
}
sb.append(" },\n");
sb.append(" \"geometry\": {\n");
sb.append(" \"type\": \"Point\",\n");
sb.append(" \"coordinates\": [\n");
sb.append(" " + formatILon(ilon) + ",\n");
sb.append(" " + formatILat(ilat) + ",\n");
sb.append(" " + elev + "\n");
sb.append(" ]\n");
sb.append(" }\n");
sb.append(" }\n");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void addJsonHeader(BufferedWriter sb) {
try {
sb.append("{\n");
sb.append(" \"type\": \"FeatureCollection\",\n");
sb.append(" \"features\": [\n");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void addJsonFooter(BufferedWriter sb) {
try {
sb.append(" ]\n");
sb.append("}\n");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,91 @@
package btools.router;
import java.util.List;
import btools.mapaccess.MatchedWaypoint;
import btools.util.StringUtils;
public class FormatKml extends Formatter {
public FormatKml(RoutingContext rc) {
super(rc);
}
@Override
public String format(OsmTrack t) {
StringBuilder sb = new StringBuilder(8192);
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
sb.append("<kml xmlns=\"http://earth.google.com/kml/2.0\">\n");
sb.append(" <Document>\n");
sb.append(" <name>KML Samples</name>\n");
sb.append(" <open>1</open>\n");
sb.append(" <distance>3.497064</distance>\n");
sb.append(" <traveltime>872</traveltime>\n");
sb.append(" <description>To enable simple instructions add: 'instructions=1' as parameter to the URL</description>\n");
sb.append(" <Folder>\n");
sb.append(" <name>Paths</name>\n");
sb.append(" <visibility>0</visibility>\n");
sb.append(" <description>Examples of paths.</description>\n");
sb.append(" <Placemark>\n");
sb.append(" <name>Tessellated</name>\n");
sb.append(" <visibility>0</visibility>\n");
sb.append(" <description><![CDATA[If the <tessellate> tag has a value of 1, the line will contour to the underlying terrain]]></description>\n");
sb.append(" <LineString>\n");
sb.append(" <tessellate>1</tessellate>\n");
sb.append(" <coordinates>");
for (OsmPathElement n : t.nodes) {
sb.append(formatILon(n.getILon())).append(",").append(formatILat(n.getILat())).append("\n");
}
sb.append(" </coordinates>\n");
sb.append(" </LineString>\n");
sb.append(" </Placemark>\n");
sb.append(" </Folder>\n");
if (t.exportWaypoints || !t.pois.isEmpty()) {
if (!t.pois.isEmpty()) {
sb.append(" <Folder>\n");
sb.append(" <name>poi</name>\n");
for (int i = 0; i < t.pois.size(); i++) {
OsmNodeNamed poi = t.pois.get(i);
createPlaceMark(sb, poi.name, poi.ilat, poi.ilon);
}
sb.append(" </Folder>\n");
}
if (t.exportWaypoints) {
int size = t.matchedWaypoints.size();
createFolder(sb, "start", t.matchedWaypoints.subList(0, 1));
if (t.matchedWaypoints.size() > 2) {
createFolder(sb, "via", t.matchedWaypoints.subList(1, size - 1));
}
createFolder(sb, "end", t.matchedWaypoints.subList(size - 1, size));
}
}
sb.append(" </Document>\n");
sb.append("</kml>\n");
return sb.toString();
}
private void createFolder(StringBuilder sb, String type, List<MatchedWaypoint> waypoints) {
sb.append(" <Folder>\n");
sb.append(" <name>" + type + "</name>\n");
for (int i = 0; i < waypoints.size(); i++) {
MatchedWaypoint wp = waypoints.get(i);
createPlaceMark(sb, wp.name, wp.waypoint.ilat, wp.waypoint.ilon);
}
sb.append(" </Folder>\n");
}
private void createPlaceMark(StringBuilder sb, String name, int ilat, int ilon) {
sb.append(" <Placemark>\n");
sb.append(" <name>" + StringUtils.escapeXml10(name) + "</name>\n");
sb.append(" <Point>\n");
sb.append(" <coordinates>" + formatILon(ilon) + "," + formatILat(ilat) + "</coordinates>\n");
sb.append(" </Point>\n");
sb.append(" </Placemark>\n");
}
}

View file

@ -0,0 +1,110 @@
package btools.router;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public abstract class Formatter {
static final String MESSAGES_HEADER = "Longitude\tLatitude\tElevation\tDistance\tCostPerKm\tElevCost\tTurnCost\tNodeCost\tInitialCost\tWayTags\tNodeTags\tTime\tEnergy";
RoutingContext rc;
Formatter() {
}
Formatter(RoutingContext rc) {
this.rc = rc;
}
/**
* writes the track in gpx-format to a file
*
* @param filename the filename to write to
* @param t the track to write
*/
public void write(String filename, OsmTrack t) throws Exception {
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
bw.write(format(t));
bw.close();
}
public OsmTrack read(String filename) throws Exception {
return null;
}
/**
* writes the track in a selected output format to a string
*
* @param t the track to format
* @return the formatted string
*/
public abstract String format(OsmTrack t);
static String formatILon(int ilon) {
return formatPos(ilon - 180000000);
}
static String formatILat(int ilat) {
return formatPos(ilat - 90000000);
}
private static String formatPos(int p) {
boolean negative = p < 0;
if (negative)
p = -p;
char[] ac = new char[12];
int i = 11;
while (p != 0 || i > 3) {
ac[i--] = (char) ('0' + (p % 10));
p /= 10;
if (i == 5)
ac[i--] = '.';
}
if (negative)
ac[i--] = '-';
return new String(ac, i + 1, 11 - i);
}
public static String getFormattedTime2(int s) {
int seconds = (int) (s + 0.5);
int hours = seconds / 3600;
int minutes = (seconds - hours * 3600) / 60;
seconds = seconds - hours * 3600 - minutes * 60;
String time = "";
if (hours != 0)
time = "" + hours + "h ";
if (minutes != 0)
time = time + minutes + "m ";
if (seconds != 0)
time = time + seconds + "s";
return time;
}
static public String getFormattedEnergy(int energy) {
return format1(energy / 3600000.) + "kwh";
}
static private String format1(double n) {
String s = "" + (long) (n * 10 + 0.5);
int len = s.length();
return s.substring(0, len - 1) + "." + s.charAt(len - 1);
}
static final String dateformat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
static public String getFormattedTime3(float time) {
SimpleDateFormat TIMESTAMP_FORMAT = new SimpleDateFormat(dateformat, 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);
}
}

View file

@ -7,33 +7,20 @@ package btools.router;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
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;
import btools.util.CompactLongMap;
import btools.util.FrozenLongMap;
import btools.util.StringUtils;
public final class OsmTrack {
final public static String version = "1.7.3";
@ -66,7 +53,7 @@ public final class OsmTrack {
private CompactLongMap<OsmPathElementHolder> detourMap;
private VoiceHintList voiceHints;
public VoiceHintList voiceHints;
public String message = null;
public List<String> messageList = null;
@ -178,7 +165,7 @@ public final class OsmTrack {
nodesMap = new FrozenLongMap<>(nodesMap);
}
private List<String> aggregateMessages() {
public List<String> aggregateMessages() {
ArrayList<String> res = new ArrayList<>();
MessageData current = null;
for (OsmPathElement n : nodes) {
@ -200,7 +187,7 @@ public final class OsmTrack {
return res;
}
private List<String> aggregateSpeedProfile() {
public List<String> aggregateSpeedProfile() {
ArrayList<String> res = new ArrayList<>();
int vmax = -1;
int vmaxe = -1;
@ -395,752 +382,9 @@ public final class OsmTrack {
public int plainAscend;
public int cost;
public int energy;
/**
* writes the track in gpx-format to a file
*
* @param filename the filename to write to
*/
public void writeGpx(String filename) throws Exception {
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
formatAsGpx(bw);
bw.close();
}
public String formatAsGpx() {
try {
StringWriter sw = new StringWriter(8192);
BufferedWriter bw = new BufferedWriter(sw);
formatAsGpx(bw);
bw.close();
return sw.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String formatAsGpx(BufferedWriter sb) throws IOException {
int turnInstructionMode = voiceHints != null ? voiceHints.turnInstructionMode : 0;
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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
sb.append("<!-- $transport-mode$").append(voiceHints.getTransportMode()).append("$ -->\n");
sb.append("<!-- cmd idx lon lat d2next geometry -->\n");
sb.append("<!-- $turn-instruction-start$\n");
for (VoiceHint hint : voiceHints.list) {
sb.append(String.format(" $turn$%6s;%6d;%10s;%10s;%6d;%s$\n", hint.getCommandString(), hint.indexInTrack,
formatILon(hint.ilon), formatILat(hint.ilat), (int) (hint.distanceToNext), hint.formatGeometry()));
}
sb.append(" $turn-instruction-end$ -->\n");
}
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 == 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");
if (turnInstructionMode == 3) {
sb.append(" creator=\"OsmAndRouter\" version=\"1.1\">\n");
} else {
sb.append(" creator=\"BRouter-" + version + "\" version=\"1.1\">\n");
}
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");
float rteTime = getVoiceHintTime(0);
StringBuffer first = new StringBuffer();
// define start point
{
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());
}
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(turnInstructionMode == 3 ? hint.getMessageString() : hint.getCruiserMessageString())
.append("</desc>\n <extensions>\n");
rteTime = getVoiceHintTime(i + 1);
if (rteTime != lastRteTime) { // add timing only if available
double t = rteTime - lastRteTime;
sb.append(" <time>").append("" + (int) (t + 0.5)).append("</time>\n");
lastRteTime = rteTime;
}
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=\"")
.append(formatILon(nodes.get(nodes.size() - 1).getILon())).append("\">\n")
.append(" <desc>destination</desc>\n <extensions>\n");
sb.append(" <time>0</time>\n");
sb.append(" <offset>").append("" + (nodes.size() - 1)).append("</offset>\n </extensions>\n </rtept>\n");
sb.append("</rte>\n");
}
if (turnInstructionMode == 7) { // old locus style
float lastRteTime = getVoiceHintTime(0);
for (int i = 0; i < voiceHints.list.size(); i++) {
VoiceHint hint = voiceHints.list.get(i);
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
.append(formatILat(hint.ilat)).append("\">")
.append(hint.selev == Short.MIN_VALUE ? "" : "<ele>" + (hint.selev / 4.) + "</ele>")
.append("<name>").append(hint.getMessageString()).append("</name>")
.append("<extensions><locus:rteDistance>").append("" + hint.distanceToNext).append("</locus:rteDistance>");
float rteTime = getVoiceHintTime(i + 1);
if (rteTime != lastRteTime) { // add timing only if available
double t = rteTime - lastRteTime;
double speed = hint.distanceToNext / t;
sb.append("<locus:rteTime>").append("" + t).append("</locus:rteTime>")
.append("<locus:rteSpeed>").append("" + speed).append("</locus:rteSpeed>");
lastRteTime = rteTime;
}
sb.append("<locus:rtePointAction>").append("" + hint.getLocusAction()).append("</locus:rtePointAction></extensions>")
.append("</wpt>\n");
}
}
if (turnInstructionMode == 5) { // gpsies style
for (VoiceHint hint : voiceHints.list) {
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
.append(formatILat(hint.ilat)).append("\">")
.append("<name>").append(hint.getMessageString()).append("</name>")
.append("<sym>").append(hint.getSymbolString().toLowerCase()).append("</sym>")
.append("<type>").append(hint.getSymbolString()).append("</type>")
.append("</wpt>\n");
}
}
if (turnInstructionMode == 6) { // orux style
for (VoiceHint hint : voiceHints.list) {
sb.append(" <wpt lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
.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())
.append("</om:ext>\n" +
" </om:oruxmapsextensions>\n" +
" </extensions>\n" +
" </wpt>\n");
}
}
for (int i = 0; i <= pois.size() - 1; i++) {
OsmNodeNamed poi = pois.get(i);
sb.append(" <wpt lon=\"").append(formatILon(poi.ilon)).append("\" lat=\"")
.append(formatILat(poi.ilat)).append("\">\n")
.append(" <name>").append(StringUtils.escapeXml10(poi.name)).append("</name>\n")
.append(" </wpt>\n");
}
if (exportWaypoints) {
for (int i = 0; i <= matchedWaypoints.size() - 1; i++) {
MatchedWaypoint wt = matchedWaypoints.get(i);
sb.append(" <wpt lon=\"").append(formatILon(wt.waypoint.ilon)).append("\" lat=\"")
.append(formatILat(wt.waypoint.ilat)).append("\">\n")
.append(" <name>").append(StringUtils.escapeXml10(wt.name)).append("</name>\n");
if (i == 0) {
sb.append(" <type>from</type>\n");
} else if (i == matchedWaypoints.size() - 1) {
sb.append(" <type>to</type>\n");
} else {
sb.append(" <type>via</type>\n");
}
sb.append(" </wpt>\n");
}
}
sb.append(" <trk>\n");
if (turnInstructionMode == 9
|| turnInstructionMode == 2
|| turnInstructionMode == 8
|| turnInstructionMode == 4) { // Locus, comment, cruise, 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 == 7) {
sb.append(" <extensions>\n");
sb.append(" <locus:rteComputeType>").append("" + voiceHints.getLocusRouteType()).append("</locus:rteComputeType>\n");
sb.append(" <locus:rteSimpleRoundabouts>1</locus:rteSimpleRoundabouts>\n");
sb.append(" </extensions>\n");
}
// all points
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>";
VoiceHint hint = getVoiceHint(idx);
MatchedWaypoint mwpt = getMatchedWaypoint(idx);
if (showTime) {
sele += "<time>" + getFormattedTime3(n.getTime()) + "</time>";
}
if (turnInstructionMode == 8) {
if (mwpt != null &&
!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
sele += "<name>" + mwpt.name + "</name>";
}
}
boolean bNeedHeader = false;
if (turnInstructionMode == 9) { // trkpt/sym style
if (hint != null) {
if (mwpt != null &&
!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
sele += "<name>" + mwpt.name + "</name>";
}
sele += "<desc>" + hint.getCruiserMessageString() + "</desc>";
sele += "<sym>" + hint.getCommandString(hint.cmd) + "</sym>";
if (mwpt != null) {
sele += "<type>Via</type>";
}
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>";
}
if (idx == 0 && hint == null) {
if (mwpt != null && mwpt.direct) {
sele += "<desc>beeline</desc>";
} else {
sele += "<desc>start</desc>";
}
sele += "<type>Via</type>";
} else if (idx == nodes.size() - 1 && hint == null) {
sele += "<desc>end</desc>";
sele += "<type>Via</type>";
} else {
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 (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>";
}
}
}
if (turnInstructionMode == 2) { // locus style new
if (hint != null) {
if (mwpt != null) {
if (!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
sele += "<name>" + mwpt.name + "</name>";
}
if (mwpt.direct && bNextDirect) {
sele += "<src>" + hint.getLocusSymbolString() + "</src><sym>pass_place</sym><type>Shaping</type>";
// bNextDirect = false;
} else if (mwpt.direct) {
if (idx == 0)
sele += "<sym>pass_place</sym><type>Via</type>";
else
sele += "<sym>pass_place</sym><type>Shaping</type>";
bNextDirect = true;
} else if (bNextDirect) {
sele += "<src>beeline</src><sym>" + hint.getLocusSymbolString() + "</sym><type>Shaping</type>";
bNextDirect = false;
} else {
sele += "<sym>" + hint.getLocusSymbolString() + "</sym><type>Via</type>";
}
} else {
sele += "<sym>" + hint.getLocusSymbolString() + "</sym>";
}
} else {
if (idx == 0 && hint == null) {
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 (idx == nodes.size() - 1 && hint == null) {
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 {
if (mwpt != null) {
if (!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
sele += "<name>" + mwpt.name + "</name>";
}
if (mwpt.direct && bNextDirect) {
sele += "<src>beeline</src><sym>pass_place</sym><type>Shaping</type>";
} else if (mwpt.direct) {
if (idx == 0)
sele += "<sym>pass_place</sym><type>Via</type>";
else
sele += "<sym>pass_place</sym><type>Shaping</type>";
bNextDirect = true;
} else if (bNextDirect) {
sele += "<src>beeline</src><sym>pass_place</sym><type>Shaping</type>";
bNextDirect = false;
} else if (mwpt.name.startsWith("via") ||
mwpt.name.startsWith("from") ||
mwpt.name.startsWith("to")) {
if (bNextDirect) {
sele += "<src>beeline</src><sym>pass_place</sym><type>Shaping</type>";
} else {
sele += "<sym>pass_place</sym><type>Via</type>";
}
bNextDirect = false;
} else {
sele += "<name>" + mwpt.name + "</name>";
sele += "<sym>pass_place</sym><type>Via</type>";
}
}
}
}
}
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");
sb.append(" </trk>\n");
sb.append("</gpx>\n");
return sb.toString();
}
static public String formatAsGpxWaypoint(OsmNodeNamed n) {
try {
StringWriter sw = new StringWriter(8192);
BufferedWriter bw = new BufferedWriter(sw);
formatGpxHeader(bw);
formatWaypointGpx(bw, n);
formatGpxFooter(bw);
bw.close();
sw.close();
return sw.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static public void formatGpxHeader(BufferedWriter sb) throws IOException {
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
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");
sb.append(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" \n");
sb.append(" creator=\"BRouter-" + version + "\" version=\"1.1\">\n");
}
static public void formatGpxFooter(BufferedWriter sb) throws IOException {
sb.append("</gpx>\n");
}
static public void formatWaypointGpx(BufferedWriter sb, OsmNodeNamed n) throws IOException {
sb.append(" <wpt lon=\"").append(formatILon(n.ilon)).append("\" lat=\"")
.append(formatILat(n.ilat)).append("\">");
if (n.getSElev() != Short.MIN_VALUE) {
sb.append("<ele>").append("" + n.getElev()).append("</ele>");
}
if (n.name != null) {
sb.append("<name>").append(StringUtils.escapeXml10(n.name)).append("</name>");
}
if (n.nodeDescription != null) {
sb.append("<desc>").append("hat desc").append("</desc>");
}
sb.append("</wpt>\n");
}
public void writeKml(String filename) throws Exception {
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
bw.write(formatAsKml());
bw.close();
}
public String formatAsKml() {
StringBuilder sb = new StringBuilder(8192);
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
sb.append("<kml xmlns=\"http://earth.google.com/kml/2.0\">\n");
sb.append(" <Document>\n");
sb.append(" <name>KML Samples</name>\n");
sb.append(" <open>1</open>\n");
sb.append(" <distance>3.497064</distance>\n");
sb.append(" <traveltime>872</traveltime>\n");
sb.append(" <description>To enable simple instructions add: 'instructions=1' as parameter to the URL</description>\n");
sb.append(" <Folder>\n");
sb.append(" <name>Paths</name>\n");
sb.append(" <visibility>0</visibility>\n");
sb.append(" <description>Examples of paths.</description>\n");
sb.append(" <Placemark>\n");
sb.append(" <name>Tessellated</name>\n");
sb.append(" <visibility>0</visibility>\n");
sb.append(" <description><![CDATA[If the <tessellate> tag has a value of 1, the line will contour to the underlying terrain]]></description>\n");
sb.append(" <LineString>\n");
sb.append(" <tessellate>1</tessellate>\n");
sb.append(" <coordinates>");
for (OsmPathElement n : nodes) {
sb.append(formatILon(n.getILon())).append(",").append(formatILat(n.getILat())).append("\n");
}
sb.append(" </coordinates>\n");
sb.append(" </LineString>\n");
sb.append(" </Placemark>\n");
sb.append(" </Folder>\n");
if (exportWaypoints || !pois.isEmpty()) {
if (!pois.isEmpty()) {
sb.append(" <Folder>\n");
sb.append(" <name>poi</name>\n");
for (int i = 0; i < pois.size(); i++) {
OsmNodeNamed poi = pois.get(i);
createPlaceMark(sb, poi.name, poi.ilat, poi.ilon);
}
sb.append(" </Folder>\n");
}
if (exportWaypoints) {
int size = matchedWaypoints.size();
createFolder(sb, "start", matchedWaypoints.subList(0, 1));
if (matchedWaypoints.size() > 2) {
createFolder(sb, "via", matchedWaypoints.subList(1, size - 1));
}
createFolder(sb, "end", matchedWaypoints.subList(size - 1, size));
}
}
sb.append(" </Document>\n");
sb.append("</kml>\n");
return sb.toString();
}
private void createFolder(StringBuilder sb, String type, List<MatchedWaypoint> waypoints) {
sb.append(" <Folder>\n");
sb.append(" <name>" + type + "</name>\n");
for (int i = 0; i < waypoints.size(); i++) {
MatchedWaypoint wp = waypoints.get(i);
createPlaceMark(sb, wp.name, wp.waypoint.ilat, wp.waypoint.ilon);
}
sb.append(" </Folder>\n");
}
private void createPlaceMark(StringBuilder sb, String name, int ilat, int ilon) {
sb.append(" <Placemark>\n");
sb.append(" <name>" + StringUtils.escapeXml10(name) + "</name>\n");
sb.append(" <Point>\n");
sb.append(" <coordinates>" + formatILon(ilon) + "," + formatILat(ilat) + "</coordinates>\n");
sb.append(" </Point>\n");
sb.append(" </Placemark>\n");
}
public List<String> iternity;
public void writeJson(String filename) throws Exception {
BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
bw.write(formatAsGeoJson());
bw.close();
}
public String formatAsGeoJson() {
int turnInstructionMode = voiceHints != null ? voiceHints.turnInstructionMode : 0;
StringBuilder sb = new StringBuilder(8192);
sb.append("{\n");
sb.append(" \"type\": \"FeatureCollection\",\n");
sb.append(" \"features\": [\n");
sb.append(" {\n");
sb.append(" \"type\": \"Feature\",\n");
sb.append(" \"properties\": {\n");
sb.append(" \"creator\": \"BRouter-" + version + "\",\n");
sb.append(" \"name\": \"").append(name).append("\",\n");
sb.append(" \"track-length\": \"").append(distance).append("\",\n");
sb.append(" \"filtered ascend\": \"").append(ascend).append("\",\n");
sb.append(" \"plain-ascend\": \"").append(plainAscend).append("\",\n");
sb.append(" \"total-time\": \"").append(getTotalSeconds()).append("\",\n");
sb.append(" \"total-energy\": \"").append(energy).append("\",\n");
sb.append(" \"cost\": \"").append(cost).append("\",\n");
if (voiceHints != null && !voiceHints.list.isEmpty()) {
sb.append(" \"voicehints\": [\n");
for (VoiceHint hint : voiceHints.list) {
sb.append(" [");
sb.append(hint.indexInTrack);
sb.append(',').append(hint.getJsonCommandIndex());
sb.append(',').append(hint.getExitNumber());
sb.append(',').append(hint.distanceToNext);
sb.append(',').append((int) hint.angle);
// not always include geometry because longer and only needed for comment style
if (turnInstructionMode == 4) { // comment style
sb.append(",\"").append(hint.formatGeometry()).append("\"");
}
sb.append("],\n");
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(" ],\n");
}
if (showSpeedProfile) { // set in profile
List<String> sp = aggregateSpeedProfile();
if (sp.size() > 0) {
sb.append(" \"speedprofile\": [\n");
for (int i = sp.size() - 1; i >= 0; i--) {
sb.append(" [").append(sp.get(i)).append(i > 0 ? "],\n" : "]\n");
}
sb.append(" ],\n");
}
}
// ... traditional message list
{
sb.append(" \"messages\": [\n");
sb.append(" [\"").append(MESSAGES_HEADER.replaceAll("\t", "\", \"")).append("\"],\n");
for (String m : aggregateMessages()) {
sb.append(" [\"").append(m.replaceAll("\t", "\", \"")).append("\"],\n");
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(" ],\n");
}
if (getTotalSeconds() > 0) {
sb.append(" \"times\": [");
DecimalFormat decimalFormat = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
decimalFormat.applyPattern("0.###");
for (OsmPathElement n : nodes) {
sb.append(decimalFormat.format(n.getTime())).append(",");
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append("]\n");
} else {
sb.deleteCharAt(sb.lastIndexOf(","));
}
sb.append(" },\n");
if (iternity != null) {
sb.append(" \"iternity\": [\n");
for (String s : iternity) {
sb.append(" \"").append(s).append("\",\n");
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(" ],\n");
}
sb.append(" \"geometry\": {\n");
sb.append(" \"type\": \"LineString\",\n");
sb.append(" \"coordinates\": [\n");
OsmPathElement nn = null;
for (OsmPathElement n : nodes) {
String sele = n.getSElev() == Short.MIN_VALUE ? "" : ", " + n.getElev();
if (showspeed) { // hack: show speed instead of elevation
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 = ", " + (((int) (speed * 10)) / 10.f);
}
sb.append(" [").append(formatILon(n.getILon())).append(", ").append(formatILat(n.getILat()))
.append(sele).append("],\n");
nn = n;
}
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(" ]\n");
sb.append(" }\n");
if (exportWaypoints || !pois.isEmpty()) {
sb.append(" },\n");
for (int i = 0; i <= pois.size() - 1; i++) {
OsmNodeNamed poi = pois.get(i);
addFeature(sb, "poi", poi.name, poi.ilat, poi.ilon);
if (i < matchedWaypoints.size() - 1) {
sb.append(",");
}
sb.append(" \n");
}
if (exportWaypoints) {
for (int i = 0; i <= matchedWaypoints.size() - 1; i++) {
String type;
if (i == 0) {
type = "from";
} else if (i == matchedWaypoints.size() - 1) {
type = "to";
} else {
type = "via";
}
MatchedWaypoint wp = matchedWaypoints.get(i);
addFeature(sb, type, wp.name, wp.waypoint.ilat, wp.waypoint.ilon);
if (i < matchedWaypoints.size() - 1) {
sb.append(",");
}
sb.append(" \n");
}
}
} else {
sb.append(" }\n");
}
sb.append(" ]\n");
sb.append("}\n");
return sb.toString();
}
private void addFeature(StringBuilder sb, String type, String name, int ilat, int ilon) {
sb.append(" {\n");
sb.append(" \"type\": \"Feature\",\n");
sb.append(" \"properties\": {\n");
sb.append(" \"name\": \"" + StringUtils.escapeJson(name) + "\",\n");
sb.append(" \"type\": \"" + type + "\"\n");
sb.append(" },\n");
sb.append(" \"geometry\": {\n");
sb.append(" \"type\": \"Point\",\n");
sb.append(" \"coordinates\": [\n");
sb.append(" " + formatILon(ilon) + ",\n");
sb.append(" " + formatILat(ilat) + "\n");
sb.append(" ]\n");
sb.append(" }\n");
sb.append(" }");
}
private VoiceHint getVoiceHint(int i) {
public VoiceHint getVoiceHint(int i) {
if (voiceHints == null) return null;
for (VoiceHint hint : voiceHints.list) {
if (hint.indexInTrack == i) {
@ -1150,7 +394,7 @@ public final class OsmTrack {
return null;
}
private MatchedWaypoint getMatchedWaypoint(int idx) {
public MatchedWaypoint getMatchedWaypoint(int idx) {
if (matchedWaypoints == null) return null;
for (MatchedWaypoint wp : matchedWaypoints) {
if (idx == wp.indexInTrack) {
@ -1168,128 +412,11 @@ public final class OsmTrack {
return vnode0 < vnode1 ? vnode0 : vnode1;
}
private int getTotalSeconds() {
public int getTotalSeconds() {
float s = nodes.size() < 2 ? 0 : nodes.get(nodes.size() - 1).getTime() - nodes.get(0).getTime();
return (int) (s + 0.5);
}
public String getFormattedTime() {
return format1(getTotalSeconds() / 60.) + "m";
}
public String getFormattedTime2() {
int seconds = (int) (getTotalSeconds() + 0.5);
int hours = seconds / 3600;
int minutes = (seconds - hours * 3600) / 60;
seconds = seconds - hours * 3600 - minutes * 60;
String time = "";
if (hours != 0)
time = "" + hours + "h ";
if (minutes != 0)
time = time + minutes + "m ";
if (seconds != 0)
time = time + seconds + "s";
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";
}
private static String formatILon(int ilon) {
return formatPos(ilon - 180000000);
}
private static String formatILat(int ilat) {
return formatPos(ilat - 90000000);
}
private static String formatPos(int p) {
boolean negative = p < 0;
if (negative)
p = -p;
char[] ac = new char[12];
int i = 11;
while (p != 0 || i > 3) {
ac[i--] = (char) ('0' + (p % 10));
p /= 10;
if (i == 5)
ac[i--] = '.';
}
if (negative)
ac[i--] = '-';
return new String(ac, i + 1, 11 - i);
}
private String format1(double n) {
String s = "" + (long) (n * 10 + 0.5);
int len = s.length();
return s.substring(0, len - 1) + "." + s.charAt(len - 1);
}
public void dumpMessages(String filename, RoutingContext rc) throws Exception {
BufferedWriter bw = filename == null ? null : new BufferedWriter(new FileWriter(filename));
writeMessages(bw, rc);
}
public void writeMessages(BufferedWriter bw, RoutingContext rc) throws Exception {
dumpLine(bw, MESSAGES_HEADER);
for (String m : aggregateMessages()) {
dumpLine(bw, m);
}
if (bw != null)
bw.close();
}
private void dumpLine(BufferedWriter bw, String s) throws Exception {
if (bw == null) {
System.out.println(s);
} else {
bw.write(s);
bw.write("\n");
}
}
public void readGpx(String filename) throws Exception {
File f = new File(filename);
if (!f.exists())
return;
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
for (; ; ) {
String line = br.readLine();
if (line == null)
break;
int idx0 = line.indexOf("<trkpt lon=\"");
if (idx0 >= 0) {
idx0 += 12;
int idx1 = line.indexOf('"', idx0);
int ilon = (int) ((Double.parseDouble(line.substring(idx0, idx1)) + 180.) * 1000000. + 0.5);
int idx2 = line.indexOf(" lat=\"");
if (idx2 < 0)
continue;
idx2 += 6;
int idx3 = line.indexOf('"', idx2);
int ilat = (int) ((Double.parseDouble(line.substring(idx2, idx3)) + 90.) * 1000000. + 0.5);
nodes.add(OsmPathElement.create(ilon, ilat, (short) 0, null, false));
}
}
br.close();
}
public boolean equalsTrack(OsmTrack t) {
if (nodes.size() != t.nodes.size())
return false;
@ -1398,7 +525,7 @@ public final class OsmTrack {
return 2;
}
private float getVoiceHintTime(int i) {
public float getVoiceHintTime(int i) {
if (voiceHints.list.isEmpty()) {
return 0f;
}

View file

@ -192,34 +192,70 @@ public class RoutingEngine extends Thread {
track.message = "track-length = " + track.distance + " filtered ascend = " + track.ascend
+ " plain-ascend = " + track.plainAscend + " cost=" + track.cost;
if (track.energy != 0) {
track.message += " energy=" + track.getFormattedEnergy() + " time=" + track.getFormattedTime2();
track.message += " energy=" + Formatter.getFormattedEnergy(track.energy) + " time=" + Formatter.getFormattedTime2(track.getTotalSeconds());
}
track.name = "brouter_" + routingContext.getProfileName() + "_" + i;
messageList.add(track.message);
track.messageList = messageList;
if (outfileBase != null) {
String filename = outfileBase + i + ".gpx";
OsmTrack oldTrack = new OsmTrack();
oldTrack.readGpx(filename);
if (track.equalsTrack(oldTrack)) {
String filename = outfileBase + i + "." + routingContext.outputFormat;
OsmTrack oldTrack = null;
switch (routingContext.outputFormat) {
case "gpx":
oldTrack = new FormatGpx(routingContext).read(filename);
break;
case "geojson": // read only gpx at the moment
case "json":
// oldTrack = new FormatJson(routingContext).read(filename);
break;
case "kml":
// oldTrack = new FormatJson(routingContext).read(filename);
break;
default:
break;
}
if (oldTrack != null && track.equalsTrack(oldTrack)) {
continue;
}
oldTrack = null;
track.exportWaypoints = routingContext.exportWaypoints;
// doesn't work at the moment
// use routingContext.outputFormat
track.writeGpx(filename);
filename = outfileBase + i + "." + routingContext.outputFormat;
switch (routingContext.outputFormat) {
case "gpx":
outputMessage = new FormatGpx(routingContext).format(track);
break;
case "geojson":
case "json":
outputMessage = new FormatJson(routingContext).format(track);
break;
case "kml":
outputMessage = new FormatKml(routingContext).format(track);
break;
case "csv":
default:
outputMessage = null;
break;
}
if (outputMessage != null) {
File out = new File(filename);
FileWriter fw = new FileWriter(filename);
fw.write(outputMessage);
fw.close();
outputMessage = null;
}
foundTrack = track;
alternativeIndex = i;
outfile = filename;
} else {
if (i == routingContext.getAlternativeIdx(0, 3)) {
if ("CSV".equals(System.getProperty("reportFormat"))) {
track.dumpMessages(null, routingContext);
String filename = outfileBase + i + ".csv";
new FormatCsv(routingContext).write(filename, track);
} else {
if (!quite) {
System.out.println(track.formatAsGpx());
System.out.println(new FormatGpx(routingContext).format(track));
}
}
foundTrack = track;
@ -229,7 +265,7 @@ public class RoutingEngine extends Thread {
}
if (logfileBase != null) {
String logfilename = logfileBase + i + ".csv";
track.dumpMessages(logfilename, routingContext);
new FormatCsv(routingContext).write(logfilename, track);
}
break;
}
@ -308,15 +344,31 @@ public class RoutingEngine extends Thread {
OsmNodeNamed n = new OsmNodeNamed(listOne.get(0).crosspoint);
n.selev = startNode != null ? startNode.getSElev() : Short.MIN_VALUE;
// doesn't work at the moment
// use routingContext.outputFormat
outputMessage = OsmTrack.formatAsGpxWaypoint(n);
switch (routingContext.outputFormat) {
case "gpx":
outputMessage = new FormatGpx(routingContext).formatAsWaypoint(n);
break;
case "geojson":
case "json":
outputMessage = new FormatJson(routingContext).formatAsWaypoint(n);
break;
case "kml":
case "csv":
default:
outputMessage = null;
break;
}
if (outfileBase != null) {
String filename = outfileBase + ".gpx";
String filename = outfileBase + "." + routingContext.outputFormat;
File out = new File(filename);
FileWriter fw = new FileWriter(filename);
fw.write(outputMessage);
fw.close();
outputMessage = null;
} else {
if (!quite && outputMessage != null) {
System.out.println(outputMessage);
}
}
long endTime = System.currentTimeMillis();
logInfo("execution time = " + (endTime - startTime) / 1000. + " seconds");
@ -951,7 +1003,7 @@ public class RoutingEngine extends Thread {
if (track == null) {
for (int cfi = 0; cfi < airDistanceCostFactors.length; cfi++) {
if (cfi > 0) lastAirDistanceCostFactor = airDistanceCostFactors[cfi-1];
if (cfi > 0) lastAirDistanceCostFactor = airDistanceCostFactors[cfi - 1];
airDistanceCostFactor = airDistanceCostFactors[cfi];
if (airDistanceCostFactor < 0.) {
@ -1447,7 +1499,7 @@ public class RoutingEngine extends Thread {
boolean inRadius = boundary == null || boundary.isInBoundary(nextNode, bestPath.cost);
if (inRadius && (isFinalLink || bestPath.cost + bestPath.airdistance <= (lastAirDistanceCostFactor != 0. ? maxTotalCost*lastAirDistanceCostFactor : maxTotalCost) + addDiff)) {
if (inRadius && (isFinalLink || bestPath.cost + bestPath.airdistance <= (lastAirDistanceCostFactor != 0. ? maxTotalCost * lastAirDistanceCostFactor : maxTotalCost) + addDiff)) {
// add only if this may beat an existing path for that link
OsmLinkHolder dominator = link.getFirstLinkHolder(currentNode);
while (!trafficSim && dominator != null) {
@ -1628,7 +1680,7 @@ public class RoutingEngine extends Thread {
}
public String getTime() {
return foundTrack.getFormattedTime2();
return Formatter.getFormattedTime2(foundTrack.getTotalSeconds());
}
public OsmTrack getFoundTrack() {

View file

@ -51,7 +51,7 @@ public final class WaypointMatcherImpl implements WaypointMatcher {
}
// sort result list
comparator = new Comparator<>() {
comparator = new Comparator<MatchedWaypoint>() {
@Override
public int compare(MatchedWaypoint mw1, MatchedWaypoint mw2) {
int cmpDist = Double.compare(mw1.radius, mw2.radius);

View file

@ -20,8 +20,6 @@ android {
minSdkVersion 14
targetSdkVersion 33
resConfigs "en"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

View file

@ -10,6 +10,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application
@ -100,6 +101,10 @@
android:enabled="true"
android:exported="true"
android:process=":brouter_service" />
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="dataSync"
tools:node="merge" />
<provider
android:name="androidx.core.content.FileProvider"

View file

@ -10,7 +10,6 @@ import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Build;
@ -171,7 +170,7 @@ public class BInstallerActivity extends AppCompatActivity {
}
mButtonDownload.setText(getString(R.string.action_download, getSegmentsPlural(selectedTilesDownload.size())));
mButtonDownload.setEnabled(true);
mSummaryInfo.setText(getString(R.string.summary_segments, Formatter.formatFileSize(this, tileSize), Formatter.formatFileSize(this, getAvailableSpace(mBaseDir.getAbsolutePath()))));
mSummaryInfo.setText(String.format(getString(R.string.summary_segments), Formatter.formatFileSize(this, tileSize), Formatter.formatFileSize(this, getAvailableSpace(mBaseDir.getAbsolutePath()))));
} else if (selectedTilesUpdate.size() > 0) {
mButtonDownload.setText(getString(R.string.action_update, getSegmentsPlural(selectedTilesUpdate.size())));
mButtonDownload.setEnabled(true);
@ -214,7 +213,8 @@ public class BInstallerActivity extends AppCompatActivity {
.build();
} catch (IllegalStateException e) {
Toast.makeText(this, "Too much data for download. Please reduce.", Toast.LENGTH_LONG).show();
Object data;
Toast.makeText(this, R.string.msg_too_much_data, Toast.LENGTH_LONG).show();
e.printStackTrace();
return;
@ -264,7 +264,7 @@ public class BInstallerActivity extends AppCompatActivity {
}
if (workInfo.getState() == WorkInfo.State.ENQUEUED) {
Toast.makeText(this, "Download scheduled. Check internet connection if it doesn't start.", Toast.LENGTH_LONG).show();
Toast.makeText(this, R.string.msg_download_start, Toast.LENGTH_LONG).show();
mProgressIndicator.hide();
mProgressIndicator.setIndeterminate(true);
mProgressIndicator.show();
@ -279,7 +279,7 @@ public class BInstallerActivity extends AppCompatActivity {
String segmentName = progress.getString(DownloadWorker.PROGRESS_SEGMENT_NAME);
int percent = progress.getInt(DownloadWorker.PROGRESS_SEGMENT_PERCENT, 0);
if (percent > 0) {
mDownloadSummaryInfo.setText("Downloading .. " + segmentName);
mDownloadSummaryInfo.setText(getString(R.string.msg_download_started) + segmentName);
}
if (percent > 0) {
mProgressIndicator.setIndeterminate(false);
@ -295,13 +295,13 @@ public class BInstallerActivity extends AppCompatActivity {
String result;
switch (workInfo.getState()) {
case FAILED:
result = "Download failed";
result = getString(R.string.msg_download_failed);
break;
case CANCELLED:
result = "Download cancelled";
result = getString(R.string.msg_download_cancel);
break;
case SUCCEEDED:
result = "Download succeeded";
result = getString(R.string.msg_download_succeed);
break;
default:
result = "";
@ -349,12 +349,12 @@ public class BInstallerActivity extends AppCompatActivity {
switch (id) {
case DIALOG_CONFIRM_DELETE_ID:
builder
.setTitle("Confirm Delete")
.setMessage("Really delete?").setPositiveButton("Yes", new DialogInterface.OnClickListener() {
.setTitle(R.string.title_delete)
.setMessage(R.string.summary_delete).setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
deleteSelectedTiles();
}
}).setNegativeButton("No", new DialogInterface.OnClickListener() {
}).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
@ -362,9 +362,9 @@ public class BInstallerActivity extends AppCompatActivity {
case DIALOG_CONFIRM_NEXTSTEPS_ID:
builder
.setTitle("Version Problem")
.setMessage("The base version for tiles has changed. What to do?")
.setPositiveButton("Continue with current download, delete other old data", new DialogInterface.OnClickListener() {
.setTitle(R.string.title_version)
.setMessage(R.string.summary_version)
.setPositiveButton(R.string.action_version1, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
ArrayList<Integer> allTiles = mBInstallerView.getSelectedTiles(MASK_INSTALLED_RD5);
@ -376,11 +376,11 @@ public class BInstallerActivity extends AppCompatActivity {
}
downloadSelectedTiles();
}
}).setNegativeButton("Select all for download and start", new DialogInterface.OnClickListener() {
}).setNegativeButton(R.string.action_version2, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
downloadInstalledTiles();
}
}).setNeutralButton("Cancel now, complete on an other day", new DialogInterface.OnClickListener() {
}).setNeutralButton(R.string.action_version3, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
File tmplookupFile = new File(mBaseDir, "brouter/profiles2/lookups.dat.tmp");
tmplookupFile.delete();
@ -391,17 +391,17 @@ public class BInstallerActivity extends AppCompatActivity {
case DIALOG_CONFIRM_GETDIFFS_ID:
builder
.setTitle("Version Differences")
.setMessage("The base version for some tiles is different. What to do?")
.setPositiveButton("Download all different tiles", new DialogInterface.OnClickListener() {
.setTitle(R.string.title_version_diff)
.setMessage(R.string.summary_version_diff)
.setPositiveButton(R.string.action_version_diff1, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
downloadDiffVersionTiles();
}
}).setNegativeButton("Drop all different tiles", new DialogInterface.OnClickListener() {
}).setNegativeButton(R.string.action_version_diff2, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dropDiffVersionTiles();
}
}).setNeutralButton("Cancel now, complete on an other day", new DialogInterface.OnClickListener() {
}).setNeutralButton(R.string.action_version_diff3, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
@ -409,9 +409,9 @@ public class BInstallerActivity extends AppCompatActivity {
return builder.create();
case DIALOG_NEW_APP_NEEDED_ID:
builder
.setTitle("App Version")
.setMessage("The new data version needs a new app. Please update BRouter first")
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
.setTitle(R.string.title_version)
.setMessage(R.string.summary_new_version)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}

View file

@ -175,7 +175,7 @@ public class BInstallerView extends View {
int tidx = gridPos2Tileindex(ix, iy);
int tilesize = BInstallerSizes.getRd5Size(tidx);
if (tilesize > 0) {
canvas.drawRect(fw * ix, fh * (iy + 1), fw * (ix + 1), fh * iy, paintGrid);
canvas.drawRect(fw * ix, fh * iy, fw * (ix + 1), fh * (iy + 1), paintGrid);
}
}
}
@ -214,7 +214,7 @@ public class BInstallerView extends View {
canvas.drawLine(fw * ix, fh * (iy + 1), fw * (ix + 1), fh * iy, pnt);
// draw frame
canvas.drawRect(fw * ix, fh * (iy + 1), fw * (ix + 1), fh * iy, pnt);
canvas.drawRect(fw * ix, fh * iy, fw * (ix + 1), fh * (iy + 1), pnt);
}
}
}

View file

@ -58,7 +58,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
private static final int DIALOG_PICKWAYPOINT_ID = 10;
private static final int DIALOG_SELECTBASEDIR_ID = 11;
private static final int DIALOG_MAINACTION_ID = 12;
private static final int DIALOG_OLDDATAHINT_ID = 13;
//private static final int DIALOG_OLDDATAHINT_ID = 13;
private static final int DIALOG_SHOW_REPEAT_TIMEOUT_HELP_ID = 16;
private final Set<Integer> dialogIds = new HashSet<>();
private BRouterView mBRouterView;
@ -133,7 +133,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
switch (id) {
case DIALOG_SELECTPROFILE_ID:
builder.setTitle("Select a routing profile");
builder.setTitle(R.string.action_select_profile);
builder.setItems(availableProfiles, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
selectedProfile = availableProfiles[item];
@ -142,9 +142,9 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
});
return builder.create();
case DIALOG_MAINACTION_ID:
builder.setTitle("Select Main Action");
builder.setTitle(R.string.main_action);
builder.setItems(
new String[]{"Download Manager", "BRouter App"},
new String[]{getString(R.string.main_action_1), getString(R.string.main_action_2)},
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if (item == 0)
@ -153,7 +153,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
showADialog(DIALOG_SELECTPROFILE_ID);
}
})
.setNegativeButton("Close", new DialogInterface.OnClickListener() {
.setNegativeButton(getString(R.string.close), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
@ -161,19 +161,15 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
return builder.create();
case DIALOG_SHOW_DM_INFO_ID:
builder
.setTitle("BRouter Download Manager")
.setMessage(
"*** Attention: ***\n\n" + "The Download Manager is used to download routing-data "
+ "files which can be up to 170MB each. Do not start the Download Manager "
+ "on a cellular data connection without a data plan! "
+ "Download speed is restricted to 16 MBit/s.")
.setPositiveButton("I know", new DialogInterface.OnClickListener() {
.setTitle(R.string.title_download)
.setMessage(R.string.summary_download)
.setPositiveButton(R.string.i_know, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent intent = new Intent(BRouterActivity.this, BInstallerActivity.class);
startActivity(intent);
showNewDialog(DIALOG_MAINACTION_ID);
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
}).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
@ -181,18 +177,15 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
return builder.create();
case DIALOG_SHOW_REPEAT_TIMEOUT_HELP_ID:
builder
.setTitle("Successfully prepared a timeout-free calculation")
.setMessage(
"You successfully repeated a calculation that previously run into a timeout "
+ "when started from your map-tool. If you repeat the same request from your "
+ "maptool, with the exact same destination point and a close-by starting point, "
+ "this request is guaranteed not to time out.")
.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
.setTitle(R.string.title_timeoutfree)
.setMessage(R.string.summary_timeoutfree)
.setNegativeButton(R.string.exit, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
});
return builder.create();
/*
case DIALOG_OLDDATAHINT_ID:
builder
.setTitle("Local setup needs reset")
@ -202,12 +195,13 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
+ "Before downloading new datafiles made for the new table, "
+ "you have to reset your local setup by 'moving away' (or deleting) "
+ "your <basedir>/brouter directory and start a new setup by calling the " + "BRouter App again.")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
});
return builder.create();
*/
case DIALOG_ROUTINGMODES_ID:
builder.setTitle(message);
builder.setMultiChoiceItems(routingModes, routingModesChecked,
@ -217,7 +211,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
routingModesChecked[which] = isChecked;
}
});
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mBRouterView.configureService(routingModes, routingModesChecked);
}
@ -225,9 +219,9 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
return builder.create();
case DIALOG_EXCEPTION_ID:
builder
.setTitle("An Error occured")
.setTitle(R.string.error)
.setMessage(errorMessage)
.setPositiveButton("OK",
.setPositiveButton(R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mBRouterView.continueProcessing();
@ -235,12 +229,12 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
});
return builder.create();
case DIALOG_TEXTENTRY_ID:
builder.setTitle("Enter SDCARD base dir:");
builder.setTitle(R.string.title_sdcard);
builder.setMessage(message);
final EditText input = new EditText(this);
// input.setText(defaultbasedir);
builder.setView(input);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String basedir = input.getText().toString();
mBRouterView.startSetup(new File(basedir), true, false);
@ -248,7 +242,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
});
return builder.create();
case DIALOG_SELECTBASEDIR_ID:
builder.setTitle("Choose brouter data base dir:");
builder.setTitle(getString(R.string.action_choose_folder));
// builder.setMessage( message );
builder.setSingleChoiceItems(basedirOptions, 0, new DialogInterface.OnClickListener() {
@Override
@ -256,7 +250,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
selectedBasedir = item;
}
});
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
if (selectedBasedir < availableBasedirs.size()) {
mBRouterView.startSetup(availableBasedirs.get(selectedBasedir), true, false);
@ -267,7 +261,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
});
return builder.create();
case DIALOG_VIASELECT_ID:
builder.setTitle("Check VIA Selection:");
builder.setTitle(R.string.action_via_select);
builder.setMultiChoiceItems(availableVias, getCheckedBooleanArray(availableVias.length),
new DialogInterface.OnMultiChoiceClickListener() {
@Override
@ -279,7 +273,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
}
}
});
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mBRouterView.updateViaList(selectedVias);
mBRouterView.startProcessing(selectedProfile);
@ -287,7 +281,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
});
return builder.create();
case DIALOG_NOGOSELECT_ID:
builder.setTitle("Check NoGo Selection:");
builder.setTitle(R.string.action_nogo_select);
String[] nogoNames = new String[nogoList.size()];
for (int i = 0; i < nogoList.size(); i++)
nogoNames[i] = nogoList.get(i).name;
@ -299,7 +293,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
nogoEnabled[which] = isChecked;
}
});
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mBRouterView.updateNogoList(nogoEnabled);
mBRouterView.startProcessing(selectedProfile);
@ -325,21 +319,21 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
List<String> slist = new ArrayList<>();
// Neutral button
if (wpCount == 0) {
slist.add("Server-Mode");
slist.add(getString(R.string.action_servermode));
} else if (wpCount == -3) {
slist.add("Info");
slist.add(getString(R.string.action_info));
} else if (wpCount >= 2) {
slist.add("Calc Route");
slist.add(getString(R.string.action_calc_route));
}
if (wpCount == 0) {
slist.add("Profile Settings");
slist.add(getString(R.string.action_profile_settings));
}
// Positive button
if (wpCount == -3 || wpCount == -1) {
slist.add("Share GPX");
slist.add(getString(R.string.action_share));
} else if (wpCount >= 0) {
String selectLabel = wpCount == 0 ? "Select from" : "Select to/via";
String selectLabel = wpCount == 0 ? getString(R.string.action_select_from) : getString(R.string.action_select_to);
slist.add(selectLabel);
}
@ -407,16 +401,16 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
*/
// Negative button
builder.setNegativeButton("Exit", (dialog, which) -> {
builder.setNegativeButton(R.string.exit, (dialog, which) -> {
finish();
});
return builder.create();
case DIALOG_MODECONFIGOVERVIEW_ID:
builder
.setTitle("Success")
.setTitle(R.string.success)
.setMessage(message)
.setPositiveButton("Exit",
.setPositiveButton(R.string.exit,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
@ -424,7 +418,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
});
return builder.create();
case DIALOG_PICKWAYPOINT_ID:
builder.setTitle(wpCount > 0 ? "Select to/via" : "Select from");
builder.setTitle(wpCount == 0 ? getString(R.string.action_select_from) : getString(R.string.action_select_to));
builder.setItems(availableWaypoints, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
mBRouterView.updateWaypointList(availableWaypoints[item]);
@ -472,11 +466,11 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
//startActivityForResult(i, 100);
someActivityResultLauncher.launch(i);
} else {
Toast.makeText(this, "no profile data", Toast.LENGTH_LONG).show();
Toast.makeText(this, R.string.msg_no_profile, Toast.LENGTH_LONG).show();
finish();
}
} else {
Toast.makeText(this, selectedProfile + ", no used profile", Toast.LENGTH_LONG).show();
Toast.makeText(this, selectedProfile + getString(R.string.msg_no_used_profile), Toast.LENGTH_LONG).show();
finish();
}
}

View file

@ -96,11 +96,13 @@ public class BRouterService extends Service {
if (errMsg != null) {
return errMsg;
}
// profile is already done
params.remove("profile");
boolean canCompress = "true".equals(params.getString("acceptCompressedResult"));
try {
String gpxMessage = worker.getTrackFromParams(params);
if (canCompress && gpxMessage.startsWith("<")) {
if (canCompress && (gpxMessage.startsWith("<") || gpxMessage.startsWith("{"))) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write("z64".getBytes(Charset.forName("UTF-8"))); // marker prefix
@ -271,6 +273,7 @@ public class BRouterService extends Service {
}
}
@SuppressWarnings("deprecation")
private void logBundle(Bundle params) {
if (AppLogger.isLogging()) {
for (String k : params.keySet()) {

View file

@ -380,14 +380,14 @@ public class BRouterView extends View {
try {
cor.readAllPoints();
} catch (Exception e) {
msg = "Error reading waypoints: " + e;
msg = getContext().getString(R.string.msg_read_wpt_error)+ ": " + e;
}
int size = cor.allpoints.size();
if (size < 1)
msg = "coordinate source does not contain any waypoints!";
msg = getContext().getString(R.string.msg_no_wpt);
if (size > 1000)
msg = "coordinate source contains too much waypoints: " + size + "(please use from/to/via names)";
msg = String.format(getContext().getString(R.string.msg_too_much_wpts), size);
}
if (msg != null) {
@ -471,13 +471,13 @@ public class BRouterView extends View {
if (needsWaypointSelection) {
StringBuilder msg;
if (wpList.size() == 0) {
msg = new StringBuilder("Expecting waypoint selection\n" + "(coordinate-source: " + cor.basedir + cor.rootdir + ")");
msg = new StringBuilder(getContext().getString(R.string.msg_no_wpt_selection) + "(coordinate-source: " + cor.basedir + cor.rootdir + ")");
} else {
msg = new StringBuilder("current waypoint selection:\n");
msg = new StringBuilder(getContext().getString(R.string.msg_wpt_selection));
for (int i = 0; i < wpList.size(); i++)
msg.append(i > 0 ? "->" : "").append(wpList.get(i).name);
}
((BRouterActivity) getContext()).showResultMessage("Select Action", msg.toString(), wpList.size());
((BRouterActivity) getContext()).showResultMessage(getContext().getString(R.string.title_action), msg.toString(), wpList.size());
return;
}
@ -718,8 +718,13 @@ public class BRouterView extends View {
((BRouterActivity) getContext()).showErrorMessage(cr.getErrorMessage());
} else {
String memstat = memoryClass + "mb pathPeak " + ((cr.getPathPeak() + 500) / 1000) + "k";
String result = "version = BRouter-" + getContext().getString(R.string.app_version) + "\n" + "mem = " + memstat + "\ndistance = " + cr.getDistance() / 1000. + " km\n" + "filtered ascend = " + cr.getAscend()
+ " m\n" + "plain ascend = " + cr.getPlainAscend() + " m\n" + "estimated time = " + cr.getTime();
String result = String.format(getContext().getString(R.string.msg_status_result),
getContext().getString(R.string.app_version),
memstat,
Double.toString(cr.getDistance() / 1000.),
Integer.toString(cr.getAscend()),
Integer.toString(cr.getPlainAscend()),
cr.getTime());
rawTrack = cr.getFoundRawTrack();
@ -728,9 +733,9 @@ public class BRouterView extends View {
writeRawTrackToPath(rawTrackPath);
}
String title = "Success";
String title = getContext().getString(R.string.success);
if (cr.getAlternativeIndex() > 0)
title += " / " + cr.getAlternativeIndex() + ". Alternative";
title += " / " + cr.getAlternativeIndex() + ". " + getContext().getString(R.string.msg_alternative);
((BRouterActivity) getContext()).showResultMessage(title, result, rawTrackPath == null ? -1 : -3);
trackOutfile = cr.getOutfile();

View file

@ -12,6 +12,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import btools.router.FormatGpx;
import btools.router.FormatJson;
import btools.router.FormatKml;
import btools.router.OsmNodeNamed;
import btools.router.OsmTrack;
import btools.router.RoutingContext;
@ -33,6 +36,7 @@ public class BRouterWorker {
public List<OsmNodeNamed> nogoPolygonsList;
public String profileParams;
@SuppressWarnings("deprecation")
public String getTrackFromParams(Bundle params) {
int engineMode = 0;
@ -151,42 +155,41 @@ public class BRouterWorker {
if ("kml".equals(rc.outputFormat)) writeFromat = OUTPUT_FORMAT_KML;
if ("json".equals(rc.outputFormat)) writeFromat = OUTPUT_FORMAT_JSON;
}
OsmTrack track = cr.getFoundTrack();
OsmTrack track = null;
track = cr.getFoundTrack();
if (track != null) {
track.exportWaypoints = rc.exportWaypoints;
if (pathToFileResult == null) {
switch (writeFromat) {
case OUTPUT_FORMAT_GPX:
return track.formatAsGpx();
case OUTPUT_FORMAT_KML:
return track.formatAsKml();
return new FormatKml(rc).format(track);
case OUTPUT_FORMAT_JSON:
return track.formatAsGeoJson();
return new FormatJson(rc).format(track);
case OUTPUT_FORMAT_GPX:
default:
return track.formatAsGpx();
return new FormatGpx(rc).format(track);
}
}
}
try {
switch (writeFromat) {
case OUTPUT_FORMAT_GPX:
track.writeGpx(pathToFileResult);
break;
case OUTPUT_FORMAT_KML:
track.writeKml(pathToFileResult);
new FormatKml(rc).write(pathToFileResult, track);
break;
case OUTPUT_FORMAT_JSON:
track.writeJson(pathToFileResult);
new FormatJson(rc).write(pathToFileResult, track);
break;
case OUTPUT_FORMAT_GPX:
default:
track.writeGpx(pathToFileResult);
new FormatGpx(rc).write(pathToFileResult, track);
break;
}
} catch (Exception e) {
return "error writing file: " + e;
}
}
} else { // get other infos
if (cr.getErrorMessage() != null) {
return cr.getErrorMessage();

View file

@ -4,6 +4,7 @@ import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.pm.ServiceInfo;
import android.os.Build;
import android.util.Log;
@ -169,6 +170,9 @@ public class DownloadWorker extends Worker {
}
notificationBuilder.setContentText("Starting Download");
// Mark the Worker as important
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
setForegroundAsync(new ForegroundInfo(NOTIFICATION_ID, notificationBuilder.build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC));
else
setForegroundAsync(new ForegroundInfo(NOTIFICATION_ID, notificationBuilder.build()));
try {
if (DEBUG) Log.d(LOG_TAG, "Download lookup & profiles");

View file

@ -10,6 +10,7 @@ import android.os.Bundle;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
@ -168,6 +169,22 @@ public class RoutingParameterDialog extends AppCompatActivity {
new OnBackInvokedCallback() {
@Override
public void onBackInvoked() {
handleBackPressed();
}
}
);
} else {
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
handleBackPressed();
}
};
getOnBackPressedDispatcher().addCallback(this, callback);
}
}
private void handleBackPressed() {
StringBuilder sb = null;
if (sharedValues != null) {
// fill preference with used params
@ -195,12 +212,7 @@ public class RoutingParameterDialog extends AppCompatActivity {
setResult(Activity.RESULT_OK, i);
finish();
}
}
);
}
}
@Override

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<plurals name="numberOfSegments" tools:ignore="MissingQuantity">
<item quantity="one">%d قطعة</item>
<item quantity="other">%d قطع</item>
</plurals>
<string name="cancel_download">إلغاء التنزيل</string>
<string name="import_profile">استيراد ملف تعريف</string>
<string name="action_download">تنزيل %s</string>
<string name="action_delete">حذف %s</string>
<string name="action_update">تحديث %s</string>
<string name="action_select">حدد القطع</string>
<string name="action_cancel">إيقاف التنزيل</string>
<string name="summary_segments">الحجم=%1$s\nالحجم المتوفر=%2$s</string>
<string name="notification_title">تحميل القطع</string>
<string name="action_choose_folder">اختر مكان قاعدة بيانات brouter:</string>
<string name="action_select_profile">اختر ملف تعريف التوجيه</string>
<string name="main_action">حدد الإجراء الرئيسي</string>
<string name="main_action_1">مدير التنزيلات</string>
<string name="main_action_2">تطبيق BRouter</string>
<string name="cancel">إلغاء</string>
<string name="i_know">أعرف ذلك</string>
<string name="close">إغلاق</string>
<string name="exit">خروج</string>
<string name="ok">موافق</string>
<string name="success">تم بنجاح</string>
<string name="error">حدث خطأ ما</string>
<string name="title_download">مدير تنزيلات BRouter</string>
<string name="summary_download">*** تحذير:***
\n\nيتم استخدام مدير التنزيل لتنزيل ملفات بيانات التوجيه عبر الطرق
والتي يمكن أن يصل حجمها إلى 170 ميجابايت، لذلك لا تقم بتشغيل
"مدير التنزيلات" حينما تكون متصلاً عبر البيانات الخلوية ومحدوداً بحجم التنزيلات!
سرعة التنزيل محدودة على 16 ميجابايت/بالثانية.</string>
<string name="title_timeoutfree">أنجزت عملية الحساب بنجاح وبدون تأخير</string>
<string name="summary_timeoutfree">لقد نجحت في تكرار عملية حسابية كانت قد انتهت في السابق
عند بدايتها من خلال أداة الخريطة، إذا قمت بتكرار نفس الطلب من
أداة الخريطة الخاصة بك ومع نفس الوجهة بالضبط وبنقطة بداية
قريبة، فسيضمن لك التطبيق عدم انتهاء مهلة هذا الطلب.</string>
<string name="title_sdcard">أدخل مسار الذاكرة الخارجية:</string>
<string name="title_action">اختر الإجراء</string>
<string name="action_via_select">التحقق من النقاط الوسيطة:</string>
<string name="action_nogo_select">التحقق من النقاط المسبتعدة:</string>
<string name="action_servermode">وضع-الخادم</string>
<string name="action_info">معلومات</string>
<string name="action_calc_route">حساب الطريق</string>
<string name="action_profile_settings">إعدادات ملف التعريف</string>
<string name="action_share">مشاركة ملف GPX</string>
<string name="action_select_from">اختر من</string>
<string name="action_select_to">اختر إلى/عبر</string>
<string name="msg_no_profile">لا توجد بيانات ملف التعريف</string>
<string name="msg_no_used_profile">، لا يوجد ملف تعريف مستخدم</string>
<string name="msg_too_much_data">هناك الكثير من البيانات للتنزيل، من فضلك قم بتقليلها.</string>
<string name="msg_download_start">تمت جدولة التنزيل، وتحقق من اتصالك بالإنترنت إذا لم يبدأ التنزيل.</string>
<string name="msg_wpt_selection">نقاط الطريق الحالية المحددة:\n</string>
<string name="msg_no_wpt_selection">نقاط الطريق المتوقعة المحددة\n</string>
<string name="msg_alternative">البديل</string>
<string name="msg_status_result">الإصدار = BRouter-%1$s \n
الذاكرة = %2$s \n
المسافة = %3$s كم\n
التصاعد المرشح = %4$s م\n
التصاعد العادي = %5$s م\n
الوقت المقدر = %6$s</string>
<string name="msg_read_wpt_error">خطأ في قراءة نقاط الطريق</string>
<string name="msg_no_wpt">لا يحتوي مصدر الإحداثيات على أي نقاط الطريق!</string>
<string name="msg_too_much_wpts">مصدر الإحداثيات يحتوي على عدد كبير جدًا من نقاط الطريق: %1$d (يرجى استخدام أسماء النقاط من/إلى/عبر from/to/via)</string>
<string name="no">لا</string>
<string name="yes">نعم</string>
<string name="title_delete">تأكيد الحذف</string>
<string name="summary_delete">هل ترغب بالحذف؟</string>
<string name="title_version">مشكلة في الإصدار</string>
<string name="summary_version">لقد تغير الإصدار الأساسي للصور المتجانبة، ما الإجراء المناسب لفعله؟</string>
<string name="action_version1">متابعة التنزيل الحالي، وحذف البيانات الأخرى القديمة</string>
<string name="action_version2">تحديد الكل للتنزيل والبدء</string>
<string name="action_version3">قم بالإلغاء في الوقت الحالي، واستكمله لاحقاً</string>
<string name="title_version_diff">اختلافات الإصدارات</string>
<string name="summary_version_diff">الإصدار الأساسي لبعض الصور المتجانبة مختلف. ما الإجراء المناسب لفعله؟</string>
<string name="action_version_diff1">تحميل المختلف من الصور المتجانبة</string>
<string name="action_version_diff2">حذف كل الصور المتجانبة المختلفة عن الأخرى</string>
<string name="action_version_diff3">قم بالإلغاء في الوقت الحالي، واستكمله لاحقاً</string>
<string name="summary_new_version">يحتاج إصدار البيانات الجديد إلى وجود التطبيق الجديد، لذا نرجوا منك تحديث BRouter أولاً</string>
<string name="msg_download_failed">فشل التنزيل</string>
<string name="msg_download_cancel">تم إلغاء التنزيل</string>
<string name="msg_download_succeed">تم التنزيل بنجاح</string>
<string name="msg_download_started">جار التنزيل…</string>
</resources>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<plurals name="numberOfSegments" tools:ignore="MissingQuantity">
<item quantity="one">%d segment</item>
<item quantity="other">%d segments</item>
</plurals>
<string name="cancel_download">Cancel·lar descàrrega</string>
<string name="import_profile">Importar perfil</string>
<string name="action_download">Descàrrega %s</string>
<string name="action_delete">Eliminar %s</string>
<string name="action_update">Actualitzar %s</string>
<string name="action_select">Seleccionar segments</string>
<string name="action_cancel">Aturar Descàrrega</string>
<string name="summary_segments">Espai=%1$s\nLliure=%2$s</string>
<string name="notification_title">Descarregar segments</string>
<string name="action_choose_folder">Escollir directori base brouter:</string>
<string name="action_select_profile">Seleccionar un perfil d\'enrutament</string>
<string name="main_action">Seleccionar Acció Principal</string>
<string name="main_action_1">Gestor de Baixades</string>
<string name="main_action_2">App BRouter</string>
<string name="cancel">Cancel·lar</string>
<string name="i_know">Ho sé</string>
<string name="close">Tancar</string>
<string name="exit">Sortir</string>
<string name="ok">D\'acord</string>
<string name="success">Èxit</string>
<string name="error">Ha aparegut un error</string>
<string name="title_download">Gestor de baixades BRouter</string>
<string name="summary_download">*** Atenció:***
\n\nEl Gestor de Baixades es fa servir per descarregar fitxers de dades
d\'enrutament, que poden arribar als 170 Mb cadascun. No inicies el Gestor
des d\'un mòbil sense un pla de dades!
La velocitat de baixada està limitada a 16 Mbit/s.</string>
<string name="title_timeoutfree">S\'ha preparat correctament un càlcul sense límit de temps</string>
<string name="summary_timeoutfree">S\'ha repetit amb èxit un càlcul a través
de l\'aplicació de cartografia que prèviament havia superat el temps d\'espera.
Si repeteixes la mateixa petició amb exactament el mateix destí i un punt de partida proper,
es garanteix que la petició no esgotarà el límit de temps.</string>
<string name="title_sdcard">Introdueix el directori base de la tarja SD:</string>
<string name="title_action">Seleccionar Acció</string>
<string name="action_via_select">Comprovar Selecció VIA:</string>
<string name="action_nogo_select">Comprovar Selecció NoGo:</string>
<string name="action_servermode">Mode-Servidor</string>
<string name="action_info">Info</string>
<string name="action_calc_route">Calc Ruta</string>
<string name="action_profile_settings">Ajustaments del perfil</string>
<string name="action_share">Compartir GPX</string>
<string name="action_select_from">Seleccionar des de</string>
<string name="action_select_to">Seleccionar a/via</string>
<string name="msg_no_profile">no hi ha dades al perfil</string>
<string name="msg_no_used_profile">, cap perfil utilitzat</string>
<string name="msg_too_much_data">Massa dades per baixar. Si us plau, redueix-les.</string>
<string name="msg_download_start">Baixada programada. Comprovar la connexió a internet si no comença.</string>
<string name="msg_wpt_selection">selecció actual de fita:\n</string>
<string name="msg_no_wpt_selection">Esperant selecció de fita\n</string>
<string name="msg_alternative">Alternativa</string>
<string name="msg_status_result">versió = BRouter-%1$s \n
memòria = %2$s \n
distància = %3$s km\n
ascensió filtrada = %4$s m\n
ascens en pla = %5$s m\n
temps estimat = %6$s</string>
<string name="msg_read_wpt_error">Error llegint fites</string>
<string name="msg_no_wpt">la font de coordenades no conté cap fita!</string>
<string name="msg_too_much_wpts">la font de coordenades conté massa fites: %1$d (si us plau, fes servir noms des de/a/via)</string>
<string name="no">No</string>
<string name="yes">Si</string>
<string name="title_delete">Confirmar Eliminar</string>
<string name="summary_delete">Voleu realment eliminar?</string>
<string name="title_version">Problema de versió</string>
<string name="summary_version">La versió base per les tesel·les ha canviat. Què vols fer?</string>
<string name="action_version1">Continuar amb la baixada, eliminar altres dades antigues</string>
<string name="action_version2">Seleccionar-ho tot per baixar i iniciar</string>
<string name="action_version3">Cancel·lar ara, completar un altre dia</string>
<string name="title_version_diff">Diferències de Versió</string>
<string name="summary_version_diff">La versió base de diverses tesel·les és diferent. Què vols fer?</string>
<string name="action_version_diff1">Baixar totes les tesel·les diferents</string>
<string name="action_version_diff2">Descartar les tesel·les diferents</string>
<string name="action_version_diff3">Cancel·lar ara, completar un altre dia</string>
<string name="summary_new_version">La nova versió de dades necessita una aplicació nova. Sisplau, actualitza BRouter primer</string>
<string name="msg_download_failed">Baixada fallida</string>
<string name="msg_download_cancel">Baixada cancel·lada</string>
<string name="msg_download_succeed">Baixada exitosa</string>
<string name="msg_download_started">Baixant…</string>
</resources>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<plurals name="numberOfSegments" tools:ignore="MissingQuantity">
<item quantity="one">%d Segment</item>
<item quantity="other">%d Segmente</item>
</plurals>
<string name="cancel_download">Download abbrechen</string>
<string name="import_profile">Profil importieren</string>
<string name="action_download">%s downloaden</string>
<string name="action_delete">%s löschen</string>
<string name="action_update">%s aktualisieren</string>
<string name="action_select">Segmente auswählen</string>
<string name="action_cancel">Download stoppen</string>
<string name="summary_segments">Größe=%1$s\nFrei=%2$s</string>
<string name="notification_title">Segmente herunterladen</string>
<string name="action_choose_folder">BRouter-Datenbankverzeichnis wählen:</string>
<string name="action_select_profile">Routenprofil wählen</string>
<string name="main_action">Standardaktion wählen</string>
<string name="main_action_1">Downloadmanager</string>
<string name="main_action_2">BRouter-App</string>
<string name="cancel">Abbrechen</string>
<string name="i_know">Ich weiß</string>
<string name="close">Schließen</string>
<string name="exit">Verlassen</string>
<string name="ok">OK</string>
<string name="success">Erfolg</string>
<string name="error">Ein Fehler ist aufgetreten</string>
<string name="title_download">BRouter Downloadmanager</string>
<string name="summary_download">*** Achtung:***
\n\nDer Downloadmanager wird zum Herunterladen von Routingdaten verwendet
die jeweils bis zu 170MB groß sein können. Starten Sie den Downloadmanager
nicht auf Mobiltelefonen ohne Mobilfunktdatentarif!
Die Downloadgeschwindigkeit ist auf 16 MBit/s begrenzt.</string>
<string name="title_timeoutfree">Berechnung ohne Zeitüberschreitung erfolgreich</string>
<string name="summary_timeoutfree">Sie haben eine Berechnung erfolgreich wiederholt, bei
der zuvor beim Start von Ihrem Karten-Tool aus eine Zeitüberschreitung auftrat.
Wenn Sie dieselbe Anfrage von Ihrem Karten-Tool aus wiederholen, mit genau demselben
Zielpunkt und einem nahe gelegenen Startpunkt, wird diese Anfrage garantiert nicht abbrechen.</string>
<string name="title_sdcard">SD-Karten Verzeichnis wählen:</string>
<string name="title_action">Aktion wählen</string>
<string name="action_via_select">Via-Auswahl prüfen:</string>
<string name="action_nogo_select">NoGo-Auswahl prüfen:</string>
<string name="action_servermode">Server-Modus</string>
<string name="action_info">Info</string>
<string name="action_calc_route">Route berechnen</string>
<string name="action_profile_settings">Profileinstellungen</string>
<string name="action_share">GPX teilen</string>
<string name="action_select_from">"Von" wählen</string>
<string name="action_select_to">"Nach"/Via wählen</string>
<string name="msg_no_profile">Keine Profildaten</string>
<string name="msg_no_used_profile">, kein verwendetes Profil</string>
<string name="msg_too_much_data">Zu viele Daten für den Download. Bitte reduzieren.</string>
<string name="msg_download_start">Download geplant. Überprüfen Sie die Internetverbindung, wenn der Download nicht startet.</string>
<string name="msg_wpt_selection">aktuelle Wegpunktauswahl:\n</string>
<string name="msg_no_wpt_selection">Erwarte Wegpunktauswahl\n</string>
<string name="msg_alternative">Alternative</string>
<string name="msg_status_result">Version = BRouter-%1$s\n
Speicher = %2$s \n
Abstand = %3$s km\n
gefilterter Aufstieg = %4$s m\n
flacher Aufstieg = %5$s m\n
geschätzte Zeit = %6$s</string>
<string name="msg_read_wpt_error">Fehler beim Lesen von Wegpunkten</string>
<string name="msg_no_wpt">Die Koordinatenquelle enthält keine Wegpunkte!</string>
<string name="msg_too_much_wpts">Die Koordinatenquelle enthält zu viele Wegpunkte: %1$d (bitte von/nach/via-Namen verwenden)</string>
<string name="no">Nein</string>
<string name="yes">Ja</string>
<string name="title_delete">Löschen bestätigen</string>
<string name="summary_delete">Wirklich löschen?</string>
<string name="title_version">Versionsproblem</string>
<string name="summary_version">Die Datenversion der Kacheln hat sich geändert. Bitte auswählen:</string>
<string name="action_version1">Download fortsetzen und alte Daten löschen?</string>
<string name="action_version2">Alle auswählen und Download starten</string>
<string name="action_version3">Abbrechen und später fortsetzen</string>
<string name="title_version_diff">Versionskonflikt</string>
<string name="summary_version_diff">Die Datenversion für einige Kacheln ist unterschiedlich. Bitte auswählen:</string>
<string name="action_version_diff1">Download alle unterschiedlichen Kacheln</string>
<string name="action_version_diff2">Überspringe alle unterschiedlichen Kacheln</string>
<string name="action_version_diff3">Abbrechen und später fortsetzen</string>
<string name="summary_new_version">Die neue Datenversion verlangt ein BRouter-Update. Bitte aktualisieren</string>
<string name="msg_download_failed">Download fehlgeschlagen</string>
<string name="msg_download_cancel">Download abgebrochen</string>
<string name="msg_download_succeed">Download erfolgreich</string>
<string name="msg_download_started">Download läuft…</string>
</resources>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<plurals name="numberOfSegments" tools:ignore="MissingQuantity">
<item quantity="one">%d τμήμα</item>
<item quantity="other">%d τμήματα</item>
</plurals>
<string name="cancel_download">Ακύρωση λήψης</string>
<string name="import_profile">Εισαγωγή προφίλ</string>
<string name="action_download">Λήψη %s</string>
<string name="action_delete">Διαγραφή %s</string>
<string name="action_update">Ενημέρωση %s</string>
<string name="action_select">Επιλογή τμημάτων</string>
<string name="action_cancel">Διακοπή λήψης</string>
<string name="summary_segments">Μέγεθος=%1$s\nΕλεύθερο=%2$s</string>
<string name="notification_title">Λήψη τμημάτων</string>
<string name="action_choose_folder">Επιλέξτε φάκελο δεδομένων brouter:</string>
<string name="action_select_profile">Επιλέξτε ένα προφίλ δρομολόγησης</string>
<string name="main_action">Επιλέξτε ενέργεια</string>
<string name="main_action_1">Διαχειριστής λήψεων</string>
<string name="main_action_2">Εφαρμογή BRouter</string>
<string name="cancel">Ακύρωση</string>
<string name="i_know">Γνωρίζω</string>
<string name="close">Κλείσιμο</string>
<string name="exit">Έξοδος</string>
<string name="ok">OK</string>
<string name="success">Επιτυχία</string>
<string name="error">Παρουσιάστηκε σφάλμα</string>
<string name="title_download">BRouter διαχειριστής λήψεων</string>
<string name="summary_download">*** Προσοχή:***
\n\nΟ διαχειριστής λήψεων χρησιμοποιείται για τη λήψη αρχείων δεδομένων δρομολόγησης
που μπορεί να είναι έως 170MB το καθένα. Μην ξεκινήσετε το διαχειριστή λήψεων
σε σύνδεση δεδομένων κινητής τηλεφωνίας χωρίς πρόγραμμα δεδομένων!
Η ταχύτητα λήψης περιορίζεται στα 16 MBit/s.</string>
<string name="title_timeoutfree">Ετοιμάστηκε επιτυχώς ένας υπολογισμός χωρίς χρονικό όριο</string>
<string name="summary_timeoutfree">Επαναλάβατε με επιτυχία έναν υπολογισμό που πριν είχε χρονικό όριο
όταν ξεκίνησε από το εργαλείο χαρτών σας. Εάν επαναλάβετε το ίδιο αίτημα
από το εργαλείο χαρτών σας, με τον ίδιο ακριβώς προορισμό και μια κοντινή αφετηρία,
αυτό το αίτημα είναι εγγυημένο ότι δεν θα λήξει.</string>
<string name="title_sdcard">Εισάγετε φάκελο SDCARD:</string>
<string name="title_action">Επιλέξτε ενέργεια</string>
<string name="action_via_select">Ελέγξτε την επιλογή VIA:</string>
<string name="action_nogo_select">Ελέγξτε την επιλογή NoGo:</string>
<string name="action_servermode">Λειτουργία διακομιστή</string>
<string name="action_info">Πληροφορίες</string>
<string name="action_calc_route">Υπολογισμός διαδρομής</string>
<string name="action_profile_settings">Ρυθμίσεις προφίλ</string>
<string name="action_share">Κοινή χρήση GPX</string>
<string name="action_select_from">Επιλέξτε από</string>
<string name="action_select_to">Επιλέξτε προς/μέσω</string>
<string name="msg_no_profile">μη δεδομένα προφίλ</string>
<string name="msg_no_used_profile">, μη χρησιμοποιημένο προφίλ</string>
<string name="msg_too_much_data">Πάρα πολλά δεδομένα για λήψη. Παρακαλώ μειώστε.</string>
<string name="msg_download_start">Προγραμματισμένη λήψη. Ελέγξτε τη σύνδεση στο διαδίκτυο εάν δεν ξεκινά.</string>
<string name="msg_wpt_selection">τρέχουσα επιλογή σημείου:\n</string>
<string name="msg_no_wpt_selection">Αναμένεται επιλογή σημείου\n</string>
<string name="msg_alternative">Εναλλακτική</string>
<string name="msg_status_result">έκδοση = BRouter-%1$s \n
μνήμη = %2$s \n
απόσταση = %3$s km\n
φιλτραρισμένη άνοδος = %4$s m\n
απλή άνοδος = %5$s m\n
εκτιμώμενος χρόνος = %6$s</string>
<string name="msg_read_wpt_error">Σφάλμα ανάγνωσης σημείων</string>
<string name="msg_no_wpt">η πηγή συντεταγμένων δεν περιέχει σημεία!</string>
<string name="msg_too_much_wpts">η πηγή συντεταγμένων περιέχει πάρα πολλά σημεία: %1$d (παρακαλώ χρησιμοποιήστε από/προς/μέσω ονόματα)</string>
<string name="no">Όχι</string>
<string name="yes">Ναι</string>
<string name="title_delete">Επιβεβαίωση διαγραφής</string>
<string name="summary_delete">Να γίνει διαγραφή;</string>
<string name="title_version">Πρόβλημα έκδοσης</string>
<string name="summary_version">Η βασική έκδοση για τμήματα άλλαξε. Τι να κάνετε;</string>
<string name="action_version1">Συνέχεια με την τρέχουσα λήψη, διαγραφή άλλων παλαιών δεδομένων</string>
<string name="action_version2">Επιλέξτε όλα για λήψη και έναρξη</string>
<string name="action_version3">Ακύρωση τώρα, ολοκλήρωση άλλη μέρα</string>
<string name="title_version_diff">Διαφορές έκδοσης</string>
<string name="summary_version_diff">Η βασική έκδοση για ορισμένα τμήματα είναι διαφορετική. Τι να κάνετε;</string>
<string name="action_version_diff1">Λήψη όλων των διαφορετικών τμημάτων</string>
<string name="action_version_diff2">Απόρριψη όλων των διαφορετικών τμημάτων</string>
<string name="action_version_diff3">Ακύρωση τώρα, ολοκλήρωση άλλη μέρα</string>
<string name="summary_new_version">Η νέα έκδοση δεδομένων χρειάζεται νέα εφαρμογή. Ενημερώστε πρώτα το BRouter</string>
<string name="msg_download_failed">Η λήψη απέτυχε</string>
<string name="msg_download_cancel">Η λήψη ακυρώθηκε</string>
<string name="msg_download_succeed">Η λήψη ολοκληρώθηκε</string>
<string name="msg_download_started">Λήψη…</string>
</resources>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<plurals name="numberOfSegments" tools:ignore="MissingQuantity">
<item quantity="one">%d segmento</item>
<item quantity="other">%d segmentos</item>
</plurals>
<string name="cancel_download">Cancelar descarga</string>
<string name="import_profile">Importar perfil</string>
<string name="action_download">Descargar %s</string>
<string name="action_delete">Eliminar %s</string>
<string name="action_update">Actualizar %s</string>
<string name="action_select">Seleccionar segmentos</string>
<string name="action_cancel">Detener descarga</string>
<string name="summary_segments">Tamaño=%1$s\nGratis=%2$s</string>
<string name="notification_title">Descargar segmentos</string>
<string name="action_choose_folder">Seleccionar directorio base brouter:</string>
<string name="action_select_profile">Seleccionar un perfil de enrutamiento</string>
<string name="main_action">Seleccionar Acción Principal</string>
<string name="main_action_1">Gestor de Descargas</string>
<string name="main_action_2">App BRouter</string>
<string name="cancel">Cancelar</string>
<string name="i_know">Lo se</string>
<string name="close">Cerrar</string>
<string name="exit">Salir</string>
<string name="ok">OK</string>
<string name="success">Salir</string>
<string name="error">Ha aparecido un error</string>
<string name="title_download">Gestor de descargas BRouter</string>
<string name="summary_download">*** Atención:***
\n\nEl Gestor de Descargas se usa para descargar ficheros de datos
de ruta, que pueden llegar a los 170 Mb cada uno. No inicies el Gestor
desde un terminal sin plan de datos!
La velocidad de descarga está limitada a 16 Mbit/s.</string>
<string name="title_timeoutfree">Se ha preparado correctamente un cálculo sin límite de tiempo</string>
<string name="summary_timeoutfree">Se ha repetido un cálculo a través
de la aplicación de mapas que previamente había superado el tiempo de espera.
Si repites la misma petición con exactamente el mismo destino y un punto de partida cercano,
se garantiza que la petición no agotará el límite de tiempo.</string>
<string name="title_sdcard">Introduce el directorio base de la tarjeta SD:</string>
<string name="title_action">Seleccionar Acción</string>
<string name="action_via_select">Comprobar Selección VIA:</string>
<string name="action_nogo_select">Comprobar Selección NoGo:</string>
<string name="action_servermode">Modo-Servidor</string>
<string name="action_info">Info</string>
<string name="action_calc_route">Calc Ruta</string>
<string name="action_profile_settings">Ajustes del perfil</string>
<string name="action_share">Compartir GPX</string>
<string name="action_select_from">Seleccionar desde</string>
<string name="action_select_to">Seleccionar a/vía</string>
<string name="msg_no_profile">no hay datos en el perfil</string>
<string name="msg_no_used_profile">, ningún perfil utilizado</string>
<string name="msg_too_much_data">Demasiados datos a descargar. Por favor, reducidlos.</string>
<string name="msg_download_start">Descarga programada. Comprueba la conexión a internet si no se inicia.</string>
<string name="msg_wpt_selection">selección actual de waypoint:\n</string>
<string name="msg_no_wpt_selection">Esperando selección de waypoint\n</string>
<string name="msg_alternative">Alternativa</string>
<string name="msg_status_result">versión = BRouter-%1$s \n
memoria = %2$s \n
distancia = %3$s km\n
ascensión filtrada = %4$s m\n
ascensión en llano = %5$s m\n
tiempo estimado = %6$s</string>
<string name="msg_read_wpt_error">Error leyendo waypoints</string>
<string name="msg_no_wpt">la fuente de coordenadas no contiene ningún waypoint!</string>
<string name="msg_too_much_wpts">la fuente de coordenadas contiene demasiados waypoints: %1$d (por favor, usa nombres desde/a/vía)</string>
<string name="no">No</string>
<string name="yes">Si</string>
<string name="title_delete">Confirmar Eliminar</string>
<string name="summary_delete">¿Quieres realmente eliminar?</string>
<string name="title_version">Problema de versión</string>
<string name="summary_version">La versión base para as teselas ha cambiado. ¿Qué quieres hacer?</string>
<string name="action_version1">Continuar con la descarga, eliminar otros datos antiguos</string>
<string name="action_version2">Seleccionar todo para descargar e iniciar</string>
<string name="action_version3">Cancelar ahora, completar otro día</string>
<string name="title_version_diff">Diferencias de versión</string>
<string name="summary_version_diff">La versión base de varias teselas es distinta. ¿Qué quieres hacer?</string>
<string name="action_version_diff1">Descargar todas las teselas distintas</string>
<string name="action_version_diff2">Descartar las teselas distintas</string>
<string name="action_version_diff3">Cancelar ahora, completar otro día</string>
<string name="summary_new_version">La nueva versión de datos necesita un aplicación nueva. Por favor, actualiza BRouter primero</string>
<string name="msg_download_failed">Descarga fallida</string>
<string name="msg_download_cancel">Descarga cancelada</string>
<string name="msg_download_succeed">Descarga exitosa</string>
<string name="msg_download_started">Descargando…</string>
</resources>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<plurals name="numberOfSegments" tools:ignore="MissingQuantity">
<item quantity="one">%d segment</item>
<item quantity="other">%d segments</item>
</plurals>
<string name="cancel_download">Annuler le téléchargement</string>
<string name="import_profile">Importer le profil</string>
<string name="action_download">Télécharger %s</string>
<string name="action_delete">Supprimer %s</string>
<string name="action_update">Mettre à jour %s</string>
<string name="action_select">Sélectionner les segments</string>
<string name="action_cancel">Arrêter le téléchargement</string>
<string name="summary_segments">Taille=%1$s\nGratuit=%2$s</string>
<string name="notification_title">Télécharger les segments</string>
<string name="action_choose_folder">Choisissez le répertoire de la base de données brouter:</string>
<string name="action_select_profile">Sélectionnez un profil de routage</string>
<string name="main_action">Sélectionner l\'action principale</string>
<string name="main_action_1">Gestionnaire de téléchargement</string>
<string name="main_action_2">Application BRouter</string>
<string name="cancel">Annuler</string>
<string name="i_know">Je sais</string>
<string name="close">Fermer</string>
<string name="exit">Quitter</string>
<string name="ok">OK</string>
<string name="success">Succès</string>
<string name="error">Une erreur s\'est produite</string>
<string name="title_download">Gestionnaire de téléchargement BRouter</string>
<string name="summary_download">*** Attention :***
\n\nLe gestionnaire de téléchargement est utilisé pour télécharger les données de routage
fichiers pouvant atteindre 170MB chacun. Ne démarrez pas le gestionnaire de téléchargement
sur une connexion de données cellulaires sans forfait de données !
La vitesse de téléchargement est limitée à 16 MBit/s.</string>
<string name="title_timeoutfree">Préparation réussie d\'un calcul sans délai d\'attente</string>
<string name="summary_timeoutfree">Vous avez répété avec succès un calcul qui avait précédemment expiré
lorsqu\'il est démarré à partir de votre outil cartographique. Si vous répétez la même demande de votre
maptool, avec exactement le même point de destination et un point de départ à proximité,
il est garanti que cette requête n\'expirera pas.</string>
<string name="title_sdcard">Entrez le répertoire de base de la SDCARD:</string>
<string name="title_action">Sélectionner une action</string>
<string name="action_via_select">Vérifier la sélection VIA:</string>
<string name="action_nogo_select">Vérifier la sélection NoGo:</string>
<string name="action_servermode">Mode serveur</string>
<string name="action_info">Informations</string>
<string name="action_calc_route">Calculer l\'itinéraire</string>
<string name="action_profile_settings">Paramètres du profil</string>
<string name="action_share">Partager GPX</string>
<string name="action_select_from">Sélectionner de</string>
<string name="action_select_to">Sélectionner vers/via</string>
<string name="msg_no_profile">aucune donnée de profil</string>
<string name="msg_no_used_profile">, aucun profil utilisé</string>
<string name="msg_too_much_data">Trop de données à télécharger. Veuillez réduire.</string>
<string name="msg_download_start">Téléchargement planifié. Vérifiez la connexion Internet si elle ne démarre pas.</string>
<string name="msg_wpt_selection">sélection actuelle du waypoint:\n</string>
<string name="msg_no_wpt_selection">Sélection de waypoint en attente\n</string>
<string name="msg_alternative">Alternative</string>
<string name="msg_status_result">version = BRouter-%1$s \n
mémoire = %2$s \n
distance = %3$s km\n
montée filtrée = %4$s m\n
montée simple = %5$s m\n
temps estimé = %6$s</string>
<string name="msg_read_wpt_error">Erreur lors de la lecture des waypoints</string>
<string name="msg_no_wpt">la source de coordonnées ne contient aucun waypoint!</string>
<string name="msg_too_much_wpts">la source de coordonnées contient trop de waypoints: %1$d (veuillez utiliser les noms de/vers/via)</string>
<string name="no">Non</string>
<string name="yes">Oui</string>
<string name="title_delete">Confirmer la suppression</string>
<string name="summary_delete">Vraiment supprimer?</string>
<string name="title_version">Problème de version</string>
<string name="summary_version">La version de base des vignettes a changé. Que faire?</string>
<string name="action_version1">Continuer le téléchargement en cours, supprimer les autres anciennes données</string>
<string name="action_version2">Sélectionnez tout pour télécharger et démarrer</string>
<string name="action_version3">Annuler maintenant, terminer un autre jour</string>
<string name="title_version_diff">Différences de version</string>
<string name="summary_version_diff">La version de base de certaines vignettes est différente. Que faire?</string>
<string name="action_version_diff1">Télécharger toutes les différentes vignettes</string>
<string name="action_version_diff2">Supprimez toutes les différentes vignettes</string>
<string name="action_version_diff3">Annuler maintenant, terminer un autre jour</string>
<string name="summary_new_version">La nouvelle version des données nécessite une nouvelle application. Veuillez d\'abord mettre à jour BRouter</string>
<string name="msg_download_failed">Téléchargement échoué</string>
<string name="msg_download_cancel">Téléchargement annulé</string>
<string name="msg_download_succeed">Téléchargement réussi</string>
<string name="msg_download_started">Téléchargement…</string>
</resources>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<plurals name="numberOfSegments" tools:ignore="MissingQuantity">
<item quantity="one">%d segmento</item>
<item quantity="other">%d segmenti</item>
</plurals>
<string name="cancel_download">Annulla download</string>
<string name="import_profile">Importa profilo</string>
<string name="action_download">Scarica %s</string>
<string name="action_delete">Elimina %s</string>
<string name="action_update">Aggiorna %s</string>
<string name="action_select">Seleziona segmenti</string>
<string name="action_cancel">Interrompi download</string>
<string name="summary_segments">Taglia=%1$s\nGratis=%2$s</string>
<string name="notification_title">Scarica segmenti</string>
<string name="action_choose_folder">Seleziona la directory del database brouter:</string>
<string name="action_select_profile">Seleziona un profilo di instradamento</string>
<string name="main_action">Seleziona azione principale</string>
<string name="main_action_1">Gestore dei download</string>
<string name="main_action_2">Applicazione BRouter</string>
<string name="cancel">Annulla</string>
<string name="i_know">Lo so</string>
<string name="close">Chiudi</string>
<string name="exit">Esci</string>
<string name="ok">OK</string>
<string name="success">Successo</string>
<string name="error">Si è verificato un errore</string>
<string name="title_download">Gestore download BRouter</string>
<string name="summary_download">*** Attenzione:***
\n\nIl Download Manager viene utilizzato per scaricare i dati di routing
file che possono pesare fino a 170 MB ciascuno. Non avviare il Download Manager
su una connessione dati cellulare senza un piano dati!
La velocità di download è limitata a 16 MBit/s.</string>
<string name="title_timeoutfree">Preparato con successo un calcolo senza timeout</string>
<string name="summary_timeoutfree">Hai ripetuto con successo un calcolo che in precedenza era terminato con un timeout
quando avviato dal tuo strumento mappa. Se ripeti la stessa richiesta dal tuo
maptool, con lo stesso identico punto di destinazione e un punto di partenza vicino,
è garantito che questa richiesta non vada in timeout.</string>
<string name="title_sdcard">Inserisci la directory base della SDCARD:</string>
<string name="title_action">Seleziona azione</string>
<string name="action_via_select">Controlla la selezione VIA:</string>
<string name="action_nogo_select">Controlla la selezione NoGo:</string>
<string name="action_servermode">Modalità server</string>
<string name="action_info">Informazioni</string>
<string name="action_calc_route">Calcola percorso</string>
<string name="action_profile_settings">Impostazioni profilo</string>
<string name="action_share">Condividi GPX</string>
<string name="action_select_from">Seleziona da</string>
<string name="action_select_to">Seleziona a/via</string>
<string name="msg_no_profile">nessun dato del profilo</string>
<string name="msg_no_used_profile">, nessun profilo utilizzato</string>
<string name="msg_too_much_data">Troppi dati per il download. Per favore riduci.</string>
<string name="msg_download_start">Download programmato. Controlla la connessione Internet se non si avvia.</string>
<string name="msg_wpt_selection">selezione del waypoint corrente:\n</string>
<string name="msg_no_wpt_selection">Attesa selezione waypoint\n</string>
<string name="msg_alternative">Alternativa</string>
<string name="msg_status_result">versione = BRouter-%1$s \n
memoria = %2$s \n
distanza = %3$s km\n
salita filtrata = %4$s m\n
salita semplice = %5$s m\n
tempo stimato = %6$s</string>
<string name="msg_read_wpt_error">Errore durante la lettura dei waypoint</string>
<string name="msg_no_wpt">la fonte delle coordinate non contiene alcun waypoint!</string>
<string name="msg_too_much_wpts">la fonte delle coordinate contiene troppi waypoint: %1$d (usa i nomi da/a/via)</string>
<string name="no">No</string>
<string name="yes"></string>
<string name="title_delete">Conferma eliminazione</string>
<string name="summary_delete">Eliminare davvero?</string>
<string name="title_version">Problema di versione</string>
<string name="summary_version">La versione base per i riquadri è cambiata. Cosa fare?</string>
<string name="action_version1">Continua con il download corrente, elimina altri vecchi dati</string>
<string name="action_version2">Seleziona tutto per il download e avvia</string>
<string name="action_version3">Annulla ora, completa un altro giorno</string>
<string name="title_version_diff">Differenze di versione</string>
<string name="summary_version_diff">La versione base di alcuni riquadri è diversa. Cosa fare?</string>
<string name="action_version_diff1">Scarica tutti i diversi riquadri</string>
<string name="action_version_diff2">Rilascia tutti i diversi riquadri</string>
<string name="action_version_diff3">Annulla ora, completa un altro giorno</string>
<string name="summary_new_version">La nuova versione dei dati necessita di una nuova app. Per favore aggiorna prima BRouter</string>
<string name="msg_download_failed">Download fallito</string>
<string name="msg_download_cancel">Download annullato</string>
<string name="msg_download_succeed">Download riuscito</string>
<string name="msg_download_started">Download in corso…</string>
</resources>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<plurals name="numberOfSegments" tools:ignore="MissingQuantity">
<item quantity="one">%d 구간</item>
<item quantity="other">%d 구간</item>
</plurals>
<string name="cancel_download">다운로드 취소</string>
<string name="import_profile">프로필 가져오기</string>
<string name="action_download">다운로드 %s</string>
<string name="action_delete">삭제 %s</string>
<string name="action_update">업데이트 %s</string>
<string name="action_select">구간 선택</string>
<string name="action_cancel">다운로드 중지</string>
<string name="summary_segments">크기=%1$s\n여유=%2$s</string>
<string name="notification_title">구간 다운로드</string>
<string name="action_choose_folder">brouter 데이터 베이스 선택 dir:</string>
<string name="action_select_profile">루트 프로필 선택</string>
<string name="main_action">주 활동 선택</string>
<string name="main_action_1">다운로드 관리자</string>
<string name="main_action_2">BRouter 앱</string>
<string name="cancel">취소</string>
<string name="i_know">알고 있습니다</string>
<string name="close">가까운</string>
<string name="exit">나가기</string>
<string name="ok">OK</string>
<string name="success">성공</string>
<string name="error">에러가 발생됐습니다</string>
<string name="title_download">BRouter 다운로드 관리자</string>
<string name="summary_download">*** 주의:***
\n\n다운로드 관리자는 라우팅 데이터를 다운로드하는 데 사용됩니다.
파일당 최대 170MB까지 가능합니다. 다운로드 관리자를 시작하지 마십시오
데이터 요금제 없이 셀룰러 데이터 연결로!
다운로드 속도는 16 MBit/s로 제한됩니다.</string>
<string name="title_timeoutfree">시간 초과 없는 계산을 성공적으로 준비했습니다</string>
<string name="summary_timeoutfree">이전에 시간 초과가 발생한 계산을 성공적으로 반복하셨습니다.
지도 도구에서 시작할 때. 귀하가 귀하로부터 동일한 요청을 반복하는 경우
정확히 동일한 목적지와 가까운 시작점이 있는 지도 도구,
이 요청은 시간 초과되지 않음이 보장됩니다.</string>
<string name="title_sdcard">SDCARD 기본 디렉토리 입력:</string>
<string name="title_action">작업 선택</string>
<string name="action_via_select">경유 선택 체크:</string>
<string name="action_nogo_select">NoGo 선택 체크:</string>
<string name="action_servermode">서버-모드</string>
<string name="action_info">정보</string>
<string name="action_calc_route">루트 계산</string>
<string name="action_profile_settings">프로필 설정</string>
<string name="action_share">GPX 공유</string>
<string name="action_select_from">~로부터 선택</string>
<string name="action_select_to">선택 ~로/경유하여</string>
<string name="msg_no_profile">프로필 데이터 없음</string>
<string name="msg_no_used_profile">, 사용된 프로필 없음</string>
<string name="msg_too_much_data">다운로드 하기에 너무 많은 데이터. 줄이도록 하세요.</string>
<string name="msg_download_start">다운로드 계획되어 있음. 인터넷 연결 체크 그렇지 않다면 시작.</string>
<string name="msg_wpt_selection">현재 장소 선택:\n</string>
<string name="msg_no_wpt_selection">장소 선택 기대\n</string>
<string name="msg_alternative">대체 가능한</string>
<string name="msg_status_result">버전 = BRouter-%1$s \n
메모리 = %2$s \n
거리 = %3$s km\n
필터링된 오름차순 = %4$s m\n
일반 오름차순 = %5$s m\n
예상 시간 = %6$s</string>
<string name="msg_read_wpt_error">장소 읽는데 에러</string>
<string name="msg_no_wpt">좌표정보는 어떤 장소도 포함하고 있지 않습니다!</string>
<string name="msg_too_much_wpts">좌표정보는 너무 많은 장소를 포함하고 있습니다: %1$d (~로 부터/~로/경유 이름 사용하세요)</string>
<string name="no">아니요</string>
<string name="yes"></string>
<string name="title_delete">삭제 확인</string>
<string name="summary_delete">정말 삭제하시겠습니까?</string>
<string name="title_version">버전 문제</string>
<string name="summary_version">타일을 위한 기본 버전이 바뀌었습니다. 무엇을 해야죠?</string>
<string name="action_version1">현재 다운로드 계속, 다른 오래된 데이터 삭제</string>
<string name="action_version2">다운로드 위해 모두 선택하고 시작</string>
<string name="action_version3">지금 취소, 다른 날 완료</string>
<string name="title_version_diff">버전 차이</string>
<string name="summary_version_diff">어떤 타일을 위한 기본 버전은 다릅니다, 무엇을 해야죠?</string>
<string name="action_version_diff1">모든 다른 타일 다운로드</string>
<string name="action_version_diff2">모든 다른 타일 백지화</string>
<string name="action_version_diff3">지금 취소, 다른 날 완료</string>
<string name="summary_new_version">새로운 데이터 버전은 새로운 앱을 필요로 합니다. 우선 BRouter를 업데이트 하세요</string>
<string name="msg_download_failed">다운로드 실패</string>
<string name="msg_download_cancel">다운로드 취소됨</string>
<string name="msg_download_succeed">다운로드 성공</string>
<string name="msg_download_started">다운로딩…</string>
</resources>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<plurals name="numberOfSegments" tools:ignore="MissingQuantity">
<item quantity="one">%d segment</item>
<item quantity="other">%d segmenten</item>
</plurals>
<string name="cancel_download">Download annuleren</string>
<string name="import_profile">Profiel importeren</string>
<string name="action_download">Downloaden %s</string>
<string name="action_delete">Verwijderen %s</string>
<string name="action_update">Bijwerken %s</string>
<string name="action_select">Segmenten selecteren</string>
<string name="action_cancel">Download stoppen</string>
<string name="summary_segments">Grootte=%1$s\nGratis=%2$s</string>
<string name="notification_title">Segmenten downloaden</string>
<string name="action_choose_folder">Kies de brouter database map:</string>
<string name="action_select_profile">Selecteer een routingprofiel</string>
<string name="main_action">Selecteer de hoofdactie</string>
<string name="main_action_1">Download beheerder</string>
<string name="main_action_2">BRouter App</string>
<string name="cancel">Annuleer</string>
<string name="i_know">Ik weet het</string>
<string name="close">Sluiten</string>
<string name="exit">Verlaat</string>
<string name="ok">OK</string>
<string name="success">Succes</string>
<string name="error">Er is een fout opgetreden</string>
<string name="title_download">BRouter Download Manager</string>
<string name="summary_download">*** OPgelet:***
\n\nDe Download Manager wordt gebruikt voor het downloaden van routing-gegevens
bestanden die elk maximaal 170 MB groot kunnen zijn. Start de Download Manager
niet op een mobiele dataverbinding zonder data-abonnement!
De downloadsnelheid is beperkt tot 16 MBit/s.</string>
<string name="title_timeoutfree">Een time-outvrije berekening is succesvol voorbereid</string>
<string name="summary_timeoutfree">Je hebt met succes een berekening herhaald die eerder op een time-out
stuitte toen deze vanuit je map tool werd gestart. Als u hetzelfde verzoek herhaalt
vanuit uw map tool, met exact hetzelfde bestemmingspunt en een dichtbijgelegen beginpunt,
zal deze aanvraag gegarandeerd geen time-out krijgen.</string>
<string name="title_sdcard">De SDCARD basis directory invoeren:</string>
<string name="title_action">Actie selecteren</string>
<string name="action_via_select">Controleer de VIA selectie:</string>
<string name="action_nogo_select">Controleer de NoGo selectie:</string>
<string name="action_servermode">Server-mode</string>
<string name="action_info">Info</string>
<string name="action_calc_route">Bereken route</string>
<string name="action_profile_settings">Profiel instellingen</string>
<string name="action_share">GPX delen</string>
<string name="action_select_from">Selecteer van</string>
<string name="action_select_to">Selecteer naar/via</string>
<string name="msg_no_profile">geen profiel data</string>
<string name="msg_no_used_profile">, geen gebruikt profiel</string>
<string name="msg_too_much_data">Te veel gegevens om te downloaden. Verminder a.u.b.</string>
<string name="msg_download_start">Download is gepland. Controleer de internetverbinding als deze niet start.</string>
<string name="msg_wpt_selection">huidige waypointselectie:\n</string>
<string name="msg_no_wpt_selection">Verwacht waypointselectie\n</string>
<string name="msg_alternative">Alternatief</string>
<string name="msg_status_result">versie = BRouter-%1$s \n
geheugen = %2$s \n
afstand = %3$s km\n
gefilterde opstijging = %4$s m\n
simpel opstijging = %5$s m\n
geschatte tijd = %6$s</string>
<string name="msg_read_wpt_error">Fout bij het lezen van waypoints</string>
<string name="msg_no_wpt">coördinaten bron bevat geen waypoints!</string>
<string name="msg_too_much_wpts">De coördinatenbron bevat te veel waypoints: %1$d (gebruik van/naar/via namen)</string>
<string name="no">Nee</string>
<string name="yes">Ja</string>
<string name="title_delete">Verwijderen bevestigen</string>
<string name="summary_delete">Echt verwijderen?</string>
<string name="title_version">Versie probleem</string>
<string name="summary_version">De basisversie voor de tegels is gewijzigd. Wat moet er gebeuren?</string>
<string name="action_version1">Doorgaan met de huidige download, verwijder de oude gegevens.</string>
<string name="action_version2">Selecteer alles om te downloaden en start</string>
<string name="action_version3">Annuleer nu, voltooi op een andere dag</string>
<string name="title_version_diff">Versieverschillen</string>
<string name="summary_version_diff">De basisversie voor sommige tiles is anders. Wat moet er gebeuren?</string>
<string name="action_version_diff1">Download alle verschillende tegels</string>
<string name="action_version_diff2">Laat alle verschillende tegels vallen</string>
<string name="action_version_diff3">Annuleer nu, en voltooi op een andere dag</string>
<string name="summary_new_version">Voor de nieuwe gegevensversie is een nieuwe app nodig. Update eerst de BRouter</string>
<string name="msg_download_failed">Download is mislukt</string>
<string name="msg_download_cancel">Download is geannuleerd</string>
<string name="msg_download_succeed">Download is geslaagd</string>
<string name="msg_download_started">Downloaden…</string>
</resources>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<plurals name="numberOfSegments" tools:ignore="MissingQuantity">
<item quantity="one">%d segment</item>
<item quantity="other">%d segmenty/ów</item>
</plurals>
<string name="cancel_download">Anuluj pobieranie</string>
<string name="import_profile">Importuj profil</string>
<string name="action_download">Pobierz %s</string>
<string name="action_delete">Usuń %s</string>
<string name="action_update">Zaktualizuj %s</string>
<string name="action_select">Wybierz segmenty</string>
<string name="action_cancel">Zatrzymaj pobieranie</string>
<string name="summary_segments">Rozmiar=%1$s\nDostępne=%2$s</string>
<string name="notification_title">Pobieranie segmentów</string>
<string name="action_choose_folder">Wybierz katalog bazy danych BRoutera:</string>
<string name="action_select_profile">Wybierz profil routingu</string>
<string name="main_action">Wybierz akcję główną</string>
<string name="main_action_1">Menedżer pobierania</string>
<string name="main_action_2">Aplikacja BRouter</string>
<string name="cancel">Anuluj</string>
<string name="i_know">Rozumiem</string>
<string name="close">Zamknij</string>
<string name="exit">Wyjdź</string>
<string name="ok">OK</string>
<string name="success">Sukces</string>
<string name="error">Wystąpił błąd</string>
<string name="title_download">Menedżer pobierania BRoutera</string>
<string name="summary_download">*** Uwaga: ***
\n\nMenedżer pobierania służy do pobierania plików danych routingu,
które mogą mieć do 170 MB każdy. Nie uruchamiaj Menedżera pobierania,
jeżeli korzystasz z komórkowej transmisji danych bez planu taryfowego!
Prędkość pobierania jest ograniczona do 16 MBit/s.</string>
<string name="title_timeoutfree">Pomyślnie przygotowano obliczenia nie przekraczając limitu czasu</string>
<string name="summary_timeoutfree">Pomyślnie powtórzono obliczenia, które wcześniej przekroczyły limit czasu
po uruchomieniu z narzędzia mapowego. Jeśli powtórzysz to samo żądanie ze swojego
narzędzia mapowego, z dokładnie tym samym punktem docelowym i pobliskim punktem początkowym,
gwarantuję, że to żądanie nie przekroczy limitu czasu.</string>
<string name="title_sdcard">Wybierz katalog SDCARD dla bazy:</string>
<string name="title_action">Wybierz akcję</string>
<string name="action_via_select">Sprawdź wybór VIA:</string>
<string name="action_nogo_select">Sprawdź wybór NoGo:</string>
<string name="action_servermode">Tryb serwera</string>
<string name="action_info">Informacje</string>
<string name="action_calc_route">Oblicz trasę</string>
<string name="action_profile_settings">Ustawienia profilu</string>
<string name="action_share">Udostępnij GPX</string>
<string name="action_select_from">Wybierz z</string>
<string name="action_select_to">Wybierz do/przez</string>
<string name="msg_no_profile">brak danych profilu</string>
<string name="msg_no_used_profile">, brak używanego profilu</string>
<string name="msg_too_much_data">Za dużo danych do pobrania. Proszę ogranicz.</string>
<string name="msg_download_start">Pobieranie zaplanowane. Jeśli się nie rozpocznie, sprawdź połączenie internetowe.</string>
<string name="msg_wpt_selection">bieżący wybór punktu trasy:\n</string>
<string name="msg_no_wpt_selection">Oczekuję na wybór punktu trasy\n</string>
<string name="msg_alternative">Alternatywa</string>
<string name="msg_status_result">wersja = BRouter-%1$s \n
pamięć = %2$s \n
odległość = %3$s km\n
filtrowane wznoszenie = %4$sm\n
zwykłe wznoszenie = %5$sm\n
szacowany czas = %6$s</string>
<string name="msg_read_wpt_error">Błąd podczas odczytu punktów trasy</string>
<string name="msg_no_wpt">Źródło współrzędnych nie zawiera żadnych punktów trasy!</string>
<string name="msg_too_much_wpts">Źródło współrzędnych zawiera zbyt dużo punktów trasy: %1$d (proszę używać nazw z/do/przez)</string>
<string name="no">Nie</string>
<string name="yes">Tak</string>
<string name="title_delete">Potwierdź usunięcie</string>
<string name="summary_delete">Naprawdę usunąć?</string>
<string name="title_version">Problem z wersją</string>
<string name="summary_version">Zmieniła się podstawowa wersja kafelków. Co robić?</string>
<string name="action_version1">Kontynuuj bieżące pobieranie, usuń inne stare dane</string>
<string name="action_version2">Wybierz wszystko i rozpocznij pobieranie</string>
<string name="action_version3">Anuluj teraz, dokończ innego dnia</string>
<string name="title_version_diff">Różnice wersji</string>
<string name="summary_version_diff">Wersja podstawowa dla niektórych kafelków jest inna. Co robić?</string>
<string name="action_version_diff1">Pobierz różne kafelki</string>
<string name="action_version_diff2">Opuść wszystkie różne kafelki</string>
<string name="action_version_diff3">Anuluj teraz, dokończ innego dnia</string>
<string name="summary_new_version">Nowa wersja danych wymaga nowej aplikacji. Najpierw zaktualizuj BRoutera</string>
<string name="msg_download_failed">Pobieranie nie powiodło się</string>
<string name="msg_download_cancel">Pobieranie anulowane</string>
<string name="msg_download_succeed">Pobieranie powiodło się</string>
<string name="msg_download_started">Pobieranie…</string>
</resources>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">BRouter</string>
<string name="profile_filename_example">filename.brf</string>
<string name="notification_channel_id">brouter_download</string>
<string name="channel_name">Downloads</string>
</resources>

View file

@ -1,37 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<plurals name="numberOfSegments">
<resources xmlns:tools="http://schemas.android.com/tools">
<plurals name="numberOfSegments" tools:ignore="MissingQuantity">
<item quantity="one">%d segment</item>
<item quantity="other">%d segments</item>
</plurals>
<string name="app_name">BRouter</string>
<string name="cancel_download">Cancel Download</string>
<string name="import_profile">Import Profile</string>
<string name="profile_filename_example">filename.brf</string>
<string name="download_info_start">Starting download…</string>
<string name="download_info_cancel">Cancelling…</string>
<string name="cancel_download">Cancel download</string>
<string name="import_profile">Import profile</string>
<string name="action_download">Download %s</string>
<string name="action_delete">Delete %s</string>
<string name="action_update">Update %s</string>
<string name="action_select">Select segments</string>
<string name="action_cancel">Stop Download</string>
<string name="summary_segments">Size=%s\nFree=%s</string>
<string name="notification_channel_id">brouter_download</string>
<string name="notification_title">Download Segments</string>
<string name="channel_name">Downloads</string>
<string name="action_cancel">Stop download</string>
<string name="summary_segments">Size=%1$s\nFree=%2$s</string>
<string name="notification_title">Download segments</string>
<string name="action_choose_folder">Choose brouter data base dir:</string>
<string name="action_select_profile">Select a routing profile</string>
<string name="main_action">Select Main Action</string>
<string name="main_action_1">Download Manager</string>
<string name="main_action_2">BRouter App</string>
<string name="cancel">Cancel</string>
<string name="i_know">I know</string>
<string name="close">Close</string>
<string name="exit">Exit</string>
<string name="ok">OK</string>
<string name="success">Success</string>
<string name="error">An Error occurred</string>
<string name="title_download">BRouter Download Manager</string>
<string name="summary_download">*** Attention:***
\n\nThe Download Manager is used to download routing-data
files which can be up to 170MB each. Do not start the Download Manager
on a cellular data connection without a data plan!
Download speed is restricted to 16 MBit/s.</string>
<string name="title_timeoutfree">Successfully prepared a timeout-free calculation</string>
<string name="summary_timeoutfree">You successfully repeated a calculation that previously run into a timeout
when started from your map tool. If you repeat the same request from your
map tool, with the exact same destination point and a close-by starting point,
this request is guaranteed not to time out.</string>
<string name="title_sdcard">Enter SDCARD base dir:</string>
<string name="title_action">Select Action</string>
<string name="action_via_select">Check VIA Selection:</string>
<string name="action_nogo_select">Check NoGo Selection:</string>
<string name="action_servermode">Server-Mode</string>
<string name="action_info">Info</string>
<string name="action_calc_route">Calc Route</string>
<string name="action_profile_settings">Profile Settings</string>
<string name="action_share">Share GPX</string>
<string name="action_select_from">Select from</string>
<string name="action_select_to">Select to/via</string>
<string name="msg_no_profile">no profile data</string>
<string name="msg_no_used_profile">, no used profile</string>
<string name="msg_too_much_data">Too much data for download. Please reduce.</string>
<string name="msg_download_start">Download scheduled. Check internet connection if it doesn\'t start.</string>
<string name="msg_wpt_selection">current waypoint selection:\n</string>
<string name="msg_no_wpt_selection">Expecting waypoint selection\n</string>
<string name="msg_alternative">Alternative</string>
<string name="msg_status_result">version = BRouter-%1$s \n
mem = %2$s \n
distance = %3$s km\n
filtered ascend = %4$s m\n
plain ascend = %5$s m\n
estimated time = %6$s</string>
<string name="msg_read_wpt_error">Error reading waypoints</string>
<string name="msg_no_wpt">coordinate source does not contain any waypoints!</string>
<string name="msg_too_much_wpts">coordinate source contains too much waypoints: %1$d (please use from/to/via names)</string>
<string name="no">No</string>
<string name="yes">Yes</string>
<string name="title_delete">Confirm Delete</string>
<string name="summary_delete">Really delete?</string>
<string name="title_version">Version Problem</string>
<string name="summary_version">The base version for tiles has changed. What to do?</string>
<string name="action_version1">Continue with current download, delete other old data</string>
<string name="action_version2">Select all for download and start</string>
<string name="action_version3">Cancel now, complete on another day</string>
<string name="title_version_diff">Version Differences</string>
<string name="summary_version_diff">The base version for some tiles is different. What to do?</string>
<string name="action_version_diff1">Download all different tiles</string>
<string name="action_version_diff2">Drop all different tiles</string>
<string name="action_version_diff3">Cancel now, complete on another day</string>
<string name="summary_new_version">The new data version needs a new app. Please update BRouter first</string>
<string name="msg_download_failed">Download failed</string>
<string name="msg_download_cancel">Download cancelled</string>
<string name="msg_download_succeed">Download succeeded</string>
<string name="msg_download_started">Downloading…</string>
</resources>

View file

@ -30,6 +30,10 @@ public class BRouter {
List<OsmNodeNamed> wplist = routingParamCollector.getWayPointList(lonlats);
Map<String, String> params = routingParamCollector.getUrlParams(queryString);
int engineMode = 0;
if (params.containsKey("engineMode")) {
engineMode = Integer.parseInt(params.get("engineMode"));
}
routingParamCollector.setParams(rc, wplist, params);
String exportName = null;
@ -47,7 +51,7 @@ public class BRouter {
maxRunningTime = Integer.parseInt(sMaxRunningTime) * 1000;
}
RoutingEngine re = new RoutingEngine(exportName, null, new File(args[0]), wplist, rc);
RoutingEngine re = new RoutingEngine(exportName, null, new File(args[0]), wplist, rc, engineMode);
re.doRun(maxRunningTime);
if (re.getErrorMessage() != null) {
System.out.println(re.getErrorMessage());

View file

@ -211,8 +211,13 @@ public class RouteServer extends Thread implements Comparable<RouteServer> {
} else {
OsmTrack track = cr.getFoundTrack();
if (engineMode == 2) {
// no zip for this engineMode
encodings = null;
}
String headers = encodings == null || encodings.indexOf("gzip") < 0 ? null : "Content-Encoding: gzip\n";
writeHttpHeader(bw, handler.getMimeType(), handler.getFileName(), headers, HTTP_STATUS_OK);
if (engineMode == 0) {
if (track != null) {
if (headers != null) { // compressed
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@ -225,6 +230,12 @@ public class RouteServer extends Thread implements Comparable<RouteServer> {
bw.write(handler.formatTrack(track));
}
}
} else if (engineMode == 2) {
String s = cr.getFoundInfo();
if (s != null) {
bw.write(s);
}
}
}
bw.flush();
} catch (Throwable e) {

View file

@ -1,10 +1,12 @@
package btools.server.request;
import java.io.BufferedWriter;
import java.io.File;
import java.io.StringWriter;
import java.util.Map;
import btools.router.FormatCsv;
import btools.router.FormatGpx;
import btools.router.FormatJson;
import btools.router.FormatKml;
import btools.router.OsmTrack;
import btools.router.RoutingContext;
import btools.server.ServiceContext;
@ -76,23 +78,17 @@ public class ServerHandler extends RequestHandler {
}
if (format == null || "gpx".equals(format)) {
result = track.formatAsGpx();
result = new FormatGpx(rc).format(track);
} else if ("kml".equals(format)) {
result = track.formatAsKml();
result = new FormatKml(rc).format(track);
} else if ("geojson".equals(format)) {
result = track.formatAsGeoJson();
result = new FormatJson(rc).format(track);
} else if ("csv".equals(format)) {
try {
StringWriter sw = new StringWriter();
BufferedWriter bw = new BufferedWriter(sw);
track.writeMessages(bw, rc);
return sw.toString();
} catch (Exception ex) {
return "Error: " + ex.getMessage();
}
result = new FormatCsv(rc).format(track);
} else {
System.out.println("unknown track format '" + format + "', using default");
result = track.formatAsGpx();
//result = track.formatAsGpx();
result = new FormatGpx(rc).format(track);
}
return result;

View file

@ -224,6 +224,7 @@ public class CompactLongMap<V> {
// does sorted array "a" contain "id" ?
@SuppressWarnings("unchecked")
private boolean contains(int idx, long id, boolean doPut) {
long[] a = al[idx];
int offset = a.length;
@ -243,6 +244,7 @@ public class CompactLongMap<V> {
return false;
}
@SuppressWarnings("unchecked")
protected void moveToFrozenArrays(long[] faid, List<V> flv) {
for (int i = 1; i < MAXLISTS; i++) {
pa[i] = 0;

View file

@ -19,6 +19,7 @@ public final class SortedHeap<V> {
/**
* @return the lowest key value, or null if none
*/
@SuppressWarnings("unchecked")
public V popLowestKeyValue() {
SortedBin bin = firstNonEmpty;
if (firstNonEmpty == null) {

View file

@ -25,7 +25,7 @@ assign allow_motorways = false # %allow_motorways% | Set to true to allow
assign consider_traffic = false # %consider_traffic% | Activate to avoid traffic | boolean
assign consider_noise = false # %consider_noise% | Activate to prefer a low-noise route | boolean
assign consider_river = false # %consider_river% | Activate to prefer a route along rivers or sees | boolean
assign consider_river = false # %consider_river% | Activate to prefer a route along rivers, lakes, etc. | boolean
assign consider_forest = false # %consider_forest% | Activate to prefer a route in forest or parks | boolean
assign consider_town = false # %consider_town% | Activate to bypass cities / big towns as far as possible | boolean

View file

@ -12,7 +12,7 @@
assign consider_elevation = false # %consider_elevation% | Activate to prefer a route with few elevation meters | boolean
assign consider_noise = false # %consider_noise% | Activate to prefer a low-noise route | boolean
assign consider_river = false # %consider_river% | Activate to prefer a route along rivers or sees | boolean
assign consider_river = false # %consider_river% | Activate to prefer a route along rivers, lakes, etc. | boolean
assign consider_forest = false # %consider_forest% | Activate to prefer a route in forest or green areas| boolean
assign consider_town = false # %consider_town% | Activate to bypass cities / big towns as far as possible | boolean
assign consider_traffic = 1 # %consider_traffic% | how do you plan to drive the tour? | [1=as cyclist alone in the week, 0.5=as cyclist alone at weekend, 0.3 =with a group of cyclists, 0.1=with a group of cyclists at week-end]

View file

@ -16,7 +16,7 @@ assign stick_to_cycleroutes = false # %stick_to_cycleroutes% | Set true t
assign avoid_unsafe = false # %avoid_unsafe% | Set true to avoid standard highways | boolean
assign consider_noise = false # %consider_noise% | Activate to prefer a low-noise route | boolean
assign consider_river = false # %consider_river% | Activate to prefer a route along rivers or sees | boolean
assign consider_river = false # %consider_river% | Activate to prefer a route along rivers, lakes, etc. | boolean
assign consider_forest = false # %consider_forest% | Activate to prefer a route in forest or parks | boolean
assign consider_town = false # %consider_town% | Activate to bypass cities / big towns as far as possible | boolean
assign consider_traffic = false # %consider_traffic% | Activate to consider traffic estimates | boolean