diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java index a174c1550c..7b7bd7d8d9 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java @@ -290,12 +290,16 @@ public class RouteCalculationResult { } public List getOriginalRoute(int startIndex) { + return getOriginalRoute(startIndex, segments.size()); + } + + public List getOriginalRoute(int startIndex, int endIndex) { if (segments.size() == 0) { return null; } - List list = new ArrayList(); + List list = new ArrayList<>(); list.add(segments.get(startIndex++)); - for (int i = startIndex; i < segments.size(); i++) { + for (int i = startIndex; i < endIndex; i++) { if (segments.get(i - 1) != segments.get(i)) { list.add(segments.get(i)); } diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java index 99cfb9f0ef..f717f6fe7b 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java @@ -153,8 +153,9 @@ public class RouteProvider { GPXRouteParams gpxParams = routeParams.gpxRoute; boolean calcWholeRoute = routeParams.gpxRoute.passWholeRoute && (routeParams.previousToRecalculate == null || !routeParams.onlyStartPointChanged); boolean calculateOsmAndRouteParts = gpxParams.calculateOsmAndRouteParts; + boolean reverseRoutePoints = gpxParams.reverse && gpxParams.routePoints.size() > 1; List gpxRouteResult = routeParams.gpxRoute.route; - if (gpxParams.reverse && gpxParams.routePoints.size() > 1) { + if (reverseRoutePoints) { List gpxRouteLocations = new ArrayList<>(); List gpxRoute = new ArrayList<>(); WptPt firstGpxPoint = gpxParams.routePoints.get(0); @@ -214,18 +215,27 @@ public class RouteProvider { List firstSegmentRoute = null; List lastSegmentRoute = null; List gpxRoute; - if (nearestGpxPointInd > 0) { - nearestGpxLocation = gpxRouteLocations.get(nearestGpxPointInd); - gpxRoute = result.getOriginalRoute(nearestGpxPointInd); - if (gpxRoute.size() > 0) { - gpxRoute.remove(0); + + if (calculateOsmAndRouteParts && !reverseRoutePoints && !Algorithms.isEmpty(gpxParams.segmentEndpoints)) { + if (nearestGpxPointInd > 0) { + nearestGpxLocation = gpxRouteLocations.get(nearestGpxPointInd); } + gpxRoute = findRouteWithIntermediateSegments(routeParams, result, gpxRouteLocations, gpxParams.segmentEndpoints, nearestGpxPointInd); } else { - if (!gpxRouteLocations.isEmpty()) { - nearestGpxLocation = gpxRouteLocations.get(0); + if (nearestGpxPointInd > 0) { + nearestGpxLocation = gpxRouteLocations.get(nearestGpxPointInd); + gpxRoute = result.getOriginalRoute(nearestGpxPointInd); + if (gpxRoute.size() > 0) { + gpxRoute.remove(0); + } + } else { + if (!gpxRouteLocations.isEmpty()) { + nearestGpxLocation = gpxRouteLocations.get(0); + } + gpxRoute = result.getOriginalRoute(); } - gpxRoute = result.getOriginalRoute(); } + if (calculateOsmAndRouteParts && routeParams.start != null && nearestGpxLocation != null && nearestGpxLocation.distanceTo(routeParams.start) > MIN_DISTANCE_FOR_INSERTING_ROUTE_SEGMENT) { @@ -267,7 +277,7 @@ public class RouteProvider { } final List inputDirections = gpxParams.directions; List gpxDirections = calcDirections(startI, endI, inputDirections); - insertSegments(routeParams, gpxRoute, gpxDirections, gpxParams.segmentEndpoints, calculateOsmAndRouteParts); + insertIntermediateSegments(routeParams, gpxRoute, gpxDirections, gpxParams.segmentEndpoints, calculateOsmAndRouteParts); insertInitialSegment(routeParams, gpxRoute, gpxDirections, calculateOsmAndRouteParts); insertFinalSegment(routeParams, gpxRoute, gpxDirections, calculateOsmAndRouteParts); @@ -281,31 +291,6 @@ public class RouteProvider { gpxParams.wpt, routeParams.gpxRoute.addMissingTurns); } - public void insertSegments(RouteCalculationParams routeParams, List points, List directions, - List segmentEndpoints, boolean calculateOsmAndRouteParts) { - for (int i = 0; i < segmentEndpoints.size() - 1; i++) { - Location prevSegmentPoint = segmentEndpoints.get(i); - Location newSegmentPoint = segmentEndpoints.get(i + 1); - - int index = points.indexOf(newSegmentPoint); - if (calculateOsmAndRouteParts && index != -1 && points.contains(prevSegmentPoint)) { - LatLon end = new LatLon(newSegmentPoint.getLatitude(), newSegmentPoint.getLongitude()); - RouteCalculationResult newRes = findOfflineRouteSegment(routeParams, prevSegmentPoint, end); - - if (newRes != null && newRes.isCalculated()) { - List loct = newRes.getImmutableAllLocations(); - List dt = newRes.getImmutableAllDirections(); - - for (RouteDirectionInfo directionInfo : dt) { - directionInfo.routePointOffset += points.size(); - } - points.addAll(index, loct); - directions.addAll(dt); - } - } - } - } - private RouteCalculationResult calculateOsmAndRouteWithIntermediatePoints(RouteCalculationParams routeParams, final List intermediates) throws IOException { RouteCalculationParams rp = new RouteCalculationParams(); @@ -442,6 +427,62 @@ public class RouteProvider { } } + public void insertIntermediateSegments(RouteCalculationParams routeParams, List points, List directions, + List segmentEndpoints, boolean calculateOsmAndRouteParts) { + for (int i = 0; i < segmentEndpoints.size() - 1; i++) { + Location prevSegmentPoint = segmentEndpoints.get(i); + Location newSegmentPoint = segmentEndpoints.get(i + 1); + + int index = points.indexOf(newSegmentPoint); + if (calculateOsmAndRouteParts && index != -1 && points.contains(prevSegmentPoint)) { + LatLon end = new LatLon(newSegmentPoint.getLatitude(), newSegmentPoint.getLongitude()); + RouteCalculationResult newRes = findOfflineRouteSegment(routeParams, prevSegmentPoint, end); + + if (newRes != null && newRes.isCalculated()) { + List loct = newRes.getImmutableAllLocations(); + List dt = newRes.getImmutableAllDirections(); + + for (RouteDirectionInfo directionInfo : dt) { + directionInfo.routePointOffset += points.size(); + } + points.addAll(index, loct); + directions.addAll(dt); + } + } + } + } + + public List findRouteWithIntermediateSegments(RouteCalculationParams routeParams, + RouteCalculationResult result, + List gpxRouteLocations, + List segmentEndpoints, + int nearestGpxPointInd) { + List newGpxRoute = new ArrayList<>(); + + int lastIndex = nearestGpxPointInd; + for (int i = 0; i < segmentEndpoints.size() - 1; i++) { + Location prevSegmentPoint = segmentEndpoints.get(i); + Location newSegmentPoint = segmentEndpoints.get(i + 1); + + int indexNew = findNearestGpxPointIndexFromRoute(gpxRouteLocations, newSegmentPoint, routeParams.gpxRoute.calculateOsmAndRouteParts); + int indexPrev = findNearestGpxPointIndexFromRoute(gpxRouteLocations, prevSegmentPoint, routeParams.gpxRoute.calculateOsmAndRouteParts); + if (indexPrev != -1 && indexPrev > nearestGpxPointInd && indexNew != -1) { + newGpxRoute.addAll(result.getOriginalRoute(lastIndex, indexPrev)); + lastIndex = indexNew; + + LatLon end = new LatLon(newSegmentPoint.getLatitude(), newSegmentPoint.getLongitude()); + RouteCalculationResult newRes = findOfflineRouteSegment(routeParams, prevSegmentPoint, end); + List segmentResults = newRes.getOriginalRoute(); + if (!Algorithms.isEmpty(segmentResults)) { + newGpxRoute.addAll(segmentResults); + } + } + } + newGpxRoute.addAll(result.getOriginalRoute(lastIndex)); + + return newGpxRoute; + } + private RouteCalculationResult findOfflineRouteSegment(RouteCalculationParams rParams, Location start, LatLon end) { RouteCalculationParams newParams = new RouteCalculationParams();