diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java index 6ebe1645ee..43f512b448 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java @@ -513,7 +513,7 @@ public class RouteSegmentResult implements StringExternalizable return endPointIndex - startPointIndex > 0; } - + private LatLon convertPoint(RouteDataObject o, int ind){ return new LatLon(MapUtils.get31LatitudeY(o.getPoint31YTile(ind)), MapUtils.get31LongitudeX(o.getPoint31XTile(ind))); } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java index 80359f7dca..8357a606fe 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java @@ -466,14 +466,16 @@ public class RoutingOptionsHelper { List list = new ArrayList(); RouteProvider.GPXRouteParamsBuilder rparams = routingHelper.getCurrentGPXRoute(); boolean osmandRouter = am.getRouteService() == RouteProvider.RouteService.OSMAND; - if (rparams != null && !routingHelper.isCurrentGPXRouteV2() && osmandRouter) { + if (rparams != null && osmandRouter) { GPXUtilities.GPXFile fl = rparams.getFile(); if (fl.hasRtePt()) { list.add(new OtherLocalRoutingParameter(R.string.use_points_as_intermediates, app.getString(R.string.use_points_as_intermediates), rparams.isUseIntermediatePointsRTE())); } - list.add(new OtherLocalRoutingParameter(R.string.gpx_option_reverse_route, - app.getString(R.string.gpx_option_reverse_route), rparams.isReverse())); + if (!routingHelper.isCurrentGPXRouteV2()) { + list.add(new OtherLocalRoutingParameter(R.string.gpx_option_reverse_route, + app.getString(R.string.gpx_option_reverse_route), rparams.isReverse())); + } if (!rparams.isUseIntermediatePointsRTE()) { list.add(new OtherLocalRoutingParameter(R.string.gpx_option_from_start_point, app.getString(R.string.gpx_option_from_start_point), rparams.isPassWholeRoute())); diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java index e70752b7f1..a458b281e9 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java @@ -137,7 +137,7 @@ public class RouteCalculationResult { } public RouteCalculationResult(List list, Location start, LatLon end, List intermediates, - OsmandApplication ctx, boolean leftSide, RoutingContext rctx, List waypoints, ApplicationMode mode) { + OsmandApplication ctx, boolean leftSide, RoutingContext rctx, List waypoints, ApplicationMode mode, boolean calculateFirstAndLastPoint) { if (rctx != null) { this.routingTime = rctx.routingTime; this.visitedSegments = rctx.getVisitedSegments(); @@ -162,7 +162,9 @@ public class RouteCalculationResult { List locations = new ArrayList(); ArrayList alarms = new ArrayList(); List segments = convertVectorResult(computeDirections, locations, list, alarms, ctx); - introduceFirstPointAndLastPoint(locations, computeDirections, segments, start, end, ctx); + if (calculateFirstAndLastPoint) { + introduceFirstPointAndLastPoint(locations, computeDirections, segments, start, end, ctx); + } this.locations = Collections.unmodifiableList(locations); this.segments = Collections.unmodifiableList(segments); @@ -300,6 +302,37 @@ public class RouteCalculationResult { return list; } + public List getRoute(int startIndex) { + if (segments.size() == 0) { + return null; + } + List list = new ArrayList(); + int skippedPoints = 0; + for (int i = 1; i <= startIndex; i++) { + RouteSegmentResult seg = segments.get(i - 1); + if (seg != segments.get(i)) { + skippedPoints += Math.abs(seg.getEndPointIndex() - seg.getStartPointIndex()); + } + } + list.add(segments.get(startIndex++)); + for (int i = startIndex; i < segments.size(); i++) { + if (segments.get(i - 1) != segments.get(i)) { + list.add(segments.get(i)); + } + } + if (!list.isEmpty()) { + RouteSegmentResult seg = list.get(0); + if (seg.isForwardDirection()) { + int index = seg.getStartPointIndex() + startIndex - skippedPoints; + seg.setStartPointIndex(index); + } else { + int index = seg.getEndPointIndex() + startIndex - skippedPoints; + seg.setEndPointIndex(index); + } + } + return list; + } + /** * PREPARATION */ diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java index 6626d5e23c..f9d43df2d2 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java @@ -79,6 +79,7 @@ public class RouteProvider { private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RouteProvider.class); private static final String OSMAND_ROUTER = "OsmAndRouter"; private static final int MIN_DISTANCE_FOR_INSERTING_ROUTE_SEGMENT = 60; + private static final int ADDITIONAL_DISTANCE_FOR_START_POINT = 300; private static final int MIN_STRAIGHT_DIST = 50000; public enum RouteService { @@ -366,22 +367,51 @@ public class RouteProvider { } private RouteCalculationResult calculateGpxRoute(RouteCalculationParams routeParams) throws IOException { - - List route = routeParams.gpxRoute.route; - if (!Algorithms.isEmpty(route)) { - return new RouteCalculationResult(route, routeParams.start, routeParams.end, - routeParams.intermediates, routeParams.ctx, routeParams.leftSide, null, null, routeParams.mode); - } - // get the closest point to start and to end GPXRouteParams gpxParams = routeParams.gpxRoute; + List gpxRouteResult = routeParams.gpxRoute.route; + if (!Algorithms.isEmpty(gpxRouteResult)) { + boolean calculateOsmAndRouteParts = gpxParams.calculateOsmAndRouteParts; + if (routeParams.gpxRoute.passWholeRoute && !calculateOsmAndRouteParts) { + return new RouteCalculationResult(gpxRouteResult, routeParams.start, routeParams.end, + routeParams.intermediates, routeParams.ctx, routeParams.leftSide, null, null, routeParams.mode, true); + } + RouteCalculationResult result = new RouteCalculationResult(gpxRouteResult, routeParams.start, routeParams.end, + routeParams.intermediates, routeParams.ctx, routeParams.leftSide, null, null, routeParams.mode, false); + List gpxRouteLocations = result.getImmutableAllLocations(); + int gpxNextIndex = routeParams.gpxRoute.passWholeRoute ? 0 : findStartIndexFromRoute(gpxRouteLocations, routeParams.start, calculateOsmAndRouteParts); + Location gpxNextLocation; + List firstSegmentRoute = null; + List gpxRoute; + if (gpxNextIndex > 0) { + gpxNextLocation = gpxRouteLocations.get(gpxNextIndex); + gpxRoute = result.getRoute(gpxNextIndex); + } else { + gpxNextLocation = gpxRouteLocations.get(0); + gpxRoute = result.getOriginalRoute(); + } + if (calculateOsmAndRouteParts + && routeParams.start != null && gpxNextLocation != null + && gpxNextLocation.distanceTo(routeParams.start) > MIN_DISTANCE_FOR_INSERTING_ROUTE_SEGMENT) { + RouteCalculationResult firstSegmentResult = findOfflineRouteSegment(routeParams, routeParams.start, new LatLon(gpxNextLocation.getLatitude(), gpxNextLocation.getLongitude())); + firstSegmentRoute = firstSegmentResult.getOriginalRoute(); + } + List newGpxRoute = new ArrayList<>(); + if (firstSegmentRoute != null && !firstSegmentRoute.isEmpty()) { + newGpxRoute.addAll(firstSegmentRoute); + } + newGpxRoute.addAll(gpxRoute); + return new RouteCalculationResult(newGpxRoute, routeParams.start, routeParams.end, + routeParams.intermediates, routeParams.ctx, routeParams.leftSide, null, null, routeParams.mode, true); + } + if(routeParams.gpxRoute.useIntermediatePointsRTE){ return calculateOsmAndRouteWithIntermediatePoints(routeParams, gpxParams.points); } List gpxRoute ; int[] startI = new int[]{0}; int[] endI = new int[]{gpxParams.points.size()}; - if(routeParams.gpxRoute.passWholeRoute) { + if (routeParams.gpxRoute.passWholeRoute) { gpxRoute = gpxParams.points; if (routeParams.previousToRecalculate != null && routeParams.onlyStartPointChanged) { List routeLocations = routeParams.previousToRecalculate.getRouteLocations(); @@ -389,7 +419,7 @@ public class RouteProvider { gpxRoute = new ArrayList<>(); Location trackStart = routeLocations.get(0); Location realStart = routeParams.start; - //insert route segment from current location to next route location if user deviated from route + //insert gpxRouteResult segment from current location to next gpxRouteResult location if user deviated from gpxRouteResult if (realStart != null && trackStart != null && realStart.distanceTo(trackStart) > MIN_DISTANCE_FOR_INSERTING_ROUTE_SEGMENT && !gpxParams.calculateOsmAndRouteParts) { @@ -625,6 +655,30 @@ public class RouteProvider { return sublist; } + private int findStartIndexFromRoute(List route, Location startLoc, boolean calculateOsmAndRouteParts) { + float minDist = Integer.MAX_VALUE; + int start = 0; + 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; + } + } + } + if (start > 0 && calculateOsmAndRouteParts) { + Location newStartLoc = route.get(start); + for (int i = start + 1; i < route.size(); i++) { + Location loc = route.get(i); + if (loc.distanceTo(newStartLoc) >= ADDITIONAL_DISTANCE_FOR_START_POINT) { + return i; + } + } + } + return start; + } + protected String getString(Context ctx, int resId){ if(ctx == null){ return ""; //$NON-NLS-1$ @@ -812,7 +866,7 @@ public class RouteProvider { } else { RouteCalculationResult res = new RouteCalculationResult(result, params.start, params.end, params.intermediates, params.ctx, params.leftSide, ctx, params.gpxRoute == null? null: params.gpxRoute.wpt, - params.mode); + params.mode, true); return res; } } catch (RuntimeException e) {