package net.osmand.plus.routing;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.LatLon;
import net.osmand.data.LocationPoint;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.Route;
import net.osmand.plus.GPXUtilities.Track;
import net.osmand.plus.GPXUtilities.TrkSegment;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.OsmandSettings.CommonPreference;
import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.TargetPointsHelper.TargetPoint;
import net.osmand.plus.Version;
import net.osmand.plus.activities.SettingsNavigationActivity;
import net.osmand.plus.render.NativeOsmandLibrary;
import net.osmand.router.GeneralRouter;
import net.osmand.router.GeneralRouter.GeneralRouterProfile;
import net.osmand.router.GeneralRouter.RoutingParameter;
import net.osmand.router.GeneralRouter.RoutingParameterType;
import net.osmand.router.PrecalculatedRouteDirection;
import net.osmand.router.RoutePlannerFrontEnd;
import net.osmand.router.RoutePlannerFrontEnd.RouteCalculationMode;
import net.osmand.router.RouteSegmentResult;
import net.osmand.router.RoutingConfiguration;
import net.osmand.router.RoutingConfiguration.Builder;
import net.osmand.router.RoutingContext;
import net.osmand.router.TurnType;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import net.osmand.util.GeoPolylineParserUtil;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import btools.routingapp.IBRouterService;
public class RouteProvider {
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RouteProvider.class);
private static final String OSMAND_ROUTER = "OsmAndRouter";
public enum RouteService {
OSMAND("OsmAnd (offline)"), YOURS("YOURS"),
// ORS("OpenRouteService"), // disable ors due to no public rest service (testing2015 doesn't seem stable)
OSRM("OSRM (only car)"),
BROUTER("BRouter (offline)"), STRAIGHT("Straight line");
private final String name;
private RouteService(String name) {
this.name = name;
}
public String getName() {
return name;
}
public boolean isOnline() {
return this != OSMAND && this != BROUTER;
}
boolean isAvailable(OsmandApplication ctx) {
if (this == BROUTER) {
return ctx.getBRouterService() != null;
}
return true;
}
public static RouteService[] getAvailableRouters(OsmandApplication ctx) {
List<RouteService> list = new ArrayList<RouteProvider.RouteService>();
for(RouteService r : values()) {
if (r.isAvailable(ctx)) {
list.add(r);
}
}
return list.toArray(new RouteService[list.size()]);
}
}
public RouteProvider() {
}
public static class GPXRouteParamsBuilder {
boolean calculateOsmAndRoute = false;
// parameters
private final GPXFile file;
private boolean reverse;
private boolean leftSide;
private boolean passWholeRoute;
private boolean calculateOsmAndRouteParts;
private boolean useIntermediatePointsRTE;
public GPXRouteParamsBuilder(GPXFile file, OsmandSettings settings) {
leftSide = settings.DRIVING_REGION.get().leftHandDriving;
this.file = file;
}
public boolean isReverse() {
return reverse;
}
public boolean isCalculateOsmAndRouteParts() {
return calculateOsmAndRouteParts;
}
public void setCalculateOsmAndRouteParts(boolean calculateOsmAndRouteParts) {
this.calculateOsmAndRouteParts = calculateOsmAndRouteParts;
}
public void setUseIntermediatePointsRTE(boolean useIntermediatePointsRTE) {
this.useIntermediatePointsRTE = useIntermediatePointsRTE;
}
public boolean isUseIntermediatePointsRTE() {
return useIntermediatePointsRTE;
}
public boolean isCalculateOsmAndRoute() {
return calculateOsmAndRoute;
}
public void setCalculateOsmAndRoute(boolean calculateOsmAndRoute) {
this.calculateOsmAndRoute = calculateOsmAndRoute;
}
public void setPassWholeRoute(boolean passWholeRoute) {
this.passWholeRoute = passWholeRoute;
}
public boolean isPassWholeRoute() {
return passWholeRoute;
}
public GPXRouteParams build(Location start, OsmandSettings settings) {
GPXRouteParams res = new GPXRouteParams();
res.prepareGPXFile(this);
// if (passWholeRoute && start != null) {
// res.points.add(0, start);
// }
return res;
}
public void setReverse(boolean reverse) {
this.reverse = reverse;
}
public GPXFile getFile() {
return file;
}
public List<Location> getPoints() {
GPXRouteParams copy = new GPXRouteParams();
copy.prepareGPXFile(this);
return copy.getPoints();
}
}
public static class GPXRouteParams {
List<Location> points = new ArrayList<Location>();
List<RouteDirectionInfo> directions;
boolean calculateOsmAndRoute;
boolean passWholeRoute;
boolean calculateOsmAndRouteParts;
boolean useIntermediatePointsRTE;
private List<LocationPoint> wpt;
boolean addMissingTurns = true;
public List<Location> getPoints() {
return points;
}
public Location getStartPointForRoute(){
if(!points.isEmpty()){
return points.get(0);
}
return null;
}
public Location getEndPointForRoute(){
if(!points.isEmpty()){
return points.get(points.size());
}
return null;
}
public LatLon getLastPoint() {
if(!points.isEmpty()){
Location l = points.get(points.size() - 1);
LatLon point = new LatLon(l.getLatitude(), l.getLongitude());
return point;
}
return null;
}
public GPXRouteParams prepareGPXFile(GPXRouteParamsBuilder builder) {
GPXFile file = builder.file;
boolean reverse = builder.reverse;
passWholeRoute = builder.passWholeRoute;
calculateOsmAndRouteParts = builder.calculateOsmAndRouteParts;
useIntermediatePointsRTE = builder.useIntermediatePointsRTE;
builder.calculateOsmAndRoute = false; // Disabled temporary builder.calculateOsmAndRoute;
if (!file.points.isEmpty()) {
wpt = new ArrayList<LocationPoint>(file.points);
}
if (file.isCloudmadeRouteFile() || OSMAND_ROUTER.equals(file.author)) {
directions = parseOsmAndGPXRoute(points, file, OSMAND_ROUTER.equals(file.author), builder.leftSide, 10);
if (OSMAND_ROUTER.equals(file.author)) {
// For files generated by OSMAND_ROUTER use directions contained unaltered
addMissingTurns = false;
}
if (reverse) {
// clear directions all turns should be recalculated
directions = null;
Collections.reverse(points);
addMissingTurns = true;
}
} else {
// first of all check tracks
if (!useIntermediatePointsRTE) {
for (Track tr : file.tracks) {
for (TrkSegment tkSeg : tr.segments) {
for (WptPt pt : tkSeg.points) {
points.add(createLocation(pt));
}
}
}
}
if (points.isEmpty()) {
for (Route rte : file.routes) {
for (WptPt pt : rte.points) {
points.add(createLocation(pt));
}
}
}
if (reverse) {
Collections.reverse(points);
}
}
return this;
}
}
private static Location createLocation(WptPt pt){
Location loc = new Location("OsmandRouteProvider");
loc.setLatitude(pt.lat);
loc.setLongitude(pt.lon);
loc.setSpeed((float) pt.speed);
if(!Double.isNaN(pt.ele)) {
loc.setAltitude(pt.ele);
}
loc.setTime(pt.time);
if(!Double.isNaN(pt.hdop)) {
loc.setAccuracy((float) pt.hdop);
}
return loc;
}
public RouteCalculationResult calculateRouteImpl(RouteCalculationParams params){
long time = System.currentTimeMillis();
if (params.start != null && params.end != null) {
if(log.isInfoEnabled()){
log.info("Start finding route from " + params.start + " to " + params.end +" using " +
params.type.getName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
try {
RouteCalculationResult res;
boolean calcGPXRoute = params.gpxRoute != null && !params.gpxRoute.points.isEmpty();
if(calcGPXRoute && !params.gpxRoute.calculateOsmAndRoute){
res = calculateGpxRoute(params);
} else if (params.type == RouteService.OSMAND) {
res = findVectorMapsRoute(params, calcGPXRoute);
} else if (params.type == RouteService.BROUTER) {
res = findBROUTERRoute(params);
} else if (params.type == RouteService.YOURS) {
res = findYOURSRoute(params);
// } else if (params.type == RouteService.ORS) {
// res = findORSRoute(params);
} else if (params.type == RouteService.OSRM) {
res = findOSRMRoute(params);
} else if (params.type == RouteService.STRAIGHT){
res = findStraightRoute(params);
}
else {
res = new RouteCalculationResult("Selected route service is not available");
}
if(log.isInfoEnabled() ){
log.info("Finding route contained " + res.getImmutableAllLocations().size() + " points for " + (System.currentTimeMillis() - time) + " ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return res;
} catch (IOException e) {
log.error("Failed to find route ", e); //$NON-NLS-1$
} catch (ParserConfigurationException e) {
log.error("Failed to find route ", e); //$NON-NLS-1$
} catch (SAXException e) {
log.error("Failed to find route ", e); //$NON-NLS-1$
} catch (JSONException e) {
log.error("Failed to find route ", e); //$NON-NLS-1$
}
}
return new RouteCalculationResult(null);
}
public RouteCalculationResult recalculatePartOfflineRoute(RouteCalculationResult res, RouteCalculationParams params) {
RouteCalculationResult rcr = params.previousToRecalculate;
List<Location> locs = new ArrayList<Location>(rcr.getRouteLocations());
try {
int[] startI = new int[]{0};
int[] endI = new int[]{locs.size()};
locs = findStartAndEndLocationsFromRoute(locs, params.start, params.end, startI, endI);
List<RouteDirectionInfo> directions = calcDirections(startI, endI, rcr.getRouteDirections());
insertInitialSegment(params, locs, directions, true);
res = new RouteCalculationResult(locs, directions, params, null, true);
} catch (RuntimeException e) {
e.printStackTrace();
}
return res;
}
private RouteCalculationResult calculateGpxRoute(RouteCalculationParams routeParams) throws IOException {
// get the closest point to start and to end
GPXRouteParams gpxParams = routeParams.gpxRoute;
if(routeParams.gpxRoute.useIntermediatePointsRTE){
return calculateOsmAndRouteWithIntermediatePoints(routeParams, gpxParams.points);
}
List<Location> gpxRoute ;
int[] startI = new int[]{0};
int[] endI = new int[]{gpxParams.points.size()};
if(routeParams.gpxRoute.passWholeRoute) {
gpxRoute = gpxParams.points;
} else {
gpxRoute = findStartAndEndLocationsFromRoute(gpxParams.points,
routeParams.start, routeParams.end, startI, endI);
}
final List<RouteDirectionInfo> inputDirections = gpxParams.directions;
List<RouteDirectionInfo> gpxDirections = calcDirections(startI, endI, inputDirections);
boolean calculateOsmAndRouteParts = gpxParams.calculateOsmAndRouteParts;
insertInitialSegment(routeParams, gpxRoute, gpxDirections, calculateOsmAndRouteParts);
insertFinalSegment(routeParams, gpxRoute, gpxDirections, calculateOsmAndRouteParts);
for (RouteDirectionInfo info : gpxDirections) {
// recalculate
info.distance = 0;
info.afterLeftTime = 0;
}
RouteCalculationResult res = new RouteCalculationResult(gpxRoute, gpxDirections, routeParams,
gpxParams == null? null: gpxParams.wpt, routeParams.gpxRoute.addMissingTurns);
return res;
}
private RouteCalculationResult calculateOsmAndRouteWithIntermediatePoints(RouteCalculationParams routeParams,
final List<Location> intermediates) throws IOException {
RouteCalculationParams rp = new RouteCalculationParams();
rp.calculationProgress = routeParams.calculationProgress;
rp.ctx = routeParams.ctx;
rp.mode = routeParams.mode;
rp.start = routeParams.start;
rp.end = routeParams.end;
rp.leftSide = routeParams.leftSide;
rp.type = routeParams.type;
rp.fast = routeParams.fast;
rp.onlyStartPointChanged = routeParams.onlyStartPointChanged;
rp.previousToRecalculate = routeParams.previousToRecalculate;
rp.intermediates = new ArrayList<LatLon>();
int closest = 0;
double maxDist = Double.POSITIVE_INFINITY;
for (int i = 0; i < intermediates.size(); i++) {
Location loc = intermediates.get(i);
double dist = MapUtils.getDistance(loc.getLatitude(), loc.getLongitude(), rp.start.getLatitude(),
rp.start.getLongitude());
if (dist <= maxDist) {
closest = i;
maxDist = dist;
}
}
for(int i = closest; i< intermediates.size() ; i++ ){
Location w = intermediates.get(i);
rp.intermediates.add(new LatLon(w.getLatitude(), w.getLongitude()));
}
return findVectorMapsRoute(rp, false);
}
private List<RouteDirectionInfo> calcDirections(int[] startI, int[] endI,
final List<RouteDirectionInfo> inputDirections) {
List<RouteDirectionInfo> directions = new ArrayList<RouteDirectionInfo>();
if (inputDirections != null) {
for (RouteDirectionInfo info : inputDirections) {
if (info.routePointOffset >= startI[0] && info.routePointOffset < endI[0]) {
RouteDirectionInfo ch = new RouteDirectionInfo(info.getAverageSpeed(), info.getTurnType());
ch.routePointOffset = info.routePointOffset - startI[0];
if(info.routeEndPointOffset != 0) {
ch.routeEndPointOffset = info.routeEndPointOffset - startI[0];
}
ch.setDescriptionRoute(info.getDescriptionRoutePart());
// Issue #2894
if (info.getRef() != null && !"null".equals(info.getRef())) {
ch.setRef(info.getRef());
}
if (info.getStreetName() != null && !"null".equals(info.getStreetName())) {
ch.setStreetName(info.getStreetName());
}
if (info.getDestinationName() != null && !"null".equals(info.getDestinationName())) {
ch.setDestinationName(info.getDestinationName());
}
directions.add(ch);
}
}
}
return directions;
}
private void insertFinalSegment(RouteCalculationParams routeParams, List<Location> points,
List<RouteDirectionInfo> directions, boolean calculateOsmAndRouteParts) {
if(points.size() > 0) {
Location routeEnd = points.get(points.size() - 1);
LatLon e = routeEnd == null ? null : new LatLon(routeEnd.getLatitude(), routeEnd.getLongitude());
LatLon finalEnd = routeParams.end;
if (finalEnd != null && MapUtils.getDistance(finalEnd, e) > 60) {
RouteCalculationResult newRes = null;
if (calculateOsmAndRouteParts) {
newRes = findOfflineRouteSegment(routeParams, routeEnd, finalEnd);
}
List<Location> loct;
List<RouteDirectionInfo> dt;
if (newRes != null && newRes.isCalculated()) {
loct = newRes.getImmutableAllLocations();
dt = newRes.getImmutableAllDirections();
} else {
loct = new ArrayList<Location>();
Location l = new Location("");
l.setLatitude(finalEnd.getLatitude());
l.setLongitude(finalEnd.getLongitude());
loct.add(l);
dt = new ArrayList<RouteDirectionInfo>();
}
for (RouteDirectionInfo i : dt) {
i.routePointOffset += points.size();
}
points.addAll(loct);
directions.addAll(dt);
}
}
}
public void insertInitialSegment(RouteCalculationParams routeParams, List<Location> points,
List<RouteDirectionInfo> directions, boolean calculateOsmAndRouteParts) {
Location realStart = routeParams.start;
if (realStart != null && points.size() > 0 && realStart.distanceTo(points.get(0)) > 60) {
Location trackStart = points.get(0);
RouteCalculationResult newRes = null;
if (calculateOsmAndRouteParts) {
LatLon end = new LatLon(trackStart.getLatitude(), trackStart.getLongitude());
newRes = findOfflineRouteSegment(routeParams, realStart, end);
}
List<Location> loct;
List<RouteDirectionInfo> dt;
if (newRes != null && newRes.isCalculated()) {
loct = newRes.getImmutableAllLocations();
dt = newRes.getImmutableAllDirections();
} else {
loct = new ArrayList<Location>();
loct.add(realStart);
dt = new ArrayList<RouteDirectionInfo>();
}
points.addAll(0, loct);
directions.addAll(0, dt);
for (int i = dt.size(); i < directions.size(); i++) {
directions.get(i).routePointOffset += loct.size();
}
}
}
private RouteCalculationResult findOfflineRouteSegment(RouteCalculationParams rParams, Location start,
LatLon end) {
RouteCalculationParams newParams = new RouteCalculationParams();
newParams.start = start;
newParams.end = end;
newParams.ctx = rParams.ctx;
newParams.calculationProgress = rParams.calculationProgress;
newParams.mode = rParams.mode;
newParams.type = RouteService.OSMAND;
newParams.leftSide = rParams.leftSide;
RouteCalculationResult newRes = null;
try {
newRes = findVectorMapsRoute(newParams, false);
} catch (IOException e) {
}
return newRes;
}
private ArrayList<Location> findStartAndEndLocationsFromRoute(List<Location> route, Location startLoc, LatLon endLoc, int[] startI, int[] endI) {
float minDist = Integer.MAX_VALUE;
int start = 0;
int end = route.size();
if (startLoc != null) {
for (int i = 0; i < route.size(); i++) {
float d = route.get(i).distanceTo(startLoc);
if (d < minDist) {
start = i;
minDist = d;
}
}
} else {
startLoc = route.get(0);
}
Location l = new Location("temp"); //$NON-NLS-1$
l.setLatitude(endLoc.getLatitude());
l.setLongitude(endLoc.getLongitude());
minDist = Integer.MAX_VALUE;
// get in reverse order taking into account ways with cycle
for (int i = route.size() - 1; i >= start; i--) {
float d = route.get(i).distanceTo(l);
if (d < minDist) {
end = i + 1;
// slightly modify to allow last point to be added
minDist = d - 40;
}
}
ArrayList<Location> sublist = new ArrayList<Location>(route.subList(start, end));
if(startI != null) {
startI[0] = start;
}
if(endI != null) {
endI[0] = end;
}
return sublist;
}
protected String getString(Context ctx, int resId){
if(ctx == null){
return ""; //$NON-NLS-1$
}
return ctx.getString(resId);
}
protected RouteCalculationResult findYOURSRoute(RouteCalculationParams params) throws MalformedURLException, IOException,
ParserConfigurationException, FactoryConfigurationError, SAXException {
List<Location> res = new ArrayList<Location>();
StringBuilder uri = new StringBuilder();
uri.append("http://www.yournavigation.org/api/1.0/gosmore.php?format=kml"); //$NON-NLS-1$
uri.append("&flat=").append(params.start.getLatitude()); //$NON-NLS-1$
uri.append("&flon=").append(params.start.getLongitude()); //$NON-NLS-1$
uri.append("&tlat=").append(params.end.getLatitude()); //$NON-NLS-1$
uri.append("&tlon=").append(params.end.getLongitude()); //$NON-NLS-1$
if (params.mode.isDerivedRoutingFrom(ApplicationMode.BICYCLE)) {
uri.append("&v=bicycle") ; //$NON-NLS-1$
} else if (params.mode.isDerivedRoutingFrom(ApplicationMode.PEDESTRIAN)) {
uri.append("&v=foot") ; //$NON-NLS-1$
} else if(params.mode.isDerivedRoutingFrom(ApplicationMode.CAR)){
uri.append("&v=motorcar"); //$NON-NLS-1$
} else {
return applicationModeNotSupported(params);
}
uri.append("&fast=").append(params.fast ? "1" : "0").append("&layer=mapnik"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
log.info("URL route " + uri);
URLConnection connection = NetworkUtils.getHttpURLConnection(uri.toString());
connection.setRequestProperty("User-Agent", Version.getFullVersion(params.ctx));
DocumentBuilder dom = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = dom.parse(new InputSource(new InputStreamReader(connection.getInputStream())));
NodeList list = doc.getElementsByTagName("coordinates"); //$NON-NLS-1$
for(int i=0; i<list.getLength(); i++){
Node item = list.item(i);
String str = item.getFirstChild().getNodeValue();
if(str == null){
continue;
}
int st = 0;
int next = 0;
while((next = str.indexOf('\n', st)) != -1){
String coordinate = str.substring(st, next + 1);
int s = coordinate.indexOf(',');
if (s != -1) {
try {
double lon = Double.parseDouble(coordinate.substring(0, s));
double lat = Double.parseDouble(coordinate.substring(s + 1));
Location l = new Location("router"); //$NON-NLS-1$
l.setLatitude(lat);
l.setLongitude(lon);
res.add(l);
} catch (NumberFormatException e) {
}
}
st = next + 1;
}
}
if(list.getLength() == 0){
if(doc.getChildNodes().getLength() == 1){
Node item = doc.getChildNodes().item(0);
return new RouteCalculationResult(item.getNodeValue());
}
}
params.intermediates = null;
return new RouteCalculationResult(res, null, params, null, true);
}
protected RouteCalculationResult findVectorMapsRoute(final RouteCalculationParams params, boolean calcGPXRoute) throws IOException {
BinaryMapIndexReader[] files = params.ctx.getResourceManager().getRoutingMapFiles();
RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(false);
OsmandSettings settings = params.ctx.getSettings();
router.setUseFastRecalculation(settings.USE_FAST_RECALCULATION.get());
RoutingConfiguration.Builder config = params.ctx.getDefaultRoutingConfig();
GeneralRouter generalRouter = SettingsNavigationActivity.getRouter(config, params.mode);
if(generalRouter == null) {
return applicationModeNotSupported(params);
}
RoutingConfiguration cf = initOsmAndRoutingConfig(config, params, settings, generalRouter);
if(cf == null){
return applicationModeNotSupported(params);
}
PrecalculatedRouteDirection precalculated = null;
if(calcGPXRoute) {
ArrayList<Location> sublist = findStartAndEndLocationsFromRoute(params.gpxRoute.points,
params.start, params.end, null, null);
LatLon[] latLon = new LatLon[sublist.size()];
for(int k = 0; k < latLon.length; k ++) {
latLon[k] = new LatLon(sublist.get(k).getLatitude(), sublist.get(k).getLongitude());
}
precalculated = PrecalculatedRouteDirection.build(latLon, generalRouter.getMaxDefaultSpeed());
precalculated.setFollowNext(true);
//cf.planRoadDirection = 1;
}
// BUILD context
NativeOsmandLibrary lib = settings.SAFE_MODE.get() ? null : NativeOsmandLibrary.getLoadedLibrary();
// check loaded files
int leftX = MapUtils.get31TileNumberX(params.start.getLongitude());
int rightX = leftX;
int bottomY = MapUtils.get31TileNumberY(params.start.getLatitude());
int topY = bottomY;
if (params.intermediates != null) {
for (LatLon l : params.intermediates) {
leftX = Math.min(MapUtils.get31TileNumberX(l.getLongitude()), leftX);
rightX = Math.max(MapUtils.get31TileNumberX(l.getLongitude()), rightX);
bottomY = Math.max(MapUtils.get31TileNumberY(l.getLatitude()), bottomY);
topY = Math.min(MapUtils.get31TileNumberY(l.getLatitude()), topY);
}
}
LatLon l = params.end;
leftX = Math.min(MapUtils.get31TileNumberX(l.getLongitude()), leftX);
rightX = Math.max(MapUtils.get31TileNumberX(l.getLongitude()), rightX);
bottomY = Math.max(MapUtils.get31TileNumberY(l.getLatitude()), bottomY);
topY = Math.min(MapUtils.get31TileNumberY(l.getLatitude()), topY);
params.ctx.getResourceManager().getRenderer().checkInitialized(15, lib, leftX, rightX, bottomY, topY);
RoutingContext ctx = router.buildRoutingContext(cf,
lib, files,
RouteCalculationMode.NORMAL);
RoutingContext complexCtx = null;
boolean complex = params.mode.isDerivedRoutingFrom(ApplicationMode.CAR) && !settings.DISABLE_COMPLEX_ROUTING.get()
&& precalculated == null;
ctx.leftSideNavigation = params.leftSide;
ctx.calculationProgress = params.calculationProgress;
if(params.previousToRecalculate != null && params.onlyStartPointChanged) {
int currentRoute = params.previousToRecalculate.getCurrentRoute();
List<RouteSegmentResult> originalRoute = params.previousToRecalculate.getOriginalRoute();
if(originalRoute != null && currentRoute < originalRoute.size()) {
ctx.previouslyCalculatedRoute = originalRoute.subList(currentRoute, originalRoute.size());
}
}
if(complex && router.getRecalculationEnd(ctx) != null) {
complex = false;
}
if(complex) {
complexCtx = router.buildRoutingContext(cf, lib,files,
RouteCalculationMode.COMPLEX);
complexCtx.calculationProgress = params.calculationProgress;
complexCtx.leftSideNavigation = params.leftSide;
complexCtx.previouslyCalculatedRoute = ctx.previouslyCalculatedRoute;
}
LatLon st = new LatLon(params.start.getLatitude(), params.start.getLongitude());
LatLon en = new LatLon(params.end.getLatitude(), params.end.getLongitude());
List<LatLon> inters = new ArrayList<LatLon>();
if (params.intermediates != null) {
inters = new ArrayList<LatLon>(params.intermediates);
}
return calcOfflineRouteImpl(params, router, ctx, complexCtx, st, en, inters, precalculated);
}
private RoutingConfiguration initOsmAndRoutingConfig(Builder config, final RouteCalculationParams params, OsmandSettings settings,
GeneralRouter generalRouter) throws IOException, FileNotFoundException {
GeneralRouterProfile p ;
if (params.mode.isDerivedRoutingFrom(ApplicationMode.BICYCLE)) {
p = GeneralRouterProfile.BICYCLE;
} else if (params.mode.isDerivedRoutingFrom(ApplicationMode.PEDESTRIAN)) {
p = GeneralRouterProfile.PEDESTRIAN;
} else if(params.mode.isDerivedRoutingFrom(ApplicationMode.CAR)){
p = GeneralRouterProfile.CAR;
} else {
return null;
}
Map<String, String> paramsR = new LinkedHashMap<String, String>();
for(Map.Entry<String, RoutingParameter> e : generalRouter.getParameters().entrySet()){
String key = e.getKey();
RoutingParameter pr = e.getValue();
String vl;
if(key.equals(GeneralRouter.USE_SHORTEST_WAY)) {
Boolean bool = !settings.FAST_ROUTE_MODE.getModeValue(params.mode);
vl = bool ? "true" : null;
} else if(pr.getType() == RoutingParameterType.BOOLEAN) {
CommonPreference<Boolean> pref = settings.getCustomRoutingBooleanProperty(key, pr.getDefaultBoolean());
Boolean bool = pref.getModeValue(params.mode);
vl = bool ? "true" : null;
} else {
vl = settings.getCustomRoutingProperty(key, "").getModeValue(params.mode);
}
if(vl != null && vl.length() > 0) {
paramsR.put(key, vl);
}
}
float mb = (1 << 20);
Runtime rt = Runtime.getRuntime();
// make visible
int memoryLimit = (int) (0.95 * ((rt.maxMemory() - rt.totalMemory()) + rt.freeMemory()) / mb);
log.warn("Use " + memoryLimit + " MB Free " + rt.freeMemory() / mb + " of " + rt.totalMemory() / mb + " max " + rt.maxMemory() / mb);
RoutingConfiguration cf = config.build(p.name().toLowerCase(), params.start.hasBearing() ?
params.start.getBearing() / 180d * Math.PI : null,
memoryLimit, paramsR);
return cf;
}
private RouteCalculationResult calcOfflineRouteImpl(final RouteCalculationParams params,
RoutePlannerFrontEnd router, RoutingContext ctx, RoutingContext complexCtx, LatLon st, LatLon en,
List<LatLon> inters, PrecalculatedRouteDirection precalculated) throws IOException {
try {
List<RouteSegmentResult> result ;
if(complexCtx != null) {
try {
result = router.searchRoute(complexCtx, st, en, inters, precalculated);
// discard ctx and replace with calculated
ctx = complexCtx;
} catch(final RuntimeException e) {
params.ctx.runInUIThread(new Runnable() {
@Override
public void run() {
params.ctx.showToastMessage(R.string.complex_route_calculation_failed, e.getMessage());
}
});
result = router.searchRoute(ctx, st, en, inters);
}
} else {
result = router.searchRoute(ctx, st, en, inters);
}
if(result == null || result.isEmpty()) {
if(ctx.calculationProgress.segmentNotFound == 0) {
return new RouteCalculationResult(params.ctx.getString(R.string.starting_point_too_far));
} else if(ctx.calculationProgress.segmentNotFound == inters.size() + 1) {
return new RouteCalculationResult(params.ctx.getString(R.string.ending_point_too_far));
} else if(ctx.calculationProgress.segmentNotFound > 0) {
return new RouteCalculationResult(params.ctx.getString(R.string.intermediate_point_too_far, "'" + ctx.calculationProgress.segmentNotFound + "'"));
}
if(ctx.calculationProgress.directSegmentQueueSize == 0) {
return new RouteCalculationResult("Route can not be found from start point (" +ctx.calculationProgress.distanceFromBegin/1000f+" km)");
} else if(ctx.calculationProgress.reverseSegmentQueueSize == 0) {
return new RouteCalculationResult("Route can not be found from end point (" +ctx.calculationProgress.distanceFromEnd/1000f+" km)");
}
if(ctx.calculationProgress.isCancelled) {
return interrupted();
}
// something really strange better to see that message on the scren
return emptyResult();
} else {
RouteCalculationResult res = new RouteCalculationResult(result, params.start, params.end,
params.intermediates, params.ctx, params.leftSide, ctx.routingTime, params.gpxRoute == null? null: params.gpxRoute.wpt,
params.mode);
return res;
}
} catch (RuntimeException e) {
return new RouteCalculationResult(e.getMessage() );
} catch (InterruptedException e) {
return interrupted();
} catch (OutOfMemoryError e) {
// ActivityManager activityManager = (ActivityManager)app.getSystemService(Context.ACTIVITY_SERVICE);
// ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
// activityManager.getMemoryInfo(memoryInfo);
// int avl = (int) (memoryInfo.availMem / (1 << 20));
int max = (int) (Runtime.getRuntime().maxMemory() / (1 << 20));
int avl = (int) (Runtime.getRuntime().freeMemory() / (1 << 20));
String s = " (" + avl + " MB available of " + max + ") ";
return new RouteCalculationResult("Not enough process memory "+ s);
}
}
private RouteCalculationResult applicationModeNotSupported(RouteCalculationParams params) {
return new RouteCalculationResult("Application mode '"+ params.mode.toHumanStringCtx(params.ctx)+ "'is not supported.");
}
private RouteCalculationResult interrupted() {
return new RouteCalculationResult("Route calculation was interrupted");
}
private RouteCalculationResult emptyResult() {
return new RouteCalculationResult("Empty result");
}
private static List<RouteDirectionInfo> parseOsmAndGPXRoute(List<Location> res, GPXFile gpxFile, boolean osmandRouter,
boolean leftSide, float defSpeed) {
List<RouteDirectionInfo> directions = null;
if (!osmandRouter) {
for (WptPt pt : gpxFile.points) {
res.add(createLocation(pt));
}
} else {
for (Track tr : gpxFile.tracks) {
for (TrkSegment ts : tr.segments) {
for (WptPt p : ts.points) {
res.add(createLocation(p));
}
}
}
}
float[] distanceToEnd = new float[res.size()];
for (int i = res.size() - 2; i >= 0; i--) {
distanceToEnd[i] = distanceToEnd[i + 1] + res.get(i).distanceTo(res.get(i + 1));
}
Route route = null;
if (gpxFile.routes.size() > 0) {
route = gpxFile.routes.get(0);
}
RouteDirectionInfo previous = null;
if (route != null && route.points.size() > 0) {
directions = new ArrayList<RouteDirectionInfo>();
Iterator<WptPt> iterator = route.points.iterator();
while(iterator.hasNext()){
WptPt item = iterator.next();
try {
String stime = item.getExtensionsToRead().get("time");
int time = 0;
if (stime != null) {
time = Integer.parseInt(stime);
}
int offset = Integer.parseInt(item.getExtensionsToRead().get("offset")); //$NON-NLS-1$
if(directions.size() > 0) {
RouteDirectionInfo last = directions.get(directions.size() - 1);
// update speed using time and idstance
last.setAverageSpeed((distanceToEnd[last.routePointOffset] - distanceToEnd[offset])/last.getAverageSpeed());
last.distance = (int) Math.round(distanceToEnd[last.routePointOffset] - distanceToEnd[offset]);
}
// save time as a speed because we don't know distance of the route segment
float avgSpeed = time;
if(!iterator.hasNext() && time > 0) {
avgSpeed = distanceToEnd[offset] / time;
}
String stype = item.getExtensionsToRead().get("turn"); //$NON-NLS-1$
TurnType turnType;
if (stype != null) {
turnType = TurnType.fromString(stype.toUpperCase(), leftSide);
} else {
turnType = TurnType.straight();
}
String sturn = item.getExtensionsToRead().get("turn-angle"); //$NON-NLS-1$
if (sturn != null) {
turnType.setTurnAngle((float) Double.parseDouble(sturn));
}
RouteDirectionInfo dirInfo = new RouteDirectionInfo(avgSpeed, turnType);
dirInfo.setDescriptionRoute(item.desc); //$NON-NLS-1$
dirInfo.routePointOffset = offset;
// Issue #2894
String sref = item.getExtensionsToRead().get("ref"); //$NON-NLS-1$
if (sref != null && !"null".equals(sref)) {
dirInfo.setRef(sref); //$NON-NLS-1$
}
String sstreetname = item.getExtensionsToRead().get("street-name"); //$NON-NLS-1$
if (sstreetname != null && !"null".equals(sstreetname)) {
dirInfo.setStreetName(sstreetname); //$NON-NLS-1$
}
String sdest = item.getExtensionsToRead().get("dest"); //$NON-NLS-1$
if (sdest != null && !"null".equals(sdest)) {
dirInfo.setDestinationName(sdest); //$NON-NLS-1$
}
if (previous != null && TurnType.C != previous.getTurnType().getValue() &&
!osmandRouter) {
// calculate angle
if (previous.routePointOffset > 0) {
float paz = res.get(previous.routePointOffset - 1).bearingTo(res.get(previous.routePointOffset));
float caz;
if (previous.getTurnType().isRoundAbout() && dirInfo.routePointOffset < res.size() - 1) {
caz = res.get(dirInfo.routePointOffset).bearingTo(res.get(dirInfo.routePointOffset + 1));
} else {
caz = res.get(dirInfo.routePointOffset - 1).bearingTo(res.get(dirInfo.routePointOffset));
}
float angle = caz - paz;
if (angle < 0) {
angle += 360;
} else if (angle > 360) {
angle -= 360;
}
// that magic number helps to fix some errors for turn
angle += 75;
if (previous.getTurnType().getTurnAngle() < 0.5f) {
previous.getTurnType().setTurnAngle(angle);
}
}
}
directions.add(dirInfo);
previous = dirInfo;
} catch (NumberFormatException e) {
log.info("Exception", e); //$NON-NLS-1$
} catch (IllegalArgumentException e) {
log.info("Exception", e); //$NON-NLS-1$
}
}
}
if (previous != null && TurnType.C != previous.getTurnType().getValue()) {
// calculate angle
if (previous.routePointOffset > 0 && previous.routePointOffset < res.size() - 1) {
float paz = res.get(previous.routePointOffset - 1).bearingTo(res.get(previous.routePointOffset));
float caz = res.get(previous.routePointOffset).bearingTo(res.get(res.size() - 1));
float angle = caz - paz;
if (angle < 0) {
angle += 360;
}
if (previous.getTurnType().getTurnAngle() < 0.5f) {
previous.getTurnType().setTurnAngle(angle);
}
}
}
return directions;
}
protected RouteCalculationResult findORSRoute(RouteCalculationParams params) throws MalformedURLException, IOException, ParserConfigurationException, FactoryConfigurationError,
SAXException {
List<Location> res = new ArrayList<Location>();
String rpref = "Fastest";
if (params.mode.isDerivedRoutingFrom(ApplicationMode.PEDESTRIAN)) {
rpref = "Pedestrian";
} else if (params.mode.isDerivedRoutingFrom(ApplicationMode.BICYCLE)) {
rpref = "Bicycle";
// } else if (ApplicationMode.LOWTRAFFIC == mode) {
// rpref = "BicycleSafety";
// } else if (ApplicationMode.RACEBIKE == mode) {
// rpref = "BicycleRacer";
// } else if (ApplicationMode.TOURBIKE == mode) {
// rpref = "BicycleRoute";
// } else if (ApplicationMode.MTBIKE == mode) {
// rpref = "BicycleMTB";
} else if (params.mode.isDerivedRoutingFrom(ApplicationMode.CAR)) {
if (!params.fast) {
rpref = "Shortest";
}
} else {
return applicationModeNotSupported(params);
}
StringBuilder request = new StringBuilder();
request.append("http://openls.geog.uni-heidelberg.de/osm/eu/routing?").append("start=").append(params.start.getLongitude()).append(',')
.append(params.start.getLatitude()).append("&end=").append(params.end.getLongitude()).append(',').append(params.end.getLatitude())
.append("&preference=").append(rpref);
// TODO if we would get instructions from the service, we could use this language setting
// .append("&language=").append(Locale.getDefault().getLanguage());
log.info("URL route " + request);
URLConnection connection = NetworkUtils.getHttpURLConnection(request.toString());
connection.setRequestProperty("User-Agent", Version.getFullVersion(params.ctx));
DocumentBuilder dom = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = dom.parse(new InputSource(new InputStreamReader(connection.getInputStream())));
NodeList list = doc.getElementsByTagName("xls:RouteGeometry"); //$NON-NLS-1$
for (int i = 0; i < list.getLength(); i++) {
NodeList poslist = ((Element) list.item(i)).getElementsByTagName("gml:pos"); //$NON-NLS-1$
for (int j = 0; j < poslist.getLength(); j++) {
String text = poslist.item(j).getFirstChild().getNodeValue();
int s = text.indexOf(' ');
try {
double lon = Double.parseDouble(text.substring(0, s));
double lat = Double.parseDouble(text.substring(s + 1));
Location l = new Location("router"); //$NON-NLS-1$
l.setLatitude(lat);
l.setLongitude(lon);
res.add(l);
} catch (NumberFormatException nfe) {
}
}
}
if (list.getLength() == 0) {
if (doc.getChildNodes().getLength() == 1) {
Node item = doc.getChildNodes().item(0);
return new RouteCalculationResult(item.getNodeValue());
}
}
params.intermediates = null;
return new RouteCalculationResult(res, null, params, null, true);
}
public GPXFile createOsmandRouterGPX(RouteCalculationResult srcRoute, OsmandApplication ctx) {
TargetPointsHelper helper = ctx.getTargetPointsHelper();
int currentRoute = srcRoute.currentRoute;
List<Location> routeNodes = srcRoute.getImmutableAllLocations();
List<RouteDirectionInfo> directionInfo = srcRoute.getImmutableAllDirections();
int currentDirectionInfo = srcRoute.currentDirectionInfo;
GPXFile gpx = new GPXFile();
gpx.author = OSMAND_ROUTER;
Track track = new Track();
gpx.tracks.add(track);
TrkSegment trkSegment = new TrkSegment();
track.segments.add(trkSegment);
int cRoute = currentRoute;
int cDirInfo = currentDirectionInfo;
// Save the start point to gpx file's trkpt section unless already contained
WptPt startpoint = new WptPt();
TargetPoint sc = helper.getPointToStart();
int routePointOffsetAdjusted = 0;
if (sc != null && ((float) sc.getLatitude() != (float) routeNodes.get(cRoute).getLatitude() || (float) sc.getLongitude() != (float) routeNodes.get(cRoute).getLongitude())){
startpoint.lat = sc.getLatitude();
startpoint.lon = sc.getLongitude();
trkSegment.points.add(startpoint);
if (directionInfo != null && !directionInfo.isEmpty()) {
for (RouteDirectionInfo i : directionInfo) {
i.routePointOffset++;
}
}
routePointOffsetAdjusted = 1;
}
for (int i = cRoute; i< routeNodes.size(); i++) {
Location loc = routeNodes.get(i);
WptPt pt = new WptPt();
pt.lat = loc.getLatitude();
pt.lon = loc.getLongitude();
if (loc.hasSpeed()) {
pt.speed = loc.getSpeed();
}
if (loc.hasAltitude()) {
pt.ele = loc.getAltitude();
}
if (loc.hasAccuracy()) {
pt.hdop = loc.getAccuracy();
}
trkSegment.points.add(pt);
}
Route route = new Route();
gpx.routes.add(route);
for (int i = cDirInfo; i < directionInfo.size(); i++) {
RouteDirectionInfo dirInfo = directionInfo.get(i);
if (dirInfo.routePointOffset - routePointOffsetAdjusted >= cRoute) {
if (dirInfo.getTurnType() != null && !dirInfo.getTurnType().isSkipToSpeak() &&
dirInfo.routePointOffset - routePointOffsetAdjusted < routeNodes.size()) {
Location loc = routeNodes.get(dirInfo.routePointOffset - routePointOffsetAdjusted);
WptPt pt = new WptPt();
pt.lat = loc.getLatitude();
pt.lon = loc.getLongitude();
// Collect distances and times for subsequent suppressed turns
int collectedDistance = 0;
int collectedTime = 0;
for (int j = i + 1; j < directionInfo.size(); j++) {
if (directionInfo.get(j).getTurnType() != null && directionInfo.get(j).getTurnType().isSkipToSpeak()) {
collectedDistance += directionInfo.get(j).getDistance();
collectedTime += directionInfo.get(j).getExpectedTime();
} else {
break;
}
}
pt.desc = dirInfo.getDescriptionRoute(ctx, collectedDistance + dirInfo.getDistance());
Map<String, String> extensions = pt.getExtensionsToWrite();
extensions.put("time", (collectedTime + dirInfo.getExpectedTime()) + "");
int turnType = dirInfo.getTurnType().getValue();
if (TurnType.C != turnType) {
extensions.put("turn", dirInfo.getTurnType().toXmlString());
extensions.put("turn-angle", dirInfo.getTurnType().getTurnAngle() + "");
}
extensions.put("offset", (dirInfo.routePointOffset - cRoute) + "");
// Issue #2894
if (dirInfo.getRef() != null && !"null".equals(dirInfo.getRef())) {
extensions.put("ref", dirInfo.getRef() + "");
}
if (dirInfo.getStreetName() != null && !"null".equals(dirInfo.getStreetName())) {
extensions.put("street-name", dirInfo.getStreetName() + "");
}
if (dirInfo.getDestinationName() != null && !"null".equals(dirInfo.getDestinationName())) {
extensions.put("dest", dirInfo.getDestinationName() + "");
}
route.points.add(pt);
}
}
}
List<TargetPoint> ps = helper.getIntermediatePointsWithTarget();
for (int k = 0; k < ps.size(); k++) {
WptPt pt = new WptPt();
pt.lat = ps.get(k).getLatitude();
pt.lon = ps.get(k).getLongitude();
if (k < ps.size()) {
pt.name = ps.get(k).getOnlyName() +"";
if (k == ps.size() - 1) {
String target = ctx.getString(R.string.destination_point, "");
if (pt.name.startsWith(target)) {
pt.name = ctx.getString(R.string.destination_point, pt.name);
}
} else {
String prefix = (k + 1) +". ";
if(Algorithms.isEmpty(pt.name)) {
pt.name = ctx.getString(R.string.target_point, pt.name);
}
if (pt.name.startsWith(prefix)) {
pt.name = prefix + pt.name;
}
}
pt.desc = pt.name;
}
gpx.points.add(pt);
}
return gpx;
}
private void appendOSRMLoc(StringBuilder uri, LatLon il) {
uri.append(";").append(String.valueOf(il.getLongitude()));
uri.append(",").append(String.valueOf(il.getLatitude()));
}
protected RouteCalculationResult findOSRMRoute(RouteCalculationParams params)
throws MalformedURLException, IOException, JSONException {
// http://router.project-osrm.org/route/v1/driving/4.83,52.28;4.95,52.28
List<Location> res = new ArrayList<Location>();
StringBuilder uri = new StringBuilder();
// possibly hide that API key because it is privacy of osmand
// A6421860EBB04234AB5EF2D049F2CD8F key is compromised
String scheme = "";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
scheme = "https";
} else {
scheme = "http";
}
uri.append(scheme + "://router.project-osrm.org/route/v1/driving/"); //$NON-NLS-1$
uri.append(String.valueOf(params.start.getLongitude()));
uri.append(",").append(String.valueOf(params.start.getLatitude()));
if(params.intermediates != null && params.intermediates.size() > 0) {
for(LatLon il : params.intermediates) {
appendOSRMLoc(uri, il);
}
}
appendOSRMLoc(uri, params.end);
// to get more waypoints, add overview=full option
// uri.append("?overview=full")
log.info("URL route " + uri);
URLConnection connection = NetworkUtils.getHttpURLConnection(uri.toString());
connection.setRequestProperty("User-Agent", Version.getFullVersion(params.ctx));
StringBuilder content = new StringBuilder();
BufferedReader rs = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String s;
while((s = rs.readLine()) != null) {
content.append(s);
}
JSONObject obj = new JSONObject(content.toString());
try {
rs.close();
} catch(IOException e){
}
List<LatLon> route = GeoPolylineParserUtil.parse(obj.getJSONArray("routes").getJSONObject(0).getString("geometry"),
GeoPolylineParserUtil.PRECISION_5);
if (route.isEmpty()) {
return new RouteCalculationResult("Route is empty");
}
for (LatLon pt : route) {
WptPt wpt = new WptPt();
wpt.lat = pt.getLatitude();
wpt.lon = pt.getLongitude();
res.add(createLocation(wpt));
}
params.intermediates = null;
return new RouteCalculationResult(res, null, params, null, true);
}
protected RouteCalculationResult findBROUTERRoute(RouteCalculationParams params) throws MalformedURLException,
IOException, ParserConfigurationException, FactoryConfigurationError, SAXException {
int numpoints = 2 + (params.intermediates != null ? params.intermediates.size() : 0);
double[] lats = new double[numpoints];
double[] lons = new double[numpoints];
int index = 0;
String mode;
lats[index] = params.start.getLatitude();
lons[index] = params.start.getLongitude();
index++;
if(params.intermediates != null && params.intermediates.size() > 0) {
for(LatLon il : params.intermediates) {
lats[index] = il.getLatitude();
lons[index] = il.getLongitude();
index++;
}
}
lats[index] = params.end.getLatitude();
lons[index] = params.end.getLongitude();
if (ApplicationMode.PEDESTRIAN == params.mode) {
mode = "foot"; //$NON-NLS-1$
} else if (ApplicationMode.BICYCLE == params.mode) {
mode = "bicycle"; //$NON-NLS-1$
} else {
mode = "motorcar"; //$NON-NLS-1$
}
Bundle bpars = new Bundle();
bpars.putDoubleArray("lats", lats);
bpars.putDoubleArray("lons", lons);
bpars.putString("fast", params.fast ? "1" : "0");
bpars.putString("v", mode);
bpars.putString("trackFormat", "gpx");
OsmandApplication ctx = (OsmandApplication) params.ctx;
List<Location> res = new ArrayList<Location>();
IBRouterService brouterService = ctx.getBRouterService();
if (brouterService == null) {
return new RouteCalculationResult("BRouter service is not available");
}
try {
String gpxMessage = brouterService.getTrackFromParams(bpars);
if (gpxMessage == null)
gpxMessage = "no result from brouter";
if (!gpxMessage.startsWith("<")) {
return new RouteCalculationResult(gpxMessage);
}
GPXFile gpxFile = GPXUtilities.loadGPXFile(
ctx, new ByteArrayInputStream(gpxMessage.getBytes("UTF-8")));
for (Track track : gpxFile.tracks) {
for (TrkSegment ts : track.segments) {
for (WptPt p : ts.points) {
Location l = new Location("router"); //$NON-NLS-1$
l.setLatitude(p.lat);
l.setLongitude(p.lon);
if (p.ele != Double.NaN) {
l.setAltitude(p.ele);
}
res.add(l);
}
}
}
} catch (Exception e) {
return new RouteCalculationResult("Exception calling BRouter: " + e); //$NON-NLS-1$
}
return new RouteCalculationResult(res, null, params, null, true);
}
private RouteCalculationResult findStraightRoute(RouteCalculationParams params) {
double[] lats = new double[] { params.start.getLatitude(), params.end.getLatitude() };
double[] lons = new double[] { params.start.getLongitude(), params.end.getLongitude() };
List<LatLon> intermediates = params.intermediates;
List<Location> dots = new ArrayList<Location>();
//writing start location
Location location = new Location(String.valueOf("start"));
location.setLatitude(lats[0]);
location.setLongitude(lons[0]);
//adding intermediate dots if they exists
if (intermediates != null){
for(int i =0; i<intermediates.size();i++){
location = new Location(String.valueOf(i));
location.setLatitude(intermediates.get(i).getLatitude());
location.setLongitude(intermediates.get(i).getLongitude());
dots.add(location);
}
}
//writing end location
location = new Location(String.valueOf("end"));
location.setLatitude(lats[1]);
location.setLongitude(lons[1]);
dots.add(location);
return new RouteCalculationResult(dots, null, params, null, true);
}
}