diff --git a/brouter-core/src/main/java/btools/router/FormatGpx.java b/brouter-core/src/main/java/btools/router/FormatGpx.java
index 582cb442..c652a0ac 100644
--- a/brouter-core/src/main/java/btools/router/FormatGpx.java
+++ b/brouter-core/src/main/java/btools/router/FormatGpx.java
@@ -197,10 +197,7 @@ public String formatAsGpx(BufferedWriter sb, OsmTrack t) throws IOException {
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");
+ formatWaypointGpx(sb, poi);
}
if (t.exportWaypoints) {
diff --git a/brouter-core/src/main/java/btools/router/FormatJson.java b/brouter-core/src/main/java/btools/router/FormatJson.java
index 3c52d9a7..53f0b4a4 100644
--- a/brouter-core/src/main/java/btools/router/FormatJson.java
+++ b/brouter-core/src/main/java/btools/router/FormatJson.java
@@ -130,8 +130,8 @@ public String format(OsmTrack t) {
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) {
+ addFeature(sb, "poi", poi.name, poi.ilat, poi.ilon, poi.getSElev());
+ if (i < t.pois.size() - 1) {
sb.append(",");
}
sb.append(" \n");
@@ -148,7 +148,7 @@ public String format(OsmTrack t) {
}
MatchedWaypoint wp = t.matchedWaypoints.get(i);
- addFeature(sb, type, wp.name, wp.waypoint.ilat, wp.waypoint.ilon);
+ addFeature(sb, type, wp.name, wp.waypoint.ilat, wp.waypoint.ilon, wp.waypoint.getSElev());
if (i < t.matchedWaypoints.size() - 1) {
sb.append(",");
}
@@ -164,7 +164,7 @@ public String format(OsmTrack t) {
return sb.toString();
}
- private void addFeature(StringBuilder sb, String type, String name, int ilat, int ilon) {
+ private void addFeature(StringBuilder sb, String type, String name, int ilat, int ilon, short selev) {
sb.append(" {\n");
sb.append(" \"type\": \"Feature\",\n");
sb.append(" \"properties\": {\n");
@@ -175,7 +175,7 @@ private void addFeature(StringBuilder sb, String type, String name, int ilat, in
sb.append(" \"type\": \"Point\",\n");
sb.append(" \"coordinates\": [\n");
sb.append(" " + formatILon(ilon) + ",\n");
- sb.append(" " + formatILat(ilat) + "\n");
+ sb.append(" " + formatILat(ilat) + (selev != Short.MIN_VALUE ? ",\n " + selev / 4. : "") + "\n");
sb.append(" ]\n");
sb.append(" }\n");
sb.append(" }");
diff --git a/brouter-core/src/main/java/btools/router/RoutingContext.java b/brouter-core/src/main/java/btools/router/RoutingContext.java
index 0d6d3b57..2559f3a0 100644
--- a/brouter-core/src/main/java/btools/router/RoutingContext.java
+++ b/brouter-core/src/main/java/btools/router/RoutingContext.java
@@ -172,10 +172,15 @@ public void readGlobalConfig() {
useDynamicDistance = expctxGlobal.getVariableValue("use_dynamic_range", 0f) == 1f;
boolean test = expctxGlobal.getVariableValue("check_start_way", 1f) == 1f;
- if (!test) expctxGlobal.freeNoWays();
+ if (!test) freeNoWays();
}
+ public void freeNoWays() {
+ BExpressionContext expctxGlobal = expctxWay;
+ if (expctxGlobal != null) expctxGlobal.freeNoWays();
+ }
+
public List poipoints;
public List nogopoints = null;
diff --git a/brouter-core/src/main/java/btools/router/RoutingEngine.java b/brouter-core/src/main/java/btools/router/RoutingEngine.java
index 1c9adad9..14fa36f6 100644
--- a/brouter-core/src/main/java/btools/router/RoutingEngine.java
+++ b/brouter-core/src/main/java/btools/router/RoutingEngine.java
@@ -30,6 +30,7 @@ public class RoutingEngine extends Thread {
public final static int BROUTER_ENGINEMODE_ROUTING = 0;
public final static int BROUTER_ENGINEMODE_SEED = 1;
public final static int BROUTER_ENGINEMODE_GETELEV = 2;
+ public final static int BROUTER_ENGINEMODE_GETINFO = 3;
private NodesCache nodesCache;
private SortedHeap openSet = new SortedHeap<>();
@@ -171,10 +172,11 @@ public void doRun(long maxRunningTime) {
case BROUTER_ENGINEMODE_SEED: /* do nothing, handled the old way */
throw new IllegalArgumentException("not a valid engine mode");
case BROUTER_ENGINEMODE_GETELEV:
+ case BROUTER_ENGINEMODE_GETINFO:
if (waypoints.size() < 1) {
throw new IllegalArgumentException("we need one lat/lon point at least!");
}
- doGetElev();
+ doGetInfo();
break;
default:
throw new IllegalArgumentException("not a valid engine mode");
@@ -321,11 +323,12 @@ public void doRouting(long maxRunningTime) {
}
}
- public void doGetElev() {
+ public void doGetInfo() {
try {
startTime = System.currentTimeMillis();
- routingContext.turnInstructionMode = 9;
+ routingContext.freeNoWays();
+
MatchedWaypoint wpt1 = new MatchedWaypoint();
wpt1.waypoint = waypoints.get(0);
wpt1.name = "wpt_info";
@@ -336,44 +339,105 @@ public void doGetElev() {
resetCache(true);
nodesCache.nodesMap.cleanupMode = 0;
- int dist_cn1 = listOne.get(0).crosspoint.calcDistance(listOne.get(0).node1);
- int dist_cn2 = listOne.get(0).crosspoint.calcDistance(listOne.get(0).node2);
+ OsmNode start1 = nodesCache.getGraphNode(listOne.get(0).node1);
+ boolean b = nodesCache.obtainNonHollowNode(start1);
- OsmNode startNode;
- if (dist_cn1 < dist_cn2) {
- startNode = nodesCache.getStartNode(listOne.get(0).node1.getIdFromPos());
- } else {
- startNode = nodesCache.getStartNode(listOne.get(0).node2.getIdFromPos());
- }
+ guideTrack = new OsmTrack();
+ guideTrack.addNode(OsmPathElement.create(wpt1.node2.ilon, wpt1.node2.ilat, (short) 0, null));
+ guideTrack.addNode(OsmPathElement.create(wpt1.node1.ilon, wpt1.node1.ilat, (short) 0, null));
- OsmNodeNamed n = new OsmNodeNamed(listOne.get(0).crosspoint);
- n.selev = startNode != null ? startNode.getSElev() : Short.MIN_VALUE;
-
- 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:
+ matchedWaypoints = new ArrayList<>();
+ MatchedWaypoint wp1 = new MatchedWaypoint();
+ wp1.crosspoint = new OsmNode(wpt1.node1.ilon, wpt1.node1.ilat);
+ wp1.node1 = new OsmNode(wpt1.node1.ilon, wpt1.node1.ilat);
+ wp1.node2 = new OsmNode(wpt1.node2.ilon, wpt1.node2.ilat);
+ matchedWaypoints.add(wp1);
+ MatchedWaypoint wp2 = new MatchedWaypoint();
+ wp2.crosspoint = new OsmNode(wpt1.node2.ilon, wpt1.node2.ilat);
+ wp2.node1 = new OsmNode(wpt1.node1.ilon, wpt1.node1.ilat);
+ wp2.node2 = new OsmNode(wpt1.node2.ilon, wpt1.node2.ilat);
+ matchedWaypoints.add(wp2);
+
+ OsmTrack t = findTrack("getinfo", wp1, wp2, null, null, false);
+ if (t != null) {
+ t.messageList = new ArrayList<>();
+ t.matchedWaypoints = matchedWaypoints;
+ t.name = (outfileBase == null ? "getinfo" : outfileBase);
+
+ // find nearest point
+ int mindist = 99999;
+ int minIdx = -1;
+ for (int i = 0; i < t.nodes.size(); i++) {
+ OsmPathElement ope = t.nodes.get(i);
+ int dist = ope.calcDistance(listOne.get(0).crosspoint);
+ if (mindist > dist) {
+ mindist = dist;
+ minIdx = i;
+ }
+ }
+ int otherIdx = 0;
+ if (minIdx == t.nodes.size()-1) {
+ otherIdx = minIdx-1;
+ } else {
+ otherIdx = minIdx+1;
+ }
+ int otherdist = t.nodes.get(otherIdx).calcDistance(listOne.get(0).crosspoint);
+ int minSElev = t.nodes.get(minIdx).getSElev();
+ int otherSElev = t.nodes.get(otherIdx).getSElev();
+ int diffSElev = 0;
+ diffSElev = otherSElev - minSElev;
+ double diff = (double) mindist/(mindist + otherdist) * diffSElev;
+
+
+ OsmNodeNamed n = new OsmNodeNamed(listOne.get(0).crosspoint);
+ n.name = wpt1.name;
+ n.selev = minIdx != -1 ? (short) (minSElev + (int) diff) : Short.MIN_VALUE;
+ if (engineMode == BROUTER_ENGINEMODE_GETINFO) {
+ n.nodeDescription = (start1 != null && start1.firstlink!=null ? start1.firstlink.descriptionBitmap : null);
+ t.pois.add(n);
+ //t.message = "get_info";
+ //t.messageList.add(t.message);
+ t.matchedWaypoints = listOne;
+ t.exportWaypoints = routingContext.exportWaypoints;
+ }
+
+ switch (routingContext.outputFormat) {
+ case "gpx":
+ if (engineMode == BROUTER_ENGINEMODE_GETELEV) {
+ outputMessage = new FormatGpx(routingContext).formatAsWaypoint(n);
+ } else {
+ outputMessage = new FormatGpx(routingContext).format(t);
+ }
+ break;
+ case "geojson":
+ case "json":
+ if (engineMode == BROUTER_ENGINEMODE_GETELEV) {
+ outputMessage = new FormatJson(routingContext).formatAsWaypoint(n);
+ } else {
+ outputMessage = new FormatJson(routingContext).format(t);
+ }
+ break;
+ case "kml":
+ case "csv":
+ default:
+ outputMessage = null;
+ break;
+ }
+ if (outfileBase != null) {
+ String filename = outfileBase + "." + routingContext.outputFormat;
+ File out = new File(filename);
+ FileWriter fw = new FileWriter(filename);
+ fw.write(outputMessage);
+ fw.close();
outputMessage = null;
- break;
- }
- if (outfileBase != null) {
- 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);
+ } else {
+ if (!quite && outputMessage != null) {
+ System.out.println(outputMessage);
+ }
}
+
+ } else {
+ if (errorMessage == null) errorMessage = "no track found";
}
long endTime = System.currentTimeMillis();
logInfo("execution time = " + (endTime - startTime) / 1000. + " seconds");
@@ -630,7 +694,7 @@ private OsmTrack tryFindTrack(OsmTrack[] refTracks, OsmTrack[] lastTracks) {
}
for (MatchedWaypoint mwp : matchedWaypoints) {
- if (hasInfo()) logInfo("new wp=" + mwp.waypoint + " " + mwp.crosspoint + (mwp.direct ? " direct" : ""));
+ if (hasInfo() && matchedWaypoints.size() != nUnmatched) logInfo("new wp=" + mwp.waypoint + " " + mwp.crosspoint + (mwp.direct ? " direct" : ""));
}
routingContext.checkMatchedWaypointAgainstNogos(matchedWaypoints);
diff --git a/brouter-routing-app/src/main/aidl/btools/routingapp/IBRouterService.aidl b/brouter-routing-app/src/main/aidl/btools/routingapp/IBRouterService.aidl
index b233082d..0e35a792 100644
--- a/brouter-routing-app/src/main/aidl/btools/routingapp/IBRouterService.aidl
+++ b/brouter-routing-app/src/main/aidl/btools/routingapp/IBRouterService.aidl
@@ -35,7 +35,7 @@ interface IBRouterService {
// "timode" = turnInstructionMode [0=none, 1=auto-choose, 2=locus-style, 3=osmand-style, 4=comment-style, 5=gpsies-style, 6=orux-style, 7=locus-old-style] default 0
// "heading" = angle (optional to give a route a start direction)
// "direction" = angle (optional, used like "heading" on a recalculation request by Locus as start direction)
- // "engineMode" = 0 (optional, default 0, 2 = get elevation)
+ // "engineMode" = 0 (optional, default 0, 2 = get elevation, 3 = get segment info)
// return null if all ok and no path given, the track if ok and path given, an error message if it was wrong
// the resultas string when 'pathToFileResult' is null, this should be default when Android Q or later
diff --git a/brouter-server/src/main/java/btools/server/BRouter.java b/brouter-server/src/main/java/btools/server/BRouter.java
index a6dfe103..308dab73 100644
--- a/brouter-server/src/main/java/btools/server/BRouter.java
+++ b/brouter-server/src/main/java/btools/server/BRouter.java
@@ -102,7 +102,8 @@ public static void main(String[] args) throws Exception {
}
try {
RoutingEngine re = null;
- if (engineMode == RoutingEngine.BROUTER_ENGINEMODE_GETELEV) {
+ if (engineMode == RoutingEngine.BROUTER_ENGINEMODE_GETELEV ||
+ engineMode == RoutingEngine.BROUTER_ENGINEMODE_GETINFO) {
re = new RoutingEngine("testinfo", null, new File(args[0]), wplist, rc, engineMode);
} else {
re = new RoutingEngine("testtrack", null, new File(args[0]), wplist, rc, engineMode);
@@ -111,7 +112,7 @@ public static void main(String[] args) throws Exception {
} catch (Exception e) {
System.out.println(e.getMessage());
}
-
+
}
diff --git a/docs/developers/android_service.md b/docs/developers/android_service.md
index 5bbc4753..cd45a5ef 100644
--- a/docs/developers/android_service.md
+++ b/docs/developers/android_service.md
@@ -131,4 +131,8 @@ This suppress the first question after installation for the BRouter path, genera
### get elevation
-"engineMode=2" allows a client to only request an elevation for a point. This can be restricted with "waypointCatchingRange".
+"engineMode=2" allows a client to request only an elevation for a point. This can be restricted with "waypointCatchingRange".
+
+### get info
+
+"engineMode=3" allows a client to request the description tags for a segment. This can be restricted with "waypointCatchingRange".