@@ -63,6 +63,8 @@ public class GTFSFeed implements Cloneable, Closeable {
63
63
64
64
private static final Logger LOG = LoggerFactory .getLogger (GTFSFeed .class );
65
65
66
+ public static final double METERS_PER_DEGREE_LATITUDE = 111111.111 ;
67
+
66
68
private DB db ;
67
69
68
70
public String feedId = null ;
@@ -248,13 +250,55 @@ public Iterable<StopTime> getInterpolatedStopTimesForTrip (String trip_id) throw
248
250
startOfInterpolatedBlock = stopTime ;
249
251
}
250
252
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 ;
252
285
}
253
286
}
254
287
255
288
return Arrays .asList (stopTimes );
256
289
}
257
290
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
+
258
302
public Collection <Frequency > getFrequencies (String trip_id ) {
259
303
// IntelliJ tells me all these casts are unnecessary, and that's also my feeling, but the code won't compile
260
304
// without them
0 commit comments