@@ -28,12 +28,12 @@ class GtfsReader {
28
28
private static class EnterAndExitNodeIdWithStopId {
29
29
final String stopId ;
30
30
final Collection <Integer > enterNodeIds ;
31
- final int exitNodeId ;
31
+ final Collection < Integer > exitNodeIds ;
32
32
33
- private EnterAndExitNodeIdWithStopId (Collection <Integer > enterNodeIds , String stopId , int exitNodeId ) {
33
+ private EnterAndExitNodeIdWithStopId (Collection <Integer > enterNodeIds , String stopId , Collection < Integer > exitNodeIds ) {
34
34
this .stopId = stopId ;
35
35
this .enterNodeIds = enterNodeIds ;
36
- this .exitNodeId = exitNodeId ;
36
+ this .exitNodeIds = exitNodeIds ;
37
37
}
38
38
}
39
39
@@ -66,10 +66,11 @@ private TimelineNodeIdWithTripId(int timelineNodeId, String tripId) {
66
66
private final String id ;
67
67
private int i ;
68
68
private GTFSFeed feed ;
69
- private TIntIntHashMap times ;
70
- private SetMultimap <String , TimelineNodeIdWithTripId > stopTimelineNodes ;
69
+ private final TIntIntHashMap times = new TIntIntHashMap ();
70
+ private final SetMultimap <String , TimelineNodeIdWithTripId > departureTimelineNodes = HashMultimap .create ();
71
+ private final SetMultimap <String , TimelineNodeIdWithTripId > arrivalTimelineNodes = HashMultimap .create ();
71
72
private Collection <EnterAndExitNodeIdWithStopId > stopEnterAndExitNodes = new ArrayList <>();
72
- private SetMultimap <String , Integer > arrivals ;
73
+ private final SetMultimap <String , Integer > arrivals = HashMultimap . create () ;
73
74
private final PtFlagEncoder encoder ;
74
75
75
76
GtfsReader (String id , GraphHopperStorage ghStorage , LocationIndex walkNetworkIndex ) {
@@ -87,33 +88,36 @@ public void readGraph() {
87
88
gtfsStorage .getFares ().putAll (feed .fares );
88
89
i = graph .getNodes ();
89
90
buildPtNetwork ();
90
- EdgeFilter filter = new EverythingButPt (encoder );
91
91
for (EnterAndExitNodeIdWithStopId entry : stopEnterAndExitNodes ) {
92
- QueryResult source = walkNetworkIndex .findClosest (nodeAccess .getLat (entry .exitNodeId ), nodeAccess .getLon (entry .exitNodeId ), filter );
93
92
Stop stop = feed .stops .get (entry .stopId );
94
- int streetNode ;
95
- if (!source .isValid ()) {
96
- streetNode = i ;
97
- nodeAccess .setNode (i ++, stop .stop_lat , stop .stop_lon );
98
- graph .edge (streetNode , streetNode , 0.0 , false );
99
- } else {
100
- streetNode = source .getClosestNode ();
101
- }
102
93
for (Integer enterNodeId : entry .enterNodeIds ) {
94
+ int streetNode = findStreetNodeForPlatformNode (enterNodeId );
103
95
EdgeIteratorState entryEdge = graph .edge (streetNode , enterNodeId , 0.0 , false );
104
96
setEdgeType (entryEdge , GtfsStorage .EdgeType .ENTER_PT );
105
97
entryEdge .setName (stop .stop_name );
106
98
}
107
- EdgeIteratorState exitEdge = graph .edge (entry .exitNodeId , streetNode , 0.0 , false );
108
- setEdgeType (exitEdge , GtfsStorage .EdgeType .EXIT_PT );
109
- exitEdge .setName (stop .stop_name );
99
+ for (Integer exitNodeId : entry .exitNodeIds ) {
100
+ int streetNode = findStreetNodeForPlatformNode (exitNodeId );
101
+ EdgeIteratorState exitEdge = graph .edge (exitNodeId , streetNode , 0.0 , false );
102
+ setEdgeType (exitEdge , GtfsStorage .EdgeType .EXIT_PT );
103
+ exitEdge .setName (stop .stop_name );
104
+ }
105
+ }
106
+ }
107
+
108
+ private int findStreetNodeForPlatformNode (int platformNodeId ) {
109
+ int streetNode ;
110
+ EdgeFilter filter = new EverythingButPt (encoder );
111
+ QueryResult source = walkNetworkIndex .findClosest (nodeAccess .getLat (platformNodeId ), nodeAccess .getLon (platformNodeId ), filter );
112
+ if (!source .isValid ()) {
113
+ throw new RuntimeException ("Can't find street node for a platform. Did you import OSM data (or create a fake walk network)?" );
114
+ } else {
115
+ streetNode = source .getClosestNode ();
110
116
}
117
+ return streetNode ;
111
118
}
112
119
113
120
private void buildPtNetwork () {
114
- stopTimelineNodes = HashMultimap .create ();
115
- arrivals = HashMultimap .create ();
116
- times = new TIntIntHashMap ();
117
121
LocalDate startDate = feed .calculateStats ().getStartDate ();
118
122
gtfsStorage .setStartDate (startDate );
119
123
LocalDate endDate = feed .calculateStats ().getEndDate ();
@@ -173,25 +177,21 @@ private void buildPtNetwork() {
173
177
edge .setFlags (encoder .setTime (edge .getFlags (), stopTime .arrival_time - prev .departure_time ));
174
178
gtfsStorage .getStopSequences ().put (edge .getEdge (), stopTime .stop_sequence );
175
179
}
176
- nodeAccess .setNode (i ++, stop .stop_lat , stop .stop_lon );
177
- final int timelineNode = i - 1 ;
178
- nodeAccess .setAdditionalNodeField (timelineNode , NodeType .INTERNAL_PT .ordinal ());
179
- times .put (timelineNode , stopTime .departure_time + time );
180
- stopTimelineNodes .put (stopTime .stop_id , new TimelineNodeIdWithTripId (timelineNode , trip .trip_id ));
180
+ final int departureTimelineNode = i ++;
181
+ nodeAccess .setNode (departureTimelineNode , stop .stop_lat , stop .stop_lon );
182
+ nodeAccess .setAdditionalNodeField (departureTimelineNode , NodeType .INTERNAL_PT .ordinal ());
183
+ times .put (departureTimelineNode , stopTime .departure_time + time );
184
+ departureTimelineNodes .put (stopTime .stop_id , new TimelineNodeIdWithTripId (departureTimelineNode , trip .trip_id ));
185
+ final int arrivalTimelineNode = i ++;
186
+ nodeAccess .setNode (arrivalTimelineNode , stop .stop_lat , stop .stop_lon );
187
+ nodeAccess .setAdditionalNodeField (arrivalTimelineNode , NodeType .INTERNAL_PT .ordinal ());
188
+ times .put (arrivalTimelineNode , stopTime .arrival_time + time );
189
+ arrivalTimelineNodes .put (stopTime .stop_id , new TimelineNodeIdWithTripId (arrivalTimelineNode , trip .trip_id ));
181
190
departureNode = i ++;
182
191
nodeAccess .setNode (departureNode , stop .stop_lat , stop .stop_lon );
183
192
nodeAccess .setAdditionalNodeField (departureNode , NodeType .INTERNAL_PT .ordinal ());
184
193
times .put (departureNode , stopTime .departure_time + time );
185
- EdgeIteratorState edge = graph .edge (
186
- i - 2 ,
187
- departureNode ,
188
- 0.0 ,
189
- false );
190
- edge .setName (getRouteName (feed , trip ));
191
194
int dayShift = stopTime .departure_time / (24 * 60 * 60 );
192
- setEdgeType (edge , GtfsStorage .EdgeType .BOARD );
193
- gtfsStorage .getStopSequences ().put (edge .getEdge (), stopTime .stop_sequence );
194
- gtfsStorage .getExtraStrings ().put (edge .getEdge (), trip .trip_id );
195
195
BitSet validOn = getValidOn (validOnDay , dayShift );
196
196
int validityId ;
197
197
if (gtfsStorage .getOperatingDayPatterns ().containsKey (validOn )) {
@@ -200,16 +200,40 @@ private void buildPtNetwork() {
200
200
validityId = gtfsStorage .getOperatingDayPatterns ().size ();
201
201
gtfsStorage .getOperatingDayPatterns ().put (validOn , validityId );
202
202
}
203
- edge .setFlags (encoder .setValidityId (edge .getFlags (), validityId ));
204
- edge .setFlags (encoder .setTransfers (edge .getFlags (), 1 ));
205
- edge = graph .edge (
206
- i - 3 ,
203
+
204
+ EdgeIteratorState boardEdge = graph .edge (
205
+ departureTimelineNode ,
207
206
departureNode ,
208
207
0.0 ,
209
208
false );
210
- edge .setName (getRouteName (feed , trip ));
211
- setEdgeType (edge , GtfsStorage .EdgeType .DWELL );
212
- edge .setFlags (encoder .setTime (edge .getFlags (), stopTime .departure_time - stopTime .arrival_time ));
209
+ boardEdge .setName (getRouteName (feed , trip ));
210
+ setEdgeType (boardEdge , GtfsStorage .EdgeType .BOARD );
211
+ gtfsStorage .getStopSequences ().put (boardEdge .getEdge (), stopTime .stop_sequence );
212
+ gtfsStorage .getExtraStrings ().put (boardEdge .getEdge (), trip .trip_id );
213
+ boardEdge .setFlags (encoder .setValidityId (boardEdge .getFlags (), validityId ));
214
+ boardEdge .setFlags (encoder .setTransfers (boardEdge .getFlags (), 1 ));
215
+
216
+ EdgeIteratorState alightEdge = graph .edge (
217
+ arrivalNode ,
218
+ arrivalTimelineNode ,
219
+ 0.0 ,
220
+ false );
221
+ alightEdge .setName (getRouteName (feed , trip ));
222
+ setEdgeType (alightEdge , GtfsStorage .EdgeType .ALIGHT );
223
+ gtfsStorage .getStopSequences ().put (alightEdge .getEdge (), stopTime .stop_sequence );
224
+ gtfsStorage .getExtraStrings ().put (alightEdge .getEdge (), trip .trip_id );
225
+ alightEdge .setFlags (encoder .setValidityId (alightEdge .getFlags (), validityId ));
226
+ // alightEdge.setFlags(encoder.setTransfers(alightEdge.getFlags(), 1));
227
+
228
+
229
+ EdgeIteratorState dwellEdge = graph .edge (
230
+ arrivalNode ,
231
+ departureNode ,
232
+ 0.0 ,
233
+ false );
234
+ dwellEdge .setName (getRouteName (feed , trip ));
235
+ setEdgeType (dwellEdge , GtfsStorage .EdgeType .DWELL );
236
+ dwellEdge .setFlags (encoder .setTime (dwellEdge .getFlags (), stopTime .departure_time - stopTime .arrival_time ));
213
237
if (prev == null ) {
214
238
insertInboundBlockTransfers (arrivalNodes , trip , departureNode , stopTime , stop , validityId );
215
239
}
@@ -223,34 +247,50 @@ private void buildPtNetwork() {
223
247
224
248
for (Stop stop : feed .stops .values ()) {
225
249
if (stop .location_type == 0 ) { // Only stops. Not interested in parent stations for now.
226
- nodeAccess .setNode (i ++, stop .stop_lat , stop .stop_lon );
227
- int stopExitNode = i -1 ;
228
- nodeAccess .setAdditionalNodeField (stopExitNode , NodeType .STOP_EXIT_NODE .ordinal ());
229
- for (Integer arrivalNodeId : arrivals .get (stop .stop_id )) {
230
- EdgeIteratorState leaveTimeExpandedNetworkEdge = graph .edge (arrivalNodeId , stopExitNode , 0.0 , false );
231
- setEdgeType (leaveTimeExpandedNetworkEdge , GtfsStorage .EdgeType .LEAVE_TIME_EXPANDED_NETWORK );
232
- int arrivalTime = times .get (arrivalNodeId );
233
- leaveTimeExpandedNetworkEdge .setFlags (encoder .setTime (leaveTimeExpandedNetworkEdge .getFlags (), arrivalTime ));
234
- }
235
- final Map <String , List <TimelineNodeIdWithTripId >> timelineNodesByRoute = stopTimelineNodes .get (stop .stop_id ).stream ().collect (Collectors .groupingBy (t -> feed .trips .get (t .tripId ).route_id ));
250
+ final Map <String , List <TimelineNodeIdWithTripId >> arrivalTimelineNodesByRoute = arrivalTimelineNodes .get (stop .stop_id ).stream ().collect (Collectors .groupingBy (t -> feed .trips .get (t .tripId ).route_id ));
251
+
252
+ List <Integer > stopExitNodeIds = new ArrayList <>();
253
+ arrivalTimelineNodesByRoute .forEach ((routeId , timelineNodesWithTripId ) -> {
254
+ nodeAccess .setNode (i ++, stop .stop_lat , stop .stop_lon );
255
+ int stopExitNode = i -1 ;
256
+ nodeAccess .setAdditionalNodeField (stopExitNode , NodeType .STOP_EXIT_NODE .ordinal ());
257
+ stopExitNodeIds .add (stopExitNode );
258
+ NavigableSet <Fun .Tuple2 <Integer , Integer >> timeNodes = new TreeSet <>();
259
+ timelineNodesWithTripId .stream ().map (t -> t .timelineNodeId )
260
+ .forEach (nodeId -> timeNodes .add (new Fun .Tuple2 <>(times .get (nodeId ) % (24 *60 *60 ), nodeId )));
261
+ wireUpAndAndConnectArrivalTimeline (stop , routeId ,stopExitNode , timeNodes );
262
+ });
263
+
264
+
265
+
266
+ final Map <String , List <TimelineNodeIdWithTripId >> departureTimelineNodesByRoute = departureTimelineNodes .get (stop .stop_id ).stream ().collect (Collectors .groupingBy (t -> feed .trips .get (t .tripId ).route_id ));
236
267
237
268
List <Integer > stopEnterNodeIds = new ArrayList <>();
238
- timelineNodesByRoute .forEach ((routeId , timelineNodesWithTripId ) -> {
269
+ departureTimelineNodesByRoute .forEach ((routeId , timelineNodesWithTripId ) -> {
239
270
nodeAccess .setNode (i ++, stop .stop_lat , stop .stop_lon );
240
271
int stopEnterNode = i -1 ;
241
272
nodeAccess .setAdditionalNodeField (stopEnterNode , NodeType .STOP_ENTER_NODE .ordinal ());
242
273
stopEnterNodeIds .add (stopEnterNode );
243
274
NavigableSet <Fun .Tuple2 <Integer , Integer >> timeNodes = new TreeSet <>();
244
275
timelineNodesWithTripId .stream ().map (t -> t .timelineNodeId )
245
276
.forEach (nodeId -> timeNodes .add (new Fun .Tuple2 <>(times .get (nodeId ) % (24 *60 *60 ), nodeId )));
246
- wireUpAndAndConnectTimeline (stop , routeId ,stopEnterNode , timeNodes );
277
+ wireUpAndAndConnectDepartureTimeline (stop , routeId ,stopEnterNode , timeNodes );
247
278
});
248
- stopEnterAndExitNodes .add (new EnterAndExitNodeIdWithStopId (stopEnterNodeIds , stop .stop_id , stopExitNode ));
279
+ stopEnterAndExitNodes .add (new EnterAndExitNodeIdWithStopId (stopEnterNodeIds , stop .stop_id , stopExitNodeIds ));
249
280
}
250
281
}
251
282
}
252
283
253
- private void wireUpAndAndConnectTimeline (Stop stop , String routeId , int stopEnterNode , NavigableSet <Fun .Tuple2 <Integer , Integer >> timeNodes ) {
284
+ private void wireUpAndAndConnectArrivalTimeline (Stop stop , String routeId , int stopExitNode , NavigableSet <Fun .Tuple2 <Integer , Integer >> timeNodes ) {
285
+ for (Fun .Tuple2 <Integer , Integer > e : timeNodes .descendingSet ()) {
286
+ EdgeIteratorState leaveTimeExpandedNetworkEdge = graph .edge (e .b , stopExitNode , 0.0 , false );
287
+ setEdgeType (leaveTimeExpandedNetworkEdge , GtfsStorage .EdgeType .LEAVE_TIME_EXPANDED_NETWORK );
288
+ int arrivalTime = e .a ;
289
+ leaveTimeExpandedNetworkEdge .setFlags (encoder .setTime (leaveTimeExpandedNetworkEdge .getFlags (), arrivalTime ));
290
+ }
291
+ }
292
+
293
+ private void wireUpAndAndConnectDepartureTimeline (Stop stop , String routeId , int stopEnterNode , NavigableSet <Fun .Tuple2 <Integer , Integer >> timeNodes ) {
254
294
int time = 0 ;
255
295
int prev = -1 ;
256
296
for (Fun .Tuple2 <Integer , Integer > e : timeNodes .descendingSet ()) {
0 commit comments