All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.transit.raptor.rangeraptor.standard.stoparrivals.view.StopsCursor Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
package org.opentripplanner.transit.raptor.rangeraptor.standard.stoparrivals.view;

import java.util.function.ToIntFunction;
import javax.validation.constraints.NotNull;
import org.opentripplanner.transit.raptor.api.transit.RaptorTransfer;
import org.opentripplanner.transit.raptor.api.transit.RaptorTripPattern;
import org.opentripplanner.transit.raptor.api.transit.RaptorTripSchedule;
import org.opentripplanner.transit.raptor.api.view.ArrivalView;
import org.opentripplanner.transit.raptor.rangeraptor.standard.stoparrivals.StopArrivalState;
import org.opentripplanner.transit.raptor.rangeraptor.standard.stoparrivals.StopArrivals;
import org.opentripplanner.transit.raptor.rangeraptor.transit.TransitCalculator;


/**
 * Used to create a view to the internal StdRangeRaptor model and to navigate
 * between stop arrivals. Since view objects are only used for path and debugging
 * operations, the view can create temporary objects for each StopArrival. These
 * view objects are temporary objects and when the algorithm progress they might
 * get invalid - so do not keep references to these objects bejond the scope of
 * of a the callers method.
 * 

* The design was originally done to support the FLyweight design pattern. * * @param The TripSchedule type defined by the user of the raptor API. */ public class StopsCursor { private final StopArrivals arrivals; private final TransitCalculator transitCalculator; private final ToIntFunction boardSlackProvider; public StopsCursor( StopArrivals arrivals, TransitCalculator transitCalculator, ToIntFunction boardSlackProvider ) { this.arrivals = arrivals; this.transitCalculator = transitCalculator; this.boardSlackProvider = boardSlackProvider; } public boolean reachedOnBoard(int round, int stop) { var a = arrivals.get(round, stop); return a != null && a.reachedOnBoard(); } public boolean reachedOnStreet(int round, int stop) { var a = arrivals.get(round, stop); if(a == null) { return false; } return a.arrivedByAccessOnStreet() || a.arrivedByTransfer(); } /** Return a fictive access stop arrival. */ public Access fictiveAccess(int round, RaptorTransfer accessPath, int arrivalTime) { return new Access<>(round, arrivalTime, accessPath); } /** * Return a fictive Transfer stop arrival view. The arrival does not exist in the state, but is * linked with the previous arrival witch is a "real" arrival present in the state. This * enables path generation. */ public Transfer fictiveTransfer( int round, int fromStop, RaptorTransfer transfer, int toStop, int arrivalTime ) { StopArrivalState arrival = StopArrivalState.create(); arrival.transferToStop(fromStop, arrivalTime, transfer); return new Transfer<>(round, toStop, arrival, this); } /** * Return a fictive Transit stop arrival view. The arrival does not exist in the state, but is * linked with the previous arrival witch is a "real" arrival present in the state. This * enables path generation. */ public Transit fictiveTransit( int round, int alightStop, int alightTime, T trip, int boardStop, int boardTime ) { StopArrivalState arrival = StopArrivalState.create(); arrival.arriveByTransit(alightTime, boardStop, boardTime, trip); return new Transit<>(round, alightStop, arrival, this); } /** * Return the stop-arrival for the given round, stop and given access. There is no * check that the access exist. */ public ArrivalView access(int round, int stop, RaptorTransfer access) { var arrival = arrivals.get(round, stop); int time = access.stopReachedOnBoard() ? arrival.onBoardArrivalTime() : arrival.time(); return new Access<>(round, time, access); } /** * Return the stop-arrival for the given round, stop and method of arrival(stopReachedOnBoard). * The returned arrival can be access(including flex), transfer or transit. * * @param stopReachedOnBoard if {@code true} the arrival returned must arrive onboard a vehicle, * if {@code false} the BEST arrival is returned on-street or on-board. */ public ArrivalView stop(int round, int stop, boolean stopReachedOnBoard) { var arrival = arrivals.get(round, stop); // We chack for on-street arrivals first, since on-street is only available if it is better // than on-board arrivals if(!stopReachedOnBoard) { if (arrival.arrivedByAccessOnStreet()) { return newAccessView(round, arrival.time(), arrival.accessPathOnStreet()); } else if (arrival.arrivedByTransfer()) { return new Transfer<>(round, stop, arrival, this); } } // On on-board arrivals can always be used, we do not care what the *stopReachedOnBoard* is. if(arrival.arrivedByAccessOnBoard()) { return newAccessView( round, arrival.onBoardArrivalTime(), arrival.accessPathOnBoard() ); } else if(arrival.arrivedByTransit()) { return new Transit<>(round, stop, arrival, this); } // Should never get here... throw new IllegalStateException("Unknown arrival: " + arrival); } /** * Set cursor to stop followed by the give transit leg - this allows access to be time-shifted * according to the next transit boarding/departure time. */ public ArrivalView stop(int round, int stop, @NotNull Transit nextTransitLeg) { var arrival = arrivals.get(round, stop); if(arrival.arrivedByAccessOnStreet()) { return newAccessView(round, arrival.accessPathOnStreet(), nextTransitLeg); } else if(arrival.arrivedByTransfer()) { return new Transfer<>(round, stop, arrival, this); } else if(arrival.arrivedByAccessOnBoard()) { return newAccessView(round, arrival.accessPathOnBoard(), nextTransitLeg); } else if(arrival.arrivedByTransit()) { return new Transit<>(round, stop, arrival, this); } // Should never get here... throw new IllegalStateException("Unknown arrival: " + arrival); } /** * A access stop arrival, time-shifted according to the first transit boarding/departure time * and the possible restrictions in the access. *

* If given transit is {@code null}, then use the iteration departure time without any * time-shifted departure. This is used for logging and debugging, not for returned paths. */ private ArrivalView newAccessView( int round, RaptorTransfer accessPath, Transit transit ) { int transitDepartureTime = transit.boardTime(); int boardSlack = boardSlackProvider.applyAsInt(transit.trip().pattern()); // Preferred time-shifted access departure int preferredDepartureTime = transitCalculator.minusDuration( transitDepartureTime, boardSlack + accessPath.durationInSeconds() ); return newAccessView(round, preferredDepartureTime, accessPath); } /** * A access stop arrival, time-shifted according to the {@code preferredDepartureTime} and the * possible restrictions in the access. */ private ArrivalView newAccessView( int round, int preferredDepartureTime, RaptorTransfer accessPath ) { // Get the real 'departureTime' honoring the time-shift restriction in the access int departureTime = transitCalculator.departureTime( accessPath, preferredDepartureTime ); int arrivalTime = transitCalculator.plusDuration( departureTime, accessPath.durationInSeconds() ); return new Access<>(round, arrivalTime, accessPath); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy