use of org.onebusaway.gtfs.model.Trip in project OpenTripPlanner by opentripplanner.
the class GtfsGraphBuilderModuleTest method testNoBikesByDefault.
@Test
public void testNoBikesByDefault() throws IOException {
// We configure two trip: one with unknown bikes_allowed and the second with bikes
// allowed.
MockGtfs gtfs = getSimpleGtfs();
gtfs.putTrips(2, "r0", "sid0", "bikes_allowed=0,1");
gtfs.putStopTimes("t0,t1", "s0,s1");
List<GtfsBundle> bundleList = getGtfsAsBundleList(gtfs);
bundleList.get(0).setDefaultBikesAllowed(false);
_builder = new GtfsModule(bundleList);
Graph graph = new Graph();
_builder.buildGraph(graph, _extra);
graph.index(new DefaultStreetVertexIndexFactory());
// Feed id is used instead of the agency id for OBA entities.
GtfsBundle gtfsBundle = bundleList.get(0);
GtfsFeedId feedId = gtfsBundle.getFeedId();
Trip trip = graph.index.tripForId.get(new AgencyAndId(feedId.getId(), "t0"));
TripPattern pattern = graph.index.patternForTrip.get(trip);
List<Trip> trips = pattern.getTrips();
assertEquals(BikeAccess.UNKNOWN, BikeAccess.fromTrip(withId(trips, new AgencyAndId(feedId.getId(), "t0"))));
assertEquals(BikeAccess.ALLOWED, BikeAccess.fromTrip(withId(trips, new AgencyAndId(feedId.getId(), "t1"))));
}
use of org.onebusaway.gtfs.model.Trip in project OpenTripPlanner by opentripplanner.
the class GTFSPatternHopFactory method run.
/**
* Generate the edges. Assumes that there are already vertices in the graph for the stops.
*/
public void run(Graph graph) {
if (fareServiceFactory == null) {
fareServiceFactory = new DefaultFareServiceFactory();
}
fareServiceFactory.processGtfs(_dao);
// TODO: Why are we loading stops? The Javadoc above says this method assumes stops are aleady loaded.
loadStops(graph);
loadPathways(graph);
loadFeedInfo(graph);
loadAgencies(graph);
// TODO: Why is there cached "data", and why are we clearing it? Due to a general lack of comments, I have no idea.
// Perhaps it is to allow name collisions with previously loaded feeds.
clearCachedData();
/* Assign 0-based numeric codes to all GTFS service IDs. */
for (AgencyAndId serviceId : _dao.getAllServiceIds()) {
// TODO: FIX Service code collision for multiple feeds.
graph.serviceCodes.put(serviceId, graph.serviceCodes.size());
}
LOG.debug("building hops from trips");
Collection<Trip> trips = _dao.getAllTrips();
int tripCount = 0;
/* First, record which trips are used by one or more frequency entries.
* These trips will be ignored for the purposes of non-frequency routing, and
* all the frequency entries referencing the same trip can be added at once to the same
* Timetable/TripPattern.
*/
ListMultimap<Trip, Frequency> frequenciesForTrip = ArrayListMultimap.create();
for (Frequency freq : _dao.getAllFrequencies()) {
frequenciesForTrip.put(freq.getTrip(), freq);
}
/* Then loop over all trips, handling each one as a frequency-based or scheduled trip. */
int freqCount = 0;
int nonFreqCount = 0;
/* The hops don't actually exist when we build their geometries, but we have to build their geometries
* below, before we throw away the modified stopTimes, saving only the tripTimes (which don't have enough
* information to build a geometry). So we keep them here.
*
* A trip pattern actually does not have a single geometry, but one per hop, so we store an array.
* FIXME _why_ doesn't it have a single geometry?
*/
Map<TripPattern, LineString[]> geometriesByTripPattern = Maps.newHashMap();
TRIP: for (Trip trip : trips) {
if (++tripCount % 100000 == 0) {
LOG.debug("loading trips {}/{}", tripCount, trips.size());
}
// TODO: move to a validator module
if (!_calendarService.getServiceIds().contains(trip.getServiceId())) {
LOG.warn(graph.addBuilderAnnotation(new TripUndefinedService(trip)));
// Invalid trip, skip it, it will break later
continue TRIP;
}
/* Fetch the stop times for this trip. Copy the list since it's immutable. */
List<StopTime> stopTimes = new ArrayList<StopTime>(_dao.getStopTimesForTrip(trip));
/* GTFS stop times frequently contain duplicate, missing, or incorrect entries. Repair them. */
TIntList removedStopSequences = removeRepeatedStops(stopTimes);
if (!removedStopSequences.isEmpty()) {
LOG.warn(graph.addBuilderAnnotation(new RepeatedStops(trip, removedStopSequences)));
}
filterStopTimes(stopTimes, graph);
interpolateStopTimes(stopTimes);
/* If after filtering this trip does not contain at least 2 stoptimes, it does not serve any purpose. */
if (stopTimes.size() < 2) {
LOG.warn(graph.addBuilderAnnotation(new TripDegenerate(trip)));
continue TRIP;
}
/* Try to get the direction id for the trip, set to -1 if not found */
int directionId;
try {
directionId = Integer.parseInt(trip.getDirectionId());
} catch (NumberFormatException e) {
LOG.debug("Trip {} does not have direction id, defaults to -1");
directionId = -1;
}
/* Get the existing TripPattern for this filtered StopPattern, or create one. */
StopPattern stopPattern = new StopPattern(stopTimes);
TripPattern tripPattern = findOrCreateTripPattern(stopPattern, trip.getRoute(), directionId);
/* Create a TripTimes object for this list of stoptimes, which form one trip. */
TripTimes tripTimes = new TripTimes(trip, stopTimes, graph.deduplicator);
/* If this trip is referenced by one or more lines in frequencies.txt, wrap it in a FrequencyEntry. */
List<Frequency> frequencies = frequenciesForTrip.get(trip);
if (frequencies != null && !(frequencies.isEmpty())) {
for (Frequency freq : frequencies) {
tripPattern.add(new FrequencyEntry(freq, tripTimes));
freqCount++;
}
// TODO replace: createGeometry(graph, trip, stopTimes, hops);
} else /* This trip was not frequency-based. Add the TripTimes directly to the TripPattern's scheduled timetable. */
{
tripPattern.add(tripTimes);
nonFreqCount++;
}
// there would be a trip pattern with no geometry yet because it failed some of these tests
if (!geometriesByTripPattern.containsKey(tripPattern) && trip.getShapeId() != null && trip.getShapeId().getId() != null && !trip.getShapeId().getId().equals("")) {
// save the geometry to later be applied to the hops
geometriesByTripPattern.put(tripPattern, createGeometry(graph, trip, stopTimes));
}
}
// end foreach TRIP
LOG.info("Added {} frequency-based and {} single-trip timetable entries.", freqCount, nonFreqCount);
graph.hasFrequencyService = graph.hasFrequencyService || freqCount > 0;
graph.hasScheduledService = graph.hasScheduledService || nonFreqCount > 0;
/* Generate unique human-readable names for all the TableTripPatterns. */
TripPattern.generateUniqueNames(tripPatterns.values());
/* Generate unique short IDs for all the TableTripPatterns. */
TripPattern.generateUniqueIds(tripPatterns.values());
/* Loop over all new TripPatterns, creating edges, setting the service codes and geometries, etc. */
for (TripPattern tripPattern : tripPatterns.values()) {
tripPattern.makePatternVerticesAndEdges(graph, context.stationStopNodes);
// Add the geometries to the hop edges.
LineString[] geom = geometriesByTripPattern.get(tripPattern);
if (geom != null) {
for (int i = 0; i < tripPattern.hopEdges.length; i++) {
tripPattern.hopEdges[i].setGeometry(geom[i]);
}
// Make a geometry for the whole TripPattern from all its constituent hops.
// This happens only if geometry is found in geometriesByTripPattern,
// because that means that geometry was created from shapes instead "as crow flies"
tripPattern.makeGeometry();
}
// TODO this could be more elegant
tripPattern.setServiceCodes(graph.serviceCodes);
/* Iterate over all stops in this pattern recording mode information. */
TraverseMode mode = GtfsLibrary.getTraverseMode(tripPattern.route);
for (TransitStop tstop : tripPattern.stopVertices) {
tstop.addMode(mode);
if (mode == TraverseMode.SUBWAY) {
tstop.setStreetToStopTime(subwayAccessTime);
}
graph.addTransitMode(mode);
}
}
/* Identify interlined trips and create the necessary edges. */
interline(tripPatterns.values(), graph);
/* Interpret the transfers explicitly defined in transfers.txt. */
loadTransfers(graph);
/* Store parent stops in graph, even if not linked. These are needed for clustering*/
for (TransitStationStop stop : context.stationStopNodes.values()) {
if (stop instanceof TransitStation) {
TransitStation parentStopVertex = (TransitStation) stop;
graph.parentStopById.put(parentStopVertex.getStopId(), parentStopVertex.getStop());
}
}
// it is already done at deserialization, but standalone mode allows using graphs without serializing them.
for (TripPattern tableTripPattern : tripPatterns.values()) {
tableTripPattern.scheduledTimetable.finish();
}
// eh?
clearCachedData();
graph.putService(FareService.class, fareServiceFactory.makeFareService());
graph.putService(OnBoardDepartService.class, new OnBoardDepartServiceImpl());
}
use of org.onebusaway.gtfs.model.Trip in project OpenTripPlanner by opentripplanner.
the class GTFSPatternHopFactory method loadTransfers.
private void loadTransfers(Graph graph) {
Collection<Transfer> transfers = _dao.getAllTransfers();
TransferTable transferTable = graph.getTransferTable();
for (Transfer sourceTransfer : transfers) {
// we thus expand transfers that use parent stations to all the member stops.
for (Transfer t : expandTransfer(sourceTransfer)) {
Stop fromStop = t.getFromStop();
Stop toStop = t.getToStop();
Route fromRoute = t.getFromRoute();
Route toRoute = t.getToRoute();
Trip fromTrip = t.getFromTrip();
Trip toTrip = t.getToTrip();
Vertex fromVertex = context.stopArriveNodes.get(fromStop);
Vertex toVertex = context.stopDepartNodes.get(toStop);
switch(t.getTransferType()) {
case 1:
// timed (synchronized) transfer
// Handle with edges that bypass the street network.
// from and to vertex here are stop_arrive and stop_depart vertices
// only add edge when it doesn't exist already
boolean hasTimedTransferEdge = false;
for (Edge outgoingEdge : fromVertex.getOutgoing()) {
if (outgoingEdge instanceof TimedTransferEdge) {
if (outgoingEdge.getToVertex() == toVertex) {
hasTimedTransferEdge = true;
break;
}
}
}
if (!hasTimedTransferEdge) {
new TimedTransferEdge(fromVertex, toVertex);
}
// add to transfer table to handle specificity
transferTable.addTransferTime(fromStop, toStop, fromRoute, toRoute, fromTrip, toTrip, StopTransfer.TIMED_TRANSFER);
break;
case 2:
// min transfer time
transferTable.addTransferTime(fromStop, toStop, fromRoute, toRoute, fromTrip, toTrip, t.getMinTransferTime());
break;
case 3:
// forbidden transfer
transferTable.addTransferTime(fromStop, toStop, fromRoute, toRoute, fromTrip, toTrip, StopTransfer.FORBIDDEN_TRANSFER);
break;
case 0:
default:
// preferred transfer
transferTable.addTransferTime(fromStop, toStop, fromRoute, toRoute, fromTrip, toTrip, StopTransfer.PREFERRED_TRANSFER);
break;
}
}
}
}
use of org.onebusaway.gtfs.model.Trip in project OpenTripPlanner by opentripplanner.
the class AlertPatch method apply.
public void apply(Graph graph) {
Agency agency = null;
if (feedId != null) {
Map<String, Agency> agencies = graph.index.agenciesForFeedId.get(feedId);
agency = this.agency != null ? agencies.get(this.agency) : null;
}
Route route = this.route != null ? graph.index.routeForId.get(this.route) : null;
Stop stop = this.stop != null ? graph.index.stopForId.get(this.stop) : null;
Trip trip = this.trip != null ? graph.index.tripForId.get(this.trip) : null;
if (route != null || trip != null || agency != null) {
Collection<TripPattern> tripPatterns = null;
if (trip != null) {
tripPatterns = new LinkedList<>();
TripPattern tripPattern = graph.index.patternForTrip.get(trip);
if (tripPattern != null) {
tripPatterns.add(tripPattern);
}
} else if (route != null) {
tripPatterns = graph.index.patternsForRoute.get(route);
} else {
// Find patterns for the feed.
tripPatterns = graph.index.patternsForFeedId.get(feedId);
}
if (tripPatterns != null) {
for (TripPattern tripPattern : tripPatterns) {
if (direction != null && !direction.equals(tripPattern.getDirection())) {
continue;
}
if (directionId != -1 && directionId == tripPattern.directionId) {
continue;
}
for (int i = 0; i < tripPattern.stopPattern.stops.length; i++) {
if (stop == null || stop.equals(tripPattern.stopPattern.stops[i])) {
graph.addAlertPatch(tripPattern.boardEdges[i], this);
graph.addAlertPatch(tripPattern.alightEdges[i], this);
}
}
}
}
} else if (stop != null) {
TransitStop transitStop = graph.index.stopVertexForStop.get(stop);
for (Edge edge : transitStop.getOutgoing()) {
if (edge instanceof PreBoardEdge) {
graph.addAlertPatch(edge, this);
break;
}
}
for (Edge edge : transitStop.getIncoming()) {
if (edge instanceof PreAlightEdge) {
graph.addAlertPatch(edge, this);
break;
}
}
}
}
use of org.onebusaway.gtfs.model.Trip in project OpenTripPlanner by opentripplanner.
the class IndexAPI method getSemanticHashForTrip.
@GET
@Path("/trips/{tripId}/semanticHash")
public Response getSemanticHashForTrip(@PathParam("tripId") String tripIdString) {
AgencyAndId tripId = GtfsLibrary.convertIdFromString(tripIdString);
Trip trip = index.tripForId.get(tripId);
if (trip != null) {
TripPattern pattern = index.patternForTrip.get(trip);
String hashString = pattern.semanticHashString(trip);
return Response.status(Status.OK).entity(hashString).build();
} else {
return Response.status(Status.NOT_FOUND).entity(MSG_404).build();
}
}
Aggregations