/** Generates a TripPlan from a set of paths */
  public TripPlan generatePlan(List<GraphPath> paths, RoutingRequest request) {

    GraphPath exemplar = paths.get(0);
    Vertex tripStartVertex = exemplar.getStartVertex();
    Vertex tripEndVertex = exemplar.getEndVertex();
    String startName = tripStartVertex.getName();
    String endName = tripEndVertex.getName();

    // Use vertex labels if they don't have names
    if (startName == null) {
      startName = tripStartVertex.getLabel();
    }
    if (endName == null) {
      endName = tripEndVertex.getLabel();
    }
    Place from = new Place(tripStartVertex.getX(), tripStartVertex.getY(), startName);
    Place to = new Place(tripEndVertex.getX(), tripEndVertex.getY(), endName);

    TripPlan plan = new TripPlan(from, to, request.getDateTime());

    for (GraphPath path : paths) {
      Itinerary itinerary = generateItinerary(path, request.getShowIntermediateStops());
      plan.addItinerary(itinerary);
    }
    return plan;
  }
 public double getTargetDistance(Vertex vertex) {
   int vertexIndex = vertex.getIndex();
   if (vertexIndex < distance.length) {
     if (distance[vertexIndex] > 0.0) {
       return distance[vertexIndex];
     } else {
       double d =
           distanceLibrary.fastDistance(
               realTargetCoordinate.y, realTargetCoordinate.x, vertex.getY(), vertex.getX());
       distance[vertexIndex] = d;
       return d;
     }
   } else {
     return distanceLibrary.fastDistance(
         realTargetCoordinate.y, realTargetCoordinate.x, vertex.getY(), vertex.getX());
   }
 }
 private void labelState(State s, String str) {
   fill(240, 240, 240);
   Vertex v = s.getVertex();
   drawVertex(v, 8);
   str += " " + shortDateFormat.format(new Date(s.getTime() * 1000));
   str += " [" + (int) s.getWeight() + "]";
   double x = toScreenX(v.getX()) + 10;
   double y = toScreenY(v.getY());
   double dy = y - lastLabelY;
   if (dy == 0) {
     y = lastLabelY + 20;
   } else if (Math.abs(dy) < 20) {
     y = lastLabelY + Math.signum(dy) * 20;
   }
   text(str, (float) x, (float) y);
   lastLabelY = y;
 }
  @Test
  public final void testOnBoardDepartureTime() {
    Coordinate[] coordinates = new Coordinate[5];
    coordinates[0] = new Coordinate(0.0, 0.0);
    coordinates[1] = new Coordinate(0.0, 1.0);
    coordinates[2] = new Coordinate(2.0, 1.0);
    coordinates[3] = new Coordinate(5.0, 1.0);
    coordinates[4] = new Coordinate(5.0, 5.0);

    PatternDepartVertex depart = mock(PatternDepartVertex.class);
    PatternArriveVertex dwell = mock(PatternArriveVertex.class);
    PatternArriveVertex arrive = mock(PatternArriveVertex.class);
    Graph graph = mock(Graph.class);
    RoutingRequest routingRequest = mock(RoutingRequest.class);
    ServiceDay serviceDay = mock(ServiceDay.class);

    when(graph.getTimeZone()).thenReturn(TimeZone.getTimeZone("GMT"));

    GeometryFactory geometryFactory = GeometryUtils.getGeometryFactory();
    CoordinateSequenceFactory coordinateSequenceFactory =
        geometryFactory.getCoordinateSequenceFactory();
    CoordinateSequence coordinateSequence = coordinateSequenceFactory.create(coordinates);
    LineString geometry = new LineString(coordinateSequence, geometryFactory);
    ArrayList<Edge> hops = new ArrayList<Edge>(2);
    RoutingContext routingContext = new RoutingContext(routingRequest, graph, null, arrive);
    AgencyAndId agencyAndId = new AgencyAndId("Agency", "ID");
    Route route = new Route();
    ArrayList<StopTime> stopTimes = new ArrayList<StopTime>(3);
    StopTime stopDepartTime = new StopTime();
    StopTime stopDwellTime = new StopTime();
    StopTime stopArriveTime = new StopTime();
    Stop stopDepart = new Stop();
    Stop stopDwell = new Stop();
    Stop stopArrive = new Stop();
    Trip trip = new Trip();

    routingContext.serviceDays = new ArrayList<ServiceDay>(Collections.singletonList(serviceDay));
    route.setId(agencyAndId);
    stopDepart.setId(agencyAndId);
    stopDwell.setId(agencyAndId);
    stopArrive.setId(agencyAndId);
    stopDepartTime.setStop(stopDepart);
    stopDepartTime.setDepartureTime(0);
    stopDwellTime.setArrivalTime(20);
    stopDwellTime.setStop(stopDwell);
    stopDwellTime.setDepartureTime(40);
    stopArriveTime.setArrivalTime(60);
    stopArriveTime.setStop(stopArrive);
    stopTimes.add(stopDepartTime);
    stopTimes.add(stopDwellTime);
    stopTimes.add(stopArriveTime);
    trip.setId(agencyAndId);
    trip.setTripHeadsign("The right");

    TripTimes tripTimes = new TripTimes(trip, stopTimes, new Deduplicator());
    StopPattern stopPattern = new StopPattern(stopTimes);
    TripPattern tripPattern = new TripPattern(route, stopPattern);

    when(depart.getTripPattern()).thenReturn(tripPattern);
    when(dwell.getTripPattern()).thenReturn(tripPattern);

    PatternHop patternHop0 = new PatternHop(depart, dwell, stopDepart, stopDwell, 0);
    PatternHop patternHop1 = new PatternHop(dwell, arrive, stopDwell, stopArrive, 1);

    hops.add(patternHop0);
    hops.add(patternHop1);

    when(graph.getEdges()).thenReturn(hops);
    when(depart.getCoordinate()).thenReturn(new Coordinate(0, 0));
    when(dwell.getCoordinate()).thenReturn(new Coordinate(0, 0));
    when(arrive.getCoordinate()).thenReturn(new Coordinate(0, 0));
    when(routingRequest.getFrom()).thenReturn(new GenericLocation());
    when(routingRequest.getStartingTransitTripId()).thenReturn(agencyAndId);
    when(serviceDay.secondsSinceMidnight(anyInt())).thenReturn(9);

    patternHop0.setGeometry(geometry);
    tripPattern.add(tripTimes);
    graph.index = new GraphIndex(graph);

    coordinates = new Coordinate[3];
    coordinates[0] = new Coordinate(3.5, 1.0);
    coordinates[1] = new Coordinate(5.0, 1.0);
    coordinates[2] = new Coordinate(5.0, 5.0);

    coordinateSequence = coordinateSequenceFactory.create(coordinates);
    geometry = new LineString(coordinateSequence, geometryFactory);

    Vertex vertex = onBoardDepartServiceImpl.setupDepartOnBoard(routingContext);
    Edge edge = vertex.getOutgoing().toArray(new Edge[1])[0];

    assertEquals(vertex, edge.getFromVertex());
    assertEquals(dwell, edge.getToVertex());
    assertEquals("The right", edge.getDirection());
    assertEquals(geometry, edge.getGeometry());

    assertEquals(coordinates[0].x, vertex.getX(), 0.0);
    assertEquals(coordinates[0].y, vertex.getY(), 0.0);
  }
  @Test
  public final void testOnBoardDepartureAtArrivalTime() {
    Coordinate[] coordinates = new Coordinate[2];
    coordinates[0] = new Coordinate(0.0, 0.0);
    coordinates[1] = new Coordinate(0.0, 1.0);

    TransitStop station0 = mock(TransitStop.class);
    TransitStop station1 = mock(TransitStop.class);
    PatternDepartVertex depart = mock(PatternDepartVertex.class);
    PatternArriveVertex arrive = mock(PatternArriveVertex.class);
    Graph graph = mock(Graph.class);
    RoutingRequest routingRequest = mock(RoutingRequest.class);
    ServiceDay serviceDay = mock(ServiceDay.class);

    when(graph.getTimeZone()).thenReturn(TimeZone.getTimeZone("GMT"));
    when(station0.getX()).thenReturn(coordinates[0].x);
    when(station0.getY()).thenReturn(coordinates[0].y);
    when(station1.getX()).thenReturn(coordinates[1].x);
    when(station1.getY()).thenReturn(coordinates[1].y);

    RoutingContext routingContext = new RoutingContext(routingRequest, graph, null, arrive);
    AgencyAndId agencyAndId = new AgencyAndId("Agency", "ID");
    Route route = new Route();
    ArrayList<StopTime> stopTimes = new ArrayList<StopTime>(2);
    StopTime stopDepartTime = new StopTime();
    StopTime stopArriveTime = new StopTime();
    Stop stopDepart = new Stop();
    Stop stopArrive = new Stop();
    Trip trip = new Trip();

    routingContext.serviceDays = new ArrayList<ServiceDay>(Collections.singletonList(serviceDay));
    route.setId(agencyAndId);
    stopDepart.setId(new AgencyAndId("Station", "0"));
    stopArrive.setId(new AgencyAndId("Station", "1"));
    stopDepartTime.setStop(stopDepart);
    stopDepartTime.setDepartureTime(0);
    stopArriveTime.setArrivalTime(10);
    stopArriveTime.setStop(stopArrive);
    stopTimes.add(stopDepartTime);
    stopTimes.add(stopArriveTime);
    trip.setId(agencyAndId);

    TripTimes tripTimes = new TripTimes(trip, stopTimes, new Deduplicator());
    StopPattern stopPattern = new StopPattern(stopTimes);
    TripPattern tripPattern = new TripPattern(route, stopPattern);

    when(depart.getTripPattern()).thenReturn(tripPattern);

    PatternHop patternHop = new PatternHop(depart, arrive, stopDepart, stopArrive, 0);

    when(graph.getEdges()).thenReturn(Collections.<Edge>singletonList(patternHop));
    when(depart.getCoordinate()).thenReturn(new Coordinate(0, 0));
    when(arrive.getCoordinate()).thenReturn(new Coordinate(0, 0));
    when(routingRequest.getFrom()).thenReturn(new GenericLocation());
    when(routingRequest.getStartingTransitTripId()).thenReturn(agencyAndId);
    when(serviceDay.secondsSinceMidnight(anyInt())).thenReturn(10);
    when(graph.getVertex("Station_0")).thenReturn(station0);
    when(graph.getVertex("Station_1")).thenReturn(station1);

    tripPattern.add(tripTimes);
    graph.index = new GraphIndex(graph);

    Vertex vertex = onBoardDepartServiceImpl.setupDepartOnBoard(routingContext);

    assertEquals(coordinates[1].x, vertex.getX(), 0.0);
    assertEquals(coordinates[1].y, vertex.getY(), 0.0);
  }
  @Override
  public boolean shouldSkipTraversalResult(
      Vertex origin,
      Vertex target,
      State parent,
      State current,
      ShortestPathTree spt,
      RoutingRequest traverseOptions) {
    if (realTarget == null) return false;

    final Vertex vertex = current.getVertex();
    int vertexIndex = vertex.getIndex();
    if (vertexIndex < distance.length) {
      if (distance[vertexIndex] > 0.0) {
        targetDistance = distance[vertexIndex];
      } else {
        targetDistance =
            distanceLibrary.fastDistance(
                realTargetCoordinate.y, realTargetCoordinate.x, vertex.getY(), vertex.getX());
        distance[vertexIndex] = targetDistance;
        if (vertex instanceof TransitStop && targetDistance < bestTargetDistance) {
          bestTargetDistance = targetDistance;
        }
      }
    } else {
      targetDistance =
          distanceLibrary.fastDistance(
              realTargetCoordinate.y, realTargetCoordinate.x, vertex.getY(), vertex.getX());
    }

    final double remainingWalk = traverseOptions.maxWalkDistance - current.getWalkDistance();
    final double minWalk;
    double minTime = 0;
    if (targetDistance > remainingWalk) {
      // then we must have some transit + some walk.
      minWalk = this.distanceToNearestTransitStop + vertex.getDistanceToNearestTransitStop();
      minTime =
          options.isArriveBy() ? traverseOptions.getAlightSlack() : traverseOptions.getBoardSlack();

      if (current.getBackEdge() instanceof StreetEdge
          && transitLocalStreets != null
          && !transitLocalStreets.transferrable(vertex)) {
        return true;
      }
    } else {
      // could walk directly to destination
      if (targetDistance < distanceToNearestTransitStop
          || transitLocalStreets == null
          || !transitLocalStreets.transferrable(vertex)) minWalk = targetDistance;
      else minWalk = distanceToNearestTransitStop;
    }
    if (minWalk > remainingWalk) return true;

    final double optimisticDistance = current.getWalkDistance() + minWalk;

    final double walkTime = minWalk / speedUpperBound;
    minTime += (targetDistance - minWalk) / Raptor.MAX_TRANSIT_SPEED + walkTime;

    double stateTime = current.getOptimizedElapsedTime() + minTime;

    double walkDistance =
        FastMath.max(
            optimisticDistance * Raptor.WALK_EPSILON,
            optimisticDistance + transferTimeInWalkDistance);

    int i = 0;
    boolean prevBounded = !bounders.isEmpty();
    for (State bounder : bounders) {
      if (removedBoundingStates.contains(bounder)) continue;
      if (current.getWeight() + minTime + walkTime * (options.getWalkReluctance() - 1)
          > bounder.getWeight() * WORST_WEIGHT_DIFFERENCE_FACTOR) {
        return true;
      }
      int prevTime = previousArrivalTime.get(i++);

      if (walkDistance > bounder.getWalkDistance()
          && current.getNumBoardings() >= bounder.getNumBoardings()) {
        if (current.getElapsedTime() + minTime >= bounder.getElapsedTime()) {
          return true;
        } else if (prevTime > 0
            && (options.arriveBy
                ? (current.getTime() - minTime >= prevTime)
                : ((current.getTime() + minTime) <= prevTime))) {
          prevBounded = false;
        }
      } else {
        prevBounded = false;
      }

      // check that the new path is not much longer in time than the bounding path
      if (bounder.getOptimizedElapsedTime() * timeBoundFactor < stateTime) {
        return true;
      }
    }
    return prevBounded;
  }
 private void drawVertex(Vertex v, double r) {
   noStroke();
   ellipse(toScreenX(v.getX()), toScreenY(v.getY()), r, r);
 }