better transit times
This commit is contained in:
parent
974f005549
commit
205302dbb8
22 changed files with 247 additions and 69 deletions
|
|
@ -25,11 +25,14 @@ public class Router {
|
|||
|
||||
private static final int ZOOM = 9; // R5 enforces range 9-12
|
||||
private static final int MAX_GRID_CELLS = 4_900_000; // under R5's 5M limit
|
||||
private static final int DEPARTURE_FROM_TIME = 7 * 3600; // 07:00
|
||||
private static final int DEPARTURE_TO_TIME = 9 * 3600; // 09:00
|
||||
private static final int MAX_TRIP_DURATION_MINUTES = 120;
|
||||
|
||||
/** Result of computing travel times for a single origin with spatial pre-filtering. */
|
||||
record FilteredResult(int[] originalIndices, short[] times) {}
|
||||
record FilteredResult(int[] originalIndices, short[] times, short[] bestTimes) {}
|
||||
|
||||
/** Max plausible travel radius in km for 120-minute trips. */
|
||||
/** Max plausible travel radius in km for {@link #MAX_TRIP_DURATION_MINUTES}-minute trips. */
|
||||
static double maxRadiusKm(String mode) {
|
||||
return switch (mode) {
|
||||
case "car" -> 150;
|
||||
|
|
@ -40,7 +43,10 @@ public class Router {
|
|||
};
|
||||
}
|
||||
|
||||
/** Load or build the transport network with Kryo caching. */
|
||||
/**
|
||||
* Load or build the transport network with Kryo caching.
|
||||
* The returned network is read-only after buildDistanceTables — safe for concurrent use.
|
||||
*/
|
||||
static TransportNetwork loadNetwork(String dataDir, String cacheDir) throws Exception {
|
||||
System.err.println("Loading transport network...");
|
||||
File cacheFile = new File(cacheDir, "network.dat");
|
||||
|
|
@ -78,7 +84,7 @@ public class Router {
|
|||
// 1. Filter destinations by bounding box
|
||||
int[] filtered = filterByDistance(allLats, allLons, originLat, originLon, maxRadius);
|
||||
if (filtered.length == 0) {
|
||||
return new FilteredResult(new int[0], new short[0]);
|
||||
return new FilteredResult(new int[0], new short[0], null);
|
||||
}
|
||||
|
||||
// 2. Extract filtered coordinate arrays
|
||||
|
|
@ -93,9 +99,14 @@ public class Router {
|
|||
List<DestinationChunk> chunks = buildDestinationChunks(fLats, fLons);
|
||||
|
||||
// 4. Compute travel times
|
||||
short[] times = computeTravelTimes(network, chunks, originLat, originLon, mode, fLats.length, date);
|
||||
boolean isTransit = mode.equals("transit");
|
||||
short[][] allTimes = computeTravelTimes(network, chunks, originLat, originLon, mode, fLats.length, date);
|
||||
|
||||
return new FilteredResult(filtered, times);
|
||||
// For transit: allTimes[0]=best (5th percentile), allTimes[1]=median (50th)
|
||||
// For others: allTimes[0]=median (50th), no best
|
||||
short[] medianTimes = isTransit ? allTimes[1] : allTimes[0];
|
||||
short[] bestTimes = isTransit ? allTimes[0] : null;
|
||||
return new FilteredResult(filtered, medianTimes, bestTimes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -175,13 +186,18 @@ public class Router {
|
|||
return chunks;
|
||||
}
|
||||
|
||||
/** Compute travel times from one origin to all destinations across all chunks. */
|
||||
private static short[] computeTravelTimes(
|
||||
/**
|
||||
* Compute travel times from one origin to all destinations across all chunks.
|
||||
* Returns one short[] per requested percentile (transit gets 2: best + median, others get 1: median).
|
||||
*/
|
||||
private static short[][] computeTravelTimes(
|
||||
TransportNetwork network, List<DestinationChunk> chunks,
|
||||
double originLat, double originLon, String mode, int nDest, LocalDate date) {
|
||||
|
||||
short[] times = new short[nDest];
|
||||
Arrays.fill(times, (short) -1);
|
||||
boolean isTransit = mode.equals("transit");
|
||||
int nPercentiles = isTransit ? 2 : 1;
|
||||
short[][] allTimes = new short[nPercentiles][nDest];
|
||||
for (short[] arr : allTimes) Arrays.fill(arr, (short) -1);
|
||||
|
||||
for (DestinationChunk chunk : chunks) {
|
||||
RegionalTask task = buildTask(chunk, originLat, originLon, mode, date);
|
||||
|
|
@ -191,14 +207,16 @@ public class Router {
|
|||
TravelTimeResult tt = result.travelTimes;
|
||||
if (tt != null) {
|
||||
int[][] values = tt.getValues();
|
||||
for (int i = 0; i < chunk.originalIndices.length && i < values[0].length; i++) {
|
||||
if (values[0][i] != Integer.MAX_VALUE) {
|
||||
times[chunk.originalIndices[i]] = (short) values[0][i];
|
||||
for (int p = 0; p < nPercentiles && p < values.length; p++) {
|
||||
for (int i = 0; i < chunk.originalIndices.length && i < values[p].length; i++) {
|
||||
if (values[p][i] != Integer.MAX_VALUE) {
|
||||
allTimes[p][chunk.originalIndices[i]] = (short) values[p][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return times;
|
||||
return allTimes;
|
||||
}
|
||||
|
||||
// --- Private helpers ---
|
||||
|
|
@ -241,7 +259,7 @@ public class Router {
|
|||
task.fromLat = originLat;
|
||||
task.fromLon = originLon;
|
||||
task.date = date;
|
||||
task.percentiles = new int[]{50};
|
||||
task.percentiles = mode.equals("transit") ? new int[]{5, 50} : new int[]{50};
|
||||
task.recordTimes = true;
|
||||
task.destinationPointSets = new PointSet[]{chunk.pointSet};
|
||||
task.zoom = chunk.extents.zoom;
|
||||
|
|
@ -249,9 +267,9 @@ public class Router {
|
|||
task.north = chunk.extents.north;
|
||||
task.width = chunk.extents.width;
|
||||
task.height = chunk.extents.height;
|
||||
task.fromTime = 8 * 3600;
|
||||
task.toTime = 8 * 3600 + 60;
|
||||
task.maxTripDurationMinutes = 120;
|
||||
task.fromTime = DEPARTURE_FROM_TIME;
|
||||
task.toTime = DEPARTURE_TO_TIME;
|
||||
task.maxTripDurationMinutes = MAX_TRIP_DURATION_MINUTES;
|
||||
|
||||
configureMode(task, mode);
|
||||
return task;
|
||||
|
|
@ -267,13 +285,14 @@ public class Router {
|
|||
task.accessModes = EnumSet.of(LegMode.WALK);
|
||||
task.egressModes = EnumSet.of(LegMode.WALK);
|
||||
task.directModes = EnumSet.of(LegMode.WALK);
|
||||
task.transitModes = EnumSet.of(TransitModes.TRANSIT);
|
||||
task.transitModes = EnumSet.allOf(TransitModes.class);
|
||||
}
|
||||
default -> throw new IllegalArgumentException("Unknown mode: " + mode);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setDirectMode(RegionalTask task, LegMode legMode) {
|
||||
task.maxRides = 0;
|
||||
task.accessModes = EnumSet.of(legMode);
|
||||
task.egressModes = EnumSet.of(legMode);
|
||||
task.directModes = EnumSet.of(legMode);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue