public static void main(String[] strs) throws Exception { CmdArgs args = CmdArgs.read(strs); GraphHopper hopper = new GraphHopper().init(args); hopper.importOrLoad(); RoutingAlgorithmSpecialAreaTests tests = new RoutingAlgorithmSpecialAreaTests(hopper); if (args.getBool("graph.testIT", false)) { tests.start(); } }
public BelgiumHubSuggester() { graphHopper = new GraphHopper().forServer(); String osmPath = "local/osm/belgium-latest.osm.pbf"; if (!new File(osmPath).exists()) { throw new IllegalStateException( "The osmPath (" + osmPath + ") does not exist.\n" + "Download the osm file from http://download.geofabrik.de/ first."); } graphHopper.setOSMFile(osmPath); graphHopper.setGraphHopperLocation("local/graphhopper"); graphHopper.setEncodingManager(new EncodingManager(EncodingManager.CAR)); graphHopper.importOrLoad(); logger.info("GraphHopper loaded."); }
public GHResponse route( List<GHPoint> waypoints, List<Double> headings, boolean withInstructions) { if (waypoints.size() < 2) { throw new IllegalArgumentException("Number of waypoints must be greater or equal 2"); } GHRequest request; if (headings != null) { request = new GHRequest(waypoints, headings); request.setVehicle(FlagEncoderFactory.CAR); request.setWeighting("fastest"); if (!USE_CONTRACTION_HIERARCHIES) { request.getHints().put(Parameters.CH.DISABLE, true); request.getHints().put("routing.flexible_mode.force", true); request.getHints().put(Parameters.Routing.EDGE_BASED, true); } else { request .getHints() .put( Parameters.CH.FORCE_HEADING, true); // Allow headings for routes using CH, but may produce artifacts (see // https://github.com/graphhopper/graphhopper/pull/434#issuecomment-110275256) } } else { request = new GHRequest(waypoints); } request.setLocale(Locale.getDefault()).setAlgorithm(Parameters.Algorithms.DIJKSTRA_BI); if (!withInstructions) { request.getHints().put(Parameters.Routing.INSTRUCTIONS, false); } return gh.route(request); }
public void startup(String dataDir, boolean loadElevationData) throws NoDataException, StartupException { if (dataDir == null) { Log.e(TAG, "No external storage available, cannot load GraphHopper data"); throw new NoDataException(); } gh = new GraphHopper().forMobile(); boolean result; try { gh.setEncodingManager(EncodingManager.create(FlagEncoderFactory.DEFAULT, dataDir)); gh.getCHFactoryDecorator().setDisablingAllowed(true); result = gh.setElevation(loadElevationData).setCHEnabled(true).load(dataDir); } catch (Exception e) { Log.e(TAG, "GraphHopper initialization failed", e); throw new StartupException(e); } if (!result) { Log.e(TAG, "GraphHopper initialization failed"); throw new StartupException(null); } }
public void suggest(File locationFile, int locationListSize, File outputFile, int hubSize) { // WARNING: this code is VERY DIRTY. // It's JUST good enough to generate the hubs for Belgium once (because we only need to // determine them once). // Further research to generate good hubs is needed. List<AirLocation> locationList = readAirLocationFile(locationFile); if (locationListSize > locationList.size()) { throw new IllegalArgumentException( "The locationListSize (" + locationListSize + ") is larger than the locationList size (" + locationList.size() + ")."); } locationList = subselectLocationList(locationListSize, locationList); Map<Point, Point> fromPointMap = new LinkedHashMap<Point, Point>(locationListSize * 10); Map<Point, Point> toPointMap = new LinkedHashMap<Point, Point>(locationListSize * 10); int rowIndex = 0; double maxAirDistance = 0.0; for (AirLocation fromAirLocation : locationList) { for (AirLocation toAirLocation : locationList) { double airDistance = fromAirLocation.getAirDistanceDouble(toAirLocation); if (airDistance > maxAirDistance) { maxAirDistance = airDistance; } } } double airDistanceThreshold = maxAirDistance / 10.0; for (AirLocation fromAirLocation : locationList) { for (AirLocation toAirLocation : locationList) { double distance; if (fromAirLocation != toAirLocation) { GHRequest request = new GHRequest( fromAirLocation.getLatitude(), fromAirLocation.getLongitude(), toAirLocation.getLatitude(), toAirLocation.getLongitude()) .setVehicle("car"); GHResponse response = graphHopper.route(request); if (response.hasErrors()) { throw new IllegalStateException( "GraphHopper gave " + response.getErrors().size() + " errors. First error chained.", response.getErrors().get(0)); } // Distance should be in km, not meter distance = response.getDistance() / 1000.0; if (distance == 0.0) { throw new IllegalArgumentException( "The fromAirLocation (" + fromAirLocation + ") and toAirLocation (" + toAirLocation + ") are the same."); } PointList ghPointList = response.getPoints(); PointPart previousFromPointPart = null; PointPart previousToPointPart = null; double previousLatitude = Double.NaN; double previousLongitude = Double.NaN; for (int i = 0; i < ghPointList.size(); i++) { double latitude = ghPointList.getLatitude(i); double longitude = ghPointList.getLongitude(i); if (latitude == previousLatitude && longitude == previousLongitude) { continue; } if (calcAirDistance( latitude, longitude, fromAirLocation.getLatitude(), fromAirLocation.getLongitude()) < airDistanceThreshold) { Point fromPoint = new Point(latitude, longitude); Point oldFromPoint = fromPointMap.get(fromPoint); if (oldFromPoint == null) { // Initialize fromPoint instance fromPoint.pointPartMap = new LinkedHashMap<AirLocation, PointPart>(); fromPointMap.put(fromPoint, fromPoint); } else { // Reuse existing fromPoint instance fromPoint = oldFromPoint; } PointPart fromPointPart = fromPoint.pointPartMap.get(fromAirLocation); if (fromPointPart == null) { fromPointPart = new PointPart(fromPoint, fromAirLocation); fromPoint.pointPartMap.put(fromAirLocation, fromPointPart); fromPointPart.previousPart = previousFromPointPart; } fromPointPart.count++; previousFromPointPart = fromPointPart; } if (calcAirDistance( latitude, longitude, toAirLocation.getLatitude(), toAirLocation.getLongitude()) < airDistanceThreshold) { Point toPoint = new Point(latitude, longitude); Point oldToPoint = toPointMap.get(toPoint); if (oldToPoint == null) { // Initialize toPoint instance toPoint.pointPartMap = new LinkedHashMap<AirLocation, PointPart>(); toPointMap.put(toPoint, toPoint); } else { // Reuse existing toPoint instance toPoint = oldToPoint; } // Basically do the same as fromPointPart, but while traversing in the other direction PointPart toPointPart = toPoint.pointPartMap.get(toAirLocation); boolean newToPointPart = false; if (toPointPart == null) { toPointPart = new PointPart(toPoint, toAirLocation); toPoint.pointPartMap.put(toAirLocation, toPointPart); newToPointPart = true; } if (previousToPointPart != null) { previousToPointPart.previousPart = toPointPart; } toPointPart.count++; if (newToPointPart) { previousToPointPart = toPointPart; } else { previousToPointPart = null; } } previousLatitude = latitude; previousLongitude = longitude; } } } logger.debug(" Finished routes for rowIndex {}/{}", rowIndex, locationList.size()); rowIndex++; } Set<Point> hubPointList = new LinkedHashSet<Point>(20); extractFromHubs(new ArrayList<Point>(fromPointMap.values()), hubPointList, (hubSize + 1) / 2); extractFromHubs(new ArrayList<Point>(toPointMap.values()), hubPointList, hubSize / 2); logger.info("Writing hubs..."); BufferedWriter vrpWriter = null; try { vrpWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8")); vrpWriter.write("HUB_COORD_SECTION\n"); int id = 0; for (Point point : hubPointList) { vrpWriter.write("" + id + " " + point.latitude + " " + point.longitude + " " + id + "\n"); id++; } vrpWriter.write("\n\nGOOGLE MAPS\n"); for (Point point : hubPointList) { vrpWriter.write("" + id + "\t0\t" + point.latitude + "," + point.longitude + "\n"); id++; } } catch (IOException e) { throw new IllegalArgumentException( "Could not read the locationFile (" + locationFile.getName() + ") or write the vrpOutputFile (" + outputFile.getName() + ").", e); } finally { IOUtils.closeQuietly(vrpWriter); } // Throw in google docs spreadsheet and use add-on Mapping Sheets to visualize. }
@Test public void testMonacoWithInstructions() { String osmFile = "files/monaco.osm.gz"; String graphFile = "target/graph-monaco"; String vehicle = "FOOT"; String importVehicles = "FOOT"; String weightCalcStr = "shortest"; try { // make sure we are using fresh graphhopper files with correct vehicle Helper.removeDir(new File(graphFile)); GraphHopper hopper = new GraphHopper() .setInMemory(true) .setOSMFile(osmFile) .disableCHShortcuts() .setGraphHopperLocation(graphFile) .setEncodingManager(new EncodingManager(importVehicles)) .importOrLoad(); Graph g = hopper.getGraph(); GHResponse rsp = hopper.route( new GHRequest(43.727687, 7.418737, 43.74958, 7.436566) .setAlgorithm("astar") .setVehicle(vehicle) .setWeighting(weightCalcStr)); assertEquals(3437.6, rsp.getDistance(), .1); assertEquals(87, rsp.getPoints().getSize()); InstructionList il = rsp.getInstructions(); assertEquals(13, il.size()); Translation tr = trMap.getWithFallBack(Locale.US); List<String> iList = il.createDescription(tr); // TODO roundabout fine tuning -> enter + leave roundabout (+ two rounabouts -> is it // necessary if we do not leave the street?) assertEquals("Continue onto Avenue des Guelfes", iList.get(0)); assertEquals("Turn slight left onto Avenue des Papalins", iList.get(1)); assertEquals("Turn sharp right onto Quai Jean-Charles Rey", iList.get(2)); assertEquals("Turn left onto road", iList.get(3)); assertEquals("Turn right onto Avenue Albert II", iList.get(4)); List<Double> dists = il.createDistances(); assertEquals(11, dists.get(0), 1); assertEquals(289, dists.get(1), 1); assertEquals(10, dists.get(2), 1); assertEquals(43, dists.get(3), 1); assertEquals(122, dists.get(4), 1); assertEquals(447, dists.get(5), 1); List<Long> times = il.createMillis(); assertEquals(7, times.get(0) / 1000); assertEquals(207, times.get(1) / 1000); assertEquals(7, times.get(2) / 1000); assertEquals(30, times.get(3) / 1000); assertEquals(87, times.get(4) / 1000); assertEquals(321, times.get(5) / 1000); List<GPXEntry> list = rsp.getInstructions().createGPXList(); assertEquals(123, list.size()); final long lastEntryMillis = list.get(list.size() - 1).getMillis(); final long totalResponseMillis = rsp.getMillis(); assertEquals(totalResponseMillis, lastEntryMillis); } catch (Exception ex) { throw new RuntimeException("cannot handle osm file " + osmFile, ex); } finally { Helper.removeDir(new File(graphFile)); } }
@Override public void doPost(HttpServletRequest httpReq, HttpServletResponse httpRes) throws ServletException, IOException { String infoStr = httpReq.getRemoteAddr() + " " + httpReq.getLocale() + " " + httpReq.getHeader("User-Agent"); String type = httpReq.getContentType(); GPXFile gpxFile; if (type.contains("application/xml")) { try { gpxFile = parseXML(httpReq); } catch (Exception ex) { logger.warn("Cannot parse XML for " + httpReq.getQueryString() + ", " + infoStr); httpRes.setStatus(SC_BAD_REQUEST); httpRes.getWriter().append(errorsToXML(Collections.<Throwable>singletonList(ex))); return; } } else { throw new IllegalArgumentException("content type not supported " + type); } final String format = getParam(httpReq, "type", "json"); boolean writeGPX = GPX_FORMAT.equals(format); boolean pointsEncoded = getBooleanParam(httpReq, "points_encoded", true); boolean enableInstructions = writeGPX || getBooleanParam(httpReq, "instructions", true); boolean enableElevation = getBooleanParam(httpReq, "elevation", false); boolean forceRepair = getBooleanParam(httpReq, "force_repair", false); // TODO export OSM IDs instead, use https://github.com/karussell/graphhopper-osm-id-mapping boolean enableTraversalKeys = getBooleanParam(httpReq, "traversal_keys", false); int maxNodesToVisit = (int) getLongParam(httpReq, "max_nodes_to_visit", 500); int separatedSearchDistance = (int) getLongParam(httpReq, "separated_search_distance", 300); String vehicle = getParam(httpReq, "vehicle", "car"); Locale locale = Helper.getLocale(getParam(httpReq, "locale", "en")); GHResponse matchGHRsp = new GHResponse(); MatchResult matchRsp = null; StopWatch sw = new StopWatch().start(); try { FlagEncoder encoder = hopper.getEncodingManager().getEncoder(vehicle); MapMatching matching = new MapMatching(hopper.getGraphHopperStorage(), locationIndexMatch, encoder); matching.setForceRepair(forceRepair); matching.setMaxNodesToVisit(maxNodesToVisit); matching.setSeparatedSearchDistance(separatedSearchDistance); matchRsp = matching.doWork(gpxFile.getEntries()); // fill GHResponse for identical structure Path path = matching.calcPath(matchRsp); Translation tr = trMap.getWithFallBack(locale); new PathMerger().doWork(matchGHRsp, Collections.singletonList(path), tr); } catch (Exception ex) { matchGHRsp.addError(ex); } logger.info( httpReq.getQueryString() + ", " + infoStr + ", took:" + sw.stop().getSeconds() + ", entries:" + gpxFile.getEntries().size() + ", " + matchGHRsp.getDebugInfo()); if (EXTENDED_JSON_FORMAT.equals(format)) { if (matchGHRsp.hasErrors()) { httpRes.setStatus(SC_BAD_REQUEST); httpRes.getWriter().append(new JSONArray(matchGHRsp.getErrors()).toString()); } else { httpRes.getWriter().write(new MatchResultToJson(matchRsp).exportTo().toString()); } } else if (GPX_FORMAT.equals(format)) { String xml = createGPXString(httpReq, httpRes, matchGHRsp); if (matchGHRsp.hasErrors()) { httpRes.setStatus(SC_BAD_REQUEST); httpRes.getWriter().append(xml); } else { writeResponse(httpRes, xml); } } else { Map<String, Object> map = routeSerializer.toJSON( matchGHRsp, true, pointsEncoded, enableElevation, enableInstructions); if (matchGHRsp.hasErrors()) { writeJsonError(httpRes, SC_BAD_REQUEST, new JSONObject(map)); } else { if (enableTraversalKeys) { if (matchRsp == null) { throw new IllegalStateException( "match response has to be none-null if no error happened"); } // encode edges as traversal keys which includes orientation // decode simply by multiplying with 0.5 List<Integer> traversalKeylist = new ArrayList<Integer>(); for (EdgeMatch em : matchRsp.getEdgeMatches()) { EdgeIteratorState edge = em.getEdgeState(); traversalKeylist.add( GHUtility.createEdgeKey( edge.getBaseNode(), edge.getAdjNode(), edge.getEdge(), false)); } map.put("traversal_keys", traversalKeylist); } writeJson(httpReq, httpRes, new JSONObject(map)); } } }
private void start(CmdArgs args) { String action = args.get("action", "").toLowerCase(); args.put("graph.location", "./graph-cache"); if (action.equals("import")) { String vehicle = args.get("vehicle", "car").toLowerCase(); args.put("graph.flagEncoders", vehicle); args.put("osmreader.osm", args.get("datasource", "")); // standard should be to remove disconnected islands args.put("prepare.minNetworkSize", 200); args.put("prepare.minOneWayNetworkSize", 200); GraphHopper hopper = new GraphHopper().init(args); hopper.setCHEnable(false); hopper.importOrLoad(); } else if (action.equals("match")) { GraphHopper hopper = new GraphHopper().init(args); hopper.setCHEnable(false); logger.info("loading graph from cache"); hopper.load("./graph-cache"); FlagEncoder firstEncoder = hopper.getEncodingManager().fetchEdgeEncoders().get(0); GraphHopperStorage graph = hopper.getGraphHopperStorage(); int gpxAccuracy = args.getInt("gpxAccuracy", 15); String instructions = args.get("instructions", ""); logger.info("Setup lookup index. Accuracy filter is at " + gpxAccuracy + "m"); LocationIndexMatch locationIndex = new LocationIndexMatch(graph, (LocationIndexTree) hopper.getLocationIndex(), gpxAccuracy); MapMatching mapMatching = new MapMatching(graph, locationIndex, firstEncoder); mapMatching.setSeparatedSearchDistance(args.getInt("separatedSearchDistance", 500)); mapMatching.setMaxNodesToVisit(args.getInt("maxNodesToVisit", 1000)); mapMatching.setForceRepair(args.getBool("forceRepair", false)); // do the actual matching, get the GPX entries from a file or via stream String gpxLocation = args.get("gpx", ""); File[] files = getFiles(gpxLocation); logger.info("Now processing " + files.length + " files"); StopWatch importSW = new StopWatch(); StopWatch matchSW = new StopWatch(); Translation tr = new TranslationMap().doImport().get(instructions); for (File gpxFile : files) { try { importSW.start(); List<GPXEntry> inputGPXEntries = new GPXFile().doImport(gpxFile.getAbsolutePath()).getEntries(); importSW.stop(); matchSW.start(); MatchResult mr = mapMatching.doWork(inputGPXEntries); matchSW.stop(); System.out.println(gpxFile); System.out.println( "\tmatches:\t" + mr.getEdgeMatches().size() + ", gps entries:" + inputGPXEntries.size()); System.out.println( "\tgpx length:\t" + (float) mr.getGpxEntriesLength() + " vs " + (float) mr.getMatchLength()); System.out.println( "\tgpx time:\t" + mr.getGpxEntriesMillis() / 1000f + " vs " + mr.getMatchMillis() / 1000f); String outFile = gpxFile.getAbsolutePath() + ".res.gpx"; System.out.println("\texport results to:" + outFile); InstructionList il; if (instructions.isEmpty()) { il = new InstructionList(null); } else { AltResponse matchGHRsp = new AltResponse(); Path path = mapMatching.calcPath(mr); new PathMerger().doWork(matchGHRsp, Collections.singletonList(path), tr); il = matchGHRsp.getInstructions(); } new GPXFile(mr, il).doExport(outFile); } catch (Exception ex) { importSW.stop(); matchSW.stop(); logger.error("Problem with file " + gpxFile + " Error: " + ex.getMessage()); } } System.out.println( "gps import took:" + importSW.getSeconds() + "s, match took: " + matchSW.getSeconds()); } else if (action.equals("getbounds")) { String gpxLocation = args.get("gpx", ""); File[] files = getFiles(gpxLocation); BBox bbox = BBox.createInverse(false); for (File gpxFile : files) { List<GPXEntry> inputGPXEntries = new GPXFile().doImport(gpxFile.getAbsolutePath()).getEntries(); for (GPXEntry entry : inputGPXEntries) { if (entry.getLat() < bbox.minLat) { bbox.minLat = entry.getLat(); } if (entry.getLat() > bbox.maxLat) { bbox.maxLat = entry.getLat(); } if (entry.getLon() < bbox.minLon) { bbox.minLon = entry.getLon(); } if (entry.getLon() > bbox.maxLon) { bbox.maxLon = entry.getLon(); } } } System.out.println("max bounds: " + bbox); // show download only for small areas if (bbox.maxLat - bbox.minLat < 0.1 && bbox.maxLon - bbox.minLon < 0.1) { double delta = 0.01; System.out.println( "Get small areas via\n" + "wget -O extract.osm 'http://overpass-api.de/api/map?bbox=" + (bbox.minLon - delta) + "," + (bbox.minLat - delta) + "," + (bbox.maxLon + delta) + "," + (bbox.maxLat + delta) + "'"); } } else { System.out.println( "Usage: Do an import once, then do the matching\n" + "./map-matching action=import datasource=your.pbf\n" + "./map-matching action=match gpx=your.gpx\n" + "./map-matching action=match gpx=.*gpx\n\n" + "Or start in-built matching web service\n" + "./map-matching action=start-server\n\n"); } }
@Override public void onDestroy() { gh.close(); gh = null; }
public Translation getTranslation() { return gh.getTranslationMap().getWithFallBack(Locale.getDefault()); }