diff --git a/brouter-core/src/main/java/btools/router/FormatCsv.java b/brouter-core/src/main/java/btools/router/FormatCsv.java
new file mode 100644
index 0000000..37b7408
--- /dev/null
+++ b/brouter-core/src/main/java/btools/router/FormatCsv.java
@@ -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");
+ }
+ }
+
+}
diff --git a/brouter-core/src/main/java/btools/router/FormatGpx.java b/brouter-core/src/main/java/btools/router/FormatGpx.java
new file mode 100644
index 0000000..0ed6cc5
--- /dev/null
+++ b/brouter-core/src/main/java/btools/router/FormatGpx.java
@@ -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("\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("\n");
+ }
+ }
+
+ if (turnInstructionMode == 4) { // comment style
+ sb.append("\n");
+ sb.append("\n");
+ sb.append("\n");
+ }
+ sb.append("\n");
+ } else {
+ sb.append(" creator=\"BRouter-" + t.version + "\" version=\"1.1\">\n");
+ }
+ if (turnInstructionMode == 9) {
+ sb.append(" \n");
+ sb.append(" ").append(t.name).append("\n");
+ sb.append(" \n");
+ sb.append(" ").append(t.messageList.get(0)).append("\n");
+ if (t.params != null && t.params.size() > 0) {
+ sb.append(" e : t.params.entrySet()) {
+ if (i++ != 0) sb.append("&");
+ sb.append(e.getKey()).append("=").append(e.getValue());
+ }
+ sb.append("]]>\n");
+ }
+ sb.append(" \n");
+ sb.append(" \n");
+ }
+ if (turnInstructionMode == 3 || turnInstructionMode == 8) { // osmand style, cruiser
+ float lastRteTime = 0;
+
+ sb.append(" \n");
+
+ float rteTime = t.getVoiceHintTime(0);
+ StringBuffer first = new StringBuffer();
+ // define start point
+ {
+ first.append(" \n")
+ .append(" start\n \n");
+ if (rteTime != lastRteTime) { // add timing only if available
+ double ti = rteTime - lastRteTime;
+ first.append(" \n");
+ lastRteTime = rteTime;
+ }
+ first.append(" 0\n \n \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(" \n")
+ .append(" ")
+ .append(turnInstructionMode == 3 ? hint.getMessageString() : hint.getCruiserMessageString())
+ .append("\n \n");
+
+ rteTime = t.getVoiceHintTime(i + 1);
+
+ if (rteTime != lastRteTime) { // add timing only if available
+ double ti = rteTime - lastRteTime;
+ sb.append(" \n");
+ lastRteTime = rteTime;
+ }
+ sb.append(" ")
+ .append(turnInstructionMode == 3 ? hint.getCommandString() : hint.getCruiserCommandString())
+ .append("\n ").append("" + (int) hint.angle)
+ .append("\n ").append("" + hint.indexInTrack).append("\n \n \n");
+ }
+ sb.append(" \n")
+ .append(" destination\n \n");
+ sb.append(" \n");
+ sb.append(" ").append("" + (t.nodes.size() - 1)).append("\n \n \n");
+
+ sb.append("\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(" ")
+ .append(hint.selev == Short.MIN_VALUE ? "" : "" + (hint.selev / 4.) + "")
+ .append("").append(hint.getMessageString()).append("")
+ .append("").append("" + hint.distanceToNext).append("");
+ 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("").append("" + ti).append("")
+ .append("").append("" + speed).append("");
+ lastRteTime = rteTime;
+ }
+ sb.append("").append("" + hint.getLocusAction()).append("")
+ .append("\n");
+ }
+ }
+ if (turnInstructionMode == 5) { // gpsies style
+ for (VoiceHint hint : t.voiceHints.list) {
+ sb.append(" ")
+ .append("").append(hint.getMessageString()).append("")
+ .append("").append(hint.getSymbolString().toLowerCase()).append("")
+ .append("").append(hint.getSymbolString()).append("")
+ .append("\n");
+ }
+ }
+
+ if (turnInstructionMode == 6) { // orux style
+ for (VoiceHint hint : t.voiceHints.list) {
+ sb.append(" ")
+ .append(hint.selev == Short.MIN_VALUE ? "" : "" + (hint.selev / 4.) + "")
+ .append("\n" +
+ " \n" +
+ " ").append("" + hint.getOruxAction())
+ .append("\n" +
+ " \n" +
+ " \n" +
+ " \n");
+ }
+ }
+
+ for (int i = 0; i <= t.pois.size() - 1; i++) {
+ OsmNodeNamed poi = t.pois.get(i);
+ sb.append(" \n")
+ .append(" ").append(StringUtils.escapeXml10(poi.name)).append("\n")
+ .append(" \n");
+ }
+
+ if (t.exportWaypoints) {
+ for (int i = 0; i <= t.matchedWaypoints.size() - 1; i++) {
+ MatchedWaypoint wt = t.matchedWaypoints.get(i);
+ sb.append(" \n")
+ .append(" ").append(StringUtils.escapeXml10(wt.name)).append("\n");
+ if (i == 0) {
+ sb.append(" from\n");
+ } else if (i == t.matchedWaypoints.size() - 1) {
+ sb.append(" to\n");
+ } else {
+ sb.append(" via\n");
+ }
+ sb.append(" \n");
+ }
+ }
+ sb.append(" \n");
+ if (turnInstructionMode == 9
+ || turnInstructionMode == 2
+ || turnInstructionMode == 8
+ || turnInstructionMode == 4) { // Locus, comment, cruise, brouter style
+ sb.append(" ").append(t.name).append("\n");
+ sb.append(" ").append(t.voiceHints.getTransportMode()).append("\n");
+ } else {
+ sb.append(" ").append(t.name).append("\n");
+ }
+
+ if (turnInstructionMode == 7) {
+ sb.append(" \n");
+ sb.append(" ").append("" + t.voiceHints.getLocusRouteType()).append("\n");
+ sb.append(" 1\n");
+ sb.append(" \n");
+ }
+
+
+ // all points
+ sb.append(" \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 ? "" : "" + n.getElev() + "";
+ VoiceHint hint = t.getVoiceHint(idx);
+ MatchedWaypoint mwpt = t.getMatchedWaypoint(idx);
+
+ if (t.showTime) {
+ sele += "";
+ }
+ if (turnInstructionMode == 8) {
+ if (mwpt != null &&
+ !mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
+ sele += "" + mwpt.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 += "" + mwpt.name + "";
+ }
+ sele += "" + hint.getCruiserMessageString() + "";
+ sele += "" + hint.getCommandString(hint.cmd) + "";
+ if (mwpt != null) {
+ sele += "Via";
+ }
+ sele += "";
+ 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 += "" + (((int) (speed * 10)) / 10.f) + "";
+ }
+
+ sele += "" + hint.getCommandString() + ";" + (int) (hint.distanceToNext) + "," + hint.formatGeometry() + "";
+ if (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway)) {
+ sele += "" + n.message.wayKeyValues + "";
+ lastway = n.message.wayKeyValues;
+ }
+ if (n.message != null && n.message.nodeKeyValues != null) {
+ sele += "" + n.message.nodeKeyValues + "";
+ }
+ sele += "";
+
+ }
+ if (idx == 0 && hint == null) {
+ if (mwpt != null && mwpt.direct) {
+ sele += "beeline";
+ } else {
+ sele += "start";
+ }
+ sele += "Via";
+
+ } else if (idx == t.nodes.size() - 1 && hint == null) {
+
+ sele += "end";
+ sele += "Via";
+
+ } else {
+ if (mwpt != null && hint == null) {
+ if (mwpt.direct) {
+ // bNextDirect = true;
+ sele += "beeline";
+ } else {
+ sele += "" + mwpt.name + "";
+ }
+ sele += "Via";
+ 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 += "";
+ 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 += "" + (((int) (speed * 10)) / 10.f) + "";
+ }
+ if (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway)) {
+ sele += "" + n.message.wayKeyValues + "";
+ lastway = n.message.wayKeyValues;
+ }
+ if (n.message != null && n.message.nodeKeyValues != null) {
+ sele += "" + n.message.nodeKeyValues + "";
+ }
+ sele += "";
+ }
+ }
+ }
+
+ 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 += "" + mwpt.name + "";
+ }
+ if (mwpt.direct && bNextDirect) {
+ sele += "" + hint.getLocusSymbolString() + "pass_placeShaping";
+ // bNextDirect = false;
+ } else if (mwpt.direct) {
+ if (idx == 0)
+ sele += "pass_placeVia";
+ else
+ sele += "pass_placeShaping";
+ bNextDirect = true;
+ } else if (bNextDirect) {
+ sele += "beeline" + hint.getLocusSymbolString() + "Shaping";
+ bNextDirect = false;
+ } else {
+ sele += "" + hint.getLocusSymbolString() + "Via";
+ }
+ } else {
+ sele += "" + hint.getLocusSymbolString() + "";
+ }
+ } else {
+ if (idx == 0 && hint == null) {
+
+ int pos = sele.indexOf("" + mwpt.name + "";
+ if (mwpt != null && mwpt.direct) {
+ bNextDirect = true;
+ }
+ sele += "pass_place";
+ sele += "Via";
+
+ } else if (idx == t.nodes.size() - 1 && hint == null) {
+
+ int pos = sele.indexOf("" + mwpt.name + "";
+ if (bNextDirect) {
+ sele += "beeline";
+ }
+ sele += "pass_place";
+ sele += "Via";
+
+ } else {
+ if (mwpt != null) {
+ if (!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
+ sele += "" + mwpt.name + "";
+ }
+ if (mwpt.direct && bNextDirect) {
+ sele += "beelinepass_placeShaping";
+ } else if (mwpt.direct) {
+ if (idx == 0)
+ sele += "pass_placeVia";
+ else
+ sele += "pass_placeShaping";
+ bNextDirect = true;
+ } else if (bNextDirect) {
+ sele += "beelinepass_placeShaping";
+ bNextDirect = false;
+ } else if (mwpt.name.startsWith("via") ||
+ mwpt.name.startsWith("from") ||
+ mwpt.name.startsWith("to")) {
+ if (bNextDirect) {
+ sele += "beelinepass_placeShaping";
+ } else {
+ sele += "pass_placeVia";
+ }
+ bNextDirect = false;
+ } else {
+ sele += "" + mwpt.name + "";
+ sele += "pass_placeVia";
+ }
+ }
+ }
+ }
+ }
+ sb.append(" ").append(sele).append("\n");
+
+ nn = n;
+ }
+
+ sb.append(" \n");
+ sb.append(" \n");
+ sb.append("\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("\n");
+ sb.append("\n");
+ }
+
+ public void formatGpxFooter(BufferedWriter sb) throws IOException {
+ sb.append("\n");
+ }
+
+ public void formatWaypointGpx(BufferedWriter sb, OsmNodeNamed n) throws IOException {
+ sb.append(" ");
+ if (n.getSElev() != Short.MIN_VALUE) {
+ sb.append("").append("" + n.getElev()).append("");
+ }
+ if (n.name != null) {
+ sb.append("").append(StringUtils.escapeXml10(n.name)).append("");
+ }
+ if (n.nodeDescription != null && rc != null) {
+ sb.append("").append(rc.expctxWay.getKeyValueDescription(false, n.nodeDescription)).append("");
+ }
+ sb.append("\n");
+ }
+
+ public static String getWaypoint(int ilon, int ilat, String name, String desc) {
+ return "" + name + "" + (desc != null ? "" + desc + "" : "") + "";
+ }
+
+ 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("= 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;
+ }
+
+}
diff --git a/brouter-core/src/main/java/btools/router/FormatJson.java b/brouter-core/src/main/java/btools/router/FormatJson.java
new file mode 100644
index 0000000..a2c5b7a
--- /dev/null
+++ b/brouter-core/src/main/java/btools/router/FormatJson.java
@@ -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 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);
+ }
+ }
+
+}
diff --git a/brouter-core/src/main/java/btools/router/FormatKml.java b/brouter-core/src/main/java/btools/router/FormatKml.java
new file mode 100644
index 0000000..5798c5c
--- /dev/null
+++ b/brouter-core/src/main/java/btools/router/FormatKml.java
@@ -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("\n");
+
+ sb.append("\n");
+ sb.append(" \n");
+ sb.append(" KML Samples\n");
+ sb.append(" 1\n");
+ sb.append(" 3.497064\n");
+ sb.append(" 872\n");
+ sb.append(" To enable simple instructions add: 'instructions=1' as parameter to the URL\n");
+ sb.append(" \n");
+ sb.append(" Paths\n");
+ sb.append(" 0\n");
+ sb.append(" Examples of paths.\n");
+ sb.append(" \n");
+ sb.append(" Tessellated\n");
+ sb.append(" 0\n");
+ sb.append(" tag has a value of 1, the line will contour to the underlying terrain]]>\n");
+ sb.append(" \n");
+ sb.append(" 1\n");
+ sb.append(" ");
+
+ for (OsmPathElement n : t.nodes) {
+ sb.append(formatILon(n.getILon())).append(",").append(formatILat(n.getILat())).append("\n");
+ }
+
+ sb.append(" \n");
+ sb.append(" \n");
+ sb.append(" \n");
+ sb.append(" \n");
+ if (t.exportWaypoints || !t.pois.isEmpty()) {
+ if (!t.pois.isEmpty()) {
+ sb.append(" \n");
+ sb.append(" poi\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(" \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(" \n");
+ sb.append("\n");
+
+ return sb.toString();
+ }
+
+ private void createFolder(StringBuilder sb, String type, List waypoints) {
+ sb.append(" \n");
+ sb.append(" " + type + "\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(" \n");
+ }
+
+ private void createPlaceMark(StringBuilder sb, String name, int ilat, int ilon) {
+ sb.append(" \n");
+ sb.append(" " + StringUtils.escapeXml10(name) + "\n");
+ sb.append(" \n");
+ sb.append(" " + formatILon(ilon) + "," + formatILat(ilat) + "\n");
+ sb.append(" \n");
+ sb.append(" \n");
+ }
+
+}
diff --git a/brouter-core/src/main/java/btools/router/Formatter.java b/brouter-core/src/main/java/btools/router/Formatter.java
new file mode 100644
index 0000000..09bdb1d
--- /dev/null
+++ b/brouter-core/src/main/java/btools/router/Formatter.java
@@ -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);
+ }
+
+
+}
diff --git a/brouter-core/src/main/java/btools/router/OsmTrack.java b/brouter-core/src/main/java/btools/router/OsmTrack.java
index ac3b51f..9ccff98 100644
--- a/brouter-core/src/main/java/btools/router/OsmTrack.java
+++ b/brouter-core/src/main/java/btools/router/OsmTrack.java
@@ -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 detourMap;
- private VoiceHintList voiceHints;
+ public VoiceHintList voiceHints;
public String message = null;
public List messageList = null;
@@ -178,7 +165,7 @@ public final class OsmTrack {
nodesMap = new FrozenLongMap<>(nodesMap);
}
- private List aggregateMessages() {
+ public List aggregateMessages() {
ArrayList res = new ArrayList<>();
MessageData current = null;
for (OsmPathElement n : nodes) {
@@ -200,7 +187,7 @@ public final class OsmTrack {
return res;
}
- private List aggregateSpeedProfile() {
+ public List aggregateSpeedProfile() {
ArrayList 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("\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("\n");
- }
- }
-
- if (turnInstructionMode == 4) { // comment style
- sb.append("\n");
- sb.append("\n");
- sb.append("\n");
- }
- sb.append("\n");
- } else {
- sb.append(" creator=\"BRouter-" + version + "\" version=\"1.1\">\n");
- }
- if (turnInstructionMode == 9) {
- sb.append(" \n");
- sb.append(" ").append(name).append("\n");
- sb.append(" \n");
- sb.append(" ").append(messageList.get(0)).append("\n");
- if (params != null && params.size() > 0) {
- sb.append(" e : params.entrySet()) {
- if (i++ != 0) sb.append("&");
- sb.append(e.getKey()).append("=").append(e.getValue());
- }
- sb.append("]]>\n");
- }
- sb.append(" \n");
- sb.append(" \n");
- }
- if (turnInstructionMode == 3 || turnInstructionMode == 8) { // osmand style, cruiser
- float lastRteTime = 0;
-
- sb.append(" \n");
-
- float rteTime = getVoiceHintTime(0);
- StringBuffer first = new StringBuffer();
- // define start point
- {
- first.append(" \n")
- .append(" start\n \n");
- if (rteTime != lastRteTime) { // add timing only if available
- double t = rteTime - lastRteTime;
- first.append(" \n");
- lastRteTime = rteTime;
- }
- first.append(" 0\n \n \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(" \n")
- .append(" ")
- .append(turnInstructionMode == 3 ? hint.getMessageString() : hint.getCruiserMessageString())
- .append("\n \n");
-
- rteTime = getVoiceHintTime(i + 1);
-
- if (rteTime != lastRteTime) { // add timing only if available
- double t = rteTime - lastRteTime;
- sb.append(" \n");
- lastRteTime = rteTime;
- }
- sb.append(" ")
- .append(turnInstructionMode == 3 ? hint.getCommandString() : hint.getCruiserCommandString())
- .append("\n ").append("" + (int) hint.angle)
- .append("\n ").append("" + hint.indexInTrack).append("\n \n \n");
- }
- sb.append(" \n")
- .append(" destination\n \n");
- sb.append(" \n");
- sb.append(" ").append("" + (nodes.size() - 1)).append("\n \n \n");
-
- sb.append("\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(" ")
- .append(hint.selev == Short.MIN_VALUE ? "" : "" + (hint.selev / 4.) + "")
- .append("").append(hint.getMessageString()).append("")
- .append("").append("" + hint.distanceToNext).append("");
- float rteTime = getVoiceHintTime(i + 1);
- if (rteTime != lastRteTime) { // add timing only if available
- double t = rteTime - lastRteTime;
- double speed = hint.distanceToNext / t;
- sb.append("").append("" + t).append("")
- .append("").append("" + speed).append("");
- lastRteTime = rteTime;
- }
- sb.append("").append("" + hint.getLocusAction()).append("")
- .append("\n");
- }
- }
- if (turnInstructionMode == 5) { // gpsies style
- for (VoiceHint hint : voiceHints.list) {
- sb.append(" ")
- .append("").append(hint.getMessageString()).append("")
- .append("").append(hint.getSymbolString().toLowerCase()).append("")
- .append("").append(hint.getSymbolString()).append("")
- .append("\n");
- }
- }
-
- if (turnInstructionMode == 6) { // orux style
- for (VoiceHint hint : voiceHints.list) {
- sb.append(" ")
- .append(hint.selev == Short.MIN_VALUE ? "" : "" + (hint.selev / 4.) + "")
- .append("\n" +
- " \n" +
- " ").append("" + hint.getOruxAction())
- .append("\n" +
- " \n" +
- " \n" +
- " \n");
- }
- }
-
- for (int i = 0; i <= pois.size() - 1; i++) {
- OsmNodeNamed poi = pois.get(i);
- sb.append(" \n")
- .append(" ").append(StringUtils.escapeXml10(poi.name)).append("\n")
- .append(" \n");
- }
-
- if (exportWaypoints) {
- for (int i = 0; i <= matchedWaypoints.size() - 1; i++) {
- MatchedWaypoint wt = matchedWaypoints.get(i);
- sb.append(" \n")
- .append(" ").append(StringUtils.escapeXml10(wt.name)).append("\n");
- if (i == 0) {
- sb.append(" from\n");
- } else if (i == matchedWaypoints.size() - 1) {
- sb.append(" to\n");
- } else {
- sb.append(" via\n");
- }
- sb.append(" \n");
- }
- }
- sb.append(" \n");
- if (turnInstructionMode == 9
- || turnInstructionMode == 2
- || turnInstructionMode == 8
- || turnInstructionMode == 4) { // Locus, comment, cruise, brouter style
- sb.append(" ").append(name).append("\n");
- sb.append(" ").append(voiceHints.getTransportMode()).append("\n");
- } else {
- sb.append(" ").append(name).append("\n");
- }
-
- if (turnInstructionMode == 7) {
- sb.append(" \n");
- sb.append(" ").append("" + voiceHints.getLocusRouteType()).append("\n");
- sb.append(" 1\n");
- sb.append(" \n");
- }
-
-
- // all points
- sb.append(" \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 ? "" : "" + n.getElev() + "";
- VoiceHint hint = getVoiceHint(idx);
- MatchedWaypoint mwpt = getMatchedWaypoint(idx);
-
- if (showTime) {
- sele += "";
- }
- if (turnInstructionMode == 8) {
- if (mwpt != null &&
- !mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
- sele += "" + mwpt.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 += "" + mwpt.name + "";
- }
- sele += "" + hint.getCruiserMessageString() + "";
- sele += "" + hint.getCommandString(hint.cmd) + "";
- if (mwpt != null) {
- sele += "Via";
- }
- sele += "";
- 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 += "" + (((int) (speed * 10)) / 10.f) + "";
- }
-
- sele += "" + hint.getCommandString() + ";" + (int) (hint.distanceToNext) + "," + hint.formatGeometry() + "";
- if (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway)) {
- sele += "" + n.message.wayKeyValues + "";
- lastway = n.message.wayKeyValues;
- }
- if (n.message != null && n.message.nodeKeyValues != null) {
- sele += "" + n.message.nodeKeyValues + "";
- }
- sele += "";
-
- }
- if (idx == 0 && hint == null) {
- if (mwpt != null && mwpt.direct) {
- sele += "beeline";
- } else {
- sele += "start";
- }
- sele += "Via";
-
- } else if (idx == nodes.size() - 1 && hint == null) {
-
- sele += "end";
- sele += "Via";
-
- } else {
- if (mwpt != null && hint == null) {
- if (mwpt.direct) {
- // bNextDirect = true;
- sele += "beeline";
- } else {
- sele += "" + mwpt.name + "";
- }
- sele += "Via";
- 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 += "";
- 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 += "" + (((int) (speed * 10)) / 10.f) + "";
- }
- if (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway)) {
- sele += "" + n.message.wayKeyValues + "";
- lastway = n.message.wayKeyValues;
- }
- if (n.message != null && n.message.nodeKeyValues != null) {
- sele += "" + n.message.nodeKeyValues + "";
- }
- sele += "";
- }
- }
- }
-
- 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 += "" + mwpt.name + "";
- }
- if (mwpt.direct && bNextDirect) {
- sele += "" + hint.getLocusSymbolString() + "pass_placeShaping";
- // bNextDirect = false;
- } else if (mwpt.direct) {
- if (idx == 0)
- sele += "pass_placeVia";
- else
- sele += "pass_placeShaping";
- bNextDirect = true;
- } else if (bNextDirect) {
- sele += "beeline" + hint.getLocusSymbolString() + "Shaping";
- bNextDirect = false;
- } else {
- sele += "" + hint.getLocusSymbolString() + "Via";
- }
- } else {
- sele += "" + hint.getLocusSymbolString() + "";
- }
- } else {
- if (idx == 0 && hint == null) {
-
- int pos = sele.indexOf("" + mwpt.name + "";
- if (mwpt != null && mwpt.direct) {
- bNextDirect = true;
- }
- sele += "pass_place";
- sele += "Via";
-
- } else if (idx == nodes.size() - 1 && hint == null) {
-
- int pos = sele.indexOf("" + mwpt.name + "";
- if (bNextDirect) {
- sele += "beeline";
- }
- sele += "pass_place";
- sele += "Via";
-
- } else {
- if (mwpt != null) {
- if (!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
- sele += "" + mwpt.name + "";
- }
- if (mwpt.direct && bNextDirect) {
- sele += "beelinepass_placeShaping";
- } else if (mwpt.direct) {
- if (idx == 0)
- sele += "pass_placeVia";
- else
- sele += "pass_placeShaping";
- bNextDirect = true;
- } else if (bNextDirect) {
- sele += "beelinepass_placeShaping";
- bNextDirect = false;
- } else if (mwpt.name.startsWith("via") ||
- mwpt.name.startsWith("from") ||
- mwpt.name.startsWith("to")) {
- if (bNextDirect) {
- sele += "beelinepass_placeShaping";
- } else {
- sele += "pass_placeVia";
- }
- bNextDirect = false;
- } else {
- sele += "" + mwpt.name + "";
- sele += "pass_placeVia";
- }
- }
- }
- }
- }
- sb.append(" ").append(sele).append("\n");
-
- nn = n;
- }
-
- sb.append(" \n");
- sb.append(" \n");
- sb.append("\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("\n");
- sb.append("\n");
- }
-
- static public void formatGpxFooter(BufferedWriter sb) throws IOException {
- sb.append("\n");
- }
-
- static public void formatWaypointGpx(BufferedWriter sb, OsmNodeNamed n) throws IOException {
- sb.append(" ");
- if (n.getSElev() != Short.MIN_VALUE) {
- sb.append("").append("" + n.getElev()).append("");
- }
- if (n.name != null) {
- sb.append("").append(StringUtils.escapeXml10(n.name)).append("");
- }
- if (n.nodeDescription != null) {
- sb.append("").append("hat desc").append("");
- }
- sb.append("\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("\n");
-
- sb.append("\n");
- sb.append(" \n");
- sb.append(" KML Samples\n");
- sb.append(" 1\n");
- sb.append(" 3.497064\n");
- sb.append(" 872\n");
- sb.append(" To enable simple instructions add: 'instructions=1' as parameter to the URL\n");
- sb.append(" \n");
- sb.append(" Paths\n");
- sb.append(" 0\n");
- sb.append(" Examples of paths.\n");
- sb.append(" \n");
- sb.append(" Tessellated\n");
- sb.append(" 0\n");
- sb.append(" tag has a value of 1, the line will contour to the underlying terrain]]>\n");
- sb.append(" \n");
- sb.append(" 1\n");
- sb.append(" ");
-
- for (OsmPathElement n : nodes) {
- sb.append(formatILon(n.getILon())).append(",").append(formatILat(n.getILat())).append("\n");
- }
-
- sb.append(" \n");
- sb.append(" \n");
- sb.append(" \n");
- sb.append(" \n");
- if (exportWaypoints || !pois.isEmpty()) {
- if (!pois.isEmpty()) {
- sb.append(" \n");
- sb.append(" poi\n");
- for (int i = 0; i < pois.size(); i++) {
- OsmNodeNamed poi = pois.get(i);
- createPlaceMark(sb, poi.name, poi.ilat, poi.ilon);
- }
- sb.append(" \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(" \n");
- sb.append("\n");
-
- return sb.toString();
- }
-
- private void createFolder(StringBuilder sb, String type, List waypoints) {
- sb.append(" \n");
- sb.append(" " + type + "\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(" \n");
- }
-
- private void createPlaceMark(StringBuilder sb, String name, int ilat, int ilon) {
- sb.append(" \n");
- sb.append(" " + StringUtils.escapeXml10(name) + "\n");
- sb.append(" \n");
- sb.append(" " + formatILon(ilon) + "," + formatILat(ilat) + "\n");
- sb.append(" \n");
- sb.append(" \n");
- }
-
public List 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 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("= 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;
}
diff --git a/brouter-core/src/main/java/btools/router/RoutingEngine.java b/brouter-core/src/main/java/btools/router/RoutingEngine.java
index baff3dc..105ed09 100644
--- a/brouter-core/src/main/java/btools/router/RoutingEngine.java
+++ b/brouter-core/src/main/java/btools/router/RoutingEngine.java
@@ -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() {
diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/WaypointMatcherImpl.java b/brouter-mapaccess/src/main/java/btools/mapaccess/WaypointMatcherImpl.java
index e70d3be..85ab9b5 100644
--- a/brouter-mapaccess/src/main/java/btools/mapaccess/WaypointMatcherImpl.java
+++ b/brouter-mapaccess/src/main/java/btools/mapaccess/WaypointMatcherImpl.java
@@ -51,7 +51,7 @@ public final class WaypointMatcherImpl implements WaypointMatcher {
}
// sort result list
- comparator = new Comparator<>() {
+ comparator = new Comparator() {
@Override
public int compare(MatchedWaypoint mw1, MatchedWaypoint mw2) {
int cmpDist = Double.compare(mw1.radius, mw2.radius);
diff --git a/brouter-routing-app/build.gradle b/brouter-routing-app/build.gradle
index 9cd72f4..2300600 100644
--- a/brouter-routing-app/build.gradle
+++ b/brouter-routing-app/build.gradle
@@ -20,8 +20,6 @@ android {
minSdkVersion 14
targetSdkVersion 33
- resConfigs "en"
-
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
diff --git a/brouter-routing-app/src/main/AndroidManifest.xml b/brouter-routing-app/src/main/AndroidManifest.xml
index e210ef7..831deea 100644
--- a/brouter-routing-app/src/main/AndroidManifest.xml
+++ b/brouter-routing-app/src/main/AndroidManifest.xml
@@ -10,6 +10,7 @@
+
+
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 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();
}
diff --git a/brouter-routing-app/src/main/java/btools/routingapp/BInstallerView.java b/brouter-routing-app/src/main/java/btools/routingapp/BInstallerView.java
index 4eaddac..8fb8949 100644
--- a/brouter-routing-app/src/main/java/btools/routingapp/BInstallerView.java
+++ b/brouter-routing-app/src/main/java/btools/routingapp/BInstallerView.java
@@ -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);
}
}
}
diff --git a/brouter-routing-app/src/main/java/btools/routingapp/BRouterActivity.java b/brouter-routing-app/src/main/java/btools/routingapp/BRouterActivity.java
index 1dca201..f633b47 100644
--- a/brouter-routing-app/src/main/java/btools/routingapp/BRouterActivity.java
+++ b/brouter-routing-app/src/main/java/btools/routingapp/BRouterActivity.java
@@ -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 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 /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 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();
}
}
diff --git a/brouter-routing-app/src/main/java/btools/routingapp/BRouterService.java b/brouter-routing-app/src/main/java/btools/routingapp/BRouterService.java
index 8d6ea4e..a1e8963 100644
--- a/brouter-routing-app/src/main/java/btools/routingapp/BRouterService.java
+++ b/brouter-routing-app/src/main/java/btools/routingapp/BRouterService.java
@@ -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()) {
diff --git a/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java b/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java
index ff50885..a14dfcf 100644
--- a/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java
+++ b/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java
@@ -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();
diff --git a/brouter-routing-app/src/main/java/btools/routingapp/BRouterWorker.java b/brouter-routing-app/src/main/java/btools/routingapp/BRouterWorker.java
index 5823db5..f7a74ff 100644
--- a/brouter-routing-app/src/main/java/btools/routingapp/BRouterWorker.java
+++ b/brouter-routing-app/src/main/java/btools/routingapp/BRouterWorker.java
@@ -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 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);
- break;
- case OUTPUT_FORMAT_JSON:
- track.writeJson(pathToFileResult);
- break;
- default:
- track.writeGpx(pathToFileResult);
- break;
- }
- } catch (Exception e) {
- return "error writing file: " + e;
- }
+
}
+ try {
+ switch (writeFromat) {
+ case OUTPUT_FORMAT_KML:
+ new FormatKml(rc).write(pathToFileResult, track);
+ break;
+ case OUTPUT_FORMAT_JSON:
+ new FormatJson(rc).write(pathToFileResult, track);
+ break;
+ case OUTPUT_FORMAT_GPX:
+ default:
+ 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();
diff --git a/brouter-routing-app/src/main/java/btools/routingapp/DownloadWorker.java b/brouter-routing-app/src/main/java/btools/routingapp/DownloadWorker.java
index 233d416..c5d5eaa 100644
--- a/brouter-routing-app/src/main/java/btools/routingapp/DownloadWorker.java
+++ b/brouter-routing-app/src/main/java/btools/routingapp/DownloadWorker.java
@@ -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,7 +170,10 @@ public class DownloadWorker extends Worker {
}
notificationBuilder.setContentText("Starting Download");
// Mark the Worker as important
- setForegroundAsync(new ForegroundInfo(NOTIFICATION_ID, notificationBuilder.build()));
+ 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");
if (!downloadLookup()) {
diff --git a/brouter-routing-app/src/main/java/btools/routingapp/RoutingParameterDialog.java b/brouter-routing-app/src/main/java/btools/routingapp/RoutingParameterDialog.java
index 8eb4365..356e2d3 100644
--- a/brouter-routing-app/src/main/java/btools/routingapp/RoutingParameterDialog.java
+++ b/brouter-routing-app/src/main/java/btools/routingapp/RoutingParameterDialog.java
@@ -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,41 +169,52 @@ public class RoutingParameterDialog extends AppCompatActivity {
new OnBackInvokedCallback() {
@Override
public void onBackInvoked() {
- StringBuilder sb = null;
- if (sharedValues != null) {
- // fill preference with used params
- // for direct use in the BRouter interface "extraParams"
- sb = new StringBuilder();
- for (Map.Entry entry : sharedValues.getAll().entrySet()) {
- if (!entry.getKey().equals("params")) {
- sb.append(sb.length() > 0 ? "&" : "")
- .append(entry.getKey())
- .append("=");
- String s = entry.getValue().toString();
- if (s.equals("true")) s = "1";
- else if (s.equals("false")) s = "0";
- sb.append(s);
- }
- }
- }
- // and return the array
- // one should be enough
- Intent i = new Intent();
- // i.putExtra("PARAMS", listParams);
- i.putExtra("PROFILE", profile);
- i.putExtra("PROFILE_HASH", profile_hash);
- if (sb != null) i.putExtra("PARAMS_VALUES", sb.toString());
-
- setResult(Activity.RESULT_OK, i);
- finish();
+ 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
+ // for direct use in the BRouter interface "extraParams"
+ sb = new StringBuilder();
+ for (Map.Entry entry : sharedValues.getAll().entrySet()) {
+ if (!entry.getKey().equals("params")) {
+ sb.append(sb.length() > 0 ? "&" : "")
+ .append(entry.getKey())
+ .append("=");
+ String s = entry.getValue().toString();
+ if (s.equals("true")) s = "1";
+ else if (s.equals("false")) s = "0";
+ sb.append(s);
+ }
+ }
+ }
+ // and return the array
+ // one should be enough
+ Intent i = new Intent();
+ // i.putExtra("PARAMS", listParams);
+ i.putExtra("PROFILE", profile);
+ i.putExtra("PROFILE_HASH", profile_hash);
+ if (sb != null) i.putExtra("PARAMS_VALUES", sb.toString());
+
+ setResult(Activity.RESULT_OK, i);
+ finish();
+
+ }
+
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
diff --git a/brouter-routing-app/src/main/res/values-ar/strings.xml b/brouter-routing-app/src/main/res/values-ar/strings.xml
new file mode 100644
index 0000000..8759f4a
--- /dev/null
+++ b/brouter-routing-app/src/main/res/values-ar/strings.xml
@@ -0,0 +1,94 @@
+
+
+
+ - %d قطعة
+ - %d قطع
+
+ إلغاء التنزيل
+ استيراد ملف تعريف
+ تنزيل %s
+ حذف %s
+ تحديث %s
+ حدد القطع
+ إيقاف التنزيل
+ الحجم=%1$s\nالحجم المتوفر=%2$s
+ تحميل القطع
+
+ اختر مكان قاعدة بيانات brouter:
+ اختر ملف تعريف التوجيه
+ حدد الإجراء الرئيسي
+ مدير التنزيلات
+ تطبيق BRouter
+
+ إلغاء
+ أعرف ذلك
+ إغلاق
+ خروج
+ موافق
+ تم بنجاح
+ حدث خطأ ما
+
+ مدير تنزيلات BRouter
+ *** تحذير:***
+ \n\nيتم استخدام مدير التنزيل لتنزيل ملفات بيانات التوجيه عبر الطرق
+ والتي يمكن أن يصل حجمها إلى 170 ميجابايت، لذلك لا تقم بتشغيل
+ "مدير التنزيلات" حينما تكون متصلاً عبر البيانات الخلوية ومحدوداً بحجم التنزيلات!
+ سرعة التنزيل محدودة على 16 ميجابايت/بالثانية.
+ أنجزت عملية الحساب بنجاح وبدون تأخير
+ لقد نجحت في تكرار عملية حسابية كانت قد انتهت في السابق
+ عند بدايتها من خلال أداة الخريطة، إذا قمت بتكرار نفس الطلب من
+ أداة الخريطة الخاصة بك ومع نفس الوجهة بالضبط وبنقطة بداية
+ قريبة، فسيضمن لك التطبيق عدم انتهاء مهلة هذا الطلب.
+ أدخل مسار الذاكرة الخارجية:
+ اختر الإجراء
+
+ التحقق من النقاط الوسيطة:
+ التحقق من النقاط المسبتعدة:
+ وضع-الخادم
+ معلومات
+ حساب الطريق
+ إعدادات ملف التعريف
+ مشاركة ملف GPX
+ اختر من
+ اختر إلى/عبر
+
+ لا توجد بيانات ملف التعريف
+ ، لا يوجد ملف تعريف مستخدم
+ هناك الكثير من البيانات للتنزيل، من فضلك قم بتقليلها.
+ تمت جدولة التنزيل، وتحقق من اتصالك بالإنترنت إذا لم يبدأ التنزيل.
+ نقاط الطريق الحالية المحددة:\n
+ نقاط الطريق المتوقعة المحددة\n
+ البديل
+ الإصدار = BRouter-%1$s \n
+ الذاكرة = %2$s \n
+ المسافة = %3$s كم\n
+ التصاعد المرشح = %4$s م\n
+ التصاعد العادي = %5$s م\n
+ الوقت المقدر = %6$s
+ خطأ في قراءة نقاط الطريق
+ لا يحتوي مصدر الإحداثيات على أي نقاط الطريق!
+ مصدر الإحداثيات يحتوي على عدد كبير جدًا من نقاط الطريق: %1$d (يرجى استخدام أسماء النقاط من/إلى/عبر from/to/via)
+
+ لا
+ نعم
+
+ تأكيد الحذف
+ هل ترغب بالحذف؟
+ مشكلة في الإصدار
+ لقد تغير الإصدار الأساسي للصور المتجانبة، ما الإجراء المناسب لفعله؟
+ متابعة التنزيل الحالي، وحذف البيانات الأخرى القديمة
+ تحديد الكل للتنزيل والبدء
+ قم بالإلغاء في الوقت الحالي، واستكمله لاحقاً
+ اختلافات الإصدارات
+ الإصدار الأساسي لبعض الصور المتجانبة مختلف. ما الإجراء المناسب لفعله؟
+ تحميل المختلف من الصور المتجانبة
+ حذف كل الصور المتجانبة المختلفة عن الأخرى
+ قم بالإلغاء في الوقت الحالي، واستكمله لاحقاً
+ يحتاج إصدار البيانات الجديد إلى وجود التطبيق الجديد، لذا نرجوا منك تحديث BRouter أولاً
+
+ فشل التنزيل
+ تم إلغاء التنزيل
+ تم التنزيل بنجاح
+ جار التنزيل…
+
+
diff --git a/brouter-routing-app/src/main/res/values-ca/strings.xml b/brouter-routing-app/src/main/res/values-ca/strings.xml
new file mode 100644
index 0000000..9df7107
--- /dev/null
+++ b/brouter-routing-app/src/main/res/values-ca/strings.xml
@@ -0,0 +1,94 @@
+
+
+
+ - %d segment
+ - %d segments
+
+ Cancel·lar descàrrega
+ Importar perfil
+ Descàrrega %s
+ Eliminar %s
+ Actualitzar %s
+ Seleccionar segments
+ Aturar Descàrrega
+ Espai=%1$s\nLliure=%2$s
+ Descarregar segments
+
+ Escollir directori base brouter:
+ Seleccionar un perfil d\'enrutament
+ Seleccionar Acció Principal
+ Gestor de Baixades
+ App BRouter
+
+ Cancel·lar
+ Ho sé
+ Tancar
+ Sortir
+ D\'acord
+ Èxit
+ Ha aparegut un error
+
+ Gestor de baixades BRouter
+ *** 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.
+ S\'ha preparat correctament un càlcul sense límit de temps
+ 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.
+ Introdueix el directori base de la tarja SD:
+ Seleccionar Acció
+
+ Comprovar Selecció VIA:
+ Comprovar Selecció NoGo:
+ Mode-Servidor
+ Info
+ Calc Ruta
+ Ajustaments del perfil
+ Compartir GPX
+ Seleccionar des de
+ Seleccionar a/via
+
+ no hi ha dades al perfil
+ , cap perfil utilitzat
+ Massa dades per baixar. Si us plau, redueix-les.
+ Baixada programada. Comprovar la connexió a internet si no comença.
+ selecció actual de fita:\n
+ Esperant selecció de fita\n
+ Alternativa
+ 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
+ Error llegint fites
+ la font de coordenades no conté cap fita!
+ la font de coordenades conté massa fites: %1$d (si us plau, fes servir noms des de/a/via)
+
+ No
+ Si
+
+ Confirmar Eliminar
+ Voleu realment eliminar?
+ Problema de versió
+ La versió base per les tesel·les ha canviat. Què vols fer?
+ Continuar amb la baixada, eliminar altres dades antigues
+ Seleccionar-ho tot per baixar i iniciar
+ Cancel·lar ara, completar un altre dia
+ Diferències de Versió
+ La versió base de diverses tesel·les és diferent. Què vols fer?
+ Baixar totes les tesel·les diferents
+ Descartar les tesel·les diferents
+ Cancel·lar ara, completar un altre dia
+ La nova versió de dades necessita una aplicació nova. Sisplau, actualitza BRouter primer
+
+ Baixada fallida
+ Baixada cancel·lada
+ Baixada exitosa
+ Baixant…
+
+
diff --git a/brouter-routing-app/src/main/res/values-de/strings.xml b/brouter-routing-app/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000..902aa4d
--- /dev/null
+++ b/brouter-routing-app/src/main/res/values-de/strings.xml
@@ -0,0 +1,94 @@
+
+
+
+ - %d Segment
+ - %d Segmente
+
+ Download abbrechen
+ Profil importieren
+ %s downloaden
+ %s löschen
+ %s aktualisieren
+ Segmente auswählen
+ Download stoppen
+ Größe=%1$s\nFrei=%2$s
+ Segmente herunterladen
+
+ BRouter-Datenbankverzeichnis wählen:
+ Routenprofil wählen
+ Standardaktion wählen
+ Downloadmanager
+ BRouter-App
+
+ Abbrechen
+ Ich weiß
+ Schließen
+ Verlassen
+ OK
+ Erfolg
+ Ein Fehler ist aufgetreten
+
+ BRouter Downloadmanager
+ *** 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.
+ Berechnung ohne Zeitüberschreitung erfolgreich
+ 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.
+ SD-Karten Verzeichnis wählen:
+ Aktion wählen
+
+ Via-Auswahl prüfen:
+ NoGo-Auswahl prüfen:
+ Server-Modus
+ Info
+ Route berechnen
+ Profileinstellungen
+ GPX teilen
+ "Von" wählen
+ "Nach"/Via wählen
+
+ Keine Profildaten
+ , kein verwendetes Profil
+ Zu viele Daten für den Download. Bitte reduzieren.
+ Download geplant. Überprüfen Sie die Internetverbindung, wenn der Download nicht startet.
+ aktuelle Wegpunktauswahl:\n
+ Erwarte Wegpunktauswahl\n
+ Alternative
+ 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
+ Fehler beim Lesen von Wegpunkten
+ Die Koordinatenquelle enthält keine Wegpunkte!
+ Die Koordinatenquelle enthält zu viele Wegpunkte: %1$d (bitte von/nach/via-Namen verwenden)
+
+ Nein
+ Ja
+
+ Löschen bestätigen
+ Wirklich löschen?
+ Versionsproblem
+ Die Datenversion der Kacheln hat sich geändert. Bitte auswählen:
+ Download fortsetzen und alte Daten löschen?
+ Alle auswählen und Download starten
+ Abbrechen und später fortsetzen
+ Versionskonflikt
+ Die Datenversion für einige Kacheln ist unterschiedlich. Bitte auswählen:
+ Download alle unterschiedlichen Kacheln
+ Überspringe alle unterschiedlichen Kacheln
+ Abbrechen und später fortsetzen
+ Die neue Datenversion verlangt ein BRouter-Update. Bitte aktualisieren
+
+ Download fehlgeschlagen
+ Download abgebrochen
+ Download erfolgreich
+ Download läuft…
+
+
diff --git a/brouter-routing-app/src/main/res/values-el/strings.xml b/brouter-routing-app/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000..f5d098b
--- /dev/null
+++ b/brouter-routing-app/src/main/res/values-el/strings.xml
@@ -0,0 +1,94 @@
+
+
+
+ - %d τμήμα
+ - %d τμήματα
+
+ Ακύρωση λήψης
+ Εισαγωγή προφίλ
+ Λήψη %s
+ Διαγραφή %s
+ Ενημέρωση %s
+ Επιλογή τμημάτων
+ Διακοπή λήψης
+ Μέγεθος=%1$s\nΕλεύθερο=%2$s
+ Λήψη τμημάτων
+
+ Επιλέξτε φάκελο δεδομένων brouter:
+ Επιλέξτε ένα προφίλ δρομολόγησης
+ Επιλέξτε ενέργεια
+ Διαχειριστής λήψεων
+ Εφαρμογή BRouter
+
+ Ακύρωση
+ Γνωρίζω
+ Κλείσιμο
+ Έξοδος
+ OK
+ Επιτυχία
+ Παρουσιάστηκε σφάλμα
+
+ BRouter διαχειριστής λήψεων
+ *** Προσοχή:***
+ \n\nΟ διαχειριστής λήψεων χρησιμοποιείται για τη λήψη αρχείων δεδομένων δρομολόγησης
+ που μπορεί να είναι έως 170MB το καθένα. Μην ξεκινήσετε το διαχειριστή λήψεων
+ σε σύνδεση δεδομένων κινητής τηλεφωνίας χωρίς πρόγραμμα δεδομένων!
+ Η ταχύτητα λήψης περιορίζεται στα 16 MBit/s.
+ Ετοιμάστηκε επιτυχώς ένας υπολογισμός χωρίς χρονικό όριο
+ Επαναλάβατε με επιτυχία έναν υπολογισμό που πριν είχε χρονικό όριο
+ όταν ξεκίνησε από το εργαλείο χαρτών σας. Εάν επαναλάβετε το ίδιο αίτημα
+ από το εργαλείο χαρτών σας, με τον ίδιο ακριβώς προορισμό και μια κοντινή αφετηρία,
+ αυτό το αίτημα είναι εγγυημένο ότι δεν θα λήξει.
+ Εισάγετε φάκελο SDCARD:
+ Επιλέξτε ενέργεια
+
+ Ελέγξτε την επιλογή VIA:
+ Ελέγξτε την επιλογή NoGo:
+ Λειτουργία διακομιστή
+ Πληροφορίες
+ Υπολογισμός διαδρομής
+ Ρυθμίσεις προφίλ
+ Κοινή χρήση GPX
+ Επιλέξτε από
+ Επιλέξτε προς/μέσω
+
+ μη δεδομένα προφίλ
+ , μη χρησιμοποιημένο προφίλ
+ Πάρα πολλά δεδομένα για λήψη. Παρακαλώ μειώστε.
+ Προγραμματισμένη λήψη. Ελέγξτε τη σύνδεση στο διαδίκτυο εάν δεν ξεκινά.
+ τρέχουσα επιλογή σημείου:\n
+ Αναμένεται επιλογή σημείου\n
+ Εναλλακτική
+ έκδοση = BRouter-%1$s \n
+ μνήμη = %2$s \n
+ απόσταση = %3$s km\n
+ φιλτραρισμένη άνοδος = %4$s m\n
+ απλή άνοδος = %5$s m\n
+ εκτιμώμενος χρόνος = %6$s
+ Σφάλμα ανάγνωσης σημείων
+ η πηγή συντεταγμένων δεν περιέχει σημεία!
+ η πηγή συντεταγμένων περιέχει πάρα πολλά σημεία: %1$d (παρακαλώ χρησιμοποιήστε από/προς/μέσω ονόματα)
+
+ Όχι
+ Ναι
+
+ Επιβεβαίωση διαγραφής
+ Να γίνει διαγραφή;
+ Πρόβλημα έκδοσης
+ Η βασική έκδοση για τμήματα άλλαξε. Τι να κάνετε;
+ Συνέχεια με την τρέχουσα λήψη, διαγραφή άλλων παλαιών δεδομένων
+ Επιλέξτε όλα για λήψη και έναρξη
+ Ακύρωση τώρα, ολοκλήρωση άλλη μέρα
+ Διαφορές έκδοσης
+ Η βασική έκδοση για ορισμένα τμήματα είναι διαφορετική. Τι να κάνετε;
+ Λήψη όλων των διαφορετικών τμημάτων
+ Απόρριψη όλων των διαφορετικών τμημάτων
+ Ακύρωση τώρα, ολοκλήρωση άλλη μέρα
+ Η νέα έκδοση δεδομένων χρειάζεται νέα εφαρμογή. Ενημερώστε πρώτα το BRouter
+
+ Η λήψη απέτυχε
+ Η λήψη ακυρώθηκε
+ Η λήψη ολοκληρώθηκε
+ Λήψη…
+
+
diff --git a/brouter-routing-app/src/main/res/values-es/strings.xml b/brouter-routing-app/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000..37094da
--- /dev/null
+++ b/brouter-routing-app/src/main/res/values-es/strings.xml
@@ -0,0 +1,94 @@
+
+
+
+ - %d segmento
+ - %d segmentos
+
+ Cancelar descarga
+ Importar perfil
+ Descargar %s
+ Eliminar %s
+ Actualizar %s
+ Seleccionar segmentos
+ Detener descarga
+ Tamaño=%1$s\nGratis=%2$s
+ Descargar segmentos
+
+ Seleccionar directorio base brouter:
+ Seleccionar un perfil de enrutamiento
+ Seleccionar Acción Principal
+ Gestor de Descargas
+ App BRouter
+
+ Cancelar
+ Lo se
+ Cerrar
+ Salir
+ OK
+ Salir
+ Ha aparecido un error
+
+ Gestor de descargas BRouter
+ *** 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.
+ Se ha preparado correctamente un cálculo sin límite de tiempo
+ 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.
+ Introduce el directorio base de la tarjeta SD:
+ Seleccionar Acción
+
+ Comprobar Selección VIA:
+ Comprobar Selección NoGo:
+ Modo-Servidor
+ Info
+ Calc Ruta
+ Ajustes del perfil
+ Compartir GPX
+ Seleccionar desde
+ Seleccionar a/vía
+
+ no hay datos en el perfil
+ , ningún perfil utilizado
+ Demasiados datos a descargar. Por favor, reducidlos.
+ Descarga programada. Comprueba la conexión a internet si no se inicia.
+ selección actual de waypoint:\n
+ Esperando selección de waypoint\n
+ Alternativa
+ 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
+ Error leyendo waypoints
+ la fuente de coordenadas no contiene ningún waypoint!
+ la fuente de coordenadas contiene demasiados waypoints: %1$d (por favor, usa nombres desde/a/vía)
+
+ No
+ Si
+
+ Confirmar Eliminar
+ ¿Quieres realmente eliminar?
+ Problema de versión
+ La versión base para as teselas ha cambiado. ¿Qué quieres hacer?
+ Continuar con la descarga, eliminar otros datos antiguos
+ Seleccionar todo para descargar e iniciar
+ Cancelar ahora, completar otro día
+ Diferencias de versión
+ La versión base de varias teselas es distinta. ¿Qué quieres hacer?
+ Descargar todas las teselas distintas
+ Descartar las teselas distintas
+ Cancelar ahora, completar otro día
+ La nueva versión de datos necesita un aplicación nueva. Por favor, actualiza BRouter primero
+
+ Descarga fallida
+ Descarga cancelada
+ Descarga exitosa
+ Descargando…
+
+
diff --git a/brouter-routing-app/src/main/res/values-fr/strings.xml b/brouter-routing-app/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000..0b028f7
--- /dev/null
+++ b/brouter-routing-app/src/main/res/values-fr/strings.xml
@@ -0,0 +1,94 @@
+
+
+
+ - %d segment
+ - %d segments
+
+ Annuler le téléchargement
+ Importer le profil
+ Télécharger %s
+ Supprimer %s
+ Mettre à jour %s
+ Sélectionner les segments
+ Arrêter le téléchargement
+ Taille=%1$s\nGratuit=%2$s
+ Télécharger les segments
+
+ Choisissez le répertoire de la base de données brouter:
+ Sélectionnez un profil de routage
+ Sélectionner l\'action principale
+ Gestionnaire de téléchargement
+ Application BRouter
+
+ Annuler
+ Je sais
+ Fermer
+ Quitter
+ OK
+ Succès
+ Une erreur s\'est produite
+
+ Gestionnaire de téléchargement BRouter
+ *** 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.
+ Préparation réussie d\'un calcul sans délai d\'attente
+ 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.
+ Entrez le répertoire de base de la SDCARD:
+ Sélectionner une action
+
+ Vérifier la sélection VIA:
+ Vérifier la sélection NoGo:
+ Mode serveur
+ Informations
+ Calculer l\'itinéraire
+ Paramètres du profil
+ Partager GPX
+ Sélectionner de
+ Sélectionner vers/via
+
+ aucune donnée de profil
+ , aucun profil utilisé
+ Trop de données à télécharger. Veuillez réduire.
+ Téléchargement planifié. Vérifiez la connexion Internet si elle ne démarre pas.
+ sélection actuelle du waypoint:\n
+ Sélection de waypoint en attente\n
+ Alternative
+ 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
+ Erreur lors de la lecture des waypoints
+ la source de coordonnées ne contient aucun waypoint!
+ la source de coordonnées contient trop de waypoints: %1$d (veuillez utiliser les noms de/vers/via)
+
+ Non
+ Oui
+
+ Confirmer la suppression
+ Vraiment supprimer?
+ Problème de version
+ La version de base des vignettes a changé. Que faire?
+ Continuer le téléchargement en cours, supprimer les autres anciennes données
+ Sélectionnez tout pour télécharger et démarrer
+ Annuler maintenant, terminer un autre jour
+ Différences de version
+ La version de base de certaines vignettes est différente. Que faire?
+ Télécharger toutes les différentes vignettes
+ Supprimez toutes les différentes vignettes
+ Annuler maintenant, terminer un autre jour
+ La nouvelle version des données nécessite une nouvelle application. Veuillez d\'abord mettre à jour BRouter
+
+ Téléchargement échoué
+ Téléchargement annulé
+ Téléchargement réussi
+ Téléchargement…
+
+
diff --git a/brouter-routing-app/src/main/res/values-it/strings.xml b/brouter-routing-app/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000..c82a6e2
--- /dev/null
+++ b/brouter-routing-app/src/main/res/values-it/strings.xml
@@ -0,0 +1,94 @@
+
+
+
+ - %d segmento
+ - %d segmenti
+
+ Annulla download
+ Importa profilo
+ Scarica %s
+ Elimina %s
+ Aggiorna %s
+ Seleziona segmenti
+ Interrompi download
+ Taglia=%1$s\nGratis=%2$s
+ Scarica segmenti
+
+ Seleziona la directory del database brouter:
+ Seleziona un profilo di instradamento
+ Seleziona azione principale
+ Gestore dei download
+ Applicazione BRouter
+
+ Annulla
+ Lo so
+ Chiudi
+ Esci
+ OK
+ Successo
+ Si è verificato un errore
+
+ Gestore download BRouter
+ *** 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.
+ Preparato con successo un calcolo senza timeout
+ 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.
+ Inserisci la directory base della SDCARD:
+ Seleziona azione
+
+ Controlla la selezione VIA:
+ Controlla la selezione NoGo:
+ Modalità server
+ Informazioni
+ Calcola percorso
+ Impostazioni profilo
+ Condividi GPX
+ Seleziona da
+ Seleziona a/via
+
+ nessun dato del profilo
+ , nessun profilo utilizzato
+ Troppi dati per il download. Per favore riduci.
+ Download programmato. Controlla la connessione Internet se non si avvia.
+ selezione del waypoint corrente:\n
+ Attesa selezione waypoint\n
+ Alternativa
+ 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
+ Errore durante la lettura dei waypoint
+ la fonte delle coordinate non contiene alcun waypoint!
+ la fonte delle coordinate contiene troppi waypoint: %1$d (usa i nomi da/a/via)
+
+ No
+ Sì
+
+ Conferma eliminazione
+ Eliminare davvero?
+ Problema di versione
+ La versione base per i riquadri è cambiata. Cosa fare?
+ Continua con il download corrente, elimina altri vecchi dati
+ Seleziona tutto per il download e avvia
+ Annulla ora, completa un altro giorno
+ Differenze di versione
+ La versione base di alcuni riquadri è diversa. Cosa fare?
+ Scarica tutti i diversi riquadri
+ Rilascia tutti i diversi riquadri
+ Annulla ora, completa un altro giorno
+ La nuova versione dei dati necessita di una nuova app. Per favore aggiorna prima BRouter
+
+ Download fallito
+ Download annullato
+ Download riuscito
+ Download in corso…
+
+
diff --git a/brouter-routing-app/src/main/res/values-ko/strings.xml b/brouter-routing-app/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000..1c316ed
--- /dev/null
+++ b/brouter-routing-app/src/main/res/values-ko/strings.xml
@@ -0,0 +1,94 @@
+
+
+
+ - %d 구간
+ - %d 구간
+
+ 다운로드 취소
+ 프로필 가져오기
+ 다운로드 %s
+ 삭제 %s
+ 업데이트 %s
+ 구간 선택
+ 다운로드 중지
+ 크기=%1$s\n여유=%2$s
+ 구간 다운로드
+
+ brouter 데이터 베이스 선택 dir:
+ 루트 프로필 선택
+ 주 활동 선택
+ 다운로드 관리자
+ BRouter 앱
+
+ 취소
+ 알고 있습니다
+ 가까운
+ 나가기
+ OK
+ 성공
+ 에러가 발생됐습니다
+
+ BRouter 다운로드 관리자
+ *** 주의:***
+ \n\n다운로드 관리자는 라우팅 데이터를 다운로드하는 데 사용됩니다.
+ 파일당 최대 170MB까지 가능합니다. 다운로드 관리자를 시작하지 마십시오
+ 데이터 요금제 없이 셀룰러 데이터 연결로!
+ 다운로드 속도는 16 MBit/s로 제한됩니다.
+ 시간 초과 없는 계산을 성공적으로 준비했습니다
+ 이전에 시간 초과가 발생한 계산을 성공적으로 반복하셨습니다.
+ 지도 도구에서 시작할 때. 귀하가 귀하로부터 동일한 요청을 반복하는 경우
+ 정확히 동일한 목적지와 가까운 시작점이 있는 지도 도구,
+ 이 요청은 시간 초과되지 않음이 보장됩니다.
+ SDCARD 기본 디렉토리 입력:
+ 작업 선택
+
+ 경유 선택 체크:
+ NoGo 선택 체크:
+ 서버-모드
+ 정보
+ 루트 계산
+ 프로필 설정
+ GPX 공유
+ ~로부터 선택
+ 선택 ~로/경유하여
+
+ 프로필 데이터 없음
+ , 사용된 프로필 없음
+ 다운로드 하기에 너무 많은 데이터. 줄이도록 하세요.
+ 다운로드 계획되어 있음. 인터넷 연결 체크 그렇지 않다면 시작.
+ 현재 장소 선택:\n
+ 장소 선택 기대\n
+ 대체 가능한
+ 버전 = BRouter-%1$s \n
+ 메모리 = %2$s \n
+ 거리 = %3$s km\n
+ 필터링된 오름차순 = %4$s m\n
+ 일반 오름차순 = %5$s m\n
+ 예상 시간 = %6$s
+ 장소 읽는데 에러
+ 좌표정보는 어떤 장소도 포함하고 있지 않습니다!
+ 좌표정보는 너무 많은 장소를 포함하고 있습니다: %1$d (~로 부터/~로/경유 이름 사용하세요)
+
+ 아니요
+ 예
+
+ 삭제 확인
+ 정말 삭제하시겠습니까?
+ 버전 문제
+ 타일을 위한 기본 버전이 바뀌었습니다. 무엇을 해야죠?
+ 현재 다운로드 계속, 다른 오래된 데이터 삭제
+ 다운로드 위해 모두 선택하고 시작
+ 지금 취소, 다른 날 완료
+ 버전 차이
+ 어떤 타일을 위한 기본 버전은 다릅니다, 무엇을 해야죠?
+ 모든 다른 타일 다운로드
+ 모든 다른 타일 백지화
+ 지금 취소, 다른 날 완료
+ 새로운 데이터 버전은 새로운 앱을 필요로 합니다. 우선 BRouter를 업데이트 하세요
+
+ 다운로드 실패
+ 다운로드 취소됨
+ 다운로드 성공
+ 다운로딩…
+
+
diff --git a/brouter-routing-app/src/main/res/values-nl/strings.xml b/brouter-routing-app/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000..fea694a
--- /dev/null
+++ b/brouter-routing-app/src/main/res/values-nl/strings.xml
@@ -0,0 +1,94 @@
+
+
+
+ - %d segment
+ - %d segmenten
+
+ Download annuleren
+ Profiel importeren
+ Downloaden %s
+ Verwijderen %s
+ Bijwerken %s
+ Segmenten selecteren
+ Download stoppen
+ Grootte=%1$s\nGratis=%2$s
+ Segmenten downloaden
+
+ Kies de brouter database map:
+ Selecteer een routingprofiel
+ Selecteer de hoofdactie
+ Download beheerder
+ BRouter App
+
+ Annuleer
+ Ik weet het
+ Sluiten
+ Verlaat
+ OK
+ Succes
+ Er is een fout opgetreden
+
+ BRouter Download Manager
+ *** 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.
+ Een time-outvrije berekening is succesvol voorbereid
+ 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.
+ De SDCARD basis directory invoeren:
+ Actie selecteren
+
+ Controleer de VIA selectie:
+ Controleer de NoGo selectie:
+ Server-mode
+ Info
+ Bereken route
+ Profiel instellingen
+ GPX delen
+ Selecteer van
+ Selecteer naar/via
+
+ geen profiel data
+ , geen gebruikt profiel
+ Te veel gegevens om te downloaden. Verminder a.u.b.
+ Download is gepland. Controleer de internetverbinding als deze niet start.
+ huidige waypointselectie:\n
+ Verwacht waypointselectie\n
+ Alternatief
+ 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
+ Fout bij het lezen van waypoints
+ coördinaten bron bevat geen waypoints!
+ De coördinatenbron bevat te veel waypoints: %1$d (gebruik van/naar/via namen)
+
+ Nee
+ Ja
+
+ Verwijderen bevestigen
+ Echt verwijderen?
+ Versie probleem
+ De basisversie voor de tegels is gewijzigd. Wat moet er gebeuren?
+ Doorgaan met de huidige download, verwijder de oude gegevens.
+ Selecteer alles om te downloaden en start
+ Annuleer nu, voltooi op een andere dag
+ Versieverschillen
+ De basisversie voor sommige tiles is anders. Wat moet er gebeuren?
+ Download alle verschillende tegels
+ Laat alle verschillende tegels vallen
+ Annuleer nu, en voltooi op een andere dag
+ Voor de nieuwe gegevensversie is een nieuwe app nodig. Update eerst de BRouter
+
+ Download is mislukt
+ Download is geannuleerd
+ Download is geslaagd
+ Downloaden…
+
+
diff --git a/brouter-routing-app/src/main/res/values-pl/strings.xml b/brouter-routing-app/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000..6901240
--- /dev/null
+++ b/brouter-routing-app/src/main/res/values-pl/strings.xml
@@ -0,0 +1,94 @@
+
+
+
+ - %d segment
+ - %d segmenty/ów
+
+ Anuluj pobieranie
+ Importuj profil
+ Pobierz %s
+ Usuń %s
+ Zaktualizuj %s
+ Wybierz segmenty
+ Zatrzymaj pobieranie
+ Rozmiar=%1$s\nDostępne=%2$s
+ Pobieranie segmentów
+
+ Wybierz katalog bazy danych BRoutera:
+ Wybierz profil routingu
+ Wybierz akcję główną
+ Menedżer pobierania
+ Aplikacja BRouter
+
+ Anuluj
+ Rozumiem
+ Zamknij
+ Wyjdź
+ OK
+ Sukces
+ Wystąpił błąd
+
+ Menedżer pobierania BRoutera
+ *** 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.
+ Pomyślnie przygotowano obliczenia nie przekraczając limitu czasu
+ 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.
+ Wybierz katalog SDCARD dla bazy:
+ Wybierz akcję
+
+ Sprawdź wybór VIA:
+ Sprawdź wybór NoGo:
+ Tryb serwera
+ Informacje
+ Oblicz trasę
+ Ustawienia profilu
+ Udostępnij GPX
+ Wybierz z
+ Wybierz do/przez
+
+ brak danych profilu
+ , brak używanego profilu
+ Za dużo danych do pobrania. Proszę ogranicz.
+ Pobieranie zaplanowane. Jeśli się nie rozpocznie, sprawdź połączenie internetowe.
+ bieżący wybór punktu trasy:\n
+ Oczekuję na wybór punktu trasy\n
+ Alternatywa
+ 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
+ Błąd podczas odczytu punktów trasy
+ Źródło współrzędnych nie zawiera żadnych punktów trasy!
+ Źródło współrzędnych zawiera zbyt dużo punktów trasy: %1$d (proszę używać nazw z/do/przez)
+
+ Nie
+ Tak
+
+ Potwierdź usunięcie
+ Naprawdę usunąć?
+ Problem z wersją
+ Zmieniła się podstawowa wersja kafelków. Co robić?
+ Kontynuuj bieżące pobieranie, usuń inne stare dane
+ Wybierz wszystko i rozpocznij pobieranie
+ Anuluj teraz, dokończ innego dnia
+ Różnice wersji
+ Wersja podstawowa dla niektórych kafelków jest inna. Co robić?
+ Pobierz różne kafelki
+ Opuść wszystkie różne kafelki
+ Anuluj teraz, dokończ innego dnia
+ Nowa wersja danych wymaga nowej aplikacji. Najpierw zaktualizuj BRoutera
+
+ Pobieranie nie powiodło się
+ Pobieranie anulowane
+ Pobieranie powiodło się
+ Pobieranie…
+
+
diff --git a/brouter-routing-app/src/main/res/values/donottranslate-strings.xml b/brouter-routing-app/src/main/res/values/donottranslate-strings.xml
new file mode 100644
index 0000000..254dd8f
--- /dev/null
+++ b/brouter-routing-app/src/main/res/values/donottranslate-strings.xml
@@ -0,0 +1,7 @@
+
+
+ BRouter
+ filename.brf
+ brouter_download
+ Downloads
+
diff --git a/brouter-routing-app/src/main/res/values/strings.xml b/brouter-routing-app/src/main/res/values/strings.xml
index 168a26a..fe274ab 100644
--- a/brouter-routing-app/src/main/res/values/strings.xml
+++ b/brouter-routing-app/src/main/res/values/strings.xml
@@ -1,37 +1,95 @@
-
-
-
-
+
+
- %d segment
- %d segments
- BRouter
- Cancel Download
- Import Profile
- filename.brf
- Starting download…
- Cancelling…
+ Cancel download
+ Import profile
Download %s
Delete %s
Update %s
Select segments
- Stop Download
- Size=%s\nFree=%s
- brouter_download
- Download Segments
- Downloads
+ Stop download
+ Size=%1$s\nFree=%2$s
+ Download segments
+
+ Choose brouter data base dir:
+ Select a routing profile
+ Select Main Action
+ Download Manager
+ BRouter App
+
+ Cancel
+ I know
+ Close
+ Exit
+ OK
+ Success
+ An Error occurred
+
+ BRouter Download Manager
+ *** 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.
+ Successfully prepared a timeout-free calculation
+ 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.
+ Enter SDCARD base dir:
+ Select Action
+
+ Check VIA Selection:
+ Check NoGo Selection:
+ Server-Mode
+ Info
+ Calc Route
+ Profile Settings
+ Share GPX
+ Select from
+ Select to/via
+
+ no profile data
+ , no used profile
+ Too much data for download. Please reduce.
+ Download scheduled. Check internet connection if it doesn\'t start.
+ current waypoint selection:\n
+ Expecting waypoint selection\n
+ Alternative
+ 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
+ Error reading waypoints
+ coordinate source does not contain any waypoints!
+ coordinate source contains too much waypoints: %1$d (please use from/to/via names)
+
+ No
+ Yes
+
+ Confirm Delete
+ Really delete?
+ Version Problem
+ The base version for tiles has changed. What to do?
+ Continue with current download, delete other old data
+ Select all for download and start
+ Cancel now, complete on another day
+ Version Differences
+ The base version for some tiles is different. What to do?
+ Download all different tiles
+ Drop all different tiles
+ Cancel now, complete on another day
+ The new data version needs a new app. Please update BRouter first
+
+ Download failed
+ Download cancelled
+ Download succeeded
+ Downloading…
+
+
diff --git a/brouter-server/src/main/java/btools/server/BRouter.java b/brouter-server/src/main/java/btools/server/BRouter.java
index 3788e51..a6dfe10 100644
--- a/brouter-server/src/main/java/btools/server/BRouter.java
+++ b/brouter-server/src/main/java/btools/server/BRouter.java
@@ -30,6 +30,10 @@ public class BRouter {
List wplist = routingParamCollector.getWayPointList(lonlats);
Map 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());
diff --git a/brouter-server/src/main/java/btools/server/RouteServer.java b/brouter-server/src/main/java/btools/server/RouteServer.java
index bb5e98c..ba421f9 100644
--- a/brouter-server/src/main/java/btools/server/RouteServer.java
+++ b/brouter-server/src/main/java/btools/server/RouteServer.java
@@ -211,18 +211,29 @@ public class RouteServer extends Thread implements Comparable {
} 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 (track != null) {
- if (headers != null) { // compressed
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- Writer w = new OutputStreamWriter(new GZIPOutputStream(baos), "UTF-8");
- w.write(handler.formatTrack(track));
- w.close();
- bw.flush();
- clientSocket.getOutputStream().write(baos.toByteArray());
- } else {
- bw.write(handler.formatTrack(track));
+ if (engineMode == 0) {
+ if (track != null) {
+ if (headers != null) { // compressed
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ Writer w = new OutputStreamWriter(new GZIPOutputStream(baos), "UTF-8");
+ w.write(handler.formatTrack(track));
+ w.close();
+ bw.flush();
+ clientSocket.getOutputStream().write(baos.toByteArray());
+ } else {
+ bw.write(handler.formatTrack(track));
+ }
+ }
+ } else if (engineMode == 2) {
+ String s = cr.getFoundInfo();
+ if (s != null) {
+ bw.write(s);
}
}
}
diff --git a/brouter-server/src/main/java/btools/server/request/ServerHandler.java b/brouter-server/src/main/java/btools/server/request/ServerHandler.java
index 898121c..505fd2b 100644
--- a/brouter-server/src/main/java/btools/server/request/ServerHandler.java
+++ b/brouter-server/src/main/java/btools/server/request/ServerHandler.java
@@ -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;
diff --git a/brouter-util/src/main/java/btools/util/CompactLongMap.java b/brouter-util/src/main/java/btools/util/CompactLongMap.java
index b29d83a..49efc08 100644
--- a/brouter-util/src/main/java/btools/util/CompactLongMap.java
+++ b/brouter-util/src/main/java/btools/util/CompactLongMap.java
@@ -224,6 +224,7 @@ public class CompactLongMap {
// 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 {
return false;
}
+ @SuppressWarnings("unchecked")
protected void moveToFrozenArrays(long[] faid, List flv) {
for (int i = 1; i < MAXLISTS; i++) {
pa[i] = 0;
diff --git a/brouter-util/src/main/java/btools/util/SortedHeap.java b/brouter-util/src/main/java/btools/util/SortedHeap.java
index 3f2c4f1..b350d63 100644
--- a/brouter-util/src/main/java/btools/util/SortedHeap.java
+++ b/brouter-util/src/main/java/btools/util/SortedHeap.java
@@ -19,6 +19,7 @@ public final class SortedHeap {
/**
* @return the lowest key value, or null if none
*/
+ @SuppressWarnings("unchecked")
public V popLowestKeyValue() {
SortedBin bin = firstNonEmpty;
if (firstNonEmpty == null) {
diff --git a/misc/profiles2/fastbike.brf b/misc/profiles2/fastbike.brf
index 5c9e6a5..d51a880 100644
--- a/misc/profiles2/fastbike.brf
+++ b/misc/profiles2/fastbike.brf
@@ -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
diff --git a/misc/profiles2/hiking-mountain.brf b/misc/profiles2/hiking-mountain.brf
index c4ce1bc..688da66 100644
--- a/misc/profiles2/hiking-mountain.brf
+++ b/misc/profiles2/hiking-mountain.brf
@@ -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]
diff --git a/misc/profiles2/trekking.brf b/misc/profiles2/trekking.brf
index 3c8841a..b4aa6ed 100644
--- a/misc/profiles2/trekking.brf
+++ b/misc/profiles2/trekking.brf
@@ -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