Search in sources :

Example 1 with GHTBitSet

use of com.graphhopper.coll.GHTBitSet in project graphhopper by graphhopper.

the class Location2IDQuadtree method findClosest.

@Override
public QueryResult findClosest(final double queryLat, final double queryLon, final EdgeFilter edgeFilter) {
    if (isClosed())
        throw new IllegalStateException("You need to create a new LocationIndex instance as it is already closed");
    if (edgeFilter != EdgeFilter.ALL_EDGES)
        throw new UnsupportedOperationException("edge filters are not yet implemented for " + Location2IDQuadtree.class.getSimpleName());
    // The following cases (e.g. dead ends or motorways crossing a normal way) could be problematic:
    // |     |
    // |  P  |
    // |  |  |< --- maxRasterWidth reached
    // \-----/
    /*
         * Problem: use additionally the 8 surrounding quadrants: There an error due to the raster
         * width. Because this index does not cover 100% of the graph you'll need to traverse the
         * graph until you find the real matching point or if you reach the raster width limit. And
         * there is a problem when using the raster limit as 'not found' indication and if you have
         * arbitrary requests e.g. from other systems (where points do not match exactly): Although
         * P is the closest point to the request one it could be that the raster limit is too short
         * to reach it via graph traversal:
         */
    long key = keyAlgo.encode(queryLat, queryLon);
    final int id = index.getInt(key * 4);
    double mainLat = nodeAccess.getLatitude(id);
    double mainLon = nodeAccess.getLongitude(id);
    final QueryResult res = new QueryResult(queryLat, queryLon);
    res.setClosestNode(id);
    res.setQueryDistance(distCalc.calcNormalizedDist(queryLat, queryLon, mainLat, mainLon));
    goFurtherHook(id);
    new BreadthFirstSearch() {

        @Override
        protected GHBitSet createBitSet() {
            return new GHTBitSet(10);
        }

        @Override
        protected boolean goFurther(int baseNode) {
            if (baseNode == id)
                return true;
            goFurtherHook(baseNode);
            double currLat = nodeAccess.getLatitude(baseNode);
            double currLon = nodeAccess.getLongitude(baseNode);
            double currNormedDist = distCalc.calcNormalizedDist(queryLat, queryLon, currLat, currLon);
            if (currNormedDist < res.getQueryDistance()) {
                res.setQueryDistance(currNormedDist);
                res.setClosestNode(baseNode);
                return true;
            }
            return currNormedDist < maxRasterWidth2InMeterNormed;
        }
    }.start(graph.createEdgeExplorer(), id);
    // denormalize distance
    res.setQueryDistance(distCalc.calcDenormalizedDist(res.getQueryDistance()));
    return res;
}
Also used : GHTBitSet(com.graphhopper.coll.GHTBitSet) BreadthFirstSearch(com.graphhopper.util.BreadthFirstSearch) GHBitSet(com.graphhopper.coll.GHBitSet) GHPoint(com.graphhopper.util.shapes.GHPoint)

Example 2 with GHTBitSet

use of com.graphhopper.coll.GHTBitSet in project graphhopper by graphhopper.

the class LocationIndexTree method findNClosest.

/**
 * Returns all edges that are within the specified radius around the queried position.
 * Searches at most 9 cells to avoid performance problems. Hence, if the radius is larger than
 * the cell width then not all edges might be returned.
 *
 * TODO: either clarify the method name and description (to only search e.g. 9 tiles) or
 * refactor so it can handle a radius larger than 9 tiles. Also remove reference to 'NClosest',
 * which is misleading, and don't always return at least one value. See map-matching #65.
 * TODO: tidy up logic - see comments in graphhopper #994.
 *
 * @param radius in meters
 */
public List<QueryResult> findNClosest(final double queryLat, final double queryLon, final EdgeFilter edgeFilter, double radius) {
    // Return ALL results which are very close and e.g. within the GPS signal accuracy.
    // Also important to get all edges if GPS point is close to a junction.
    final double returnAllResultsWithin = distCalc.calcNormalizedDist(radius);
    // implement a cheap priority queue via List, sublist and Collections.sort
    final List<QueryResult> queryResults = new ArrayList<QueryResult>();
    GHIntHashSet set = new GHIntHashSet();
    // Doing 2 iterations means searching 9 tiles.
    for (int iteration = 0; iteration < 2; iteration++) {
        // should we use the return value of earlyFinish?
        findNetworkEntries(queryLat, queryLon, set, iteration);
        final GHBitSet exploredNodes = new GHTBitSet(new GHIntHashSet(set));
        final EdgeExplorer explorer = graph.createEdgeExplorer(edgeFilter);
        set.forEach(new IntPredicate() {

            @Override
            public boolean apply(int node) {
                new XFirstSearchCheck(queryLat, queryLon, exploredNodes, edgeFilter) {

                    @Override
                    protected double getQueryDistance() {
                        // do not skip search if distance is 0 or near zero (equalNormedDelta)
                        return Double.MAX_VALUE;
                    }

                    @Override
                    protected boolean check(int node, double normedDist, int wayIndex, EdgeIteratorState edge, QueryResult.Position pos) {
                        if (normedDist < returnAllResultsWithin || queryResults.isEmpty() || queryResults.get(0).getQueryDistance() > normedDist) {
                            // TODO: refactor below:
                            // - should only add edges within search radius (below allows the
                            // returning of a candidate outside search radius if it's the only
                            // one). Removing this test would simplify it a lot and probably
                            // match the expected behaviour (see method description)
                            // - create QueryResult first and the add/set as required - clean up
                            // the index tracking business.
                            int index = -1;
                            for (int qrIndex = 0; qrIndex < queryResults.size(); qrIndex++) {
                                QueryResult qr = queryResults.get(qrIndex);
                                // overwrite older queryResults which are potentially more far away than returnAllResultsWithin
                                if (qr.getQueryDistance() > returnAllResultsWithin) {
                                    index = qrIndex;
                                    break;
                                }
                                // avoid duplicate edges
                                if (qr.getClosestEdge().getEdge() == edge.getEdge()) {
                                    if (qr.getQueryDistance() < normedDist) {
                                        // do not add current edge
                                        return true;
                                    } else {
                                        // overwrite old edge with current
                                        index = qrIndex;
                                        break;
                                    }
                                }
                            }
                            QueryResult qr = new QueryResult(queryLat, queryLon);
                            qr.setQueryDistance(normedDist);
                            qr.setClosestNode(node);
                            qr.setClosestEdge(edge.detach(false));
                            qr.setWayIndex(wayIndex);
                            qr.setSnappedPosition(pos);
                            if (index < 0) {
                                queryResults.add(qr);
                            } else {
                                queryResults.set(index, qr);
                            }
                        }
                        return true;
                    }
                }.start(explorer, node);
                return true;
            }
        });
    }
    // TODO: pass boolean argument for whether or not to sort? Can be expensive if not required.
    Collections.sort(queryResults, QR_COMPARATOR);
    for (QueryResult qr : queryResults) {
        if (qr.isValid()) {
            // denormalize distance
            qr.setQueryDistance(distCalc.calcDenormalizedDist(qr.getQueryDistance()));
            qr.calcSnappedPoint(distCalc);
        } else {
            throw new IllegalStateException("Invalid QueryResult should not happen here: " + qr);
        }
    }
    return queryResults;
}
Also used : GHIntHashSet(com.graphhopper.coll.GHIntHashSet) IntPredicate(com.carrotsearch.hppc.predicates.IntPredicate) GHBitSet(com.graphhopper.coll.GHBitSet) ArrayList(java.util.ArrayList) IntArrayList(com.carrotsearch.hppc.IntArrayList) GHPoint(com.graphhopper.util.shapes.GHPoint) GHTBitSet(com.graphhopper.coll.GHTBitSet)

Example 3 with GHTBitSet

use of com.graphhopper.coll.GHTBitSet in project graphhopper by graphhopper.

the class BreadthFirstSearchTest method testBFS.

@Test
public void testBFS() {
    BreadthFirstSearch bfs = new BreadthFirstSearch() {

        @Override
        protected GHBitSet createBitSet() {
            return new GHTBitSet();
        }

        @Override
        public boolean goFurther(int v) {
            counter++;
            assertFalse(set.contains(v), "v " + v + " is already contained in set. iteration:" + counter);
            set.add(v);
            list.add(v);
            return super.goFurther(v);
        }
    };
    FlagEncoder encoder = new CarFlagEncoder();
    Graph g = new GraphBuilder(EncodingManager.create(encoder)).create();
    GHUtility.setSpeed(60, true, true, encoder, g.edge(0, 1).setDistance(85));
    GHUtility.setSpeed(60, true, true, encoder, g.edge(0, 2).setDistance(217));
    GHUtility.setSpeed(60, true, true, encoder, g.edge(0, 3).setDistance(173));
    GHUtility.setSpeed(60, true, true, encoder, g.edge(0, 5).setDistance(173));
    GHUtility.setSpeed(60, true, true, encoder, g.edge(1, 6).setDistance(75));
    GHUtility.setSpeed(60, true, true, encoder, g.edge(2, 7).setDistance(51));
    GHUtility.setSpeed(60, true, true, encoder, g.edge(3, 8).setDistance(23));
    GHUtility.setSpeed(60, true, true, encoder, g.edge(4, 8).setDistance(793));
    GHUtility.setSpeed(60, true, true, encoder, g.edge(8, 10).setDistance(343));
    GHUtility.setSpeed(60, true, true, encoder, g.edge(6, 9).setDistance(72));
    GHUtility.setSpeed(60, true, true, encoder, g.edge(9, 10).setDistance(8));
    GHUtility.setSpeed(60, true, true, encoder, g.edge(5, 10).setDistance(1));
    bfs.start(g.createEdgeExplorer(), 0);
    assertTrue(counter > 0);
    assertEquals(g.getNodes(), counter);
    assertEquals("[0, 5, 3, 2, 1, 10, 8, 7, 6, 9, 4]", list.toString());
}
Also used : GHTBitSet(com.graphhopper.coll.GHTBitSet) Graph(com.graphhopper.storage.Graph) CarFlagEncoder(com.graphhopper.routing.util.CarFlagEncoder) FlagEncoder(com.graphhopper.routing.util.FlagEncoder) GraphBuilder(com.graphhopper.storage.GraphBuilder) CarFlagEncoder(com.graphhopper.routing.util.CarFlagEncoder) Test(org.junit.jupiter.api.Test)

Example 4 with GHTBitSet

use of com.graphhopper.coll.GHTBitSet in project graphhopper by graphhopper.

the class BreadthFirstSearchTest method testBFS2.

@Test
public void testBFS2() {
    BreadthFirstSearch bfs = new BreadthFirstSearch() {

        @Override
        protected GHBitSet createBitSet() {
            return new GHTBitSet();
        }

        @Override
        public boolean goFurther(int v) {
            counter++;
            assertFalse(set.contains(v), "v " + v + " is already contained in set. iteration:" + counter);
            set.add(v);
            list.add(v);
            return super.goFurther(v);
        }
    };
    FlagEncoder encoder = new CarFlagEncoder();
    Graph g = new GraphBuilder(EncodingManager.create(encoder)).create();
    GHUtility.setSpeed(60, true, false, encoder, g.edge(1, 2).setDistance(1));
    GHUtility.setSpeed(60, true, false, encoder, g.edge(2, 3).setDistance(1));
    GHUtility.setSpeed(60, true, false, encoder, g.edge(3, 4).setDistance(1));
    GHUtility.setSpeed(60, true, false, encoder, g.edge(1, 5).setDistance(1));
    GHUtility.setSpeed(60, true, false, encoder, g.edge(5, 6).setDistance(1));
    GHUtility.setSpeed(60, true, false, encoder, g.edge(6, 4).setDistance(1));
    bfs.start(g.createEdgeExplorer(), 1);
    assertTrue(counter > 0);
    assertEquals("[1, 5, 2, 6, 3, 4]", list.toString());
}
Also used : GHTBitSet(com.graphhopper.coll.GHTBitSet) Graph(com.graphhopper.storage.Graph) CarFlagEncoder(com.graphhopper.routing.util.CarFlagEncoder) FlagEncoder(com.graphhopper.routing.util.FlagEncoder) GraphBuilder(com.graphhopper.storage.GraphBuilder) CarFlagEncoder(com.graphhopper.routing.util.CarFlagEncoder) Test(org.junit.jupiter.api.Test)

Aggregations

GHTBitSet (com.graphhopper.coll.GHTBitSet)4 GHBitSet (com.graphhopper.coll.GHBitSet)2 CarFlagEncoder (com.graphhopper.routing.util.CarFlagEncoder)2 FlagEncoder (com.graphhopper.routing.util.FlagEncoder)2 Graph (com.graphhopper.storage.Graph)2 GraphBuilder (com.graphhopper.storage.GraphBuilder)2 GHPoint (com.graphhopper.util.shapes.GHPoint)2 Test (org.junit.jupiter.api.Test)2 IntArrayList (com.carrotsearch.hppc.IntArrayList)1 IntPredicate (com.carrotsearch.hppc.predicates.IntPredicate)1 GHIntHashSet (com.graphhopper.coll.GHIntHashSet)1 BreadthFirstSearch (com.graphhopper.util.BreadthFirstSearch)1 ArrayList (java.util.ArrayList)1