diff --git a/brouter-core/pom.xml b/brouter-core/pom.xml index 43b909f..eb6ffcb 100644 --- a/brouter-core/pom.xml +++ b/brouter-core/pom.xml @@ -37,5 +37,10 @@ junit test + + org.apache.commons + commons-text + 1.8 + diff --git a/brouter-core/src/main/java/btools/router/OsmTrack.java b/brouter-core/src/main/java/btools/router/OsmTrack.java index 9a2c7ed..9d8a2e1 100644 --- a/brouter-core/src/main/java/btools/router/OsmTrack.java +++ b/brouter-core/src/main/java/btools/router/OsmTrack.java @@ -26,6 +26,7 @@ import btools.mapaccess.MatchedWaypoint; import btools.mapaccess.OsmPos; import btools.util.CompactLongMap; import btools.util.FrozenLongMap; +import org.apache.commons.text.StringEscapeUtils; public final class OsmTrack { @@ -39,6 +40,8 @@ public final class OsmTrack public boolean showspeed; + public List pois = new ArrayList(); + private static class OsmPathElementHolder { public OsmPathElement node; @@ -534,13 +537,23 @@ public final class OsmTrack } } + for( int i=0; i<=pois.size() - 1; i++ ) + { + OsmNodeNamed poi = pois.get(i); + sb.append( " \n" ) + .append( " " ).append( StringEscapeUtils.escapeXml10(poi.name) ).append( "\n" ) + .append( " \n" ); + } + if ( exportWaypoints ) { for( int i=0; i<=matchedWaypoints.size() - 1; i++ ) { - sb.append( " \n" ) - .append( " " ).append( matchedWaypoints.get(i).name ).append( "\n" ); + MatchedWaypoint wt = matchedWaypoints.get(i); + sb.append( " \n" ) + .append( " " ).append( StringEscapeUtils.escapeXml10(wt.name) ).append( "\n" ); if(i == 0) { sb.append( " from\n" ); @@ -637,40 +650,27 @@ public final class OsmTrack sb.append( " \n" ); sb.append( " \n" ); sb.append( " \n" ); - if ( exportWaypoints ) + if ( exportWaypoints || !pois.isEmpty() ) { + if (!pois.isEmpty()) { sb.append( " \n" ); - sb.append( " start\n" ); - sb.append( " \n" ); - sb.append( " " + matchedWaypoints.get(0).name + "\n" ); - sb.append( " \n" ); - sb.append( " " + formatILon(matchedWaypoints.get(0).waypoint.ilon) + "," + formatILat(matchedWaypoints.get(0).waypoint.ilat) + "\n" ); - sb.append( " \n" ); - sb.append( " \n" ); - sb.append( " \n" ); - if (matchedWaypoints.size() > 2) { - sb.append( " \n" ); - sb.append( " via\n" ); - for( int i=1; i<=matchedWaypoints.size() - 2; i++ ) - { - sb.append( " \n" ); - sb.append( " " + matchedWaypoints.get(i).name + "\n" ); - sb.append( " \n" ); - sb.append( " " + formatILon(matchedWaypoints.get(i).waypoint.ilon) + "," + formatILat(matchedWaypoints.get(i).waypoint.ilat) + "\n" ); - sb.append( " \n" ); - sb.append( " \n" ); - } - 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" ); - sb.append( " end\n" ); - sb.append( " \n" ); - sb.append( " " + matchedWaypoints.get(matchedWaypoints.size() - 1).name + "\n" ); - sb.append( " \n" ); - sb.append( " " + formatILon(matchedWaypoints.get(matchedWaypoints.size() - 1).waypoint.ilon) + "," + formatILat(matchedWaypoints.get(matchedWaypoints.size() - 1).waypoint.ilat) + "\n" ); - sb.append( " \n" ); - sb.append( " \n" ); - sb.append( " \n" ); + 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" ); @@ -678,6 +678,25 @@ public final class OsmTrack 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(" " + StringEscapeUtils.escapeXml10(name) + "\n"); + sb.append(" \n"); + sb.append(" " + formatILon(ilon) + "," + formatILat(ilat) + "\n"); + sb.append(" \n"); + sb.append(" \n"); + } + public List iternity; public String formatAsGeoJson() @@ -773,45 +792,40 @@ public final class OsmTrack sb.append( " ]\n" ); sb.append( " }\n" ); - if ( exportWaypoints ) + if ( exportWaypoints || !pois.isEmpty()) { - sb.append( " },\n" ); - for( int i=0; i<=matchedWaypoints.size() - 1; i++ ) - { - sb.append( " {\n" ); - sb.append( " \"type\": \"Feature\",\n" ); - sb.append( " \"properties\": {\n" ); - sb.append( " \"name\": \"" + matchedWaypoints.get(i).name + "\",\n" ); - if(i == 0) - { - sb.append( " \"type\": \"from\"\n" ); - } - else if (i == matchedWaypoints.size() - 1) - { - sb.append( " \"type\": \"to\"\n" ); - } - else - sb.append( " \"type\": \"via\"\n" ); - { - } - sb.append( " },\n" ); - sb.append( " \"geometry\": {\n" ); - sb.append( " \"type\": \"Point\",\n" ); - sb.append( " \"coordinates\": [\n" ); - sb.append( " " + formatILon(matchedWaypoints.get(i).waypoint.ilon) + ",\n" ); - sb.append( " " + formatILat(matchedWaypoints.get(i).waypoint.ilat) + "\n" ); - sb.append( " ]\n" ); - sb.append( " }\n" ); - if (i < matchedWaypoints.size() - 1) { - sb.append( " },\n" ); - } - else { - sb.append( " }\n" ); - } + 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" ); sb.append( "}\n" ); @@ -819,6 +833,23 @@ public final class OsmTrack 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\": \"" + StringEscapeUtils.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 int getVNode( int i ) { MessageData m1 = i+1 < nodes.size() ? nodes.get(i+1).message : null; @@ -841,18 +872,18 @@ public final class OsmTrack 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; + 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; } public String getFormattedEnergy() diff --git a/brouter-core/src/main/java/btools/router/RoutingContext.java b/brouter-core/src/main/java/btools/router/RoutingContext.java index be0fe55..78dccd3 100644 --- a/brouter-core/src/main/java/btools/router/RoutingContext.java +++ b/brouter-core/src/main/java/btools/router/RoutingContext.java @@ -21,7 +21,7 @@ import btools.util.CheapRuler; public final class RoutingContext { - public void setAlternativeIdx( int idx ) + public void setAlternativeIdx(int idx ) { alternativeIdx = idx; } @@ -188,6 +188,8 @@ public final class RoutingContext bikerPower = expctxGlobal.getVariableValue( "bikerPower", 100.f ); } + public List poipoints; + public List nogopoints = null; private List keepnogopoints = null; diff --git a/brouter-core/src/main/java/btools/router/RoutingEngine.java b/brouter-core/src/main/java/btools/router/RoutingEngine.java index 4be519b..4dcc23a 100644 --- a/brouter-core/src/main/java/btools/router/RoutingEngine.java +++ b/brouter-core/src/main/java/btools/router/RoutingEngine.java @@ -446,6 +446,7 @@ public class RoutingEngine extends Thread totaltrack.appendTrack( seg ); lastTracks[i] = seg; } + if (routingContext.poipoints != null) totaltrack.pois = routingContext.poipoints; totaltrack.matchedWaypoints = matchedWaypoints; return totaltrack; } 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 62a2bce..023ee50 100644 --- a/brouter-server/src/main/java/btools/server/request/ServerHandler.java +++ b/brouter-server/src/main/java/btools/server/request/ServerHandler.java @@ -1,5 +1,6 @@ package btools.server.request; +import btools.mapaccess.OsmNode; import btools.router.OsmNodeNamed; import btools.router.OsmNogoPolygon; import btools.router.OsmTrack; @@ -25,10 +26,11 @@ import java.util.List; * format = [kml|gpx|geojson] (optional, default gpx) * trackname = name used for filename and format specific trackname (optional, default brouter) * exportWaypoints = 1 to export them (optional, default is no export) + * pois = lon,lat,name|... (optional) * * Example URLs: * {@code http://localhost:17777/brouter?lonlats=8.799297,49.565883|8.811764,49.563606&nogos=&profile=trekking&alternativeidx=0&format=gpx} - * {@code http://localhost:17777/brouter?lonlats=1.1,1.2|2.1,2.2|3.1,3.2|4.1,4.2&nogos=-1.1,-1.2,1|-2.1,-2.2,2&profile=shortest&alternativeidx=1&format=kml&trackname=Ride} + * {@code http://localhost:17777/brouter?lonlats=1.1,1.2|2.1,2.2|3.1,3.2|4.1,4.2&nogos=-1.1,-1.2,1|-2.1,-2.2,2&profile=shortest&alternativeidx=1&format=kml&trackname=Ride&pois=1.1,2.1,Barner Bar} * */ public class ServerHandler extends RequestHandler { @@ -62,6 +64,9 @@ public class ServerHandler extends RequestHandler { rc.setAlternativeIdx(Integer.parseInt(params.get( "alternativeidx" ))); + List poisList = readPoisList(); + rc.poipoints = poisList; + List nogoList = readNogoList(); List nogoPolygonsList = readNogoPolygons(); @@ -226,6 +231,29 @@ public class ServerHandler extends RequestHandler { return n; } + private List readPoisList() + { + // lon,lat,name|... + String pois = params.get( "pois" ); + if ( pois == null ) return null; + + String[] lonLatNameList = pois.split("\\|"); + + List poisList = new ArrayList(); + for (int i = 0; i < lonLatNameList.length; i++) + { + String[] lonLatName = lonLatNameList[i].split(","); + + OsmNodeNamed n = new OsmNodeNamed(); + n.ilon = (int)( ( Double.parseDouble(lonLatName[0]) + 180. ) *1000000. + 0.5); + n.ilat = (int)( ( Double.parseDouble(lonLatName[1]) + 90. ) *1000000. + 0.5); + n.name = lonLatName[2]; + poisList.add(n); + } + + return poisList; + } + private List readNogoList() { // lon,lat,radius|...