Search in sources :

Example 41 with Vertex

use of org.opentripplanner.routing.graph.Vertex in project OpenTripPlanner by opentripplanner.

the class SimpleIsochrone method makePointFeatures.

private SimpleFeatureCollection makePointFeatures() throws Exception {
    Map<Vertex, Double> points = makePoints();
    /* Stage the point features in memory */
    DefaultFeatureCollection featureCollection = new DefaultFeatureCollection(null, pointSchema);
    SimpleFeatureBuilder fbuilder = new SimpleFeatureBuilder(pointSchema);
    GeometryFactory gf = new GeometryFactory();
    for (Map.Entry<Vertex, Double> entry : points.entrySet()) {
        Vertex vertex = entry.getKey();
        Double travelTime = entry.getValue();
        fbuilder.add(gf.createPoint(vertex.getCoordinate()));
        fbuilder.add(travelTime);
        featureCollection.add(fbuilder.buildFeature(null));
    }
    return featureCollection;
}
Also used : StreetVertex(org.opentripplanner.routing.vertextype.StreetVertex) Vertex(org.opentripplanner.routing.graph.Vertex) IntersectionVertex(org.opentripplanner.routing.vertextype.IntersectionVertex) GeometryFactory(com.vividsolutions.jts.geom.GeometryFactory) Map(java.util.Map) HashMap(java.util.HashMap) DefaultFeatureCollection(org.geotools.feature.DefaultFeatureCollection) SimpleFeatureBuilder(org.geotools.feature.simple.SimpleFeatureBuilder)

Example 42 with Vertex

use of org.opentripplanner.routing.graph.Vertex in project OpenTripPlanner by opentripplanner.

the class SimpleIsochrone method makePoints.

/**
 * @return a map from each vertex to minimum travel time over the course of the day.
 */
private Map<Vertex, Double> makePoints() throws Exception {
    rangeCheckParameters();
    request = buildRequest();
    Router router = otpServer.getRouter(routerId);
    Graph graph = router.graph;
    // double speed = request.getWalkSpeed();
    Coordinate originCoord = request.from.getCoordinate();
    if (originCoord == null)
        return null;
    List<TransitStop> stops = graph.streetIndex.getNearbyTransitStops(originCoord, radiusMeters);
    if (stops.isEmpty()) {
        LOG.error("No stops found within {} meters.", radiusMeters);
        return null;
    }
    if (shpName == null)
        shpName = stops.get(0).getName().split(" ")[0];
    StreetVertex origin = new IntersectionVertex(graph, "iso_temp", originCoord.x, originCoord.y);
    for (TransitStop stop : stops) {
        new StreetTransitLink(origin, stop, false);
        LOG.debug("linked to stop {}", stop.getName());
    }
    request.setRoutingContext(graph, origin, null);
    /* Make one request every M minutes over H hours */
    int nRequests = (requestTimespanHours * 60) / requestSpacingMinutes;
    request.clampInitialWait = (requestSpacingMinutes * 60);
    Date date = request.getDateTime();
    MinMap<Vertex, Double> points = new MinMap<Vertex, Double>();
    for (int r = 0; r < nRequests; r++) {
        request.dateTime = date.getTime() / 1000 + r * requestSpacingMinutes * 60;
        LOG.debug("date: {} {}", new Date(request.dateTime), request.dateTime);
        ShortestPathTree spt = sptService.getShortestPathTree(request, 10);
        /* This could even be a good use for a generic SPT merging function */
        for (State s : spt.getAllStates()) {
            if (stopsOnly && !(s.getVertex() instanceof TransitStop))
                continue;
            points.putMin(s.getVertex(), (double) (s.getActiveTime()));
        }
    }
    graph.removeVertexAndEdges(origin);
    return points;
}
Also used : StreetVertex(org.opentripplanner.routing.vertextype.StreetVertex) Vertex(org.opentripplanner.routing.graph.Vertex) IntersectionVertex(org.opentripplanner.routing.vertextype.IntersectionVertex) TransitStop(org.opentripplanner.routing.vertextype.TransitStop) Router(org.opentripplanner.standalone.Router) StreetTransitLink(org.opentripplanner.routing.edgetype.StreetTransitLink) Point(com.vividsolutions.jts.geom.Point) Date(java.util.Date) Graph(org.opentripplanner.routing.graph.Graph) ShortestPathTree(org.opentripplanner.routing.spt.ShortestPathTree) Coordinate(com.vividsolutions.jts.geom.Coordinate) State(org.opentripplanner.routing.core.State) IntersectionVertex(org.opentripplanner.routing.vertextype.IntersectionVertex) StreetVertex(org.opentripplanner.routing.vertextype.StreetVertex)

Example 43 with Vertex

use of org.opentripplanner.routing.graph.Vertex in project OpenTripPlanner by opentripplanner.

the class MidblockMatchState method getNextStates.

@Override
public List<MatchState> getNextStates() {
    ArrayList<MatchState> nextStates = new ArrayList<MatchState>();
    if (routeIndex.getSegmentIndex() == routeGeometry.getNumPoints() - 1) {
        // this has either hit the end, or gone off the end. It's not real clear which.
        // for now, let's assume it means that the ending is somewhere along this edge,
        // so we return an end state
        Coordinate pt = routeIndex.getCoordinate(routeGeometry);
        double error = distance(pt, edgeIndex.getCoordinate(edgeGeometry));
        nextStates.add(new EndMatchState(this, error, 0));
        return nextStates;
    }
    LinearIterator it = new LinearIterator(routeGeometry, routeIndex);
    if (it.hasNext()) {
        it.next();
        LinearLocation routeSuccessor = it.getLocation();
        // now we want to see where this new point is in terms of the edge's geometry
        Coordinate newRouteCoord = routeSuccessor.getCoordinate(routeGeometry);
        LinearLocation newEdgeIndex = indexedEdge.project(newRouteCoord);
        Coordinate edgeCoord = newEdgeIndex.getCoordinate(edgeGeometry);
        if (newEdgeIndex.compareTo(edgeIndex) <= 0) {
            /* this should not require the try/catch, but there is a bug in JTS */
            try {
                LinearLocation projected2 = indexedEdge.indexOfAfter(edgeCoord, edgeIndex);
                // another bug in JTS
                if (Double.isNaN(projected2.getSegmentFraction())) {
                    // we are probably moving backwards
                    return Collections.emptyList();
                } else {
                    newEdgeIndex = projected2;
                    if (newEdgeIndex.equals(edgeIndex)) {
                        return Collections.emptyList();
                    }
                }
                edgeCoord = newEdgeIndex.getCoordinate(edgeGeometry);
            } catch (AssertionFailedException e) {
                // we are not making progress, so just return an empty list
                return Collections.emptyList();
            }
        }
        if (newEdgeIndex.getSegmentIndex() == edgeGeometry.getNumPoints() - 1) {
            // we might choose to continue from the end of the edge and a point mid-way
            // along this route segment
            // find nearest point that makes progress along the route
            Vertex toVertex = edge.getToVertex();
            Coordinate endCoord = toVertex.getCoordinate();
            LocationIndexedLine indexedRoute = new LocationIndexedLine(routeGeometry);
            // FIXME: it would be better to do this project/indexOfAfter in one step
            // as the two-step version could snap to a bad place and be unable to escape.
            LinearLocation routeProjectedEndIndex = indexedRoute.project(endCoord);
            Coordinate routeProjectedEndCoord = routeProjectedEndIndex.getCoordinate(routeGeometry);
            if (routeProjectedEndIndex.compareTo(routeIndex) <= 0) {
                try {
                    routeProjectedEndIndex = indexedRoute.indexOfAfter(routeProjectedEndCoord, routeIndex);
                    if (Double.isNaN(routeProjectedEndIndex.getSegmentFraction())) {
                        // can't go forward
                        // this is bad, but not terrible
                        routeProjectedEndIndex = routeIndex;
                    // since we are advancing along the edge
                    }
                } catch (AssertionFailedException e) {
                    routeProjectedEndIndex = routeIndex;
                }
                routeProjectedEndCoord = routeProjectedEndIndex.getCoordinate(routeGeometry);
            }
            double positionError = distance(routeProjectedEndCoord, endCoord);
            double travelAlongRoute = distanceAlongGeometry(routeGeometry, routeIndex, routeProjectedEndIndex);
            double travelAlongEdge = distanceAlongGeometry(edgeGeometry, edgeIndex, newEdgeIndex);
            double travelError = Math.abs(travelAlongEdge - travelAlongRoute);
            double error = positionError + travelError;
            if (error > MAX_ERROR) {
                // totally wrong
                return nextStates;
            }
            for (Edge e : getOutgoingMatchableEdges(toVertex)) {
                double cost = error + NEW_SEGMENT_PENALTY;
                if (!carsCanTraverse(e)) {
                    cost += NO_TRAVERSE_PENALTY;
                }
                MatchState nextState = new MidblockMatchState(this, routeGeometry, e, routeProjectedEndIndex, new LinearLocation(), cost, travelAlongRoute);
                nextStates.add(nextState);
            }
        } else {
            double travelAlongEdge = distanceAlongGeometry(edgeGeometry, edgeIndex, newEdgeIndex);
            double travelAlongRoute = distanceAlongGeometry(routeGeometry, routeIndex, routeSuccessor);
            double travelError = Math.abs(travelAlongRoute - travelAlongEdge);
            double positionError = distance(edgeCoord, newRouteCoord);
            double error = travelError + positionError;
            MatchState nextState = new MidblockMatchState(this, routeGeometry, edge, routeSuccessor, newEdgeIndex, error, travelAlongRoute);
            nextStates.add(nextState);
            // it's also possible that, although we have not yet reached the end of this edge,
            // we are going to turn, because the route turns earlier than the edge. In that
            // case, we jump to the corner, and our error is the distance from the route point
            // and the corner
            Vertex toVertex = edge.getToVertex();
            double travelAlongOldEdge = distanceAlongGeometry(edgeGeometry, edgeIndex, null);
            for (Edge e : getOutgoingMatchableEdges(toVertex)) {
                Geometry newEdgeGeometry = e.getGeometry();
                LocationIndexedLine newIndexedEdge = new LocationIndexedLine(newEdgeGeometry);
                newEdgeIndex = newIndexedEdge.project(newRouteCoord);
                Coordinate newEdgeCoord = newEdgeIndex.getCoordinate(newEdgeGeometry);
                positionError = distance(newEdgeCoord, newRouteCoord);
                travelAlongEdge = travelAlongOldEdge + distanceAlongGeometry(newEdgeGeometry, new LinearLocation(), newEdgeIndex);
                travelError = Math.abs(travelAlongRoute - travelAlongEdge);
                error = travelError + positionError;
                if (error > MAX_ERROR) {
                    // totally wrong
                    return nextStates;
                }
                double cost = error + NEW_SEGMENT_PENALTY;
                if (!carsCanTraverse(e)) {
                    cost += NO_TRAVERSE_PENALTY;
                }
                nextState = new MidblockMatchState(this, routeGeometry, e, routeSuccessor, new LinearLocation(), cost, travelAlongRoute);
                nextStates.add(nextState);
            }
        }
        return nextStates;
    } else {
        Coordinate routeCoord = routeIndex.getCoordinate(routeGeometry);
        LinearLocation projected = indexedEdge.project(routeCoord);
        double locationError = distance(projected.getCoordinate(edgeGeometry), routeCoord);
        MatchState end = new EndMatchState(this, locationError, 0);
        return Arrays.asList(end);
    }
}
Also used : Vertex(org.opentripplanner.routing.graph.Vertex) LinearLocation(com.vividsolutions.jts.linearref.LinearLocation) LocationIndexedLine(com.vividsolutions.jts.linearref.LocationIndexedLine) ArrayList(java.util.ArrayList) Geometry(com.vividsolutions.jts.geom.Geometry) Coordinate(com.vividsolutions.jts.geom.Coordinate) AssertionFailedException(com.vividsolutions.jts.util.AssertionFailedException) Edge(org.opentripplanner.routing.graph.Edge)

Example 44 with Vertex

use of org.opentripplanner.routing.graph.Vertex in project OpenTripPlanner by opentripplanner.

the class GraphPathToTripPlanConverter method generatePlan.

/**
 * Generates a TripPlan from a set of paths
 */
public static TripPlan generatePlan(List<GraphPath> paths, RoutingRequest request) {
    Locale requestedLocale = request.locale;
    GraphPath exemplar = paths.get(0);
    Vertex tripStartVertex = exemplar.getStartVertex();
    Vertex tripEndVertex = exemplar.getEndVertex();
    String startName = tripStartVertex.getName(requestedLocale);
    String endName = tripEndVertex.getName(requestedLocale);
    // 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);
    from.orig = request.from.name;
    to.orig = request.to.name;
    TripPlan plan = new TripPlan(from, to, request.getDateTime());
    // Convert GraphPaths to Itineraries, keeping track of the best non-transit (e.g. walk/bike-only) option time
    long bestNonTransitTime = Long.MAX_VALUE;
    List<Itinerary> itineraries = new LinkedList<>();
    for (GraphPath path : paths) {
        Itinerary itinerary = generateItinerary(path, request.showIntermediateStops, request.disableAlertFiltering, requestedLocale);
        itinerary = adjustItinerary(request, itinerary);
        if (itinerary.transitTime == 0 && itinerary.walkTime < bestNonTransitTime) {
            bestNonTransitTime = itinerary.walkTime;
        }
        itineraries.add(itinerary);
    }
    // Filter and add itineraries to plan
    for (Itinerary itinerary : itineraries) {
        // do not include in plan
        if (itinerary.transitTime > 0 && itinerary.walkTime > bestNonTransitTime)
            continue;
        plan.addItinerary(itinerary);
    }
    if (plan != null) {
        for (Itinerary i : plan.itinerary) {
            /* Communicate the fact that the only way we were able to get a response was by removing a slope limit. */
            i.tooSloped = request.rctx.slopeRestrictionRemoved;
            /* fix up from/to on first/last legs */
            if (i.legs.size() == 0) {
                LOG.warn("itinerary has no legs");
                continue;
            }
            Leg firstLeg = i.legs.get(0);
            firstLeg.from.orig = plan.from.orig;
            Leg lastLeg = i.legs.get(i.legs.size() - 1);
            lastLeg.to.orig = plan.to.orig;
        }
    }
    request.rctx.debugOutput.finishedRendering();
    return plan;
}
Also used : Vertex(org.opentripplanner.routing.graph.Vertex) GraphPath(org.opentripplanner.routing.spt.GraphPath) LineString(com.vividsolutions.jts.geom.LineString)

Example 45 with Vertex

use of org.opentripplanner.routing.graph.Vertex in project OpenTripPlanner by opentripplanner.

the class GraphPathToTripPlanConverter 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
 *
 * @return
 */
public static List<WalkStep> generateWalkSteps(Graph graph, State[] states, WalkStep previous, Locale requestedLocale) {
    List<WalkStep> steps = new ArrayList<WalkStep>();
    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;
    // Check if this leg is a SimpleTransfer; if so, rebuild state array based on stored transfer edges
    if (states.length == 2 && states[1].getBackEdge() instanceof SimpleTransfer) {
        SimpleTransfer transferEdge = ((SimpleTransfer) states[1].getBackEdge());
        List<Edge> transferEdges = transferEdge.getEdges();
        if (transferEdges != null) {
            // Create a new initial state. Some parameters may have change along the way, copy them from the first state
            StateEditor se = new StateEditor(states[0].getOptions(), transferEdges.get(0).getFromVertex());
            se.setNonTransitOptionsFromState(states[0]);
            State s = se.makeState();
            ArrayList<State> transferStates = new ArrayList<>();
            transferStates.add(s);
            for (Edge e : transferEdges) {
                s = e.traverse(s);
                transferStates.add(s);
            }
            states = transferStates.toArray(new State[transferStates.size()]);
        }
    }
    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.getDistance();
        } 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.getDistance();
        } 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.getDistance();
                }
            }
        }
        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.getDistance();
        }
        // increment the total length for this step
        step.distance += edge.getDistance();
        step.addAlerts(graph.streetNotesService.getNotes(forwardState), requestedLocale);
        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 : Vertex(org.opentripplanner.routing.graph.Vertex) LineString(com.vividsolutions.jts.geom.LineString) P2(org.opentripplanner.common.model.P2) BikeRentalStationInfo(org.opentripplanner.profile.BikeRentalStationInfo) Geometry(com.vividsolutions.jts.geom.Geometry) Edge(org.opentripplanner.routing.graph.Edge)

Aggregations

Vertex (org.opentripplanner.routing.graph.Vertex)143 Edge (org.opentripplanner.routing.graph.Edge)63 IntersectionVertex (org.opentripplanner.routing.vertextype.IntersectionVertex)45 GraphPath (org.opentripplanner.routing.spt.GraphPath)39 RoutingRequest (org.opentripplanner.routing.core.RoutingRequest)35 ShortestPathTree (org.opentripplanner.routing.spt.ShortestPathTree)34 StreetEdge (org.opentripplanner.routing.edgetype.StreetEdge)32 Graph (org.opentripplanner.routing.graph.Graph)29 TransitStop (org.opentripplanner.routing.vertextype.TransitStop)28 Coordinate (com.vividsolutions.jts.geom.Coordinate)24 StreetVertex (org.opentripplanner.routing.vertextype.StreetVertex)24 AgencyAndId (org.onebusaway.gtfs.model.AgencyAndId)20 State (org.opentripplanner.routing.core.State)20 Stop (org.onebusaway.gtfs.model.Stop)18 LineString (com.vividsolutions.jts.geom.LineString)16 ArrayList (java.util.ArrayList)16 HashSet (java.util.HashSet)13 Test (org.junit.Test)13 Trip (org.onebusaway.gtfs.model.Trip)12 Envelope (com.vividsolutions.jts.geom.Envelope)11