package btools.routingapp; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.StringTokenizer; import android.os.Bundle; import btools.router.OsmNodeNamed; import btools.router.OsmNogoPolygon; import btools.router.OsmTrack; import btools.router.RoutingContext; import btools.router.RoutingEngine; public class BRouterWorker { private static final int OUTPUT_FORMAT_GPX = 0; private static final int OUTPUT_FORMAT_KML = 1; private static final int OUTPUT_FORMAT_JSON = 2; public String baseDir; public File segmentDir; public String profileName; public String profilePath; public String rawTrackPath; public List waypoints; public List nogoList; public List nogoPolygonsList; public String getTrackFromParams(Bundle params) { String pathToFileResult = params.getString("pathToFileResult"); if (pathToFileResult != null) { File f = new File(pathToFileResult); File dir = f.getParentFile(); if (!dir.exists() || !dir.canWrite()) { return "file folder does not exists or can not be written!"; } } long maxRunningTime = 60000; String sMaxRunningTime = params.getString("maxRunningTime"); if (sMaxRunningTime != null) { maxRunningTime = Integer.parseInt(sMaxRunningTime) * 1000; } RoutingContext rc = new RoutingContext(); rc.rawTrackPath = rawTrackPath; rc.localFunction = profilePath; String tiFormat = params.getString("turnInstructionFormat"); if (tiFormat != null) { if ("osmand".equalsIgnoreCase(tiFormat)) { rc.turnInstructionMode = 3; } else if ("locus".equalsIgnoreCase(tiFormat)) { rc.turnInstructionMode = 2; } } if (params.containsKey("timode")) { rc.turnInstructionMode = params.getInt("timode"); } if ( params.containsKey( "direction" ) ) { rc.startDirection = params.getInt( "direction" ); } if ( params.containsKey( "alternativeidx" ) ) { rc.alternativeIdx = params.getInt( "alternativeidx" ); } readNogos( params ); // add interface provided nogos if ( nogoList != null ) { RoutingContext.prepareNogoPoints(nogoList); if (rc.nogopoints == null) { rc.nogopoints = nogoList; } else { rc.nogopoints.addAll(nogoList); } } if (rc.nogopoints == null) { rc.nogopoints = nogoPolygonsList; } else if ( nogoPolygonsList != null ) { rc.nogopoints.addAll(nogoPolygonsList); } List poisList = readPoisList(params); rc.poipoints = poisList; if (params.containsKey("lats")) { waypoints = readPositions(params); } if (params.containsKey("lonlats")) { waypoints = readLonlats(params); } if (waypoints == null) return "no pts "; if (params.containsKey( "extraParams" )) { // add user params String extraParams = params.getString("extraParams"); if (rc.keyValues == null) rc.keyValues = new HashMap(); StringTokenizer tk = new StringTokenizer( extraParams, "?&" ); while( tk.hasMoreTokens() ) { String t = tk.nextToken(); StringTokenizer tk2 = new StringTokenizer( t, "=" ); if ( tk2.hasMoreTokens() ) { String key = tk2.nextToken(); if ( tk2.hasMoreTokens() ) { String value = tk2.nextToken(); rc.keyValues.put( key, value ); } } } } try { writeTimeoutData( rc ); } catch( Exception e ) {} RoutingEngine cr = new RoutingEngine( null, null, segmentDir, waypoints, rc ); cr.quite = true; cr.doRun( maxRunningTime ); // store new reference track if any // (can exist for timed-out search) if ( cr.getFoundRawTrack() != null ) { try { cr.getFoundRawTrack().writeBinary( rawTrackPath ); } catch( Exception e ) {} } if ( cr.getErrorMessage() != null ) { return cr.getErrorMessage(); } String format = params.getString("trackFormat"); int writeFromat = OUTPUT_FORMAT_GPX; if (format != null) { if ("kml".equals(format)) writeFromat = OUTPUT_FORMAT_KML; if ("json".equals(format)) writeFromat = OUTPUT_FORMAT_JSON; } OsmTrack track = cr.getFoundTrack(); if ( track != null ) { if (params.containsKey("exportWaypoints")) { track.exportWaypoints = (params.getInt("exportWaypoints",0) == 1 ); } if ( pathToFileResult == null ) { switch ( writeFromat ) { case OUTPUT_FORMAT_GPX: return track.formatAsGpx(); case OUTPUT_FORMAT_KML: return track.formatAsKml(); case OUTPUT_FORMAT_JSON: return track.formatAsGeoJson(); default: return track.formatAsGpx(); } } 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; } } return null; } private List readPositions( Bundle params ) { List wplist = new ArrayList(); double[] lats = params.getDoubleArray("lats"); double[] lons = params.getDoubleArray("lons"); if (lats == null || lats.length < 2 || lons == null || lons.length < 2) { throw new IllegalArgumentException( "we need two lat/lon points at least!" ); } for( int i=0; i readLonlats(Bundle params ) { List wplist = new ArrayList(); String lonLats = params.getString( "lonlats" ); if (lonLats == null) throw new IllegalArgumentException( "lonlats parameter not set" ); String[] coords = lonLats.split("\\|"); if (coords.length < 2) throw new IllegalArgumentException( "we need two lat/lon points at least!" ); for (int i = 0; i < coords.length; i++) { String[] lonLat = coords[i].split(","); if (lonLat.length < 2) throw new IllegalArgumentException( "we need two lat/lon points at least!" ); wplist.add( readPosition( lonLat[0], lonLat[1], "via" + i ) ); } wplist.get(0).name = "from"; wplist.get(wplist.size()-1).name = "to"; return wplist; } private static OsmNodeNamed readPosition( String vlon, String vlat, String name ) { if ( vlon == null ) throw new IllegalArgumentException( "lon " + name + " not found in input" ); if ( vlat == null ) throw new IllegalArgumentException( "lat " + name + " not found in input" ); return readPosition(Double.parseDouble( vlon ), Double.parseDouble( vlat ), name); } private static OsmNodeNamed readPosition( double lon, double lat, String name ) { OsmNodeNamed n = new OsmNodeNamed(); n.name = name; n.ilon = (int)( ( lon + 180. ) *1000000. + 0.5); n.ilat = (int)( ( lat + 90. ) *1000000. + 0.5); return n; } private void readNogos( Bundle params ) { if (params.containsKey("nogoLats")) { double[] lats = params.getDoubleArray("nogoLats"); double[] lons = params.getDoubleArray("nogoLons"); double[] radi = params.getDoubleArray("nogoRadi"); if (lats == null || lons == null || radi == null) return; for (int i = 0; i < lats.length && i < lons.length && i < radi.length; i++) { OsmNodeNamed n = new OsmNodeNamed(); n.name = "nogo" + (int) radi[i]; n.ilon = (int) ((lons[i] + 180.) * 1000000. + 0.5); n.ilat = (int) ((lats[i] + 90.) * 1000000. + 0.5); n.isNogo = true; n.nogoWeight = Double.NaN; AppLogger.log("added interface provided nogo: " + n); nogoList.add(n); } } if (params.containsKey("nogos")) { nogoList = readNogoList(params); } if (params.containsKey("polylines") || params.containsKey("polygons")) { nogoPolygonsList = readNogoPolygons(params); } } private List readNogoList(Bundle params) { // lon,lat,radius|... String nogos = params.getString( "nogos" ); if ( nogos == null ) return null; String[] lonLatRadList = nogos.split("\\|"); List nogoList = new ArrayList(); for (int i = 0; i < lonLatRadList.length; i++) { String[] lonLatRad = lonLatRadList[i].split(","); String nogoWeight = "NaN"; if (lonLatRad.length > 3) { nogoWeight = lonLatRad[3]; } nogoList.add(readNogo(lonLatRad[0], lonLatRad[1], lonLatRad[2], nogoWeight)); } return nogoList; } private static OsmNodeNamed readNogo( String lon, String lat, String radius, String nogoWeight ) { double weight = "undefined".equals( nogoWeight ) ? Double.NaN : Double.parseDouble( nogoWeight ); return readNogo(Double.parseDouble( lon ), Double.parseDouble( lat ), Integer.parseInt( radius ), weight ); } private static OsmNodeNamed readNogo( double lon, double lat, int radius, double nogoWeight ) { OsmNodeNamed n = new OsmNodeNamed(); n.name = "nogo" + radius; n.ilon = (int)( ( lon + 180. ) *1000000. + 0.5); n.ilat = (int)( ( lat + 90. ) *1000000. + 0.5); n.isNogo = true; n.nogoWeight = nogoWeight; return n; } private List readNogoPolygons(Bundle params) { List result = new ArrayList(); parseNogoPolygons( params.getString("polylines"), result, false ); parseNogoPolygons( params.getString("polygons"), result, true ); return result.size() > 0 ? result : null; } private static void parseNogoPolygons(String polygons, List result, boolean closed ) { if ( polygons != null ) { OsmNogoPolygon polygon = new OsmNogoPolygon(closed); polygon.name = "nogopoly" ; String nogoWeight = "NaN"; String[] polygonList = polygons.split("\\|"); for (int i = 0; i < polygonList.length; i++) { String[] lonLatList = polygonList[i].split(","); if ( lonLatList.length > 1 ) { int j; for (j = 0; j < 2 * (lonLatList.length / 2) - 1;) { String slon = lonLatList[j++]; String slat = lonLatList[j++]; int lon = (int)( ( Double.parseDouble(slon) + 180. ) *1000000. + 0.5); int lat = (int)( ( Double.parseDouble(slat) + 90. ) *1000000. + 0.5); polygon.addVertex(lon, lat); } if (j < lonLatList.length) { nogoWeight = lonLatList[j]; } } } polygon.nogoWeight = Double.parseDouble( nogoWeight ); if ( polygon.points.size() > 0 ) { polygon.calcBoundingCircle(); result.add(polygon); } } } private static void parseNogoPolygons_alt(String polygons, List result, boolean closed ) { if ( polygons != null ) { String[] polygonList = polygons.split("\\|"); for (int i = 0; i < polygonList.length; i++) { String[] lonLatList = polygonList[i].split(","); if ( lonLatList.length > 1 ) { OsmNogoPolygon polygon = new OsmNogoPolygon(closed); polygon.name = "nogo" + i; int j; for (j = 0; j < 2 * (lonLatList.length / 2) - 1;) { String slon = lonLatList[j++]; String slat = lonLatList[j++]; int lon = (int)( ( Double.parseDouble(slon) + 180. ) *1000000. + 0.5); int lat = (int)( ( Double.parseDouble(slat) + 90. ) *1000000. + 0.5); polygon.addVertex(lon, lat); } String nogoWeight = "NaN"; if (j < lonLatList.length) { nogoWeight = lonLatList[j]; } polygon.nogoWeight = Double.parseDouble( nogoWeight ); if ( polygon.points.size() > 0 ) { polygon.calcBoundingCircle(); result.add(polygon); } } } } } private List readPoisList(Bundle params ) { // lon,lat,name|... String pois = params.getString( "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 void writeTimeoutData( RoutingContext rc ) throws Exception { String timeoutFile = baseDir + "/brouter/modes/timeoutdata.txt"; BufferedWriter bw = new BufferedWriter( new FileWriter( timeoutFile ) ); bw.write( profileName ); bw.write( "\n" ); bw.write( rc.rawTrackPath ); bw.write( "\n" ); writeWPList( bw, waypoints ); writeWPList( bw, nogoList ); bw.close(); } private void writeWPList( BufferedWriter bw, List wps ) throws Exception { bw.write( wps.size() + "\n" ); for( OsmNodeNamed wp : wps ) { bw.write( wp.toString() ); bw.write( "\n" ); } } }