/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.routing.edgetype; import org.onebusaway.gtfs.model.Stop; import org.onebusaway.gtfs.model.Trip; import org.opentripplanner.common.geometry.GeometryUtils; import org.opentripplanner.common.geometry.SphericalDistanceLibrary; import org.opentripplanner.gtfs.GtfsLibrary; import org.opentripplanner.routing.core.RoutingRequest; import org.opentripplanner.routing.core.ServiceDay; import org.opentripplanner.routing.core.State; import org.opentripplanner.routing.core.StateEditor; import org.opentripplanner.routing.core.TraverseMode; import org.opentripplanner.routing.graph.Edge; import org.opentripplanner.routing.trippattern.TripTimes; import org.opentripplanner.routing.vertextype.OnboardDepartVertex; import org.opentripplanner.routing.vertextype.PatternStopVertex; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.LineString; /** * A transit vehicle's journey (temporary vertex) between departure while onboard a trip and arrival * at the next. This version represents a set of such journeys specified by a TripPattern. * * @author laurent */ public class OnBoardDepartPatternHop extends Edge implements OnBoardForwardEdge { private static final long serialVersionUID = 1L; private TripTimes tripTimes; private ServiceDay serviceDay; private int stopIndex; private float positionInHop; private Trip trip; private Stop endStop; private LineString geometry = null; /** * @param from Originating vertex. * @param to Destination vertex: a PatternStopVertex for the next stop of the current hop. * @param tripTimes Resolved trip times for the trip with updated real-time info if available. * @param serviceDay Service day on which trip is running. * @param stopIndex Index of the *next* stop. * @param positionInHop Between 0 to 1, an estimation of the covered distance in this hop so * far. */ public OnBoardDepartPatternHop(OnboardDepartVertex from, PatternStopVertex to, TripTimes tripTimes, ServiceDay serviceDay, int stopIndex, float positionInHop) { super(from, to); this.stopIndex = stopIndex; this.tripTimes = tripTimes; this.positionInHop = positionInHop; this.trip = tripTimes.getTrip(); this.endStop = to.getStop(); } public double getDistance() { /* * Do not multiply by positionInHop, as it is already taken into account by the from vertex * location. */ return SphericalDistanceLibrary.getInstance().distance(getFromVertex().getY(), getFromVertex().getX(), endStop.getLat(), endStop.getLon()); } public TraverseMode getMode() { return GtfsLibrary.getTraverseMode(trip.getRoute()); } public String getName() { return GtfsLibrary.getRouteName(trip.getRoute()); } public State optimisticTraverse(State state0) { return traverse(state0); } public State traverse(State state0) { RoutingRequest options = state0.getOptions(); if (options.isReverseOptimizing() || options.isReverseOptimizeOnTheFly()) { throw new UnsupportedOperationException( "Cannot (yet) reverse-optimize depart-on-board mode."); } /* Can't be traversed backwards. */ if (options.isArriveBy()) return null; StateEditor s1 = state0.edit(this); // s1.setBackMode(TraverseMode.BOARDING); TODO Do we need this? s1.setServiceDay(serviceDay); s1.setTripTimes(tripTimes); // s1.incrementNumBoardings(); TODO Needed? s1.setTripId(trip.getId()); s1.setZone(endStop.getZoneId()); s1.setRoute(trip.getRoute().getId()); int remainingTime = Math .round((1.0f - positionInHop) * tripTimes.getRunningTime(stopIndex)); s1.incrementTimeInSeconds(remainingTime); s1.incrementWeight(remainingTime); s1.setBackMode(getMode()); return s1.makeState(); } public void setGeometry(LineString geometry) { this.geometry = geometry; } public LineString getGeometry() { if (geometry == null) { Coordinate c1 = new Coordinate(getFromVertex().getX(), getFromVertex().getY()); Coordinate c2 = new Coordinate(endStop.getLon(), endStop.getLat()); geometry = GeometryUtils.getGeometryFactory().createLineString( new Coordinate[] { c1, c2 }); } return geometry; } public String toString() { return "OnBoardPatternHop(" + getFromVertex() + ", " + getToVertex() + ")"; } @Override public int getStopIndex() { return stopIndex; } @Override public Trip getTrip() { return trip; } @Override public String getDirection() { return tripTimes.getHeadsign(stopIndex); } }