@Test public void testNormedDist() { Location2IDQuadtree index = new Location2IDQuadtree(createGHStorage(new EncodingManager("car")), new RAMDirectory()); index.initAlgo(5, 6); assertEquals(1, index.getNormedDist(0, 1), 1e-6); assertEquals(2, index.getNormedDist(0, 7), 1e-6); assertEquals(2, index.getNormedDist(7, 2), 1e-6); assertEquals(1, index.getNormedDist(7, 1), 1e-6); assertEquals(4, index.getNormedDist(13, 25), 1e-6); assertEquals(8, index.getNormedDist(15, 25), 1e-6); }
public Location2IDQuadtree(Graph g, Directory dir) { this.graph = g; this.nodeAccess = g.getNodeAccess(); index = dir.find("loc2id_index"); setResolution(100 * 100); }
/** * Fill quadtree which will span a raster over the entire specified graph g. But do this in a * pre-defined resolution which is controlled via capacity. This data structure then uses approx. * capacity * 4 bytes. So maximum capacity is 2^30 where the quadtree would cover the world * boundaries every 1.3km - IMO enough for EU or US networks. */ @Override public LocationIndex prepareIndex() { initBuffer(); initAlgo(latSize, lonSize); StopWatch sw = new StopWatch().start(); GHBitSet filledIndices = fillQuadtree(latSize * lonSize); int fillQT = filledIndices.getCardinality(); float res1 = sw.stop().getSeconds(); sw = new StopWatch().start(); int counter = fillEmptyIndices(filledIndices); float fillEmpty = sw.stop().getSeconds(); logger.info("filled quadtree index array in " + res1 + "s. size is " + getCapacity() + " (" + fillQT + "). filled empty " + counter + " in " + fillEmpty + "s"); flush(); return this; }
@Override public LocationIndex createIndex(Graph g, int resolution) { if (resolution < 0) resolution = 120; return new Location2IDQuadtree(g, new MMapDirectory(location + "loc2idIndex").create()). setResolution(resolution).prepareIndex(); }
@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"); res.setClosestNode(id); res.setQueryDistance(distCalc.calcNormalizedDist(queryLat, queryLon, mainLat, mainLon)); goFurtherHook(id); new BreadthFirstSearch() { @Override
/** * Loads the index from disc if exists. Make sure you are using the identical graph which was * used while flushing this index. * <p> * * @return if loading from file was successfully. */ @Override public boolean loadExisting() { if (!index.loadExisting()) return false; if (index.getHeader(0) != MAGIC_INT) throw new IllegalStateException("incorrect loc2id index version"); int lat = index.getHeader(1 * 4); int lon = index.getHeader(2 * 4); int checksum = index.getHeader(3 * 4); if (checksum != graph.getNodes()) throw new IllegalStateException("index was created from a different graph with " + checksum + ". Current nodes:" + graph.getNodes()); initAlgo(lat, lon); return true; }
|| getNormedDist(from, to) >= getNormedDist(takenFrom[to], to)) { continue;
void initAlgo(int lat, int lon) { this.latSize = lat; this.lonSize = lon; BBox b = graph.getBounds(); keyAlgo = new LinearKeyAlgo(lat, lon).setBounds(b); double max = Math.max(distCalc.calcDist(b.minLat, b.minLon, b.minLat, b.maxLon), distCalc.calcDist(b.minLat, b.minLon, b.maxLat, b.minLon)); maxRasterWidth2InMeterNormed = distCalc.calcNormalizedDist(max / Math.sqrt(getCapacity()) * 2); // as long as we have "dist < PI*R/2" it is save to compare the normalized distances instead of the real // distances. because sin(x) is only monotonic increasing for x <= PI/2 (and positive for x >= 0) }
@Override public LocationIndex setResolution(int resolution) { initLatLonSize(resolution); return this; }
@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);
@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"); res.setClosestNode(id); res.setQueryDistance(distCalc.calcNormalizedDist(queryLat, queryLon, mainLat, mainLon)); goFurtherHook(id); new BreadthFirstSearch() { @Override
/** * Loads the index from disc if exists. Make sure you are using the identical graph which was * used while flushing this index. * <p> * @return if loading from file was successfully. */ @Override public boolean loadExisting() { if (!index.loadExisting()) return false; if (index.getHeader(0) != MAGIC_INT) throw new IllegalStateException("incorrect loc2id index version"); int lat = index.getHeader(1 * 4); int lon = index.getHeader(2 * 4); int checksum = index.getHeader(3 * 4); if (checksum != graph.getNodes()) throw new IllegalStateException("index was created from a different graph with " + checksum + ". Current nodes:" + graph.getNodes()); initAlgo(lat, lon); return true; }
|| getNormedDist(from, to) >= getNormedDist(takenFrom[to], to)) { continue;
void initAlgo(int lat, int lon) { this.latSize = lat; this.lonSize = lon; BBox b = graph.getBounds(); keyAlgo = new LinearKeyAlgo(lat, lon).setBounds(b); double max = Math.max(distCalc.calcDist(b.minLat, b.minLon, b.minLat, b.maxLon), distCalc.calcDist(b.minLat, b.minLon, b.maxLat, b.minLon)); maxRasterWidth2InMeterNormed = distCalc.calcNormalizedDist(max / Math.sqrt(getCapacity()) * 2); // as long as we have "dist < PI*R/2" it is save to compare the normalized distances instead of the real // distances. because sin(x) is only monotonic increasing for x <= PI/2 (and positive for x >= 0) }
@Override public LocationIndex setResolution(int resolution) { initLatLonSize(resolution); return this; }
@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);
/** * Fill quadtree which will span a raster over the entire specified graph g. But do this in a * pre-defined resolution which is controlled via capacity. This data structure then uses approx. * capacity * 4 bytes. So maximum capacity is 2^30 where the quadtree would cover the world * boundaries every 1.3km - IMO enough for EU or US networks. */ @Override public LocationIndex prepareIndex() { initBuffer(); initAlgo(latSize, lonSize); StopWatch sw = new StopWatch().start(); GHBitSet filledIndices = fillQuadtree(latSize * lonSize); int fillQT = filledIndices.getCardinality(); float res1 = sw.stop().getSeconds(); sw = new StopWatch().start(); int counter = fillEmptyIndices(filledIndices); float fillEmpty = sw.stop().getSeconds(); logger.info("filled quadtree index array in " + res1 + "s. size is " + getCapacity() + " (" + fillQT + "). filled empty " + counter + " in " + fillEmpty + "s"); flush(); return this; }
@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"); res.setClosestNode(id); res.setQueryDistance(distCalc.calcNormalizedDist(queryLat, queryLon, mainLat, mainLon)); goFurtherHook(id); new BreadthFirstSearch() { @Override
public Location2IDQuadtree( Graph g, Directory dir ) { this.graph = g; this.nodeAccess = g.getNodeAccess(); index = dir.find("loc2id_index"); setResolution(100 * 100); }
/** * Loads the index from disc if exists. Make sure you are using the identical graph which was * used while flushing this index. * <p> * * @return if loading from file was successfully. */ @Override public boolean loadExisting() { if (!index.loadExisting()) return false; if (index.getHeader(0) != MAGIC_INT) throw new IllegalStateException("incorrect loc2id index version"); int lat = index.getHeader(1 * 4); int lon = index.getHeader(2 * 4); int checksum = index.getHeader(3 * 4); if (checksum != graph.getNodes()) throw new IllegalStateException("index was created from a different graph with " + checksum + ". Current nodes:" + graph.getNodes()); initAlgo(lat, lon); return true; }