Skip to content

Commit b718baa

Browse files
authored
Merge pull request #7042 from entur/fix-missing-tx
Fix missing transfers
2 parents 725845d + c6f8673 commit b718baa

38 files changed

+1784
-1310
lines changed

application/src/ext-test/java/org/opentripplanner/ext/flex/FlexIntegrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
import org.opentripplanner.TestServerContext;
2121
import org.opentripplanner.framework.application.OTPFeature;
2222
import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore;
23-
import org.opentripplanner.graph_builder.module.DirectTransferGenerator;
2423
import org.opentripplanner.graph_builder.module.TestStreetLinkerModule;
24+
import org.opentripplanner.graph_builder.module.transfer.DirectTransferGenerator;
2525
import org.opentripplanner.gtfs.graphbuilder.GtfsBundleTestFactory;
2626
import org.opentripplanner.gtfs.graphbuilder.GtfsModule;
2727
import org.opentripplanner.model.GenericLocation;

application/src/main/java/org/opentripplanner/framework/application/OTPFeature.java

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,6 @@ public enum OTPFeature {
2222
),
2323
APIServerInfo(true, false, "Enable the server info endpoint."),
2424
APIUpdaterStatus(true, false, "Enable endpoint for graph updaters status."),
25-
IncludeEmptyRailStopsInTransfers(
26-
false,
27-
false,
28-
"""
29-
Turning this on guarantees that Rail stops without scheduled departures still get included
30-
when generating transfers using `ConsiderPatternsForDirectTransfers`. It is common for stops
31-
to be assign at real-time for Rail. Turning this on will help to avoid dropping transfers which
32-
are needed, when the stop is in use later. Turning this on, if
33-
ConsiderPatternsForDirectTransfers is off has no effect.
34-
"""
35-
),
3625
ConsiderPatternsForDirectTransfers(
3726
true,
3827
false,
@@ -54,6 +43,20 @@ public enum OTPFeature {
5443
),
5544
FloatingBike(true, false, "Enable floating bike routing."),
5645
GtfsGraphQlApi(true, false, "Enable the [GTFS GraphQL API](apis/GTFS-GraphQL-API.md)."),
46+
IncludeStopsUsedRealTimeInTransfers(
47+
false,
48+
false,
49+
"""
50+
When generating transfers, stops without any patterns are excluded to improve performance if
51+
`ConsiderPatternsForDirectTransfers` is enabled. However, some stops are only used by trips
52+
changed or added by real-time updates. Since transfer generation happens before real-time
53+
updates are applied, OTP cannot know which stops will be needed. Instead, OTP will attempt to
54+
identify stops likely to be used by real-time updates at import time. Common cases include rail
55+
stops (which often have late platform assignments) and stops reserved for replacement services.
56+
This is detected examining the stop `subMode`(NeTEx) and `vehicleType`(GTFS). This feature has
57+
no effect if `ConsiderPatternsForDirectTransfers` is disabled.
58+
"""
59+
),
5760
/**
5861
* If this feature flag is switched on, then the minimum transfer time is not the minimum transfer
5962
* time, but the definitive transfer time. Use this to override what we think the transfer will

application/src/main/java/org/opentripplanner/graph_builder/module/configure/GraphBuilderFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.opentripplanner.graph_builder.GraphBuilderDataSources;
2222
import org.opentripplanner.graph_builder.configure.GraphBuilderModule;
2323
import org.opentripplanner.graph_builder.issue.report.DataImportIssueReporter;
24-
import org.opentripplanner.graph_builder.module.DirectTransferGenerator;
2524
import org.opentripplanner.graph_builder.module.GraphCoherencyCheckerModule;
2625
import org.opentripplanner.graph_builder.module.OsmBoardingLocationsModule;
2726
import org.opentripplanner.graph_builder.module.RouteToCentroidStationIdsValidator;
@@ -33,6 +32,7 @@
3332
import org.opentripplanner.graph_builder.module.islandpruning.PruneIslands;
3433
import org.opentripplanner.graph_builder.module.ned.ElevationModule;
3534
import org.opentripplanner.graph_builder.module.osm.OsmModule;
35+
import org.opentripplanner.graph_builder.module.transfer.DirectTransferGenerator;
3636
import org.opentripplanner.gtfs.graphbuilder.GtfsModule;
3737
import org.opentripplanner.netex.NetexModule;
3838
import org.opentripplanner.routing.fares.FareServiceFactory;

application/src/main/java/org/opentripplanner/graph_builder/module/configure/GraphBuilderModules.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.opentripplanner.graph_builder.issue.report.DataImportIssueReporter;
2222
import org.opentripplanner.graph_builder.issue.service.DefaultDataImportIssueStore;
2323
import org.opentripplanner.graph_builder.model.ConfiguredDataSource;
24-
import org.opentripplanner.graph_builder.module.DirectTransferGenerator;
2524
import org.opentripplanner.graph_builder.module.RouteToCentroidStationIdsValidator;
2625
import org.opentripplanner.graph_builder.module.StreetLinkerModule;
2726
import org.opentripplanner.graph_builder.module.TurnRestrictionModule;
@@ -33,6 +32,7 @@
3332
import org.opentripplanner.graph_builder.module.ned.parameter.DemExtractParameters;
3433
import org.opentripplanner.graph_builder.module.osm.OsmModule;
3534
import org.opentripplanner.graph_builder.module.osm.parameters.OsmExtractParameters;
35+
import org.opentripplanner.graph_builder.module.transfer.DirectTransferGenerator;
3636
import org.opentripplanner.graph_builder.services.ned.ElevationGridCoverageFactory;
3737
import org.opentripplanner.gtfs.graphbuilder.GtfsBundle;
3838
import org.opentripplanner.gtfs.graphbuilder.GtfsModule;

application/src/main/java/org/opentripplanner/graph_builder/module/nearbystops/MinMap.java

Lines changed: 0 additions & 41 deletions
This file was deleted.

application/src/main/java/org/opentripplanner/graph_builder/module/nearbystops/PatternConsideringNearbyStopFinder.java

Lines changed: 0 additions & 103 deletions
This file was deleted.

application/src/main/java/org/opentripplanner/graph_builder/module/DirectTransferGenerator.java renamed to application/src/main/java/org/opentripplanner/graph_builder/module/transfer/DirectTransferGenerator.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package org.opentripplanner.graph_builder.module;
1+
package org.opentripplanner.graph_builder.module.transfer;
22

33
import com.google.common.collect.HashMultimap;
44
import com.google.common.collect.Multimaps;
@@ -15,12 +15,13 @@
1515
import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore;
1616
import org.opentripplanner.graph_builder.issues.StopNotLinkedForTransfers;
1717
import org.opentripplanner.graph_builder.model.GraphBuilderModule;
18+
import org.opentripplanner.graph_builder.module.TransferParameters;
1819
import org.opentripplanner.graph_builder.module.nearbystops.NearbyStopFinder;
19-
import org.opentripplanner.graph_builder.module.nearbystops.PatternConsideringNearbyStopFinder;
2020
import org.opentripplanner.graph_builder.module.nearbystops.SiteRepositoryResolver;
2121
import org.opentripplanner.graph_builder.module.nearbystops.StopResolver;
2222
import org.opentripplanner.graph_builder.module.nearbystops.StraightLineNearbyStopFinder;
2323
import org.opentripplanner.graph_builder.module.nearbystops.StreetNearbyStopFinder;
24+
import org.opentripplanner.graph_builder.module.transfer.filter.PatternConsideringNearbyStopFinder;
2425
import org.opentripplanner.model.PathTransfer;
2526
import org.opentripplanner.routing.api.request.RouteRequest;
2627
import org.opentripplanner.routing.api.request.StreetMode;
@@ -388,9 +389,6 @@ private void calculateDefaultTransfers(
388389
if (sd.stop == stop) {
389390
continue;
390391
}
391-
if (sd.stop.transfersNotAllowed()) {
392-
continue;
393-
}
394392
createPathTransfer(stop, sd.stop, sd, distinctTransfers, mode);
395393
}
396394
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package org.opentripplanner.graph_builder.module.transfer.filter;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collection;
5+
import java.util.HashSet;
6+
import java.util.List;
7+
import java.util.Set;
8+
import org.opentripplanner.routing.graphfinder.NearbyStop;
9+
import org.opentripplanner.transit.model.framework.FeedScopedId;
10+
11+
/**
12+
* Combines multiple {@link NearbyStopFilter}s into a single filter.
13+
* <p>
14+
* This filter applies all configured filters and returns the union of their results. A stop is
15+
* included if ANY of the component filters include it (OR logic for from-stops, union for
16+
* to-stops).
17+
*/
18+
class CompositeNearbyStopFilter implements NearbyStopFilter {
19+
20+
private final List<NearbyStopFilter> filters;
21+
22+
private CompositeNearbyStopFilter(List<NearbyStopFilter> filters) {
23+
this.filters = filters;
24+
}
25+
26+
static Builder of() {
27+
return new Builder();
28+
}
29+
30+
@Override
31+
public boolean includeFromStop(FeedScopedId id, boolean reverseDirection) {
32+
for (NearbyStopFilter filter : filters) {
33+
if (filter.includeFromStop(id, reverseDirection)) {
34+
return true;
35+
}
36+
}
37+
return false;
38+
}
39+
40+
@Override
41+
public Collection<NearbyStop> filterToStops(
42+
Collection<NearbyStop> nearbyStops,
43+
boolean reverseDirection
44+
) {
45+
Set<NearbyStop> result = new HashSet<>();
46+
47+
for (NearbyStopFilter it : filters) {
48+
result.addAll(it.filterToStops(nearbyStops, reverseDirection));
49+
}
50+
return result;
51+
}
52+
53+
static class Builder {
54+
55+
List<NearbyStopFilter> filters = new ArrayList<>();
56+
57+
Builder add(NearbyStopFilter filter) {
58+
filters.add(filter);
59+
return this;
60+
}
61+
62+
NearbyStopFilter build() {
63+
if (filters.size() == 1) {
64+
return filters.getFirst();
65+
}
66+
return new CompositeNearbyStopFilter(filters);
67+
}
68+
}
69+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package org.opentripplanner.graph_builder.module.transfer.filter;
2+
3+
import java.util.Collection;
4+
import org.opentripplanner.ext.flex.trip.FlexTrip;
5+
import org.opentripplanner.routing.graphfinder.NearbyStop;
6+
import org.opentripplanner.transit.model.framework.FeedScopedId;
7+
import org.opentripplanner.transit.service.TransitService;
8+
9+
/**
10+
* Filters nearby stops based on flex trip availability.
11+
* <p>
12+
* This filter ensures that transfers are generated for stops used by flex trips. For each flex
13+
* trip, it keeps only the closest stop where the flex trip can board or alight (depending on
14+
* direction).
15+
*/
16+
class FlexTripNearbyStopFilter implements NearbyStopFilter {
17+
18+
private final TransitService transitService;
19+
20+
FlexTripNearbyStopFilter(TransitService transitService) {
21+
this.transitService = transitService;
22+
}
23+
24+
@Override
25+
public boolean includeFromStop(FeedScopedId id, boolean reverseDirection) {
26+
var stop = transitService.getStopLocation(id);
27+
return !transitService.getFlexIndex().getFlexTripsByStop(stop).isEmpty();
28+
}
29+
30+
@Override
31+
public Collection<NearbyStop> filterToStops(
32+
Collection<NearbyStop> nearbyStops,
33+
boolean reverseDirection
34+
) {
35+
MinMap<FlexTrip<?, ?>, NearbyStop> closestStopForFlexTrip = new MinMap<>();
36+
for (var it : nearbyStops) {
37+
var stop = it.stop;
38+
var flexTrips = transitService.getFlexIndex().getFlexTripsByStop(stop);
39+
40+
for (FlexTrip<?, ?> trip : flexTrips) {
41+
if (reverseDirection ? trip.isAlightingPossible(stop) : trip.isBoardingPossible(stop)) {
42+
closestStopForFlexTrip.putMin(trip, it);
43+
}
44+
}
45+
}
46+
return closestStopForFlexTrip.values();
47+
}
48+
}

0 commit comments

Comments
 (0)