From b094bd32c2b7d04bfba762ef1560616e4c05daea Mon Sep 17 00:00:00 2001 From: max-klaus Date: Tue, 1 Sep 2020 19:03:26 +0300 Subject: [PATCH] Fixed reverse gpx route --- .../osmand/router/RoutePlannerFrontEnd.java | 2 +- OsmAnd/res/values/strings.xml | 1 + .../MeasurementEditingContext.java | 3 +- .../MeasurementToolFragment.java | 18 ++++- .../OptionsBottomSheetDialogFragment.java | 6 +- .../command/MeasurementModeCommand.java | 3 +- .../command/ReversePointsCommand.java | 73 +++++++++++++++++++ .../FollowTrackFragment.java | 14 ++-- .../MapRouteInfoMenu.java | 26 ++++--- .../RoutingOptionsHelper.java | 51 ++++++++----- .../cards/ReverseTrackCard.java | 8 +- .../osmand/plus/routing/RouteProvider.java | 68 +++++++++++++++-- 12 files changed, 221 insertions(+), 52 deletions(-) create mode 100644 OsmAnd/src/net/osmand/plus/measurementtool/command/ReversePointsCommand.java diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java b/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java index 861c4cf009..f284a205aa 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java @@ -404,7 +404,7 @@ public class RoutePlannerFrontEnd { cleanupResultAndAddTurns(gctx); } - public RouteSegmentResult generateStraightLineSegment(float averageSpeed, List points) { + public static RouteSegmentResult generateStraightLineSegment(float averageSpeed, List points) { RouteRegion reg = new RouteRegion(); reg.initRouteEncodingRule(0, "highway", RouteResultPreparation.UNMATCHED_HIGHWAY_TYPE); RouteDataObject rdo = new RouteDataObject(reg); diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 48444fd8c4..2f45a54ce4 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,7 @@ Thx - Hardy --> + Please add at least two points. is saved Open saved track All previous segments will be recalculated using selected profile. diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java index 74bdbce787..88ee2848ae 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java @@ -598,7 +598,6 @@ public class MeasurementEditingContext { RouteRegion reg = new RouteRegion(); reg.initRouteEncodingRule(0, "highway", RouteResultPreparation.UNMATCHED_HIGHWAY_TYPE); - final RoutePlannerFrontEnd routePlannerFrontEnd = new RoutePlannerFrontEnd(); final RouteCalculationParams params = new RouteCalculationParams(); params.inSnapToRoadMode = true; @@ -658,7 +657,7 @@ public class MeasurementEditingContext { params.calculationProgressCallback.updateProgress(0); List originalRoute = route.getOriginalRoute(); if (Algorithms.isEmpty(originalRoute)) { - originalRoute = Collections.singletonList(routePlannerFrontEnd.generateStraightLineSegment( + originalRoute = Collections.singletonList(RoutePlannerFrontEnd.generateStraightLineSegment( DEFAULT_APP_MODE.getDefaultSpeed(), new LocationsHolder(pts).getLatLonList())); } roadSegmentData.put(currentPair, new RoadSegmentData(route.getAppMode(), currentPair.first, currentPair.second, pts, originalRoute)); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index 55286a0461..16b0550c7a 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -80,6 +80,7 @@ import net.osmand.plus.measurementtool.command.ClearPointsCommand; import net.osmand.plus.measurementtool.command.MovePointCommand; import net.osmand.plus.measurementtool.command.RemovePointCommand; import net.osmand.plus.measurementtool.command.ReorderPointCommand; +import net.osmand.plus.measurementtool.command.ReversePointsCommand; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback; @@ -760,7 +761,22 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void reverseRouteOnClick() { - + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + List points = editingCtx.getPoints(); + if (points.size() > 1) { + MeasurementToolLayer measurementLayer = getMeasurementLayer(); + editingCtx.getCommandManager().execute(new ReversePointsCommand(measurementLayer)); + if (pointsListOpened) { + hidePointsList(); + } + updateUndoRedoButton(false, redoBtn); + updateUndoRedoButton(true, undoBtn); + updateDistancePointsText(); + } else { + Toast.makeText(mapActivity, getString(R.string.one_point_error), Toast.LENGTH_SHORT).show(); + } + } } @Override diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/OptionsBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/OptionsBottomSheetDialogFragment.java index 5d2b23cdd4..93fecb7c33 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/OptionsBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/OptionsBottomSheetDialogFragment.java @@ -135,8 +135,8 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm .create(); items.add(directions); - /*BaseBottomSheetItem reverse = new SimpleBottomSheetItem.Builder() - .setIcon(getContentIcon(R.drawable.ic_action_reverse_direction)) + BaseBottomSheetItem reverse = new SimpleBottomSheetItem.Builder() + .setIcon(getContentIcon(R.drawable.ic_action_change_navigation_points)) .setTitle(getString(R.string.reverse_route)) .setLayoutId(R.layout.bottom_sheet_item_simple) .setOnClickListener(new View.OnClickListener() { @@ -150,7 +150,7 @@ public class OptionsBottomSheetDialogFragment extends MenuBottomSheetDialogFragm } }) .create(); - items.add(reverse);*/ + items.add(reverse); items.add(new OptionsDividerItem(getContext())); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementModeCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementModeCommand.java index 99230f61e5..92eb938233 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementModeCommand.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/MeasurementModeCommand.java @@ -40,6 +40,7 @@ public abstract class MeasurementModeCommand implements Command { REORDER_POINT, SNAP_TO_ROAD, CHANGE_ROUTE_MODE, - APPROXIMATE_POINTS + APPROXIMATE_POINTS, + REVERSE_POINTS } } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/command/ReversePointsCommand.java b/OsmAnd/src/net/osmand/plus/measurementtool/command/ReversePointsCommand.java new file mode 100644 index 0000000000..8d6c56d81f --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/measurementtool/command/ReversePointsCommand.java @@ -0,0 +1,73 @@ +package net.osmand.plus.measurementtool.command; + +import android.util.Pair; + +import net.osmand.GPXUtilities.WptPt; +import net.osmand.plus.measurementtool.MeasurementEditingContext; +import net.osmand.plus.measurementtool.MeasurementEditingContext.RoadSegmentData; +import net.osmand.plus.measurementtool.MeasurementToolLayer; +import net.osmand.plus.settings.backend.ApplicationMode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static net.osmand.plus.measurementtool.MeasurementEditingContext.DEFAULT_APP_MODE; + +public class ReversePointsCommand extends MeasurementModeCommand { + + private List oldPoints; + private List newPoints; + private Map, RoadSegmentData> oldRoadSegmentData; + private ApplicationMode oldMode; + + public ReversePointsCommand(MeasurementToolLayer measurementLayer) { + super(measurementLayer); + this.oldMode = getEditingCtx().getAppMode(); + } + + @Override + public boolean execute() { + MeasurementEditingContext editingCtx = getEditingCtx(); + oldPoints = new ArrayList<>(editingCtx.getPoints()); + oldRoadSegmentData = editingCtx.getRoadSegmentData(); + newPoints = new ArrayList<>(oldPoints); + Collections.reverse(newPoints); + executeCommand(); + return true; + } + + private void executeCommand() { + MeasurementEditingContext editingCtx = getEditingCtx(); + editingCtx.clearSnappedToRoadPoints(); + editingCtx.getPoints().clear(); + editingCtx.addPoints(newPoints); + if (!newPoints.isEmpty()) { + WptPt lastPoint = newPoints.get(newPoints.size() - 1); + editingCtx.setAppMode(ApplicationMode.valueOfStringKey(lastPoint.getProfileType(), DEFAULT_APP_MODE)); + } + editingCtx.updateCacheForSnap(); + } + + @Override + public void undo() { + MeasurementEditingContext editingCtx = getEditingCtx(); + editingCtx.getPoints().clear(); + editingCtx.addPoints(oldPoints); + editingCtx.setAppMode(oldMode); + editingCtx.setRoadSegmentData(oldRoadSegmentData); + editingCtx.updateCacheForSnap(); + + } + + @Override + public void redo() { + executeCommand(); + } + + @Override + MeasurementCommandType getType() { + return MeasurementCommandType.REVERSE_POINTS; + } +} diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java index eb613f234b..54747b068e 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java @@ -196,15 +196,11 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca GPXRouteParamsBuilder rparams = routingHelper.getCurrentGPXRoute(); boolean osmandRouter = mode.getRouteService() == RouteProvider.RouteService.OSMAND; if (rparams != null && osmandRouter) { -// if (!routingHelper.isCurrentGPXRouteV2()) { - int textId = R.string.gpx_option_reverse_route; - String title = app.getString(textId); - LocalRoutingParameter parameter = new OtherLocalRoutingParameter(textId, title, rparams.isReverse()); - - ReverseTrackCard reverseTrackCard = new ReverseTrackCard(mapActivity, parameter); - reverseTrackCard.setListener(this); - cardsContainer.addView(reverseTrackCard.build(mapActivity)); -// } + if (!gpxFile.hasRoute() || gpxFile.hasRtePt()) { + ReverseTrackCard reverseTrackCard = new ReverseTrackCard(mapActivity, rparams.isReverse()); + reverseTrackCard.setListener(this); + cardsContainer.addView(reverseTrackCard.build(mapActivity)); + } if (!gpxFile.hasRtePt()) { cardsContainer.addView(buildDividerView(cardsContainer, true)); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java index 00d5613cd7..d8388d4594 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java @@ -76,6 +76,7 @@ import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidRoadsRouti import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.LocalRoutingParameter; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.LocalRoutingParameterGroup; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.MuteSoundRoutingParameter; +import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.OtherLocalRoutingParameter; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.RouteMenuAppModes; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.ShowAlongTheRouteItem; import net.osmand.plus.routepreparationmenu.cards.BaseCard; @@ -1794,16 +1795,23 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener } else if (endPoint == null) { app.showShortToastMessage(R.string.mark_final_location_first); } else { - if (startPoint == null && loc != null) { - startPoint = TargetPoint.createStartPoint(new LatLon(loc.getLatitude(), loc.getLongitude()), - new PointDescription(PointDescription.POINT_TYPE_MY_LOCATION, mapActivity.getString(R.string.shared_string_my_location))); - } - if (startPoint != null) { - targetPointsHelper.navigateToPoint(startPoint.point, false, -1, startPoint.getPointDescription(mapActivity)); - targetPointsHelper.setStartPoint(endPoint.point, false, endPoint.getPointDescription(mapActivity)); - targetPointsHelper.updateRouteAndRefresh(true); + GPXRouteParamsBuilder gpxParams = app.getRoutingHelper().getCurrentGPXRoute(); + if (gpxParams != null) { + boolean reverse = !gpxParams.isReverse(); + LocalRoutingParameter parameter = new OtherLocalRoutingParameter(R.string.gpx_option_reverse_route, app.getString(R.string.gpx_option_reverse_route), reverse); + app.getRoutingOptionsHelper().applyRoutingParameter(parameter, reverse); } else { - app.showShortToastMessage(R.string.route_add_start_point); + if (startPoint == null && loc != null) { + startPoint = TargetPoint.createStartPoint(new LatLon(loc.getLatitude(), loc.getLongitude()), + new PointDescription(PointDescription.POINT_TYPE_MY_LOCATION, mapActivity.getString(R.string.shared_string_my_location))); + } + if (startPoint != null) { + targetPointsHelper.navigateToPoint(startPoint.point, false, -1, startPoint.getPointDescription(mapActivity)); + targetPointsHelper.setStartPoint(endPoint.point, false, endPoint.getPointDescription(mapActivity)); + targetPointsHelper.updateRouteAndRefresh(true); + } else { + app.showShortToastMessage(R.string.route_add_start_point); + } } } } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java index 546b600c7b..c2681b2f7b 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java @@ -17,15 +17,19 @@ import androidx.appcompat.widget.AppCompatCheckedTextView; import androidx.core.content.ContextCompat; import net.osmand.CallbackWithObject; +import net.osmand.GPXUtilities; +import net.osmand.GPXUtilities.WptPt; import net.osmand.IndexConstants; import net.osmand.Location; import net.osmand.data.LatLon; +import net.osmand.data.PointDescription; import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuItem; import net.osmand.plus.DialogListItemAdapter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.TargetPointsHelper; +import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.SettingsBaseActivity; @@ -50,6 +54,7 @@ import net.osmand.util.MapUtils; import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; @@ -231,7 +236,7 @@ public class RoutingOptionsHelper { } public void updateGpxRoutingParameter(OtherLocalRoutingParameter gpxParam) { - RouteProvider.GPXRouteParamsBuilder rp = app.getRoutingHelper().getCurrentGPXRoute(); + GPXRouteParamsBuilder rp = app.getRoutingHelper().getCurrentGPXRoute(); final OsmandSettings settings = app.getSettings(); boolean selected = gpxParam.isSelected(settings); if (rp != null) { @@ -240,23 +245,31 @@ public class RoutingOptionsHelper { TargetPointsHelper tg = app.getTargetPointsHelper(); List ps = rp.getPoints(app); if (ps.size() > 0) { - Location first = ps.get(0); - Location end = ps.get(ps.size() - 1); - TargetPointsHelper.TargetPoint pn = tg.getPointToNavigate(); - boolean update = false; - if (pn == null - || MapUtils.getDistance(pn.point, new LatLon(first.getLatitude(), first.getLongitude())) < 10) { - tg.navigateToPoint(new LatLon(end.getLatitude(), end.getLongitude()), false, -1); - update = true; - } - if (tg.getPointToStart() == null - || MapUtils.getDistance(tg.getPointToStart().point, - new LatLon(end.getLatitude(), end.getLongitude())) < 10) { - tg.setStartPoint(new LatLon(first.getLatitude(), first.getLongitude()), false, null); - update = true; - } - if (update) { + if (rp.getFile().hasRoute()) { + tg.clearStartPoint(false); + Location finishLoc = ps.get(ps.size() - 1); + TargetPoint pn = tg.getPointToNavigate(); + tg.navigateToPoint(new LatLon(finishLoc.getLatitude(), finishLoc.getLongitude()), false, -1, pn != null ? pn.getOriginalPointDescription() : null); tg.updateRouteAndRefresh(true); + } else { + Location first = ps.get(0); + Location end = ps.get(ps.size() - 1); + TargetPoint pn = tg.getPointToNavigate(); + boolean update = false; + if (pn == null + || MapUtils.getDistance(pn.point, new LatLon(first.getLatitude(), first.getLongitude())) < 10) { + tg.navigateToPoint(new LatLon(end.getLatitude(), end.getLongitude()), false, -1); + update = true; + } + if (tg.getPointToStart() == null + || MapUtils.getDistance(tg.getPointToStart().point, + new LatLon(end.getLatitude(), end.getLongitude())) < 10) { + tg.setStartPoint(new LatLon(first.getLatitude(), first.getLongitude()), false, null); + update = true; + } + if (update) { + tg.updateRouteAndRefresh(true); + } } } } else if (gpxParam.id == R.string.gpx_option_calculate_first_last_segment) { @@ -403,7 +416,7 @@ public class RoutingOptionsHelper { } public LocalRoutingParameter getRoutingParameterInnerById(ApplicationMode am, String parameterId) { - RouteProvider.GPXRouteParamsBuilder rparams = app.getRoutingHelper().getCurrentGPXRoute(); + GPXRouteParamsBuilder rparams = app.getRoutingHelper().getCurrentGPXRoute(); GeneralRouter rm = app.getRouter(am); if (rm == null || (rparams != null && !rparams.isCalculateOsmAndRoute()) && !rparams.getFile().hasRtePt()) { return null; @@ -484,7 +497,7 @@ public class RoutingOptionsHelper { return getOsmandRouterParameters(am); } - RouteProvider.GPXRouteParamsBuilder rparams = app.getRoutingHelper().getCurrentGPXRoute(); + GPXRouteParamsBuilder rparams = app.getRoutingHelper().getCurrentGPXRoute(); List list = new ArrayList(getGpxRouterParameters(am)); GeneralRouter rm = app.getRouter(am); if (rm == null || (rparams != null && !rparams.isCalculateOsmAndRoute()) && !rparams.getFile().hasRtePt()) { diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/ReverseTrackCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/ReverseTrackCard.java index dd6bd2d673..4817fe18e4 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/ReverseTrackCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/ReverseTrackCard.java @@ -10,15 +10,19 @@ import androidx.annotation.NonNull; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.LocalRoutingParameter; +import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.OtherLocalRoutingParameter; public class ReverseTrackCard extends BaseCard { private LocalRoutingParameter parameter; - public ReverseTrackCard(@NonNull MapActivity mapActivity, @NonNull LocalRoutingParameter parameter) { + public ReverseTrackCard(@NonNull MapActivity mapActivity, boolean isReverse) { super(mapActivity); - this.parameter = parameter; + int textId = R.string.gpx_option_reverse_route; + String title = app.getString(textId); + this.parameter = new OtherLocalRoutingParameter(textId, title, isReverse); } @Override diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java index a2743eba58..c1aa605955 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java @@ -34,6 +34,7 @@ import net.osmand.router.GeneralRouter; import net.osmand.router.GeneralRouter.RoutingParameter; import net.osmand.router.GeneralRouter.RoutingParameterType; import net.osmand.router.PrecalculatedRouteDirection; +import net.osmand.router.RouteCalculationProgress; import net.osmand.router.RouteExporter; import net.osmand.router.RouteImporter; import net.osmand.router.RoutePlannerFrontEnd; @@ -62,6 +63,7 @@ import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URLConnection; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; @@ -229,9 +231,11 @@ public class RouteProvider { } public static class GPXRouteParams { - List points = new ArrayList(); + List points = new ArrayList<>(); List directions; List route; + List routePoints = new ArrayList<>(); + boolean reverse; boolean calculateOsmAndRoute; boolean passWholeRoute; boolean calculateOsmAndRouteParts; @@ -269,7 +273,7 @@ public class RouteProvider { public GPXRouteParams prepareGPXFile(GPXRouteParamsBuilder builder) { GPXFile file = builder.file; - boolean reverse = builder.reverse; + reverse = builder.reverse; passWholeRoute = builder.passWholeRoute; calculateOsmAndRouteParts = builder.calculateOsmAndRouteParts; useIntermediatePointsRTE = builder.isUseIntermediatePointsRTE(); @@ -282,7 +286,12 @@ public class RouteProvider { } if (OSMAND_ROUTER_V2.equals(file.author)) { route = parseOsmAndGPXRoute(points, file); - addMissingTurns = route.isEmpty(); + routePoints = file.getRoutePoints(); + if (reverse) { + Collections.reverse(points); + Collections.reverse(routePoints); + } + addMissingTurns = route != null && route.isEmpty(); } else 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) && file.hasRtePt()) { @@ -347,7 +356,8 @@ public class RouteProvider { } try { RouteCalculationResult res; - boolean calcGPXRoute = params.gpxRoute != null && !params.gpxRoute.points.isEmpty(); + boolean calcGPXRoute = params.gpxRoute != null && (!params.gpxRoute.points.isEmpty() + || (params.gpxRoute.reverse && !params.gpxRoute.routePoints.isEmpty())); if (calcGPXRoute && !params.gpxRoute.calculateOsmAndRoute) { res = calculateGpxRoute(params); } else if (params.mode.getRouteService() == RouteService.OSMAND) { @@ -396,11 +406,59 @@ public class RouteProvider { } private RouteCalculationResult calculateGpxRoute(RouteCalculationParams routeParams) throws IOException { - // get the closest point to start and to end GPXRouteParams gpxParams = routeParams.gpxRoute; boolean calcWholeRoute = routeParams.gpxRoute.passWholeRoute && (routeParams.previousToRecalculate == null || !routeParams.onlyStartPointChanged); boolean calculateOsmAndRouteParts = gpxParams.calculateOsmAndRouteParts; List gpxRouteResult = routeParams.gpxRoute.route; + if (gpxParams.reverse && gpxParams.routePoints.size() > 1) { + List gpxRouteLocations = new ArrayList<>(); + List gpxRoute = new ArrayList<>(); + Location start = null; + for (int i = 0; i < gpxParams.routePoints.size(); i++) { + WptPt pt = gpxParams.routePoints.get(i); + ApplicationMode appMode = ApplicationMode.valueOfStringKey(pt.getProfileType(), ApplicationMode.DEFAULT); + LatLon end = new LatLon(pt.getLatitude(), pt.getLongitude()); + if (start == null) { + start = new Location(""); + start.setLatitude(routeParams.start.getLatitude()); + start.setLongitude(routeParams.start.getLongitude()); + } + + RouteCalculationParams params = new RouteCalculationParams(); + params.inSnapToRoadMode = true; + params.start = start; + params.end = end; + RoutingHelper.applyApplicationSettings(params, routeParams.ctx.getSettings(), appMode); + params.mode = appMode; + params.ctx = routeParams.ctx; + params.calculationProgress = routeParams.calculationProgress; + RouteCalculationResult result = findOfflineRouteSegment(params, start, end); + List locations = result.getRouteLocations(); + List route = result.getOriginalRoute(); + if (Algorithms.isEmpty(route)) { + if (Algorithms.isEmpty(locations)) { + Location endLoc = new Location(""); + endLoc.setLatitude(end.getLatitude()); + endLoc.setLongitude(end.getLongitude()); + locations = Arrays.asList(start, endLoc); + } + route = Collections.singletonList(RoutePlannerFrontEnd.generateStraightLineSegment( + routeParams.mode.getDefaultSpeed(), new LocationsHolder(locations).getLatLonList())); + } + gpxRouteLocations.addAll(locations); + if (i > 0 && !gpxRouteLocations.isEmpty()) { + gpxRouteLocations.remove(gpxRouteLocations.size() - 1); + } + gpxRoute.addAll(route); + + start = new Location(""); + start.setLatitude(end.getLatitude()); + start.setLongitude(end.getLongitude()); + } + gpxParams.points = gpxRouteLocations; + gpxParams.route = gpxRoute; + gpxRouteResult = gpxRoute; + } if (!Algorithms.isEmpty(gpxRouteResult)) { if (calcWholeRoute && !calculateOsmAndRouteParts) { return new RouteCalculationResult(gpxRouteResult, routeParams.start, routeParams.end,