use of org.onebusaway.gtfs.model.Stop in project OpenTripPlanner by opentripplanner.
the class GTFSPatternHopFactory method createParentStationTransfers.
/**
* Create bidirectional, "free" edges (zero-time, low-cost edges) between stops and their
* parent stations. This is used to produce implicit transfers between all stops that are
* part of the same parent station. It was introduced as a workaround to allow in-station
* transfers for underground/grade-separated transportation systems like the NYC subway (where
* it's important to provide in-station transfers for fare computation).
*
* This step used to be automatically applied whenever transfers.txt was used to create
* transfers (rather than or in addition to transfers through the street netowrk),
* but has been separated out since it is really a separate process.
*/
public void createParentStationTransfers() {
for (Stop stop : _dao.getAllStops()) {
String parentStation = stop.getParentStation();
if (parentStation != null) {
Vertex stopVertex = context.stationStopNodes.get(stop);
String agencyId = stop.getId().getAgencyId();
AgencyAndId parentStationId = new AgencyAndId(agencyId, parentStation);
Stop parentStop = _dao.getStopForId(parentStationId);
Vertex parentStopVertex = context.stationStopNodes.get(parentStop);
new FreeEdge(parentStopVertex, stopVertex);
new FreeEdge(stopVertex, parentStopVertex);
// Stops with location_type=2 (entrances as defined in the pathways.txt
// proposal) have no arrive/depart vertices, hence the null checks.
Vertex stopArriveVertex = context.stopArriveNodes.get(stop);
Vertex parentStopArriveVertex = context.stopArriveNodes.get(parentStop);
if (stopArriveVertex != null && parentStopArriveVertex != null) {
new FreeEdge(parentStopArriveVertex, stopArriveVertex);
new FreeEdge(stopArriveVertex, parentStopArriveVertex);
}
Vertex stopDepartVertex = context.stopDepartNodes.get(stop);
Vertex parentStopDepartVertex = context.stopDepartNodes.get(parentStop);
if (stopDepartVertex != null && parentStopDepartVertex != null) {
new FreeEdge(parentStopDepartVertex, stopDepartVertex);
new FreeEdge(stopDepartVertex, parentStopDepartVertex);
}
// TODO: provide a cost for these edges when stations and
// stops have different locations
}
}
}
use of org.onebusaway.gtfs.model.Stop in project OpenTripPlanner by opentripplanner.
the class GTFSPatternHopFactory method createGeometry.
/**
* Creates a set of geometries for a single trip, considering the GTFS shapes.txt,
* The geometry is broken down into one geometry per inter-stop segment ("hop"). We also need a shape for the entire
* trip and tripPattern, but given the complexity of the existing code for generating hop geometries, we will create
* the full-trip geometry by simply concatenating the hop geometries.
*
* This geometry will in fact be used for an entire set of trips in a trip pattern. Technically one of the trips
* with exactly the same sequence of stops could follow a different route on the streets, but that's very uncommon.
*/
private LineString[] createGeometry(Graph graph, Trip trip, List<StopTime> stopTimes) {
AgencyAndId shapeId = trip.getShapeId();
// One less geometry than stoptime as array indexes represetn hops not stops (fencepost problem).
LineString[] geoms = new LineString[stopTimes.size() - 1];
// Detect presence or absence of shape_dist_traveled on a per-trip basis
StopTime st0 = stopTimes.get(0);
boolean hasShapeDist = st0.isShapeDistTraveledSet();
if (hasShapeDist) {
// this trip has shape_dist in stop_times
for (int i = 0; i < stopTimes.size() - 1; ++i) {
st0 = stopTimes.get(i);
StopTime st1 = stopTimes.get(i + 1);
geoms[i] = getHopGeometryViaShapeDistTraveled(graph, shapeId, st0, st1);
}
return geoms;
}
LineString shape = getLineStringForShapeId(shapeId);
if (shape == null) {
// create straight line segments between stops for each hop
for (int i = 0; i < stopTimes.size() - 1; ++i) {
st0 = stopTimes.get(i);
StopTime st1 = stopTimes.get(i + 1);
LineString geometry = createSimpleGeometry(st0.getStop(), st1.getStop());
geoms[i] = geometry;
}
return geoms;
}
// This trip does not have shape_dist in stop_times, but does have an associated shape.
ArrayList<IndexedLineSegment> segments = new ArrayList<IndexedLineSegment>();
for (int i = 0; i < shape.getNumPoints() - 1; ++i) {
segments.add(new IndexedLineSegment(i, shape.getCoordinateN(i), shape.getCoordinateN(i + 1)));
}
// Find possible segment matches for each stop.
List<List<IndexedLineSegment>> possibleSegmentsForStop = new ArrayList<List<IndexedLineSegment>>();
int minSegmentIndex = 0;
for (int i = 0; i < stopTimes.size(); ++i) {
Stop stop = stopTimes.get(i).getStop();
Coordinate coord = new Coordinate(stop.getLon(), stop.getLat());
List<IndexedLineSegment> stopSegments = new ArrayList<IndexedLineSegment>();
double bestDistance = Double.MAX_VALUE;
IndexedLineSegment bestSegment = null;
int maxSegmentIndex = -1;
int index = -1;
int minSegmentIndexForThisStop = -1;
for (IndexedLineSegment segment : segments) {
index++;
if (segment.index < minSegmentIndex) {
continue;
}
double distance = segment.distance(coord);
if (distance < maxStopToShapeSnapDistance) {
stopSegments.add(segment);
maxSegmentIndex = index;
if (minSegmentIndexForThisStop == -1)
minSegmentIndexForThisStop = index;
} else if (distance < bestDistance) {
bestDistance = distance;
bestSegment = segment;
if (maxSegmentIndex != -1) {
maxSegmentIndex = index;
}
}
}
if (stopSegments.size() == 0) {
// no segments within 150m
// fall back to nearest segment
stopSegments.add(bestSegment);
minSegmentIndex = bestSegment.index;
} else {
minSegmentIndex = minSegmentIndexForThisStop;
Collections.sort(stopSegments, new IndexedLineSegmentComparator(coord));
}
for (int j = i - 1; j >= 0; j--) {
for (Iterator<IndexedLineSegment> it = possibleSegmentsForStop.get(j).iterator(); it.hasNext(); ) {
IndexedLineSegment segment = it.next();
if (segment.index > maxSegmentIndex) {
it.remove();
}
}
}
possibleSegmentsForStop.add(stopSegments);
}
List<LinearLocation> locations = getStopLocations(possibleSegmentsForStop, stopTimes, 0, -1);
if (locations == null) {
for (int i = 0; i < stopTimes.size() - 1; ++i) {
st0 = stopTimes.get(i);
StopTime st1 = stopTimes.get(i + 1);
LineString geometry = createSimpleGeometry(st0.getStop(), st1.getStop());
geoms[i] = geometry;
// this warning is not strictly correct, but will do
LOG.warn(graph.addBuilderAnnotation(new BogusShapeGeometryCaught(shapeId, st0, st1)));
}
return geoms;
}
Iterator<LinearLocation> locationIt = locations.iterator();
LinearLocation endLocation = locationIt.next();
double distanceSoFar = 0;
int last = 0;
for (int i = 0; i < stopTimes.size() - 1; ++i) {
LinearLocation startLocation = endLocation;
endLocation = locationIt.next();
// it does not matter at all if this is accurate so long as it is consistent
for (int j = last; j < startLocation.getSegmentIndex(); ++j) {
Coordinate from = shape.getCoordinateN(j);
Coordinate to = shape.getCoordinateN(j + 1);
double xd = from.x - to.x;
double yd = from.y - to.y;
distanceSoFar += FastMath.sqrt(xd * xd + yd * yd);
}
last = startLocation.getSegmentIndex();
double startIndex = distanceSoFar + startLocation.getSegmentFraction() * startLocation.getSegmentLength(shape);
// advance distanceSoFar up to start of segment containing endLocation
for (int j = last; j < endLocation.getSegmentIndex(); ++j) {
Coordinate from = shape.getCoordinateN(j);
Coordinate to = shape.getCoordinateN(j + 1);
double xd = from.x - to.x;
double yd = from.y - to.y;
distanceSoFar += FastMath.sqrt(xd * xd + yd * yd);
}
last = startLocation.getSegmentIndex();
double endIndex = distanceSoFar + endLocation.getSegmentFraction() * endLocation.getSegmentLength(shape);
ShapeSegmentKey key = new ShapeSegmentKey(shapeId, startIndex, endIndex);
LineString geometry = _geometriesByShapeSegmentKey.get(key);
if (geometry == null) {
LocationIndexedLine locationIndexed = new LocationIndexedLine(shape);
geometry = (LineString) locationIndexed.extractLine(startLocation, endLocation);
// Pack the resulting line string
CoordinateSequence sequence = new PackedCoordinateSequence.Double(geometry.getCoordinates(), 2);
geometry = _geometryFactory.createLineString(sequence);
}
geoms[i] = geometry;
}
return geoms;
}
use of org.onebusaway.gtfs.model.Stop in project OpenTripPlanner by opentripplanner.
the class GTFSPatternHopFactory method linkStopsToParentStations.
/**
* Links the vertices representing parent stops to their child stops bidirectionally. This is
* not intended to provide implicit transfers (i.e. child stop to parent station to another
* child stop) but instead to allow beginning or ending a path (itinerary) at a parent station.
*
* Currently this linking is only intended for use in the long distance path service. The
* pathparsers should ensure that it is effectively ignored in other path services, and even in
* the long distance path service anywhere but the beginning or end of a path.
*/
public void linkStopsToParentStations(Graph graph) {
for (Stop stop : _dao.getAllStops()) {
String parentStation = stop.getParentStation();
if (parentStation != null) {
TransitStop stopVertex = (TransitStop) context.stationStopNodes.get(stop);
String agencyId = stop.getId().getAgencyId();
AgencyAndId parentStationId = new AgencyAndId(agencyId, parentStation);
Stop parentStop = _dao.getStopForId(parentStationId);
if (context.stationStopNodes.get(parentStop) instanceof TransitStation) {
TransitStation parentStopVertex = (TransitStation) context.stationStopNodes.get(parentStop);
new StationStopEdge(parentStopVertex, stopVertex);
new StationStopEdge(stopVertex, parentStopVertex);
} else {
LOG.warn(graph.addBuilderAnnotation(new NonStationParentStation(stopVertex)));
}
}
}
}
use of org.onebusaway.gtfs.model.Stop in project OpenTripPlanner by opentripplanner.
the class GTFSPatternHopFactory method getStopLocations.
/**
* Find a consistent, increasing list of LinearLocations along a shape for a set of stops.
* Handles loops routes.
* @return
*/
private List<LinearLocation> getStopLocations(List<List<IndexedLineSegment>> possibleSegmentsForStop, List<StopTime> stopTimes, int index, int prevSegmentIndex) {
if (index == stopTimes.size()) {
return new LinkedList<LinearLocation>();
}
StopTime st = stopTimes.get(index);
Stop stop = st.getStop();
Coordinate stopCoord = new Coordinate(stop.getLon(), stop.getLat());
for (IndexedLineSegment segment : possibleSegmentsForStop.get(index)) {
if (segment.index < prevSegmentIndex) {
// can't go backwards along line
continue;
}
List<LinearLocation> locations = getStopLocations(possibleSegmentsForStop, stopTimes, index + 1, segment.index);
if (locations != null) {
LinearLocation location = new LinearLocation(0, segment.index, segment.fraction(stopCoord));
locations.add(0, location);
// we found one!
return locations;
}
}
return null;
}
use of org.onebusaway.gtfs.model.Stop 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;
}
}
}
}
Aggregations