use of org.opentripplanner.routing.core.State in project OpenTripPlanner by opentripplanner.
the class NearbyStopFinder method stopAtDistanceForState.
/**
* Given a State at a TransitStop, bundle the TransitStop together with information about how far away it is
* and the geometry of the path leading up to the given State.
*
* TODO this should probably be merged with similar classes in Profile routing.
*/
public static StopAtDistance stopAtDistanceForState(State state) {
double distance = 0.0;
GraphPath graphPath = new GraphPath(state, false);
CoordinateArrayListSequence coordinates = new CoordinateArrayListSequence();
List<Edge> edges = new ArrayList<>();
for (Edge edge : graphPath.edges) {
if (edge instanceof StreetEdge) {
LineString geometry = edge.getGeometry();
if (geometry != null) {
if (coordinates.size() == 0) {
coordinates.extend(geometry.getCoordinates());
} else {
coordinates.extend(geometry.getCoordinates(), 1);
}
}
distance += edge.getDistance();
}
edges.add(edge);
}
if (coordinates.size() < 2) {
// Otherwise the walk step generator breaks.
ArrayList<Coordinate> coordinateList = new ArrayList<Coordinate>(2);
coordinateList.add(graphPath.states.get(1).getVertex().getCoordinate());
State lastState = graphPath.states.getLast().getBackState();
coordinateList.add(lastState.getVertex().getCoordinate());
coordinates = new CoordinateArrayListSequence(coordinateList);
}
StopAtDistance sd = new StopAtDistance((TransitStop) state.getVertex(), distance);
sd.geom = geometryFactory.createLineString(new PackedCoordinateSequence.Double(coordinates.toCoordinateArray()));
sd.edges = edges;
return sd;
}
use of org.opentripplanner.routing.core.State in project OpenTripPlanner by opentripplanner.
the class NearbyStopFinder method findNearbyStopsViaStreets.
/**
* Return all stops within a certain radius of the given vertex, using network distance along streets.
* If the origin vertex is a TransitStop, the result will include it.
*/
public List<StopAtDistance> findNearbyStopsViaStreets(Vertex originVertex) {
RoutingRequest routingRequest = new RoutingRequest(TraverseMode.WALK);
routingRequest.clampInitialWait = (0L);
routingRequest.setRoutingContext(graph, originVertex, null);
ShortestPathTree spt = earliestArrivalSearch.getShortestPathTree(routingRequest);
List<StopAtDistance> stopsFound = Lists.newArrayList();
if (spt != null) {
// TODO use GenericAStar and a traverseVisitor? Add an earliestArrival switch to genericAStar?
for (State state : spt.getAllStates()) {
Vertex targetVertex = state.getVertex();
if (targetVertex == originVertex)
continue;
if (targetVertex instanceof TransitStop) {
stopsFound.add(stopAtDistanceForState(state));
}
}
}
/* Add the origin vertex if needed. The SPT does not include the initial state. FIXME shouldn't it? */
if (originVertex instanceof TransitStop) {
stopsFound.add(new StopAtDistance((TransitStop) originVertex, 0));
}
routingRequest.cleanup();
return stopsFound;
}
use of org.opentripplanner.routing.core.State in project OpenTripPlanner by opentripplanner.
the class ProfileRouter method findDirectOption.
/**
* Look for an option connecting origin to destination without using transit.
*/
private void findDirectOption(QualifiedMode qmode) {
// Make a normal OTP routing request so we can traverse edges and use GenericAStar
RoutingRequest rr = new RoutingRequest(new TraverseModeSet());
// false because we never use transit in direct options
qmode.applyToRoutingRequest(rr, false);
if (qmode.mode == TraverseMode.BICYCLE) {
// TRIANGLE should only affect bicycle searches, but we wrap this in a conditional just to be clear.
rr.optimize = OptimizeType.TRIANGLE;
rr.setTriangleNormalized(request.bikeSafe, request.bikeSlope, request.bikeTime);
}
rr.from = (new GenericLocation(request.fromLat, request.fromLon));
rr.to = new GenericLocation(request.toLat, request.toLon);
rr.setArriveBy(false);
rr.setRoutingContext(graph);
rr.dominanceFunction = new DominanceFunction.MinimumWeight();
// This is not a batch search, it is a point-to-point search with goal direction.
// Impose a max time to protect against very slow searches.
int worstElapsedTime = request.streetTime * 60;
rr.worstTime = (rr.dateTime + worstElapsedTime);
rr.walkSpeed = request.walkSpeed;
rr.bikeSpeed = request.bikeSpeed;
AStar astar = new AStar();
rr.setNumItineraries(1);
ShortestPathTree spt = astar.getShortestPathTree(rr, 5);
State state = spt.getState(rr.rctx.target);
if (state != null) {
LOG.info("Found non-transit option for {}", qmode);
directPaths.add(new StopAtDistance(state, qmode));
}
// save context for later cleanup so temp edges remain available
routingContexts.add(rr.rctx);
}
use of org.opentripplanner.routing.core.State in project OpenTripPlanner by opentripplanner.
the class RaptorWorkerData method findStopsNear.
/**
* find stops from a given SPT, including temporary stops. If useTimes is true, use times from the SPT, otherwise use distances
*/
public TIntIntMap findStopsNear(ShortestPathTree spt, Graph graph, boolean useTimes, float walkSpeed) {
TIntIntMap accessTimes = new TIntIntHashMap();
for (TransitStop tstop : graph.index.stopVertexForStop.values()) {
State s = spt.getState(tstop);
if (s != null) {
// note that we calculate the time based on the walk speed here rather than
// based on the time. this matches what we do in the stop tree cache.
int stopIndex = indexForStop.get(tstop.getIndex());
if (stopIndex != -1) {
if (useTimes)
accessTimes.put(stopIndex, (int) s.getElapsedTimeSeconds());
else
accessTimes.put(stopIndex, (int) (s.getWalkDistance() / walkSpeed));
}
}
}
// and handle the additional stops
for (TObjectIntIterator<AddTripPattern.TemporaryStop> it = addedStops.iterator(); it.hasNext(); ) {
it.advance();
AddTripPattern.TemporaryStop tstop = it.key();
if (tstop.sample == null) {
continue;
}
double dist = Double.POSITIVE_INFINITY;
if (tstop.sample.v0 != null) {
State s0 = spt.getState(tstop.sample.v0);
if (s0 != null) {
dist = s0.getWalkDistance() + tstop.sample.d0;
}
}
if (tstop.sample.v1 != null) {
State s1 = spt.getState(tstop.sample.v1);
if (s1 != null) {
double d1 = s1.getWalkDistance() + tstop.sample.d1;
dist = Double.isInfinite(dist) ? d1 : Math.min(d1, dist);
}
}
if (Double.isInfinite(dist))
continue;
// NB using the index in the worker data not the index in the graph!
accessTimes.put(it.value(), (int) (dist / walkSpeed));
}
return accessTimes;
}
use of org.opentripplanner.routing.core.State in project OpenTripPlanner by opentripplanner.
the class RepeatedRaptorProfileRouter method route.
public ResultEnvelope route() {
// When no sample set is provided, we're making isochrones.
boolean isochrone = (sampleSet == null);
// Does the search involve transit at all?
boolean transit = (request.transitModes != null && request.transitModes.isTransit());
long computationStartTime = System.currentTimeMillis();
LOG.info("Begin profile request");
// We only create data tables if transit is in use, otherwise they wouldn't serve any purpose.
if (raptorWorkerData == null && transit) {
long dataStart = System.currentTimeMillis();
raptorWorkerData = getRaptorWorkerData(request, graph, sampleSet, ts);
ts.raptorData = (int) (System.currentTimeMillis() - dataStart);
}
// Find the transit stops that are accessible from the origin, leaving behind an SPT behind of access
// times to all reachable vertices.
long initialStopStartTime = System.currentTimeMillis();
// This will return null if we have no transit data, but will leave behind a pre-transit SPT.
TIntIntMap transitStopAccessTimes = findInitialStops(false, raptorWorkerData);
// Create an array containing the best travel time in seconds to each vertex in the graph when not using transit.
int[] nonTransitTimes = new int[Vertex.getMaxIndex()];
Arrays.fill(nonTransitTimes, Integer.MAX_VALUE);
for (State state : preTransitSpt.getAllStates()) {
// Note that we are using the walk distance divided by speed here in order to be consistent with the
// least-walk optimization in the initial stop search (and the stop tree cache which is used at egress)
// TODO consider why this matters, I'm using reported travel time from the states
int time = (int) state.getElapsedTimeSeconds();
int vidx = state.getVertex().getIndex();
int otime = nonTransitTimes[vidx];
// There may be dominated states in the SPT. Make sure we don't include them here.
if (otime > time) {
nonTransitTimes[vidx] = time;
}
}
ts.initialStopSearch = (int) (System.currentTimeMillis() - initialStopStartTime);
// FIXME wasn't the walk search already performed above?
long walkSearchStart = System.currentTimeMillis();
// in the graph. Therefore we must replace the vertex-indexed array with a new point-indexed array.
if (sampleSet != null) {
nonTransitTimes = sampleSet.eval(nonTransitTimes);
}
ts.walkSearch = (int) (System.currentTimeMillis() - walkSearchStart);
if (transit) {
RaptorWorker worker = new RaptorWorker(raptorWorkerData, request);
propagatedTimesStore = worker.runRaptor(graph, transitStopAccessTimes, nonTransitTimes, ts);
ts.initialStopCount = transitStopAccessTimes.size();
} else {
// Nontransit case: skip transit routing and make a propagated times store based on only one row.
propagatedTimesStore = new PropagatedTimesStore(graph, request, nonTransitTimes.length);
int[][] singleRoundResults = new int[1][];
singleRoundResults[0] = nonTransitTimes;
propagatedTimesStore.setFromArray(singleRoundResults, new boolean[] { true }, PropagatedTimesStore.ConfidenceCalculationMethod.MIN_MAX);
}
for (int min : propagatedTimesStore.mins) {
if (min != RaptorWorker.UNREACHED)
ts.targetsReached++;
}
ts.compute = (int) (System.currentTimeMillis() - computationStartTime);
LOG.info("Profile request finished in {} seconds", (ts.compute) / 1000.0);
// Turn the results of the search into isochrone geometries or accessibility data as requested.
long resultSetStart = System.currentTimeMillis();
ResultEnvelope envelope = new ResultEnvelope();
if (isochrone) {
// No destination point set was provided and we're just making isochrones based on travel time to vertices,
// rather than finding access times to a set of user-specified points.
envelope = propagatedTimesStore.makeIsochronesForVertices();
} else {
// A destination point set was provided. We've found access times to a set of specified points.
// TODO actually use those boolean params to calculate isochrones on a regular grid pointset
// TODO maybe there's a better way to pass includeTimes in here from the clusterRequest,
// maybe we should just provide the whole clusterRequest not just the wrapped profileRequest.
envelope = propagatedTimesStore.makeResults(sampleSet, includeTimes, true, false);
}
ts.resultSets = (int) (System.currentTimeMillis() - resultSetStart);
return envelope;
}
Aggregations