added new format classes
This commit is contained in:
parent
c6473055f4
commit
56dbd52065
5 changed files with 985 additions and 0 deletions
43
brouter-core/src/main/java/btools/router/FormatCsv.java
Normal file
43
brouter-core/src/main/java/btools/router/FormatCsv.java
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package btools.router;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
public class FormatCsv extends Formatter {
|
||||||
|
|
||||||
|
|
||||||
|
public FormatCsv(RoutingContext rc) {
|
||||||
|
super(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String format(OsmTrack t) {
|
||||||
|
try {
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
BufferedWriter bw = new BufferedWriter(sw);
|
||||||
|
writeMessages(bw, t);
|
||||||
|
return sw.toString();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
return "Error: " + ex.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeMessages(BufferedWriter bw, OsmTrack t) throws Exception {
|
||||||
|
dumpLine(bw, MESSAGES_HEADER);
|
||||||
|
for (String m : t.aggregateMessages()) {
|
||||||
|
dumpLine(bw, m);
|
||||||
|
}
|
||||||
|
if (bw != null)
|
||||||
|
bw.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dumpLine(BufferedWriter bw, String s) throws Exception {
|
||||||
|
if (bw == null) {
|
||||||
|
System.out.println(s);
|
||||||
|
} else {
|
||||||
|
bw.write(s);
|
||||||
|
bw.write("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
532
brouter-core/src/main/java/btools/router/FormatGpx.java
Normal file
532
brouter-core/src/main/java/btools/router/FormatGpx.java
Normal file
|
@ -0,0 +1,532 @@
|
||||||
|
package btools.router;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import btools.mapaccess.MatchedWaypoint;
|
||||||
|
import btools.util.StringUtils;
|
||||||
|
|
||||||
|
public class FormatGpx extends Formatter {
|
||||||
|
public FormatGpx(RoutingContext rc) {
|
||||||
|
super(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String format(OsmTrack t) {
|
||||||
|
try {
|
||||||
|
StringWriter sw = new StringWriter(8192);
|
||||||
|
BufferedWriter bw = new BufferedWriter(sw);
|
||||||
|
formatAsGpx(bw, t);
|
||||||
|
bw.close();
|
||||||
|
return sw.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String formatAsGpx(BufferedWriter sb, OsmTrack t) throws IOException {
|
||||||
|
int turnInstructionMode = t.voiceHints != null ? t.voiceHints.turnInstructionMode : 0;
|
||||||
|
|
||||||
|
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||||
|
if (turnInstructionMode != 9) {
|
||||||
|
for (int i = t.messageList.size() - 1; i >= 0; i--) {
|
||||||
|
String message = t.messageList.get(i);
|
||||||
|
if (i < t.messageList.size() - 1)
|
||||||
|
message = "(alt-index " + i + ": " + message + " )";
|
||||||
|
if (message != null)
|
||||||
|
sb.append("<!-- ").append(message).append(" -->\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (turnInstructionMode == 4) { // comment style
|
||||||
|
sb.append("<!-- $transport-mode$").append(t.voiceHints.getTransportMode()).append("$ -->\n");
|
||||||
|
sb.append("<!-- cmd idx lon lat d2next geometry -->\n");
|
||||||
|
sb.append("<!-- $turn-instruction-start$\n");
|
||||||
|
for (VoiceHint hint : t.voiceHints.list) {
|
||||||
|
sb.append(String.format(" $turn$%6s;%6d;%10s;%10s;%6d;%s$\n", hint.getCommandString(), hint.indexInTrack,
|
||||||
|
formatILon(hint.ilon), formatILat(hint.ilat), (int) (hint.distanceToNext), hint.formatGeometry()));
|
||||||
|
}
|
||||||
|
sb.append(" $turn-instruction-end$ -->\n");
|
||||||
|
}
|
||||||
|
sb.append("<gpx \n");
|
||||||
|
sb.append(" xmlns=\"http://www.topografix.com/GPX/1/1\" \n");
|
||||||
|
sb.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n");
|
||||||
|
if (turnInstructionMode == 9) { // BRouter style
|
||||||
|
sb.append(" xmlns:brouter=\"Not yet documented\" \n");
|
||||||
|
}
|
||||||
|
if (turnInstructionMode == 7) { // old locus style
|
||||||
|
sb.append(" xmlns:locus=\"http://www.locusmap.eu\" \n");
|
||||||
|
}
|
||||||
|
sb.append(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" \n");
|
||||||
|
|
||||||
|
if (turnInstructionMode == 3) {
|
||||||
|
sb.append(" creator=\"OsmAndRouter\" version=\"1.1\">\n");
|
||||||
|
} else {
|
||||||
|
sb.append(" creator=\"BRouter-" + t.version + "\" version=\"1.1\">\n");
|
||||||
|
}
|
||||||
|
if (turnInstructionMode == 9) {
|
||||||
|
sb.append(" <metadata>\n");
|
||||||
|
sb.append(" <name>").append(t.name).append("</name>\n");
|
||||||
|
sb.append(" <extensions>\n");
|
||||||
|
sb.append(" <brouter:info>").append(t.messageList.get(0)).append("</brouter:info>\n");
|
||||||
|
if (t.params != null && t.params.size() > 0) {
|
||||||
|
sb.append(" <brouter:params><![CDATA[");
|
||||||
|
int i = 0;
|
||||||
|
for (Map.Entry<String, String> e : t.params.entrySet()) {
|
||||||
|
if (i++ != 0) sb.append("&");
|
||||||
|
sb.append(e.getKey()).append("=").append(e.getValue());
|
||||||
|
}
|
||||||
|
sb.append("]]></brouter:params>\n");
|
||||||
|
}
|
||||||
|
sb.append(" </extensions>\n");
|
||||||
|
sb.append(" </metadata>\n");
|
||||||
|
}
|
||||||
|
if (turnInstructionMode == 3 || turnInstructionMode == 8) { // osmand style, cruiser
|
||||||
|
float lastRteTime = 0;
|
||||||
|
|
||||||
|
sb.append(" <rte>\n");
|
||||||
|
|
||||||
|
float rteTime = t.getVoiceHintTime(0);
|
||||||
|
StringBuffer first = new StringBuffer();
|
||||||
|
// define start point
|
||||||
|
{
|
||||||
|
first.append(" <rtept lat=\"").append(formatILat(t.nodes.get(0).getILat())).append("\" lon=\"")
|
||||||
|
.append(formatILon(t.nodes.get(0).getILon())).append("\">\n")
|
||||||
|
.append(" <desc>start</desc>\n <extensions>\n");
|
||||||
|
if (rteTime != lastRteTime) { // add timing only if available
|
||||||
|
double ti = rteTime - lastRteTime;
|
||||||
|
first.append(" <time>").append("" + (int) (ti + 0.5)).append("</time>\n");
|
||||||
|
lastRteTime = rteTime;
|
||||||
|
}
|
||||||
|
first.append(" <offset>0</offset>\n </extensions>\n </rtept>\n");
|
||||||
|
}
|
||||||
|
if (turnInstructionMode == 8) {
|
||||||
|
if (t.matchedWaypoints.get(0).direct && t.voiceHints.list.get(0).indexInTrack == 0) {
|
||||||
|
// has a voice hint do nothing, voice hint will do
|
||||||
|
} else {
|
||||||
|
sb.append(first.toString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append(first.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < t.voiceHints.list.size(); i++) {
|
||||||
|
VoiceHint hint = t.voiceHints.list.get(i);
|
||||||
|
sb.append(" <rtept lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
|
||||||
|
.append(formatILon(hint.ilon)).append("\">\n")
|
||||||
|
.append(" <desc>")
|
||||||
|
.append(turnInstructionMode == 3 ? hint.getMessageString() : hint.getCruiserMessageString())
|
||||||
|
.append("</desc>\n <extensions>\n");
|
||||||
|
|
||||||
|
rteTime = t.getVoiceHintTime(i + 1);
|
||||||
|
|
||||||
|
if (rteTime != lastRteTime) { // add timing only if available
|
||||||
|
double ti = rteTime - lastRteTime;
|
||||||
|
sb.append(" <time>").append("" + (int) (ti + 0.5)).append("</time>\n");
|
||||||
|
lastRteTime = rteTime;
|
||||||
|
}
|
||||||
|
sb.append(" <turn>")
|
||||||
|
.append(turnInstructionMode == 3 ? hint.getCommandString() : hint.getCruiserCommandString())
|
||||||
|
.append("</turn>\n <turn-angle>").append("" + (int) hint.angle)
|
||||||
|
.append("</turn-angle>\n <offset>").append("" + hint.indexInTrack).append("</offset>\n </extensions>\n </rtept>\n");
|
||||||
|
}
|
||||||
|
sb.append(" <rtept lat=\"").append(formatILat(t.nodes.get(t.nodes.size() - 1).getILat())).append("\" lon=\"")
|
||||||
|
.append(formatILon(t.nodes.get(t.nodes.size() - 1).getILon())).append("\">\n")
|
||||||
|
.append(" <desc>destination</desc>\n <extensions>\n");
|
||||||
|
sb.append(" <time>0</time>\n");
|
||||||
|
sb.append(" <offset>").append("" + (t.nodes.size() - 1)).append("</offset>\n </extensions>\n </rtept>\n");
|
||||||
|
|
||||||
|
sb.append("</rte>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (turnInstructionMode == 7) { // old locus style
|
||||||
|
float lastRteTime = t.getVoiceHintTime(0);
|
||||||
|
|
||||||
|
for (int i = 0; i < t.voiceHints.list.size(); i++) {
|
||||||
|
VoiceHint hint = t.voiceHints.list.get(i);
|
||||||
|
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
|
||||||
|
.append(formatILat(hint.ilat)).append("\">")
|
||||||
|
.append(hint.selev == Short.MIN_VALUE ? "" : "<ele>" + (hint.selev / 4.) + "</ele>")
|
||||||
|
.append("<name>").append(hint.getMessageString()).append("</name>")
|
||||||
|
.append("<extensions><locus:rteDistance>").append("" + hint.distanceToNext).append("</locus:rteDistance>");
|
||||||
|
float rteTime = t.getVoiceHintTime(i + 1);
|
||||||
|
if (rteTime != lastRteTime) { // add timing only if available
|
||||||
|
double ti = rteTime - lastRteTime;
|
||||||
|
double speed = hint.distanceToNext / ti;
|
||||||
|
sb.append("<locus:rteTime>").append("" + ti).append("</locus:rteTime>")
|
||||||
|
.append("<locus:rteSpeed>").append("" + speed).append("</locus:rteSpeed>");
|
||||||
|
lastRteTime = rteTime;
|
||||||
|
}
|
||||||
|
sb.append("<locus:rtePointAction>").append("" + hint.getLocusAction()).append("</locus:rtePointAction></extensions>")
|
||||||
|
.append("</wpt>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (turnInstructionMode == 5) { // gpsies style
|
||||||
|
for (VoiceHint hint : t.voiceHints.list) {
|
||||||
|
sb.append(" <wpt lon=\"").append(formatILon(hint.ilon)).append("\" lat=\"")
|
||||||
|
.append(formatILat(hint.ilat)).append("\">")
|
||||||
|
.append("<name>").append(hint.getMessageString()).append("</name>")
|
||||||
|
.append("<sym>").append(hint.getSymbolString().toLowerCase()).append("</sym>")
|
||||||
|
.append("<type>").append(hint.getSymbolString()).append("</type>")
|
||||||
|
.append("</wpt>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (turnInstructionMode == 6) { // orux style
|
||||||
|
for (VoiceHint hint : t.voiceHints.list) {
|
||||||
|
sb.append(" <wpt lat=\"").append(formatILat(hint.ilat)).append("\" lon=\"")
|
||||||
|
.append(formatILon(hint.ilon)).append("\">")
|
||||||
|
.append(hint.selev == Short.MIN_VALUE ? "" : "<ele>" + (hint.selev / 4.) + "</ele>")
|
||||||
|
.append("<extensions>\n" +
|
||||||
|
" <om:oruxmapsextensions xmlns:om=\"http://www.oruxmaps.com/oruxmapsextensions/1/0\">\n" +
|
||||||
|
" <om:ext type=\"ICON\" subtype=\"0\">").append("" + hint.getOruxAction())
|
||||||
|
.append("</om:ext>\n" +
|
||||||
|
" </om:oruxmapsextensions>\n" +
|
||||||
|
" </extensions>\n" +
|
||||||
|
" </wpt>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i <= t.pois.size() - 1; i++) {
|
||||||
|
OsmNodeNamed poi = t.pois.get(i);
|
||||||
|
sb.append(" <wpt lon=\"").append(formatILon(poi.ilon)).append("\" lat=\"")
|
||||||
|
.append(formatILat(poi.ilat)).append("\">\n")
|
||||||
|
.append(" <name>").append(StringUtils.escapeXml10(poi.name)).append("</name>\n")
|
||||||
|
.append(" </wpt>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.exportWaypoints) {
|
||||||
|
for (int i = 0; i <= t.matchedWaypoints.size() - 1; i++) {
|
||||||
|
MatchedWaypoint wt = t.matchedWaypoints.get(i);
|
||||||
|
sb.append(" <wpt lon=\"").append(formatILon(wt.waypoint.ilon)).append("\" lat=\"")
|
||||||
|
.append(formatILat(wt.waypoint.ilat)).append("\">\n")
|
||||||
|
.append(" <name>").append(StringUtils.escapeXml10(wt.name)).append("</name>\n");
|
||||||
|
if (i == 0) {
|
||||||
|
sb.append(" <type>from</type>\n");
|
||||||
|
} else if (i == t.matchedWaypoints.size() - 1) {
|
||||||
|
sb.append(" <type>to</type>\n");
|
||||||
|
} else {
|
||||||
|
sb.append(" <type>via</type>\n");
|
||||||
|
}
|
||||||
|
sb.append(" </wpt>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(" <trk>\n");
|
||||||
|
if (turnInstructionMode == 9
|
||||||
|
|| turnInstructionMode == 2
|
||||||
|
|| turnInstructionMode == 8
|
||||||
|
|| turnInstructionMode == 4) { // Locus, comment, cruise, brouter style
|
||||||
|
sb.append(" <src>").append(t.name).append("</src>\n");
|
||||||
|
sb.append(" <type>").append(t.voiceHints.getTransportMode()).append("</type>\n");
|
||||||
|
} else {
|
||||||
|
sb.append(" <name>").append(t.name).append("</name>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (turnInstructionMode == 7) {
|
||||||
|
sb.append(" <extensions>\n");
|
||||||
|
sb.append(" <locus:rteComputeType>").append("" + t.voiceHints.getLocusRouteType()).append("</locus:rteComputeType>\n");
|
||||||
|
sb.append(" <locus:rteSimpleRoundabouts>1</locus:rteSimpleRoundabouts>\n");
|
||||||
|
sb.append(" </extensions>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// all points
|
||||||
|
sb.append(" <trkseg>\n");
|
||||||
|
String lastway = "";
|
||||||
|
boolean bNextDirect = false;
|
||||||
|
OsmPathElement nn = null;
|
||||||
|
String aSpeed;
|
||||||
|
|
||||||
|
for (int idx = 0; idx < t.nodes.size(); idx++) {
|
||||||
|
OsmPathElement n = t.nodes.get(idx);
|
||||||
|
String sele = n.getSElev() == Short.MIN_VALUE ? "" : "<ele>" + n.getElev() + "</ele>";
|
||||||
|
VoiceHint hint = t.getVoiceHint(idx);
|
||||||
|
MatchedWaypoint mwpt = t.getMatchedWaypoint(idx);
|
||||||
|
|
||||||
|
if (t.showTime) {
|
||||||
|
sele += "<time>" + t.getFormattedTime3(n.getTime()) + "</time>";
|
||||||
|
}
|
||||||
|
if (turnInstructionMode == 8) {
|
||||||
|
if (mwpt != null &&
|
||||||
|
!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
|
||||||
|
sele += "<name>" + mwpt.name + "</name>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean bNeedHeader = false;
|
||||||
|
if (turnInstructionMode == 9) { // trkpt/sym style
|
||||||
|
|
||||||
|
if (hint != null) {
|
||||||
|
|
||||||
|
if (mwpt != null &&
|
||||||
|
!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
|
||||||
|
sele += "<name>" + mwpt.name + "</name>";
|
||||||
|
}
|
||||||
|
sele += "<desc>" + hint.getCruiserMessageString() + "</desc>";
|
||||||
|
sele += "<sym>" + hint.getCommandString(hint.cmd) + "</sym>";
|
||||||
|
if (mwpt != null) {
|
||||||
|
sele += "<type>Via</type>";
|
||||||
|
}
|
||||||
|
sele += "<extensions>";
|
||||||
|
if (t.showspeed) {
|
||||||
|
double speed = 0;
|
||||||
|
if (nn != null) {
|
||||||
|
int dist = n.calcDistance(nn);
|
||||||
|
float dt = n.getTime() - nn.getTime();
|
||||||
|
if (dt != 0.f) {
|
||||||
|
speed = ((3.6f * dist) / dt + 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sele += "<brouter:speed>" + (((int) (speed * 10)) / 10.f) + "</brouter:speed>";
|
||||||
|
}
|
||||||
|
|
||||||
|
sele += "<brouter:voicehint>" + hint.getCommandString() + ";" + (int) (hint.distanceToNext) + "," + hint.formatGeometry() + "</brouter:voicehint>";
|
||||||
|
if (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway)) {
|
||||||
|
sele += "<brouter:way>" + n.message.wayKeyValues + "</brouter:way>";
|
||||||
|
lastway = n.message.wayKeyValues;
|
||||||
|
}
|
||||||
|
if (n.message != null && n.message.nodeKeyValues != null) {
|
||||||
|
sele += "<brouter:node>" + n.message.nodeKeyValues + "</brouter:node>";
|
||||||
|
}
|
||||||
|
sele += "</extensions>";
|
||||||
|
|
||||||
|
}
|
||||||
|
if (idx == 0 && hint == null) {
|
||||||
|
if (mwpt != null && mwpt.direct) {
|
||||||
|
sele += "<desc>beeline</desc>";
|
||||||
|
} else {
|
||||||
|
sele += "<desc>start</desc>";
|
||||||
|
}
|
||||||
|
sele += "<type>Via</type>";
|
||||||
|
|
||||||
|
} else if (idx == t.nodes.size() - 1 && hint == null) {
|
||||||
|
|
||||||
|
sele += "<desc>end</desc>";
|
||||||
|
sele += "<type>Via</type>";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (mwpt != null && hint == null) {
|
||||||
|
if (mwpt.direct) {
|
||||||
|
// bNextDirect = true;
|
||||||
|
sele += "<desc>beeline</desc>";
|
||||||
|
} else {
|
||||||
|
sele += "<desc>" + mwpt.name + "</desc>";
|
||||||
|
}
|
||||||
|
sele += "<type>Via</type>";
|
||||||
|
bNextDirect = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (hint == null) {
|
||||||
|
bNeedHeader = (t.showspeed || (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway))) ||
|
||||||
|
(n.message != null && n.message.nodeKeyValues != null);
|
||||||
|
if (bNeedHeader) {
|
||||||
|
sele += "<extensions>";
|
||||||
|
if (t.showspeed) {
|
||||||
|
double speed = 0;
|
||||||
|
if (nn != null) {
|
||||||
|
int dist = n.calcDistance(nn);
|
||||||
|
float dt = n.getTime() - nn.getTime();
|
||||||
|
if (dt != 0.f) {
|
||||||
|
speed = ((3.6f * dist) / dt + 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sele += "<brouter:speed>" + (((int) (speed * 10)) / 10.f) + "</brouter:speed>";
|
||||||
|
}
|
||||||
|
if (n.message != null && n.message.wayKeyValues != null && !n.message.wayKeyValues.equals(lastway)) {
|
||||||
|
sele += "<brouter:way>" + n.message.wayKeyValues + "</brouter:way>";
|
||||||
|
lastway = n.message.wayKeyValues;
|
||||||
|
}
|
||||||
|
if (n.message != null && n.message.nodeKeyValues != null) {
|
||||||
|
sele += "<brouter:node>" + n.message.nodeKeyValues + "</brouter:node>";
|
||||||
|
}
|
||||||
|
sele += "</extensions>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (turnInstructionMode == 2) { // locus style new
|
||||||
|
if (hint != null) {
|
||||||
|
if (mwpt != null) {
|
||||||
|
if (!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
|
||||||
|
sele += "<name>" + mwpt.name + "</name>";
|
||||||
|
}
|
||||||
|
if (mwpt.direct && bNextDirect) {
|
||||||
|
sele += "<src>" + hint.getLocusSymbolString() + "</src><sym>pass_place</sym><type>Shaping</type>";
|
||||||
|
// bNextDirect = false;
|
||||||
|
} else if (mwpt.direct) {
|
||||||
|
if (idx == 0)
|
||||||
|
sele += "<sym>pass_place</sym><type>Via</type>";
|
||||||
|
else
|
||||||
|
sele += "<sym>pass_place</sym><type>Shaping</type>";
|
||||||
|
bNextDirect = true;
|
||||||
|
} else if (bNextDirect) {
|
||||||
|
sele += "<src>beeline</src><sym>" + hint.getLocusSymbolString() + "</sym><type>Shaping</type>";
|
||||||
|
bNextDirect = false;
|
||||||
|
} else {
|
||||||
|
sele += "<sym>" + hint.getLocusSymbolString() + "</sym><type>Via</type>";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sele += "<sym>" + hint.getLocusSymbolString() + "</sym>";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (idx == 0 && hint == null) {
|
||||||
|
|
||||||
|
int pos = sele.indexOf("<sym");
|
||||||
|
if (pos != -1) {
|
||||||
|
sele = sele.substring(0, pos);
|
||||||
|
}
|
||||||
|
if (mwpt != null && !mwpt.name.startsWith("from"))
|
||||||
|
sele += "<name>" + mwpt.name + "</name>";
|
||||||
|
if (mwpt != null && mwpt.direct) {
|
||||||
|
bNextDirect = true;
|
||||||
|
}
|
||||||
|
sele += "<sym>pass_place</sym>";
|
||||||
|
sele += "<type>Via</type>";
|
||||||
|
|
||||||
|
} else if (idx == t.nodes.size() - 1 && hint == null) {
|
||||||
|
|
||||||
|
int pos = sele.indexOf("<sym");
|
||||||
|
if (pos != -1) {
|
||||||
|
sele = sele.substring(0, pos);
|
||||||
|
}
|
||||||
|
if (mwpt != null && mwpt.name != null && !mwpt.name.startsWith("to"))
|
||||||
|
sele += "<name>" + mwpt.name + "</name>";
|
||||||
|
if (bNextDirect) {
|
||||||
|
sele += "<src>beeline</src>";
|
||||||
|
}
|
||||||
|
sele += "<sym>pass_place</sym>";
|
||||||
|
sele += "<type>Via</type>";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (mwpt != null) {
|
||||||
|
if (!mwpt.name.startsWith("via") && !mwpt.name.startsWith("from") && !mwpt.name.startsWith("to")) {
|
||||||
|
sele += "<name>" + mwpt.name + "</name>";
|
||||||
|
}
|
||||||
|
if (mwpt.direct && bNextDirect) {
|
||||||
|
sele += "<src>beeline</src><sym>pass_place</sym><type>Shaping</type>";
|
||||||
|
} else if (mwpt.direct) {
|
||||||
|
if (idx == 0)
|
||||||
|
sele += "<sym>pass_place</sym><type>Via</type>";
|
||||||
|
else
|
||||||
|
sele += "<sym>pass_place</sym><type>Shaping</type>";
|
||||||
|
bNextDirect = true;
|
||||||
|
} else if (bNextDirect) {
|
||||||
|
sele += "<src>beeline</src><sym>pass_place</sym><type>Shaping</type>";
|
||||||
|
bNextDirect = false;
|
||||||
|
} else if (mwpt.name.startsWith("via") ||
|
||||||
|
mwpt.name.startsWith("from") ||
|
||||||
|
mwpt.name.startsWith("to")) {
|
||||||
|
if (bNextDirect) {
|
||||||
|
sele += "<src>beeline</src><sym>pass_place</sym><type>Shaping</type>";
|
||||||
|
} else {
|
||||||
|
sele += "<sym>pass_place</sym><type>Via</type>";
|
||||||
|
}
|
||||||
|
bNextDirect = false;
|
||||||
|
} else {
|
||||||
|
sele += "<name>" + mwpt.name + "</name>";
|
||||||
|
sele += "<sym>pass_place</sym><type>Via</type>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(" <trkpt lon=\"").append(formatILon(n.getILon())).append("\" lat=\"")
|
||||||
|
.append(formatILat(n.getILat())).append("\">").append(sele).append("</trkpt>\n");
|
||||||
|
|
||||||
|
nn = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(" </trkseg>\n");
|
||||||
|
sb.append(" </trk>\n");
|
||||||
|
sb.append("</gpx>\n");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String formatAsWaypoint(OsmNodeNamed n) {
|
||||||
|
try {
|
||||||
|
StringWriter sw = new StringWriter(8192);
|
||||||
|
BufferedWriter bw = new BufferedWriter(sw);
|
||||||
|
formatGpxHeader(bw);
|
||||||
|
formatWaypointGpx(bw, n);
|
||||||
|
formatGpxFooter(bw);
|
||||||
|
bw.close();
|
||||||
|
sw.close();
|
||||||
|
return sw.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void formatGpxHeader(BufferedWriter sb) throws IOException {
|
||||||
|
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||||
|
sb.append("<gpx \n");
|
||||||
|
sb.append(" xmlns=\"http://www.topografix.com/GPX/1/1\" \n");
|
||||||
|
sb.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n");
|
||||||
|
sb.append(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\" \n");
|
||||||
|
sb.append(" creator=\"BRouter-" + OsmTrack.version + "\" version=\"1.1\">\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void formatGpxFooter(BufferedWriter sb) throws IOException {
|
||||||
|
sb.append("</gpx>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void formatWaypointGpx(BufferedWriter sb, OsmNodeNamed n) throws IOException {
|
||||||
|
sb.append(" <wpt lon=\"").append(formatILon(n.ilon)).append("\" lat=\"")
|
||||||
|
.append(formatILat(n.ilat)).append("\">");
|
||||||
|
if (n.getSElev() != Short.MIN_VALUE) {
|
||||||
|
sb.append("<ele>").append("" + n.getElev()).append("</ele>");
|
||||||
|
}
|
||||||
|
if (n.name != null) {
|
||||||
|
sb.append("<name>").append(StringUtils.escapeXml10(n.name)).append("</name>");
|
||||||
|
}
|
||||||
|
if (n.nodeDescription != null && rc != null) {
|
||||||
|
sb.append("<desc>").append(rc.expctxWay.getKeyValueDescription(false, n.nodeDescription)).append("</desc>");
|
||||||
|
}
|
||||||
|
sb.append("</wpt>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWaypoint(int ilon, int ilat, String name, String desc) {
|
||||||
|
return "<wpt lon=\"" + formatILon(ilon) + "\" lat=\"" + formatILat(ilat) + "\"><name>" + name + "</name>" + (desc != null ? "<desc>" + desc + "</desc>" : "") + "</wpt>";
|
||||||
|
}
|
||||||
|
|
||||||
|
public OsmTrack read(String filename) throws Exception {
|
||||||
|
File f = new File(filename);
|
||||||
|
if (!f.exists()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
OsmTrack track = new OsmTrack();
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
|
||||||
|
|
||||||
|
for (; ; ) {
|
||||||
|
String line = br.readLine();
|
||||||
|
if (line == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
int idx0 = line.indexOf("<trkpt ");
|
||||||
|
if (idx0 >= 0) {
|
||||||
|
idx0 = line.indexOf(" lon=\"");
|
||||||
|
idx0 += 6;
|
||||||
|
int idx1 = line.indexOf('"', idx0);
|
||||||
|
int ilon = (int) ((Double.parseDouble(line.substring(idx0, idx1)) + 180.) * 1000000. + 0.5);
|
||||||
|
int idx2 = line.indexOf(" lat=\"");
|
||||||
|
if (idx2 < 0)
|
||||||
|
continue;
|
||||||
|
idx2 += 6;
|
||||||
|
int idx3 = line.indexOf('"', idx2);
|
||||||
|
int ilat = (int) ((Double.parseDouble(line.substring(idx2, idx3)) + 90.) * 1000000. + 0.5);
|
||||||
|
track.nodes.add(OsmPathElement.create(ilon, ilat, (short) 0, null, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
br.close();
|
||||||
|
return track;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
246
brouter-core/src/main/java/btools/router/FormatJson.java
Normal file
246
brouter-core/src/main/java/btools/router/FormatJson.java
Normal file
|
@ -0,0 +1,246 @@
|
||||||
|
package btools.router;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import btools.mapaccess.MatchedWaypoint;
|
||||||
|
import btools.util.StringUtils;
|
||||||
|
|
||||||
|
public class FormatJson extends Formatter {
|
||||||
|
|
||||||
|
public FormatJson(RoutingContext rc) {
|
||||||
|
super(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String format(OsmTrack t) {
|
||||||
|
int turnInstructionMode = t.voiceHints != null ? t.voiceHints.turnInstructionMode : 0;
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder(8192);
|
||||||
|
|
||||||
|
sb.append("{\n");
|
||||||
|
sb.append(" \"type\": \"FeatureCollection\",\n");
|
||||||
|
sb.append(" \"features\": [\n");
|
||||||
|
sb.append(" {\n");
|
||||||
|
sb.append(" \"type\": \"Feature\",\n");
|
||||||
|
sb.append(" \"properties\": {\n");
|
||||||
|
sb.append(" \"creator\": \"BRouter-" + t.version + "\",\n");
|
||||||
|
sb.append(" \"name\": \"").append(t.name).append("\",\n");
|
||||||
|
sb.append(" \"track-length\": \"").append(t.distance).append("\",\n");
|
||||||
|
sb.append(" \"filtered ascend\": \"").append(t.ascend).append("\",\n");
|
||||||
|
sb.append(" \"plain-ascend\": \"").append(t.plainAscend).append("\",\n");
|
||||||
|
sb.append(" \"total-time\": \"").append(t.getTotalSeconds()).append("\",\n");
|
||||||
|
sb.append(" \"total-energy\": \"").append(t.energy).append("\",\n");
|
||||||
|
sb.append(" \"cost\": \"").append(t.cost).append("\",\n");
|
||||||
|
if (t.voiceHints != null && !t.voiceHints.list.isEmpty()) {
|
||||||
|
sb.append(" \"voicehints\": [\n");
|
||||||
|
for (VoiceHint hint : t.voiceHints.list) {
|
||||||
|
sb.append(" [");
|
||||||
|
sb.append(hint.indexInTrack);
|
||||||
|
sb.append(',').append(hint.getJsonCommandIndex());
|
||||||
|
sb.append(',').append(hint.getExitNumber());
|
||||||
|
sb.append(',').append(hint.distanceToNext);
|
||||||
|
sb.append(',').append((int) hint.angle);
|
||||||
|
|
||||||
|
// not always include geometry because longer and only needed for comment style
|
||||||
|
if (turnInstructionMode == 4) { // comment style
|
||||||
|
sb.append(",\"").append(hint.formatGeometry()).append("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("],\n");
|
||||||
|
}
|
||||||
|
sb.deleteCharAt(sb.lastIndexOf(","));
|
||||||
|
sb.append(" ],\n");
|
||||||
|
}
|
||||||
|
if (t.showSpeedProfile) { // set in profile
|
||||||
|
List<String> sp = t.aggregateSpeedProfile();
|
||||||
|
if (sp.size() > 0) {
|
||||||
|
sb.append(" \"speedprofile\": [\n");
|
||||||
|
for (int i = sp.size() - 1; i >= 0; i--) {
|
||||||
|
sb.append(" [").append(sp.get(i)).append(i > 0 ? "],\n" : "]\n");
|
||||||
|
}
|
||||||
|
sb.append(" ],\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ... traditional message list
|
||||||
|
{
|
||||||
|
sb.append(" \"messages\": [\n");
|
||||||
|
sb.append(" [\"").append(MESSAGES_HEADER.replaceAll("\t", "\", \"")).append("\"],\n");
|
||||||
|
for (String m : t.aggregateMessages()) {
|
||||||
|
sb.append(" [\"").append(m.replaceAll("\t", "\", \"")).append("\"],\n");
|
||||||
|
}
|
||||||
|
sb.deleteCharAt(sb.lastIndexOf(","));
|
||||||
|
sb.append(" ],\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.getTotalSeconds() > 0) {
|
||||||
|
sb.append(" \"times\": [");
|
||||||
|
DecimalFormat decimalFormat = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
|
||||||
|
decimalFormat.applyPattern("0.###");
|
||||||
|
for (OsmPathElement n : t.nodes) {
|
||||||
|
sb.append(decimalFormat.format(n.getTime())).append(",");
|
||||||
|
}
|
||||||
|
sb.deleteCharAt(sb.lastIndexOf(","));
|
||||||
|
sb.append("]\n");
|
||||||
|
} else {
|
||||||
|
sb.deleteCharAt(sb.lastIndexOf(","));
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(" },\n");
|
||||||
|
|
||||||
|
if (t.iternity != null) {
|
||||||
|
sb.append(" \"iternity\": [\n");
|
||||||
|
for (String s : t.iternity) {
|
||||||
|
sb.append(" \"").append(s).append("\",\n");
|
||||||
|
}
|
||||||
|
sb.deleteCharAt(sb.lastIndexOf(","));
|
||||||
|
sb.append(" ],\n");
|
||||||
|
}
|
||||||
|
sb.append(" \"geometry\": {\n");
|
||||||
|
sb.append(" \"type\": \"LineString\",\n");
|
||||||
|
sb.append(" \"coordinates\": [\n");
|
||||||
|
|
||||||
|
OsmPathElement nn = null;
|
||||||
|
for (OsmPathElement n : t.nodes) {
|
||||||
|
String sele = n.getSElev() == Short.MIN_VALUE ? "" : ", " + n.getElev();
|
||||||
|
if (t.showspeed) { // hack: show speed instead of elevation
|
||||||
|
double speed = 0;
|
||||||
|
if (nn != null) {
|
||||||
|
int dist = n.calcDistance(nn);
|
||||||
|
float dt = n.getTime() - nn.getTime();
|
||||||
|
if (dt != 0.f) {
|
||||||
|
speed = ((3.6f * dist) / dt + 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sele = ", " + (((int) (speed * 10)) / 10.f);
|
||||||
|
}
|
||||||
|
sb.append(" [").append(formatILon(n.getILon())).append(", ").append(formatILat(n.getILat()))
|
||||||
|
.append(sele).append("],\n");
|
||||||
|
nn = n;
|
||||||
|
}
|
||||||
|
sb.deleteCharAt(sb.lastIndexOf(","));
|
||||||
|
|
||||||
|
sb.append(" ]\n");
|
||||||
|
sb.append(" }\n");
|
||||||
|
if (t.exportWaypoints || !t.pois.isEmpty()) {
|
||||||
|
sb.append(" },\n");
|
||||||
|
for (int i = 0; i <= t.pois.size() - 1; i++) {
|
||||||
|
OsmNodeNamed poi = t.pois.get(i);
|
||||||
|
addFeature(sb, "poi", poi.name, poi.ilat, poi.ilon);
|
||||||
|
if (i < t.matchedWaypoints.size() - 1) {
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
sb.append(" \n");
|
||||||
|
}
|
||||||
|
if (t.exportWaypoints) {
|
||||||
|
for (int i = 0; i <= t.matchedWaypoints.size() - 1; i++) {
|
||||||
|
String type;
|
||||||
|
if (i == 0) {
|
||||||
|
type = "from";
|
||||||
|
} else if (i == t.matchedWaypoints.size() - 1) {
|
||||||
|
type = "to";
|
||||||
|
} else {
|
||||||
|
type = "via";
|
||||||
|
}
|
||||||
|
|
||||||
|
MatchedWaypoint wp = t.matchedWaypoints.get(i);
|
||||||
|
addFeature(sb, type, wp.name, wp.waypoint.ilat, wp.waypoint.ilon);
|
||||||
|
if (i < t.matchedWaypoints.size() - 1) {
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
sb.append(" \n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append(" }\n");
|
||||||
|
}
|
||||||
|
sb.append(" ]\n");
|
||||||
|
sb.append("}\n");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFeature(StringBuilder sb, String type, String name, int ilat, int ilon) {
|
||||||
|
sb.append(" {\n");
|
||||||
|
sb.append(" \"type\": \"Feature\",\n");
|
||||||
|
sb.append(" \"properties\": {\n");
|
||||||
|
sb.append(" \"name\": \"" + StringUtils.escapeJson(name) + "\",\n");
|
||||||
|
sb.append(" \"type\": \"" + type + "\"\n");
|
||||||
|
sb.append(" },\n");
|
||||||
|
sb.append(" \"geometry\": {\n");
|
||||||
|
sb.append(" \"type\": \"Point\",\n");
|
||||||
|
sb.append(" \"coordinates\": [\n");
|
||||||
|
sb.append(" " + formatILon(ilon) + ",\n");
|
||||||
|
sb.append(" " + formatILat(ilat) + "\n");
|
||||||
|
sb.append(" ]\n");
|
||||||
|
sb.append(" }\n");
|
||||||
|
sb.append(" }");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String formatAsWaypoint(OsmNodeNamed n) {
|
||||||
|
try {
|
||||||
|
StringWriter sw = new StringWriter(8192);
|
||||||
|
BufferedWriter bw = new BufferedWriter(sw);
|
||||||
|
addJsonHeader(bw);
|
||||||
|
addJsonFeature(bw, "info", "wpinfo", n.ilon, n.ilat, n.getElev(), (n.nodeDescription != null ? rc.expctxWay.getKeyValueDescription(false, n.nodeDescription) : null));
|
||||||
|
addJsonFooter(bw);
|
||||||
|
bw.close();
|
||||||
|
sw.close();
|
||||||
|
return sw.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addJsonFeature(BufferedWriter sb, String type, String name, int ilon, int ilat, double elev, String desc) {
|
||||||
|
try {
|
||||||
|
sb.append(" {\n");
|
||||||
|
sb.append(" \"type\": \"Feature\",\n");
|
||||||
|
sb.append(" \"properties\": {\n");
|
||||||
|
sb.append(" \"creator\": \"BRouter-" + OsmTrack.version + "\",\n");
|
||||||
|
sb.append(" \"name\": \"" + StringUtils.escapeJson(name) + "\",\n");
|
||||||
|
sb.append(" \"type\": \"" + type + "\"");
|
||||||
|
if (desc != null) {
|
||||||
|
sb.append(",\n \"message\": \"" + desc + "\"\n");
|
||||||
|
} else {
|
||||||
|
sb.append("\n");
|
||||||
|
}
|
||||||
|
sb.append(" },\n");
|
||||||
|
sb.append(" \"geometry\": {\n");
|
||||||
|
sb.append(" \"type\": \"Point\",\n");
|
||||||
|
sb.append(" \"coordinates\": [\n");
|
||||||
|
sb.append(" " + formatILon(ilon) + ",\n");
|
||||||
|
sb.append(" " + formatILat(ilat) + ",\n");
|
||||||
|
sb.append(" " + elev + "\n");
|
||||||
|
sb.append(" ]\n");
|
||||||
|
sb.append(" }\n");
|
||||||
|
sb.append(" }\n");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addJsonHeader(BufferedWriter sb) {
|
||||||
|
try {
|
||||||
|
sb.append("{\n");
|
||||||
|
sb.append(" \"type\": \"FeatureCollection\",\n");
|
||||||
|
sb.append(" \"features\": [\n");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addJsonFooter(BufferedWriter sb) {
|
||||||
|
try {
|
||||||
|
sb.append(" ]\n");
|
||||||
|
sb.append("}\n");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
91
brouter-core/src/main/java/btools/router/FormatKml.java
Normal file
91
brouter-core/src/main/java/btools/router/FormatKml.java
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
package btools.router;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import btools.mapaccess.MatchedWaypoint;
|
||||||
|
import btools.util.StringUtils;
|
||||||
|
|
||||||
|
public class FormatKml extends Formatter {
|
||||||
|
public FormatKml(RoutingContext rc) {
|
||||||
|
super(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String format(OsmTrack t) {
|
||||||
|
StringBuilder sb = new StringBuilder(8192);
|
||||||
|
|
||||||
|
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||||
|
|
||||||
|
sb.append("<kml xmlns=\"http://earth.google.com/kml/2.0\">\n");
|
||||||
|
sb.append(" <Document>\n");
|
||||||
|
sb.append(" <name>KML Samples</name>\n");
|
||||||
|
sb.append(" <open>1</open>\n");
|
||||||
|
sb.append(" <distance>3.497064</distance>\n");
|
||||||
|
sb.append(" <traveltime>872</traveltime>\n");
|
||||||
|
sb.append(" <description>To enable simple instructions add: 'instructions=1' as parameter to the URL</description>\n");
|
||||||
|
sb.append(" <Folder>\n");
|
||||||
|
sb.append(" <name>Paths</name>\n");
|
||||||
|
sb.append(" <visibility>0</visibility>\n");
|
||||||
|
sb.append(" <description>Examples of paths.</description>\n");
|
||||||
|
sb.append(" <Placemark>\n");
|
||||||
|
sb.append(" <name>Tessellated</name>\n");
|
||||||
|
sb.append(" <visibility>0</visibility>\n");
|
||||||
|
sb.append(" <description><![CDATA[If the <tessellate> tag has a value of 1, the line will contour to the underlying terrain]]></description>\n");
|
||||||
|
sb.append(" <LineString>\n");
|
||||||
|
sb.append(" <tessellate>1</tessellate>\n");
|
||||||
|
sb.append(" <coordinates>");
|
||||||
|
|
||||||
|
for (OsmPathElement n : t.nodes) {
|
||||||
|
sb.append(formatILon(n.getILon())).append(",").append(formatILat(n.getILat())).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(" </coordinates>\n");
|
||||||
|
sb.append(" </LineString>\n");
|
||||||
|
sb.append(" </Placemark>\n");
|
||||||
|
sb.append(" </Folder>\n");
|
||||||
|
if (t.exportWaypoints || !t.pois.isEmpty()) {
|
||||||
|
if (!t.pois.isEmpty()) {
|
||||||
|
sb.append(" <Folder>\n");
|
||||||
|
sb.append(" <name>poi</name>\n");
|
||||||
|
for (int i = 0; i < t.pois.size(); i++) {
|
||||||
|
OsmNodeNamed poi = t.pois.get(i);
|
||||||
|
createPlaceMark(sb, poi.name, poi.ilat, poi.ilon);
|
||||||
|
}
|
||||||
|
sb.append(" </Folder>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t.exportWaypoints) {
|
||||||
|
int size = t.matchedWaypoints.size();
|
||||||
|
createFolder(sb, "start", t.matchedWaypoints.subList(0, 1));
|
||||||
|
if (t.matchedWaypoints.size() > 2) {
|
||||||
|
createFolder(sb, "via", t.matchedWaypoints.subList(1, size - 1));
|
||||||
|
}
|
||||||
|
createFolder(sb, "end", t.matchedWaypoints.subList(size - 1, size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(" </Document>\n");
|
||||||
|
sb.append("</kml>\n");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createFolder(StringBuilder sb, String type, List<MatchedWaypoint> waypoints) {
|
||||||
|
sb.append(" <Folder>\n");
|
||||||
|
sb.append(" <name>" + type + "</name>\n");
|
||||||
|
for (int i = 0; i < waypoints.size(); i++) {
|
||||||
|
MatchedWaypoint wp = waypoints.get(i);
|
||||||
|
createPlaceMark(sb, wp.name, wp.waypoint.ilat, wp.waypoint.ilon);
|
||||||
|
}
|
||||||
|
sb.append(" </Folder>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createPlaceMark(StringBuilder sb, String name, int ilat, int ilon) {
|
||||||
|
sb.append(" <Placemark>\n");
|
||||||
|
sb.append(" <name>" + StringUtils.escapeXml10(name) + "</name>\n");
|
||||||
|
sb.append(" <Point>\n");
|
||||||
|
sb.append(" <coordinates>" + formatILon(ilon) + "," + formatILat(ilat) + "</coordinates>\n");
|
||||||
|
sb.append(" </Point>\n");
|
||||||
|
sb.append(" </Placemark>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
73
brouter-core/src/main/java/btools/router/Formatter.java
Normal file
73
brouter-core/src/main/java/btools/router/Formatter.java
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package btools.router;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
|
||||||
|
public abstract class Formatter {
|
||||||
|
private static final int OUTPUT_FORMAT_GPX = 0;
|
||||||
|
private static final int OUTPUT_FORMAT_KML = 1;
|
||||||
|
private static final int OUTPUT_FORMAT_JSON = 2;
|
||||||
|
private static final int OUTPUT_FORMAT_CSV = 3;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue