Merge remote-tracking branch 'origin/RoutePreparationMenu' into RoutePreparationMenu

This commit is contained in:
Chumva 2018-11-28 19:28:35 +02:00
commit 1a440d73b5
16 changed files with 671 additions and 72 deletions

View file

@ -10,6 +10,7 @@
- For wording and consistency, please note https://osmand.net/help-online?id=technical-articles#Creating_a_Consistent_User_Experience - For wording and consistency, please note https://osmand.net/help-online?id=technical-articles#Creating_a_Consistent_User_Experience
Thx - Hardy Thx - Hardy
--> -->
<string name="app_mode_public_transport">Public transport</string>
<string name="avoid_roads_descr">Select road on the map or from the list below that you want to avoid during navigation:</string> <string name="avoid_roads_descr">Select road on the map or from the list below that you want to avoid during navigation:</string>
<string name="show_along_the_route">Show along the route</string> <string name="show_along_the_route">Show along the route</string>
<string name="simulate_navigation">Simulate navigation</string> <string name="simulate_navigation">Simulate navigation</string>

View file

@ -44,6 +44,7 @@ import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.resources.ResourceManager; import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper;
import net.osmand.plus.search.QuickSearchHelper; import net.osmand.plus.search.QuickSearchHelper;
import net.osmand.plus.views.corenative.NativeCoreContext; import net.osmand.plus.views.corenative.NativeCoreContext;
import net.osmand.plus.voice.CommandPlayer; import net.osmand.plus.voice.CommandPlayer;
@ -458,6 +459,7 @@ public class AppInitializer implements IProgress {
app.applyTheme(app); app.applyTheme(app);
app.inAppPurchaseHelper = startupInit(new InAppPurchaseHelper(app), InAppPurchaseHelper.class); app.inAppPurchaseHelper = startupInit(new InAppPurchaseHelper(app), InAppPurchaseHelper.class);
app.poiTypes = startupInit(MapPoiTypes.getDefaultNoInit(), MapPoiTypes.class); app.poiTypes = startupInit(MapPoiTypes.getDefaultNoInit(), MapPoiTypes.class);
app.transportRoutingHelper = startupInit(new TransportRoutingHelper(app), TransportRoutingHelper.class);
app.routingHelper = startupInit(new RoutingHelper(app), RoutingHelper.class); app.routingHelper = startupInit(new RoutingHelper(app), RoutingHelper.class);
app.resourceManager = startupInit(new ResourceManager(app), ResourceManager.class); app.resourceManager = startupInit(new ResourceManager(app), ResourceManager.class);
app.daynightHelper = startupInit(new DayNightHelper(app), DayNightHelper.class); app.daynightHelper = startupInit(new DayNightHelper(app), DayNightHelper.class);

View file

@ -57,6 +57,9 @@ public class ApplicationMode {
public static final ApplicationMode TRAIN = create(R.string.app_mode_train, "train").speed(25f, 40). public static final ApplicationMode TRAIN = create(R.string.app_mode_train, "train").speed(25f, 40).
carLocation().icon(R.drawable.map_action_train, R.drawable.ic_action_train).reg(); carLocation().icon(R.drawable.map_action_train, R.drawable.ic_action_train).reg();
public static final ApplicationMode PUBLIC_TRANSPORT = create(R.string.app_mode_public_transport, "public_transport").
icon(R.drawable.map_action_bus_dark, R.drawable.ic_action_bus_dark).reg();
static { static {
ApplicationMode[] exceptDefault = new ApplicationMode[]{CAR, PEDESTRIAN, BICYCLE, BOAT, AIRCRAFT, BUS, TRAIN}; ApplicationMode[] exceptDefault = new ApplicationMode[]{CAR, PEDESTRIAN, BICYCLE, BOAT, AIRCRAFT, BUS, TRAIN};
ApplicationMode[] exceptPedestrianAndDefault = new ApplicationMode[]{CAR, BICYCLE, BOAT, AIRCRAFT, BUS, TRAIN}; ApplicationMode[] exceptPedestrianAndDefault = new ApplicationMode[]{CAR, BICYCLE, BOAT, AIRCRAFT, BUS, TRAIN};

View file

@ -57,6 +57,7 @@ import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.resources.ResourceManager; import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper;
import net.osmand.plus.search.QuickSearchHelper; import net.osmand.plus.search.QuickSearchHelper;
import net.osmand.plus.voice.CommandPlayer; import net.osmand.plus.voice.CommandPlayer;
import net.osmand.plus.wikivoyage.data.TravelDbHelper; import net.osmand.plus.wikivoyage.data.TravelDbHelper;
@ -106,6 +107,7 @@ public class OsmandApplication extends MultiDexApplication {
PoiFiltersHelper poiFilters; PoiFiltersHelper poiFilters;
MapPoiTypes poiTypes; MapPoiTypes poiTypes;
RoutingHelper routingHelper; RoutingHelper routingHelper;
TransportRoutingHelper transportRoutingHelper;
FavouritesDbHelper favorites; FavouritesDbHelper favorites;
CommandPlayer player; CommandPlayer player;
GpxSelectionHelper selectedGpxHelper; GpxSelectionHelper selectedGpxHelper;
@ -402,6 +404,10 @@ public class OsmandApplication extends MultiDexApplication {
return routingHelper; return routingHelper;
} }
public TransportRoutingHelper getTransportRoutingHelper() {
return transportRoutingHelper;
}
public RoutingOptionsHelper getRoutingOptionsHelper() { public RoutingOptionsHelper getRoutingOptionsHelper() {
return routingOptionsHelper; return routingOptionsHelper;
} }

View file

@ -379,8 +379,8 @@ public class TargetPointsHelper {
} }
public void updateRouteAndRefresh(boolean updateRoute) { public void updateRouteAndRefresh(boolean updateRoute) {
if(updateRoute && ( routingHelper.isRouteBeingCalculated() || routingHelper.isRouteCalculated() || if(updateRoute && (routingHelper.isPublicTransportMode() || routingHelper.isRouteBeingCalculated() ||
routingHelper.isFollowingMode() || routingHelper.isRoutePlanningMode())) { routingHelper.isRouteCalculated() || routingHelper.isFollowingMode() || routingHelper.isRoutePlanningMode())) {
updateRoutingHelper(); updateRoutingHelper();
} }
updateListeners(); updateListeners();
@ -388,15 +388,14 @@ public class TargetPointsHelper {
private void updateRoutingHelper() { private void updateRoutingHelper() {
LatLon start = settings.getPointToStart(); LatLon start = settings.getPointToStart();
Location lastKnownLocation = ctx.getLocationProvider().getLastKnownLocation(); LatLon finish = settings.getPointToNavigate();
List<LatLon> is = getIntermediatePointsLatLonNavigation(); List<LatLon> is = getIntermediatePointsLatLonNavigation();
Location lastKnownLocation = ctx.getLocationProvider().getLastKnownLocation();
if((routingHelper.isFollowingMode() && lastKnownLocation != null) || start == null) { if((routingHelper.isFollowingMode() && lastKnownLocation != null) || start == null) {
routingHelper.setFinalAndCurrentLocation(settings.getPointToNavigate(), routingHelper.setFinalAndCurrentLocation(finish, is, lastKnownLocation);
is, lastKnownLocation);
} else { } else {
Location loc = wrap(start); Location loc = wrap(start);
routingHelper.setFinalAndCurrentLocation(settings.getPointToNavigate(), routingHelper.setFinalAndCurrentLocation(finish, is, loc);
is, loc);
} }
} }

View file

@ -110,9 +110,11 @@ import net.osmand.plus.measurementtool.MeasurementToolFragment;
import net.osmand.plus.measurementtool.NewGpxData; import net.osmand.plus.measurementtool.NewGpxData;
import net.osmand.plus.render.RendererRegistry; import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.resources.ResourceManager; import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.routing.IRouteInformationListener;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.RoutingHelper.IRouteInformationListener;
import net.osmand.plus.routing.RoutingHelper.RouteCalculationProgressCallback; import net.osmand.plus.routing.RoutingHelper.RouteCalculationProgressCallback;
import net.osmand.plus.routing.TransportRoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper.TransportRouteCalculationProgressCallback;
import net.osmand.plus.search.QuickSearchDialogFragment; import net.osmand.plus.search.QuickSearchDialogFragment;
import net.osmand.plus.search.QuickSearchDialogFragment.QuickSearchTab; import net.osmand.plus.search.QuickSearchDialogFragment.QuickSearchTab;
import net.osmand.plus.search.QuickSearchDialogFragment.QuickSearchType; import net.osmand.plus.search.QuickSearchDialogFragment.QuickSearchType;
@ -439,7 +441,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
private void createProgressBarForRouting() { private void createProgressBarForRouting() {
final ProgressBar pb = (ProgressBar) findViewById(R.id.map_horizontal_progress); final ProgressBar pb = (ProgressBar) findViewById(R.id.map_horizontal_progress);
app.getRoutingHelper().setProgressBar(new RouteCalculationProgressCallback() { final RouteCalculationProgressCallback progressCallback = new RouteCalculationProgressCallback() {
@Override @Override
public void start() { public void start() {
@ -501,6 +503,25 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
dashboardOnMap.routeCalculationFinished(); dashboardOnMap.routeCalculationFinished();
pb.setVisibility(View.GONE); pb.setVisibility(View.GONE);
} }
};
app.getRoutingHelper().setProgressBar(progressCallback);
app.getTransportRoutingHelper().setProgressBar(new TransportRouteCalculationProgressCallback() {
@Override
public void start() {
progressCallback.start();
}
@Override
public void updateProgress(int progress) {
progressCallback.updateProgress(progress);
}
@Override
public void finish() {
progressCallback.finish();
}
}); });
} }

View file

@ -25,7 +25,7 @@ import net.osmand.plus.R;
import net.osmand.plus.dashboard.DashboardOnMap; import net.osmand.plus.dashboard.DashboardOnMap;
import net.osmand.plus.mapcontextmenu.MapContextMenu; import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.RoutingHelper.IRouteInformationListener; import net.osmand.plus.routing.IRouteInformationListener;
import net.osmand.plus.views.AnimateDraggingMapThread; import net.osmand.plus.views.AnimateDraggingMapThread;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;

View file

@ -80,7 +80,7 @@ import net.osmand.plus.mapillary.MapillaryPlugin.MapillaryFirstDialogFragment;
import net.osmand.plus.osmedit.OsmNotesMenu; import net.osmand.plus.osmedit.OsmNotesMenu;
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin; import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.RoutingHelper.IRouteInformationListener; import net.osmand.plus.routing.IRouteInformationListener;
import net.osmand.plus.srtmplugin.ContourLinesMenu; import net.osmand.plus.srtmplugin.ContourLinesMenu;
import net.osmand.plus.srtmplugin.HillshadeMenu; import net.osmand.plus.srtmplugin.HillshadeMenu;
import net.osmand.plus.srtmplugin.SRTMPlugin; import net.osmand.plus.srtmplugin.SRTMPlugin;

View file

@ -108,7 +108,8 @@ public class ResourceManager {
TRANSPORT, TRANSPORT,
ADDRESS, ADDRESS,
QUICK_SEARCH, QUICK_SEARCH,
ROUTING ROUTING,
TRANSPORT_ROUTING
} }
public static class BinaryMapReaderResource { public static class BinaryMapReaderResource {
@ -998,7 +999,20 @@ public class ResourceManager {
} }
return readers.toArray(new BinaryMapIndexReader[readers.size()]); return readers.toArray(new BinaryMapIndexReader[readers.size()]);
} }
public BinaryMapIndexReader[] getTransportRoutingMapFiles() {
List<BinaryMapIndexReader> readers = new ArrayList<>(fileReaders.size());
for(BinaryMapReaderResource r : fileReaders.values()) {
if(r.isUseForRouting()) {
BinaryMapIndexReader reader = r.getReader(BinaryMapReaderResourceType.TRANSPORT_ROUTING);
if (reader != null) {
readers.add(reader);
}
}
}
return readers.toArray(new BinaryMapIndexReader[readers.size()]);
}
public BinaryMapIndexReader[] getQuickSearchFiles() { public BinaryMapIndexReader[] getQuickSearchFiles() {
List<BinaryMapIndexReader> readers = new ArrayList<>(fileReaders.size()); List<BinaryMapIndexReader> readers = new ArrayList<>(fileReaders.size());
for(BinaryMapReaderResource r : fileReaders.values()) { for(BinaryMapReaderResource r : fileReaders.values()) {

View file

@ -70,7 +70,7 @@ import net.osmand.plus.mapmarkers.MapMarkerSelectionFragment;
import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.RoutingHelper.IRouteInformationListener; import net.osmand.plus.routing.IRouteInformationListener;
import net.osmand.plus.views.MapControlsLayer; import net.osmand.plus.views.MapControlsLayer;
import net.osmand.router.GeneralRouter; import net.osmand.router.GeneralRouter;

View file

@ -0,0 +1,12 @@
package net.osmand.plus.routing;
import net.osmand.ValueHolder;
public interface IRouteInformationListener {
void newRouteIsCalculated(boolean newRoute, ValueHolder<Boolean> showToast);
void routeWasCancelled();
void routeWasFinished();
}

View file

@ -36,21 +36,12 @@ public class RoutingHelper {
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RoutingHelper.class); private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RoutingHelper.class);
public interface IRouteInformationListener {
void newRouteIsCalculated(boolean newRoute, ValueHolder<Boolean> showToast);
void routeWasCancelled();
void routeWasFinished();
}
private static final float POSITION_TOLERANCE = 60; private static final float POSITION_TOLERANCE = 60;
private List<WeakReference<IRouteInformationListener>> listeners = new LinkedList<>();
private List<WeakReference<IRouteInformationListener>> listeners = new LinkedList<WeakReference<IRouteInformationListener>>();
private OsmandApplication app; private OsmandApplication app;
private TransportRoutingHelper transportRoutingHelper;
private boolean isFollowingMode = false; private boolean isFollowingMode = false;
private boolean isRoutePlanningMode = false; private boolean isRoutePlanningMode = false;
@ -99,9 +90,13 @@ public class RoutingHelper {
settings = context.getSettings(); settings = context.getSettings();
voiceRouter = new VoiceRouter(this, settings); voiceRouter = new VoiceRouter(this, settings);
provider = new RouteProvider(); provider = new RouteProvider();
transportRoutingHelper = context.getTransportRoutingHelper();
setAppMode(settings.APPLICATION_MODE.get()); setAppMode(settings.APPLICATION_MODE.get());
} }
public TransportRoutingHelper getTransportRoutingHelper() {
return transportRoutingHelper;
}
public boolean isFollowingMode() { public boolean isFollowingMode() {
return isFollowingMode; return isFollowingMode;
@ -160,8 +155,6 @@ public class RoutingHelper {
this.isRoutePlanningMode = isRoutePlanningMode; this.isRoutePlanningMode = isRoutePlanningMode;
} }
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List<LatLon> intermediatePoints, Location currentLocation){ public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List<LatLon> intermediatePoints, Location currentLocation){
RouteCalculationResult previousRoute = route; RouteCalculationResult previousRoute = route;
clearCurrentRoute(finalLocation, intermediatePoints); clearCurrentRoute(finalLocation, intermediatePoints);
@ -201,6 +194,7 @@ public class RoutingHelper {
this.lastProjection = null; this.lastProjection = null;
setFollowingMode(false); setFollowingMode(false);
} }
transportRoutingHelper.clearCurrentRoute(newFinalLocation);
} }
private synchronized void finishCurrentRoute() { private synchronized void finishCurrentRoute() {
@ -265,7 +259,8 @@ public class RoutingHelper {
} }
public void addListener(IRouteInformationListener l){ public void addListener(IRouteInformationListener l){
listeners.add(new WeakReference<RoutingHelper.IRouteInformationListener>(l)); listeners.add(new WeakReference<>(l));
transportRoutingHelper.addListener(l);
} }
public boolean removeListener(IRouteInformationListener lt){ public boolean removeListener(IRouteInformationListener lt){
@ -278,6 +273,7 @@ public class RoutingHelper {
return true; return true;
} }
} }
transportRoutingHelper.removeListener(lt);
return false; return false;
} }
@ -305,7 +301,11 @@ public class RoutingHelper {
private Location setCurrentLocation(Location currentLocation, boolean returnUpdatedLocation, private Location setCurrentLocation(Location currentLocation, boolean returnUpdatedLocation,
RouteCalculationResult previousRoute, boolean targetPointsChanged) { RouteCalculationResult previousRoute, boolean targetPointsChanged) {
Location locationProjection = currentLocation; Location locationProjection = currentLocation;
if (finalLocation == null || currentLocation == null) { if (isPublicTransportMode() && currentLocation != null) {
transportRoutingHelper.setFinalAndCurrentLocation(finalLocation,
new LatLon(currentLocation.getLatitude(), currentLocation.getLongitude()));
}
if (finalLocation == null || currentLocation == null || isPublicTransportMode()) {
isDeviatedFromRoute = false; isDeviatedFromRoute = false;
return locationProjection; return locationProjection;
} }
@ -567,7 +567,7 @@ public class RoutingHelper {
private boolean identifyUTurnIsNeeded(Location currentLocation, float posTolerance) { private boolean identifyUTurnIsNeeded(Location currentLocation, float posTolerance) {
if (finalLocation == null || currentLocation == null || !route.isCalculated()) { if (finalLocation == null || currentLocation == null || !route.isCalculated() || isPublicTransportMode()) {
return false; return false;
} }
boolean isOffRoute = false; boolean isOffRoute = false;
@ -664,7 +664,7 @@ public class RoutingHelper {
app.runInUIThread(new Runnable() { app.runInUIThread(new Runnable() {
@Override @Override
public void run() { public void run() {
ValueHolder<Boolean> showToast = new ValueHolder<Boolean>(); ValueHolder<Boolean> showToast = new ValueHolder<>();
showToast.value = true; showToast.value = true;
Iterator<WeakReference<IRouteInformationListener>> it = listeners.iterator(); Iterator<WeakReference<IRouteInformationListener>> it = listeners.iterator();
while (it.hasNext()) { while (it.hasNext()) {
@ -937,7 +937,18 @@ public class RoutingHelper {
public void recalculateRouteDueToSettingsChange() { public void recalculateRouteDueToSettingsChange() {
clearCurrentRoute(finalLocation, intermediatePoints); clearCurrentRoute(finalLocation, intermediatePoints);
recalculateRouteInBackground(lastFixedLocation, finalLocation, intermediatePoints, currentGPXRoute, route, true, false); if (isPublicTransportMode()) {
Location start = lastFixedLocation;
LatLon finish = finalLocation;
if (start != null && finish != null) {
transportRoutingHelper.setFinalAndCurrentLocation(finish,
new LatLon(start.getLatitude(), start.getLongitude()));
} else {
transportRoutingHelper.recalculateRouteDueToSettingsChange();
}
} else {
recalculateRouteInBackground(lastFixedLocation, finalLocation, intermediatePoints, currentGPXRoute, route, true, false);
}
} }
private void recalculateRouteInBackground(final Location start, final LatLon end, final List<LatLon> intermediates, private void recalculateRouteInBackground(final Location start, final LatLon end, final List<LatLon> intermediates,
@ -1060,6 +1071,9 @@ public class RoutingHelper {
void finish(); void finish();
} }
public boolean isPublicTransportMode() {
return mode == ApplicationMode.PUBLIC_TRANSPORT;
}
public boolean isRouteBeingCalculated(){ public boolean isRouteBeingCalculated(){
return currentRunningJob instanceof RouteRecalculationThread; return currentRunningJob instanceof RouteRecalculationThread;

View file

@ -0,0 +1,358 @@
package net.osmand.plus.routing;
import android.support.annotation.NonNull;
import net.osmand.PlatformUtil;
import net.osmand.ValueHolder;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.routing.RouteProvider.RouteService;
import net.osmand.router.RouteCalculationProgress;
import net.osmand.router.RoutingConfiguration;
import net.osmand.router.TransportRoutePlanner;
import net.osmand.router.TransportRoutePlanner.TransportRouteResult;
import net.osmand.router.TransportRoutePlanner.TransportRoutingContext;
import net.osmand.router.TransportRoutingConfiguration;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import static net.osmand.plus.notifications.OsmandNotification.NotificationType.NAVIGATION;
public class TransportRoutingHelper {
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(TransportRoutingHelper.class);
private List<WeakReference<IRouteInformationListener>> listeners = new LinkedList<>();
private OsmandApplication app;
private List<TransportRouteResult> routes;
private int currentRoute;
private LatLon startLocation;
private LatLon endLocation;
private boolean useSchedule;
private Thread currentRunningJob;
private String lastRouteCalcError;
private String lastRouteCalcErrorShort;
private long lastTimeEvaluatedRoute = 0;
private TransportRouteCalculationProgressCallback progressRoute;
public TransportRoutingHelper(@NonNull OsmandApplication app) {
this.app = app;
}
public LatLon getStartLocation() {
return startLocation;
}
public LatLon getEndLocation() {
return endLocation;
}
public boolean isUseSchedule() {
return useSchedule;
}
public void setUseSchedule(boolean useSchedule) {
this.useSchedule = useSchedule;
}
public int getCurrentRoute() {
return currentRoute;
}
public List<TransportRouteResult> getRoutes() {
return routes;
}
public void setCurrentRoute(int currentRoute) {
this.currentRoute = currentRoute;
}
public void addListener(IRouteInformationListener l){
listeners.add(new WeakReference<>(l));
}
public boolean removeListener(IRouteInformationListener lt){
Iterator<WeakReference<IRouteInformationListener>> it = listeners.iterator();
while(it.hasNext()) {
WeakReference<IRouteInformationListener> ref = it.next();
IRouteInformationListener l = ref.get();
if(l == null || lt == l) {
it.remove();
return true;
}
}
return false;
}
public void recalculateRouteDueToSettingsChange() {
clearCurrentRoute(endLocation);
recalculateRouteInBackground(startLocation, endLocation);
}
private void recalculateRouteInBackground(LatLon start, LatLon end) {
if (start == null || end == null) {
return;
}
TransportRouteCalculationParams params = new TransportRouteCalculationParams();
params.start = start;
params.end = end;
params.useSchedule = useSchedule;
params.type = RouteService.OSMAND;
params.ctx = app;
params.calculationProgress = new RouteCalculationProgress();
startRouteCalculationThread(params);
}
private void startRouteCalculationThread(TransportRouteCalculationParams params) {
synchronized (this) {
final Thread prevRunningJob = currentRunningJob;
RouteRecalculationThread newThread =
new RouteRecalculationThread("Calculating public transport route", params);
currentRunningJob = newThread;
startProgress(params);
updateProgress(params);
if (prevRunningJob != null) {
newThread.setWaitPrevJob(prevRunningJob);
}
currentRunningJob.start();
}
}
public void setProgressBar(TransportRouteCalculationProgressCallback progressRoute) {
this.progressRoute = progressRoute;
}
private void startProgress(final TransportRouteCalculationParams params) {
final TransportRouteCalculationProgressCallback progressRoute = this.progressRoute;
if (progressRoute != null) {
progressRoute.start();
}
}
private void updateProgress(final TransportRouteCalculationParams params) {
final TransportRouteCalculationProgressCallback progressRoute = this.progressRoute;
if (progressRoute != null) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
RouteCalculationProgress calculationProgress = params.calculationProgress;
if (isRouteBeingCalculated()) {
float pr = calculationProgress.getLinearProgress();
progressRoute.updateProgress((int) pr);
Thread t = currentRunningJob;
if (t instanceof RouteRecalculationThread && ((RouteRecalculationThread) t).params != params) {
// different calculation started
} else {
updateProgress(params);
}
} else {
progressRoute.finish();
}
}
}, 300);
}
}
public boolean isRouteBeingCalculated() {
return currentRunningJob instanceof RouteRecalculationThread;
}
private void setNewRoute(final List<TransportRouteResult> res) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
ValueHolder<Boolean> showToast = new ValueHolder<>();
showToast.value = true;
Iterator<WeakReference<IRouteInformationListener>> it = listeners.iterator();
while (it.hasNext()) {
WeakReference<IRouteInformationListener> ref = it.next();
IRouteInformationListener l = ref.get();
if (l == null) {
it.remove();
} else {
l.newRouteIsCalculated(true, showToast);
}
}
if (showToast.value && OsmandPlugin.isDevelopment()) {
String msg = "Public transport routes calculated: " + res.size();
app.showToastMessage(msg);
}
}
});
}
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, LatLon currentLocation) {
clearCurrentRoute(finalLocation);
// to update route
setCurrentLocation(currentLocation);
}
public synchronized void clearCurrentRoute(LatLon newFinalLocation) {
routes = null;
app.getWaypointHelper().setNewRoute(new RouteCalculationResult(""));
app.runInUIThread(new Runnable() {
@Override
public void run() {
Iterator<WeakReference<IRouteInformationListener>> it = listeners.iterator();
while (it.hasNext()) {
WeakReference<IRouteInformationListener> ref = it.next();
IRouteInformationListener l = ref.get();
if (l == null) {
it.remove();
} else {
l.routeWasCancelled();
}
}
}
});
this.endLocation = newFinalLocation;
if (currentRunningJob instanceof RouteRecalculationThread) {
((RouteRecalculationThread) currentRunningJob).stopCalculation();
}
}
private void setCurrentLocation(LatLon currentLocation) {
if (endLocation == null || currentLocation == null) {
return;
}
startLocation = currentLocation;
recalculateRouteInBackground(currentLocation, endLocation);
}
private void showMessage(final String msg) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
app.showToastMessage(msg);
}
});
}
public interface TransportRouteCalculationProgressCallback {
void start();
void updateProgress(int progress);
void finish();
}
public static class TransportRouteCalculationParams {
public LatLon start;
public LatLon end;
public OsmandApplication ctx;
public RouteService type;
public boolean useSchedule;
public RouteCalculationProgress calculationProgress;
public TransportRouteCalculationResultListener resultListener;
public interface TransportRouteCalculationResultListener {
void onRouteCalculated(List<TransportRouteResult> route);
}
}
private class RouteRecalculationThread extends Thread {
private final TransportRouteCalculationParams params;
private Thread prevRunningJob;
public RouteRecalculationThread(String name, TransportRouteCalculationParams params) {
super(name);
this.params = params;
if (params.calculationProgress == null) {
params.calculationProgress = new RouteCalculationProgress();
}
}
public void stopCalculation() {
params.calculationProgress.isCancelled = true;
}
private List<TransportRouteResult> calculateRouteImpl(TransportRouteCalculationParams params) throws IOException {
RoutingConfiguration.Builder config = params.ctx.getDefaultRoutingConfig();
BinaryMapIndexReader[] files = params.ctx.getResourceManager().getTransportRoutingMapFiles();
TransportRoutingConfiguration cfg = new TransportRoutingConfiguration(config);
cfg.useSchedule = params.useSchedule;
TransportRoutePlanner planner = new TransportRoutePlanner();
TransportRoutingContext ctx = new TransportRoutingContext(cfg, files);
return planner.buildRoute(ctx, params.start, params.end);
}
@Override
public void run() {
synchronized (TransportRoutingHelper.this) {
currentRunningJob = this;
}
if (prevRunningJob != null) {
while (prevRunningJob.isAlive()) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// ignore
}
}
synchronized (TransportRoutingHelper.this) {
currentRunningJob = this;
}
}
List<TransportRouteResult> res = null;
String error = null;
try {
res = calculateRouteImpl(params);
} catch (IOException e) {
error = e.getMessage();
log.error(e);
}
if (params.calculationProgress.isCancelled) {
synchronized (TransportRoutingHelper.this) {
currentRunningJob = null;
}
return;
}
synchronized (TransportRoutingHelper.this) {
routes = res;
if (res != null) {
if (params.resultListener != null) {
params.resultListener.onRouteCalculated(res);
}
}
currentRunningJob = null;
}
if (res != null) {
setNewRoute(res);
} else if (error != null) {
lastRouteCalcError = app.getString(R.string.error_calculating_route) + ":\n" + error;
lastRouteCalcErrorShort = app.getString(R.string.error_calculating_route);
showMessage(lastRouteCalcError);
} 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;
}
}
}

View file

@ -13,6 +13,7 @@ import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.util.Pair;
import android.view.MotionEvent; import android.view.MotionEvent;
import net.osmand.binary.BinaryMapIndexReader; import net.osmand.binary.BinaryMapIndexReader;
@ -137,14 +138,25 @@ public abstract class OsmandMapLayer {
return x >= lx && x <= rx && y >= ty && y <= by; return x >= lx && x <= rx && y >= ty && y <= by;
} }
public int calculatePath(RotatedTileBox tb, TIntArrayList xs, TIntArrayList ys, Path path) { public int calculatePath(RotatedTileBox tb, TIntArrayList xs, TIntArrayList ys, Path path) {
List<Pair<Path, Integer>> paths = new ArrayList<>();
int res = calculatePath(tb, xs, ys, null, paths);
if (paths.size() > 0) {
path.addPath(paths.get(0).first);
}
return res;
}
public int calculatePath(RotatedTileBox tb, TIntArrayList xs, TIntArrayList ys, List<Integer> colors, List<Pair<Path, Integer>> paths) {
boolean segmentStarted = false; boolean segmentStarted = false;
int prevX = xs.get(0); int prevX = xs.get(0);
int prevY = ys.get(0); int prevY = ys.get(0);
int height = tb.getPixHeight(); int height = tb.getPixHeight();
int width = tb.getPixWidth(); int width = tb.getPixWidth();
int cnt = 0; int cnt = 0;
boolean hasColors = colors != null && colors.size() == xs.size();
int color = hasColors ? colors.get(0) : 0;
Path path = new Path();
boolean prevIn = isIn(prevX, prevY, 0, 0, width, height); boolean prevIn = isIn(prevX, prevY, 0, 0, width, height);
for (int i = 1; i < xs.size(); i++) { for (int i = 1; i < xs.size(); i++) {
int currX = xs.get(i); int currX = xs.get(i);
@ -186,6 +198,21 @@ public abstract class OsmandMapLayer {
prevIn = currIn; prevIn = currIn;
prevX = currX; prevX = currX;
prevY = currY; prevY = currY;
if (hasColors) {
int newColor = colors.get(i);
if (color != newColor) {
paths.add(new Pair<>(path, color));
path = new Path();
if (segmentStarted) {
path.moveTo(currX, currY);
}
color = newColor;
}
}
}
if (!path.isEmpty()) {
paths.add(new Pair<>(path, color));
} }
return cnt; return cnt;
} }
@ -383,6 +410,8 @@ public abstract class OsmandMapLayer {
protected static class RenderingLineAttributes { protected static class RenderingLineAttributes {
protected int cachedHash; protected int cachedHash;
public Paint paint; public Paint paint;
public Paint customColorPaint;
public int customColor = 0;
public int defaultWidth = 0; public int defaultWidth = 0;
public int defaultColor = 0; public int defaultColor = 0;
public boolean isPaint2; public boolean isPaint2;
@ -402,6 +431,7 @@ public abstract class OsmandMapLayer {
public RenderingLineAttributes(String renderingAttribute) { public RenderingLineAttributes(String renderingAttribute) {
this.renderingAttribute = renderingAttribute; this.renderingAttribute = renderingAttribute;
paint = initPaint(); paint = initPaint();
customColorPaint = new Paint(paint);
paint2 = initPaint(); paint2 = initPaint();
paint3 = initPaint(); paint3 = initPaint();
paint_1 = initPaint(); paint_1 = initPaint();
@ -462,6 +492,7 @@ public abstract class OsmandMapLayer {
if (paint.getStrokeWidth() == 0 && defaultWidth != 0) { if (paint.getStrokeWidth() == 0 && defaultWidth != 0) {
paint.setStrokeWidth(defaultWidth); paint.setStrokeWidth(defaultWidth);
} }
customColorPaint = new Paint(paint);
} }
return true; return true;
} }
@ -486,7 +517,12 @@ public abstract class OsmandMapLayer {
if (isShadowPaint) { if (isShadowPaint) {
canvas.drawPath(path, shadowPaint); canvas.drawPath(path, shadowPaint);
} }
canvas.drawPath(path, paint); if (customColor != 0) {
customColorPaint.setColor(customColor);
canvas.drawPath(path, customColorPaint);
} else {
canvas.drawPath(path, paint);
}
if (isPaint2) { if (isPaint2) {
canvas.drawPath(path, paint2); canvas.drawPath(path, paint2);
} }

View file

@ -39,7 +39,7 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.poi.PoiUIFilter;
import net.osmand.plus.render.RenderingIcons; import net.osmand.plus.render.RenderingIcons;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.RoutingHelper.IRouteInformationListener; import net.osmand.plus.routing.IRouteInformationListener;
import net.osmand.plus.views.MapTextLayer.MapTextProvider; import net.osmand.plus.views.MapTextLayer.MapTextProvider;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;

View file

@ -12,11 +12,16 @@ import android.graphics.PointF;
import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.support.annotation.ColorInt; import android.support.annotation.ColorInt;
import android.util.Pair;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.QuadRect; import net.osmand.data.QuadRect;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.data.TransportRoute;
import net.osmand.osm.edit.Node;
import net.osmand.osm.edit.OSMSettings;
import net.osmand.osm.edit.Way;
import net.osmand.plus.GPXUtilities.WptPt; import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu;
@ -24,9 +29,15 @@ import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu.TrackChartPoints;
import net.osmand.plus.routing.RouteCalculationResult; import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.routing.TransportRoutingHelper;
import net.osmand.plus.transport.TransportStopRoute;
import net.osmand.plus.transport.TransportStopType;
import net.osmand.router.TransportRoutePlanner.TransportRouteResult;
import net.osmand.router.TransportRoutePlanner.TransportRouteResultSegment;
import net.osmand.util.MapUtils; import net.osmand.util.MapUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -42,11 +53,10 @@ public class RouteLayer extends OsmandMapLayer {
private OsmandMapTileView view; private OsmandMapTileView view;
private final RoutingHelper helper; private final RoutingHelper helper;
private final TransportRoutingHelper transportHelper;
// keep array lists created // keep array lists created
private List<Location> actionPoints = new ArrayList<Location>(); private List<Location> actionPoints = new ArrayList<Location>();
private Path path;
// cache // cache
private Bitmap coloredArrowUp; private Bitmap coloredArrowUp;
private Bitmap actionArrow; private Bitmap actionArrow;
@ -61,10 +71,12 @@ public class RouteLayer extends OsmandMapLayer {
private TrackChartPoints trackChartPoints; private TrackChartPoints trackChartPoints;
private RenderingLineAttributes attrs; private RenderingLineAttributes attrs;
private boolean nightMode;
public RouteLayer(RoutingHelper helper){ public RouteLayer(RoutingHelper helper) {
this.helper = helper; this.helper = helper;
this.transportHelper = helper.getTransportRoutingHelper();
} }
public void setTrackChartPoints(TrackDetailsMenu.TrackChartPoints trackChartPoints) { public void setTrackChartPoints(TrackDetailsMenu.TrackChartPoints trackChartPoints) {
@ -73,8 +85,7 @@ public class RouteLayer extends OsmandMapLayer {
private void initUI() { private void initUI() {
actionArrow = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_action_arrow, null); actionArrow = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_action_arrow, null);
path = new Path();
paintIcon = new Paint(); paintIcon = new Paint();
paintIcon.setFilterBitmap(true); paintIcon.setFilterBitmap(true);
paintIcon.setAntiAlias(true); paintIcon.setAntiAlias(true);
@ -119,7 +130,9 @@ public class RouteLayer extends OsmandMapLayer {
@Override @Override
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (helper.getFinalLocation() != null && helper.getRoute().isCalculated()) { if ((helper.isPublicTransportMode() && transportHelper.getRoutes() != null) ||
(helper.getFinalLocation() != null && helper.getRoute().isCalculated())) {
updateAttrs(settings, tileBox); updateAttrs(settings, tileBox);
if(coloredArrowUp == null) { if(coloredArrowUp == null) {
@ -178,6 +191,7 @@ public class RouteLayer extends OsmandMapLayer {
paintIconAction.setColorFilter(new PorterDuffColorFilter(attrs.paint3.getColor(), Mode.MULTIPLY)); paintIconAction.setColorFilter(new PorterDuffColorFilter(attrs.paint3.getColor(), Mode.MULTIPLY));
paintIcon.setColorFilter(new PorterDuffColorFilter(attrs.paint2.getColor(), Mode.MULTIPLY)); paintIcon.setColorFilter(new PorterDuffColorFilter(attrs.paint2.getColor(), Mode.MULTIPLY));
} }
nightMode = settings != null && settings.isNightMode();
} }
private void drawXAxisPoints(Canvas canvas, RotatedTileBox tileBox) { private void drawXAxisPoints(Canvas canvas, RotatedTileBox tileBox) {
@ -413,24 +427,79 @@ public class RouteLayer extends OsmandMapLayer {
private class RouteSimplificationGeometry { private class RouteSimplificationGeometry {
RouteCalculationResult route; RouteCalculationResult route;
TransportRouteResult transportRoute;
double mapDensity; double mapDensity;
TreeMap<Integer, RouteGeometryZoom> zooms = new TreeMap<>(); TreeMap<Integer, RouteGeometryZoom> zooms = new TreeMap<>();
List<Location> locations = Collections.emptyList(); List<Location> locations = Collections.emptyList();
TreeMap<Integer, Integer> colorsMap = new TreeMap<>();
// cache arrays // cache arrays
TIntArrayList tx = new TIntArrayList(); TIntArrayList tx = new TIntArrayList();
TIntArrayList ty = new TIntArrayList(); TIntArrayList ty = new TIntArrayList();
List<Double> angles = new ArrayList<>(); List<Double> angles = new ArrayList<>();
List<Double> distances = new ArrayList<>(); List<Double> distances = new ArrayList<>();
List<Integer> colors = new ArrayList<>();
private int getColor(int index) {
List<Integer> list = new ArrayList<>(colorsMap.keySet());
for (int i = list.size() -1; i >= 0; i--) {
int c = list.get(i);
if (c <= index) {
return colorsMap.get(c);
}
}
return attrs.paint.getColor();
}
public void updateRoute(RotatedTileBox tb, RouteCalculationResult route) { public void updateRoute(RotatedTileBox tb, RouteCalculationResult route) {
if(tb.getMapDensity() != mapDensity || this.route != route) { if(tb.getMapDensity() != mapDensity || this.route != route) {
this.route = route; this.route = route;
if(route == null) { if (route == null) {
locations = Collections.emptyList(); locations = Collections.emptyList();
} else { } else {
locations = route.getImmutableAllLocations(); locations = route.getImmutableAllLocations();
} }
colorsMap.clear();
this.mapDensity = tb.getMapDensity();
zooms.clear();
}
}
public void updateTransportRoute(RotatedTileBox tb, TransportRouteResult route) {
if (tb.getMapDensity() != mapDensity || this.transportRoute != route) {
this.transportRoute = route;
if (route == null) {
locations = Collections.emptyList();
colorsMap.clear();
} else {
LatLon start = transportHelper.getStartLocation();
LatLon end = transportHelper.getEndLocation();
List<Way> list = new ArrayList<>();
List<Integer> cols = new ArrayList<>();
calculateTransportResult(start, end, route, list, cols);
List<Location> locs = new ArrayList<>();
TreeMap<Integer, Integer> colsMap = new TreeMap<>();
int i = 0;
int k = 0;
if (list.size() > 0) {
for (Way w : list) {
colsMap.put(k, cols.get(i++));
//Location loc = new Location("");
//loc.setLatitude(w.getLatitude());
//loc.setLongitude(w.getLongitude());
//locs.add(loc);
for (Node n : w.getNodes()) {
Location ln = new Location("");
ln.setLatitude(n.getLatitude());
ln.setLongitude(n.getLongitude());
locs.add(ln);
k++;
}
}
}
locations = locs;
colorsMap = colsMap;
}
this.mapDensity = tb.getMapDensity(); this.mapDensity = tb.getMapDensity();
zooms.clear(); zooms.clear();
} }
@ -452,14 +521,13 @@ public class RouteLayer extends OsmandMapLayer {
TByteArrayList simplification = geometryZoom.getSimplifyPoints(); TByteArrayList simplification = geometryZoom.getSimplifyPoints();
List<Double> odistances = geometryZoom.getDistances(); List<Double> odistances = geometryZoom.getDistances();
clearArrays(); clearArrays();
int color = attrs.paint.getColor();
boolean previousVisible = false; boolean previousVisible = false;
if (lastProjection != null) { if (lastProjection != null) {
if (leftLongitude <= lastProjection.getLongitude() && lastProjection.getLongitude() <= rightLongitude if (leftLongitude <= lastProjection.getLongitude() && lastProjection.getLongitude() <= rightLongitude
&& bottomLatitude <= lastProjection.getLatitude() && lastProjection.getLatitude() <= topLatitude) { && bottomLatitude <= lastProjection.getLatitude() && lastProjection.getLatitude() <= topLatitude) {
addLocation(tb, lastProjection, tx, ty, angles, distances, 0); addLocation(tb, lastProjection, color, tx, ty, angles, distances, 0, colors);
previousVisible = true; previousVisible = true;
} }
} }
@ -467,7 +535,8 @@ public class RouteLayer extends OsmandMapLayer {
int previous = -1; int previous = -1;
for (int i = currentRoute; i < routeNodes.size(); i++) { for (int i = currentRoute; i < routeNodes.size(); i++) {
Location ls = routeNodes.get(i); Location ls = routeNodes.get(i);
if(simplification.getQuick(i) == 0) { color = getColor(i);
if (simplification.getQuick(i) == 0 && !colorsMap.containsKey(i)) {
continue; continue;
} }
if (leftLongitude <= ls.getLongitude() && ls.getLongitude() <= rightLongitude && bottomLatitude <= ls.getLatitude() if (leftLongitude <= ls.getLongitude() && ls.getLongitude() <= rightLongitude && bottomLatitude <= ls.getLatitude()
@ -481,23 +550,23 @@ public class RouteLayer extends OsmandMapLayer {
} else if (lastProjection != null) { } else if (lastProjection != null) {
lt = lastProjection; lt = lastProjection;
} }
addLocation(tb, lt, tx, ty, angles, distances, 0); // first point addLocation(tb, lt, color, tx, ty, angles, distances, 0, colors); // first point
} }
addLocation(tb, ls, tx, ty, angles, distances, dist); addLocation(tb, ls, color, tx, ty, angles, distances, dist, colors);
previousVisible = true; previousVisible = true;
} else if (previousVisible) { } else if (previousVisible) {
addLocation(tb, ls, tx, ty, angles, distances, previous == -1 ? 0 : odistances.get(i)); addLocation(tb, ls, color, tx, ty, angles, distances, previous == -1 ? 0 : odistances.get(i), colors);
double distToFinish = 0; double distToFinish = 0;
for(int ki = i + 1; ki < odistances.size(); ki++) { for(int ki = i + 1; ki < odistances.size(); ki++) {
distToFinish += odistances.get(ki); distToFinish += odistances.get(ki);
} }
drawRouteSegment(tb, canvas, tx, ty, angles, distances, distToFinish); drawRouteSegment(tb, canvas, tx, ty, angles, distances, distToFinish, colors);
previousVisible = false; previousVisible = false;
clearArrays(); clearArrays();
} }
previous = i; previous = i;
} }
drawRouteSegment(tb, canvas, tx, ty, angles, distances, 0); drawRouteSegment(tb, canvas, tx, ty, angles, distances, 0, colors);
} }
private void clearArrays() { private void clearArrays() {
@ -505,10 +574,11 @@ public class RouteLayer extends OsmandMapLayer {
ty.clear(); ty.clear();
distances.clear(); distances.clear();
angles.clear(); angles.clear();
colors.clear();
} }
private void addLocation(RotatedTileBox tb, Location ls, TIntArrayList tx, TIntArrayList ty, private void addLocation(RotatedTileBox tb, Location ls, int color, TIntArrayList tx, TIntArrayList ty,
List<Double> angles, List<Double> distances, double dist) { List<Double> angles, List<Double> distances, double dist, List<Integer> colors) {
float x = tb.getPixXFromLatLon(ls.getLatitude(), ls.getLongitude()); float x = tb.getPixXFromLatLon(ls.getLatitude(), ls.getLongitude());
float y = tb.getPixYFromLatLon(ls.getLatitude(), ls.getLongitude()); float y = tb.getPixYFromLatLon(ls.getLatitude(), ls.getLongitude());
float px = x; float px = x;
@ -531,21 +601,26 @@ public class RouteLayer extends OsmandMapLayer {
ty.add((int) y); ty.add((int) y);
angles.add(angle); angles.add(angle);
distances.add(distSegment); distances.add(distSegment);
colors.add(color);
} }
} }
RouteSimplificationGeometry routeGeometry = new RouteSimplificationGeometry(); RouteSimplificationGeometry routeGeometry = new RouteSimplificationGeometry();
private void drawRouteSegment(RotatedTileBox tb, Canvas canvas, TIntArrayList tx, TIntArrayList ty, private void drawRouteSegment(RotatedTileBox tb, Canvas canvas, TIntArrayList tx, TIntArrayList ty,
List<Double> angles, List<Double> distances, double distToFinish) { List<Double> angles, List<Double> distances, double distToFinish, List<Integer> colors) {
if(tx.size() < 2) { if (tx.size() < 2) {
return; return;
} }
try { try {
path.reset(); List<Pair<Path, Integer>> paths = new ArrayList<>();
canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY()); canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY());
calculatePath(tb, tx, ty, path); calculatePath(tb, tx, ty, colors, paths);
attrs.drawPath(canvas, path); for (Pair<Path, Integer> pc : paths) {
attrs.customColor = pc.second;
attrs.drawPath(canvas, pc.first);
}
attrs.customColor = 0;
if (tb.getZoomAnimation() == 0) { if (tb.getZoomAnimation() == 0) {
drawArrowsOverPath(canvas, tb, tx, ty, angles, distances, coloredArrowUp, distToFinish); drawArrowsOverPath(canvas, tb, tx, ty, angles, distances, coloredArrowUp, distToFinish);
} }
@ -555,16 +630,32 @@ public class RouteLayer extends OsmandMapLayer {
} }
public void drawLocations(RotatedTileBox tb, Canvas canvas, double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude) { public void drawLocations(RotatedTileBox tb, Canvas canvas, double topLatitude, double leftLongitude, double bottomLatitude, double rightLongitude) {
RouteCalculationResult route = helper.getRoute(); if (helper.isPublicTransportMode()) {
routeGeometry.updateRoute(tb, route); int currentRoute = transportHelper.getCurrentRoute();
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude, List<TransportRouteResult> routes = transportHelper.getRoutes();
helper.getLastProjection(), route == null ? 0 : route.getCurrentRoute()); TransportRouteResult route = routes != null && routes.size() > currentRoute ? routes.get(currentRoute) : null;
List<RouteDirectionInfo> rd = helper.getRouteDirections(); routeGeometry.updateRoute(tb, null);
Iterator<RouteDirectionInfo> it = rd.iterator(); routeGeometry.updateTransportRoute(tb, route);
if (tb.getZoom() >= 14) { if (route != null) {
List<Location> actionPoints = calculateActionPoints(topLatitude, leftLongitude, bottomLatitude, rightLongitude, helper.getLastProjection(), LatLon start = transportHelper.getStartLocation();
helper.getRoute().getRouteLocations(), helper.getRoute().getCurrentRoute(), it, tb.getZoom()); Location startLocation = new Location("transport");
drawAction(tb, canvas, actionPoints); startLocation.setLatitude(start.getLatitude());
startLocation.setLongitude(start.getLongitude());
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude, startLocation, 0);
}
} else {
RouteCalculationResult route = helper.getRoute();
routeGeometry.updateTransportRoute(tb, null);
routeGeometry.updateRoute(tb, route);
routeGeometry.drawSegments(tb, canvas, topLatitude, leftLongitude, bottomLatitude, rightLongitude,
helper.getLastProjection(), route == null ? 0 : route.getCurrentRoute());
List<RouteDirectionInfo> rd = helper.getRouteDirections();
Iterator<RouteDirectionInfo> it = rd.iterator();
if (tb.getZoom() >= 14) {
List<Location> actionPoints = calculateActionPoints(topLatitude, leftLongitude, bottomLatitude, rightLongitude, helper.getLastProjection(),
helper.getRoute().getRouteLocations(), helper.getRoute().getCurrentRoute(), it, tb.getZoom());
drawAction(tb, canvas, actionPoints);
}
} }
} }
@ -710,7 +801,49 @@ public class RouteLayer extends OsmandMapLayer {
return false; return false;
} }
private void calculateTransportResult(LatLon start, LatLon end, TransportRouteResult r, List<Way> res, List<Integer> colors) {
if (r != null) {
LatLon p = start;
for (TransportRouteResultSegment s : r.getSegments()) {
LatLon floc = s.getStart().getLocation();
addRouteWalk(p, floc, res, colors);
List<Way> geometry = s.getGeometry();
res.addAll(geometry);
addColors(s.route, geometry.size(), colors);
p = s.getEnd().getLocation();
}
addRouteWalk(p, end, res, colors);
}
}
private void addRouteWalk(LatLon s, LatLon e, List<Way> res, List<Integer> colors) {
double dist = MapUtils.getDistance(s, e);
if (dist > 50) {
Way way = new Way(-1);
way.putTag(OSMSettings.OSMTagKey.NAME.getValue(), String.format("Walk %.1f m", dist));
way.addNode(new Node(s.getLatitude(), s.getLongitude(), -1));
way.addNode(new Node(e.getLatitude(), e.getLongitude(), -1));
res.add(way);
addColors(null, 1, colors);
}
}
private void addColors(TransportRoute route, int count, List<Integer> colors) {
int color;
if (route == null) {
color = attrs.paint.getColor();
} else {
TransportStopRoute r = new TransportStopRoute();
r.type = TransportStopType.findType(route.getType());
r.route = route;
color = r.getColor(helper.getApplication(), nightMode);
}
addColors(color, count, colors);
}
private void addColors(int color, int count, List<Integer> colors) {
Integer[] integers = new Integer[count];
Arrays.fill(integers, color);
colors.addAll(Arrays.asList(integers));
}
} }