Merge branch 'straight_to'

Conflicts:
	OsmAnd/res/values/strings.xml
	OsmAnd/src/net/osmand/plus/settings/RouteParametersFragment.java
This commit is contained in:
Victor Shcherb 2020-02-17 20:14:45 +01:00
commit b3466bcf69
15 changed files with 320 additions and 167 deletions

View file

@ -67,6 +67,12 @@ public class Location {
mProvider = provider;
}
public Location(String provider, double lat, double lon) {
mProvider = provider;
setLatitude(lat);
setLongitude(lon);
}
/**
* Constructs a new Location object that is a copy of the given
* location.

View file

@ -57,7 +57,23 @@ public class MapUtils {
// Scalar multiplication between (AB, AC)
return (xB - xA) * (xC - xA) + (yB - yA) * (yC - yA);
}
public static Location calculateMidPoint(Location s1, Location s2) {
double lat1 = s1.getLatitude() / 180 * Math.PI;
double lon1 = s1.getLongitude() / 180 * Math.PI;
double lat2 = s2.getLatitude() / 180 * Math.PI;
double lon2 = s2.getLongitude() / 180 * Math.PI;
double Bx = Math.cos(lat2) * Math.cos(lon2 - lon1);
double By = Math.cos(lat2) * Math.sin(lon2 - lon1);
double latMid = Math.atan2(Math.sin(lat1) + Math.sin(lat2),
Math.sqrt((Math.cos(lat1) + Bx) * (Math.cos(lat1) + Bx) + By * By));
double lonMid = lon1 + Math.atan2(By, Math.cos(lat1) + Bx);
Location r = new Location("");
r.setLatitude(MapUtils.checkLatitude(latMid * 180 / Math.PI));
r.setLongitude(MapUtils.checkLongitude(lonMid * 180 / Math.PI));
return r;
}
public static LatLon calculateMidPoint(LatLon s1, LatLon s2) {
double lat1 = s1.getLatitude() / 180 * Math.PI;
double lon1 = s1.getLongitude() / 180 * Math.PI;

View file

@ -13,12 +13,16 @@
-->
<string name="navigation_notification_desc">Show system notification while navigation with navigation instructions.</string>
<string name="navigation_notification">Navigation notification</string>
<string name="shared_string_app_default_w_val">App Default (%s)</string>
<string name="please_provide_profile_name_message">Please provide a name for the profile</string>
<string name="no_recalculation_setting">Disable recalculation</string>
<string name="open_settings">Open settings</string>
<string name="plugin_disabled">Plugin disabled</string>
<string name="plugin_disabled_descr">This plugin is a separate application, you will need to remove it separately if you no longer plan to use it.\n\nThe plugin will remain on the device after removing OsmAnd.</string>
<string name="shared_string_menu">Menu</string>
<string name="ltr_or_rtl_triple_combine_via_dash">%1$s — %2$s — %3$s</string>
<string name="route_recalculation_dist_title">Minimal distance to recalculate route</string>
<string name="route_recalculation_dist_descr">The route will be recalculated if the distance to the route is longer than specified parameter</string>
<string name="routing_profile_direct_to">Direct-to-point</string>
<string name="clear_recorded_data">Clear recorded data</string>
<string name="release_3_6">

View file

@ -33,8 +33,6 @@ public class AccessibilityPlugin extends OsmandPlugin {
pluginPreferences.add(settings.SPEECH_RATE);
pluginPreferences.add(settings.ACCESSIBILITY_SMART_AUTOANNOUNCE);
pluginPreferences.add(settings.ACCESSIBILITY_AUTOANNOUNCE_PERIOD);
pluginPreferences.add(settings.DISABLE_OFFROUTE_RECALC);
pluginPreferences.add(settings.DISABLE_WRONG_DIRECTION_RECALC);
pluginPreferences.add(settings.DIRECTION_STYLE);
pluginPreferences.add(settings.DIRECTION_AUDIO_FEEDBACK);
pluginPreferences.add(settings.DIRECTION_HAPTIC_FEEDBACK);

View file

@ -64,9 +64,6 @@ public class AccessibilitySettingsFragment extends BaseSettingsFragment implemen
setupSmartAutoAnnouncePref();
setupAutoAnnouncePeriodPref();
setupDisableOffRouteRecalculationPref();
setupDisableWrongDirectionRecalculationPref();
setupDirectionStylePref();
setupDirectionAudioFeedbackPref();
setupDirectionHapticFeedbackPref();
@ -175,15 +172,6 @@ public class AccessibilitySettingsFragment extends BaseSettingsFragment implemen
autoAnnouncePeriod.setDescription(R.string.access_autoannounce_period_descr);
}
private void setupDisableOffRouteRecalculationPref() {
SwitchPreferenceEx disableOffRouteRecalculation = (SwitchPreferenceEx) findPreference(settings.DISABLE_OFFROUTE_RECALC.getId());
disableOffRouteRecalculation.setDescription(getString(R.string.access_disable_offroute_recalc_descr));
}
private void setupDisableWrongDirectionRecalculationPref() {
SwitchPreferenceEx disableWrongDirectionRecalculation = (SwitchPreferenceEx) findPreference(settings.DISABLE_WRONG_DIRECTION_RECALC.getId());
disableWrongDirectionRecalculation.setDescription(getString(R.string.access_disable_wrong_direction_recalc_descr));
}
private void setupDirectionStylePref() {
RelativeDirectionStyle[] relativeDirectionStyles = RelativeDirectionStyle.values();

View file

@ -90,12 +90,6 @@ public class SettingsAccessibilityActivity extends SettingsBaseActivity {
}
});
cat.addPreference(autoannouncePeriodPreference);
cat.addPreference(createCheckBoxPreference(settings.DISABLE_OFFROUTE_RECALC, R.string.access_disable_offroute_recalc,
R.string.access_disable_offroute_recalc_descr));
cat.addPreference(createCheckBoxPreference(settings.DISABLE_WRONG_DIRECTION_RECALC, R.string.access_disable_wrong_direction_recalc,
R.string.access_disable_wrong_direction_recalc_descr));
cat.addPreference(createCheckBoxPreference(settings.DIRECTION_AUDIO_FEEDBACK, R.string.access_direction_audio_feedback,
R.string.access_direction_audio_feedback_descr));
cat.addPreference(createCheckBoxPreference(settings.DIRECTION_HAPTIC_FEEDBACK, R.string.access_direction_haptic_feedback,

View file

@ -1465,7 +1465,7 @@ public class OsmandSettings {
@Override
public SpeedConstants getProfileDefaultValue(ApplicationMode mode) {
MetricsConstants mc = METRIC_SYSTEM.get();
MetricsConstants mc = METRIC_SYSTEM.getModeValue(mode);
if (mode.isDerivedRoutingFrom(ApplicationMode.PEDESTRIAN)) {
if (mc == MetricsConstants.KILOMETERS_AND_METERS) {
return SpeedConstants.MINUTES_PER_KILOMETER;
@ -1606,8 +1606,8 @@ public class OsmandSettings {
new BooleanAccessibilityPreference("disable_offroute_recalc", false).makeProfile();
// this value string is synchronized with settings_pref.xml preference name
public final OsmandPreference<Boolean> DISABLE_WRONG_DIRECTION_RECALC =
new BooleanAccessibilityPreference("disable_wrong_direction_recalc", false).makeProfile();
// public final OsmandPreference<Boolean> DISABLE_WRONG_DIRECTION_RECALC =
// new BooleanAccessibilityPreference("disable_wrong_direction_recalc", false).makeProfile();
// this value string is synchronized with settings_pref.xml preference name
public final OsmandPreference<Boolean> DIRECTION_AUDIO_FEEDBACK =
@ -3284,6 +3284,9 @@ public class OsmandSettings {
return customBooleanRoutingProps.get(attrName);
}
public final CommonPreference<Float> ROUTE_RECALCULATION_DISTANCE = new FloatPreference("routing_recalc_distance", 0.f).makeProfile();
public final CommonPreference<Float> ROUTE_STRAIGHT_ANGLE = new FloatPreference("routing_straight_angle", 30.f).makeProfile();
public final OsmandPreference<Boolean> USE_OSM_LIVE_FOR_ROUTING = new BooleanPreference("enable_osmc_routing", true).makeGlobal();
public final OsmandPreference<Boolean> USE_OSM_LIVE_FOR_PUBLIC_TRANSPORT = new BooleanPreference("enable_osmc_public_transport", false).makeGlobal();

View file

@ -353,7 +353,6 @@ public class MeasurementEditingContext {
}
}
};
return params;
}

View file

@ -17,9 +17,9 @@ public class RouteCalculationParams {
public Location start;
public LatLon end;
public List<LatLon> intermediates;
public Location currentLocation;
public OsmandApplication ctx;
public RoutingContext cachedRoutingContext;
public ApplicationMode mode;
public GPXRouteParams gpxRoute;
public RouteCalculationResult previousToRecalculate;
@ -34,8 +34,6 @@ public class RouteCalculationParams {
public RouteCalculationProgressCallback calculationProgressCallback;
public RouteCalculationResultListener resultListener;
public boolean showOriginalRoute;
public interface RouteCalculationResultListener {
void onRouteCalculated(RouteCalculationResult route);
}

View file

@ -2,6 +2,7 @@ package net.osmand.plus.routing;
import android.content.Context;
import android.support.annotation.Nullable;
import android.system.Os;
import net.osmand.Location;
import net.osmand.PlatformUtil;
@ -55,6 +56,12 @@ public class RouteCalculationResult {
protected List<RouteDirectionInfo> cacheAgreggatedDirections;
protected List<LocationPoint> locationPoints = new ArrayList<LocationPoint>();
// params
protected final ApplicationMode appMode;
protected final RouteProvider.RouteService routeService;
protected final double routeRecalcDistance;
protected final double routeVisibleAngle;
// Note always currentRoute > get(currentDirectionInfo).routeOffset,
// but currentRoute <= get(currentDirectionInfo+1).routeOffset
protected int currentDirectionInfo = 0;
@ -62,9 +69,9 @@ public class RouteCalculationResult {
protected int nextIntermediate = 0;
protected int currentWaypointGPX = 0;
protected int lastWaypointGPX = 0;
protected ApplicationMode appMode;
protected int currentStraightAngleRoute = -1;
protected Location currentStraightAnglePoint = null;
protected boolean showOriginalRoute = false;
public RouteCalculationResult(String errorMessage) {
this.errorMessage = errorMessage;
@ -78,6 +85,10 @@ public class RouteCalculationResult {
this.listDistance = new int[0];
this.directions = new ArrayList<RouteDirectionInfo>();
this.alarmInfo = new ArrayList<AlarmInfo>();
this.routeService = null;
this.appMode = null;
this.routeRecalcDistance = 0;
this.routeVisibleAngle = 0;
}
public RouteCalculationResult(List<Location> list, List<RouteDirectionInfo> directions, RouteCalculationParams params, List<LocationPoint> waypoints, boolean addMissingTurns) {
@ -111,8 +122,15 @@ public class RouteCalculationResult {
calculateIntermediateIndexes(params.ctx, this.locations, params.intermediates, localDirections, this.intermediatePoints);
this.directions = Collections.unmodifiableList(localDirections);
updateDirectionsTime(this.directions, this.listDistance);
this.showOriginalRoute = params.showOriginalRoute;
this.routeService = params.mode.getRouteService();
if(params.ctx != null) {
this.routeRecalcDistance = params.ctx.getSettings().ROUTE_RECALCULATION_DISTANCE.getModeValue(params.mode);
this.routeVisibleAngle = routeService == RouteProvider.RouteService.STRAIGHT ?
params.ctx.getSettings().ROUTE_STRAIGHT_ANGLE.getModeValue(params.mode) : 0;
} else {
this.routeRecalcDistance = 0;
this.routeVisibleAngle = 0;
}
}
public RouteCalculationResult(List<RouteSegmentResult> list, Location start, LatLon end, List<LatLon> intermediates,
@ -138,10 +156,14 @@ public class RouteCalculationResult {
calculateIntermediateIndexes(ctx, this.locations, intermediates, computeDirections, this.intermediatePoints);
updateListDistanceTime(this.listDistance, this.locations);
this.appMode = mode;
this.routeService = mode.getRouteService();
this.directions = Collections.unmodifiableList(computeDirections);
updateDirectionsTime(this.directions, this.listDistance);
this.alarmInfo = Collections.unmodifiableList(alarms);
this.routeRecalcDistance = ctx.getSettings().ROUTE_RECALCULATION_DISTANCE.getModeValue(mode);
this.routeVisibleAngle = routeService == RouteProvider.RouteService.STRAIGHT ?
ctx.getSettings().ROUTE_STRAIGHT_ANGLE.getModeValue(mode) : 0;
}
public ApplicationMode getAppMode() {
@ -233,6 +255,18 @@ public class RouteCalculationResult {
}
}
public double getRouteRecalcDistance() {
return routeRecalcDistance;
}
public RouteProvider.RouteService getRouteService() {
return routeService;
}
public double getRouteVisibleAngle() {
return routeVisibleAngle;
}
public List<RouteSegmentResult> getOriginalRoute() {
if (segments.size() == 0) {
return null;
@ -1026,7 +1060,7 @@ public class RouteCalculationResult {
info.directionInfoInd = -1;
info.distanceTo = -1;
info.directionInfo = null;
return null;
return info;
}
/*public */NextDirectionInfo getNextRouteDirectionInfoAfter(NextDirectionInfo prev, NextDirectionInfo next, boolean toSpeak) {
@ -1201,7 +1235,20 @@ public class RouteCalculationResult {
private int getListDistance(int index) {
return listDistance.length > index ? listDistance[index] : 0;
}
public int getCurrentStraightAngleRoute() {
return currentStraightAngleRoute > currentRoute ? currentStraightAngleRoute : currentRoute;
}
public Location getCurrentStraightAnglePoint() {
return currentStraightAnglePoint;
}
public void updateNextVisiblePoint(int nextPoint, Location mp) {
currentStraightAngleRoute = nextPoint;
currentStraightAnglePoint = mp;
}
public static class NextDirectionInfo {
public RouteDirectionInfo directionInfo;
public int distanceTo;
@ -1211,7 +1258,4 @@ public class RouteCalculationResult {
private int directionInfoInd;
}
public boolean isShowOriginalRoute() {
return showOriginalRoute;
}
}

View file

@ -9,9 +9,12 @@ import android.util.Base64;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.DataTileManager;
import net.osmand.data.LatLon;
import net.osmand.data.LocationPoint;
import net.osmand.data.WptLocationPoint;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.Way;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.ApplicationMode;
import net.osmand.GPXUtilities;
@ -59,6 +62,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -74,6 +78,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 MIN_STRAIGHT_DIST = 50000;
public enum RouteService {
OSMAND("OsmAnd (offline)"),
@ -317,10 +322,9 @@ public class RouteProvider {
// res = findORSRoute(params);
// } else if (params.type == RouteService.OSRM) {
// res = findOSRMRoute(params);
} else if (params.mode.getRouteService() == RouteService.STRAIGHT) {
} else if (params.mode.getRouteService() == RouteService.STRAIGHT ||
params.mode.getRouteService() == RouteService.DIRECT_TO) {
res = findStraightRoute(params);
} else if (params.mode.getRouteService() == RouteService.DIRECT_TO) {
res = findDirectTo(params);
} else {
res = new RouteCalculationResult("Selected route service is not available");
}
@ -1236,55 +1240,30 @@ public class RouteProvider {
}
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);
Location currentLocation = params.currentLocation;
LinkedList<Location> points = new LinkedList<>();
List<Location> segments = new ArrayList<>();
points.add(params.start);
if(params.intermediates != null) {
for (LatLon l : params.intermediates) {
points.add(new Location("", l.getLatitude(), l.getLongitude()));
}
}
//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);
points.add(new Location("", params.end.getLatitude(), params.end.getLongitude()));
Location lastAdded = points.poll();
segments.add(lastAdded);
while(!points.isEmpty()) {
Location pl = points.peek();
if (lastAdded.distanceTo(pl) < MIN_STRAIGHT_DIST) {
lastAdded = points.poll();
segments.add(lastAdded);
} else {
Location mp = MapUtils.calculateMidPoint(lastAdded, pl);
points.add(0, mp);
}
}
return new RouteCalculationResult(segments, null, params, null, false);
}
private RouteCalculationResult findDirectTo(RouteCalculationParams params) {
params.showOriginalRoute = true;
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);
}
}

View file

@ -42,6 +42,7 @@ public class RoutingHelper {
private static final float POSITION_TOLERANCE = 60;
private static final int CACHE_RADIUS = 100000;
public static final float ALLOWED_DEVIATION = 2;
private List<WeakReference<IRouteInformationListener>> listeners = new LinkedList<>();
private List<WeakReference<IRoutingDataUpdateListener>> updateListeners = new LinkedList<>();
@ -60,7 +61,6 @@ public class RoutingHelper {
private List<LatLon> intermediatePoints;
private Location lastProjection;
private Location lastFixedLocation;
private Location originalStartingLocation;
private RouteCalculationResult originalRoute = null;
@ -179,7 +179,6 @@ public class RoutingHelper {
}
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List<LatLon> intermediatePoints, Location currentLocation){
setOriginalStartLocation(currentLocation);
checkAndUpdateStartLocation(currentLocation);
RouteCalculationResult previousRoute = route;
clearCurrentRoute(finalLocation, intermediatePoints);
@ -187,25 +186,6 @@ public class RoutingHelper {
setCurrentLocation(currentLocation, false, previousRoute, true);
}
public RouteCalculationResult getOriginalRoute() {
return originalRoute;
}
public List<Location> getOriginalRouteAllLoc() {
return originalRoute.getImmutableAllLocations();
}
public void setOriginalRoute(RouteCalculationResult originalRoute) {
this.originalRoute = originalRoute;
}
private void setOriginalStartLocation(Location currentLocation) {
originalStartingLocation = currentLocation;
}
public Location getOriginalStartingLocation() {
return originalStartingLocation;
}
public synchronized void clearCurrentRoute(LatLon newFinalLocation, List<LatLon> newIntermediatePoints) {
route = new RouteCalculationResult("");
isDeviatedFromRoute = false;
@ -319,6 +299,9 @@ public class RoutingHelper {
return lastProjection;
}
public Location getLastFixedLocation() {
return lastFixedLocation;
}
public void addRouteDataListener(IRoutingDataUpdateListener listener) {
updateListeners = updateListenersList(new ArrayList<>(updateListeners), listener, true);
@ -398,6 +381,31 @@ public class RoutingHelper {
return getOrthogonalDistance(lastFixedLocation, routeNodes.get(route.currentRoute -1), routeNodes.get(route.currentRoute));
}
public static float getDefaultAllowedDeviation(OsmandSettings settings, ApplicationMode mode, float posTolerance) {
if (settings.DISABLE_OFFROUTE_RECALC.getModeValue(mode)) {
return -1.0f;
} else if (mode.getRouteService() == RouteService.DIRECT_TO) {
return -1.0f;
} else if (mode.getRouteService() == RouteService.STRAIGHT) {
OsmandSettings.MetricsConstants mc = settings.METRIC_SYSTEM.getModeValue(mode);
if (mc == OsmandSettings.MetricsConstants.KILOMETERS_AND_METERS || mc == OsmandSettings.MetricsConstants.MILES_AND_METERS) {
return 500.f;
} else {
// 1/4 mile
return 482.f;
}
}
return posTolerance * ALLOWED_DEVIATION;
}
public static float getPosTolerance(float accuracy) {
if(accuracy > 0) {
return POSITION_TOLERANCE / 2 + accuracy;
}
return POSITION_TOLERANCE;
}
private Location setCurrentLocation(Location currentLocation, boolean returnUpdatedLocation,
RouteCalculationResult previousRoute, boolean targetPointsChanged) {
Location locationProjection = currentLocation;
@ -413,10 +421,7 @@ public class RoutingHelper {
isDeviatedFromRoute = false;
return locationProjection;
}
float posTolerance = POSITION_TOLERANCE;
if(currentLocation.hasAccuracy()) {
posTolerance = POSITION_TOLERANCE / 2 + currentLocation.getAccuracy();
}
float posTolerance = getPosTolerance(currentLocation.hasAccuracy() ? currentLocation.getAccuracy() : 0);
boolean calculateRoute = false;
synchronized (this) {
isDeviatedFromRoute = false;
@ -434,12 +439,16 @@ public class RoutingHelper {
}
List<Location> routeNodes = route.getImmutableAllLocations();
int currentRoute = route.currentRoute;
double allowableDeviation = route.getRouteRecalcDistance();
if (allowableDeviation == 0) {
allowableDeviation = getDefaultAllowedDeviation(settings, route.getAppMode(), posTolerance);
}
// 2. Analyze if we need to recalculate route
// >100m off current route (sideways)
if (currentRoute > 0) {
// >100m off current route (sideways) or parameter (for Straight line)
if (currentRoute > 0 && allowableDeviation > 0) {
distOrth = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute));
if ((!settings.DISABLE_OFFROUTE_RECALC.get()) && (distOrth > (1.7 * posTolerance))) {
if (distOrth > allowableDeviation) {
log.info("Recalculate route, because correlation : " + distOrth); //$NON-NLS-1$
isDeviatedFromRoute = true;
calculateRoute = true;
@ -447,8 +456,11 @@ public class RoutingHelper {
}
// 3. Identify wrong movement direction
Location next = route.getNextRouteLocation();
boolean isStraight =
route.getRouteService() == RouteService.DIRECT_TO || route.getRouteService() == RouteService.STRAIGHT;
boolean wrongMovementDirection = checkWrongMovementDirection(currentLocation, next);
if ((!settings.DISABLE_WRONG_DIRECTION_RECALC.get()) && wrongMovementDirection && (currentLocation.distanceTo(routeNodes.get(currentRoute)) > (2 * posTolerance))) {
if (allowableDeviation > 0 && wrongMovementDirection && !isStraight
&& (currentLocation.distanceTo(routeNodes.get(currentRoute)) > allowableDeviation)) {
log.info("Recalculate route, because wrong movement direction: " + currentLocation.distanceTo(routeNodes.get(currentRoute))); //$NON-NLS-1$
isDeviatedFromRoute = true;
calculateRoute = true;
@ -460,15 +472,15 @@ public class RoutingHelper {
// 5. Update Voice router
// Do not update in route planning mode
if (isFollowingMode) {
boolean inRecalc = calculateRoute || isRouteBeingCalculated();
boolean inRecalc = (calculateRoute || isRouteBeingCalculated());
if (!inRecalc && !wrongMovementDirection) {
voiceRouter.updateStatus(currentLocation, false);
voiceRouterStopped = false;
} else if (isDeviatedFromRoute && !voiceRouterStopped) {
} else if (isDeviatedFromRoute && !voiceRouterStopped && !settings.DISABLE_OFFROUTE_RECALC.get()) {
voiceRouter.interruptRouteCommands();
voiceRouterStopped = true; // Prevents excessive execution of stop() code
}
if (distOrth > mode.getOffRouteDistance()) {
if (distOrth > mode.getOffRouteDistance() && !settings.DISABLE_OFFROUTE_RECALC.get()) {
voiceRouter.announceOffRoute(distOrth);
}
}
@ -542,7 +554,7 @@ public class RoutingHelper {
return index;
}
private boolean updateCurrentRouteStatus(Location currentLocation, float posTolerance) {
private boolean updateCurrentRouteStatus(Location currentLocation, double posTolerance) {
List<Location> routeNodes = route.getImmutableAllLocations();
int currentRoute = route.currentRoute;
// 1. Try to proceed to next point using orthogonal distance (finding minimum orthogonal dist)
@ -670,6 +682,45 @@ public class RoutingHelper {
// targets.clearPointToNavigate(false);
return true;
}
}
// 4. update angle point
if (route.getRouteVisibleAngle() > 0) {
// proceed to the next point with min acceptable bearing
double ANGLE_TO_DECLINE = route.getRouteVisibleAngle();
int nextPoint = route.currentRoute;
for (; nextPoint < routeNodes.size() - 1; nextPoint++) {
float bearingTo = currentLocation.bearingTo(routeNodes.get(nextPoint));
float bearingTo2 = routeNodes.get(nextPoint).bearingTo(routeNodes.get(nextPoint + 1));
if (Math.abs(MapUtils.degreesDiff(bearingTo2, bearingTo)) <= ANGLE_TO_DECLINE) {
break;
}
}
if(nextPoint > 0) {
Location next = routeNodes.get(nextPoint);
Location prev = routeNodes.get(nextPoint - 1);
float bearing = prev.bearingTo(next);
double bearingTo = Math.abs(MapUtils.degreesDiff(bearing, currentLocation.bearingTo(next)));
double bearingPrev = Math.abs(MapUtils.degreesDiff(bearing, currentLocation.bearingTo(prev)));
while (true) {
Location mp = MapUtils.calculateMidPoint(prev, next);
if(mp.distanceTo(next) <= 100) {
break;
}
double bearingMid = Math.abs(MapUtils.degreesDiff(bearing, currentLocation.bearingTo(mp)));
if(bearingPrev < ANGLE_TO_DECLINE) {
next = mp;
bearingTo = bearingMid;
} else if(bearingTo < ANGLE_TO_DECLINE){
prev = mp;
bearingPrev = bearingMid;
} else {
break;
}
}
route.updateNextVisiblePoint(nextPoint, next);
}
}
return false;
@ -680,7 +731,7 @@ public class RoutingHelper {
}
private boolean identifyUTurnIsNeeded(Location currentLocation, float posTolerance) {
private boolean identifyUTurnIsNeeded(Location currentLocation, double posTolerance) {
if (finalLocation == null || currentLocation == null || !route.isCalculated() || isPublicTransportMode()) {
return false;
}
@ -884,7 +935,7 @@ public class RoutingHelper {
if(l != null && l.hasSpeed()) {
speed = l.getSpeed();
}
if(next != null) {
if(next != null && n.directionInfo != null) {
next[0] = n.directionInfo.getTurnType();
}
if(n.distanceTo > 0 && n.directionInfo != null && !n.directionInfo.getTurnType().isSkipToSpeak() &&
@ -1116,6 +1167,9 @@ public class RoutingHelper {
}
};
}
if (lastProjection != null) {
params.currentLocation = lastFixedLocation;
}
startRouteCalculationThread(params, paramsChanged, updateProgress);
}
}

View file

@ -9,8 +9,10 @@ import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.PreferenceViewHolder;
import android.widget.ImageView;
import net.osmand.Location;
import net.osmand.StateChangedListener;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.OsmandSettings.BooleanPreference;
@ -135,10 +137,15 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP
fastRoute.setSummaryOn(R.string.shared_string_on);
fastRoute.setSummaryOff(R.string.shared_string_off);
ApplicationMode am = getSelectedAppMode();
float defaultAllowedDeviation = RoutingHelper.getDefaultAllowedDeviation(settings, am,
RoutingHelper.getPosTolerance(0));
if (am.getRouteService() != RouteProvider.RouteService.OSMAND) {
screen.addPreference(fastRoute);
setupSelectRouteRecalcDistance(screen, defaultAllowedDeviation);
} else {
setupSelectRouteRecalcDistance(screen, defaultAllowedDeviation);
GeneralRouter router = app.getRouter(am);
clearParameters();
if (router != null) {
@ -227,6 +234,37 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP
}
}
private void setupSelectRouteRecalcDistance(PreferenceScreen screen, float defaultAllowedDeviation) {
Float[] entryValues;
OsmandSettings settings = app.getSettings();
OsmandSettings.MetricsConstants mc = settings.METRIC_SYSTEM.get();
if (mc == OsmandSettings.MetricsConstants.KILOMETERS_AND_METERS) {
entryValues = new Float[] {-1.0f, 0.f, 10.f, 20.0f, 30.0f, 50.0f, 100.0f, 200.0f, 500.0f, 1000.0f, 1500.0f};
} else {
entryValues = new Float[] {-1.0f, 0.f, 9.1f, 18.3f, 30.5f, 45.7f, 91.5f, 183.0f, 482.0f, 965.0f, 1609.0f};
}
String[] entries = new String[entryValues.length];
entries[0] = getString(R.string.no_recalculation_setting);
String defaultDistance = defaultAllowedDeviation < 0 ? getString(R.string.no_recalculation_setting) :
OsmAndFormatter.getFormattedDistance(defaultAllowedDeviation , app, false);
entries[1] = String.format(getString(R.string.shared_string_app_default_w_val), defaultDistance);
for (int i = 2; i < entryValues.length; i++) {
entries[i] = OsmAndFormatter.getFormattedDistance(entryValues[i], app, false);
}
ListPreferenceEx routeRecalculationDist = createListPreferenceEx(settings.ROUTE_RECALCULATION_DISTANCE.getId(),
entries, entryValues, R.string.route_recalculation_dist_title, R.layout.preference_with_descr);
routeRecalculationDist.setEntries(entries);
routeRecalculationDist.setEntryValues(entryValues);
routeRecalculationDist.setDescription(getString(R.string.route_recalculation_dist_descr));
routeRecalculationDist.setIcon(getRoutingPrefIcon("routing_recalc_distance"));
screen.addPreference(routeRecalculationDist);
}
@Override
public void onResume() {
super.onResume();
@ -292,6 +330,12 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP
return true;
} else if ("prouting_short_way".equals(key) && newValue instanceof Boolean) {
return app.getSettings().FAST_ROUTE_MODE.setModeValue(getSelectedAppMode(), !(Boolean) newValue);
} else if (settings.ROUTE_RECALCULATION_DISTANCE.getId().equals(key) && newValue instanceof Float) {
if ((float) newValue == -1.f) {
settings.DISABLE_OFFROUTE_RECALC.setModeValue(getSelectedAppMode(), true);
} else {
settings.DISABLE_OFFROUTE_RECALC.setModeValue(getSelectedAppMode(), false);
}
}
return super.onPreferenceChange(preference, newValue);
@ -401,6 +445,9 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP
return getPersistentPrefIcon(R.drawable.ic_action_fastest_route);
case "enable_time_conditional_routing":
return getPersistentPrefIcon(R.drawable.ic_action_road_works_dark);
case "routing_recalc_distance":
return getPersistentPrefIcon(R.drawable.ic_action_minimal_distance);
default:
return null;
}

View file

@ -17,6 +17,7 @@ import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.Pair;
import net.osmand.AndroidUtils;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.data.LatLon;
@ -37,6 +38,7 @@ import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu.TrackChartPoints;
import net.osmand.plus.render.RenderingIcons;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RouteProvider;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper;
import net.osmand.plus.transport.TransportStopRoute;
@ -315,7 +317,7 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
}
}
private void drawProjectionPoint(RotatedTileBox box, Canvas canvas, double[] projectionXY) {
private void drawProjectionPoint(Canvas canvas, double[] projectionXY) {
if (projectionIcon == null) {
projectionIcon = (LayerDrawable) view.getResources().getDrawable(helper.getSettings().getApplicationMode().getLocationIcon().getIconId());
}
@ -951,7 +953,7 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
}
private void drawSegments(RotatedTileBox tb, Canvas canvas, double topLatitude, double leftLongitude,
double bottomLatitude, double rightLongitude, Location lastProjection, int currentRoute, boolean showOriginalRoute) {
double bottomLatitude, double rightLongitude, Location lastProjection, int currentRoute) {
if (locations.size() == 0) {
return;
}
@ -965,26 +967,21 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
new GeometrySolidWayStyle(wayContext, attrs.paint.getColor());
GeometryWayStyle style = defaultWayStyle;
boolean previousVisible = false;
if (lastProjection != null) {
if (leftLongitude <= lastProjection.getLongitude() && lastProjection.getLongitude() <= rightLongitude
&& bottomLatitude <= lastProjection.getLatitude() && lastProjection.getLatitude() <= topLatitude) {
addLocation(tb, lastProjection, style, tx, ty, angles, distances, 0, styles);
previousVisible = true;
}
Location lastPoint = lastProjection;
if (lastPoint != null) {
previousVisible = addPoint(tb, topLatitude, leftLongitude, bottomLatitude, rightLongitude, style, previousVisible, lastPoint);
}
List<Location> routeNodes;
if (showOriginalRoute && helper.getOriginalRoute() != null && helper.getOriginalRouteAllLoc() != null) {
routeNodes = helper.getOriginalRouteAllLoc();
} else {
routeNodes = locations;
Location sp = helper.getRoute().getCurrentStraightAnglePoint();
if (sp != null) {
lastPoint = sp;
previousVisible = addPoint(tb, topLatitude, leftLongitude, bottomLatitude, rightLongitude, style, previousVisible, sp);
}
List<Location> routeNodes = locations;
int previous = -1;
for (int i = currentRoute; i < routeNodes.size(); i++) {
Location ls = routeNodes.get(i);
style = getStyle(i, defaultWayStyle);
if (!showOriginalRoute && (simplification.getQuick(i) == 0 && !styleMap.containsKey(i))) {
continue;
}
if (leftLongitude <= ls.getLongitude() && ls.getLongitude() <= rightLongitude && bottomLatitude <= ls.getLatitude()
&& ls.getLatitude() <= topLatitude) {
double dist = 0;
@ -996,7 +993,9 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
} else if (lastProjection != null) {
lt = lastProjection;
}
addLocation(tb, lt, style, tx, ty, angles, distances, 0, styles); // first point
if(lt != null) {
addLocation(tb, lt, style, tx, ty, angles, distances, 0, styles); // first point
}
}
addLocation(tb, ls, style, tx, ty, angles, distances, dist, styles);
previousVisible = true;
@ -1015,6 +1014,15 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
drawRouteSegment(tb, canvas, tx, ty, angles, distances, 0, styles);
}
private boolean addPoint(RotatedTileBox tb, double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude, GeometryWayStyle style, boolean previousVisible, Location lastPoint) {
if (leftLongitude <= lastPoint .getLongitude() && lastPoint .getLongitude() <= rightLongitude
&& bottomLatitude <= lastPoint .getLatitude() && lastPoint .getLatitude() <= topLatitude) {
addLocation(tb, lastPoint, style, tx, ty, angles, distances, 0, styles);
previousVisible = true;
}
return previousVisible;
}
private void clearArrays() {
tx.clear();
ty.clear();
@ -1098,43 +1106,52 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
Location startLocation = new Location("transport");
startLocation.setLatitude(start.getLatitude());
startLocation.setLongitude(start.getLongitude());
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude, startLocation, 0, false);
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude,
startLocation, 0);
}
} else {
RouteCalculationResult route = helper.getRoute();
boolean directTo = route.getRouteService() == RouteProvider.RouteService.DIRECT_TO;
boolean straight = route.getRouteService() == RouteProvider.RouteService.STRAIGHT;
routeGeometry.clearTransportRoute();
routeGeometry.updateRoute(tb, route);
if (helper.getRoute().isShowOriginalRoute() && helper.getOriginalStartingLocation() != null) {
RouteProvider.RouteService rs = helper.getRoute().getRouteService();
if (directTo) {
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude,
helper.getOriginalStartingLocation(), 0, true);
null, 0);
} else if (straight) {
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude,
helper.getLastFixedLocation(), route.getCurrentStraightAngleRoute());
} else {
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude,
helper.getLastProjection(), route == null ? 0 : route.getCurrentRoute(), false);
helper.getLastProjection(), route.getCurrentStraightAngleRoute());
}
List<RouteDirectionInfo> rd = helper.getRouteDirections();
Iterator<RouteDirectionInfo> it = rd.iterator();
if (!helper.getRoute().isShowOriginalRoute() && tb.getZoom() >= 14) {
if (!directTo && tb.getZoom() >= 14) {
List<Location> actionPoints = calculateActionPoints(topLatitude, leftLongitude, bottomLatitude, rightLongitude, helper.getLastProjection(),
helper.getRoute().getRouteLocations(), helper.getRoute().getCurrentRoute(), it, tb.getZoom());
drawAction(tb, canvas, actionPoints);
}
if (helper.getRoute().isShowOriginalRoute()) {
if (directTo) {
//add projection point on original route
double[] projectionOnRoute = calculateProjectionOnRoutePoint(helper.getLastProjection(),
helper.getOriginalRouteAllLoc(), helper, tb);
double[] projectionOnRoute = calculateProjectionOnRoutePoint(
helper.getRoute().getImmutableAllLocations(), helper, tb);
if (projectionOnRoute != null) {
drawProjectionPoint(tb, canvas, projectionOnRoute);
drawProjectionPoint(canvas, projectionOnRoute);
}
}
}
}
private double[] calculateProjectionOnRoutePoint(Location lastProjection, List<Location> routeNodes, RoutingHelper helper, RotatedTileBox box) {
private double[] calculateProjectionOnRoutePoint(List<Location> routeNodes, RoutingHelper helper, RotatedTileBox box) {
double[] projectionXY;
boolean visible;
Location previousInRoute = null;
Location nextInRoute = null;
//need to change this code by fixing helper.route.getCurrentRoute() miscalculation
// TODO simplifiy all culation!
if (helper.getRoute().getIntermediatePointsToPass() > 0) {
for (int i = 1; i < routeNodes.size(); i++) {
LatLon routePoint = new LatLon(routeNodes.get(i).getLatitude(), routeNodes.get(i).getLongitude());
@ -1148,25 +1165,31 @@ public class RouteLayer extends OsmandMapLayer implements ContextMenuLayer.ICont
nextInRoute = routeNodes.get(routeNodes.size() - 1);
}
int centerX = box.getPixXFromLonNoRot(nextInRoute.getLongitude());
int centerY = box.getPixYFromLatNoRot(nextInRoute.getLatitude());
int aX = box.getPixXFromLonNoRot(lastProjection.getLongitude());
int aY = box.getPixYFromLatNoRot(lastProjection.getLatitude());
int bX = box.getPixXFromLonNoRot(previousInRoute.getLongitude());
int bY = box.getPixYFromLatNoRot(previousInRoute.getLatitude());
if (nextInRoute != null && previousInRoute != null) {
double radius = MapUtils.getVectorMagnitude(centerX, centerY, aX, aY);
double angle2 = MapUtils.getAngleForRadiusVector(centerX, centerY, bX, bY);
projectionXY = MapUtils.getCoordinatesFromRadiusAndAngle(centerX, centerY, radius, angle2);
visible = box.containsPoint((float)projectionXY[0], (float)projectionXY[1], 20.0f)
&& Math.abs(Math.toDegrees(MapUtils.getAngleBetweenVectors(centerX, centerY, aX, aY, centerX, centerY, bX, bY))) < 90;
final Location ll = view.getApplication().getLocationProvider().getLastKnownLocation();
final int aX = box.getPixXFromLonNoRot(ll.getLongitude());
final int aY = box.getPixYFromLatNoRot(ll.getLatitude());
final int centerX = box.getPixXFromLonNoRot(nextInRoute.getLongitude());
final int centerY = box.getPixYFromLatNoRot(nextInRoute.getLatitude());
final int bX = box.getPixXFromLonNoRot(previousInRoute.getLongitude());
final int bY = box.getPixYFromLatNoRot(previousInRoute.getLatitude());
if (visible) {
return projectionXY;
} else {
return null;
double radius = MapUtils.getVectorMagnitude(centerX, centerY, aX, aY);
double angle2 = MapUtils.getAngleForRadiusVector(centerX, centerY, bX, bY);
projectionXY = MapUtils.getCoordinatesFromRadiusAndAngle(centerX, centerY, radius, angle2);
double distanceLoc2Proj = MapUtils.getVectorMagnitude(aX, aY, (int)projectionXY[0], (int)projectionXY[1]);
boolean isProjectionOnSegment = MapUtils.getVectorMagnitude(centerX ,centerY, (int) projectionXY[0], (int) projectionXY[1])
< MapUtils.getVectorMagnitude(centerX, centerY, bX, bY);
visible = box.containsPoint((float)projectionXY[0], (float)projectionXY[1], 20.0f)
&& Math.abs(Math.toDegrees(MapUtils.getAngleBetweenVectors(centerX, centerY, aX, aY, centerX, centerY, bX, bY))) < 90
&& distanceLoc2Proj > AndroidUtils.dpToPx(view.getContext(), 52) / 2.0
&& isProjectionOnSegment;
if (visible) {
return projectionXY;
}
}
return null;
}
private List<Location> calculateActionPoints(double topLatitude, double leftLongitude, double bottomLatitude,

View file

@ -1025,8 +1025,8 @@ public class MapInfoWidgetsFactory {
text = exitInfo.getExitStreetName();
}
if (nextDirInfo.directionInfo.getRouteDataObject() != null) {
object = nextDirInfo.directionInfo.getRouteDataObject();
if (directionInfo != null && directionInfo.getRouteDataObject() != null) {
object = directionInfo.getRouteDataObject();
showShield = true;
}
}