org.opentripplanner.routing.graph.GraphIndex Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of otp Show documentation
Show all versions of otp Show documentation
The OpenTripPlanner multimodal journey planning system
package org.opentripplanner.routing.graph;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import gnu.trove.set.TIntSet;
import gnu.trove.set.hash.TIntHashSet;
import org.locationtech.jts.geom.Envelope;
import org.opentripplanner.common.geometry.CompactElevationProfile;
import org.opentripplanner.common.geometry.HashGridSpatialIndex;
import org.opentripplanner.ext.flex.FlexIndex;
import org.opentripplanner.model.Agency;
import org.opentripplanner.model.FeedInfo;
import org.opentripplanner.model.FeedScopedId;
import org.opentripplanner.model.MultiModalStation;
import org.opentripplanner.model.Operator;
import org.opentripplanner.model.Route;
import org.opentripplanner.model.Station;
import org.opentripplanner.model.Stop;
import org.opentripplanner.model.StopLocation;
import org.opentripplanner.model.TimetableSnapshot;
import org.opentripplanner.model.Trip;
import org.opentripplanner.model.TripPattern;
import org.opentripplanner.model.calendar.CalendarService;
import org.opentripplanner.model.calendar.ServiceDate;
import org.opentripplanner.routing.vertextype.TransitStopVertex;
import org.opentripplanner.util.OTPFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class GraphIndex {
private static final Logger LOG = LoggerFactory.getLogger(GraphIndex.class);
// TODO: consistently key on model object or id string
private final Map agencyForId = Maps.newHashMap();
private final Map operatorForId = Maps.newHashMap();
private final Map feedInfoForId = Maps.newHashMap();
private final Map stopForId = Maps.newHashMap();
private final Map tripForId = Maps.newHashMap();
private final Map routeForId = Maps.newHashMap();
private final Map stopVertexForStop = Maps.newHashMap();
private final Map patternForTrip = Maps.newHashMap();
private final Multimap patternsForFeedId = ArrayListMultimap.create();
private final Multimap patternsForRoute = ArrayListMultimap.create();
private final Multimap patternsForStopId = ArrayListMultimap.create();
private final Map multiModalStationForStations = Maps.newHashMap();
private final HashGridSpatialIndex stopSpatialIndex = new HashGridSpatialIndex<>();
private final Map serviceCodesRunningForDate = new HashMap<>();
private FlexIndex flexIndex = null;
public GraphIndex(Graph graph) {
LOG.info("GraphIndex init...");
CompactElevationProfile.setDistanceBetweenSamplesM(graph.getDistanceBetweenElevationSamples());
for (Agency agency : graph.getAgencies()) {
this.agencyForId.put(agency.getId(), agency);
}
for (Operator operator : graph.getOperators()) {
this.operatorForId.put(operator.getId(), operator);
}
/* We will keep a separate set of all vertices in case some have the same label.
* Maybe we should just guarantee unique labels. */
for (Vertex vertex : graph.getVertices()) {
if (vertex instanceof TransitStopVertex) {
TransitStopVertex stopVertex = (TransitStopVertex) vertex;
Stop stop = stopVertex.getStop();
stopForId.put(stop.getId(), stop);
stopVertexForStop.put(stop, stopVertex);
}
}
for (TransitStopVertex stopVertex : stopVertexForStop.values()) {
Envelope envelope = new Envelope(stopVertex.getCoordinate());
stopSpatialIndex.insert(envelope, stopVertex);
}
for (TripPattern pattern : graph.tripPatternForId.values()) {
patternsForFeedId.put(pattern.getFeedId(), pattern);
patternsForRoute.put(pattern.route, pattern);
for (Trip trip : pattern.getTrips()) {
patternForTrip.put(trip, pattern);
tripForId.put(trip.getId(), trip);
}
for (Stop stop : pattern.getStops()) {
patternsForStopId.put(stop, pattern);
}
}
for (Route route : patternsForRoute.asMap().keySet()) {
routeForId.put(route.getId(), route);
}
for (MultiModalStation multiModalStation : graph.multiModalStationById.values()) {
for (Station childStation : multiModalStation.getChildStations()) {
multiModalStationForStations.put(childStation, multiModalStation);
}
}
initalizeServiceCodesForDate(graph);
if (OTPFeature.FlexRouting.isOn()) {
flexIndex = new FlexIndex(graph);
for (Route route : flexIndex.routeById.values()) {
routeForId.put(route.getId(), route);
}
for (Trip trip : flexIndex.tripById.values()) {
tripForId.put(trip.getId(), trip);
}
}
LOG.info("GraphIndex init complete.");
}
private void initalizeServiceCodesForDate(Graph graph) {
CalendarService calendarService = graph.getCalendarService();
if (calendarService == null) { return; }
// CalendarService has one main implementation (CalendarServiceImpl) which contains a
// CalendarServiceData which can easily supply all of the dates. But it's impossible to
// actually see those dates without modifying the interfaces and inheritance. So we have
// to work around this abstraction and reconstruct the CalendarData.
// Note the "multiCalendarServiceImpl" which has docs saying it expects one single
// CalendarData. It seems to merge the calendar services from multiple GTFS feeds, but
// its only documentation says it's a hack.
// TODO OTP2 - This cleanup is added to the 'Final cleanup OTP2' issue #2757
// Reconstruct set of all dates where service is defined, keeping track of which services
// run on which days.
Multimap serviceIdsForServiceDate = HashMultimap.create();
for (FeedScopedId serviceId : calendarService.getServiceIds()) {
Set serviceDatesForService = calendarService.getServiceDatesForServiceId(
serviceId);
for (ServiceDate serviceDate : serviceDatesForService) {
serviceIdsForServiceDate.put(serviceDate, serviceId);
}
}
for (ServiceDate serviceDate : serviceIdsForServiceDate.keySet()) {
TIntSet serviceCodesRunning = new TIntHashSet();
for (FeedScopedId serviceId : serviceIdsForServiceDate.get(serviceDate)) {
serviceCodesRunning.add(graph.getServiceCodes().get(serviceId));
}
serviceCodesRunningForDate.put(serviceDate, serviceCodesRunning);
}
}
public Agency getAgencyForId(FeedScopedId id) {
return agencyForId.get(id);
}
public Stop getStopForId(FeedScopedId id) {
return stopForId.get(id);
}
public Route getRouteForId(FeedScopedId id) {
return routeForId.get(id);
}
/**
* TODO OTP2 - This is NOT THREAD-SAFE and is used in the real-time updaters, we need to fix
* - this when doing the issue #3030.
*/
public void addRoutes(Route route) {
routeForId.put(route.getId(), route);
}
/** Dynamically generate the set of Routes passing though a Stop on demand. */
public Set getRoutesForStop(Stop stop) {
Set routes = Sets.newHashSet();
for (TripPattern p : getPatternsForStop(stop)) {
routes.add(p.route);
}
return routes;
}
public Collection getPatternsForStop(StopLocation stop) {
return patternsForStopId.get(stop);
}
/**
* Returns all the patterns for a specific stop. If includeRealtimeUpdates is set, new patterns
* added by realtime updates are added to the collection. A set is used here because trip
* patterns that were updated by realtime data is both part of the GraphIndex and the
* TimetableSnapshot.
*/
public Collection getPatternsForStop(
Stop stop,
TimetableSnapshot timetableSnapshot
) {
Set tripPatterns = new HashSet<>(getPatternsForStop(stop));
if (timetableSnapshot != null) {
tripPatterns.addAll(timetableSnapshot.getPatternsForStop(stop));
}
return tripPatterns;
}
/**
* Get a list of all operators spanning across all feeds.
*/
public Collection getAllOperators() {
return getOperatorForId().values();
}
public Map getOperatorForId() {
return operatorForId;
}
public Map getFeedInfoForId() {
return feedInfoForId;
}
public Collection getAllStops() {
return stopForId.values();
}
public Map getTripForId() {
return tripForId;
}
public Collection getAllRoutes() {
return routeForId.values();
}
public Map getStopVertexForStop() {
return stopVertexForStop;
}
public Map getPatternForTrip() {
return patternForTrip;
}
public Multimap getPatternsForFeedId() {
return patternsForFeedId;
}
public Multimap getPatternsForRoute() {
return patternsForRoute;
}
public Map getMultiModalStationForStations() {
return multiModalStationForStations;
}
public HashGridSpatialIndex getStopSpatialIndex() {
return stopSpatialIndex;
}
public Map getServiceCodesRunningForDate() {
return serviceCodesRunningForDate;
}
public FlexIndex getFlexIndex() {
return flexIndex;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy