Search in sources :

Example 1 with TraverseModeSet

use of org.opentripplanner.routing.core.TraverseModeSet in project OpenTripPlanner by opentripplanner.

the class SIsochrone method getIsochrone.

/**
 * Calculates walksheds for a given location, based on time given to walk and the walk speed.
 *
 * Depending on the value for the "output" parameter (i.e. "POINTS", "SHED" or "EDGES"), a
 * different type of GeoJSON geometry is returned. If a SHED is requested, then a ConcaveHull
 * of the EDGES/roads is returned. If that fails, a ConvexHull will be returned.
 * <p>
 * The ConcaveHull parameter is set to 0.005 degrees. The offroad walkspeed is assumed to be
 * 0.83333 m/sec (= 3km/h) until a road is hit.
 * <p>
 * Note that the set of EDGES/roads returned as well as POINTS returned may contain duplicates.
 * If POINTS are requested, then not the end-points are returned at which the max time is
 * reached, but instead all the graph nodes/crossings that are within the time limits.
 * <p>
 * In case there is no road near by within the given time, then a circle for the walktime limit
 * is created and returned for the SHED parameter. Otherwise the edge with the direction
 * towards the closest road. Note that the circle is calculated in Euclidian 2D coordinates,
 * and distortions towards an ellipse will appear if it is transformed/projected to the user location.
 * <p>
 * An example request may look like this:
 * localhost:8080/otp-rest-servlet/ws/iso?layers=traveltime&styles=mask&batch=true&fromPlace=51.040193121307176
 * %2C-114.04471635818481&toPlace
 * =51.09098935%2C-113.95179705&time=2012-06-06T08%3A00%3A00&mode=WALK&maxWalkDistance=10000&walkSpeed=1.38&walkTime=10.7&output=EDGES
 * Though the first parameters (i) layer, (ii) styles and (iii) batch could be discarded.
 *
 * @param walkmins Maximum number of minutes to walk.
 * @param output Can be set to "POINTS", "SHED" or "EDGES" to return different types of GeoJSON
 *        geometry. SHED returns a ConcaveHull or ConvexHull of the edges/roads. POINTS returns
 *        all graph nodes that are within the time limit.
 * @return a JSON document containing geometries (either points, lineStrings or a polygon).
 * @throws Exception
 * @author sstein---geo.uzh.ch
 */
@GET
@Produces({ MediaType.APPLICATION_JSON })
public String getIsochrone(@QueryParam("walkTime") @DefaultValue("15") double walkmins, @QueryParam("output") @DefaultValue("POINTS") String output) throws Exception {
    this.debugGeoms = new ArrayList();
    this.tooFastTraversedEdgeGeoms = new ArrayList();
    RoutingRequest sptRequestA = buildRequest();
    String from = sptRequestA.from.toString();
    int pos = 1;
    float lat = 0;
    float lon = 0;
    for (String s : from.split(",")) {
        if (s.isEmpty()) {
            // no location
            Response.status(Status.BAD_REQUEST).entity("no position").build();
            return null;
        }
        try {
            float num = Float.parseFloat(s);
            if (pos == 1) {
                lat = num;
            }
            if (pos == 2) {
                lon = num;
            }
        } catch (Exception e) {
            throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("Could not parse position string to number. Require numerical lat & long coords.").build());
        }
        pos++;
    }
    GeometryFactory gf = new GeometryFactory();
    Coordinate dropPoint = new Coordinate(lon, lat);
    int walkInMin = (int) Math.floor(walkmins);
    double walkInSec = walkmins * 60;
    LOG.debug("given travel time: " + walkInMin + " mins + " + (walkInSec - (60 * walkInMin)) + " sec");
    // graph dynamically by 1.3 * min -> this should save processing time
    if (walkInMin < 30) {
        sptRequestA.worstTime = sptRequestA.dateTime + (30 * 60);
    } else {
        sptRequestA.worstTime = sptRequestA.dateTime + Math.round(walkInMin * 1.3 * 60);
    }
    // set the switch-time for shed/area calculation, i.e. to decide if the hull is calculated based on points or on edges
    TraverseModeSet modes = sptRequestA.modes;
    LOG.debug("mode(s): " + modes);
    if (modes.contains(TraverseMode.TRANSIT)) {
        // 20min (use 20min for transit, since buses may not come all the time)
        shedCalcMethodSwitchTimeInSec = 60 * 20;
    } else if (modes.contains(TraverseMode.CAR)) {
        // 10min
        shedCalcMethodSwitchTimeInSec = 60 * 10;
    } else if (modes.contains(TraverseMode.BICYCLE)) {
        // 10min
        shedCalcMethodSwitchTimeInSec = 60 * 10;
    } else {
        // 20min
        shedCalcMethodSwitchTimeInSec = 60 * 20;
    }
    // set the maxUserSpeed, which is used later to check for u-type streets/crescents when calculating sub-edges;
    // Note, that the car speed depends on the edge itself, so this value may be replaced later
    this.usesCar = false;
    int numberOfModes = modes.getModes().size();
    if (numberOfModes == 1) {
        if (modes.getWalk()) {
            this.maxUserSpeed = sptRequestA.walkSpeed;
        } else if (modes.getBicycle()) {
            this.maxUserSpeed = sptRequestA.bikeSpeed;
        } else if (modes.getCar()) {
            this.maxUserSpeed = sptRequestA.carSpeed;
            this.usesCar = true;
        }
    } else {
        // for all other cases (multiple-modes)
        // sstein: I thought I may set it to 36.111 m/sec = 130 km/h,
        // but maybe it is better to assume walk speed for transit, i.e. treat it like if the
        // person gets off the bus on the last crossing and walks the "last mile".
        this.maxUserSpeed = sptRequestA.walkSpeed;
    }
    if (doSpeedTest) {
        LOG.debug("performing angle and speed based test to detect u-shapes");
    } else {
        LOG.debug("performing only angle based test to detect u-shapes");
    }
    // TODO: OTP prefers to snap to car-roads/ways, which is not so nice, when walking,
    // and a footpath is closer by. So far there is no option to switch that off
    Router router = otpServer.getRouter(routerId);
    // create the ShortestPathTree
    try {
        sptRequestA.setRoutingContext(router.graph);
    } catch (Exception e) {
        // if we get an exception here, and in particular a VertexNotFoundException,
        // then it is likely that we chose a (transit) mode without having that (transit) modes data
        LOG.debug("cannot set RoutingContext: " + e.toString());
        LOG.debug("cannot set RoutingContext: setting mode=WALK");
        // fall back to walk mode
        sptRequestA.setMode(TraverseMode.WALK);
        sptRequestA.setRoutingContext(router.graph);
    }
    ShortestPathTree sptA = new AStar().getShortestPathTree(sptRequestA);
    StreetLocation origin = (StreetLocation) sptRequestA.rctx.fromVertex;
    // remove inserted points
    sptRequestA.cleanup();
    // create a LineString for display
    Coordinate[] pathToStreetCoords = new Coordinate[2];
    pathToStreetCoords[0] = dropPoint;
    pathToStreetCoords[1] = origin.getCoordinate();
    LineString pathToStreet = gf.createLineString(pathToStreetCoords);
    // get distance between origin and drop point for time correction
    double distanceToRoad = SphericalDistanceLibrary.distance(origin.getY(), origin.getX(), dropPoint.y, dropPoint.x);
    long offRoadTimeCorrection = (long) (distanceToRoad / this.offRoadWalkspeed);
    // 
    // --- filter the states ---
    // 
    Set<Coordinate> visitedCoords = new HashSet<Coordinate>();
    ArrayList<Edge> allConnectingEdges = new ArrayList<Edge>();
    Coordinate[] coords = null;
    long maxTime = (long) walkInSec - offRoadTimeCorrection;
    // if the initial walk is already to long, there is no need to parse...
    if (maxTime <= 0) {
        noRoadNearBy = true;
        long timeToWalk = (long) walkInSec;
        long timeBetweenStates = offRoadTimeCorrection;
        long timeMissing = timeToWalk;
        double fraction = (double) timeMissing / (double) timeBetweenStates;
        pathToStreet = getSubLineString(pathToStreet, fraction);
        LOG.debug("no street found within giving travel time (for off-road walkspeed: {} m/sec)", this.offRoadWalkspeed);
    } else {
        noRoadNearBy = false;
        Map<ReversibleLineStringWrapper, Edge> connectingEdgesMap = Maps.newHashMap();
        for (State state : sptA.getAllStates()) {
            long et = state.getElapsedTimeSeconds();
            if (et <= maxTime) {
                // 250 points away (while 145 were finally displayed)
                if (visitedCoords.contains(state.getVertex().getCoordinate())) {
                    continue;
                } else {
                    visitedCoords.add(state.getVertex().getCoordinate());
                }
                // -- get all Edges needed later for the edge representation
                // and to calculate an edge-based walkshed
                // Note, it can happen that we get a null geometry here, e.g. for hop-edges!
                Collection<Edge> vertexEdgesIn = state.getVertex().getIncoming();
                for (Iterator<Edge> iterator = vertexEdgesIn.iterator(); iterator.hasNext(); ) {
                    Edge edge = (Edge) iterator.next();
                    Geometry edgeGeom = edge.getGeometry();
                    if (edgeGeom != null) {
                        // make sure we get only real edges
                        if (edgeGeom instanceof LineString) {
                            // allConnectingEdges.add(edge); // instead of this, use a map now, so we don't have similar edge many times
                            connectingEdgesMap.put(new ReversibleLineStringWrapper((LineString) edgeGeom), edge);
                        }
                    }
                }
                Collection<Edge> vertexEdgesOut = state.getVertex().getOutgoing();
                for (Iterator<Edge> iterator = vertexEdgesOut.iterator(); iterator.hasNext(); ) {
                    Edge edge = (Edge) iterator.next();
                    Geometry edgeGeom = edge.getGeometry();
                    if (edgeGeom != null) {
                        if (edgeGeom instanceof LineString) {
                            // allConnectingEdges.add(edge); // instead of this, use a map now, so we don't similar edge many times
                            connectingEdgesMap.put(new ReversibleLineStringWrapper((LineString) edgeGeom), edge);
                        }
                    }
                }
            }
        // end : if(et < maxTime)
        }
        // --
        // points from list to array, for later
        coords = new Coordinate[visitedCoords.size()];
        int i = 0;
        for (Coordinate c : visitedCoords) coords[i++] = c;
        // connection edges from Map to List
        allConnectingEdges.clear();
        for (Edge tedge : connectingEdgesMap.values()) allConnectingEdges.add(tedge);
    }
    StringWriter sw = new StringWriter();
    GeometryJSON geometryJSON = new GeometryJSON();
    // 
    try {
        if (output.equals(SIsochrone.RESULT_TYPE_POINTS)) {
            // and return those points
            if (noRoadNearBy) {
                Geometry circleShape = createCirle(dropPoint, pathToStreet);
                coords = circleShape.getCoordinates();
            }
            // -- the states/nodes with time elapsed <= X min.
            LOG.debug("write multipoint geom with {} points", coords.length);
            geometryJSON.write(gf.createMultiPoint(coords), sw);
            LOG.debug("done");
        } else if (output.equals(SIsochrone.RESULT_TYPE_SHED)) {
            Geometry[] geomsArray = null;
            // in case there was no road we create a circle
            if (noRoadNearBy) {
                Geometry circleShape = createCirle(dropPoint, pathToStreet);
                geometryJSON.write(circleShape, sw);
            } else {
                if (maxTime > shedCalcMethodSwitchTimeInSec) {
                    // eg., walkshed > 20 min
                    // -- create a point-based walkshed
                    // less exact and should be used for large walksheds with many edges
                    LOG.debug("create point-based shed (not from edges)");
                    geomsArray = new Geometry[coords.length];
                    for (int j = 0; j < geomsArray.length; j++) {
                        geomsArray[j] = gf.createPoint(coords[j]);
                    }
                } else {
                    // -- create an edge-based walkshed
                    // it is more exact and should be used for short walks
                    LOG.debug("create edge-based shed (not from points)");
                    Map<ReversibleLineStringWrapper, LineString> walkShedEdges = Maps.newHashMap();
                    // add the walk from the pushpin to closest street point
                    walkShedEdges.put(new ReversibleLineStringWrapper(pathToStreet), pathToStreet);
                    // get the edges and edge parts within time limits
                    ArrayList<LineString> withinTimeEdges = this.getLinesAndSubEdgesWithinMaxTime(maxTime, allConnectingEdges, sptA, angleLimitForUShapeDetection, distanceToleranceForUShapeDetection, maxUserSpeed, usesCar, doSpeedTest);
                    for (LineString ls : withinTimeEdges) {
                        walkShedEdges.put(new ReversibleLineStringWrapper(ls), ls);
                    }
                    geomsArray = new Geometry[walkShedEdges.size()];
                    int k = 0;
                    for (LineString ls : walkShedEdges.values()) geomsArray[k++] = ls;
                }
                // end if-else: maxTime condition
                GeometryCollection gc = gf.createGeometryCollection(geomsArray);
                // create the concave hull, but in case it fails we just return the convex hull
                Geometry outputHull = null;
                LOG.debug("create concave hull from {} geoms with edge length limit of about {} m (distance on meridian)", geomsArray.length, concaveHullAlpha * 111132);
                // (see wikipedia: http://en.wikipedia.org/wiki/Latitude#The_length_of_a_degree_of_latitude)
                try {
                    ConcaveHull hull = new ConcaveHull(gc, concaveHullAlpha);
                    outputHull = hull.getConcaveHull();
                } catch (Exception e) {
                    outputHull = gc.convexHull();
                    LOG.debug("Could not generate ConcaveHull for WalkShed, using ConvexHull instead.");
                }
                LOG.debug("write shed geom");
                geometryJSON.write(outputHull, sw);
                LOG.debug("done");
            }
        } else if (output.equals(SIsochrone.RESULT_TYPE_EDGES)) {
            // in case there was no road we return only the suggested path to the street
            if (noRoadNearBy) {
                geometryJSON.write(pathToStreet, sw);
            } else {
                // -- if we would use only the edges from the paths to the origin we will miss
                // some edges that will be never on the shortest path (e.g. loops/crescents).
                // However, we can retrieve all edges by checking the times for each
                // edge end-point
                Map<ReversibleLineStringWrapper, LineString> walkShedEdges = Maps.newHashMap();
                // add the walk from the pushpin to closest street point
                walkShedEdges.put(new ReversibleLineStringWrapper(pathToStreet), pathToStreet);
                // get the edges and edge parts within time limits
                ArrayList<LineString> withinTimeEdges = this.getLinesAndSubEdgesWithinMaxTime(maxTime, allConnectingEdges, sptA, angleLimitForUShapeDetection, distanceToleranceForUShapeDetection, maxUserSpeed, usesCar, doSpeedTest);
                for (LineString ls : withinTimeEdges) {
                    walkShedEdges.put(new ReversibleLineStringWrapper(ls), ls);
                }
                Geometry mls = null;
                LineString[] edges = new LineString[walkShedEdges.size()];
                int k = 0;
                for (LineString ls : walkShedEdges.values()) edges[k++] = ls;
                LOG.debug("create multilinestring from {} geoms", edges.length);
                mls = gf.createMultiLineString(edges);
                LOG.debug("write geom");
                geometryJSON.write(mls, sw);
                LOG.debug("done");
            }
        } else if (output.equals("DEBUGEDGES")) {
            // -- for debugging, i.e. display of detected u-shapes/crescents
            ArrayList<LineString> withinTimeEdges = this.getLinesAndSubEdgesWithinMaxTime(maxTime, allConnectingEdges, sptA, angleLimitForUShapeDetection, distanceToleranceForUShapeDetection, maxUserSpeed, usesCar, doSpeedTest);
            if (this.showTooFastEdgesAsDebugGeomsANDnotUShapes) {
                LOG.debug("displaying edges that are traversed too fast");
                this.debugGeoms = this.tooFastTraversedEdgeGeoms;
            } else {
                LOG.debug("displaying detected u-shaped roads/crescents");
            }
            LineString[] edges = new LineString[this.debugGeoms.size()];
            int k = 0;
            for (Iterator iterator = debugGeoms.iterator(); iterator.hasNext(); ) {
                LineString ls = (LineString) iterator.next();
                edges[k] = ls;
                k++;
            }
            Geometry mls = gf.createMultiLineString(edges);
            LOG.debug("write debug geom");
            geometryJSON.write(mls, sw);
            LOG.debug("done");
        }
    } catch (Exception e) {
        LOG.error("Exception creating isochrone", e);
    }
    return sw.toString();
}
Also used : GeometryJSON(org.geotools.geojson.geom.GeometryJSON) AStar(org.opentripplanner.routing.algorithm.AStar) StringWriter(java.io.StringWriter) RoutingRequest(org.opentripplanner.routing.core.RoutingRequest) ConcaveHull(org.opensphere.geometry.algorithm.ConcaveHull) Router(org.opentripplanner.standalone.Router) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet) ShortestPathTree(org.opentripplanner.routing.spt.ShortestPathTree) ReversibleLineStringWrapper(org.opentripplanner.common.geometry.ReversibleLineStringWrapper) State(org.opentripplanner.routing.core.State) StreetLocation(org.opentripplanner.routing.location.StreetLocation) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) Edge(org.opentripplanner.routing.graph.Edge)

Example 2 with TraverseModeSet

use of org.opentripplanner.routing.core.TraverseModeSet in project OpenTripPlanner by opentripplanner.

the class SimpleStreetSplitter method getClosestVertex.

/**
 * Used to link origin and destination points to graph non destructively.
 *
 * Split edges don't replace existing ones and only temporary edges and vertices are created.
 *
 * Will throw ThrivialPathException if origin and destination Location are on the same edge
 *
 * @param location
 * @param options
 * @param endVertex true if this is destination vertex
 * @return
 */
public Vertex getClosestVertex(GenericLocation location, RoutingRequest options, boolean endVertex) {
    if (destructiveSplitting) {
        throw new RuntimeException("Origin and destination search is used with destructive splitting. Something is wrong!");
    }
    if (endVertex) {
        LOG.debug("Finding end vertex for {}", location);
    } else {
        LOG.debug("Finding start vertex for {}", location);
    }
    Coordinate coord = location.getCoordinate();
    // TODO: add nice name
    String name;
    if (location.name == null || location.name.isEmpty()) {
        if (endVertex) {
            name = "Destination";
        } else {
            name = "Origin";
        }
    } else {
        name = location.name;
    }
    TemporaryStreetLocation closest = new TemporaryStreetLocation(UUID.randomUUID().toString(), coord, new NonLocalizedString(name), endVertex);
    TraverseMode nonTransitMode = TraverseMode.WALK;
    // It can be null in tests
    if (options != null) {
        TraverseModeSet modes = options.modes;
        if (modes.getCar())
            // for park and ride we will start in car mode and walk to the end vertex
            if (endVertex && (options.parkAndRide || options.kissAndRide)) {
                nonTransitMode = TraverseMode.WALK;
            } else {
                nonTransitMode = TraverseMode.CAR;
            }
        else if (modes.getWalk())
            nonTransitMode = TraverseMode.WALK;
        else if (modes.getBicycle())
            nonTransitMode = TraverseMode.BICYCLE;
    }
    if (!link(closest, nonTransitMode, options)) {
        LOG.warn("Couldn't link {}", location);
    }
    return closest;
}
Also used : TemporaryStreetLocation(org.opentripplanner.routing.location.TemporaryStreetLocation) Coordinate(com.vividsolutions.jts.geom.Coordinate) NonLocalizedString(org.opentripplanner.util.NonLocalizedString) TraverseMode(org.opentripplanner.routing.core.TraverseMode) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet) LineString(com.vividsolutions.jts.geom.LineString) NonLocalizedString(org.opentripplanner.util.NonLocalizedString)

Example 3 with TraverseModeSet

use of org.opentripplanner.routing.core.TraverseModeSet in project OpenTripPlanner by opentripplanner.

the class SimpleStreetSplitter method link.

/**
 * Link this vertex into the graph
 */
public boolean link(Vertex vertex, TraverseMode traverseMode, RoutingRequest options) {
    // find nearby street edges
    // TODO: we used to use an expanding-envelope search, which is more efficient in
    // dense areas. but first let's see how inefficient this is. I suspect it's not too
    // bad and the gains in simplicity are considerable.
    final double radiusDeg = SphericalDistanceLibrary.metersToDegrees(MAX_SEARCH_RADIUS_METERS);
    Envelope env = new Envelope(vertex.getCoordinate());
    // Perform a simple local equirectangular projection, so distances are expressed in degrees latitude.
    final double xscale = Math.cos(vertex.getLat() * Math.PI / 180);
    // Expand more in the longitude direction than the latitude direction to account for converging meridians.
    env.expandBy(radiusDeg / xscale, radiusDeg);
    final double DUPLICATE_WAY_EPSILON_DEGREES = SphericalDistanceLibrary.metersToDegrees(DUPLICATE_WAY_EPSILON_METERS);
    final TraverseModeSet traverseModeSet;
    if (traverseMode == TraverseMode.BICYCLE) {
        traverseModeSet = new TraverseModeSet(traverseMode, TraverseMode.WALK);
    } else {
        traverseModeSet = new TraverseModeSet(traverseMode);
    }
    // We sort the list of candidate edges by distance to the stop
    // This should remove any issues with things coming out of the spatial index in different orders
    // Then we link to everything that is within DUPLICATE_WAY_EPSILON_METERS of of the best distance
    // so that we capture back edges and duplicate ways.
    List<StreetEdge> candidateEdges = idx.query(env).stream().filter(streetEdge -> streetEdge instanceof StreetEdge).map(edge -> (StreetEdge) edge).filter(edge -> edge.canTraverse(traverseModeSet) && // only link to edges still in the graph.
    edge.getToVertex().getIncoming().contains(edge)).collect(Collectors.toList());
    // Make a map of distances to all edges.
    final TIntDoubleMap distances = new TIntDoubleHashMap();
    for (StreetEdge e : candidateEdges) {
        distances.put(e.getId(), distance(vertex, e, xscale));
    }
    // Sort the list.
    Collections.sort(candidateEdges, (o1, o2) -> {
        double diff = distances.get(o1.getId()) - distances.get(o2.getId());
        // A Comparator must return an integer but our distances are doubles.
        if (diff < 0)
            return -1;
        if (diff > 0)
            return 1;
        return 0;
    });
    // find the closest candidate edges
    if (candidateEdges.isEmpty() || distances.get(candidateEdges.get(0).getId()) > radiusDeg) {
        // We only link to stops if we are searching for origin/destination and for that we need transitStopIndex.
        if (destructiveSplitting || transitStopIndex == null) {
            return false;
        }
        LOG.debug("No street edge was found for {}", vertex);
        // We search for closest stops (since this is only used in origin/destination linking if no edges were found)
        // in the same way the closest edges are found.
        List<TransitStop> candidateStops = new ArrayList<>();
        transitStopIndex.query(env).forEach(candidateStop -> candidateStops.add((TransitStop) candidateStop));
        final TIntDoubleMap stopDistances = new TIntDoubleHashMap();
        for (TransitStop t : candidateStops) {
            stopDistances.put(t.getIndex(), distance(vertex, t, xscale));
        }
        Collections.sort(candidateStops, (o1, o2) -> {
            double diff = stopDistances.get(o1.getIndex()) - stopDistances.get(o2.getIndex());
            if (diff < 0) {
                return -1;
            }
            if (diff > 0) {
                return 1;
            }
            return 0;
        });
        if (candidateStops.isEmpty() || stopDistances.get(candidateStops.get(0).getIndex()) > radiusDeg) {
            LOG.debug("Stops aren't close either!");
            return false;
        } else {
            List<TransitStop> bestStops = Lists.newArrayList();
            // Add stops until there is a break of epsilon meters.
            // we do this to enforce determinism. if there are a lot of stops that are all extremely close to each other,
            // we want to be sure that we deterministically link to the same ones every time. Any hard cutoff means things can
            // fall just inside or beyond the cutoff depending on floating-point operations.
            int i = 0;
            do {
                bestStops.add(candidateStops.get(i++));
            } while (i < candidateStops.size() && stopDistances.get(candidateStops.get(i).getIndex()) - stopDistances.get(candidateStops.get(i - 1).getIndex()) < DUPLICATE_WAY_EPSILON_DEGREES);
            for (TransitStop stop : bestStops) {
                LOG.debug("Linking vertex to stop: {}", stop.getName());
                makeTemporaryEdges((TemporaryStreetLocation) vertex, stop);
            }
            return true;
        }
    } else {
        // find the best edges
        List<StreetEdge> bestEdges = Lists.newArrayList();
        // add edges until there is a break of epsilon meters.
        // we do this to enforce determinism. if there are a lot of edges that are all extremely close to each other,
        // we want to be sure that we deterministically link to the same ones every time. Any hard cutoff means things can
        // fall just inside or beyond the cutoff depending on floating-point operations.
        int i = 0;
        do {
            bestEdges.add(candidateEdges.get(i++));
        } while (i < candidateEdges.size() && distances.get(candidateEdges.get(i).getId()) - distances.get(candidateEdges.get(i - 1).getId()) < DUPLICATE_WAY_EPSILON_DEGREES);
        for (StreetEdge edge : bestEdges) {
            link(vertex, edge, xscale, options);
        }
        // Warn if a linkage was made, but the linkage was suspiciously long.
        if (vertex instanceof TransitStop) {
            double distanceDegreesLatitude = distances.get(candidateEdges.get(0).getId());
            int distanceMeters = (int) SphericalDistanceLibrary.degreesLatitudeToMeters(distanceDegreesLatitude);
            if (distanceMeters > WARNING_DISTANCE_METERS) {
                // Registering an annotation but not logging because tests produce thousands of these warnings.
                graph.addBuilderAnnotation(new StopLinkedTooFar((TransitStop) vertex, distanceMeters));
            }
        }
        return true;
    }
}
Also used : P2(org.opentripplanner.common.model.P2) Iterables(com.google.common.collect.Iterables) TemporarySplitterVertex(org.opentripplanner.routing.vertextype.TemporarySplitterVertex) TemporaryFreeEdge(org.opentripplanner.routing.edgetype.TemporaryFreeEdge) TemporaryVertex(org.opentripplanner.routing.vertextype.TemporaryVertex) LocationIndexedLine(com.vividsolutions.jts.linearref.LocationIndexedLine) LoggerFactory(org.slf4j.LoggerFactory) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) TransitStop(org.opentripplanner.routing.vertextype.TransitStop) SphericalDistanceLibrary(org.opentripplanner.common.geometry.SphericalDistanceLibrary) TemporaryStreetLocation(org.opentripplanner.routing.location.TemporaryStreetLocation) LineString(com.vividsolutions.jts.geom.LineString) NonLocalizedString(org.opentripplanner.util.NonLocalizedString) StopLinkedTooFar(org.opentripplanner.graph_builder.annotation.StopLinkedTooFar) SplitterVertex(org.opentripplanner.routing.vertextype.SplitterVertex) ArrayList(java.util.ArrayList) StopUnlinked(org.opentripplanner.graph_builder.annotation.StopUnlinked) StreetTransitLink(org.opentripplanner.routing.edgetype.StreetTransitLink) Graph(org.opentripplanner.routing.graph.Graph) BikeRentalStationVertex(org.opentripplanner.routing.vertextype.BikeRentalStationVertex) GenericLocation(org.opentripplanner.common.model.GenericLocation) SpatialIndex(com.vividsolutions.jts.index.SpatialIndex) TraverseMode(org.opentripplanner.routing.core.TraverseMode) Lists(jersey.repackaged.com.google.common.collect.Lists) HashGridSpatialIndex(org.opentripplanner.common.geometry.HashGridSpatialIndex) Coordinate(com.vividsolutions.jts.geom.Coordinate) Logger(org.slf4j.Logger) Envelope(com.vividsolutions.jts.geom.Envelope) Vertex(org.opentripplanner.routing.graph.Vertex) StreetBikeRentalLink(org.opentripplanner.routing.edgetype.StreetBikeRentalLink) TIntDoubleHashMap(gnu.trove.map.hash.TIntDoubleHashMap) BikeParkUnlinked(org.opentripplanner.graph_builder.annotation.BikeParkUnlinked) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet) StreetBikeParkLink(org.opentripplanner.routing.edgetype.StreetBikeParkLink) StreetVertex(org.opentripplanner.routing.vertextype.StreetVertex) GeometryUtils(org.opentripplanner.common.geometry.GeometryUtils) List(java.util.List) TIntDoubleMap(gnu.trove.map.TIntDoubleMap) BikeRentalStationUnlinked(org.opentripplanner.graph_builder.annotation.BikeRentalStationUnlinked) GeometryFactory(com.vividsolutions.jts.geom.GeometryFactory) LinearLocation(com.vividsolutions.jts.linearref.LinearLocation) BikeParkVertex(org.opentripplanner.routing.vertextype.BikeParkVertex) RoutingRequest(org.opentripplanner.routing.core.RoutingRequest) Collections(java.util.Collections) Edge(org.opentripplanner.routing.graph.Edge) TransitStop(org.opentripplanner.routing.vertextype.TransitStop) TIntDoubleMap(gnu.trove.map.TIntDoubleMap) ArrayList(java.util.ArrayList) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) StopLinkedTooFar(org.opentripplanner.graph_builder.annotation.StopLinkedTooFar) Envelope(com.vividsolutions.jts.geom.Envelope) TIntDoubleHashMap(gnu.trove.map.hash.TIntDoubleHashMap)

Example 4 with TraverseModeSet

use of org.opentripplanner.routing.core.TraverseModeSet in project OpenTripPlanner by opentripplanner.

the class BarrierVertexTest method testStreetsWithBollard.

@Test
public void testStreetsWithBollard() {
    Graph _graph = new Graph();
    // default permissions are PEDESTRIAND and BICYCLE
    BarrierVertex bv = new BarrierVertex(_graph, "start_bollard", 2.0, 2.0, 0);
    StreetVertex endVertex = new IntersectionVertex(_graph, "end_vertex", 1.0, 2.0);
    StreetEdge bv_to_endVertex_forward = edge(bv, endVertex, 100, false);
    assertTrue(bv_to_endVertex_forward.canTraverse(new TraverseModeSet("CAR")));
    assertTrue(bv_to_endVertex_forward.canTraverse(new TraverseModeSet("BICYCLE")));
    assertTrue(bv_to_endVertex_forward.canTraverse(new TraverseModeSet("WALK")));
    assertFalse(bv_to_endVertex_forward.canTraverseIncludingBarrier(TraverseMode.CAR));
    assertTrue(bv_to_endVertex_forward.canTraverseIncludingBarrier(TraverseMode.BICYCLE));
    assertTrue(bv_to_endVertex_forward.canTraverseIncludingBarrier(TraverseMode.WALK));
    StreetEdge endVertex_to_bv_backward = edge(endVertex, bv, 100, true);
    assertTrue(endVertex_to_bv_backward.canTraverse(new TraverseModeSet("CAR")));
    assertTrue(endVertex_to_bv_backward.canTraverse(new TraverseModeSet("BICYCLE")));
    assertTrue(endVertex_to_bv_backward.canTraverse(new TraverseModeSet("WALK")));
    assertFalse(endVertex_to_bv_backward.canTraverseIncludingBarrier(TraverseMode.CAR));
    assertTrue(endVertex_to_bv_backward.canTraverseIncludingBarrier(TraverseMode.BICYCLE));
    assertTrue(endVertex_to_bv_backward.canTraverseIncludingBarrier(TraverseMode.WALK));
    StreetEdge bv_to_endVertex_backward = edge(bv, endVertex, 100, true);
    assertTrue(bv_to_endVertex_backward.canTraverse(new TraverseModeSet("CAR")));
    assertTrue(bv_to_endVertex_backward.canTraverse(new TraverseModeSet("BICYCLE")));
    assertTrue(bv_to_endVertex_backward.canTraverse(new TraverseModeSet("WALK")));
    assertFalse(bv_to_endVertex_backward.canTraverseIncludingBarrier(TraverseMode.CAR));
    assertTrue(bv_to_endVertex_backward.canTraverseIncludingBarrier(TraverseMode.BICYCLE));
    assertTrue(bv_to_endVertex_backward.canTraverseIncludingBarrier(TraverseMode.WALK));
    StreetEdge endVertex_to_bv_forward = edge(endVertex, bv, 100, false);
    assertTrue(endVertex_to_bv_forward.canTraverse(new TraverseModeSet("CAR")));
    assertTrue(endVertex_to_bv_forward.canTraverse(new TraverseModeSet("BICYCLE")));
    assertTrue(endVertex_to_bv_forward.canTraverse(new TraverseModeSet("WALK")));
    assertFalse(endVertex_to_bv_forward.canTraverseIncludingBarrier(TraverseMode.CAR));
    assertTrue(endVertex_to_bv_forward.canTraverseIncludingBarrier(TraverseMode.BICYCLE));
    assertTrue(endVertex_to_bv_forward.canTraverseIncludingBarrier(TraverseMode.WALK));
    // tests bollard which doesn't allow cycling
    BarrierVertex noBicycleBollard = new BarrierVertex(_graph, "no_bike_bollard", 1.5, 1, 0);
    noBicycleBollard.setBarrierPermissions(StreetTraversalPermission.PEDESTRIAN);
    StreetEdge no_bike_to_endVertex = edge(noBicycleBollard, endVertex, 100, false);
    assertTrue(no_bike_to_endVertex.canTraverse(new TraverseModeSet("CAR")));
    assertTrue(no_bike_to_endVertex.canTraverse(new TraverseModeSet("BICYCLE")));
    assertTrue(no_bike_to_endVertex.canTraverse(new TraverseModeSet("WALK")));
    assertFalse(no_bike_to_endVertex.canTraverseIncludingBarrier(TraverseMode.CAR));
    assertFalse(no_bike_to_endVertex.canTraverseIncludingBarrier(TraverseMode.BICYCLE));
    assertTrue(no_bike_to_endVertex.canTraverseIncludingBarrier(TraverseMode.WALK));
}
Also used : Graph(org.opentripplanner.routing.graph.Graph) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet) Test(org.junit.Test)

Example 5 with TraverseModeSet

use of org.opentripplanner.routing.core.TraverseModeSet in project OpenTripPlanner by opentripplanner.

the class TestPatternHopFactory method testTraverseMode.

public void testTraverseMode() throws Exception {
    Vertex stop_a = graph.getVertex(feedId + ":A_depart");
    Vertex stop_b = graph.getVertex(feedId + ":B_arrive");
    ShortestPathTree spt;
    RoutingRequest options = new RoutingRequest();
    options.setModes(new TraverseModeSet("TRAM,RAIL,SUBWAY,FUNICULAR,GONDOLA"));
    options.dateTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 0, 0, 0, 0);
    options.setRoutingContext(graph, stop_a, stop_b);
    spt = aStar.getShortestPathTree(options);
    // a to b is bus only
    assertNull(spt.getPath(stop_b, false));
    options.setModes(new TraverseModeSet("TRAM,RAIL,SUBWAY,FUNICULAR,GONDOLA,CABLE_CAR,BUS"));
    spt = aStar.getShortestPathTree(options);
    assertNotNull(spt.getPath(stop_b, false));
}
Also used : Vertex(org.opentripplanner.routing.graph.Vertex) IntersectionVertex(org.opentripplanner.routing.vertextype.IntersectionVertex) ShortestPathTree(org.opentripplanner.routing.spt.ShortestPathTree) RoutingRequest(org.opentripplanner.routing.core.RoutingRequest) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet)

Aggregations

TraverseModeSet (org.opentripplanner.routing.core.TraverseModeSet)44 Test (org.junit.Test)25 RoutingRequest (org.opentripplanner.routing.core.RoutingRequest)17 Graph (org.opentripplanner.routing.graph.Graph)14 Edge (org.opentripplanner.routing.graph.Edge)10 Vertex (org.opentripplanner.routing.graph.Vertex)10 Coordinate (com.vividsolutions.jts.geom.Coordinate)8 QualifiedModeSet (org.opentripplanner.api.parameter.QualifiedModeSet)8 GenericLocation (org.opentripplanner.common.model.GenericLocation)8 ShortestPathTree (org.opentripplanner.routing.spt.ShortestPathTree)8 LocalDate (org.joda.time.LocalDate)7 ProfileRequest (org.opentripplanner.profile.ProfileRequest)7 RepeatedRaptorProfileRouter (org.opentripplanner.profile.RepeatedRaptorProfileRouter)7 StreetEdge (org.opentripplanner.routing.edgetype.StreetEdge)6 GraphPath (org.opentripplanner.routing.spt.GraphPath)6 FakeGraph (org.opentripplanner.graph_builder.module.FakeGraph)5 DefaultStreetVertexIndexFactory (org.opentripplanner.routing.impl.DefaultStreetVertexIndexFactory)5 NonLocalizedString (org.opentripplanner.util.NonLocalizedString)5 LineString (com.vividsolutions.jts.geom.LineString)4 ArrayList (java.util.ArrayList)4