Example #1
0
 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.");
 }
Example #3
0
  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);
  }
Example #4
0
  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.
 }
Example #6
0
  @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));
    }
  }
Example #7
0
  @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");
    }
  }
Example #9
0
 @Override
 public void onDestroy() {
   gh.close();
   gh = null;
 }
Example #10
0
 public Translation getTranslation() {
   return gh.getTranslationMap().getWithFallBack(Locale.getDefault());
 }