Skip to content

Commit 6d409ee

Browse files
gchevalgchevalier
and
gchevalier
authored
Restored the code from conveyal GTFSFeed to support interpolated stop times (graphhopper#2096)
See: https://github.com/conveyal/gtfs-lib/blob/dev/src/main/java/com/conveyal/gtfs/GTFSFeed.java Co-authored-by: gchevalier <[email protected]>
1 parent e14da30 commit 6d409ee

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

reader-gtfs/src/main/java/com/conveyal/gtfs/GTFSFeed.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public class GTFSFeed implements Cloneable, Closeable {
6363

6464
private static final Logger LOG = LoggerFactory.getLogger(GTFSFeed.class);
6565

66+
public static final double METERS_PER_DEGREE_LATITUDE = 111111.111;
67+
6668
private DB db;
6769

6870
public String feedId = null;
@@ -248,13 +250,55 @@ public Iterable<StopTime> getInterpolatedStopTimesForTrip (String trip_id) throw
248250
startOfInterpolatedBlock = stopTime;
249251
}
250252
else if (stopTimes[stopTime].departure_time != Entity.INT_MISSING && startOfInterpolatedBlock != -1) {
251-
throw new RuntimeException("Missing stop times not supported.");
253+
// we have found the end of the interpolated section
254+
int nInterpolatedStops = stopTime - startOfInterpolatedBlock;
255+
double totalLengthOfInterpolatedSection = 0;
256+
double[] lengthOfInterpolatedSections = new double[nInterpolatedStops];
257+
258+
for (int stopTimeToInterpolate = startOfInterpolatedBlock, i = 0; stopTimeToInterpolate < stopTime; stopTimeToInterpolate++, i++) {
259+
Stop start = stops.get(stopTimes[stopTimeToInterpolate - 1].stop_id);
260+
Stop end = stops.get(stopTimes[stopTimeToInterpolate].stop_id);
261+
double segLen = fastDistance(start.stop_lat, start.stop_lon, end.stop_lat, end.stop_lon);
262+
totalLengthOfInterpolatedSection += segLen;
263+
lengthOfInterpolatedSections[i] = segLen;
264+
}
265+
266+
// add the segment post-last-interpolated-stop
267+
Stop start = stops.get(stopTimes[stopTime - 1].stop_id);
268+
Stop end = stops.get(stopTimes[stopTime].stop_id);
269+
totalLengthOfInterpolatedSection += fastDistance(start.stop_lat, start.stop_lon, end.stop_lat, end.stop_lon);
270+
271+
int departureBeforeInterpolation = stopTimes[startOfInterpolatedBlock - 1].departure_time;
272+
int arrivalAfterInterpolation = stopTimes[stopTime].arrival_time;
273+
int totalTime = arrivalAfterInterpolation - departureBeforeInterpolation;
274+
275+
double lengthSoFar = 0;
276+
for (int stopTimeToInterpolate = startOfInterpolatedBlock, i = 0; stopTimeToInterpolate < stopTime; stopTimeToInterpolate++, i++) {
277+
lengthSoFar += lengthOfInterpolatedSections[i];
278+
279+
int time = (int) (departureBeforeInterpolation + totalTime * (lengthSoFar / totalLengthOfInterpolatedSection));
280+
stopTimes[stopTimeToInterpolate].arrival_time = stopTimes[stopTimeToInterpolate].departure_time = time;
281+
}
282+
283+
// we're done with this block
284+
startOfInterpolatedBlock = -1;
252285
}
253286
}
254287

255288
return Arrays.asList(stopTimes);
256289
}
257290

291+
/**
292+
* @return Equirectangular approximation to distance.
293+
*/
294+
public static double fastDistance (double lat0, double lon0, double lat1, double lon1) {
295+
double midLat = (lat0 + lat1) / 2;
296+
double xscale = Math.cos(Math.toRadians(midLat));
297+
double dx = xscale * (lon1 - lon0);
298+
double dy = (lat1 - lat0);
299+
return Math.sqrt(dx * dx + dy * dy) * METERS_PER_DEGREE_LATITUDE;
300+
}
301+
258302
public Collection<Frequency> getFrequencies (String trip_id) {
259303
// IntelliJ tells me all these casts are unnecessary, and that's also my feeling, but the code won't compile
260304
// without them

0 commit comments

Comments
 (0)