Search in sources :

Example 1 with DefaultEdgeFilter

use of com.graphhopper.routing.util.DefaultEdgeFilter in project graphhopper by graphhopper.

the class QueryGraph method createEdgeExplorer.

@Override
public EdgeExplorer createEdgeExplorer(final EdgeFilter edgeFilter) {
    if (!isInitialized())
        throw new IllegalStateException("Call lookup before using this graph");
    if (useEdgeExplorerCache) {
        int counter = -1;
        if (edgeFilter instanceof DefaultEdgeFilter) {
            DefaultEdgeFilter dee = (DefaultEdgeFilter) edgeFilter;
            counter = 0;
            if (dee.acceptsBackward())
                counter = 1;
            if (dee.acceptsForward())
                counter += 2;
            if (counter == 0)
                throw new IllegalStateException("You tried to use an edge filter blocking every access");
        } else if (edgeFilter == EdgeFilter.ALL_EDGES) {
            counter = 4;
        }
        if (counter >= 0) {
            EdgeExplorer cached = cacheMap.get(counter);
            if (cached == null) {
                cached = createUncachedEdgeExplorer(edgeFilter);
                cacheMap.put(counter, cached);
            }
            return cached;
        }
    }
    return createUncachedEdgeExplorer(edgeFilter);
}
Also used : GHPoint(com.graphhopper.util.shapes.GHPoint) DefaultEdgeFilter(com.graphhopper.routing.util.DefaultEdgeFilter)

Example 2 with DefaultEdgeFilter

use of com.graphhopper.routing.util.DefaultEdgeFilter in project graphhopper by graphhopper.

the class PrepareRoutingSubnetworks method removeDeadEndUnvisitedNetworks.

/**
     * This method removes networks that will be never be visited by this filter. See #235 for
     * example, small areas like parking lots are sometimes connected to the whole network through a
     * one-way road. This is clearly an error - but is causes the routing to fail when a point gets
     * connected to this small area. This routine removes all these networks from the graph.
     * <p>
     *
     * @return number of removed edges
     */
int removeDeadEndUnvisitedNetworks(final PrepEdgeFilter bothFilter) {
    StopWatch sw = new StopWatch(bothFilter.getEncoder() + " findComponents").start();
    final EdgeFilter outFilter = new DefaultEdgeFilter(bothFilter.getEncoder(), false, true);
    // partition graph into strongly connected components using Tarjan's algorithm        
    TarjansSCCAlgorithm tarjan = new TarjansSCCAlgorithm(ghStorage, outFilter, true);
    List<IntArrayList> components = tarjan.findComponents();
    logger.info(sw.stop() + ", size:" + components.size());
    return removeEdges(bothFilter, components, minOneWayNetworkSize);
}
Also used : EdgeFilter(com.graphhopper.routing.util.EdgeFilter) DefaultEdgeFilter(com.graphhopper.routing.util.DefaultEdgeFilter) GHIntArrayList(com.graphhopper.coll.GHIntArrayList) IntArrayList(com.carrotsearch.hppc.IntArrayList) DefaultEdgeFilter(com.graphhopper.routing.util.DefaultEdgeFilter)

Example 3 with DefaultEdgeFilter

use of com.graphhopper.routing.util.DefaultEdgeFilter in project graphhopper by graphhopper.

the class ChangeGraphHelper method applyChange.

private long applyChange(JsonFeature jsonFeature, FlagEncoder encoder) {
    long updates = 0;
    EdgeFilter filter = new DefaultEdgeFilter(encoder);
    GHIntHashSet edges = new GHIntHashSet();
    if (jsonFeature.hasGeometry()) {
        graphBrowser.fillEdgeIDs(edges, jsonFeature.getGeometry(), filter);
    } else if (jsonFeature.getBBox() != null) {
        graphBrowser.findEdgesInShape(edges, jsonFeature.getBBox(), filter);
    } else
        throw new IllegalArgumentException("Feature " + jsonFeature.getId() + " has no geometry and no bbox");
    Iterator<IntCursor> iter = edges.iterator();
    Map<String, Object> props = jsonFeature.getProperties();
    while (iter.hasNext()) {
        int edgeId = iter.next().value;
        EdgeIteratorState edge = graph.getEdgeIteratorState(edgeId, Integer.MIN_VALUE);
        if (props.containsKey("access")) {
            boolean value = (boolean) props.get("access");
            updates++;
            if (enableLogging)
                logger.info(encoder.toString() + " - access change via feature " + jsonFeature.getId());
            edge.setFlags(encoder.setAccess(edge.getFlags(), value, value));
        } else if (props.containsKey("speed")) {
            // TODO use different speed for the different directions (see e.g. Bike2WeightFlagEncoder)
            double value = ((Number) props.get("speed")).doubleValue();
            double oldSpeed = encoder.getSpeed(edge.getFlags());
            if (oldSpeed != value) {
                updates++;
                if (enableLogging)
                    logger.info(encoder.toString() + " - speed change via feature " + jsonFeature.getId() + ". Old: " + oldSpeed + ", new:" + value);
                edge.setFlags(encoder.setSpeed(edge.getFlags(), value));
            }
        }
    }
    return updates;
}
Also used : GHIntHashSet(com.graphhopper.coll.GHIntHashSet) DefaultEdgeFilter(com.graphhopper.routing.util.DefaultEdgeFilter) EdgeIteratorState(com.graphhopper.util.EdgeIteratorState) EdgeFilter(com.graphhopper.routing.util.EdgeFilter) DefaultEdgeFilter(com.graphhopper.routing.util.DefaultEdgeFilter) IntCursor(com.carrotsearch.hppc.cursors.IntCursor)

Example 4 with DefaultEdgeFilter

use of com.graphhopper.routing.util.DefaultEdgeFilter in project graphhopper by graphhopper.

the class RoundTripRoutingTemplate method lookup.

@Override
public List<QueryResult> lookup(List<GHPoint> points, FlagEncoder encoder) {
    if (points.isEmpty())
        throw new IllegalStateException("For round trip calculation one point is required");
    final double distanceInMeter = ghRequest.getHints().getDouble(RoundTrip.DISTANCE, 10000);
    final long seed = ghRequest.getHints().getLong(RoundTrip.SEED, 0L);
    final double initialHeading = ghRequest.getHints().getDouble(RoundTrip.HEADING, Double.NaN);
    final int roundTripPointCount = Math.min(20, ghRequest.getHints().getInt(Algorithms.ROUND_TRIP + ".points", 2 + (int) (distanceInMeter / 50000)));
    final GHPoint start = ghRequest.getPoints().get(0);
    TourStrategy strategy = new MultiPointTour(new Random(seed), distanceInMeter, roundTripPointCount, initialHeading);
    queryResults = new ArrayList<>(2 + strategy.getNumberOfGeneratedPoints());
    EdgeFilter edgeFilter = new DefaultEdgeFilter(encoder);
    QueryResult startQR = locationIndex.findClosest(start.lat, start.lon, edgeFilter);
    if (!startQR.isValid())
        throw new PointNotFoundException("Cannot find point 0: " + start, 0);
    queryResults.add(startQR);
    GHPoint last = points.get(0);
    for (int i = 0; i < strategy.getNumberOfGeneratedPoints(); i++) {
        double heading = strategy.getHeadingForIteration(i);
        QueryResult result = generateValidPoint(last, strategy.getDistanceForIteration(i), heading, edgeFilter);
        if (result == null) {
            ghResponse.addError(new IllegalStateException("Could not find a valid point after " + maxRetries + " tries, for the point:" + last));
            return Collections.emptyList();
        }
        last = result.getSnappedPoint();
        queryResults.add(result);
    }
    queryResults.add(startQR);
    return queryResults;
}
Also used : PointNotFoundException(com.graphhopper.util.exceptions.PointNotFoundException) TourStrategy(com.graphhopper.routing.util.tour.TourStrategy) GHPoint(com.graphhopper.util.shapes.GHPoint) DefaultEdgeFilter(com.graphhopper.routing.util.DefaultEdgeFilter) QueryResult(com.graphhopper.storage.index.QueryResult) MultiPointTour(com.graphhopper.routing.util.tour.MultiPointTour) Random(java.util.Random) EdgeFilter(com.graphhopper.routing.util.EdgeFilter) DefaultEdgeFilter(com.graphhopper.routing.util.DefaultEdgeFilter) GHPoint(com.graphhopper.util.shapes.GHPoint)

Example 5 with DefaultEdgeFilter

use of com.graphhopper.routing.util.DefaultEdgeFilter in project graphhopper by graphhopper.

the class Path method calcInstructions.

/**
     * @return the list of instructions for this path.
     */
public InstructionList calcInstructions(final Translation tr) {
    final InstructionList ways = new InstructionList(edgeIds.size() / 4, tr);
    if (edgeIds.isEmpty()) {
        if (isFound()) {
            ways.add(new FinishInstruction(nodeAccess, endNode));
        }
        return ways;
    }
    final int tmpNode = getFromNode();
    forEveryEdge(new EdgeVisitor() {

        /*
             * We need three points to make directions
             *
             *        (1)----(2)
             *        /
             *       /
             *    (0)
             *
             * 0 is the node visited at t-2, 1 is the node visited
             * at t-1 and 2 is the node being visited at instant t.
             * orientation is the angle of the vector(1->2) expressed
             * as atan2, while previousOrientation is the angle of the
             * vector(0->1)
             * Intuitively, if orientation is smaller than
             * previousOrientation, then we have to turn right, while
             * if it is greater we have to turn left. To make this
             * algorithm work, we need to make the comparison by
             * considering orientation belonging to the interval
             * [ - pi + previousOrientation , + pi + previousOrientation ]
             */
        private double prevLat = nodeAccess.getLatitude(tmpNode);

        private double prevLon = nodeAccess.getLongitude(tmpNode);

        // Lat and Lon of node t-2
        private double doublePrevLat, doublePrevLong;

        private int prevNode = -1;

        private double prevOrientation;

        private Instruction prevInstruction;

        private boolean prevInRoundabout = false;

        private String name, prevName = null;

        private InstructionAnnotation annotation, prevAnnotation;

        private EdgeExplorer outEdgeExplorer = graph.createEdgeExplorer(new DefaultEdgeFilter(encoder, false, true));

        @Override
        public void next(EdgeIteratorState edge, int index) {
            // baseNode is the current node and adjNode is the next
            int adjNode = edge.getAdjNode();
            int baseNode = edge.getBaseNode();
            long flags = edge.getFlags();
            double adjLat = nodeAccess.getLatitude(adjNode);
            double adjLon = nodeAccess.getLongitude(adjNode);
            double latitude, longitude;
            PointList wayGeo = edge.fetchWayGeometry(3);
            boolean isRoundabout = encoder.isBool(flags, FlagEncoder.K_ROUNDABOUT);
            if (wayGeo.getSize() <= 2) {
                latitude = adjLat;
                longitude = adjLon;
            } else {
                latitude = wayGeo.getLatitude(1);
                longitude = wayGeo.getLongitude(1);
                assert Double.compare(prevLat, nodeAccess.getLatitude(baseNode)) == 0;
                assert Double.compare(prevLon, nodeAccess.getLongitude(baseNode)) == 0;
            }
            name = edge.getName();
            annotation = encoder.getAnnotation(flags, tr);
            if (// very first instruction (if not in Roundabout)
            (prevName == null) && (!isRoundabout)) {
                int sign = Instruction.CONTINUE_ON_STREET;
                prevInstruction = new Instruction(sign, name, annotation, new PointList(10, nodeAccess.is3D()));
                ways.add(prevInstruction);
                prevName = name;
                prevAnnotation = annotation;
            } else if (isRoundabout) {
                // remark: names and annotations within roundabout are ignored
                if (//just entered roundabout
                !prevInRoundabout) {
                    int sign = Instruction.USE_ROUNDABOUT;
                    RoundaboutInstruction roundaboutInstruction = new RoundaboutInstruction(sign, name, annotation, new PointList(10, nodeAccess.is3D()));
                    if (prevName != null) {
                        // check if there is an exit at the same node the roundabout was entered
                        EdgeIterator edgeIter = outEdgeExplorer.setBaseNode(baseNode);
                        while (edgeIter.next()) {
                            if ((edgeIter.getAdjNode() != prevNode) && !encoder.isBool(edgeIter.getFlags(), FlagEncoder.K_ROUNDABOUT)) {
                                roundaboutInstruction.increaseExitNumber();
                                break;
                            }
                        }
                        // previous orientation is last orientation before entering roundabout
                        prevOrientation = AC.calcOrientation(doublePrevLat, doublePrevLong, prevLat, prevLon);
                        // calculate direction of entrance turn to determine direction of rotation
                        // right turn == counterclockwise and vice versa
                        double orientation = AC.calcOrientation(prevLat, prevLon, latitude, longitude);
                        orientation = AC.alignOrientation(prevOrientation, orientation);
                        double delta = (orientation - prevOrientation);
                        roundaboutInstruction.setDirOfRotation(delta);
                    } else // first instructions is roundabout instruction
                    {
                        prevOrientation = AC.calcOrientation(prevLat, prevLon, latitude, longitude);
                        prevName = name;
                        prevAnnotation = annotation;
                    }
                    prevInstruction = roundaboutInstruction;
                    ways.add(prevInstruction);
                }
                // Add passed exits to instruction. A node is counted if there is at least one outgoing edge
                // out of the roundabout
                EdgeIterator edgeIter = outEdgeExplorer.setBaseNode(adjNode);
                while (edgeIter.next()) {
                    if (!encoder.isBool(edgeIter.getFlags(), FlagEncoder.K_ROUNDABOUT)) {
                        ((RoundaboutInstruction) prevInstruction).increaseExitNumber();
                        break;
                    }
                }
            } else if (//previously in roundabout but not anymore
            prevInRoundabout) {
                prevInstruction.setName(name);
                // calc angle between roundabout entrance and exit
                double orientation = AC.calcOrientation(prevLat, prevLon, latitude, longitude);
                orientation = AC.alignOrientation(prevOrientation, orientation);
                double deltaInOut = (orientation - prevOrientation);
                // calculate direction of exit turn to determine direction of rotation
                // right turn == counterclockwise and vice versa
                double recentOrientation = AC.calcOrientation(doublePrevLat, doublePrevLong, prevLat, prevLon);
                orientation = AC.alignOrientation(recentOrientation, orientation);
                double deltaOut = (orientation - recentOrientation);
                prevInstruction = ((RoundaboutInstruction) prevInstruction).setRadian(deltaInOut).setDirOfRotation(deltaOut).setExited();
                prevName = name;
                prevAnnotation = annotation;
            } else if ((!name.equals(prevName)) || (!annotation.equals(prevAnnotation))) {
                prevOrientation = AC.calcOrientation(doublePrevLat, doublePrevLong, prevLat, prevLon);
                double orientation = AC.calcOrientation(prevLat, prevLon, latitude, longitude);
                orientation = AC.alignOrientation(prevOrientation, orientation);
                double delta = orientation - prevOrientation;
                double absDelta = Math.abs(delta);
                int sign;
                if (absDelta < 0.2) {
                    // 0.2 ~= 11°
                    sign = Instruction.CONTINUE_ON_STREET;
                } else if (absDelta < 0.8) {
                    // 0.8 ~= 40°
                    if (delta > 0)
                        sign = Instruction.TURN_SLIGHT_LEFT;
                    else
                        sign = Instruction.TURN_SLIGHT_RIGHT;
                } else if (absDelta < 1.8) {
                    // 1.8 ~= 103°
                    if (delta > 0)
                        sign = Instruction.TURN_LEFT;
                    else
                        sign = Instruction.TURN_RIGHT;
                } else if (delta > 0)
                    sign = Instruction.TURN_SHARP_LEFT;
                else
                    sign = Instruction.TURN_SHARP_RIGHT;
                prevInstruction = new Instruction(sign, name, annotation, new PointList(10, nodeAccess.is3D()));
                ways.add(prevInstruction);
                prevName = name;
                prevAnnotation = annotation;
            }
            updatePointsAndInstruction(edge, wayGeo);
            if (wayGeo.getSize() <= 2) {
                doublePrevLat = prevLat;
                doublePrevLong = prevLon;
            } else {
                int beforeLast = wayGeo.getSize() - 2;
                doublePrevLat = wayGeo.getLatitude(beforeLast);
                doublePrevLong = wayGeo.getLongitude(beforeLast);
            }
            prevInRoundabout = isRoundabout;
            prevNode = baseNode;
            prevLat = adjLat;
            prevLon = adjLon;
            boolean lastEdge = index == edgeIds.size() - 1;
            if (lastEdge) {
                if (isRoundabout) {
                    // calc angle between roundabout entrance and finish
                    double orientation = AC.calcOrientation(doublePrevLat, doublePrevLong, prevLat, prevLon);
                    orientation = AC.alignOrientation(prevOrientation, orientation);
                    double delta = (orientation - prevOrientation);
                    ((RoundaboutInstruction) prevInstruction).setRadian(delta);
                }
                ways.add(new FinishInstruction(nodeAccess, adjNode));
            }
        }

        private void updatePointsAndInstruction(EdgeIteratorState edge, PointList pl) {
            // skip adjNode
            int len = pl.size() - 1;
            for (int i = 0; i < len; i++) {
                prevInstruction.getPoints().add(pl, i);
            }
            double newDist = edge.getDistance();
            prevInstruction.setDistance(newDist + prevInstruction.getDistance());
            prevInstruction.setTime(weighting.calcMillis(edge, false, EdgeIterator.NO_EDGE) + prevInstruction.getTime());
        }
    });
    return ways;
}
Also used : DefaultEdgeFilter(com.graphhopper.routing.util.DefaultEdgeFilter)

Aggregations

DefaultEdgeFilter (com.graphhopper.routing.util.DefaultEdgeFilter)10 Test (org.junit.Test)5 EdgeFilter (com.graphhopper.routing.util.EdgeFilter)4 EncodingManager (com.graphhopper.routing.util.EncodingManager)4 FlagEncoder (com.graphhopper.routing.util.FlagEncoder)3 Graph (com.graphhopper.storage.Graph)3 GraphBuilder (com.graphhopper.storage.GraphBuilder)3 GHIntHashSet (com.graphhopper.coll.GHIntHashSet)2 CarFlagEncoder (com.graphhopper.routing.util.CarFlagEncoder)2 FastestWeighting (com.graphhopper.routing.weighting.FastestWeighting)2 GHPoint (com.graphhopper.util.shapes.GHPoint)2 IntArrayList (com.carrotsearch.hppc.IntArrayList)1 IntCursor (com.carrotsearch.hppc.cursors.IntCursor)1 GHIntArrayList (com.graphhopper.coll.GHIntArrayList)1 HintsMap (com.graphhopper.routing.util.HintsMap)1 MultiPointTour (com.graphhopper.routing.util.tour.MultiPointTour)1 TourStrategy (com.graphhopper.routing.util.tour.TourStrategy)1 CHGraph (com.graphhopper.storage.CHGraph)1 GraphHopperStorage (com.graphhopper.storage.GraphHopperStorage)1 SPTEntry (com.graphhopper.storage.SPTEntry)1