11package org .eqasim .core .simulation .modes .feeder_drt .router ;
22
3+ import org .eqasim .core .scenario .cutter .extent .ScenarioExtent ;
34import org .eqasim .core .simulation .modes .feeder_drt .router .access_egress_selector .AccessEgressStopsSelector ;
45import org .matsim .api .core .v01 .population .*;
56import org .matsim .core .router .DefaultRoutingRequest ;
@@ -23,14 +24,17 @@ public enum FeederDrtTripSegmentType {MAIN, DRT}
2324
2425 private final String mode ;
2526 private final AccessEgressStopsSelector accessEgressStopsSelector ;
27+ private final ScenarioExtent drtServiceAreaExtent ;
2628
2729 public FeederDrtRoutingModule (String mode ,RoutingModule feederRoutingModule , RoutingModule transitRoutingModule ,
28- PopulationFactory populationFactory , AccessEgressStopsSelector accessEgressStopsSelector ) {
30+ PopulationFactory populationFactory , AccessEgressStopsSelector accessEgressStopsSelector ,
31+ ScenarioExtent drtServiceAreaExtent ) {
2932 this .mode = mode ;
3033 this .drtRoutingModule = feederRoutingModule ;
3134 this .transitRoutingModule = transitRoutingModule ;
3235 this .populationFactory = populationFactory ;
3336 this .accessEgressStopsSelector = accessEgressStopsSelector ;
37+ this .drtServiceAreaExtent = drtServiceAreaExtent ;
3438 }
3539
3640 @ Override
@@ -46,19 +50,20 @@ public List<? extends PlanElement> calcRoute(RoutingRequest routingRequest) {
4650 Facility egressFacility = this .accessEgressStopsSelector .getEgressFacility (routingRequest );
4751
4852 List <PlanElement > intermodalRoute = new LinkedList <>();
49- // Computing the access DRT route
50- List <? extends PlanElement > drtRoute = null ;
53+ List <? extends PlanElement > accessDrtRoute = null ;
54+ List <? extends PlanElement > egressDrtRoute = null ;
5155
52- if (accessFacility != null ) {
53- drtRoute = drtRoutingModule .calcRoute (DefaultRoutingRequest .withoutAttributes (fromFacility , accessFacility , departureTime , person ));
56+ // Computing the access DRT route if it's possible
57+ if (accessFacility != null && (drtServiceAreaExtent == null || drtServiceAreaExtent .isInside (fromFacility .getCoord ()))) {
58+ accessDrtRoute = drtRoutingModule .calcRoute (DefaultRoutingRequest .withoutAttributes (fromFacility , accessFacility , departureTime , person ));
5459 }
5560 double accessTime = departureTime ;
56- if (drtRoute == null ) {
61+ if (accessDrtRoute == null ) {
5762 // if no DRT route, next part of the trip starts from the origin
5863 accessFacility = fromFacility ;
5964 } else {
6065 //Otherwise we have already a first part of the trip
61- intermodalRoute .addAll (drtRoute );
66+ intermodalRoute .addAll (accessDrtRoute );
6267 for (PlanElement element : intermodalRoute ) {
6368 if (element instanceof Leg leg ) {
6469 accessTime = Math .max (accessTime , leg .getDepartureTime ().seconds ());
@@ -71,37 +76,44 @@ public List<? extends PlanElement> calcRoute(RoutingRequest routingRequest) {
7176 intermodalRoute .add (accessInteractionActivity );
7277 }
7378
74- // Compute the PT part of the route
75- List <PlanElement > ptRoute = new LinkedList <>(transitRoutingModule .calcRoute (DefaultRoutingRequest .withoutAttributes (accessFacility , egressFacility , accessTime , person )));
76- double egressTime = accessTime ;
7779
78- for (PlanElement element : ptRoute ) {
79- if (element instanceof Leg leg ) {
80- egressTime = Math .max (egressTime , leg .getDepartureTime ().seconds ());
81- egressTime += leg .getTravelTime ().seconds ();
82- leg .getAttributes ().putAttribute (CURRENT_SEGMENT_TYPE_ATTR , FeederDrtTripSegmentType .MAIN );
83- }
80+ // We have to check the existence of the egress facility here, the pt router will not support a null value
81+ if (egressFacility == null || (drtServiceAreaExtent != null && !drtServiceAreaExtent .isInside (toFacility .getCoord ()))) {
82+ egressFacility = toFacility ;
8483 }
8584
86- if (egressFacility != null ) {
87- drtRoute = drtRoutingModule .calcRoute (DefaultRoutingRequest .withoutAttributes (egressFacility , toFacility , egressTime , person ));
88- } else {
89- drtRoute = null ;
85+ // Compute the PT part of the route towards the egress (or to) facility
86+ List <PlanElement > ptRoute = new LinkedList <>(transitRoutingModule .calcRoute (DefaultRoutingRequest .withoutAttributes (accessFacility , egressFacility , accessTime , person )));
87+ ptRoute .stream ().filter (planElement -> planElement instanceof Leg ).map (planElement -> (Leg ) planElement ).forEach (leg -> leg .getAttributes ().putAttribute (CURRENT_SEGMENT_TYPE_ATTR , FeederDrtTripSegmentType .MAIN ));
88+
89+ // It's ok to compare reference here, we want to check if we assigned toFacility to egressFacility above
90+ if (egressFacility != toFacility ) {
91+ double egressTime = accessTime ;
92+ for (PlanElement element : ptRoute ) {
93+ if (element instanceof Leg leg ) {
94+ egressTime = Math .max (egressTime , leg .getDepartureTime ().seconds ());
95+ egressTime += leg .getTravelTime ().seconds ();
96+ }
97+ }
98+ egressDrtRoute = drtRoutingModule .calcRoute (DefaultRoutingRequest .withoutAttributes (egressFacility , toFacility , egressTime , person ));
9099 }
91100
92- // If no valid DRT route is found, we recompute a PT route from the access facility to the trip destination
93- if (drtRoute == null ) {
94- ptRoute = new LinkedList <>(transitRoutingModule .calcRoute (DefaultRoutingRequest .withoutAttributes (accessFacility , toFacility , accessTime , person )));
95- ptRoute .stream ().filter (planElement -> planElement instanceof Leg ).map (planElement -> (Leg ) planElement ).forEach (leg -> leg .getAttributes ().putAttribute (CURRENT_SEGMENT_TYPE_ATTR , FeederDrtTripSegmentType .MAIN ));
101+ // egressDrtRoute is assigned only in the above if, but it can be null without entering the if block, so we need to do this here, If no valid DRT route is found, we recompute a PT route from the access facility to the trip destination
102+ if (egressDrtRoute == null ) {
103+ if (egressFacility != toFacility ) {
104+ // In this case, the egressDrtRoute is null because the attempt to compute one wasn't successful, so we need to compute a pt route from the access (or from facility) to the to facility
105+ ptRoute = new LinkedList <>(transitRoutingModule .calcRoute (DefaultRoutingRequest .withoutAttributes (accessFacility , toFacility , accessTime , person )));
106+ ptRoute .stream ().filter (planElement -> planElement instanceof Leg ).map (planElement -> (Leg ) planElement ).forEach (leg -> leg .getAttributes ().putAttribute (CURRENT_SEGMENT_TYPE_ATTR , FeederDrtTripSegmentType .MAIN ));
107+ }
96108 intermodalRoute .addAll (ptRoute );
97109 } else {
98- // Otherwise we add it as an egress to the whole route
110+ // Here we have a pt route and an egress drt route, we need to propriately concatenate them in the overall route
99111 intermodalRoute .addAll (ptRoute );
100112 Activity egressInteractionActivity = populationFactory .createActivityFromLinkId (this .mode + " interaction" , egressFacility .getLinkId ());
101113 egressInteractionActivity .setMaximumDuration (0 );
102- drtRoute .stream ().filter (planElement -> planElement instanceof Leg ).map (planElement -> (Leg ) planElement ).forEach (leg -> leg .getAttributes ().putAttribute (CURRENT_SEGMENT_TYPE_ATTR , FeederDrtTripSegmentType .DRT ));
114+ egressDrtRoute .stream ().filter (planElement -> planElement instanceof Leg ).map (planElement -> (Leg ) planElement ).forEach (leg -> leg .getAttributes ().putAttribute (CURRENT_SEGMENT_TYPE_ATTR , FeederDrtTripSegmentType .DRT ));
103115 intermodalRoute .add (egressInteractionActivity );
104- intermodalRoute .addAll (drtRoute );
116+ intermodalRoute .addAll (egressDrtRoute );
105117 }
106118 return intermodalRoute ;
107119 }
0 commit comments