Calculate walking routes for public transport

This commit is contained in:
crimean 2018-12-08 11:46:03 +03:00
parent 42b17c78de
commit cd7fae500b
8 changed files with 188 additions and 14 deletions

View file

@ -162,6 +162,7 @@ public class TransportRoutePlanner {
}
p = p.parentRoute;
}
route.finishWalkSegment = new TransportRouteResultSegment(null, 0, 0, route.finishWalkDist, -1);
// test if faster routes fully included
boolean include = false;
for(TransportRouteResult s : lst) {
@ -316,6 +317,7 @@ public class TransportRoutePlanner {
public static class TransportRouteResult {
List<TransportRouteResultSegment> segments = new ArrayList<TransportRouteResultSegment>(4);
TransportRouteResultSegment finishWalkSegment;
double finishWalkDist;
double routeTime;
private final TransportRoutingConfiguration cfg;
@ -327,7 +329,11 @@ public class TransportRoutePlanner {
public List<TransportRouteResultSegment> getSegments() {
return segments;
}
public TransportRouteResultSegment getFinishWalkSegment() {
return finishWalkSegment;
}
public double getWalkDist() {
double d = finishWalkDist;
for (TransportRouteResultSegment s : segments) {

View file

@ -222,7 +222,7 @@ public class SearchCoreUITest {
});
if (files != null) {
for (File f : files) {
testSearchImpl(f);
//testSearchImpl(f);
}
}
}

View file

@ -10,6 +10,7 @@ import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.MapMarkersHelper;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.routing.RouteCalculationParams;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.router.RouteCalculationProgress;
import net.osmand.util.MapUtils;
@ -246,7 +247,8 @@ public class MarkersPlanRouteContext {
};
params.resultListener = new RouteCalculationParams.RouteCalculationResultListener() {
@Override
public void onRouteCalculated(List<Location> locations) {
public void onRouteCalculated(RouteCalculationResult route) {
List<Location> locations = route.getRouteLocations();
ArrayList<WptPt> pts = new ArrayList<>(locations.size());
for (Location loc : locations) {
WptPt pt = new WptPt();

View file

@ -10,6 +10,7 @@ import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.measurementtool.command.MeasurementCommandManager;
import net.osmand.plus.routing.RouteCalculationParams;
import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.router.RouteCalculationProgress;
@ -312,7 +313,8 @@ public class MeasurementEditingContext {
};
params.resultListener = new RouteCalculationParams.RouteCalculationResultListener() {
@Override
public void onRouteCalculated(List<Location> locations) {
public void onRouteCalculated(RouteCalculationResult route) {
List<Location> locations = route.getRouteLocations();
ArrayList<WptPt> pts = new ArrayList<>(locations.size());
for (Location loc : locations) {
if(!loc.hasAltitude()){

View file

@ -34,6 +34,6 @@ public class RouteCalculationParams {
public RouteCalculationResultListener resultListener;
public interface RouteCalculationResultListener {
void onRouteCalculated(List<Location> locations);
void onRouteCalculated(RouteCalculationResult route);
}
}

View file

@ -91,6 +91,7 @@ public class RoutingHelper {
voiceRouter = new VoiceRouter(this, settings);
provider = new RouteProvider();
transportRoutingHelper = context.getTransportRoutingHelper();
transportRoutingHelper.setRoutingHelper(this);
setAppMode(settings.APPLICATION_MODE.get());
}
@ -898,7 +899,7 @@ public class RoutingHelper {
route = res;
}
if (params.resultListener != null) {
params.resultListener.onRouteCalculated(res.getRouteLocations());
params.resultListener.onRouteCalculated(res);
}
} else {
evalWaitInterval = Math.max(3000, evalWaitInterval * 3 / 2); // for Issue #3899

View file

@ -1,27 +1,38 @@
package net.osmand.plus.routing;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.ValueHolder;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.LatLon;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
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.RouteCalculationProgress;
import net.osmand.router.RoutingConfiguration;
import net.osmand.router.TransportRoutePlanner;
import net.osmand.router.TransportRoutePlanner.TransportRouteResult;
import net.osmand.router.TransportRoutePlanner.TransportRouteResultSegment;
import net.osmand.router.TransportRoutePlanner.TransportRoutingContext;
import net.osmand.router.TransportRoutingConfiguration;
import net.osmand.util.MapUtils;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import static net.osmand.plus.notifications.OsmandNotification.NotificationType.NAVIGATION;
@ -32,8 +43,10 @@ public class TransportRoutingHelper {
private List<WeakReference<IRouteInformationListener>> listeners = new LinkedList<>();
private OsmandApplication app;
private RoutingHelper routingHelper;
private List<TransportRouteResult> routes;
private Map<TransportRouteResultSegment, RouteCalculationResult> walkingRouteSegments;
private int currentRoute;
private LatLon startLocation;
@ -51,6 +64,10 @@ public class TransportRoutingHelper {
this.app = app;
}
public void setRoutingHelper(RoutingHelper routingHelper) {
this.routingHelper = routingHelper;
}
public LatLon getStartLocation() {
return startLocation;
}
@ -75,6 +92,11 @@ public class TransportRoutingHelper {
return routes;
}
@Nullable
public RouteCalculationResult getWalkingRouteSegment(TransportRouteResultSegment s) {
return walkingRouteSegments.get(s);
}
public void setCurrentRoute(int currentRoute) {
this.currentRoute = currentRoute;
}
@ -113,6 +135,9 @@ public class TransportRoutingHelper {
params.ctx = app;
params.calculationProgress = new RouteCalculationProgress();
float rd = (float) MapUtils.getDistance(start, end);
params.calculationProgress.totalEstimatedDistance = rd * 1.5f;
startRouteCalculationThread(params);
}
@ -203,6 +228,7 @@ public class TransportRoutingHelper {
public synchronized void clearCurrentRoute(LatLon newFinalLocation) {
routes = null;
walkingRouteSegments = null;
app.getWaypointHelper().setNewRoute(new RouteCalculationResult(""));
app.runInUIThread(new Runnable() {
@Override
@ -267,11 +293,27 @@ public class TransportRoutingHelper {
}
}
private class WalkingRouteSegment {
TransportRouteResultSegment s;
LatLon start;
LatLon end;
WalkingRouteSegment(TransportRouteResultSegment s, LatLon start, LatLon end) {
this.s = s;
this.start = start;
this.end = end;
}
}
private class RouteRecalculationThread extends Thread {
private final TransportRouteCalculationParams params;
private Thread prevRunningJob;
private final Queue<WalkingRouteSegment> walkingSegmentsToCalculate = new ConcurrentLinkedQueue<>();
private Map<TransportRouteResultSegment, RouteCalculationResult> walkingRouteSegments = new HashMap<>();
private boolean walkingSegmentsCalculated;
public RouteRecalculationThread(String name, TransportRouteCalculationParams params) {
super(name);
this.params = params;
@ -295,6 +337,110 @@ public class TransportRoutingHelper {
return planner.buildRoute(ctx, params.start, params.end);
}
@Nullable
private RouteCalculationParams getWalkingRouteParams() {
ApplicationMode walkingMode = ApplicationMode.PEDESTRIAN;
final WalkingRouteSegment walkingRouteSegment = walkingSegmentsToCalculate.poll();
if (walkingRouteSegment == null) {
return null;
}
Location start = new Location("");
start.setLatitude(walkingRouteSegment.start.getLatitude());
start.setLongitude(walkingRouteSegment.start.getLongitude());
LatLon end = new LatLon(walkingRouteSegment.end.getLatitude(), walkingRouteSegment.end.getLongitude());
final float currentDistanceFromBegin =
RouteRecalculationThread.this.params.calculationProgress.distanceFromBegin + (float) walkingRouteSegment.s.getTravelDist();
final RouteCalculationParams params = new RouteCalculationParams();
params.inSnapToRoadMode = true;
params.start = start;
params.end = end;
RoutingHelper.applyApplicationSettings(params, app.getSettings(), walkingMode);
params.mode = walkingMode;
params.ctx = app;
params.calculationProgress = new RouteCalculationProgress();
params.calculationProgressCallback = new RouteCalculationProgressCallback() {
@Override
public void start() {
}
@Override
public void updateProgress(int progress) {
float p = Math.max(params.calculationProgress.distanceFromBegin,
params.calculationProgress.distanceFromEnd);
RouteRecalculationThread.this.params.calculationProgress.distanceFromBegin =
Math.max(RouteRecalculationThread.this.params.calculationProgress.distanceFromBegin, currentDistanceFromBegin + p);
}
@Override
public void requestPrivateAccessRouting() {
}
@Override
public void finish() {
if (walkingSegmentsToCalculate.isEmpty()) {
walkingSegmentsCalculated = true;
} else {
updateProgress(0);
}
}
};
params.resultListener = new RouteCalculationResultListener() {
@Override
public void onRouteCalculated(RouteCalculationResult route) {
RouteRecalculationThread.this.walkingRouteSegments.put(walkingRouteSegment.s, route);
if (!walkingSegmentsToCalculate.isEmpty()) {
RouteCalculationParams walkingRouteParams = getWalkingRouteParams();
if (walkingRouteParams != null) {
routingHelper.startRouteCalculationThread(walkingRouteParams, true, true);
}
}
}
};
return params;
}
private void calculateWalkingRoutes(List<TransportRouteResult> routes) {
walkingSegmentsCalculated = false;
walkingSegmentsToCalculate.clear();
walkingRouteSegments.clear();
if (routes != null && routes.size() > 0) {
for (TransportRouteResult r : routes) {
LatLon start = params.start;
for (TransportRouteResultSegment s : r.getSegments()) {
LatLon end = s.getStart().getLocation();
double dist = MapUtils.getDistance(start, end);
if (dist > 50) {
walkingSegmentsToCalculate.add(new WalkingRouteSegment(s, start, end));
}
start = s.getEnd().getLocation();
}
walkingSegmentsToCalculate.add(new WalkingRouteSegment(r.getFinishWalkSegment(), start, params.end));
}
RouteCalculationParams walkingRouteParams = getWalkingRouteParams();
if (walkingRouteParams != null) {
routingHelper.startRouteCalculationThread(walkingRouteParams, true, true);
// wait until all segments calculated
while (!walkingSegmentsCalculated) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// ignore
}
}
}
}
}
@Override
public void run() {
synchronized (TransportRoutingHelper.this) {
@ -317,6 +463,9 @@ public class TransportRoutingHelper {
String error = null;
try {
res = calculateRouteImpl(params);
if (res != null) {
calculateWalkingRoutes(res);
}
} catch (IOException e) {
error = e.getMessage();
log.error(e);
@ -329,6 +478,7 @@ public class TransportRoutingHelper {
}
synchronized (TransportRoutingHelper.this) {
routes = res;
TransportRoutingHelper.this.walkingRouteSegments = walkingRouteSegments;
if (res != null) {
if (params.resultListener != null) {
params.resultListener.onRouteCalculated(res);

View file

@ -41,6 +41,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.TreeMap;
import gnu.trove.list.array.TByteArrayList;
@ -806,25 +807,37 @@ public class RouteLayer extends OsmandMapLayer {
LatLon p = start;
for (TransportRouteResultSegment s : r.getSegments()) {
LatLon floc = s.getStart().getLocation();
addRouteWalk(p, floc, res, colors);
addRouteWalk(s, 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);
addRouteWalk(r.getFinishWalkSegment(), 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) {
private void addRouteWalk(TransportRouteResultSegment s, LatLon start, LatLon end, List<Way> res, List<Integer> colors) {
final RouteCalculationResult walkingRouteSegment = transportHelper.getWalkingRouteSegment(s);
if (walkingRouteSegment != null && walkingRouteSegment.getRouteLocations().size() > 0) {
final List<Location> routeLocations = walkingRouteSegment.getRouteLocations();
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));
way.putTag(OSMSettings.OSMTagKey.NAME.getValue(), String.format(Locale.US, "Walk %d m", walkingRouteSegment.getWholeDistance()));
for (Location l : routeLocations) {
way.addNode(new Node(l.getLatitude(), l.getLongitude(), -1));
}
res.add(way);
addColors(null, 1, colors);
} else {
double dist = MapUtils.getDistance(start, end);
if (dist > 50) {
Way way = new Way(-1);
way.putTag(OSMSettings.OSMTagKey.NAME.getValue(), String.format(Locale.US, "Walk %.1f m", dist));
way.addNode(new Node(start.getLatitude(), start.getLongitude(), -1));
way.addNode(new Node(end.getLatitude(), end.getLongitude(), -1));
res.add(way);
addColors(null, 1, colors);
}
}
}