Fixed reverse gpx route

This commit is contained in:
max-klaus 2020-09-01 19:03:26 +03:00
parent 52d9961914
commit b094bd32c2
12 changed files with 221 additions and 52 deletions

View file

@ -404,7 +404,7 @@ public class RoutePlannerFrontEnd {
cleanupResultAndAddTurns(gctx);
}
public RouteSegmentResult generateStraightLineSegment(float averageSpeed, List<LatLon> points) {
public static RouteSegmentResult generateStraightLineSegment(float averageSpeed, List<LatLon> points) {
RouteRegion reg = new RouteRegion();
reg.initRouteEncodingRule(0, "highway", RouteResultPreparation.UNMATCHED_HIGHWAY_TYPE);
RouteDataObject rdo = new RouteDataObject(reg);

View file

@ -11,6 +11,7 @@
Thx - Hardy
-->
<string name="one_point_error">Please add at least two points.</string>
<string name="shared_string_is_saved">is saved</string>
<string name="open_saved_track">Open saved track</string>
<string name="all_previous_segments_will_be_recalc">All previous segments will be recalculated using selected profile.</string>

View file

@ -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<RouteSegmentResult> 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));

View file

@ -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<WptPt> 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

View file

@ -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()));

View file

@ -40,6 +40,7 @@ public abstract class MeasurementModeCommand implements Command {
REORDER_POINT,
SNAP_TO_ROAD,
CHANGE_ROUTE_MODE,
APPROXIMATE_POINTS
APPROXIMATE_POINTS,
REVERSE_POINTS
}
}

View file

@ -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<WptPt> oldPoints;
private List<WptPt> newPoints;
private Map<Pair<WptPt, WptPt>, 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;
}
}

View file

@ -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));

View file

@ -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);
}
}
}
}

View file

@ -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<Location> 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<LocalRoutingParameter> list = new ArrayList<LocalRoutingParameter>(getGpxRouterParameters(am));
GeneralRouter rm = app.getRouter(am);
if (rm == null || (rparams != null && !rparams.isCalculateOsmAndRoute()) && !rparams.getFile().hasRtePt()) {

View file

@ -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

View file

@ -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<Location> points = new ArrayList<Location>();
List<Location> points = new ArrayList<>();
List<RouteDirectionInfo> directions;
List<RouteSegmentResult> route;
List<WptPt> 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<RouteSegmentResult> gpxRouteResult = routeParams.gpxRoute.route;
if (gpxParams.reverse && gpxParams.routePoints.size() > 1) {
List<Location> gpxRouteLocations = new ArrayList<>();
List<RouteSegmentResult> 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<Location> locations = result.getRouteLocations();
List<RouteSegmentResult> 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,