MATSIM
PreparedTransitSchedule.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * *
4  * *********************************************************************** *
5  * *
6  * copyright : (C) 2012 by the members listed in the COPYING, *
7  * LICENSE and WARRANTY file. *
8  * email : info at matsim dot org *
9  * *
10  * *********************************************************************** *
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * See also COPYING, LICENSE and WARRANTY file *
17  * *
18  * *********************************************************************** */
19 
20 package org.matsim.pt.router;
21 
22 import java.util.Arrays;
23 import java.util.Map;
24 import java.util.concurrent.ConcurrentHashMap;
25 
30 
44 
45  final static double MIDNIGHT = 24.0*3600;
46 
47  /*
48  * This needs to be a ConcurrentHashMap since multiple threads might add
49  * data concurrently. Alternatively, the map could be filled with data
50  * before getNextDepartureTime(...) - then all concurrent accesses would be
51  * read only.
52  * cdobler, nov'12
53  */
54  private final Map<TransitRoute, double[]> sortedDepartureCache = new ConcurrentHashMap<TransitRoute, double[]>();
55 
56  /*
57  * Conceptually, an instance of this class wraps a TransitSchedule to optimize a function of it.
58  */
60 
61  }
62 
63  @Deprecated
64  /*
65  * See other constructor.
66  */
68 
69  }
70 
71  public double getNextDepartureTime(final TransitRoute route, final TransitRouteStop stop, final double depTime) {
72 
73  double earliestDepartureTimeAtTerminus = depTime - stop.getDepartureOffset().seconds();
74  // This shifts my time back to the terminus.
75 
76  if (earliestDepartureTimeAtTerminus >= MIDNIGHT) {
77  earliestDepartureTimeAtTerminus = earliestDepartureTimeAtTerminus % MIDNIGHT;
78  }
79  if (earliestDepartureTimeAtTerminus < 0) {
80  // this may happen when depTime < departureOffset, e.g. I want to start at 24:03, but the bus departs at 23:55 at terminus
81  earliestDepartureTimeAtTerminus += MIDNIGHT;
82  }
83 
84  // this will search for the terminus departure that corresponds to my departure at the stop:
85  double[] cache = sortedDepartureCache.get(route);
86  if (cache == null) {
87  cache = new double[route.getDepartures().size()];
88  int i = 0;
89  for (Departure dep : route.getDepartures().values()) {
90  cache[i++] = dep.getDepartureTime();
91  }
92  Arrays.sort(cache);
93  sortedDepartureCache.put(route, cache);
94  }
95  int pos = Arrays.binarySearch(cache, earliestDepartureTimeAtTerminus);
96  if (pos < 0) {
97  // (if the departure time is not found _exactly_, binarySearch returns (-(insertion point) - 1). That is
98  // retval = -(insertion point) - 1 or insertion point = -(retval+1) .
99  // This will, in fact, be the normal situation, so it is important to understand this.)
100  pos = -(pos + 1);
101  }
102  if (pos >= cache.length) {
103  pos = 0; // there is no later departure time, take the first in the morning
104  }
105  double bestDepartureTime = cache[pos];
106  // (departure time at terminus)
107 
108  bestDepartureTime += stop.getDepartureOffset().seconds();
109  // (resulting departure time at stop)
110 
111  while (bestDepartureTime < depTime) {
112  bestDepartureTime += MIDNIGHT;
113  // (add enough "MIDNIGHT"s until we are _after_ the desired departure time)
114  }
115  return bestDepartureTime;
116  }
117 }
final Map< TransitRoute, double[]> sortedDepartureCache
double getNextDepartureTime(final TransitRoute route, final TransitRouteStop stop, final double depTime)
Map< Id< Departure >, Departure > getDepartures()