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 000000000..37b740810 --- /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 000000000..0ed6cc5ba --- /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(""; + 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(""; + 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 000000000..a2c5b7a2f --- /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 000000000..5798c5ca1 --- /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 000000000..09bdb1da5 --- /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 ac3b51ffd..9ccff98e9 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 @@ 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 static class OsmPathElementHolder { private CompactLongMap detourMap; - private VoiceHintList voiceHints; + public VoiceHintList voiceHints; public String message = null; public List messageList = null; @@ -178,7 +165,7 @@ public void buildMap() { 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 @@ private List aggregateMessages() { return res; } - private List aggregateSpeedProfile() { + public List aggregateSpeedProfile() { ArrayList res = new ArrayList<>(); int vmax = -1; int vmaxe = -1; @@ -395,752 +382,9 @@ public void appendTrack(OsmTrack t) { 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(""; - if (mwpt != null && mwpt.direct) { - bNextDirect = true; - } - sele += "pass_place"; - sele += "Via"; - - } else if (idx == nodes.size() - 1 && hint == null) { - - int pos = sele.indexOf(""; - 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 @@ private VoiceHint getVoiceHint(int i) { 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 @@ private int getVNode(int i) { 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 @@ int getMinDistance() { 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 baff3dca4..105ed0952 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 void doRouting(long maxRunningTime) { 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 void doRouting(long maxRunningTime) { } if (logfileBase != null) { String logfilename = logfileBase + i + ".csv"; - track.dumpMessages(logfilename, routingContext); + new FormatCsv(routingContext).write(logfilename, track); } break; } @@ -308,15 +344,31 @@ public void doGetElev() { 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 @@ private OsmTrack searchRoutedTrack(MatchedWaypoint startWp, MatchedWaypoint endW 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 @@ private OsmTrack _findTrack(String operationName, MatchedWaypoint startWp, Match 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 int getPlainAscend() { } public String getTime() { - return foundTrack.getFormattedTime2(); + return Formatter.getFormattedTime2(foundTrack.getTotalSeconds()); } public OsmTrack getFoundTrack() { 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 8d6ea4e60..90b875cb2 100644 --- a/brouter-routing-app/src/main/java/btools/routingapp/BRouterService.java +++ b/brouter-routing-app/src/main/java/btools/routingapp/BRouterService.java @@ -100,7 +100,7 @@ public String getTrackFromParams(Bundle params) throws RemoteException { boolean canCompress = "true".equals(params.getString("acceptCompressedResult")); try { String gpxMessage = worker.getTrackFromParams(params); - if (canCompress && gpxMessage.startsWith("<")) { + if (canCompress) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.write("z64".getBytes(Charset.forName("UTF-8"))); // marker prefix 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 5823db5b1..64e73d53e 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.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; @@ -151,42 +154,41 @@ public String getTrackFromParams(Bundle params) { 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-server/src/main/java/btools/server/BRouter.java b/brouter-server/src/main/java/btools/server/BRouter.java index 3788e51aa..a6dfe1037 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 static void main(String[] args) throws Exception { 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 static void main(String[] args) throws Exception { 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 bb5e98cbc..ba421f9f0 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 void run() { } 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 898121c66..505fd2b2d 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 String formatTrack(OsmTrack track) { } 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;