Search in sources :

Example 31 with Snap

use of com.graphhopper.storage.index.Snap in project graphhopper by graphhopper.

the class QueryOverlayBuilder method buildVirtualEdges.

/**
 * For all specified snaps calculate the snapped point and if necessary set the closest node
 * to a virtual one and reverse the closest edge. Additionally the wayIndex can change if an edge is
 * swapped.
 */
private void buildVirtualEdges(List<Snap> snaps) {
    GHIntObjectHashMap<List<Snap>> edge2res = new GHIntObjectHashMap<>(snaps.size());
    // calculate snapped point and swap direction of closest edge if necessary
    for (Snap snap : snaps) {
        // Do not create virtual node for a snap if it is directly on a tower node or not found
        if (snap.getSnappedPosition() == Snap.Position.TOWER)
            continue;
        EdgeIteratorState closestEdge = snap.getClosestEdge();
        if (closestEdge == null)
            throw new IllegalStateException("Do not call QueryGraph.create with invalid Snap " + snap);
        int base = closestEdge.getBaseNode();
        // Force the identical direction for all closest edges.
        // It is important to sort multiple results for the same edge by its wayIndex
        boolean doReverse = base > closestEdge.getAdjNode();
        if (base == closestEdge.getAdjNode()) {
            // check for special case #162 where adj == base and force direction via latitude comparison
            PointList pl = closestEdge.fetchWayGeometry(FetchMode.PILLAR_ONLY);
            if (pl.size() > 1)
                doReverse = pl.getLat(0) > pl.getLat(pl.size() - 1);
        }
        if (doReverse) {
            closestEdge = closestEdge.detach(true);
            PointList fullPL = closestEdge.fetchWayGeometry(FetchMode.ALL);
            snap.setClosestEdge(closestEdge);
            if (snap.getSnappedPosition() == Snap.Position.PILLAR)
                // ON pillar node
                snap.setWayIndex(fullPL.size() - snap.getWayIndex() - 1);
            else
                // for case "OFF pillar node"
                snap.setWayIndex(fullPL.size() - snap.getWayIndex() - 2);
            if (snap.getWayIndex() < 0)
                throw new IllegalStateException("Problem with wayIndex while reversing closest edge:" + closestEdge + ", " + snap);
        }
        // find multiple results on same edge
        int edgeId = closestEdge.getEdge();
        List<Snap> list = edge2res.get(edgeId);
        if (list == null) {
            list = new ArrayList<>(5);
            edge2res.put(edgeId, list);
        }
        list.add(snap);
    }
    // Phase 2 - now it is clear which points cut one edge
    // 1. create point lists
    // 2. create virtual edges between virtual nodes and its neighbor (virtual or normal nodes)
    edge2res.forEach(new IntObjectPredicate<List<Snap>>() {

        @Override
        public boolean apply(int edgeId, List<Snap> results) {
            // we can expect at least one entry in the results
            EdgeIteratorState closestEdge = results.get(0).getClosestEdge();
            final PointList fullPL = closestEdge.fetchWayGeometry(FetchMode.ALL);
            int baseNode = closestEdge.getBaseNode();
            Collections.sort(results, new Comparator<Snap>() {

                @Override
                public int compare(Snap o1, Snap o2) {
                    int diff = Integer.compare(o1.getWayIndex(), o2.getWayIndex());
                    if (diff == 0) {
                        return Double.compare(distanceOfSnappedPointToPillarNode(o1), distanceOfSnappedPointToPillarNode(o2));
                    } else {
                        return diff;
                    }
                }

                private double distanceOfSnappedPointToPillarNode(Snap o) {
                    GHPoint snappedPoint = o.getSnappedPoint();
                    double fromLat = fullPL.getLat(o.getWayIndex());
                    double fromLon = fullPL.getLon(o.getWayIndex());
                    return DistancePlaneProjection.DIST_PLANE.calcNormalizedDist(fromLat, fromLon, snappedPoint.lat, snappedPoint.lon);
                }
            });
            GHPoint3D prevPoint = fullPL.get(0);
            int adjNode = closestEdge.getAdjNode();
            int origEdgeKey = closestEdge.getEdgeKey();
            int origRevEdgeKey = GHUtility.reverseEdgeKey(origEdgeKey);
            int prevWayIndex = 1;
            int prevNodeId = baseNode;
            int virtNodeId = queryOverlay.getVirtualNodes().size() + firstVirtualNodeId;
            boolean addedEdges = false;
            // fullPL into the right pieces.
            for (Snap res : results) {
                if (res.getClosestEdge().getBaseNode() != baseNode)
                    throw new IllegalStateException("Base nodes have to be identical but were not: " + closestEdge + " vs " + res.getClosestEdge());
                GHPoint3D currSnapped = res.getSnappedPoint();
                // no new virtual nodes if exactly the same snapped point
                if (prevPoint.equals(currSnapped)) {
                    res.setClosestNode(prevNodeId);
                    continue;
                }
                queryOverlay.getClosestEdges().add(res.getClosestEdge().getEdge());
                boolean isPillar = res.getSnappedPosition() == Snap.Position.PILLAR;
                createEdges(origEdgeKey, origRevEdgeKey, prevPoint, prevWayIndex, isPillar, res.getSnappedPoint(), res.getWayIndex(), fullPL, closestEdge, prevNodeId, virtNodeId);
                queryOverlay.getVirtualNodes().add(currSnapped.lat, currSnapped.lon, currSnapped.ele);
                // add edges again to set adjacent edges for newVirtNodeId
                if (addedEdges) {
                    queryOverlay.addVirtualEdge(queryOverlay.getVirtualEdge(queryOverlay.getNumVirtualEdges() - 2));
                    queryOverlay.addVirtualEdge(queryOverlay.getVirtualEdge(queryOverlay.getNumVirtualEdges() - 2));
                }
                addedEdges = true;
                res.setClosestNode(virtNodeId);
                prevNodeId = virtNodeId;
                prevWayIndex = res.getWayIndex() + 1;
                prevPoint = currSnapped;
                virtNodeId++;
            }
            // two edges between last result and adjacent node are still missing if not all points skipped
            if (addedEdges)
                createEdges(origEdgeKey, origRevEdgeKey, prevPoint, prevWayIndex, false, fullPL.get(fullPL.size() - 1), fullPL.size() - 2, fullPL, closestEdge, virtNodeId - 1, adjNode);
            return true;
        }
    });
}
Also used : GHIntObjectHashMap(com.graphhopper.coll.GHIntObjectHashMap) GHPoint3D(com.graphhopper.util.shapes.GHPoint3D) Snap(com.graphhopper.storage.index.Snap) GHPoint(com.graphhopper.util.shapes.GHPoint) Comparator(java.util.Comparator) List(java.util.List) ArrayList(java.util.ArrayList) GHPoint(com.graphhopper.util.shapes.GHPoint)

Example 32 with Snap

use of com.graphhopper.storage.index.Snap in project graphhopper by graphhopper.

the class PrepareLandmarksTest method testLandmarkStorageAndRouting.

@Test
public void testLandmarkStorageAndRouting() {
    // create graph with lat,lon
    // 0  1  2  ...
    // 15 16 17 ...
    Random rand = new Random(0);
    int width = 15, height = 15;
    DecimalEncodedValue avSpeedEnc = encoder.getAverageSpeedEnc();
    BooleanEncodedValue accessEnc = encoder.getAccessEnc();
    for (int hIndex = 0; hIndex < height; hIndex++) {
        for (int wIndex = 0; wIndex < width; wIndex++) {
            int node = wIndex + hIndex * width;
            // do not connect first with last column!
            double speed = 20 + rand.nextDouble() * 30;
            if (wIndex + 1 < width)
                graph.edge(node, node + 1).set(accessEnc, true, true).set(avSpeedEnc, speed);
            // avoid dead ends
            if (hIndex + 1 < height)
                graph.edge(node, node + width).set(accessEnc, true, true).set(avSpeedEnc, speed);
            updateDistancesFor(graph, node, -hIndex / 50.0, wIndex / 50.0);
        }
    }
    Directory dir = new RAMDirectory();
    LocationIndexTree index = new LocationIndexTree(graph, dir);
    index.prepareIndex();
    int lm = 5, activeLM = 2;
    Weighting weighting = new FastestWeighting(encoder);
    LMConfig lmConfig = new LMConfig("car", weighting);
    LandmarkStorage store = new LandmarkStorage(graph, dir, lmConfig, lm);
    store.setMinimumNodes(2);
    store.createLandmarks();
    // landmarks should be the 4 corners of the grid:
    int[] intList = store.getLandmarks(1);
    Arrays.sort(intList);
    assertEquals("[0, 14, 70, 182, 224]", Arrays.toString(intList));
    // two landmarks: one for subnetwork 0 (all empty) and one for subnetwork 1
    assertEquals(2, store.getSubnetworksWithLandmarks());
    assertEquals(0, store.getFromWeight(0, 224));
    double factor = store.getFactor();
    assertEquals(4671, Math.round(store.getFromWeight(0, 47) * factor));
    assertEquals(3640, Math.round(store.getFromWeight(0, 52) * factor));
    long weight1_224 = store.getFromWeight(1, 224);
    assertEquals(5525, Math.round(weight1_224 * factor));
    long weight1_47 = store.getFromWeight(1, 47);
    assertEquals(921, Math.round(weight1_47 * factor));
    // grid is symmetric
    assertEquals(weight1_224, store.getToWeight(1, 224));
    assertEquals(weight1_47, store.getToWeight(1, 47));
    // prefer the landmarks before and behind the goal
    int[] activeLandmarkIndices = new int[activeLM];
    Arrays.fill(activeLandmarkIndices, -1);
    store.chooseActiveLandmarks(27, 47, activeLandmarkIndices, false);
    List<Integer> list = new ArrayList<>();
    for (int idx : activeLandmarkIndices) {
        list.add(store.getLandmarks(1)[idx]);
    }
    // TODO should better select 0 and 224?
    assertEquals(Arrays.asList(224, 70), list);
    PrepareLandmarks prepare = new PrepareLandmarks(new RAMDirectory(), graph, lmConfig, 4);
    prepare.setMinimumNodes(2);
    prepare.doWork();
    LandmarkStorage lms = prepare.getLandmarkStorage();
    AStar expectedAlgo = new AStar(graph, weighting, tm);
    Path expectedPath = expectedAlgo.calcPath(41, 183);
    PMap hints = new PMap().putObject(Parameters.Landmark.ACTIVE_COUNT, 2);
    // landmarks with A*
    RoutingAlgorithm oneDirAlgoWithLandmarks = new LMRoutingAlgorithmFactory(lms).createAlgo(graph, weighting, new AlgorithmOptions().setAlgorithm(ASTAR).setTraversalMode(tm).setHints(hints));
    Path path = oneDirAlgoWithLandmarks.calcPath(41, 183);
    assertEquals(expectedPath.getWeight(), path.getWeight(), .1);
    assertEquals(expectedPath.calcNodes(), path.calcNodes());
    assertEquals(expectedAlgo.getVisitedNodes() - 135, oneDirAlgoWithLandmarks.getVisitedNodes());
    // landmarks with bidir A*
    RoutingAlgorithm biDirAlgoWithLandmarks = new LMRoutingAlgorithmFactory(lms).createAlgo(graph, weighting, new AlgorithmOptions().setAlgorithm(ASTAR_BI).setTraversalMode(tm).setHints(hints));
    path = biDirAlgoWithLandmarks.calcPath(41, 183);
    assertEquals(expectedPath.getWeight(), path.getWeight(), .1);
    assertEquals(expectedPath.calcNodes(), path.calcNodes());
    assertEquals(expectedAlgo.getVisitedNodes() - 162, biDirAlgoWithLandmarks.getVisitedNodes());
    // landmarks with A* and a QueryGraph. We expect slightly less optimal as two more cycles needs to be traversed
    // due to the two more virtual nodes but this should not harm in practise
    Snap fromSnap = index.findClosest(-0.0401, 0.2201, EdgeFilter.ALL_EDGES);
    Snap toSnap = index.findClosest(-0.2401, 0.0601, EdgeFilter.ALL_EDGES);
    QueryGraph qGraph = QueryGraph.create(graph, fromSnap, toSnap);
    RoutingAlgorithm qGraphOneDirAlgo = new LMRoutingAlgorithmFactory(lms).createAlgo(qGraph, weighting, new AlgorithmOptions().setAlgorithm(ASTAR).setTraversalMode(tm).setHints(hints));
    path = qGraphOneDirAlgo.calcPath(fromSnap.getClosestNode(), toSnap.getClosestNode());
    expectedAlgo = new AStar(qGraph, weighting, tm);
    expectedPath = expectedAlgo.calcPath(fromSnap.getClosestNode(), toSnap.getClosestNode());
    assertEquals(expectedPath.getWeight(), path.getWeight(), .1);
    assertEquals(expectedPath.calcNodes(), path.calcNodes());
    assertEquals(expectedAlgo.getVisitedNodes() - 135, qGraphOneDirAlgo.getVisitedNodes());
}
Also used : RoutingAlgorithm(com.graphhopper.routing.RoutingAlgorithm) ArrayList(java.util.ArrayList) AStar(com.graphhopper.routing.AStar) PMap(com.graphhopper.util.PMap) AlgorithmOptions(com.graphhopper.routing.AlgorithmOptions) Snap(com.graphhopper.storage.index.Snap) Random(java.util.Random) FastestWeighting(com.graphhopper.routing.weighting.FastestWeighting) Directory(com.graphhopper.storage.Directory) RAMDirectory(com.graphhopper.storage.RAMDirectory) Path(com.graphhopper.routing.Path) RAMDirectory(com.graphhopper.storage.RAMDirectory) LocationIndexTree(com.graphhopper.storage.index.LocationIndexTree) BooleanEncodedValue(com.graphhopper.routing.ev.BooleanEncodedValue) FastestWeighting(com.graphhopper.routing.weighting.FastestWeighting) Weighting(com.graphhopper.routing.weighting.Weighting) DecimalEncodedValue(com.graphhopper.routing.ev.DecimalEncodedValue) QueryGraph(com.graphhopper.routing.querygraph.QueryGraph) Test(org.junit.jupiter.api.Test)

Example 33 with Snap

use of com.graphhopper.storage.index.Snap in project graphhopper by graphhopper.

the class BlockAreaWeightingTest method testBlockVirtualEdges_QueryGraph.

@Test
public void testBlockVirtualEdges_QueryGraph() {
    GraphEdgeIdFinder.BlockArea bArea = new GraphEdgeIdFinder.BlockArea(graph);
    // add base graph edge to fill caches and trigger edgeId cache search (without virtual edges)
    GHIntHashSet set = new GHIntHashSet();
    set.add(0);
    bArea.add(new Circle(0.0025, 0.0025, 1), set);
    LocationIndex index = new LocationIndexTree(graph, graph.getDirectory()).prepareIndex();
    Snap snap = index.findClosest(0.005, 0.005, EdgeFilter.ALL_EDGES);
    QueryGraph queryGraph = QueryGraph.create(graph, snap);
    BlockAreaWeighting instance = new BlockAreaWeighting(new FastestWeighting(encoder), bArea);
    EdgeIterator iter = queryGraph.createEdgeExplorer().setBaseNode(snap.getClosestNode());
    int blockedEdges = 0, totalEdges = 0;
    while (iter.next()) {
        if (Double.isInfinite(instance.calcEdgeWeight(iter, false)))
            blockedEdges++;
        totalEdges++;
    }
    assertEquals(1, blockedEdges);
    assertEquals(2, totalEdges);
}
Also used : Circle(com.graphhopper.util.shapes.Circle) GraphEdgeIdFinder(com.graphhopper.storage.GraphEdgeIdFinder) GHIntHashSet(com.graphhopper.coll.GHIntHashSet) LocationIndex(com.graphhopper.storage.index.LocationIndex) Snap(com.graphhopper.storage.index.Snap) LocationIndexTree(com.graphhopper.storage.index.LocationIndexTree) EdgeIterator(com.graphhopper.util.EdgeIterator) QueryGraph(com.graphhopper.routing.querygraph.QueryGraph) Test(org.junit.jupiter.api.Test)

Example 34 with Snap

use of com.graphhopper.storage.index.Snap in project graphhopper by graphhopper.

the class GHUtility method createRandomSnaps.

public static List<Snap> createRandomSnaps(BBox bbox, LocationIndex locationIndex, Random rnd, int numPoints, boolean acceptTower, EdgeFilter filter) {
    int maxTries = numPoints * 100;
    int tries = 0;
    List<Snap> snaps = new ArrayList<>(numPoints);
    while (snaps.size() < numPoints) {
        if (tries > maxTries)
            throw new IllegalArgumentException("Could not create " + numPoints + " random points. tries: " + tries + ", maxTries: " + maxTries);
        Snap snap = getRandomSnap(locationIndex, rnd, bbox, filter);
        boolean accepted = snap.isValid();
        if (!acceptTower)
            accepted = accepted && !snap.getSnappedPosition().equals(Snap.Position.TOWER);
        if (accepted)
            snaps.add(snap);
        tries++;
    }
    return snaps;
}
Also used : IntArrayList(com.carrotsearch.hppc.IntArrayList) Snap(com.graphhopper.storage.index.Snap)

Example 35 with Snap

use of com.graphhopper.storage.index.Snap in project graphhopper by graphhopper.

the class RoundTripRouting method generateValidPoint.

private static Snap generateValidPoint(GHPoint lastPoint, double distanceInMeters, double heading, EdgeFilter edgeFilter, LocationIndex locationIndex, int maxRetries) {
    int tryCount = 0;
    while (true) {
        GHPoint generatedPoint = DistanceCalcEarth.DIST_EARTH.projectCoordinate(lastPoint.getLat(), lastPoint.getLon(), distanceInMeters, heading);
        Snap snap = locationIndex.findClosest(generatedPoint.getLat(), generatedPoint.getLon(), edgeFilter);
        if (snap.isValid())
            return snap;
        tryCount++;
        distanceInMeters *= 0.95;
        if (tryCount >= maxRetries)
            throw new IllegalArgumentException("Could not find a valid point after " + maxRetries + " tries, for the point:" + lastPoint);
    }
}
Also used : GHPoint(com.graphhopper.util.shapes.GHPoint) Snap(com.graphhopper.storage.index.Snap) GHPoint(com.graphhopper.util.shapes.GHPoint)

Aggregations

Snap (com.graphhopper.storage.index.Snap)77 Test (org.junit.jupiter.api.Test)39 QueryGraph (com.graphhopper.routing.querygraph.QueryGraph)31 GHPoint (com.graphhopper.util.shapes.GHPoint)22 LocationIndexTree (com.graphhopper.storage.index.LocationIndexTree)20 EdgeIteratorState (com.graphhopper.util.EdgeIteratorState)13 QueryRoutingCHGraph (com.graphhopper.routing.querygraph.QueryRoutingCHGraph)12 Weighting (com.graphhopper.routing.weighting.Weighting)11 ArrayList (java.util.ArrayList)11 Path (com.graphhopper.routing.Path)9 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)9 FastestWeighting (com.graphhopper.routing.weighting.FastestWeighting)8 RoutingAlgorithm (com.graphhopper.routing.RoutingAlgorithm)6 DecimalEncodedValue (com.graphhopper.routing.ev.DecimalEncodedValue)6 LocationIndex (com.graphhopper.storage.index.LocationIndex)6 IntArrayList (com.carrotsearch.hppc.IntArrayList)5 GraphHopper (com.graphhopper.GraphHopper)5 Profile (com.graphhopper.config.Profile)5 ValueSource (org.junit.jupiter.params.provider.ValueSource)5 DefaultSnapFilter (com.graphhopper.routing.util.DefaultSnapFilter)4