use of org.opentripplanner.routing.vertextype.TransitStop in project OpenTripPlanner by opentripplanner.
the class Graph method calculateTransitCenter.
/**
* Calculates Transit center from median of coordinates of all transitStops if graph
* has transit. If it doesn't it isn't calculated. (mean walue of min, max latitude and longitudes are used)
*
* Transit center is saved in center variable
*
* This speeds up calculation, but problem is that median needs to have all of latitudes/longitudes
* in memory, this can become problematic in large installations. It works without a problem on New York State.
* @see GraphEnvelope
*/
public void calculateTransitCenter() {
if (hasTransit) {
TDoubleList latitudes = new TDoubleLinkedList();
TDoubleList longitudes = new TDoubleLinkedList();
Median median = new Median();
getVertices().stream().filter(v -> v instanceof TransitStop).forEach(v -> {
latitudes.add(v.getLat());
longitudes.add(v.getLon());
});
median.setData(latitudes.toArray());
double medianLatitude = median.evaluate();
median = new Median();
median.setData(longitudes.toArray());
double medianLongitude = median.evaluate();
this.center = new Coordinate(medianLongitude, medianLatitude);
}
}
use of org.opentripplanner.routing.vertextype.TransitStop in project OpenTripPlanner by opentripplanner.
the class PreBoardEdge method traverse.
@Override
public State traverse(State s0) {
RoutingRequest options = s0.getOptions();
// Ignore this edge if its stop is banned
if (!options.bannedStops.isEmpty()) {
if (options.bannedStops.matches(((TransitStop) fromv).getStop())) {
return null;
}
}
if (!options.bannedStopsHard.isEmpty()) {
if (options.bannedStopsHard.matches(((TransitStop) fromv).getStop())) {
return null;
}
}
if (options.arriveBy) {
/* Traverse backward: not much to do */
StateEditor s1 = s0.edit(this);
TransitStop fromVertex = (TransitStop) getFromVertex();
// apply board slack
s1.incrementTimeInSeconds(options.boardSlack);
s1.alightTransit();
s1.setBackMode(getMode());
return s1.makeState();
} else {
// options can be used to find transit stops without boarding vehicles.
if (!options.modes.isTransit())
return null;
// If we've hit our transfer limit, don't go any further
if (s0.getNumBoardings() > options.maxTransfers)
return null;
/* apply transfer rules */
/*
* look in the global transfer table for the rules from the previous stop to this stop.
*/
long t0 = s0.getTimeSeconds();
long slack;
if (s0.isEverBoarded()) {
slack = options.transferSlack - options.alightSlack;
} else {
slack = options.boardSlack;
}
long board_after = t0 + slack;
long transfer_penalty = 0;
// penalize transfers more heavily if requested by the user
if (s0.isEverBoarded()) {
// this is not the first boarding, therefore we must have "transferred" -- whether
// via a formal transfer or by walking.
transfer_penalty += options.transferPenalty;
}
StateEditor s1 = s0.edit(this);
s1.setTimeSeconds(board_after);
long wait_cost = board_after - t0;
s1.incrementWeight(wait_cost + transfer_penalty);
s1.setBackMode(getMode());
return s1.makeState();
}
}
use of org.opentripplanner.routing.vertextype.TransitStop in project OpenTripPlanner by opentripplanner.
the class SimpleStreetSplitter method link.
/**
* Link this vertex into the graph
*/
public boolean link(Vertex vertex, TraverseMode traverseMode, RoutingRequest options) {
// find nearby street edges
// TODO: we used to use an expanding-envelope search, which is more efficient in
// dense areas. but first let's see how inefficient this is. I suspect it's not too
// bad and the gains in simplicity are considerable.
final double radiusDeg = SphericalDistanceLibrary.metersToDegrees(MAX_SEARCH_RADIUS_METERS);
Envelope env = new Envelope(vertex.getCoordinate());
// Perform a simple local equirectangular projection, so distances are expressed in degrees latitude.
final double xscale = Math.cos(vertex.getLat() * Math.PI / 180);
// Expand more in the longitude direction than the latitude direction to account for converging meridians.
env.expandBy(radiusDeg / xscale, radiusDeg);
final double DUPLICATE_WAY_EPSILON_DEGREES = SphericalDistanceLibrary.metersToDegrees(DUPLICATE_WAY_EPSILON_METERS);
final TraverseModeSet traverseModeSet;
if (traverseMode == TraverseMode.BICYCLE) {
traverseModeSet = new TraverseModeSet(traverseMode, TraverseMode.WALK);
} else {
traverseModeSet = new TraverseModeSet(traverseMode);
}
// We sort the list of candidate edges by distance to the stop
// This should remove any issues with things coming out of the spatial index in different orders
// Then we link to everything that is within DUPLICATE_WAY_EPSILON_METERS of of the best distance
// so that we capture back edges and duplicate ways.
List<StreetEdge> candidateEdges = idx.query(env).stream().filter(streetEdge -> streetEdge instanceof StreetEdge).map(edge -> (StreetEdge) edge).filter(edge -> edge.canTraverse(traverseModeSet) && // only link to edges still in the graph.
edge.getToVertex().getIncoming().contains(edge)).collect(Collectors.toList());
// Make a map of distances to all edges.
final TIntDoubleMap distances = new TIntDoubleHashMap();
for (StreetEdge e : candidateEdges) {
distances.put(e.getId(), distance(vertex, e, xscale));
}
// Sort the list.
Collections.sort(candidateEdges, (o1, o2) -> {
double diff = distances.get(o1.getId()) - distances.get(o2.getId());
// A Comparator must return an integer but our distances are doubles.
if (diff < 0)
return -1;
if (diff > 0)
return 1;
return 0;
});
// find the closest candidate edges
if (candidateEdges.isEmpty() || distances.get(candidateEdges.get(0).getId()) > radiusDeg) {
// We only link to stops if we are searching for origin/destination and for that we need transitStopIndex.
if (destructiveSplitting || transitStopIndex == null) {
return false;
}
LOG.debug("No street edge was found for {}", vertex);
// We search for closest stops (since this is only used in origin/destination linking if no edges were found)
// in the same way the closest edges are found.
List<TransitStop> candidateStops = new ArrayList<>();
transitStopIndex.query(env).forEach(candidateStop -> candidateStops.add((TransitStop) candidateStop));
final TIntDoubleMap stopDistances = new TIntDoubleHashMap();
for (TransitStop t : candidateStops) {
stopDistances.put(t.getIndex(), distance(vertex, t, xscale));
}
Collections.sort(candidateStops, (o1, o2) -> {
double diff = stopDistances.get(o1.getIndex()) - stopDistances.get(o2.getIndex());
if (diff < 0) {
return -1;
}
if (diff > 0) {
return 1;
}
return 0;
});
if (candidateStops.isEmpty() || stopDistances.get(candidateStops.get(0).getIndex()) > radiusDeg) {
LOG.debug("Stops aren't close either!");
return false;
} else {
List<TransitStop> bestStops = Lists.newArrayList();
// Add stops until there is a break of epsilon meters.
// we do this to enforce determinism. if there are a lot of stops that are all extremely close to each other,
// we want to be sure that we deterministically link to the same ones every time. Any hard cutoff means things can
// fall just inside or beyond the cutoff depending on floating-point operations.
int i = 0;
do {
bestStops.add(candidateStops.get(i++));
} while (i < candidateStops.size() && stopDistances.get(candidateStops.get(i).getIndex()) - stopDistances.get(candidateStops.get(i - 1).getIndex()) < DUPLICATE_WAY_EPSILON_DEGREES);
for (TransitStop stop : bestStops) {
LOG.debug("Linking vertex to stop: {}", stop.getName());
makeTemporaryEdges((TemporaryStreetLocation) vertex, stop);
}
return true;
}
} else {
// find the best edges
List<StreetEdge> bestEdges = Lists.newArrayList();
// add edges until there is a break of epsilon meters.
// we do this to enforce determinism. if there are a lot of edges that are all extremely close to each other,
// we want to be sure that we deterministically link to the same ones every time. Any hard cutoff means things can
// fall just inside or beyond the cutoff depending on floating-point operations.
int i = 0;
do {
bestEdges.add(candidateEdges.get(i++));
} while (i < candidateEdges.size() && distances.get(candidateEdges.get(i).getId()) - distances.get(candidateEdges.get(i - 1).getId()) < DUPLICATE_WAY_EPSILON_DEGREES);
for (StreetEdge edge : bestEdges) {
link(vertex, edge, xscale, options);
}
// Warn if a linkage was made, but the linkage was suspiciously long.
if (vertex instanceof TransitStop) {
double distanceDegreesLatitude = distances.get(candidateEdges.get(0).getId());
int distanceMeters = (int) SphericalDistanceLibrary.degreesLatitudeToMeters(distanceDegreesLatitude);
if (distanceMeters > WARNING_DISTANCE_METERS) {
// Registering an annotation but not logging because tests produce thousands of these warnings.
graph.addBuilderAnnotation(new StopLinkedTooFar((TransitStop) vertex, distanceMeters));
}
}
return true;
}
}
use of org.opentripplanner.routing.vertextype.TransitStop 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.vertextype.TransitStop 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();
}
}
Aggregations