Search in sources :

Example 1 with WalkStep

use of org.opentripplanner.model.plan.WalkStep in project OpenTripPlanner by opentripplanner.

the class TransmodelGraphQLSchema method createPlanType.

public GraphQLObjectType createPlanType(GraphQLOutputType bookingArrangementType, GraphQLOutputType interchangeType, GraphQLOutputType linkGeometryType, GraphQLOutputType systemNoticeType, GraphQLOutputType authorityType, GraphQLOutputType operatorType, GraphQLOutputType bikeRentalStationType, GraphQLOutputType quayType, GraphQLOutputType estimatedCallType, GraphQLOutputType lineType, GraphQLOutputType serviceJourneyType, GraphQLOutputType ptSituationElementType) {
    final GraphQLObjectType placeType = GraphQLObjectType.newObject().name("Place").description("Common super class for all places (stop places, quays, car parks, bike parks and bike rental stations )").field(GraphQLFieldDefinition.newFieldDefinition().name("name").description("For transit quays, the name of the quay. For points of interest, the name of the POI.").type(Scalars.GraphQLString).dataFetcher(environment -> ((Place) environment.getSource()).name).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("vertexType").description("Type of vertex. (Normal, Bike sharing station, Bike P+R, Transit quay) Mostly used for better localization of bike sharing and P+R station names").type(EnumTypes.VERTEX_TYPE).dataFetcher(environment -> ((Place) environment.getSource()).vertexType).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("latitude").description("The latitude of the place.").type(new GraphQLNonNull(Scalars.GraphQLFloat)).dataFetcher(environment -> ((Place) environment.getSource()).coordinate.latitude()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("longitude").description("The longitude of the place.").type(new GraphQLNonNull(Scalars.GraphQLFloat)).dataFetcher(environment -> ((Place) environment.getSource()).coordinate.longitude()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("quay").description("The quay related to the place.").type(quayType).dataFetcher(environment -> ((Place) environment.getSource()).vertexType.equals(VertexType.TRANSIT) ? GqlUtil.getRoutingService(environment).getStopForId(((Place) environment.getSource()).stopId) : null).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("bikeRentalStation").type(bikeRentalStationType).description("The bike rental station related to the place").dataFetcher(environment -> {
        return ((Place) environment.getSource()).vertexType.equals(VertexType.BIKESHARE) ? GqlUtil.getRoutingService(environment).getBikerentalStationService().getBikeRentalStations().stream().filter(bikeRentalStation -> bikeRentalStation.id.equals(((Place) environment.getSource()).bikeShareId)).findFirst().orElse(null) : null;
    }).build()).build();
    final GraphQLObjectType pathGuidanceType = GraphQLObjectType.newObject().name("PathGuidance").description("A series of turn by turn instructions used for walking, biking and driving.").field(GraphQLFieldDefinition.newFieldDefinition().name("distance").description("The distance in meters that this step takes.").type(Scalars.GraphQLFloat).dataFetcher(environment -> ((WalkStep) environment.getSource()).distance).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("relativeDirection").description("The relative direction of this step.").type(EnumTypes.RELATIVE_DIRECTION).dataFetcher(environment -> ((WalkStep) environment.getSource()).relativeDirection).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("streetName").description("The name of the street.").type(Scalars.GraphQLString).dataFetcher(environment -> ((WalkStep) environment.getSource()).streetName).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("heading").description("The absolute direction of this step.").type(EnumTypes.ABSOLUTE_DIRECTION).dataFetcher(environment -> ((WalkStep) environment.getSource()).absoluteDirection).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("exit").description("When exiting a highway or traffic circle, the exit name/number.").type(Scalars.GraphQLString).dataFetcher(environment -> ((WalkStep) environment.getSource()).exit).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("stayOn").description("Indicates whether or not a street changes direction at an intersection.").type(Scalars.GraphQLBoolean).dataFetcher(environment -> ((WalkStep) environment.getSource()).stayOn).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("area").description("This step is on an open area, such as a plaza or train platform, and thus the directions should say something like \"cross\"").type(Scalars.GraphQLBoolean).dataFetcher(environment -> ((WalkStep) environment.getSource()).area).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("bogusName").description("The name of this street was generated by the system, so we should only display it once, and generally just display right/left directions").type(Scalars.GraphQLBoolean).dataFetcher(environment -> ((WalkStep) environment.getSource()).bogusName).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("latitude").description("The latitude of the step.").type(Scalars.GraphQLFloat).dataFetcher(environment -> ((WalkStep) environment.getSource()).startLocation.latitude()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("longitude").description("The longitude of the step.").type(Scalars.GraphQLFloat).dataFetcher(environment -> ((WalkStep) environment.getSource()).startLocation.longitude()).build()).build();
    final GraphQLObjectType legType = GraphQLObjectType.newObject().name("Leg").description("Part of a trip pattern. Either a ride on a public transport vehicle or access or path link to/from/between places").field(GraphQLFieldDefinition.newFieldDefinition().name("aimedStartTime").description("The aimed date and time this leg starts.").type(gqlUtil.dateTimeScalar).dataFetcher(environment -> ((Leg) environment.getSource()).startTime.getTimeInMillis() - (1000 * ((Leg) environment.getSource()).departureDelay)).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("expectedStartTime").description("The expected, realtime adjusted date and time this leg starts.").type(gqlUtil.dateTimeScalar).dataFetcher(environment -> ((Leg) environment.getSource()).startTime.getTimeInMillis()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("aimedEndTime").description("The aimed date and time this leg ends.").type(gqlUtil.dateTimeScalar).dataFetcher(environment -> ((Leg) environment.getSource()).endTime.getTimeInMillis() - (1000 * ((Leg) environment.getSource()).arrivalDelay)).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("expectedEndTime").description("The expected, realtime adjusted date and time this leg ends.").type(gqlUtil.dateTimeScalar).dataFetcher(environment -> ((Leg) environment.getSource()).endTime.getTimeInMillis()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("mode").description("The mode of transport or access (e.g., foot) used when traversing this leg.").type(EnumTypes.MODE).dataFetcher(environment -> ((Leg) environment.getSource()).mode).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("transportSubmode").description("The transport sub mode (e.g., localBus or expressBus) used when traversing this leg. Null if leg is not a ride").type(EnumTypes.TRANSPORT_SUBMODE).dataFetcher(environment -> TransmodelTransportSubmode.UNDEFINED).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("duration").description("The legs's duration in seconds").type(Scalars.GraphQLLong).dataFetcher(environment -> ((Leg) environment.getSource()).getDuration()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("directDuration").type(Scalars.GraphQLLong).description("NOT IMPLEMENTED").dataFetcher(environment -> ((Leg) environment.getSource()).getDuration()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("pointsOnLink").description("The legs's geometry.").type(linkGeometryType).dataFetcher(environment -> ((Leg) environment.getSource()).legGeometry).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("authority").description("For ride legs, the service authority used for this legs. For non-ride legs, null.").type(authorityType).dataFetcher(environment -> ((Leg) environment.getSource()).getAgency()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("operator").description("For ride legs, the operator used for this legs. For non-ride legs, null.").type(operatorType).dataFetcher(environment -> ((Leg) environment.getSource()).getOperator()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("realtime").description("Whether there is real-time data about this leg").type(Scalars.GraphQLBoolean).dataFetcher(environment -> ((Leg) environment.getSource()).realTime).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("distance").description("The distance traveled while traversing the leg in meters.").type(Scalars.GraphQLFloat).dataFetcher(environment -> ((Leg) environment.getSource()).distanceMeters).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("ride").description("Whether this leg is a ride leg or not.").type(Scalars.GraphQLBoolean).dataFetcher(environment -> ((Leg) environment.getSource()).isTransitLeg()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("rentedBike").description("Whether this leg is with a rented bike.").type(Scalars.GraphQLBoolean).dataFetcher(environment -> ((Leg) environment.getSource()).rentedBike).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("fromPlace").description("The Place where the leg originates.").type(new GraphQLNonNull(placeType)).dataFetcher(environment -> ((Leg) environment.getSource()).from).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("toPlace").description("The Place where the leg ends.").type(new GraphQLNonNull(placeType)).dataFetcher(environment -> ((Leg) environment.getSource()).to).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("fromEstimatedCall").description("EstimatedCall for the quay where the leg originates.").type(estimatedCallType).dataFetcher(environment -> tripTimeShortHelper.getTripTimeShortForFromPlace(environment.getSource(), gqlUtil.getRoutingService(environment))).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("toEstimatedCall").description("EstimatedCall for the quay where the leg ends.").type(estimatedCallType).dataFetcher(environment -> tripTimeShortHelper.getTripTimeShortForToPlace(environment.getSource(), gqlUtil.getRoutingService(environment))).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("line").description("For ride legs, the line. For non-ride legs, null.").type(lineType).dataFetcher(environment -> ((Leg) environment.getSource()).getRoute()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("serviceJourney").description("For ride legs, the service journey. For non-ride legs, null.").type(serviceJourneyType).dataFetcher(environment -> ((Leg) environment.getSource()).getTrip()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("intermediateQuays").description("For ride legs, intermediate quays between the Place where the leg originates and the Place where the leg ends. For non-ride legs, empty list.").type(new GraphQLNonNull(new GraphQLList(quayType))).dataFetcher(environment -> {
        List<StopArrival> stops = ((Leg) environment.getSource()).intermediateStops;
        if (stops == null || stops.isEmpty()) {
            return List.of();
        } else {
            return (stops.stream().filter(stop -> stop.place.stopId != null).map(s -> {
                return GqlUtil.getRoutingService(environment).getStopForId(s.place.stopId);
            }).filter(Objects::nonNull).collect(Collectors.toList()));
        }
    }).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("intermediateEstimatedCalls").description("For ride legs, estimated calls for quays between the Place where the leg originates and the Place where the leg ends. For non-ride legs, empty list.").type(new GraphQLNonNull(new GraphQLList(estimatedCallType))).dataFetcher(environment -> tripTimeShortHelper.getIntermediateTripTimeShortsForLeg((environment.getSource()), GqlUtil.getRoutingService(environment))).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("serviceJourneyEstimatedCalls").description("For ride legs, all estimated calls for the service journey. For non-ride legs, empty list.").type(new GraphQLNonNull(new GraphQLList(estimatedCallType))).dataFetcher(environment -> {
        return tripTimeShortHelper.getAllTripTimeShortsForLegsTrip(environment.getSource(), GqlUtil.getRoutingService(environment));
    }).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("situations").description("All relevant situations for this leg").type(new GraphQLNonNull(new GraphQLList(ptSituationElementType))).dataFetcher(environment -> ((Leg) environment.getSource()).transitAlerts).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("steps").description("Do we continue from a specified via place").type(new GraphQLNonNull(new GraphQLList(pathGuidanceType))).dataFetcher(environment -> ((Leg) environment.getSource()).walkSteps).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("interchangeFrom").description("NOT IMPLEMENTED").type(interchangeType).dataFetcher(environment -> null).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("interchangeTo").description("NOT IMPLEMENTED").type(interchangeType).dataFetcher(environment -> null).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("bookingArrangements").type(bookingArrangementType).build()).build();
    final GraphQLObjectType tripPatternType = GraphQLObjectType.newObject().name("TripPattern").description("List of legs constituting a suggested sequence of rides and links for a specific trip.").field(GraphQLFieldDefinition.newFieldDefinition().name("startTime").description("Time that the trip departs.").type(gqlUtil.dateTimeScalar).dataFetcher(environment -> ((Itinerary) environment.getSource()).startTime().getTime().getTime()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("endTime").description("Time that the trip arrives.").type(gqlUtil.dateTimeScalar).dataFetcher(environment -> ((Itinerary) environment.getSource()).endTime().getTime().getTime()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("duration").description("Duration of the trip, in seconds.").type(Scalars.GraphQLLong).dataFetcher(environment -> ((Itinerary) environment.getSource()).durationSeconds).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("directDuration").description("NOT IMPLEMENTED.").type(Scalars.GraphQLLong).dataFetcher(environment -> ((Itinerary) environment.getSource()).durationSeconds).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("waitingTime").description("How much time is spent waiting for transit to arrive, in seconds.").type(Scalars.GraphQLLong).dataFetcher(environment -> ((Itinerary) environment.getSource()).waitingTimeSeconds).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("distance").description("Total distance for the trip, in meters. NOT IMPLEMENTED").type(Scalars.GraphQLFloat).dataFetcher(environment -> ((Itinerary) environment.getSource()).distanceMeters()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("walkTime").description("How much time is spent walking, in seconds.").type(Scalars.GraphQLLong).dataFetcher(environment -> ((Itinerary) environment.getSource()).nonTransitTimeSeconds).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("walkDistance").description("How far the user has to walk, in meters.").type(Scalars.GraphQLFloat).dataFetcher(environment -> ((Itinerary) environment.getSource()).nonTransitDistanceMeters).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("legs").description("A list of legs. Each leg is either a walking (cycling, car) portion of the trip, or a ride leg on a particular vehicle. So a trip where the use walks to the Q train, transfers to the 6, then walks to their destination, has four legs.").type(new GraphQLNonNull(new GraphQLList(legType))).dataFetcher(environment -> ((Itinerary) environment.getSource()).legs).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("systemNotices").description("Get all system notices.").type(new GraphQLNonNull(new GraphQLList(systemNoticeType))).dataFetcher(env -> ((Itinerary) env.getSource()).systemNotices).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("weight").description("Generalized cost or weight of the itinerary. Used for debugging.").type(Scalars.GraphQLFloat).dataFetcher(env -> ((Itinerary) env.getSource()).generalizedCost).build()).build();
    GraphQLObjectType tripMetadataType = TripMetadataType.create(gqlUtil);
    return GraphQLObjectType.newObject().name("Trip").description("Description of a travel between two places.").field(GraphQLFieldDefinition.newFieldDefinition().name("dateTime").description("The time and date of travel").type(gqlUtil.dateTimeScalar).dataFetcher(env -> ((PlanResponse) env.getSource()).plan.date.getTime()).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("metadata").description("The trip request metadata.").type(tripMetadataType).dataFetcher(env -> ((PlanResponse) env.getSource()).metadata).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("fromPlace").description("The origin").type(new GraphQLNonNull(placeType)).dataFetcher(env -> ((PlanResponse) env.getSource()).plan.from).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("toPlace").description("The destination").type(new GraphQLNonNull(placeType)).dataFetcher(env -> ((PlanResponse) env.getSource()).plan.to).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("tripPatterns").description("A list of possible trip patterns").type(new GraphQLNonNull(new GraphQLList(tripPatternType))).dataFetcher(env -> ((PlanResponse) env.getSource()).plan.itineraries).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("messageEnums").description("A list of possible error messages as enum").type(new GraphQLNonNull(new GraphQLList(Scalars.GraphQLString))).dataFetcher(env -> ((PlanResponse) env.getSource()).messages.stream().map(Enum::name).collect(Collectors.toList())).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("messageStrings").description("A list of possible error messages in cleartext").type(new GraphQLNonNull(new GraphQLList(Scalars.GraphQLString))).dataFetcher(env -> ((PlanResponse) env.getSource()).listErrorMessages(env.getArgument("locale"))).build()).field(GraphQLFieldDefinition.newFieldDefinition().name("debugOutput").description("Information about the timings for the trip generation").type(new GraphQLNonNull(GraphQLObjectType.newObject().name("debugOutput").field(GraphQLFieldDefinition.newFieldDefinition().name("totalTime").type(Scalars.GraphQLLong).build()).build())).dataFetcher(env -> ((PlanResponse) env.getSource()).debugOutput).build()).build();
}
Also used : TripMetadataType(org.opentripplanner.ext.transmodelapi.model.timetable.TripMetadataType) RoutingService(org.opentripplanner.routing.RoutingService) STREET_MODE(org.opentripplanner.ext.transmodelapi.model.EnumTypes.STREET_MODE) ServerInfoType(org.opentripplanner.ext.transmodelapi.model.framework.ServerInfoType) GraphQLInputObjectType(graphql.schema.GraphQLInputObjectType) GraphQLFieldDefinition(graphql.schema.GraphQLFieldDefinition) LoggerFactory(org.slf4j.LoggerFactory) GraphQLInterfaceType(graphql.schema.GraphQLInterfaceType) PresentationType(org.opentripplanner.ext.transmodelapi.model.network.PresentationType) ServiceJourneyType(org.opentripplanner.ext.transmodelapi.model.timetable.ServiceJourneyType) TransitIdMapper.mapIDsToDomain(org.opentripplanner.ext.transmodelapi.mapping.TransitIdMapper.mapIDsToDomain) GraphQLInputObjectField(graphql.schema.GraphQLInputObjectField) TransportModeSlack(org.opentripplanner.ext.transmodelapi.model.TransportModeSlack) QuayType(org.opentripplanner.ext.transmodelapi.model.stop.QuayType) StopPlaceType(org.opentripplanner.ext.transmodelapi.model.stop.StopPlaceType) BookingArrangementType(org.opentripplanner.ext.transmodelapi.model.timetable.BookingArrangementType) MultilingualStringType(org.opentripplanner.ext.transmodelapi.model.framework.MultilingualStringType) TraverseMode(org.opentripplanner.routing.core.TraverseMode) PlaceInterfaceType(org.opentripplanner.ext.transmodelapi.model.stop.PlaceInterfaceType) GraphQLObjectType(graphql.schema.GraphQLObjectType) FeedScopedId(org.opentripplanner.model.FeedScopedId) MavenVersion(org.opentripplanner.common.MavenVersion) EnumTypes(org.opentripplanner.ext.transmodelapi.model.EnumTypes) GraphQLNamedOutputType(graphql.schema.GraphQLNamedOutputType) Collections.emptyList(java.util.Collections.emptyList) GraphQLNonNull(graphql.schema.GraphQLNonNull) Collection(java.util.Collection) TransitIdMapper(org.opentripplanner.ext.transmodelapi.mapping.TransitIdMapper) Set(java.util.Set) GraphQLArgument(graphql.schema.GraphQLArgument) TransmodelTransportSubmode(org.opentripplanner.ext.transmodelapi.model.TransmodelTransportSubmode) InfoLinkType(org.opentripplanner.ext.transmodelapi.model.framework.InfoLinkType) TimetabledPassingTimeType(org.opentripplanner.ext.transmodelapi.model.timetable.TimetabledPassingTimeType) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) TransitAlert(org.opentripplanner.routing.alertpatch.TransitAlert) List(java.util.List) Stream(java.util.stream.Stream) DefaultPageInfo(graphql.relay.DefaultPageInfo) BikeParkType(org.opentripplanner.ext.transmodelapi.model.stop.BikeParkType) BikeRentalStation(org.opentripplanner.routing.bike_rental.BikeRentalStation) PlanResponse(org.opentripplanner.ext.transmodelapi.model.PlanResponse) RequestFunctions(org.opentripplanner.routing.api.request.RequestFunctions) LocationInputType(org.opentripplanner.ext.transmodelapi.model.framework.LocationInputType) GraphQLEnumType(graphql.schema.GraphQLEnumType) JourneyWhiteListed(org.opentripplanner.ext.transmodelapi.model.route.JourneyWhiteListed) Relay(graphql.relay.Relay) JourneyPatternType(org.opentripplanner.ext.transmodelapi.model.network.JourneyPatternType) TRUE(java.lang.Boolean.TRUE) TripTimeShortHelper(org.opentripplanner.ext.transmodelapi.model.TripTimeShortHelper) Leg(org.opentripplanner.model.plan.Leg) StopAtDistance(org.opentripplanner.routing.graphfinder.StopAtDistance) DefaultRoutingRequestType(org.opentripplanner.ext.transmodelapi.model.DefaultRoutingRequestType) Itinerary(org.opentripplanner.model.plan.Itinerary) AuthorityType(org.opentripplanner.ext.transmodelapi.model.framework.AuthorityType) InterchangeType(org.opentripplanner.ext.transmodelapi.model.timetable.InterchangeType) StopArrival(org.opentripplanner.model.plan.StopArrival) WalkStep(org.opentripplanner.model.plan.WalkStep) GraphQLType(graphql.schema.GraphQLType) TRANSPORT_MODE(org.opentripplanner.ext.transmodelapi.model.EnumTypes.TRANSPORT_MODE) RoutingValidationException(org.opentripplanner.routing.error.RoutingValidationException) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Scalars(graphql.Scalars) DefaultConnection(graphql.relay.DefaultConnection) CollectionUtils(org.apache.commons.collections.CollectionUtils) NoticeType(org.opentripplanner.ext.transmodelapi.model.framework.NoticeType) GraphQLSchema(graphql.schema.GraphQLSchema) BikeRentalStationType(org.opentripplanner.ext.transmodelapi.model.stop.BikeRentalStationType) SystemNoticeType(org.opentripplanner.ext.transmodelapi.model.framework.SystemNoticeType) PointsOnLinkType(org.opentripplanner.ext.transmodelapi.model.framework.PointsOnLinkType) Place(org.opentripplanner.model.plan.Place) ValidityPeriodType(org.opentripplanner.ext.transmodelapi.model.framework.ValidityPeriodType) PtSituationElementType(org.opentripplanner.ext.transmodelapi.model.siri.sx.PtSituationElementType) DestinationDisplayType(org.opentripplanner.ext.transmodelapi.model.network.DestinationDisplayType) TariffZoneType(org.opentripplanner.ext.transmodelapi.model.stop.TariffZoneType) Logger(org.slf4j.Logger) OperatorType(org.opentripplanner.ext.transmodelapi.model.framework.OperatorType) GqlUtil(org.opentripplanner.ext.transmodelapi.support.GqlUtil) VertexType(org.opentripplanner.model.plan.VertexType) SimpleListConnection(graphql.relay.SimpleListConnection) GraphQLOutputType(graphql.schema.GraphQLOutputType) EstimatedCallType(org.opentripplanner.ext.transmodelapi.model.siri.et.EstimatedCallType) GraphQLList(graphql.schema.GraphQLList) LineType(org.opentripplanner.ext.transmodelapi.model.network.LineType) Route(org.opentripplanner.model.Route) GraphQLTypeReference(graphql.schema.GraphQLTypeReference) QuayAtDistanceType(org.opentripplanner.ext.transmodelapi.model.stop.QuayAtDistanceType) RoutingRequest(org.opentripplanner.routing.api.request.RoutingRequest) Comparator(java.util.Comparator) Collections(java.util.Collections) GraphQLList(graphql.schema.GraphQLList) StopArrival(org.opentripplanner.model.plan.StopArrival) PlanResponse(org.opentripplanner.ext.transmodelapi.model.PlanResponse) GraphQLObjectType(graphql.schema.GraphQLObjectType) GraphQLNonNull(graphql.schema.GraphQLNonNull) Objects(java.util.Objects) Itinerary(org.opentripplanner.model.plan.Itinerary) WalkStep(org.opentripplanner.model.plan.WalkStep) Place(org.opentripplanner.model.plan.Place) Leg(org.opentripplanner.model.plan.Leg)

Example 2 with WalkStep

use of org.opentripplanner.model.plan.WalkStep in project OpenTripPlanner by opentripplanner.

the class GraphPathToItineraryMapper method generateWalkSteps.

/**
 * Converts a list of street edges to a list of turn-by-turn directions.
 *
 * @param previous a non-transit leg that immediately precedes this one (bike-walking, say), or null
 */
public static List<WalkStep> generateWalkSteps(Graph graph, State[] states, WalkStep previous, Locale requestedLocale) {
    List<WalkStep> steps = new ArrayList<>();
    WalkStep step = null;
    // distance used for appending elevation profiles
    double lastAngle = 0, distance = 0;
    // track whether we are in a roundabout, and if so the exit number
    int roundaboutExit = 0;
    String roundaboutPreviousStreet = null;
    State onBikeRentalState = null, offBikeRentalState = null;
    for (int i = 0; i < states.length - 1; i++) {
        State backState = states[i];
        State forwardState = states[i + 1];
        Edge edge = forwardState.getBackEdge();
        if (edge instanceof RentABikeOnEdge)
            onBikeRentalState = forwardState;
        if (edge instanceof RentABikeOffEdge)
            offBikeRentalState = forwardState;
        boolean createdNewStep = false, disableZagRemovalForThisStep = false;
        if (edge instanceof FreeEdge) {
            continue;
        }
        if (forwardState.getBackMode() == null || !forwardState.getBackMode().isOnStreetNonTransit()) {
            // ignore STLs and the like
            continue;
        }
        Geometry geom = edge.getGeometry();
        if (geom == null) {
            continue;
        }
        // before or will come after
        if (edge instanceof ElevatorAlightEdge) {
            // don't care what came before or comes after
            step = createWalkStep(graph, forwardState, requestedLocale);
            createdNewStep = true;
            disableZagRemovalForThisStep = true;
            // tell the user where to get off the elevator using the exit notation, so the
            // i18n interface will say 'Elevator to <exit>'
            // what happens is that the webapp sees name == null and ignores that, and it sees
            // exit != null and uses to <exit>
            // the floor name is the AlightEdge name
            // reset to avoid confusion with 'Elevator on floor 1 to floor 1'
            step.streetName = ((ElevatorAlightEdge) edge).getName(requestedLocale);
            step.relativeDirection = RelativeDirection.ELEVATOR;
            steps.add(step);
            continue;
        }
        String streetName = edge.getName(requestedLocale);
        int idx = streetName.indexOf('(');
        String streetNameNoParens;
        if (idx > 0)
            streetNameNoParens = streetName.substring(0, idx - 1);
        else
            streetNameNoParens = streetName;
        if (step == null) {
            // first step
            step = createWalkStep(graph, forwardState, requestedLocale);
            createdNewStep = true;
            steps.add(step);
            double thisAngle = DirectionUtils.getFirstAngle(geom);
            if (previous == null) {
                step.setAbsoluteDirection(thisAngle);
                step.relativeDirection = RelativeDirection.DEPART;
            } else {
                step.setDirections(previous.angle, thisAngle, false);
            }
            // new step, set distance to length of first edge
            distance = edge.getDistanceMeters();
        } else if (((step.streetName != null && !step.streetNameNoParens().equals(streetNameNoParens)) && (!step.bogusName || !edge.hasBogusName())) || // went on to or off of a roundabout
        edge.isRoundabout() != (roundaboutExit > 0) || isLink(edge) && !isLink(backState.getBackEdge())) {
            // Street name has changed, or we've gone on to or off of a roundabout.
            if (roundaboutExit > 0) {
                // if we were just on a roundabout,
                // make note of which exit was taken in the existing step
                // ordinal numbers from
                step.exit = Integer.toString(roundaboutExit);
                if (streetNameNoParens.equals(roundaboutPreviousStreet)) {
                    step.stayOn = true;
                }
                roundaboutExit = 0;
            }
            /* start a new step */
            step = createWalkStep(graph, forwardState, requestedLocale);
            createdNewStep = true;
            steps.add(step);
            if (edge.isRoundabout()) {
                // indicate that we are now on a roundabout
                // and use one-based exit numbering
                roundaboutExit = 1;
                roundaboutPreviousStreet = backState.getBackEdge().getName(requestedLocale);
                idx = roundaboutPreviousStreet.indexOf('(');
                if (idx > 0)
                    roundaboutPreviousStreet = roundaboutPreviousStreet.substring(0, idx - 1);
            }
            double thisAngle = DirectionUtils.getFirstAngle(geom);
            step.setDirections(lastAngle, thisAngle, edge.isRoundabout());
            // new step, set distance to length of first edge
            distance = edge.getDistanceMeters();
        } else {
            /* street name has not changed */
            double thisAngle = DirectionUtils.getFirstAngle(geom);
            RelativeDirection direction = WalkStep.getRelativeDirection(lastAngle, thisAngle, edge.isRoundabout());
            boolean optionsBefore = backState.multipleOptionsBefore();
            if (edge.isRoundabout()) {
                // we are on a roundabout, and have already traversed at least one edge of it.
                if (optionsBefore) {
                    // increment exit count if we passed one.
                    roundaboutExit += 1;
                }
            }
            if (edge.isRoundabout() || direction == RelativeDirection.CONTINUE) {
            // we are continuing almost straight, or continuing along a roundabout.
            // just append elevation info onto the existing step.
            } else {
                // we are not on a roundabout, and not continuing straight through.
                // figure out if there were other plausible turn options at the last
                // intersection
                // to see if we should generate a "left to continue" instruction.
                boolean shouldGenerateContinue = false;
                if (edge instanceof StreetEdge) {
                    // the next edges will be PlainStreetEdges, we hope
                    double angleDiff = getAbsoluteAngleDiff(thisAngle, lastAngle);
                    for (Edge alternative : backState.getVertex().getOutgoingStreetEdges()) {
                        if (alternative.getName(requestedLocale).equals(streetName)) {
                            // are usually caused by street splits
                            continue;
                        }
                        double altAngle = DirectionUtils.getFirstAngle(alternative.getGeometry());
                        double altAngleDiff = getAbsoluteAngleDiff(altAngle, lastAngle);
                        if (angleDiff > Math.PI / 4 || altAngleDiff - angleDiff < Math.PI / 16) {
                            shouldGenerateContinue = true;
                            break;
                        }
                    }
                } else {
                    double angleDiff = getAbsoluteAngleDiff(lastAngle, thisAngle);
                    // FIXME: this code might be wrong with the removal of the edge-based graph
                    State twoStatesBack = backState.getBackState();
                    Vertex backVertex = twoStatesBack.getVertex();
                    for (Edge alternative : backVertex.getOutgoingStreetEdges()) {
                        List<Edge> alternatives = alternative.getToVertex().getOutgoingStreetEdges();
                        if (alternatives.size() == 0) {
                            // this is not an alternative
                            continue;
                        }
                        alternative = alternatives.get(0);
                        if (alternative.getName(requestedLocale).equals(streetName)) {
                            // are usually caused by street splits
                            continue;
                        }
                        double altAngle = DirectionUtils.getFirstAngle(alternative.getGeometry());
                        double altAngleDiff = getAbsoluteAngleDiff(altAngle, lastAngle);
                        if (angleDiff > Math.PI / 4 || altAngleDiff - angleDiff < Math.PI / 16) {
                            shouldGenerateContinue = true;
                            break;
                        }
                    }
                }
                if (shouldGenerateContinue) {
                    // turn to stay on same-named street
                    step = createWalkStep(graph, forwardState, requestedLocale);
                    createdNewStep = true;
                    steps.add(step);
                    step.setDirections(lastAngle, thisAngle, false);
                    step.stayOn = true;
                    // new step, set distance to length of first edge
                    distance = edge.getDistanceMeters();
                }
            }
        }
        State exitState = backState;
        Edge exitEdge = exitState.getBackEdge();
        while (exitEdge instanceof FreeEdge) {
            exitState = exitState.getBackState();
            exitEdge = exitState.getBackEdge();
        }
        if (exitState.getVertex() instanceof ExitVertex) {
            step.exit = ((ExitVertex) exitState.getVertex()).getExitName();
        }
        if (createdNewStep && !disableZagRemovalForThisStep && forwardState.getBackMode() == backState.getBackMode()) {
            // check last three steps for zag
            int last = steps.size() - 1;
            if (last >= 2) {
                WalkStep threeBack = steps.get(last - 2);
                WalkStep twoBack = steps.get(last - 1);
                WalkStep lastStep = steps.get(last);
                if (twoBack.distance < MAX_ZAG_DISTANCE && lastStep.streetNameNoParens().equals(threeBack.streetNameNoParens())) {
                    if (((lastStep.relativeDirection == RelativeDirection.RIGHT || lastStep.relativeDirection == RelativeDirection.HARD_RIGHT) && (twoBack.relativeDirection == RelativeDirection.RIGHT || twoBack.relativeDirection == RelativeDirection.HARD_RIGHT)) || ((lastStep.relativeDirection == RelativeDirection.LEFT || lastStep.relativeDirection == RelativeDirection.HARD_LEFT) && (twoBack.relativeDirection == RelativeDirection.LEFT || twoBack.relativeDirection == RelativeDirection.HARD_LEFT))) {
                        // in this case, we have two left turns or two right turns in quick
                        // succession; this is probably a U-turn.
                        steps.remove(last - 1);
                        lastStep.distance += twoBack.distance;
                        // A U-turn to the left, typical in the US.
                        if (lastStep.relativeDirection == RelativeDirection.LEFT || lastStep.relativeDirection == RelativeDirection.HARD_LEFT)
                            lastStep.relativeDirection = RelativeDirection.UTURN_LEFT;
                        else
                            lastStep.relativeDirection = RelativeDirection.UTURN_RIGHT;
                        // in this case, we're definitely staying on the same street
                        // (since it's zag removal, the street names are the same)
                        lastStep.stayOn = true;
                    } else {
                        // What is a zag? TODO write meaningful documentation for this.
                        // It appears to mean simplifying out several rapid turns in succession
                        // from the description.
                        // total hack to remove zags.
                        steps.remove(last);
                        steps.remove(last - 1);
                        step = threeBack;
                        step.distance += twoBack.distance;
                        distance += step.distance;
                        if (twoBack.elevation != null) {
                            if (step.elevation == null) {
                                step.elevation = twoBack.elevation;
                            } else {
                                for (P2<Double> d : twoBack.elevation) {
                                    step.elevation.add(new P2<Double>(d.first + step.distance, d.second));
                                }
                            }
                        }
                    }
                }
            }
        } else {
            if (!createdNewStep && step.elevation != null) {
                List<P2<Double>> s = encodeElevationProfile(edge, distance, backState.getOptions().geoidElevation ? -graph.ellipsoidToGeoidDifference : 0);
                if (step.elevation != null && step.elevation.size() > 0) {
                    step.elevation.addAll(s);
                } else {
                    step.elevation = s;
                }
            }
            distance += edge.getDistanceMeters();
        }
        // increment the total length for this step
        step.distance += edge.getDistanceMeters();
        step.addStreetNotes(graph.streetNotesService.getNotes(forwardState));
        lastAngle = DirectionUtils.getLastAngle(geom);
        step.edges.add(edge);
    }
    // add bike rental information if applicable
    if (onBikeRentalState != null && !steps.isEmpty()) {
        steps.get(steps.size() - 1).bikeRentalOnStation = new BikeRentalStationInfo((BikeRentalStationVertex) onBikeRentalState.getBackEdge().getToVertex());
    }
    if (offBikeRentalState != null && !steps.isEmpty()) {
        steps.get(0).bikeRentalOffStation = new BikeRentalStationInfo((BikeRentalStationVertex) offBikeRentalState.getBackEdge().getFromVertex());
    }
    return steps;
}
Also used : TransitStopVertex(org.opentripplanner.routing.vertextype.TransitStopVertex) BikeRentalStationVertex(org.opentripplanner.routing.vertextype.BikeRentalStationVertex) StreetVertex(org.opentripplanner.routing.vertextype.StreetVertex) ExitVertex(org.opentripplanner.routing.vertextype.ExitVertex) Vertex(org.opentripplanner.routing.graph.Vertex) BikeParkVertex(org.opentripplanner.routing.vertextype.BikeParkVertex) ArrayList(java.util.ArrayList) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) LineString(org.locationtech.jts.geom.LineString) FreeEdge(org.opentripplanner.routing.edgetype.FreeEdge) WalkStep(org.opentripplanner.model.plan.WalkStep) ElevatorAlightEdge(org.opentripplanner.routing.edgetype.ElevatorAlightEdge) ExitVertex(org.opentripplanner.routing.vertextype.ExitVertex) BikeRentalStationVertex(org.opentripplanner.routing.vertextype.BikeRentalStationVertex) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) P2(org.opentripplanner.common.model.P2) BikeRentalStationInfo(org.opentripplanner.model.BikeRentalStationInfo) RentABikeOffEdge(org.opentripplanner.routing.edgetype.RentABikeOffEdge) Geometry(org.locationtech.jts.geom.Geometry) RentABikeOnEdge(org.opentripplanner.routing.edgetype.RentABikeOnEdge) RelativeDirection(org.opentripplanner.model.plan.RelativeDirection) State(org.opentripplanner.routing.core.State) PathwayEdge(org.opentripplanner.routing.edgetype.PathwayEdge) ElevatorAlightEdge(org.opentripplanner.routing.edgetype.ElevatorAlightEdge) FreeEdge(org.opentripplanner.routing.edgetype.FreeEdge) RentABikeOnEdge(org.opentripplanner.routing.edgetype.RentABikeOnEdge) AreaEdge(org.opentripplanner.routing.edgetype.AreaEdge) RentABikeOffEdge(org.opentripplanner.routing.edgetype.RentABikeOffEdge) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) Edge(org.opentripplanner.routing.graph.Edge)

Example 3 with WalkStep

use of org.opentripplanner.model.plan.WalkStep in project OpenTripPlanner by opentripplanner.

the class GraphPathToItineraryMapper method createWalkStep.

private static WalkStep createWalkStep(Graph graph, State s, Locale wantedLocale) {
    Edge en = s.getBackEdge();
    WalkStep step;
    step = new WalkStep();
    step.streetName = en.getName(wantedLocale);
    step.startLocation = new WgsCoordinate(en.getFromVertex().getLat(), en.getFromVertex().getLon());
    step.elevation = encodeElevationProfile(s.getBackEdge(), 0, s.getOptions().geoidElevation ? -graph.ellipsoidToGeoidDifference : 0);
    step.bogusName = en.hasBogusName();
    step.addStreetNotes(graph.streetNotesService.getNotes(s));
    step.angle = DirectionUtils.getFirstAngle(s.getBackEdge().getGeometry());
    if (s.getBackEdge() instanceof AreaEdge) {
        step.area = true;
    }
    return step;
}
Also used : WgsCoordinate(org.opentripplanner.model.WgsCoordinate) WalkStep(org.opentripplanner.model.plan.WalkStep) PathwayEdge(org.opentripplanner.routing.edgetype.PathwayEdge) ElevatorAlightEdge(org.opentripplanner.routing.edgetype.ElevatorAlightEdge) FreeEdge(org.opentripplanner.routing.edgetype.FreeEdge) RentABikeOnEdge(org.opentripplanner.routing.edgetype.RentABikeOnEdge) AreaEdge(org.opentripplanner.routing.edgetype.AreaEdge) RentABikeOffEdge(org.opentripplanner.routing.edgetype.RentABikeOffEdge) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) Edge(org.opentripplanner.routing.graph.Edge) AreaEdge(org.opentripplanner.routing.edgetype.AreaEdge)

Example 4 with WalkStep

use of org.opentripplanner.model.plan.WalkStep in project OpenTripPlanner by opentripplanner.

the class GraphPathToItineraryMapper method addWalkSteps.

/**
 * Add a {@link WalkStep} {@link List} to a {@link Leg} {@link List}.
 * It's more convenient to process all legs in one go because the previous step should be kept.
 *
 * @param legs The legs of the itinerary
 * @param legsStates The states that go with the legs
 */
private static void addWalkSteps(Graph graph, List<Leg> legs, State[][] legsStates, Locale requestedLocale) {
    WalkStep previousStep = null;
    TraverseMode lastMode = null;
    for (int i = 0; i < legsStates.length; i++) {
        List<WalkStep> walkSteps = generateWalkSteps(graph, legsStates[i], previousStep, requestedLocale);
        TraverseMode legMode = legs.get(i).mode;
        if (legMode != lastMode && !walkSteps.isEmpty()) {
            lastMode = legMode;
        }
        legs.get(i).walkSteps = walkSteps;
        if (walkSteps.size() > 0) {
            previousStep = walkSteps.get(walkSteps.size() - 1);
        } else {
            previousStep = null;
        }
    }
}
Also used : TraverseMode(org.opentripplanner.routing.core.TraverseMode) WalkStep(org.opentripplanner.model.plan.WalkStep)

Aggregations

WalkStep (org.opentripplanner.model.plan.WalkStep)4 ArrayList (java.util.ArrayList)2 List (java.util.List)2 AreaEdge (org.opentripplanner.routing.edgetype.AreaEdge)2 ElevatorAlightEdge (org.opentripplanner.routing.edgetype.ElevatorAlightEdge)2 FreeEdge (org.opentripplanner.routing.edgetype.FreeEdge)2 PathwayEdge (org.opentripplanner.routing.edgetype.PathwayEdge)2 RentABikeOffEdge (org.opentripplanner.routing.edgetype.RentABikeOffEdge)2 RentABikeOnEdge (org.opentripplanner.routing.edgetype.RentABikeOnEdge)2 StreetEdge (org.opentripplanner.routing.edgetype.StreetEdge)2 Edge (org.opentripplanner.routing.graph.Edge)2 Scalars (graphql.Scalars)1 DefaultConnection (graphql.relay.DefaultConnection)1 DefaultPageInfo (graphql.relay.DefaultPageInfo)1 Relay (graphql.relay.Relay)1 SimpleListConnection (graphql.relay.SimpleListConnection)1 GraphQLArgument (graphql.schema.GraphQLArgument)1 GraphQLEnumType (graphql.schema.GraphQLEnumType)1 GraphQLFieldDefinition (graphql.schema.GraphQLFieldDefinition)1 GraphQLInputObjectField (graphql.schema.GraphQLInputObjectField)1