From cf916a5da7194de4a9a69ecf9c1b1a38f679d7db Mon Sep 17 00:00:00 2001 From: max-klaus Date: Sun, 20 Dec 2020 15:47:36 +0300 Subject: [PATCH] Refactor RoutingHelper (reduce class code lines) --- OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java | 3 +- .../osmand/plus/OsmAndLocationProvider.java | 4 +- .../net/osmand/plus/TargetPointsHelper.java | 3 +- .../osmand/plus/activities/MapActivity.java | 4 +- .../plus/base/MapViewTrackingUtilities.java | 3 +- .../plus/helpers/AvoidSpecificRoads.java | 13 +- .../plus/helpers/ExternalApiHelper.java | 3 +- .../ImpassibleRoadsMenuController.java | 5 +- .../other/RoutePreferencesMenu.java | 6 +- .../mapmarkers/MarkersPlanRouteContext.java | 7 +- .../MeasurementEditingContext.java | 6 +- .../MeasurementToolFragment.java | 2 +- .../AvoidRoadsBottomSheetDialogFragment.java | 2 +- .../FollowTrackFragment.java | 2 +- .../MapRouteInfoMenu.java | 9 +- .../RouteOptionsBottomSheet.java | 2 +- .../RoutingOptionsHelper.java | 4 +- .../cards/MapMarkersCard.java | 2 +- .../plus/routing/CurrentStreetName.java | 87 ++ .../plus/routing/RouteCalculationParams.java | 1 - .../RouteCalculationProgressCallback.java | 12 + .../plus/routing/RouteCalculationResult.java | 2 +- .../RouteRecalculationThreadHelper.java | 389 ++++++++ .../routing/RouteSegmentSearchResult.java | 59 ++ .../osmand/plus/routing/RoutingHelper.java | 877 +++--------------- .../plus/routing/RoutingHelperUtils.java | 210 +++++ .../plus/routing/TransportRoutingHelper.java | 5 +- ...ecalculateRouteInDeviationBottomSheet.java | 6 +- .../fragments/RouteParametersFragment.java | 12 +- .../fragments/VehicleParametersFragment.java | 13 +- .../plus/views/layers/MapControlsLayer.java | 2 +- .../mapwidgets/MapInfoWidgetsFactory.java | 8 +- 32 files changed, 966 insertions(+), 797 deletions(-) create mode 100644 OsmAnd/src/net/osmand/plus/routing/CurrentStreetName.java create mode 100644 OsmAnd/src/net/osmand/plus/routing/RouteCalculationProgressCallback.java create mode 100644 OsmAnd/src/net/osmand/plus/routing/RouteRecalculationThreadHelper.java create mode 100644 OsmAnd/src/net/osmand/plus/routing/RouteSegmentSearchResult.java create mode 100644 OsmAnd/src/net/osmand/plus/routing/RoutingHelperUtils.java diff --git a/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java b/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java index 15f7dd123b..ddb7965c9c 100644 --- a/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java +++ b/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java @@ -80,6 +80,7 @@ import net.osmand.plus.routing.IRoutingDataUpdateListener; import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.routing.RoutingHelperUtils; import net.osmand.plus.routing.VoiceRouter; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; @@ -1803,7 +1804,7 @@ public class OsmandAidlApi { if (ni.directionInfo != null && ni.directionInfo.getTurnType() != null) { TurnType tt = ni.directionInfo.getTurnType(); RouteDirectionInfo a = ni.directionInfo; - bundle.putString(prefix + PARAM_NT_DIRECTION_NAME, RoutingHelper.formatStreetName(a.getStreetName(), a.getRef(), a.getDestinationName(), "")); + bundle.putString(prefix + PARAM_NT_DIRECTION_NAME, RoutingHelperUtils.formatStreetName(a.getStreetName(), a.getRef(), a.getDestinationName(), "")); bundle.putString(prefix + PARAM_NT_DIRECTION_TURN, tt.toXmlString()); bundle.putFloat(prefix + PARAM_NT_DIRECTION_ANGLE, tt.getTurnAngle()); bundle.putBoolean(prefix + PARAM_NT_DIRECTION_POSSIBLY_LEFT, tt.isPossibleLeftTurn()); diff --git a/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java b/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java index c465ce2f77..2d35556d84 100644 --- a/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java +++ b/OsmAnd/src/net/osmand/plus/OsmAndLocationProvider.java @@ -39,7 +39,7 @@ import net.osmand.data.LatLon; import net.osmand.data.QuadPoint; import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.routing.RoutingHelper.RouteSegmentSearchResult; +import net.osmand.plus.routing.RouteSegmentSearchResult; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.router.RouteSegmentResult; @@ -154,7 +154,7 @@ public class OsmAndLocationProvider implements SensorEventListener { startLocation.setTime(ms); } RouteSegmentSearchResult searchResult = - RoutingHelper.searchRouteSegment(currentLocation.getLatitude(), currentLocation.getLongitude(), -1, roads); + RouteSegmentSearchResult.searchRouteSegment(currentLocation.getLatitude(), currentLocation.getLongitude(), -1, roads); if (searchResult != null) { currentRoad = searchResult.getRoadIndex(); currentSegment = searchResult.getSegmentIndex(); diff --git a/OsmAnd/src/net/osmand/plus/TargetPointsHelper.java b/OsmAnd/src/net/osmand/plus/TargetPointsHelper.java index 4221ffa308..2d46b63fd1 100644 --- a/OsmAnd/src/net/osmand/plus/TargetPointsHelper.java +++ b/OsmAnd/src/net/osmand/plus/TargetPointsHelper.java @@ -12,6 +12,7 @@ import net.osmand.data.PointDescription; import net.osmand.plus.GeocodingLookupService.AddressLookupRequest; import net.osmand.plus.routing.RouteProvider.RouteService; import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.routing.RoutingHelperUtils; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmAndAppCustomization.OsmAndAppCustomizationListener; import net.osmand.plus.settings.backend.OsmandSettings; @@ -444,7 +445,7 @@ public class TargetPointsHelper { Location lastKnownLocation = ctx.getLocationProvider().getLastKnownLocation(); LatLon latLon = lastKnownLocation != null ? new LatLon(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude()) : null; - routingHelper.checkAndUpdateStartLocation(latLon); + RoutingHelperUtils.checkAndUpdateStartLocation(ctx, latLon); setMyLocationPoint(latLon, false, null); } } diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java index 8541ab5e87..02a61a8219 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java @@ -126,7 +126,7 @@ import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu; import net.osmand.plus.routepreparationmenu.MapRouteInfoMenuFragment; import net.osmand.plus.routing.IRouteInformationListener; import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.routing.RoutingHelper.RouteCalculationProgressCallback; +import net.osmand.plus.routing.RouteCalculationProgressCallback; import net.osmand.plus.routing.TransportRoutingHelper.TransportRouteCalculationProgressCallback; import net.osmand.plus.search.QuickSearchDialogFragment; import net.osmand.plus.search.QuickSearchDialogFragment.QuickSearchTab; @@ -553,7 +553,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven allowPrivate.setModeValue(mode, true); } } - getRoutingHelper().recalculateRouteDueToSettingsChange(); + getRoutingHelper().onSettingsChanged(true); } }); dlg.setNegativeButton(R.string.shared_string_no, null); diff --git a/OsmAnd/src/net/osmand/plus/base/MapViewTrackingUtilities.java b/OsmAnd/src/net/osmand/plus/base/MapViewTrackingUtilities.java index 9c6c6c2e7e..fa66a5c91a 100644 --- a/OsmAnd/src/net/osmand/plus/base/MapViewTrackingUtilities.java +++ b/OsmAnd/src/net/osmand/plus/base/MapViewTrackingUtilities.java @@ -25,6 +25,7 @@ import net.osmand.plus.dashboard.DashboardOnMap; import net.osmand.plus.mapcontextmenu.MapContextMenu; import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.routing.RoutingHelperUtils; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.views.AnimateDraggingMapThread; import net.osmand.plus.views.OsmandMapTileView; @@ -175,7 +176,7 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc locationProvider = location.getProvider(); if (settings.DRIVING_REGION_AUTOMATIC.get() && !drivingRegionUpdated && !app.isApplicationInitializing()) { drivingRegionUpdated = true; - app.getRoutingHelper().checkAndUpdateStartLocation(location); + RoutingHelperUtils.checkAndUpdateStartLocation(app, location); } } if (mapView != null) { diff --git a/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java b/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java index bfa84b8474..bfb0ff75b1 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java +++ b/OsmAnd/src/net/osmand/plus/helpers/AvoidSpecificRoads.java @@ -32,8 +32,8 @@ import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.MapContextMenu; -import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.routing.RoutingHelper.RouteSegmentSearchResult; +import net.osmand.plus.routing.RouteSegmentSearchResult; +import net.osmand.plus.routing.RoutingHelperUtils; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.views.layers.ContextMenuLayer; import net.osmand.router.RouteSegmentResult; @@ -150,7 +150,7 @@ public class AvoidSpecificRoads { if (obj != null) { String locale = app.getSettings().MAP_PREFERRED_LOCALE.get(); boolean transliterate = app.getSettings().MAP_TRANSLITERATE_NAMES.get(); - String name = RoutingHelper.formatStreetName( + String name = RoutingHelperUtils.formatStreetName( obj.getName(locale, transliterate), obj.getRef(locale, transliterate, true), obj.getDestinationName(locale, transliterate, true), @@ -164,10 +164,7 @@ public class AvoidSpecificRoads { } private void recalculateRoute() { - RoutingHelper rh = app.getRoutingHelper(); - if (rh.isRouteCalculated() || rh.isRouteBeingCalculated()) { - rh.recalculateRouteDueToSettingsChange(); - } + app.getRoutingHelper().onSettingsChanged(); } public void removeImpassableRoad(LatLon latLon) { @@ -244,7 +241,7 @@ public class AvoidSpecificRoads { RotatedTileBox tb = mapActivity.getMapView().getCurrentRotatedTileBox().copy(); float maxDistPx = MAX_AVOID_ROUTE_SEARCH_RADIUS_DP * tb.getDensity(); RouteSegmentSearchResult searchResult = - RoutingHelper.searchRouteSegment(loc.getLatitude(), loc.getLongitude(), maxDistPx / tb.getPixDensity(), roads); + RouteSegmentSearchResult.searchRouteSegment(loc.getLatitude(), loc.getLongitude(), maxDistPx / tb.getPixDensity(), roads); if (searchResult != null) { QuadPoint point = searchResult.getPoint(); LatLon newLoc = new LatLon(MapUtils.get31LatitudeY((int) point.y), MapUtils.get31LongitudeX((int) point.x)); diff --git a/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java index a81540be89..23c65ac932 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ExternalApiHelper.java @@ -47,6 +47,7 @@ import net.osmand.plus.quickaction.QuickActionRegistry; import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.routing.RoutingHelperUtils; import net.osmand.plus.search.listitems.QuickSearchListItem; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.track.SaveGpxAsyncTask; @@ -697,7 +698,7 @@ public class ExternalApiHelper { if (ni.directionInfo != null && ni.directionInfo.getTurnType() != null) { TurnType tt = ni.directionInfo.getTurnType(); RouteDirectionInfo a = ni.directionInfo; - result.putExtra(prefix + PARAM_NT_DIRECTION_NAME, RoutingHelper.formatStreetName(a.getStreetName(), a.getRef(), a.getDestinationName(), "")); + result.putExtra(prefix + PARAM_NT_DIRECTION_NAME, RoutingHelperUtils.formatStreetName(a.getStreetName(), a.getRef(), a.getDestinationName(), "")); result.putExtra(prefix + PARAM_NT_DIRECTION_TURN, tt.toXmlString()); result.putExtra(prefix + PARAM_NT_DIRECTION_ANGLE, tt.getTurnAngle()); result.putExtra(prefix + PARAM_NT_DIRECTION_POSSIBLY_LEFT, tt.isPossibleLeftTurn()); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/ImpassibleRoadsMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/ImpassibleRoadsMenuController.java index b4779f1d27..450d89f093 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/ImpassibleRoadsMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/ImpassibleRoadsMenuController.java @@ -31,10 +31,7 @@ public class ImpassibleRoadsMenuController extends MenuController { if (activity != null) { app.getAvoidSpecificRoads().removeImpassableRoad( ImpassibleRoadsMenuController.this.avoidRoadInfo); - RoutingHelper rh = app.getRoutingHelper(); - if (rh.isRouteCalculated() || rh.isRouteBeingCalculated()) { - rh.recalculateRouteDueToSettingsChange(); - } + app.getRoutingHelper().onSettingsChanged(); activity.getContextMenu().close(); } } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/RoutePreferencesMenu.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/RoutePreferencesMenu.java index 65656cec79..005433cbe2 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/RoutePreferencesMenu.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/RoutePreferencesMenu.java @@ -137,7 +137,7 @@ public class RoutePreferencesMenu { LocalRoutingParameter rp = group.getRoutingParameters().get(i); rp.setSelected(settings, i == position); } - mapActivity.getRoutingHelper().recalculateRouteDueToSettingsChange(); + mapActivity.getRoutingHelper().onSettingsChanged(true); updateParameters(); } } @@ -366,7 +366,7 @@ public class RoutePreferencesMenu { app.getTargetPointsHelper().updateRouteAndRefresh(true); updateSpinnerItems(gpxSpinner); updateParameters(); - mapActivity.getRoutingHelper().recalculateRouteDueToSettingsChange(); + mapActivity.getRoutingHelper().onSettingsChanged(true); return true; } }, app.getDaynightHelper().isNightModeForMapControls()); @@ -389,7 +389,7 @@ public class RoutePreferencesMenu { if (mapActivity.getRoutingHelper().getCurrentGPXRoute() != null) { mapActivity.getRoutingHelper().setGpxParams(null); settings.FOLLOW_THE_GPX_ROUTE.set(null); - mapActivity.getRoutingHelper().recalculateRouteDueToSettingsChange(); + mapActivity.getRoutingHelper().onSettingsChanged(true); } updateParameters(); return true; diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/MarkersPlanRouteContext.java b/OsmAnd/src/net/osmand/plus/mapmarkers/MarkersPlanRouteContext.java index 622fa39542..2060140d3d 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/MarkersPlanRouteContext.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/MarkersPlanRouteContext.java @@ -4,6 +4,7 @@ import android.util.Pair; import net.osmand.Location; import net.osmand.data.LatLon; +import net.osmand.plus.routing.RouteCalculationProgressCallback; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.GPXUtilities.TrkSegment; import net.osmand.GPXUtilities.WptPt; @@ -127,7 +128,7 @@ public class MarkersPlanRouteContext { findPairsToCalculate(points); RoutingHelper routingHelper = app.getRoutingHelper(); if (!snapToRoadPairsToCalculate.isEmpty() && !routingHelper.isRouteBeingCalculated()) { - routingHelper.startRouteCalculationThread(getParams(), true, true); + routingHelper.startRouteCalculationThread(getParams()); app.runInUIThread(new Runnable() { @Override public void run() { @@ -217,7 +218,7 @@ public class MarkersPlanRouteContext { params.mode = snappedMode; params.ctx = app; params.calculationProgress = calculationProgress = new RouteCalculationProgress(); - params.calculationProgressCallback = new RoutingHelper.RouteCalculationProgressCallback() { + params.calculationProgressCallback = new RouteCalculationProgressCallback() { @Override public void start() { @@ -265,7 +266,7 @@ public class MarkersPlanRouteContext { } }); if (!snapToRoadPairsToCalculate.isEmpty()) { - app.getRoutingHelper().startRouteCalculationThread(getParams(), true, true); + app.getRoutingHelper().startRouteCalculationThread(getParams()); } else { app.runInUIThread(new Runnable() { @Override diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java index 6d1522de1d..f4f2bd3da9 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java @@ -20,7 +20,7 @@ import net.osmand.plus.routing.RouteCalculationParams; import net.osmand.plus.routing.RouteCalculationParams.RouteCalculationResultListener; import net.osmand.plus.routing.RouteCalculationResult; import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.routing.RoutingHelper.RouteCalculationProgressCallback; +import net.osmand.plus.routing.RouteCalculationProgressCallback; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.router.RouteCalculationProgress; import net.osmand.router.RouteExporter; @@ -673,7 +673,7 @@ public class MeasurementEditingContext { if (progressListener != null && !routingHelper.isRouteBeingCalculated()) { RouteCalculationParams params = getParams(true); if (params != null) { - routingHelper.startRouteCalculationThread(params, true, true); + routingHelper.startRouteCalculationThread(params); application.runInUIThread(new Runnable() { @Override public void run() { @@ -1063,7 +1063,7 @@ public class MeasurementEditingContext { progressListener.refresh(); RouteCalculationParams params = getParams(false); if (params != null) { - application.getRoutingHelper().startRouteCalculationThread(params, true, true); + application.getRoutingHelper().startRouteCalculationThread(params); } else { progressListener.hideProgressBar(); } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index 3d8d9163b0..e3987d903c 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -930,7 +930,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (isFollowTrackMode()) { mapActivity.getMapActions().setGPXRouteParams(gpx); app.getTargetPointsHelper().updateRouteAndRefresh(true); - app.getRoutingHelper().recalculateRouteDueToSettingsChange(); + app.getRoutingHelper().onSettingsChanged(true); } else { mapActivity.getMapActions().stopNavigationActionConfirm(null , new Runnable() { @Override diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/AvoidRoadsBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/AvoidRoadsBottomSheetDialogFragment.java index ffcf3a5149..5045a34cea 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/AvoidRoadsBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/AvoidRoadsBottomSheetDialogFragment.java @@ -301,7 +301,7 @@ public class AvoidRoadsBottomSheetDialogFragment extends MenuBottomSheetDialogFr avoidSpecificRoads.removeImpassableRoad(routeLocation); } - app.getRoutingHelper().recalculateRouteDueToSettingsChange(); + app.getRoutingHelper().onSettingsChanged(true); MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { final MapRouteInfoMenu mapRouteInfoMenu = mapActivity.getMapRouteInfoMenu(); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java index f20b9f9350..e75dad04de 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java @@ -521,7 +521,7 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca } mapActivity.getMapActions().setGPXRouteParams(gpxFile); app.getTargetPointsHelper().updateRouteAndRefresh(true); - app.getRoutingHelper().recalculateRouteDueToSettingsChange(); + app.getRoutingHelper().onSettingsChanged(true); } } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java index c856a47426..49edb61649 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java @@ -54,6 +54,7 @@ import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.mapmarkers.MapMarker; import net.osmand.plus.OsmAndLocationProvider; import net.osmand.plus.OsmandApplication; +import net.osmand.plus.routing.RoutingHelperUtils; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.CommonPreference; import net.osmand.plus.settings.backend.OsmandPreference; @@ -862,7 +863,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener } routingHelper.setAppMode(next); app.initVoiceCommandPlayer(mapActivity, next, true, null, false, false, true); - routingHelper.recalculateRouteDueToSettingsChange(); + routingHelper.onSettingsChanged(true); } } @@ -1279,7 +1280,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener if (mapActivity != null) { OsmandApplication app = mapActivity.getMyApplication(); app.getAvoidSpecificRoads().removeImpassableRoad(avoidRoadInfo); - app.getRoutingHelper().recalculateRouteDueToSettingsChange(); + app.getRoutingHelper().onSettingsChanged(true); if (app.getAvoidSpecificRoads().getImpassableRoads().isEmpty() && getAvoidedParameters(app).isEmpty()) { mode.parameters.remove(parameter); } @@ -1312,7 +1313,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener CommonPreference preference = settings.getCustomRoutingBooleanProperty(routingParameter.getId(), routingParameter.getDefaultBoolean()); preference.setModeValue(app.getRoutingHelper().getAppMode(), false); avoidedParameters.remove(routingParameter); - app.getRoutingHelper().recalculateRouteDueToSettingsChange(); + app.getRoutingHelper().onSettingsChanged(true); if (app.getAvoidSpecificRoads().getImpassableRoads().isEmpty() && avoidedParameters.isEmpty()) { mode.parameters.remove(parameter); } @@ -2411,7 +2412,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener } } else if (routingHelper.isRouteCalculated()) { RouteCalculationResult result = routingHelper.getRoute(); - QuadRect routeRect = routingHelper.getRouteRect(result); + QuadRect routeRect = RoutingHelperUtils.getRouteRect(app, result); if (routeRect != null) { rect = routeRect; } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java index 8daf44e8e8..c7ebb4ce99 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java @@ -400,7 +400,7 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { boolean enabled = !settings.ENABLE_TIME_CONDITIONAL_ROUTING.getModeValue(applicationMode); settings.ENABLE_TIME_CONDITIONAL_ROUTING.setModeValue(applicationMode, enabled); timeConditionalRoutingItem[0].setChecked(enabled); - app.getRoutingHelper().recalculateRouteDueToSettingsChange(); + app.getRoutingHelper().onSettingsChanged(true); } }) .create(); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java index d34144cbdc..1c54c1b4d2 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RoutingOptionsHelper.java @@ -230,7 +230,7 @@ public class RoutingOptionsHelper { if (rp instanceof OtherLocalRoutingParameter) { updateGpxRoutingParameter((OtherLocalRoutingParameter) rp); } - routingHelper.recalculateRouteDueToSettingsChange(); + routingHelper.onSettingsChanged(true); } public void updateGpxRoutingParameter(OtherLocalRoutingParameter gpxParam) { @@ -377,7 +377,7 @@ public class RoutingOptionsHelper { LocalRoutingParameter rp = group.getRoutingParameters().get(i); rp.setSelected(settings, i == position); } - mapActivity.getRoutingHelper().recalculateRouteDueToSettingsChange(); + mapActivity.getRoutingHelper().onSettingsChanged(true); if (listener != null) { listener.onClick(); } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/MapMarkersCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/MapMarkersCard.java index 6367a1df9a..6e18fb0521 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/MapMarkersCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/MapMarkersCard.java @@ -108,7 +108,7 @@ public class MapMarkersCard extends BaseCard { public void onClick(View v) { LatLon point = new LatLon(marker.getLatitude(), marker.getLongitude()); app.getTargetPointsHelper().navigateToPoint(point, true, -1, marker.getPointDescription(mapActivity)); - app.getRoutingHelper().recalculateRouteDueToSettingsChange(); + app.getRoutingHelper().onSettingsChanged(true); } }); if (i > 0) { diff --git a/OsmAnd/src/net/osmand/plus/routing/CurrentStreetName.java b/OsmAnd/src/net/osmand/plus/routing/CurrentStreetName.java new file mode 100644 index 0000000000..c984fb9119 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/routing/CurrentStreetName.java @@ -0,0 +1,87 @@ +package net.osmand.plus.routing; + +import androidx.annotation.NonNull; + +import net.osmand.Location; +import net.osmand.binary.RouteDataObject; +import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.router.RouteSegmentResult; +import net.osmand.router.TurnType; +import net.osmand.util.Algorithms; + +public class CurrentStreetName { + public String text; + public TurnType turnType; + public boolean showMarker; // turn type has priority over showMarker + public RouteDataObject shieldObject; + public String exitRef; + + @NonNull + private static String getRouteSegmentStreetName(@NonNull RoutingHelper routingHelper, @NonNull RouteSegmentResult rs, boolean includeRef) { + OsmandSettings settings = routingHelper.getSettings(); + String nm = rs.getObject().getName(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get()); + String rf = rs.getObject().getRef(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get(), rs.isForwardDirection()); + String dn = rs.getObject().getDestinationName(settings.MAP_PREFERRED_LOCALE.get(), + settings.MAP_TRANSLITERATE_NAMES.get(), rs.isForwardDirection()); + return RoutingHelperUtils.formatStreetName(nm, includeRef ? rf : null, dn, "»"); + } + + @NonNull + public static CurrentStreetName getCurrentName(@NonNull RoutingHelper routingHelper, @NonNull NextDirectionInfo n) { + CurrentStreetName streetName = new CurrentStreetName(); + Location l = routingHelper.getLastFixedLocation(); + float speed = 0; + if (l != null && l.hasSpeed()) { + speed = l.getSpeed(); + } + boolean isSet = false; + // 1. turn is imminent + if (n.distanceTo > 0 && n.directionInfo != null && !n.directionInfo.getTurnType().isSkipToSpeak() && + routingHelper.getVoiceRouter().isDistanceLess(speed, n.distanceTo, routingHelper.getVoiceRouter().PREPARE_DISTANCE * 0.75f)) { + String nm = n.directionInfo.getStreetName(); + String rf = n.directionInfo.getRef(); + String dn = n.directionInfo.getDestinationName(); + isSet = !(Algorithms.isEmpty(nm) && Algorithms.isEmpty(rf) && Algorithms.isEmpty(dn)); + streetName.text = RoutingHelperUtils.formatStreetName(nm, null, dn, "»"); + streetName.turnType = n.directionInfo.getTurnType(); + streetName.shieldObject = n.directionInfo.getRouteDataObject(); + if (streetName.turnType == null) { + streetName.turnType = TurnType.valueOf(TurnType.C, false); + } + if (n.directionInfo.getExitInfo() != null) { + streetName.exitRef = n.directionInfo.getExitInfo().getRef(); + if (!Algorithms.isEmpty(n.directionInfo.getExitInfo().getExitStreetName())) { + streetName.text = n.directionInfo.getExitInfo().getExitStreetName(); + } + } + } + // 2. display current road street name + if (!isSet) { + RouteSegmentResult rs = routingHelper.getCurrentSegmentResult(); + if (rs != null) { + streetName.text = getRouteSegmentStreetName(routingHelper, rs, false); + if (Algorithms.isEmpty(streetName.text)) { + isSet = !Algorithms.isEmpty(getRouteSegmentStreetName(routingHelper, rs, true)); + } else { + isSet = true; + } + streetName.showMarker = true; + streetName.shieldObject = rs.getObject(); + } + } + // 3. display next road street name if this one empty + if (!isSet) { + RouteSegmentResult rs = routingHelper.getNextStreetSegmentResult(); + if (rs != null) { + streetName.text = getRouteSegmentStreetName(routingHelper, rs, false); + streetName.turnType = TurnType.valueOf(TurnType.C, false); + streetName.shieldObject = rs.getObject(); + } + } + if (streetName.turnType == null) { + streetName.showMarker = true; + } + return streetName; + } +} diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationParams.java b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationParams.java index fbc361c4d5..7b38b5c91a 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationParams.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationParams.java @@ -5,7 +5,6 @@ import net.osmand.data.LatLon; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.OsmandApplication; import net.osmand.plus.routing.RouteProvider.GPXRouteParams; -import net.osmand.plus.routing.RoutingHelper.RouteCalculationProgressCallback; import net.osmand.router.RouteCalculationProgress; import java.util.List; diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationProgressCallback.java b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationProgressCallback.java new file mode 100644 index 0000000000..a0649ba109 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationProgressCallback.java @@ -0,0 +1,12 @@ +package net.osmand.plus.routing; + +public interface RouteCalculationProgressCallback { + + void start(); + + void updateProgress(int progress); + + void requestPrivateAccessRouting(); + + void finish(); +} diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java index a6dcc20fca..e6efcc321f 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java @@ -435,7 +435,7 @@ public class RouteCalculationResult { } } - String description = toString(turn, ctx, false) + " " + RoutingHelper.formatStreetName(info.getStreetName(), + String description = toString(turn, ctx, false) + " " + RoutingHelperUtils.formatStreetName(info.getStreetName(), info.getRef(), info.getDestinationName(), ctx.getString(R.string.towards)); description = description.trim(); String[] pointNames = s.getObject().getPointNames(s.getStartPointIndex()); diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteRecalculationThreadHelper.java b/OsmAnd/src/net/osmand/plus/routing/RouteRecalculationThreadHelper.java new file mode 100644 index 0000000000..340d13fedf --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/routing/RouteRecalculationThreadHelper.java @@ -0,0 +1,389 @@ +package net.osmand.plus.routing; + +import androidx.annotation.NonNull; + +import net.osmand.Location; +import net.osmand.data.LatLon; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.router.RouteCalculationProgress; + +import java.util.List; + +import static net.osmand.plus.notifications.OsmandNotification.NotificationType.NAVIGATION; + +class RouteRecalculationThreadHelper { + + private static final int RECALCULATE_THRESHOLD_COUNT_CAUSING_FULL_RECALCULATE = 3; + private static final int RECALCULATE_THRESHOLD_CAUSING_FULL_RECALCULATE_INTERVAL = 2 * 60 * 1000; + + private final OsmandApplication app; + private final RoutingHelper routingHelper; + + private Thread currentRunningJob; + private long lastTimeEvaluatedRoute = 0; + private String lastRouteCalcError; + private String lastRouteCalcErrorShort; + private long recalculateCountInInterval = 0; + private int evalWaitInterval = 0; + private boolean waitingNextJob; + + private RouteCalculationProgressCallback progressRoute; + + RouteRecalculationThreadHelper(@NonNull RoutingHelper routingHelper) { + this.routingHelper = routingHelper; + this.app = routingHelper.getApplication(); + } + + String getLastRouteCalcError() { + return lastRouteCalcError; + } + + String getLastRouteCalcErrorShort() { + return lastRouteCalcErrorShort; + } + + void setProgressBar(RouteCalculationProgressCallback progressRoute) { + this.progressRoute = progressRoute; + } + + boolean isRouteBeingCalculated() { + return currentRunningJob instanceof RouteRecalculationThread || waitingNextJob; + } + + void resetEvalWaitInterval() { + evalWaitInterval = 0; + } + + void stopCalculation() { + Thread job = currentRunningJob; + if (job instanceof RouteRecalculationThread) { + ((RouteRecalculationThread) job).stopCalculation(); + } + } + + void stopCalculationIfParamsChanged() { + Thread job = currentRunningJob; + if (job instanceof RouteRecalculationThread) { + RouteRecalculationThread thread = (RouteRecalculationThread) job; + if (!thread.isParamsChanged()) { + thread.stopCalculation(); + } + if (isFollowingMode()) { + getVoiceRouter().announceBackOnRoute(); + } + } + } + + private OsmandSettings getSettings() { + return routingHelper.getSettings(); + } + + private ApplicationMode getAppMode() { + return routingHelper.getAppMode(); + } + + private boolean isFollowingMode() { + return routingHelper.isFollowingMode(); + } + + private VoiceRouter getVoiceRouter() { + return routingHelper.getVoiceRouter(); + } + + private Location getLastFixedLocation() { + return routingHelper.getLastFixedLocation(); + } + + private boolean isDeviatedFromRoute() { + return routingHelper.isDeviatedFromRoute(); + } + + private Location getLastProjection() { + return routingHelper.getLastProjection(); + } + + private void setNewRoute(RouteCalculationResult prevRoute, final RouteCalculationResult res, Location start) { + final boolean newRoute = !prevRoute.isCalculated(); + if (isFollowingMode()) { + Location lastFixedLocation = getLastFixedLocation(); + if (lastFixedLocation != null) { + start = lastFixedLocation; + } + // try remove false route-recalculated prompts by checking direction to second route node + boolean wrongMovementDirection = false; + List routeNodes = res.getImmutableAllLocations(); + if (routeNodes != null && !routeNodes.isEmpty()) { + int newCurrentRoute = RoutingHelperUtils.lookAheadFindMinOrthogonalDistance(start, routeNodes, res.currentRoute, 15); + if (newCurrentRoute + 1 < routeNodes.size()) { + // This check is valid for Online/GPX services (offline routing is aware of route direction) + wrongMovementDirection = RoutingHelperUtils.checkWrongMovementDirection(start, routeNodes.get(newCurrentRoute + 1)); + // set/reset evalWaitInterval only if new route is in forward direction + if (wrongMovementDirection) { + evalWaitInterval = 3000; + } else { + evalWaitInterval = Math.max(3000, evalWaitInterval * 3 / 2); + evalWaitInterval = Math.min(evalWaitInterval, 120000); + } + + } + } + + + // trigger voice prompt only if new route is in forward direction + // If route is in wrong direction after one more setLocation it will be recalculated + if (!wrongMovementDirection || newRoute) { + getVoiceRouter().newRouteIsCalculated(newRoute); + } + } + app.getWaypointHelper().setNewRoute(res); + routingHelper.newRouteCalculated(newRoute, res); + } + + void startRouteCalculationThread(RouteCalculationParams params, boolean paramsChanged, boolean updateProgress) { + synchronized (routingHelper) { + final Thread prevRunningJob = currentRunningJob; + getSettings().LAST_ROUTE_APPLICATION_MODE.set(getAppMode()); + RouteRecalculationThread newThread = new RouteRecalculationThread("Calculating route", params, paramsChanged); + currentRunningJob = newThread; + startProgress(params); + if (updateProgress) { + updateProgress(params); + } + if (prevRunningJob != null) { + newThread.setWaitPrevJob(prevRunningJob); + } + currentRunningJob.start(); + } + } + + public void recalculateRouteInBackground(final Location start, final LatLon end, final List intermediates, + final RouteProvider.GPXRouteParamsBuilder gpxRoute, final RouteCalculationResult previousRoute, boolean paramsChanged, boolean onlyStartPointChanged) { + if (start == null || end == null) { + return; + } + // do not evaluate very often + if ((currentRunningJob == null && System.currentTimeMillis() - lastTimeEvaluatedRoute > evalWaitInterval) + || paramsChanged || !onlyStartPointChanged) { + if (System.currentTimeMillis() - lastTimeEvaluatedRoute < RECALCULATE_THRESHOLD_CAUSING_FULL_RECALCULATE_INTERVAL) { + recalculateCountInInterval++; + } + ApplicationMode mode = getAppMode(); + final RouteCalculationParams params = new RouteCalculationParams(); + params.start = start; + params.end = end; + params.intermediates = intermediates; + params.gpxRoute = gpxRoute == null ? null : gpxRoute.build(app); + params.onlyStartPointChanged = onlyStartPointChanged; + if (recalculateCountInInterval < RECALCULATE_THRESHOLD_COUNT_CAUSING_FULL_RECALCULATE + || (gpxRoute != null && gpxRoute.isPassWholeRoute() && isDeviatedFromRoute())) { + params.previousToRecalculate = previousRoute; + } else { + recalculateCountInInterval = 0; + } + params.leftSide = getSettings().DRIVING_REGION.get().leftHandDriving; + params.fast = getSettings().FAST_ROUTE_MODE.getModeValue(mode); + params.mode = mode; + params.ctx = app; + boolean updateProgress = false; + if (params.mode.getRouteService() == RouteProvider.RouteService.OSMAND) { + params.calculationProgress = new RouteCalculationProgress(); + updateProgress = true; + } else { + params.resultListener = new RouteCalculationParams.RouteCalculationResultListener() { + @Override + public void onRouteCalculated(RouteCalculationResult route) { + app.runInUIThread(new Runnable() { + + @Override + public void run() { + finishProgress(params); + } + }); + } + }; + } + if (getLastProjection() != null) { + params.currentLocation = getLastFixedLocation(); + } + startRouteCalculationThread(params, paramsChanged, updateProgress); + } + } + + void startProgress(final RouteCalculationParams params) { + if (params.calculationProgressCallback != null) { + params.calculationProgressCallback.start(); + } else if (progressRoute != null) { + progressRoute.start(); + } + } + + void updateProgress(final RouteCalculationParams params) { + final RouteCalculationProgressCallback progressRoute; + if (params.calculationProgressCallback != null) { + progressRoute = params.calculationProgressCallback; + } else { + progressRoute = this.progressRoute; + } + if (progressRoute != null) { + app.runInUIThread(new Runnable() { + + @Override + public void run() { + RouteCalculationProgress calculationProgress = params.calculationProgress; + if (isRouteBeingCalculated()) { + Thread t = currentRunningJob; + if (t instanceof RouteRecalculationThread && ((RouteRecalculationThread) t).params != params) { + // different calculation started + return; + } else { + progressRoute.updateProgress((int) calculationProgress.getLinearProgress()); + if (calculationProgress.requestPrivateAccessRouting) { + progressRoute.requestPrivateAccessRouting(); + } + updateProgress(params); + } + } else { + if (calculationProgress.requestPrivateAccessRouting) { + progressRoute.requestPrivateAccessRouting(); + } + progressRoute.finish(); + } + } + }, 300); + } + } + + void finishProgress(RouteCalculationParams params) { + final RouteCalculationProgressCallback progressRoute; + if (params.calculationProgressCallback != null) { + progressRoute = params.calculationProgressCallback; + } else { + progressRoute = this.progressRoute; + } + if (progressRoute != null) { + progressRoute.finish(); + } + } + + private void showMessage(final String msg) { + app.runInUIThread(new Runnable() { + @Override + public void run() { + app.showToastMessage(msg); + } + }); + } + + class RouteRecalculationThread extends Thread { + + private final RouteCalculationParams params; + private final boolean paramsChanged; + private Thread prevRunningJob; + + public RouteRecalculationThread(String name, RouteCalculationParams params, boolean paramsChanged) { + super(name); + this.params = params; + this.paramsChanged = paramsChanged; + if (params.calculationProgress == null) { + params.calculationProgress = new RouteCalculationProgress(); + } + } + + public boolean isParamsChanged() { + return paramsChanged; + } + + public void stopCalculation() { + params.calculationProgress.isCancelled = true; + } + + + @Override + public void run() { + synchronized (routingHelper) { + routingHelper.resetRouteWasFinished(); + currentRunningJob = this; + waitingNextJob = prevRunningJob != null; + } + if (prevRunningJob != null) { + while (prevRunningJob.isAlive()) { + try { + Thread.sleep(50); + } catch (InterruptedException e) { + // ignore + } + } + synchronized (routingHelper) { + if (params.calculationProgress.isCancelled) { + return; + } + currentRunningJob = this; + waitingNextJob = false; + } + } + lastRouteCalcError = null; + lastRouteCalcErrorShort = null; + RouteProvider provider = routingHelper.getProvider(); + OsmandSettings settings = getSettings(); + RouteCalculationResult res = provider.calculateRouteImpl(params); + if (params.calculationProgress.isCancelled) { + synchronized (routingHelper) { + currentRunningJob = null; + } + return; + } + final boolean onlineSourceWithoutInternet = !res.isCalculated() && + params.mode.getRouteService().isOnline() && !settings.isInternetConnectionAvailable(); + if (onlineSourceWithoutInternet && settings.GPX_ROUTE_CALC_OSMAND_PARTS.get()) { + if (params.previousToRecalculate != null && params.previousToRecalculate.isCalculated()) { + res = provider.recalculatePartOfflineRoute(res, params); + } + } + RouteCalculationResult prev = routingHelper.getRoute(); + synchronized (routingHelper) { + if (res.isCalculated()) { + if (!params.inSnapToRoadMode && !params.inPublicTransportMode) { + routingHelper.setRoute(res); + routingHelper.updateOriginalRoute(); + } + if (params.resultListener != null) { + params.resultListener.onRouteCalculated(res); + } + } else { + evalWaitInterval = Math.max(3000, evalWaitInterval * 3 / 2); // for Issue #3899 + evalWaitInterval = Math.min(evalWaitInterval, 120000); + } + currentRunningJob = null; + } + if (res.isCalculated()) { + if (!params.inSnapToRoadMode && !params.inPublicTransportMode) { + setNewRoute(prev, res, params.start); + } + } else if (onlineSourceWithoutInternet) { + lastRouteCalcError = app.getString(R.string.error_calculating_route) + + ":\n" + app.getString(R.string.internet_connection_required_for_online_route); + lastRouteCalcErrorShort = app.getString(R.string.error_calculating_route); + showMessage(lastRouteCalcError); //$NON-NLS-1$ + } else { + if (res.getErrorMessage() != null) { + lastRouteCalcError = app.getString(R.string.error_calculating_route) + ":\n" + res.getErrorMessage(); + lastRouteCalcErrorShort = app.getString(R.string.error_calculating_route); + showMessage(lastRouteCalcError); //$NON-NLS-1$ + } else { + lastRouteCalcError = app.getString(R.string.empty_route_calculated); + lastRouteCalcErrorShort = app.getString(R.string.empty_route_calculated); + showMessage(lastRouteCalcError); + } + } + app.getNotificationHelper().refreshNotification(NAVIGATION); + lastTimeEvaluatedRoute = System.currentTimeMillis(); + } + + public void setWaitPrevJob(Thread prevRunningJob) { + this.prevRunningJob = prevRunningJob; + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteSegmentSearchResult.java b/OsmAnd/src/net/osmand/plus/routing/RouteSegmentSearchResult.java new file mode 100644 index 0000000000..dcecfa69be --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/routing/RouteSegmentSearchResult.java @@ -0,0 +1,59 @@ +package net.osmand.plus.routing; + +import net.osmand.binary.RouteDataObject; +import net.osmand.data.QuadPoint; +import net.osmand.router.RouteSegmentResult; +import net.osmand.util.MapUtils; + +import java.util.List; + +public class RouteSegmentSearchResult { + private final int roadIndex; + private final int segmentIndex; + private final QuadPoint point; + + RouteSegmentSearchResult(int roadIndex, int segmentIndex, QuadPoint point) { + this.roadIndex = roadIndex; + this.segmentIndex = segmentIndex; + this.point = point; + } + + public int getRoadIndex() { + return roadIndex; + } + + public int getSegmentIndex() { + return segmentIndex; + } + + public QuadPoint getPoint() { + return point; + } + + public static RouteSegmentSearchResult searchRouteSegment(double latitude, double longitude, double maxDist, List roads) { + int roadIndex = -1; + int segmentIndex = -1; + QuadPoint point = null; + int px = MapUtils.get31TileNumberX(longitude); + int py = MapUtils.get31TileNumberY(latitude); + double dist = maxDist < 0 ? 1000 : maxDist; + for (int i = 0; i < roads.size(); i++) { + RouteSegmentResult road = roads.get(i); + int startPointIndex = Math.min(road.getStartPointIndex(), road.getEndPointIndex()); + int endPointIndex = Math.max(road.getEndPointIndex(), road.getStartPointIndex()); + RouteDataObject obj = road.getObject(); + for (int j = startPointIndex + 1; j <= endPointIndex; j++) { + QuadPoint proj = MapUtils.getProjectionPoint31(px, py, obj.getPoint31XTile(j - 1), obj.getPoint31YTile(j - 1), + obj.getPoint31XTile(j), obj.getPoint31YTile(j)); + double dd = MapUtils.squareRootDist31((int) proj.x, (int) proj.y, px, py); + if (dd < dist) { + dist = dd; + roadIndex = i; + segmentIndex = j; + point = proj; + } + } + } + return roadIndex != -1 ? new RouteSegmentSearchResult(roadIndex, segmentIndex, point) : null; + } +} diff --git a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java index 49b8babdc8..179318790e 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java @@ -1,8 +1,6 @@ package net.osmand.plus.routing; - import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import net.osmand.GPXUtilities.GPXFile; import net.osmand.Location; @@ -10,10 +8,7 @@ import net.osmand.LocationsHolder; import net.osmand.PlatformUtil; import net.osmand.ResultMatcher; import net.osmand.ValueHolder; -import net.osmand.binary.RouteDataObject; import net.osmand.data.LatLon; -import net.osmand.data.QuadPoint; -import net.osmand.data.QuadRect; import net.osmand.plus.NavigationService; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; @@ -21,7 +16,6 @@ import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.TargetPointsHelper.TargetPoint; -import net.osmand.plus.helpers.enums.MetricsConstants; import net.osmand.plus.notifications.OsmandNotification.NotificationType; import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo; import net.osmand.plus.routing.RouteProvider.GPXRouteParamsBuilder; @@ -30,13 +24,10 @@ import net.osmand.plus.routing.RouteProvider.RoutingEnvironment; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmAndAppCustomization.OsmAndAppCustomizationListener; import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.router.RouteCalculationProgress; import net.osmand.router.RouteExporter; import net.osmand.router.RoutePlannerFrontEnd.GpxPoint; import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation; import net.osmand.router.RouteSegmentResult; -import net.osmand.router.TurnType; -import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; import java.io.IOException; @@ -46,25 +37,25 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import static net.osmand.plus.notifications.OsmandNotification.NotificationType.NAVIGATION; - public class RoutingHelper { private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RoutingHelper.class); - private static final float POSITION_TOLERANCE = 60; - private static final int CACHE_RADIUS = 100000; public static final float ALLOWED_DEVIATION = 2; // This should be correlated with RoutingHelper.updateCurrentRouteStatus ( when processed turn now is not announced) - private static int DEFAULT_GPS_TOLERANCE = 12; + private static final int DEFAULT_GPS_TOLERANCE = 12; public static int GPS_TOLERANCE = DEFAULT_GPS_TOLERANCE; public static float ARRIVAL_DISTANCE_FACTOR = 1; private List> listeners = new LinkedList<>(); private List> updateListeners = new LinkedList<>(); - private OsmandApplication app; - private TransportRoutingHelper transportRoutingHelper; + private final OsmandApplication app; + private OsmandSettings settings; + private final RouteProvider provider; + private final VoiceRouter voiceRouter; + private final RouteRecalculationThreadHelper routeRecalculationHelper; + private final TransportRoutingHelper transportRoutingHelper; private boolean isFollowingMode = false; private boolean isRoutePlanningMode = false; @@ -81,33 +72,15 @@ public class RoutingHelper { private RouteCalculationResult originalRoute = null; - private static final int RECALCULATE_THRESHOLD_COUNT_CAUSING_FULL_RECALCULATE = 3; - private static final int RECALCULATE_THRESHOLD_CAUSING_FULL_RECALCULATE_INTERVAL = 2*60*1000; - private Thread currentRunningJob; - private long lastTimeEvaluatedRoute = 0; - private String lastRouteCalcError; - private String lastRouteCalcErrorShort; - private long recalculateCountInInterval = 0; - private int evalWaitInterval = 0; - private boolean waitingNextJob; private boolean routeWasFinished; private ApplicationMode mode; - private OsmandSettings settings; - - private RouteProvider provider; - private VoiceRouter voiceRouter; private static boolean isDeviatedFromRoute = false; private long deviateFromRouteDetected = 0; //private long wrongMovementDetected = 0; private boolean voiceRouterStopped = false; - private RouteCalculationProgressCallback progressRoute; - -// private ProgressBar progress; -// private Handler progressHandler; - public boolean isDeviatedFromRoute() { return isDeviatedFromRoute; } @@ -116,11 +89,12 @@ public class RoutingHelper { return routeWasFinished; } - public RoutingHelper(OsmandApplication context){ + public RoutingHelper(OsmandApplication context) { this.app = context; settings = context.getSettings(); voiceRouter = new VoiceRouter(this); provider = new RouteProvider(); + routeRecalculationHelper = new RouteRecalculationThreadHelper(this); transportRoutingHelper = context.getTransportRoutingHelper(); transportRoutingHelper.setRoutingHelper(this); setAppMode(settings.APPLICATION_MODE.get()); @@ -134,6 +108,26 @@ public class RoutingHelper { app.getAppCustomization().addListener(customizationListener); } + RouteProvider getProvider() { + return provider; + } + + void resetRouteWasFinished() { + routeWasFinished = false; + } + + void setRoute(RouteCalculationResult route) { + this.route = route; + } + + long getDeviateFromRouteDetected() { + return deviateFromRouteDetected; + } + + void setDeviateFromRouteDetected(long deviateFromRouteDetected) { + this.deviateFromRouteDetected = deviateFromRouteDetected; + } + public TransportRoutingHelper getTransportRoutingHelper() { return transportRoutingHelper; } @@ -147,11 +141,11 @@ public class RoutingHelper { } public String getLastRouteCalcError() { - return lastRouteCalcError; + return routeRecalculationHelper.getLastRouteCalcError(); } public String getLastRouteCalcErrorShort() { - return lastRouteCalcErrorShort; + return routeRecalculationHelper.getLastRouteCalcErrorShort(); } public void setPauseNavigation(boolean b) { @@ -195,8 +189,8 @@ public class RoutingHelper { this.isRoutePlanningMode = isRoutePlanningMode; } - public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List intermediatePoints, Location currentLocation){ - checkAndUpdateStartLocation(currentLocation); + public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List intermediatePoints, Location currentLocation) { + RoutingHelperUtils.checkAndUpdateStartLocation(app, currentLocation); RouteCalculationResult previousRoute = route; clearCurrentRoute(finalLocation, intermediatePoints); // to update route @@ -206,17 +200,17 @@ public class RoutingHelper { public synchronized void clearCurrentRoute(LatLon newFinalLocation, List newIntermediatePoints) { route = new RouteCalculationResult(""); isDeviatedFromRoute = false; - evalWaitInterval = 0; + routeRecalculationHelper.resetEvalWaitInterval(); originalRoute = null; app.getWaypointHelper().setNewRoute(route); app.runInUIThread(new Runnable() { @Override public void run() { Iterator> it = listeners.iterator(); - while(it.hasNext()) { + while (it.hasNext()) { WeakReference ref = it.next(); IRouteInformationListener l = ref.get(); - if(l == null) { + if (l == null) { it.remove(); } else { l.routeWasCancelled(); @@ -226,9 +220,7 @@ public class RoutingHelper { }); this.finalLocation = newFinalLocation; this.intermediatePoints = newIntermediatePoints; - if(currentRunningJob instanceof RouteRecalculationThread) { - ((RouteRecalculationThread) currentRunningJob).stopCalculation(); - } + routeRecalculationHelper.stopCalculation(); if (newFinalLocation == null) { settings.FOLLOW_THE_ROUTE.set(false); settings.FOLLOW_THE_GPX_ROUTE.set(null); @@ -245,10 +237,10 @@ public class RoutingHelper { @Override public void run() { Iterator> it = listeners.iterator(); - while(it.hasNext()) { + while (it.hasNext()) { WeakReference ref = it.next(); IRouteInformationListener l = ref.get(); - if(l == null) { + if (l == null) { it.remove(); } else { l.routeWasFinished(); @@ -258,11 +250,38 @@ public class RoutingHelper { }); } + void newRouteCalculated(final boolean newRoute, final RouteCalculationResult res) { + app.runInUIThread(new Runnable() { + @Override + public void run() { + ValueHolder showToast = new ValueHolder<>(); + showToast.value = true; + Iterator> it = listeners.iterator(); + while (it.hasNext()) { + WeakReference ref = it.next(); + IRouteInformationListener l = ref.get(); + if (l == null) { + it.remove(); + } else { + l.newRouteIsCalculated(newRoute, showToast); + } + } + if (showToast.value && newRoute && OsmandPlugin.isDevelopment()) { + String msg = app.getString(R.string.new_route_calculated_dist_dbg, + OsmAndFormatter.getFormattedDistance(res.getWholeDistance(), app), + ((int) res.getRoutingTime()) + " sec", + res.getCalculateTime(), res.getVisitedSegments(), res.getLoadedTiles()); + app.showToastMessage(msg); + } + } + }); + } + public GPXRouteParamsBuilder getCurrentGPXRoute() { return currentGPXRoute; } - public boolean isCurrentGPXRouteV2() { + public boolean isCurrentGPXRouteV2() { return currentGPXRoute != null && RouteExporter.OSMAND_ROUTER_V2.equals(currentGPXRoute.getFile().author); } @@ -274,7 +293,7 @@ public class RoutingHelper { return route.getImmutableAllLocations(); } - public void setAppMode(ApplicationMode mode){ + public void setAppMode(ApplicationMode mode) { this.mode = mode; ARRIVAL_DISTANCE_FACTOR = Math.max(settings.ARRIVAL_DISTANCE_FACTOR.getModeValue(mode), 0.1f); GPS_TOLERANCE = (int) (DEFAULT_GPS_TOLERANCE * ARRIVAL_DISTANCE_FACTOR); @@ -288,27 +307,12 @@ public class RoutingHelper { public LatLon getFinalLocation() { return finalLocation; } - public void checkAndUpdateStartLocation(Location nextStartLocation) { - if (nextStartLocation != null) { - checkAndUpdateStartLocation(new LatLon(nextStartLocation.getLatitude(), nextStartLocation.getLongitude())); - } - } - - public void checkAndUpdateStartLocation(LatLon newStartLocation) { - if (newStartLocation != null) { - LatLon lastStartLocation = app.getSettings().getLastStartPoint(); - if (lastStartLocation == null || MapUtils.getDistance(newStartLocation, lastStartLocation) > CACHE_RADIUS) { - app.getMapViewTrackingUtilities().detectDrivingRegion(newStartLocation); - app.getSettings().setLastStartPoint(newStartLocation); - } - } - } public List getIntermediatePoints() { return intermediatePoints; } - public boolean isRouteCalculated(){ + public boolean isRouteCalculated() { return route.isCalculated(); } @@ -316,7 +320,7 @@ public class RoutingHelper { return voiceRouter; } - public Location getLastProjection(){ + public Location getLastProjection() { return lastProjection; } @@ -333,8 +337,8 @@ public class RoutingHelper { } private List> updateListenersList( - List> copyList, - IRoutingDataUpdateListener listener, boolean isNewListener) { + List> copyList, + IRoutingDataUpdateListener listener, boolean isNewListener) { Iterator> it = copyList.iterator(); while (it.hasNext()) { WeakReference ref = it.next(); @@ -349,18 +353,18 @@ public class RoutingHelper { return copyList; } - public void addListener(IRouteInformationListener l){ + public void addListener(IRouteInformationListener l) { listeners = updateInformationListeners(new ArrayList<>(listeners), l, true); transportRoutingHelper.addListener(l); } - public void removeListener(IRouteInformationListener lt){ + public void removeListener(IRouteInformationListener lt) { listeners = updateInformationListeners(new ArrayList<>(listeners), lt, false); } private List> updateInformationListeners( - List> copyList, - IRouteInformationListener listener, boolean isNewListener) { + List> copyList, + IRouteInformationListener listener, boolean isNewListener) { Iterator> it = copyList.iterator(); while (it.hasNext()) { WeakReference ref = it.next(); @@ -382,7 +386,7 @@ public class RoutingHelper { app.getTargetPointsHelper().setMyLocationPoint( new LatLon(currentLocation.getLatitude(), currentLocation.getLongitude()), false, null); } - if(isFollowingMode() || (settings.getPointToStart() == null && isRoutePlanningMode) || + if (isFollowingMode() || (settings.getPointToStart() == null && isRoutePlanningMode) || app.getLocationProvider().getLocationSimulation().isRouteAnimating()) { setCurrentLocation(currentLocation, false); } @@ -392,43 +396,18 @@ public class RoutingHelper { return setCurrentLocation(currentLocation, returnUpdatedLocation, route, false); } - public double getRouteDeviation(){ + public double getRouteDeviation() { if (route == null || - route.getImmutableAllDirections().size() < 2 || - route.currentRoute == 0){ + route.getImmutableAllDirections().size() < 2 || + route.currentRoute == 0) { return 0; } List routeNodes = route.getImmutableAllLocations(); - 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) { - MetricsConstants mc = settings.METRIC_SYSTEM.getModeValue(mode); - if (mc == MetricsConstants.KILOMETERS_AND_METERS || mc == 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; + return RoutingHelperUtils.getOrthogonalDistance(lastFixedLocation, routeNodes.get(route.currentRoute - 1), routeNodes.get(route.currentRoute)); } private Location setCurrentLocation(Location currentLocation, boolean returnUpdatedLocation, - RouteCalculationResult previousRoute, boolean targetPointsChanged) { + RouteCalculationResult previousRoute, boolean targetPointsChanged) { Location locationProjection = currentLocation; if (isPublicTransportMode() && currentLocation != null && finalLocation != null && (targetPointsChanged || transportRoutingHelper.getStartLocation() == null)) { @@ -442,14 +421,14 @@ public class RoutingHelper { isDeviatedFromRoute = false; return locationProjection; } - float posTolerance = getPosTolerance(currentLocation.hasAccuracy() ? currentLocation.getAccuracy() : 0); + float posTolerance = RoutingHelperUtils.getPosTolerance(currentLocation.hasAccuracy() ? currentLocation.getAccuracy() : 0); boolean calculateRoute = false; synchronized (this) { isDeviatedFromRoute = false; double distOrth = 0; // 0. Route empty or needs to be extended? Then re-calculate route. - if(route.isEmpty()) { + if (route.isEmpty()) { calculateRoute = true; } else { // 1. Update current route position status according to latest received location @@ -461,13 +440,13 @@ public class RoutingHelper { int currentRoute = route.currentRoute; double allowableDeviation = route.getRouteRecalcDistance(); if (allowableDeviation == 0) { - allowableDeviation = getDefaultAllowedDeviation(settings, route.getAppMode(), posTolerance); + allowableDeviation = RoutingHelperUtils.getDefaultAllowedDeviation(settings, route.getAppMode(), posTolerance); } // 2. Analyze if we need to recalculate route // >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)); + distOrth = RoutingHelperUtils.getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute)); if (distOrth > allowableDeviation) { log.info("Recalculate route, because correlation : " + distOrth); //$NON-NLS-1$ isDeviatedFromRoute = true; @@ -478,7 +457,7 @@ public class RoutingHelper { Location next = route.getNextRouteLocation(); boolean isStraight = route.getRouteService() == RouteService.DIRECT_TO || route.getRouteService() == RouteService.STRAIGHT; - boolean wrongMovementDirection = checkWrongMovementDirection(currentLocation, next); + boolean wrongMovementDirection = RoutingHelperUtils.checkWrongMovementDirection(currentLocation, next); if ((allowableDeviation > 0 && wrongMovementDirection && !isStraight && (currentLocation.distanceTo(routeNodes.get(currentRoute)) > allowableDeviation)) && !settings.DISABLE_WRONG_DIRECTION_RECALC.get()) { log.info("Recalculate route, because wrong movement direction: " + currentLocation.distanceTo(routeNodes.get(currentRoute))); //$NON-NLS-1$ @@ -486,7 +465,7 @@ public class RoutingHelper { calculateRoute = true; } // 4. Identify if UTurn is needed - if (identifyUTurnIsNeeded(currentLocation, posTolerance)) { + if (RoutingHelperUtils.identifyUTurnIsNeeded(this, currentLocation, posTolerance)) { isDeviatedFromRoute = true; } // 5. Update Voice router @@ -509,7 +488,7 @@ public class RoutingHelper { if (currentRoute > 0) { locationProjection = new Location(currentLocation); Location nextLocation = routeNodes.get(currentRoute); - LatLon project = getProject(currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute)); + LatLon project = RoutingHelperUtils.getProject(currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute)); locationProjection.setLatitude(project.getLatitude()); locationProjection.setLongitude(project.getLongitude()); @@ -523,76 +502,39 @@ public class RoutingHelper { } if (calculateRoute) { - recalculateRouteInBackground(currentLocation, finalLocation, intermediatePoints, currentGPXRoute, + routeRecalculationHelper.recalculateRouteInBackground(currentLocation, finalLocation, intermediatePoints, currentGPXRoute, previousRoute.isCalculated() ? previousRoute : null, false, !targetPointsChanged); } else { - Thread job = currentRunningJob; - if(job instanceof RouteRecalculationThread) { - RouteRecalculationThread thread = (RouteRecalculationThread) job; - if(!thread.isParamsChanged()) { - thread.stopCalculation(); - } - if (isFollowingMode){ - voiceRouter.announceBackOnRoute(); - } - } + routeRecalculationHelper.stopCalculationIfParamsChanged(); } double projectDist = mode != null && mode.hasFastSpeed() ? posTolerance : posTolerance / 2; - if(returnUpdatedLocation && locationProjection != null && currentLocation.distanceTo(locationProjection) < projectDist) { + if (returnUpdatedLocation && locationProjection != null && currentLocation.distanceTo(locationProjection) < projectDist) { return locationProjection; } else { return currentLocation; } } - private static double getOrthogonalDistance(Location loc, Location from, Location to) { - return MapUtils.getOrthogonalDistance(loc.getLatitude(), - loc.getLongitude(), from.getLatitude(), from.getLongitude(), - to.getLatitude(), to.getLongitude()); - } - - private static LatLon getProject(Location loc, Location from, Location to) { - return MapUtils.getProjection(loc.getLatitude(), - loc.getLongitude(), from.getLatitude(), from.getLongitude(), - to.getLatitude(), to.getLongitude()); - } - - private static int lookAheadFindMinOrthogonalDistance(Location currentLocation, List routeNodes, int currentRoute, int iterations) { - double newDist; - double dist = Double.POSITIVE_INFINITY; - int index = currentRoute; - while (iterations > 0 && currentRoute + 1 < routeNodes.size()) { - newDist = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute), routeNodes.get(currentRoute + 1)); - if (newDist < dist) { - index = currentRoute; - dist = newDist; - } - currentRoute++; - iterations--; - } - return index; - } - private boolean updateCurrentRouteStatus(Location currentLocation, double posTolerance) { List routeNodes = route.getImmutableAllLocations(); int currentRoute = route.currentRoute; // 1. Try to proceed to next point using orthogonal distance (finding minimum orthogonal dist) while (currentRoute + 1 < routeNodes.size()) { double dist = currentLocation.distanceTo(routeNodes.get(currentRoute)); - if(currentRoute > 0) { - dist = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute - 1), + if (currentRoute > 0) { + dist = RoutingHelperUtils.getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute)); } boolean processed = false; // if we are still too far try to proceed many points // if not then look ahead only 3 in order to catch sharp turns boolean longDistance = dist >= 250; - int newCurrentRoute = lookAheadFindMinOrthogonalDistance(currentLocation, routeNodes, currentRoute, longDistance ? 15 : 8); - double newDist = getOrthogonalDistance(currentLocation, routeNodes.get(newCurrentRoute), + int newCurrentRoute = RoutingHelperUtils.lookAheadFindMinOrthogonalDistance(currentLocation, routeNodes, currentRoute, longDistance ? 15 : 8); + double newDist = RoutingHelperUtils.getOrthogonalDistance(currentLocation, routeNodes.get(newCurrentRoute), routeNodes.get(newCurrentRoute + 1)); - if(longDistance) { - if(newDist < dist) { + if (longDistance) { + if (newDist < dist) { if (log.isDebugEnabled()) { log.debug("Processed by distance : (new) " + newDist + " (old) " + dist); //$NON-NLS-1$//$NON-NLS-2$ } @@ -644,32 +586,32 @@ public class RoutingHelper { } // 2. check if intermediate found - if(route.getIntermediatePointsToPass() > 0 - && route.getDistanceToNextIntermediate(lastFixedLocation) < getArrivalDistance() * 2f && !isRoutePlanningMode) { + if (route.getIntermediatePointsToPass() > 0 + && route.getDistanceToNextIntermediate(lastFixedLocation) < RoutingHelperUtils.getArrivalDistance(mode, settings) * 2f && !isRoutePlanningMode) { showMessage(app.getString(R.string.arrived_at_intermediate_point)); route.passIntermediatePoint(); TargetPointsHelper targets = app.getTargetPointsHelper(); String name = ""; - if(intermediatePoints != null && !intermediatePoints.isEmpty()) { + if (intermediatePoints != null && !intermediatePoints.isEmpty()) { LatLon rm = intermediatePoints.remove(0); List ll = targets.getIntermediatePointsNavigation(); int ind = -1; - for(int i = 0; i < ll.size(); i++) { - if(ll.get(i).point != null && MapUtils.getDistance(ll.get(i).point, rm) < 5) { + for (int i = 0; i < ll.size(); i++) { + if (ll.get(i).point != null && MapUtils.getDistance(ll.get(i).point, rm) < 5) { name = ll.get(i).getOnlyName(); ind = i; break; } } - if(ind >= 0) { + if (ind >= 0) { targets.removeWayPoint(false, ind); } } - if(isFollowingMode) { + if (isFollowingMode) { voiceRouter.arrivedIntermediatePoint(name); } // double check - while(intermediatePoints != null && route.getIntermediatePointsToPass() < intermediatePoints.size()) { + while (intermediatePoints != null && route.getIntermediatePointsToPass() < intermediatePoints.size()) { intermediatePoints.remove(0); } } @@ -677,13 +619,13 @@ public class RoutingHelper { // 3. check if destination found Location lastPoint = routeNodes.get(routeNodes.size() - 1); if (currentRoute > routeNodes.size() - 3 - && currentLocation.distanceTo(lastPoint) < getArrivalDistance() + && currentLocation.distanceTo(lastPoint) < RoutingHelperUtils.getArrivalDistance(mode, settings) && !isRoutePlanningMode) { //showMessage(app.getString(R.string.arrived_at_destination)); TargetPointsHelper targets = app.getTargetPointsHelper(); TargetPoint tp = targets.getPointToNavigate(); String description = tp == null ? "" : tp.getOnlyName(); - if(isFollowingMode) { + if (isFollowingMode) { voiceRouter.arrivedDestinationPoint(description); } boolean onDestinationReached = OsmandPlugin.onDestinationReached(); @@ -717,7 +659,7 @@ public class RoutingHelper { } } - if(nextPoint > 0) { + if (nextPoint > 0) { Location next = routeNodes.get(nextPoint); Location prev = routeNodes.get(nextPoint - 1); float bearing = prev.bearingTo(next); @@ -725,14 +667,14 @@ public class RoutingHelper { double bearingPrev = Math.abs(MapUtils.degreesDiff(bearing, currentLocation.bearingTo(prev))); while (true) { Location mp = MapUtils.calculateMidPoint(prev, next); - if(mp.distanceTo(next) <= 100) { + if (mp.distanceTo(next) <= 100) { break; } double bearingMid = Math.abs(MapUtils.degreesDiff(bearing, currentLocation.bearingTo(mp))); - if(bearingPrev < ANGLE_TO_DECLINE) { + if (bearingPrev < ANGLE_TO_DECLINE) { next = mp; bearingTo = bearingMid; - } else if(bearingTo < ANGLE_TO_DECLINE){ + } else if (bearingTo < ANGLE_TO_DECLINE) { prev = mp; bearingPrev = bearingMid; } else { @@ -746,140 +688,7 @@ public class RoutingHelper { return false; } - private float getArrivalDistance() { - ApplicationMode m = mode == null ? settings.getApplicationMode() : mode; - float defaultSpeed = Math.max(0.3f, m.getDefaultSpeed()); - - /// Used to be: car - 90 m, bicycle - 50 m, pedestrian - 20 m - // return ((float)settings.getApplicationMode().getArrivalDistance()) * settings.ARRIVAL_DISTANCE_FACTOR.getModeValue(m); - // GPS_TOLERANCE - 12 m - // 5 seconds: car - 80 m @ 50 kmh, bicyle - 45 m @ 25 km/h, bicyle - 25 m @ 10 km/h, pedestrian - 18 m @ 4 km/h, - return GPS_TOLERANCE + defaultSpeed * 5 * ARRIVAL_DISTANCE_FACTOR; - } - - - private boolean identifyUTurnIsNeeded(Location currentLocation, double posTolerance) { - if (finalLocation == null || currentLocation == null || !route.isCalculated() || isPublicTransportMode()) { - return false; - } - boolean isOffRoute = false; - if (currentLocation.hasBearing()) { - float bearingMotion = currentLocation.getBearing() ; - Location nextRoutePosition = route.getNextRouteLocation(); - float bearingToRoute = currentLocation.bearingTo(nextRoutePosition); - double diff = MapUtils.degreesDiff(bearingMotion, bearingToRoute); - // 7. Check if you left the route and an unscheduled U-turn would bring you back (also Issue 863) - // This prompt is an interim advice and does only sound if a new route in forward direction could not be found in x seconds - if (Math.abs(diff) > 135f) { - float d = currentLocation.distanceTo(nextRoutePosition); - // 60m tolerance to allow for GPS inaccuracy - if (d > posTolerance) { - // require x sec continuous since first detection - if (deviateFromRouteDetected == 0) { - deviateFromRouteDetected = System.currentTimeMillis(); - } else if ((System.currentTimeMillis() - deviateFromRouteDetected > 10000)) { - isOffRoute = true; - //log.info("bearingMotion is opposite to bearingRoute"); //$NON-NLS-1$ - } - } - } else { - deviateFromRouteDetected = 0; - } - } - return isOffRoute; - } - - /** - * Wrong movement direction is considered when between - * current location bearing (determines by 2 last fixed position or provided) - * and bearing from currentLocation to next (current) point - * the difference is more than 60 degrees - */ - public boolean checkWrongMovementDirection(Location currentLocation, Location nextRouteLocation) { - // measuring without bearing could be really error prone (with last fixed location) - // this code has an effect on route recalculation which should be detected without mistakes - if (currentLocation.hasBearing() && nextRouteLocation != null) { - float bearingMotion = currentLocation.getBearing(); - float bearingToRoute = currentLocation.bearingTo(nextRouteLocation); - double diff = MapUtils.degreesDiff(bearingMotion, bearingToRoute); - if (Math.abs(diff) > 60f) { - // require delay interval since first detection, to avoid false positive - //but leave out for now, as late detection is worse than false positive (it may reset voice router then cause bogus turn and u-turn prompting) - //if (wrongMovementDetected == 0) { - // wrongMovementDetected = System.currentTimeMillis(); - //} else if ((System.currentTimeMillis() - wrongMovementDetected > 500)) { - return true; - //} - } else { - //wrongMovementDetected = 0; - return false; - } - } - //wrongMovementDetected = 0; - return false; - } - - private void setNewRoute(RouteCalculationResult prevRoute, final RouteCalculationResult res, Location start){ - final boolean newRoute = !prevRoute.isCalculated(); - if (isFollowingMode) { - if(lastFixedLocation != null) { - start = lastFixedLocation; - } - // try remove false route-recalculated prompts by checking direction to second route node - boolean wrongMovementDirection = false; - List routeNodes = res.getImmutableAllLocations(); - if (routeNodes != null && !routeNodes.isEmpty()) { - int newCurrentRoute = lookAheadFindMinOrthogonalDistance(start, routeNodes, res.currentRoute, 15); - if (newCurrentRoute + 1 < routeNodes.size()) { - // This check is valid for Online/GPX services (offline routing is aware of route direction) - wrongMovementDirection = checkWrongMovementDirection(start, routeNodes.get(newCurrentRoute + 1)); - // set/reset evalWaitInterval only if new route is in forward direction - if (wrongMovementDirection) { - evalWaitInterval = 3000; - } else { - evalWaitInterval = Math.max(3000, evalWaitInterval * 3 / 2); - evalWaitInterval = Math.min(evalWaitInterval, 120000); - } - - } - } - - - // trigger voice prompt only if new route is in forward direction - // If route is in wrong direction after one more setLocation it will be recalculated - if (!wrongMovementDirection || newRoute) { - voiceRouter.newRouteIsCalculated(newRoute); - } - } - app.getWaypointHelper().setNewRoute(res); - - app.runInUIThread(new Runnable() { - @Override - public void run() { - ValueHolder showToast = new ValueHolder<>(); - showToast.value = true; - Iterator> it = listeners.iterator(); - while (it.hasNext()) { - WeakReference ref = it.next(); - IRouteInformationListener l = ref.get(); - if (l == null) { - it.remove(); - } else { - l.newRouteIsCalculated(newRoute, showToast); - } - } - if (showToast.value && newRoute && OsmandPlugin.isDevelopment()) { - String msg = app.getString(R.string.new_route_calculated_dist_dbg, - OsmAndFormatter.getFormattedDistance(res.getWholeDistance(), app), - ((int)res.getRoutingTime()) + " sec", - res.getCalculateTime(), res.getVisitedSegments(), res.getLoadedTiles()); - app.showToastMessage(msg); - } - } - }); - } - - public int getLeftDistance(){ + public int getLeftDistance() { return route.getDistanceToFinish(lastFixedLocation); } @@ -899,7 +708,7 @@ public class RoutingHelper { return settings; } - public String getGeneralRouteInformation(){ + public String getGeneralRouteInformation() { int dist = getLeftDistance(); int hours = getLeftTime() / (60 * 60); int minutes = (getLeftTime() / 60) % 60; @@ -907,14 +716,14 @@ public class RoutingHelper { hours, minutes); } - public Location getLocationFromRouteDirection(RouteDirectionInfo i){ + public Location getLocationFromRouteDirection(RouteDirectionInfo i) { return route.getLocationFromRouteDirection(i); } - public synchronized NextDirectionInfo getNextRouteDirectionInfo(NextDirectionInfo info, boolean toSpeak){ + public synchronized NextDirectionInfo getNextRouteDirectionInfo(NextDirectionInfo info, boolean toSpeak) { NextDirectionInfo i = route.getNextRouteDirectionInfo(info, lastProjection, toSpeak); - if(i != null) { - i.imminent = voiceRouter.calculateImminent(i.distanceTo, lastProjection); + if (i != null) { + i.imminent = voiceRouter.calculateImminent(i.distanceTo, lastProjection); } return i; } @@ -923,257 +732,46 @@ public class RoutingHelper { return route.getCurrentMaxSpeed(); } - - public static String formatStreetName(String name, String ref, String destination, String towards) { - String formattedStreetName = ""; - if (ref != null && ref.length() > 0) { - formattedStreetName = ref; - } - if (name != null && name.length() > 0) { - if (formattedStreetName.length() > 0) { - formattedStreetName = formattedStreetName + " "; - } - formattedStreetName = formattedStreetName + name; - } - if (destination != null && destination.length() > 0) { - if (formattedStreetName.length() > 0) { - formattedStreetName = formattedStreetName + " "; - } - formattedStreetName = formattedStreetName + towards + " " + destination; - } - return formattedStreetName.replace(";", ", "); - - } - - - public static class CurrentStreetName { - public String text; - public TurnType turnType; - public boolean showMarker; // turn type has priority over showMarker - public RouteDataObject shieldObject; - public String exitRef; - } - - public synchronized CurrentStreetName getCurrentName(NextDirectionInfo n){ - CurrentStreetName streetName = new CurrentStreetName(); - Location l = lastFixedLocation; - float speed = 0; - if (l != null && l.hasSpeed()) { - speed = l.getSpeed(); - } - boolean isSet = false; - // 1. turn is imminent - if (n.distanceTo > 0 && n.directionInfo != null && !n.directionInfo.getTurnType().isSkipToSpeak() && - voiceRouter.isDistanceLess(speed, n.distanceTo, voiceRouter.PREPARE_DISTANCE * 0.75f)) { - String nm = n.directionInfo.getStreetName(); - String rf = n.directionInfo.getRef(); - String dn = n.directionInfo.getDestinationName(); - isSet = !(Algorithms.isEmpty(nm) && Algorithms.isEmpty(rf) && Algorithms.isEmpty(dn)); - streetName.text = formatStreetName(nm, null, dn, "»"); - streetName.turnType = n.directionInfo.getTurnType(); - streetName.shieldObject = n.directionInfo.getRouteDataObject(); - if (streetName.turnType == null) { - streetName.turnType = TurnType.valueOf(TurnType.C, false); - } - if (n.directionInfo.getExitInfo() != null) { - streetName.exitRef = n.directionInfo.getExitInfo().getRef(); - if (!Algorithms.isEmpty(n.directionInfo.getExitInfo().getExitStreetName())) { - streetName.text = n.directionInfo.getExitInfo().getExitStreetName(); - } - } - } - // 2. display current road street name - if (!isSet) { - RouteSegmentResult rs = getCurrentSegmentResult(); - if (rs != null) { - streetName.text = getRouteSegmentStreetName(rs, false); - if (Algorithms.isEmpty(streetName.text)) { - isSet = !Algorithms.isEmpty(getRouteSegmentStreetName(rs, true)); - } else { - isSet = true; - } - streetName.showMarker = true; - streetName.shieldObject = rs.getObject(); - } - } - // 3. display next road street name if this one empty - if (!isSet) { - RouteSegmentResult rs = getNextStreetSegmentResult(); - if (rs != null) { - streetName.text = getRouteSegmentStreetName(rs, false); - streetName.turnType = TurnType.valueOf(TurnType.C, false); - streetName.shieldObject = rs.getObject(); - } - } - if (streetName.turnType == null) { - streetName.showMarker = true; - } - return streetName; - } - - private String getRouteSegmentStreetName(RouteSegmentResult rs, boolean includeRef) { - String nm = rs.getObject().getName(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get()); - String rf = rs.getObject().getRef(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get(), rs.isForwardDirection()); - String dn = rs.getObject().getDestinationName(settings.MAP_PREFERRED_LOCALE.get(), - settings.MAP_TRANSLITERATE_NAMES.get(), rs.isForwardDirection()); - return formatStreetName(nm, includeRef ? rf : null, dn, "»"); + @NonNull + public synchronized CurrentStreetName getCurrentName(NextDirectionInfo n) { + return CurrentStreetName.getCurrentName(this, n); } public RouteSegmentResult getCurrentSegmentResult() { - return route.getCurrentSegmentResult(); - } + return route.getCurrentSegmentResult(); + } public RouteSegmentResult getNextStreetSegmentResult() { return route.getNextStreetSegmentResult(); } - public List getUpcomingTunnel(float distToStart) { - return route.getUpcomingTunnel(distToStart); - } + public List getUpcomingTunnel(float distToStart) { + return route.getUpcomingTunnel(distToStart); + } - public synchronized NextDirectionInfo getNextRouteDirectionInfoAfter(NextDirectionInfo previous, NextDirectionInfo to, boolean toSpeak){ + public synchronized NextDirectionInfo getNextRouteDirectionInfoAfter(NextDirectionInfo previous, NextDirectionInfo to, boolean toSpeak) { NextDirectionInfo i = route.getNextRouteDirectionInfoAfter(previous, to, toSpeak); - if(i != null) { - i.imminent = voiceRouter.calculateImminent(i.distanceTo, null); + if (i != null) { + i.imminent = voiceRouter.calculateImminent(i.distanceTo, null); } return i; } - public List getRouteDirections(){ + public List getRouteDirections() { return route.getRouteDirections(); } - @Nullable - public QuadRect getRouteRect(@NonNull RouteCalculationResult result) { - QuadRect rect = new QuadRect(0, 0, 0, 0); - Location lt = getLastProjection(); - if (lt == null) { - lt = app.getTargetPointsHelper().getPointToStartLocation(); - } - if (lt == null) { - lt = app.getLocationProvider().getLastKnownLocation(); - } - if (lt != null) { - MapUtils.insetLatLonRect(rect, lt.getLatitude(), lt.getLongitude()); - } - List list = result.getImmutableAllLocations(); - for (Location l : list) { - MapUtils.insetLatLonRect(rect, l.getLatitude(), l.getLongitude()); - } - List targetPoints = app.getTargetPointsHelper().getIntermediatePointsWithTarget(); - for (TargetPoint l : targetPoints) { - MapUtils.insetLatLonRect(rect, l.getLatitude(), l.getLongitude()); - } - - return rect.left == 0 && rect.right == 0 ? null : rect; + public void onSettingsChanged() { + onSettingsChanged(false); } - private class RouteRecalculationThread extends Thread { - - private final RouteCalculationParams params; - private boolean paramsChanged; - private Thread prevRunningJob; - - public RouteRecalculationThread(String name, RouteCalculationParams params, boolean paramsChanged) { - super(name); - this.params = params; - this.paramsChanged = paramsChanged; - if(params.calculationProgress == null) { - params.calculationProgress = new RouteCalculationProgress(); - } - } - - public boolean isParamsChanged() { - return paramsChanged; - } - - public void stopCalculation(){ - params.calculationProgress.isCancelled = true; - } - - - @Override - public void run() { - synchronized (RoutingHelper.this) { - routeWasFinished = false; - currentRunningJob = this; - waitingNextJob = prevRunningJob != null; - } - if(prevRunningJob != null) { - while(prevRunningJob.isAlive()){ - try { - Thread.sleep(50); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - synchronized (RoutingHelper.this) { - currentRunningJob = this; - waitingNextJob = false; - } - } - lastRouteCalcError = null; - lastRouteCalcErrorShort = null; - RouteCalculationResult res = provider.calculateRouteImpl(params); - if (params.calculationProgress.isCancelled) { - synchronized (RoutingHelper.this) { - currentRunningJob = null; - } - return; - } - final boolean onlineSourceWithoutInternet = !res.isCalculated() && - params.mode.getRouteService().isOnline() && !settings.isInternetConnectionAvailable(); - if (onlineSourceWithoutInternet && settings.GPX_ROUTE_CALC_OSMAND_PARTS.get()) { - if (params.previousToRecalculate != null && params.previousToRecalculate.isCalculated()) { - res = provider.recalculatePartOfflineRoute(res, params); - } - } - RouteCalculationResult prev = route; - synchronized (RoutingHelper.this) { - if (res.isCalculated()) { - if (!params.inSnapToRoadMode && !params.inPublicTransportMode) { - route = res; - updateOriginalRoute(); - } - if (params.resultListener != null) { - params.resultListener.onRouteCalculated(res); - } - } else { - evalWaitInterval = Math.max(3000, evalWaitInterval * 3 / 2); // for Issue #3899 - evalWaitInterval = Math.min(evalWaitInterval, 120000); - } - currentRunningJob = null; - } - if(res.isCalculated()){ - if (!params.inSnapToRoadMode && !params.inPublicTransportMode) { - setNewRoute(prev, res, params.start); - } - } else if (onlineSourceWithoutInternet) { - lastRouteCalcError = app.getString(R.string.error_calculating_route) - + ":\n" + app.getString(R.string.internet_connection_required_for_online_route); - lastRouteCalcErrorShort = app.getString(R.string.error_calculating_route); - showMessage(lastRouteCalcError); //$NON-NLS-1$ - } else { - if (res.getErrorMessage() != null) { - lastRouteCalcError = app.getString(R.string.error_calculating_route) + ":\n" + res.getErrorMessage(); - lastRouteCalcErrorShort = app.getString(R.string.error_calculating_route); - showMessage(lastRouteCalcError); //$NON-NLS-1$ - } else { - lastRouteCalcError = app.getString(R.string.empty_route_calculated); - lastRouteCalcErrorShort = app.getString(R.string.empty_route_calculated); - showMessage(lastRouteCalcError); - } - } - app.getNotificationHelper().refreshNotification(NAVIGATION); - lastTimeEvaluatedRoute = System.currentTimeMillis(); - } - - public void setWaitPrevJob(Thread prevRunningJob) { - this.prevRunningJob = prevRunningJob; + public void onSettingsChanged(boolean forceRouteRecalculation) { + if (forceRouteRecalculation || isRouteCalculated() || isRouteBeingCalculated()) { + recalculateRouteDueToSettingsChange(); } } - public void recalculateRouteDueToSettingsChange() { + private void recalculateRouteDueToSettingsChange() { clearCurrentRoute(finalLocation, intermediatePoints); if (isPublicTransportMode()) { Location start = lastFixedLocation; @@ -1186,140 +784,19 @@ public class RoutingHelper { transportRoutingHelper.recalculateRouteDueToSettingsChange(); } } else { - recalculateRouteInBackground(lastFixedLocation, finalLocation, intermediatePoints, currentGPXRoute, route, true, false); + routeRecalculationHelper.recalculateRouteInBackground(lastFixedLocation, finalLocation, + intermediatePoints, currentGPXRoute, route, true, false); } } - private void recalculateRouteInBackground(final Location start, final LatLon end, final List intermediates, - final GPXRouteParamsBuilder gpxRoute, final RouteCalculationResult previousRoute, boolean paramsChanged, boolean onlyStartPointChanged){ - if (start == null || end == null) { - return; - } - // do not evaluate very often - if ((currentRunningJob == null && System.currentTimeMillis() - lastTimeEvaluatedRoute > evalWaitInterval) - || paramsChanged || !onlyStartPointChanged) { - if(System.currentTimeMillis() - lastTimeEvaluatedRoute < RECALCULATE_THRESHOLD_CAUSING_FULL_RECALCULATE_INTERVAL) { - recalculateCountInInterval ++; - } - final RouteCalculationParams params = new RouteCalculationParams(); - params.start = start; - params.end = end; - params.intermediates = intermediates; - params.gpxRoute = gpxRoute == null ? null : gpxRoute.build(app); - params.onlyStartPointChanged = onlyStartPointChanged; - if (recalculateCountInInterval < RECALCULATE_THRESHOLD_COUNT_CAUSING_FULL_RECALCULATE - || (gpxRoute != null && gpxRoute.isPassWholeRoute() && isDeviatedFromRoute)) { - params.previousToRecalculate = previousRoute; - } else { - recalculateCountInInterval = 0; - } - params.leftSide = settings.DRIVING_REGION.get().leftHandDriving; - params.fast = settings.FAST_ROUTE_MODE.getModeValue(mode); - params.mode = mode; - params.ctx = app; - boolean updateProgress = false; - if (params.mode.getRouteService() == RouteService.OSMAND) { - params.calculationProgress = new RouteCalculationProgress(); - updateProgress = true; - } else { - params.resultListener = new RouteCalculationParams.RouteCalculationResultListener() { - @Override - public void onRouteCalculated(RouteCalculationResult route) { - app.runInUIThread(new Runnable() { - - @Override - public void run() { - finishProgress(params); - } - }); - } - }; - } - if (lastProjection != null) { - params.currentLocation = lastFixedLocation; - } - startRouteCalculationThread(params, paramsChanged, updateProgress); - } - } - - private void updateOriginalRoute() { + void updateOriginalRoute() { if (originalRoute == null) { originalRoute = route; } } - public void startRouteCalculationThread(RouteCalculationParams params, boolean paramsChanged, boolean updateProgress) { - synchronized (this) { - final Thread prevRunningJob = currentRunningJob; - getSettings().LAST_ROUTE_APPLICATION_MODE.set(getAppMode()); - RouteRecalculationThread newThread = new RouteRecalculationThread( - "Calculating route", params, paramsChanged); //$NON-NLS-1$ - currentRunningJob = newThread; - startProgress(params); - if (updateProgress) { - updateProgress(params); - } - if (prevRunningJob != null) { - newThread.setWaitPrevJob(prevRunningJob); - } - currentRunningJob.start(); - } - } - - private void startProgress(final RouteCalculationParams params) { - if (params.calculationProgressCallback != null) { - params.calculationProgressCallback.start(); - } else if (progressRoute != null) { - progressRoute.start(); - } - } - - private void updateProgress(final RouteCalculationParams params) { - final RouteCalculationProgressCallback progressRoute; - if (params.calculationProgressCallback != null) { - progressRoute = params.calculationProgressCallback; - } else { - progressRoute = this.progressRoute; - } - if (progressRoute != null ) { - app.runInUIThread(new Runnable() { - - @Override - public void run() { - RouteCalculationProgress calculationProgress = params.calculationProgress; - if (isRouteBeingCalculated()) { - Thread t = currentRunningJob; - if(t instanceof RouteRecalculationThread && ((RouteRecalculationThread) t).params != params) { - // different calculation started - return; - } else { - progressRoute.updateProgress((int) calculationProgress.getLinearProgress()); - if (calculationProgress.requestPrivateAccessRouting) { - progressRoute.requestPrivateAccessRouting(); - } - updateProgress(params); - } - } else { - if (calculationProgress.requestPrivateAccessRouting) { - progressRoute.requestPrivateAccessRouting(); - } - progressRoute.finish(); - } - } - }, 300); - } - } - - private void finishProgress(RouteCalculationParams params) { - final RouteCalculationProgressCallback progressRoute; - if (params.calculationProgressCallback != null) { - progressRoute = params.calculationProgressCallback; - } else { - progressRoute = this.progressRoute; - } - if (progressRoute != null ) { - progressRoute.finish(); - } + public void startRouteCalculationThread(RouteCalculationParams params) { + routeRecalculationHelper.startRouteCalculationThread(params, true, true); } public static void applyApplicationSettings(RouteCalculationParams params, OsmandSettings settings, ApplicationMode mode) { @@ -1328,18 +805,7 @@ public class RoutingHelper { } public void setProgressBar(RouteCalculationProgressCallback progressRoute) { - this.progressRoute = progressRoute; - } - - public interface RouteCalculationProgressCallback { - - void start(); - - void updateProgress(int progress); - - void requestPrivateAccessRouting(); - - void finish(); + routeRecalculationHelper.setProgressBar(progressRoute); } public boolean isPublicTransportMode() { @@ -1355,10 +821,10 @@ public class RoutingHelper { } public boolean isRouteBeingCalculated() { - return currentRunningJob instanceof RouteRecalculationThread || waitingNextJob; + return routeRecalculationHelper.isRouteBeingCalculated(); } - private void showMessage(final String msg){ + private void showMessage(final String msg) { app.runInUIThread(new Runnable() { @Override public void run() { @@ -1367,8 +833,6 @@ public class RoutingHelper { }); } - - // NEVER returns null @NonNull public RouteCalculationResult getRoute() { return route; @@ -1396,58 +860,7 @@ public class RoutingHelper { public void notifyIfRouteIsCalculated() { if (route.isCalculated()) { - voiceRouter.newRouteIsCalculated(true) ; + voiceRouter.newRouteIsCalculated(true); } } - - public static class RouteSegmentSearchResult { - private int roadIndex; - private int segmentIndex; - private QuadPoint point; - - private RouteSegmentSearchResult(int roadIndex, int segmentIndex, QuadPoint point) { - this.roadIndex = roadIndex; - this.segmentIndex = segmentIndex; - this.point = point; - } - - public int getRoadIndex() { - return roadIndex; - } - - public int getSegmentIndex() { - return segmentIndex; - } - - public QuadPoint getPoint() { - return point; - } - } - - public static RouteSegmentSearchResult searchRouteSegment(double latitude, double longitude, double maxDist, List roads) { - int roadIndex = -1; - int segmentIndex = -1; - QuadPoint point = null; - int px = MapUtils.get31TileNumberX(longitude); - int py = MapUtils.get31TileNumberY(latitude); - double dist = maxDist < 0 ? 1000 : maxDist; - for (int i = 0; i < roads.size(); i++) { - RouteSegmentResult road = roads.get(i); - int startPointIndex = road.getStartPointIndex() < road.getEndPointIndex() ? road.getStartPointIndex() : road.getEndPointIndex(); - int endPointIndex = road.getEndPointIndex() > road.getStartPointIndex() ? road.getEndPointIndex() : road.getStartPointIndex(); - RouteDataObject obj = road.getObject(); - for (int j = startPointIndex + 1; j <= endPointIndex; j++) { - QuadPoint proj = MapUtils.getProjectionPoint31(px, py, obj.getPoint31XTile(j - 1), obj.getPoint31YTile(j - 1), - obj.getPoint31XTile(j), obj.getPoint31YTile(j)); - double dd = MapUtils.squareRootDist31((int) proj.x, (int) proj.y, px, py); - if (dd < dist) { - dist = dd; - roadIndex = i; - segmentIndex = j; - point = proj; - } - } - } - return roadIndex != -1 ? new RouteSegmentSearchResult(roadIndex, segmentIndex, point) : null; - } } diff --git a/OsmAnd/src/net/osmand/plus/routing/RoutingHelperUtils.java b/OsmAnd/src/net/osmand/plus/routing/RoutingHelperUtils.java new file mode 100644 index 0000000000..c696c13585 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelperUtils.java @@ -0,0 +1,210 @@ +package net.osmand.plus.routing; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import net.osmand.Location; +import net.osmand.data.LatLon; +import net.osmand.data.QuadRect; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.TargetPointsHelper; +import net.osmand.plus.helpers.enums.MetricsConstants; +import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.util.MapUtils; + +import java.util.List; + +public class RoutingHelperUtils { + + private static final float POSITION_TOLERANCE = 60; + private static final int CACHE_RADIUS = 100000; + + @NonNull + public static String formatStreetName(String name, String ref, String destination, String towards) { + String formattedStreetName = ""; + if (ref != null && ref.length() > 0) { + formattedStreetName = ref; + } + if (name != null && name.length() > 0) { + if (formattedStreetName.length() > 0) { + formattedStreetName = formattedStreetName + " "; + } + formattedStreetName = formattedStreetName + name; + } + if (destination != null && destination.length() > 0) { + if (formattedStreetName.length() > 0) { + formattedStreetName = formattedStreetName + " "; + } + formattedStreetName = formattedStreetName + towards + " " + destination; + } + return formattedStreetName.replace(";", ", "); + } + + @Nullable + public static QuadRect getRouteRect(@NonNull OsmandApplication app, @NonNull RouteCalculationResult result) { + QuadRect rect = new QuadRect(0, 0, 0, 0); + Location lt = app.getRoutingHelper().getLastProjection(); + if (lt == null) { + lt = app.getTargetPointsHelper().getPointToStartLocation(); + } + if (lt == null) { + lt = app.getLocationProvider().getLastKnownLocation(); + } + if (lt != null) { + MapUtils.insetLatLonRect(rect, lt.getLatitude(), lt.getLongitude()); + } + List list = result.getImmutableAllLocations(); + for (Location l : list) { + MapUtils.insetLatLonRect(rect, l.getLatitude(), l.getLongitude()); + } + List targetPoints = app.getTargetPointsHelper().getIntermediatePointsWithTarget(); + for (TargetPointsHelper.TargetPoint l : targetPoints) { + MapUtils.insetLatLonRect(rect, l.getLatitude(), l.getLongitude()); + } + + return rect.left == 0 && rect.right == 0 ? null : rect; + } + + static LatLon getProject(Location loc, Location from, Location to) { + return MapUtils.getProjection(loc.getLatitude(), + loc.getLongitude(), from.getLatitude(), from.getLongitude(), + to.getLatitude(), to.getLongitude()); + } + + static double getOrthogonalDistance(Location loc, Location from, Location to) { + return MapUtils.getOrthogonalDistance(loc.getLatitude(), + loc.getLongitude(), from.getLatitude(), from.getLongitude(), + to.getLatitude(), to.getLongitude()); + } + + static int lookAheadFindMinOrthogonalDistance(Location currentLocation, List routeNodes, int currentRoute, int iterations) { + double newDist; + double dist = Double.POSITIVE_INFINITY; + int index = currentRoute; + while (iterations > 0 && currentRoute + 1 < routeNodes.size()) { + newDist = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute), routeNodes.get(currentRoute + 1)); + if (newDist < dist) { + index = currentRoute; + dist = newDist; + } + currentRoute++; + iterations--; + } + return index; + } + + public static float getPosTolerance(float accuracy) { + if (accuracy > 0) { + return POSITION_TOLERANCE / 2 + accuracy; + } + return POSITION_TOLERANCE; + } + + public static float getDefaultAllowedDeviation(OsmandSettings settings, ApplicationMode mode, float posTolerance) { + if (settings.DISABLE_OFFROUTE_RECALC.getModeValue(mode)) { + return -1.0f; + } else if (mode.getRouteService() == RouteProvider.RouteService.DIRECT_TO) { + return -1.0f; + } else if (mode.getRouteService() == RouteProvider.RouteService.STRAIGHT) { + MetricsConstants mc = settings.METRIC_SYSTEM.getModeValue(mode); + if (mc == MetricsConstants.KILOMETERS_AND_METERS || mc == MetricsConstants.MILES_AND_METERS) { + return 500.f; + } else { + // 1/4 mile + return 482.f; + } + } + return posTolerance * RoutingHelper.ALLOWED_DEVIATION; + } + + /** + * Wrong movement direction is considered when between + * current location bearing (determines by 2 last fixed position or provided) + * and bearing from currentLocation to next (current) point + * the difference is more than 60 degrees + */ + public static boolean checkWrongMovementDirection(Location currentLocation, Location nextRouteLocation) { + // measuring without bearing could be really error prone (with last fixed location) + // this code has an effect on route recalculation which should be detected without mistakes + if (currentLocation.hasBearing() && nextRouteLocation != null) { + float bearingMotion = currentLocation.getBearing(); + float bearingToRoute = currentLocation.bearingTo(nextRouteLocation); + double diff = MapUtils.degreesDiff(bearingMotion, bearingToRoute); + if (Math.abs(diff) > 60f) { + // require delay interval since first detection, to avoid false positive + //but leave out for now, as late detection is worse than false positive (it may reset voice router then cause bogus turn and u-turn prompting) + //if (wrongMovementDetected == 0) { + // wrongMovementDetected = System.currentTimeMillis(); + //} else if ((System.currentTimeMillis() - wrongMovementDetected > 500)) { + return true; + //} + } else { + //wrongMovementDetected = 0; + return false; + } + } + //wrongMovementDetected = 0; + return false; + } + + static boolean identifyUTurnIsNeeded(@NonNull RoutingHelper routingHelper, @NonNull Location currentLocation, double posTolerance) { + RouteCalculationResult route = routingHelper.getRoute(); + if (routingHelper.getFinalLocation() == null || currentLocation == null || !route.isCalculated() || routingHelper.isPublicTransportMode()) { + return false; + } + boolean isOffRoute = false; + if (currentLocation.hasBearing()) { + float bearingMotion = currentLocation.getBearing(); + Location nextRoutePosition = route.getNextRouteLocation(); + float bearingToRoute = currentLocation.bearingTo(nextRoutePosition); + double diff = MapUtils.degreesDiff(bearingMotion, bearingToRoute); + // 7. Check if you left the route and an unscheduled U-turn would bring you back (also Issue 863) + // This prompt is an interim advice and does only sound if a new route in forward direction could not be found in x seconds + if (Math.abs(diff) > 135f) { + float d = currentLocation.distanceTo(nextRoutePosition); + // 60m tolerance to allow for GPS inaccuracy + if (d > posTolerance) { + // require x sec continuous since first detection + long deviateFromRouteDetected = routingHelper.getDeviateFromRouteDetected(); + if (deviateFromRouteDetected == 0) { + routingHelper.setDeviateFromRouteDetected(System.currentTimeMillis()); + } else if ((System.currentTimeMillis() - deviateFromRouteDetected > 10000)) { + isOffRoute = true; + //log.info("bearingMotion is opposite to bearingRoute"); //$NON-NLS-1$ + } + } + } else { + routingHelper.setDeviateFromRouteDetected(0); + } + } + return isOffRoute; + } + + static float getArrivalDistance(ApplicationMode mode, OsmandSettings settings) { + ApplicationMode m = mode == null ? settings.getApplicationMode() : mode; + float defaultSpeed = Math.max(0.3f, m.getDefaultSpeed()); + + /// Used to be: car - 90 m, bicycle - 50 m, pedestrian - 20 m + // return ((float)settings.getApplicationMode().getArrivalDistance()) * settings.ARRIVAL_DISTANCE_FACTOR.getModeValue(m); + // GPS_TOLERANCE - 12 m + // 5 seconds: car - 80 m @ 50 kmh, bicyle - 45 m @ 25 km/h, bicyle - 25 m @ 10 km/h, pedestrian - 18 m @ 4 km/h, + return RoutingHelper.GPS_TOLERANCE + defaultSpeed * 5 * RoutingHelper.ARRIVAL_DISTANCE_FACTOR; + } + + public static void checkAndUpdateStartLocation(@NonNull OsmandApplication app, LatLon newStartLocation) { + if (newStartLocation != null) { + LatLon lastStartLocation = app.getSettings().getLastStartPoint(); + if (lastStartLocation == null || MapUtils.getDistance(newStartLocation, lastStartLocation) > CACHE_RADIUS) { + app.getMapViewTrackingUtilities().detectDrivingRegion(newStartLocation); + app.getSettings().setLastStartPoint(newStartLocation); + } + } + } + + public static void checkAndUpdateStartLocation(@NonNull OsmandApplication app, Location nextStartLocation) { + if (nextStartLocation != null) { + checkAndUpdateStartLocation(app, new LatLon(nextStartLocation.getLatitude(), nextStartLocation.getLongitude())); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java index 4fa70f4c9f..b5a90da2ce 100644 --- a/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java @@ -22,7 +22,6 @@ import net.osmand.plus.R; import net.osmand.plus.render.NativeOsmandLibrary; import net.osmand.plus.routing.RouteCalculationParams.RouteCalculationResultListener; import net.osmand.plus.routing.RouteProvider.RouteService; -import net.osmand.plus.routing.RoutingHelper.RouteCalculationProgressCallback; import net.osmand.router.GeneralRouter; import net.osmand.router.RouteCalculationProgress; @@ -564,7 +563,7 @@ public class TransportRoutingHelper { updateProgress(0); RouteCalculationParams walkingRouteParams = getWalkingRouteParams(); if (walkingRouteParams != null) { - routingHelper.startRouteCalculationThread(walkingRouteParams, true, true); + routingHelper.startRouteCalculationThread(walkingRouteParams); } } } @@ -603,7 +602,7 @@ public class TransportRoutingHelper { } RouteCalculationParams walkingRouteParams = getWalkingRouteParams(); if (walkingRouteParams != null) { - routingHelper.startRouteCalculationThread(walkingRouteParams, true, true); + routingHelper.startRouteCalculationThread(walkingRouteParams); // wait until all segments calculated while (!walkingSegmentsCalculated) { try { diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/RecalculateRouteInDeviationBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/RecalculateRouteInDeviationBottomSheet.java index 99fb5fa73a..40f6889397 100644 --- a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/RecalculateRouteInDeviationBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/RecalculateRouteInDeviationBottomSheet.java @@ -15,6 +15,7 @@ import com.google.android.material.slider.Slider; import net.osmand.AndroidUtils; import net.osmand.plus.helpers.enums.MetricsConstants; +import net.osmand.plus.routing.RoutingHelperUtils; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; @@ -28,7 +29,6 @@ import net.osmand.plus.base.bottomsheetmenu.simpleitems.LongDescriptionItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.SubtitmeListDividerItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; -import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.settings.fragments.ApplyQueryType; import net.osmand.plus.settings.fragments.OnConfirmPreferenceChange; import net.osmand.plus.settings.preferences.SwitchPreferenceEx; @@ -207,8 +207,8 @@ public class RecalculateRouteInDeviationBottomSheet extends BooleanPreferenceBot } private void getDefaultValue() { - currentValue = RoutingHelper.getDefaultAllowedDeviation(settings, appMode, - RoutingHelper.getPosTolerance(0)); + currentValue = RoutingHelperUtils.getDefaultAllowedDeviation(settings, appMode, + RoutingHelperUtils.getPosTolerance(0)); } private int findIndexOfValue(float allowedValue) { diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/RouteParametersFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/RouteParametersFragment.java index 00f0960dfe..88e2a4f957 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/RouteParametersFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/RouteParametersFragment.java @@ -33,6 +33,7 @@ import net.osmand.plus.UiUtilities; import net.osmand.plus.Version; import net.osmand.plus.routing.RouteProvider; import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.routing.RoutingHelperUtils; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.BooleanPreference; import net.osmand.plus.settings.backend.CommonPreference; @@ -432,8 +433,8 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP mode.setStrAngle(angleValue[0]); updateAllSettings(); RoutingHelper routingHelper = app.getRoutingHelper(); - if (mode.equals(routingHelper.getAppMode()) && (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated())) { - routingHelper.recalculateRouteDueToSettingsChange(); + if (mode.equals(routingHelper.getAppMode())) { + routingHelper.onSettingsChanged(); } } }); @@ -481,7 +482,7 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP float allowedValue = settings.ROUTE_RECALCULATION_DISTANCE.getModeValue(appMode); boolean enabled = allowedValue != DISABLE_MODE; if (allowedValue <= 0) { - allowedValue = RoutingHelper.getDefaultAllowedDeviation(settings, appMode, RoutingHelper.getPosTolerance(0)); + allowedValue = RoutingHelperUtils.getDefaultAllowedDeviation(settings, appMode, RoutingHelperUtils.getPosTolerance(0)); } String summary = String.format(getString(R.string.ltr_or_rtl_combine_via_bold_point), enabled ? getString(R.string.shared_string_enabled) : getString(R.string.shared_string_disabled), @@ -644,9 +645,8 @@ public class RouteParametersFragment extends BaseSettingsFragment implements OnP private static void recalculateRoute(OsmandApplication app, ApplicationMode mode) { RoutingHelper routingHelper = app.getRoutingHelper(); - if (mode.equals(routingHelper.getAppMode()) - && (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated())) { - routingHelper.recalculateRouteDueToSettingsChange(); + if (mode.equals(routingHelper.getAppMode())) { + routingHelper.onSettingsChanged(); } } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/VehicleParametersFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/VehicleParametersFragment.java index 738c44de35..a70dbca171 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/VehicleParametersFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/VehicleParametersFragment.java @@ -194,9 +194,8 @@ public class VehicleParametersFragment extends BaseSettingsFragment implements O private void recalculateRoute() { RoutingHelper routingHelper = app.getRoutingHelper(); - if (getSelectedAppMode().equals(routingHelper.getAppMode()) - && (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated())) { - routingHelper.recalculateRouteDueToSettingsChange(); + if (getSelectedAppMode().equals(routingHelper.getAppMode())) { + routingHelper.onSettingsChanged(); } } @@ -269,8 +268,8 @@ public class VehicleParametersFragment extends BaseSettingsFragment implements O mode.setMaxSpeed(maxValue[0] / ratio[0]); } RoutingHelper routingHelper = app.getRoutingHelper(); - if (mode.equals(routingHelper.getAppMode()) && (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated())) { - routingHelper.recalculateRouteDueToSettingsChange(); + if (mode.equals(routingHelper.getAppMode())) { + routingHelper.onSettingsChanged(); } } }); @@ -284,8 +283,8 @@ public class VehicleParametersFragment extends BaseSettingsFragment implements O mode.setMaxSpeed(0f); } RoutingHelper routingHelper = app.getRoutingHelper(); - if (mode.equals(routingHelper.getAppMode()) && (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated())) { - routingHelper.recalculateRouteDueToSettingsChange(); + if (mode.equals(routingHelper.getAppMode())) { + routingHelper.onSettingsChanged(); } } }); diff --git a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java index e7cc9b4466..f73a504dfb 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java @@ -497,7 +497,7 @@ public class MapControlsLayer extends OsmandMapLayer { if (object instanceof SelectedGpxPoint && !((SelectedGpxPoint) object).getSelectedGpxFile().isShowCurrentTrack()) { GPXFile gpxFile = ((SelectedGpxPoint) object).getSelectedGpxFile().getGpxFile(); mapActivity.getMapActions().enterRoutePlanningModeGivenGpx(gpxFile, null, null, true, true, MenuState.HEADER_ONLY); - routingHelper.recalculateRouteDueToSettingsChange(); + routingHelper.onSettingsChanged(true); menu.close(); } else { if (routingHelper.isFollowingMode() || routingHelper.isRoutePlanningMode()) { diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java index d8101b487d..fca0ae429e 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java @@ -49,6 +49,8 @@ import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmAndLocationProvider; import net.osmand.plus.OsmAndLocationProvider.GPSInfo; import net.osmand.plus.OsmandApplication; +import net.osmand.plus.routing.CurrentStreetName; +import net.osmand.plus.routing.RoutingHelperUtils; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; @@ -933,7 +935,7 @@ public class MapInfoWidgetsFactory { public boolean updateInfo(DrawSettings d) { - RoutingHelper.CurrentStreetName streetName = null; + CurrentStreetName streetName = null; boolean showClosestWaypointFirstInAddress = true; if (routingHelper != null && routingHelper.isRouteCalculated() && !routingHelper.isDeviatedFromRoute()) { if (routingHelper.isFollowingMode()) { @@ -953,11 +955,11 @@ public class MapInfoWidgetsFactory { } } else if (map.getMapViewTrackingUtilities().isMapLinkedToLocation() && settings.SHOW_STREET_NAME.get()) { - streetName = new RoutingHelper.CurrentStreetName(); + streetName = new CurrentStreetName(); RouteDataObject rt = locationProvider.getLastKnownRouteSegment(); if (rt != null) { Location lastKnownLocation = locationProvider.getLastKnownLocation(); - streetName.text = RoutingHelper.formatStreetName( + streetName.text = RoutingHelperUtils.formatStreetName( rt.getName(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get()), rt.getRef(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get(), rt.bearingVsRouteDirection(lastKnownLocation)), rt.getDestinationName(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get(), rt.bearingVsRouteDirection(lastKnownLocation)),