use of org.opentripplanner.routing.edgetype.SimpleTransfer in project OpenTripPlanner by opentripplanner.
the class DirectTransferGenerator method buildGraph.
@Override
public void buildGraph(Graph graph, HashMap<Class<?>, Object> extra) {
/* Initialize graph index which is needed by the nearby stop finder. */
if (graph.index == null) {
graph.index = new GraphIndex(graph);
}
/* The linker will use streets if they are available, or straight-line distance otherwise. */
NearbyStopFinder nearbyStopFinder = new NearbyStopFinder(graph, radiusMeters);
if (nearbyStopFinder.useStreets) {
LOG.info("Creating direct transfer edges between stops using the street network from OSM...");
} else {
LOG.info("Creating direct transfer edges between stops using straight line distance (not streets)...");
}
int nTransfersTotal = 0;
int nLinkableStops = 0;
for (TransitStop ts0 : Iterables.filter(graph.getVertices(), TransitStop.class)) {
/* Skip stops that are entrances to stations or whose entrances are coded separately */
if (!ts0.isStreetLinkable())
continue;
if (++nLinkableStops % 1000 == 0) {
LOG.info("Linked {} stops", nLinkableStops);
}
LOG.debug("Linking stop '{}' {}", ts0.getStop(), ts0);
/* Determine the set of stops that are already reachable via other pathways or transfers */
Set<TransitStop> pathwayDestinations = new HashSet<TransitStop>();
for (Edge e : ts0.getOutgoing()) {
if (e instanceof PathwayEdge || e instanceof SimpleTransfer) {
if (e.getToVertex() instanceof TransitStop) {
TransitStop to = (TransitStop) e.getToVertex();
pathwayDestinations.add(to);
}
}
}
/* Make transfers to each nearby stop that is the closest stop on some trip pattern. */
int n = 0;
for (NearbyStopFinder.StopAtDistance sd : nearbyStopFinder.findNearbyStopsConsideringPatterns(ts0)) {
/* Skip the origin stop, loop transfers are not needed. */
if (sd.tstop == ts0 || pathwayDestinations.contains(sd.tstop))
continue;
new SimpleTransfer(ts0, sd.tstop, sd.dist, sd.geom, sd.edges);
n += 1;
}
LOG.debug("Linked stop {} to {} nearby stops on other patterns.", ts0.getStop(), n);
if (n == 0) {
LOG.debug(graph.addBuilderAnnotation(new StopNotLinkedForTransfers(ts0)));
}
nTransfersTotal += n;
}
LOG.info("Done connecting stops to one another. Created a total of {} transfers from {} stops.", nTransfersTotal, nLinkableStops);
graph.hasDirectTransfers = true;
}
use of org.opentripplanner.routing.edgetype.SimpleTransfer in project OpenTripPlanner by opentripplanner.
the class IndexAPI method getTransfers.
/**
* Return the generated transfers a stop in the graph, by stop ID
*/
@GET
@Path("/stops/{stopId}/transfers")
public Response getTransfers(@PathParam("stopId") String stopIdString) {
Stop stop = index.stopForId.get(GtfsLibrary.convertIdFromString(stopIdString));
if (stop != null) {
// get the transfers for the stop
TransitStop v = index.stopVertexForStop.get(stop);
Collection<Edge> transfers = Collections2.filter(v.getOutgoing(), new Predicate<Edge>() {
@Override
public boolean apply(Edge edge) {
return edge instanceof SimpleTransfer;
}
});
Collection<Transfer> out = Collections2.transform(transfers, new Function<Edge, Transfer>() {
@Override
public Transfer apply(Edge edge) {
// TODO Auto-generated method stub
return new Transfer((SimpleTransfer) edge);
}
});
return Response.status(Status.OK).entity(out).build();
} else {
return Response.status(Status.NOT_FOUND).entity(MSG_404).build();
}
}
use of org.opentripplanner.routing.edgetype.SimpleTransfer in project OpenTripPlanner by opentripplanner.
the class TestTransfers method createSimpleTransfer.
/**
* Create simple transfer edge between two vertices given their labels
* @param from is label of from vertex
* @param to is label of to vertex
* @param distance is distance of transfer
*/
private void createSimpleTransfer(String from, String to, int distance) {
TransitStop fromv = ((TransitStop) graph.getVertex(from));
TransitStop tov = ((TransitStop) graph.getVertex(to));
new SimpleTransfer(fromv, tov, distance, null);
}
use of org.opentripplanner.routing.edgetype.SimpleTransfer in project OpenTripPlanner by opentripplanner.
the class AnalystProfileRouterPrototype method route.
public TimeSurface.RangeSet route() {
// NOT USED here, however FIXME this is not threadsafe, needs lock graph.index.clusterStopsAsNeeded();
LOG.info("access modes: {}", request.accessModes);
LOG.info("egress modes: {}", request.egressModes);
LOG.info("direct modes: {}", request.directModes);
// Establish search timeouts
searchBeginTime = System.currentTimeMillis();
abortTime = searchBeginTime + TIMEOUT * 1000;
// TimeWindow could constructed in the caller, which does have access to the graph index.
this.window = new TimeWindow(request.fromTime, request.toTime, graph.index.servicesRunning(request.date));
fromStops = findClosestStops(TraverseMode.WALK);
LOG.info("From patterns/stops: {}", fromStops);
/* Initialize time range tracker to begin the search. */
TimeRange.Tracker times = new TimeRange.Tracker();
for (Stop stop : fromStops.keySet()) {
times.set(stop, fromStops.get(stop));
}
Set<Stop> stopsUpdated = fromStops.keySet();
for (int round = 0; round < MAX_RIDES; round++) {
// TODO maybe even loop until no updates happen? That should happen automatically if MAX_RIDES is high enough.
/* Get all patterns passing through stops updated in the last round, then reinitialize the updated stops set. */
Set<TripPattern> patternsUpdated = uniquePatternsVisiting(stopsUpdated);
LOG.info("ROUND {} : {} stops and {} patterns to explore.", round, stopsUpdated.size(), patternsUpdated.size());
stopsUpdated = Sets.newHashSet();
/* RAPTOR style: iterate over each pattern once. */
for (TripPattern pattern : patternsUpdated) {
// checkTimeout();
TimeRange rangeBeingPropagated = null;
List<Stop> stops = pattern.getStops();
FrequencyEntry freq = pattern.getSingleFrequencyEntry();
if (freq == null)
continue;
TripTimes tt = freq.tripTimes;
int headway = freq.headway;
for (int sidx = 0; sidx < stops.size(); sidx++) {
Stop stop = stops.get(sidx);
TimeRange existingRange = times.get(stop);
TimeRange reBoardRange = (existingRange != null) ? existingRange.wait(headway) : null;
if (rangeBeingPropagated == null) {
// We do not yet have a range worth propagating
if (reBoardRange != null) {
// this is a fresh protective copy
rangeBeingPropagated = reBoardRange;
}
} else {
// We already have a range that is being propagated along the pattern.
// We are certain sidx >= 1 here because we have already boarded in a previous iteration.
TimeRange arrivalRange = rangeBeingPropagated.shift(tt.getRunningTime(sidx - 1));
if (times.add(stop, arrivalRange)) {
// The propagated time improved the best known time in some way.
stopsUpdated.add(stop);
}
// TODO handle case where arrival and departure are different
rangeBeingPropagated = arrivalRange.shift(tt.getDwellTime(sidx));
if (reBoardRange != null) {
rangeBeingPropagated.mergeIn(reBoardRange);
}
}
}
}
/* Transfer from updated stops to adjacent stops before beginning the next round.
Iterate over a protective copy because we add more stops to the updated list during iteration. */
if (!graph.hasDirectTransfers) {
throw new RuntimeException("Requires the SimpleTransfers generated in long distance mode.");
}
for (Stop stop : Lists.newArrayList(stopsUpdated)) {
Collection<Edge> outgoingEdges = graph.index.stopVertexForStop.get(stop).getOutgoing();
for (SimpleTransfer transfer : Iterables.filter(outgoingEdges, SimpleTransfer.class)) {
Stop targetStop = ((TransitStop) transfer.getToVertex()).getStop();
double walkTime = transfer.getDistance() / request.walkSpeed;
TimeRange rangeAfterTransfer = times.get(stop).shift((int) walkTime);
if (times.add(targetStop, rangeAfterTransfer)) {
stopsUpdated.add(targetStop);
}
}
}
}
LOG.info("Done with transit.");
LOG.info("Propagating from transit stops to the street network...");
// Grab a cached map of distances to street intersections from each transit stop
StopTreeCache stopTreeCache = graph.index.getStopTreeCache();
// Iterate over all stops that were reached in the transit part of the search
for (Stop stop : times) {
TransitStop tstop = graph.index.stopVertexForStop.get(stop);
// Iterate over street intersections in the vicinity of this particular transit stop.
// Shift the time range at this transit stop, merging it into that for all reachable street intersections.
TimeRange rangeAtTransitStop = times.get(stop);
// FIXME stopTreeCache.getDistancesForStop(tstop);
TObjectIntMap<Vertex> distanceToVertex = null;
for (TObjectIntIterator<Vertex> iter = distanceToVertex.iterator(); iter.hasNext(); ) {
iter.advance();
Vertex vertex = iter.key();
// distance in meters over walkspeed in meters per second --> seconds
int egressWalkTimeSeconds = (int) (iter.value() / request.walkSpeed);
if (egressWalkTimeSeconds > request.maxWalkTime * 60) {
continue;
}
TimeRange propagatedRange = rangeAtTransitStop.shift(egressWalkTimeSeconds);
TimeRange existingTimeRange = propagatedTimes.get(vertex);
if (existingTimeRange == null) {
propagatedTimes.put(vertex, propagatedRange);
} else {
existingTimeRange.mergeIn(propagatedRange);
}
}
}
LOG.info("Done with propagation.");
TimeSurface.RangeSet result = TimeSurface.makeSurfaces(this);
LOG.info("Done making time surfaces.");
return result;
}
use of org.opentripplanner.routing.edgetype.SimpleTransfer in project OpenTripPlanner by opentripplanner.
the class SampleStopLinker method link.
/**
* Link all transit stops. If makeTransfers is true, create direct transfer
* edges between stops linked to the same pair of vertices. This is important
* e.g. for transit centers where there are many stops on the same street segment;
* we don't want to force the user to walk to the end of the street and back.
*
* If you're not generating transfers via the street network there is no need to make
* transfers at this stage. But if you're not generating transfers via the street network,
* why are you using this module at all?
*/
public void link(boolean makeTransfers) {
if (makeTransfers)
links = HashMultimap.create();
SampleFactory sf = graph.getSampleFactory();
for (TransitStop tstop : Iterables.filter(graph.getVertices(), TransitStop.class)) {
Sample s = sf.getSample(tstop.getLon(), tstop.getLat());
// TODO: stop unlinked annotation
if (s == null)
continue;
new IntersectionTransitLink(tstop, (OsmVertex) s.v0, s.d0);
new IntersectionTransitLink((OsmVertex) s.v0, tstop, s.d0);
new IntersectionTransitLink(tstop, (OsmVertex) s.v1, s.d1);
new IntersectionTransitLink((OsmVertex) s.v1, tstop, s.d1);
if (makeTransfers) {
// save the sample so we can make direct transfers between stops
VertexPair vp = new VertexPair(s.v0, s.v1);
links.put(vp, tstop);
}
}
if (makeTransfers) {
// make direct transfers between stops
for (Collection<TransitStop> tss : links.asMap().values()) {
for (TransitStop ts0 : tss) {
for (TransitStop ts1 : tss) {
// make a geometry
GeometryFactory gf = GeometryUtils.getGeometryFactory();
LineString geom = gf.createLineString(new Coordinate[] { ts0.getCoordinate(), ts1.getCoordinate() });
double dist = SphericalDistanceLibrary.distance(ts0.getLat(), ts0.getLon(), ts1.getLat(), ts1.getLon());
// building unidirectional edge, we'll hit this again in the opposite direction
new SimpleTransfer(ts1, ts1, dist, geom);
}
}
}
}
}
Aggregations