/** Finds shortcuts, does not change the underlying graph. */
  void findShortcuts(ShortcutHandler sch) {
    long tmpDegreeCounter = 0;
    EdgeIterator incomingEdges = vehicleInExplorer.setBaseNode(sch.getNode());
    // collect outgoing nodes (goal-nodes) only once
    while (incomingEdges.next()) {
      int u_fromNode = incomingEdges.getAdjNode();
      // accept only uncontracted nodes
      if (g.getLevel(u_fromNode) != 0) continue;

      double v_u_weight = incomingEdges.getDistance();
      int skippedEdge1 = incomingEdges.getEdge();
      int incomingEdgeOrigCount = getOrigEdgeCount(skippedEdge1);
      // collect outgoing nodes (goal-nodes) only once
      EdgeIterator outgoingEdges = vehicleOutExplorer.setBaseNode(sch.getNode());
      // force fresh maps etc as this cannot be determined by from node alone (e.g. same from node
      // but different avoidNode)
      algo.clear();
      tmpDegreeCounter++;
      while (outgoingEdges.next()) {
        int w_toNode = outgoingEdges.getAdjNode();
        // add only uncontracted nodes
        if (g.getLevel(w_toNode) != 0 || u_fromNode == w_toNode) {
          continue;
        }

        // Limit weight as ferries or forbidden edges can increase local search too much.
        // If we decrease the correct weight we only explore less and introduce more shortcuts.
        // I.e. no change to accuracy is made.
        double existingDirectWeight = v_u_weight + outgoingEdges.getDistance();
        algo.setLimitWeight(existingDirectWeight)
            .setLimitVisitedNodes((int) meanDegree * 100)
            .setEdgeFilter(levelEdgeFilter.setAvoidNode(sch.getNode()));

        dijkstraSW.start();
        dijkstraCount++;
        int endNode = algo.findEndNode(u_fromNode, w_toNode);
        dijkstraSW.stop();

        // compare end node as the limit could force dijkstra to finish earlier
        if (endNode == w_toNode && algo.getWeight(endNode) <= existingDirectWeight)
          // FOUND witness path, so do not add shortcut
          continue;

        sch.foundShortcut(
            u_fromNode,
            w_toNode,
            existingDirectWeight,
            outgoingEdges,
            skippedEdge1,
            incomingEdgeOrigCount);
      }
    }
    if (sch instanceof AddShortcutHandler) {
      // sliding mean value when using "*2" => slower changes
      meanDegree = (meanDegree * 2 + tmpDegreeCounter) / 3;
      // meanDegree = (meanDegree + tmpDegreeCounter) / 2;
    }
  }
 public RoutingAlgorithmSpecialAreaTests(Graph graph) {
   this.unterfrankenGraph = graph;
   StopWatch sw = new StopWatch().start();
   Location2IDQuadtree index;
   if (graph instanceof GraphStorage) {
     Directory dir = ((GraphStorage) graph).getDirectory();
     index = new Location2IDQuadtree(unterfrankenGraph, dir);
     // logger.info("dir: " + dir.getLocation());
   } else
     index = new Location2IDQuadtree(unterfrankenGraph, new RAMDirectory("loc2idIndex", false));
   // Location2IDPreciseIndex index = new Location2IDPreciseIndex(unterfrankenGraph, dir);
   // Location2IDFullIndex index = new Location2IDFullIndex(graph);
   if (!index.loadExisting()) {
     index.prepareIndex(200000);
     index.flush();
   }
   idx = index;
   logger.info(
       index.getClass().getSimpleName()
           + " index. Size:"
           + idx.calcMemInMB()
           + " MB, took:"
           + sw.stop().getSeconds());
 }
  @Override
  public PrepareContractionHierarchies doWork() {
    checkGraph();
    if (prepareEncoder == null) throw new IllegalStateException("No vehicle encoder set.");

    if (prepareWeighting == null) throw new IllegalStateException("No weight calculation set.");

    allSW.start();
    super.doWork();

    initFromGraph();
    if (!prepareEdges()) return this;

    if (!prepareNodes()) return this;

    contractNodes();
    return this;
  }
  void contractNodes() {
    meanDegree = g.getAllEdges().getMaxId() / g.getNodes();
    int level = 1;
    counter = 0;
    int initSize = sortedNodes.getSize();
    int logSize =
        (int) Math.round(Math.max(10, sortedNodes.getSize() / 100 * logMessagesPercentage));
    if (logMessagesPercentage == 0) logSize = Integer.MAX_VALUE;

    // preparation takes longer but queries are slightly faster with preparation
    // => enable it but call not so often
    boolean periodicUpdate = true;
    StopWatch periodSW = new StopWatch();
    int updateCounter = 0;
    int periodicUpdatesCount =
        Math.max(10, sortedNodes.getSize() / 100 * periodicUpdatesPercentage);
    if (periodicUpdatesPercentage == 0) periodicUpdate = false;

    // disable as preparation is slower and query time does not benefit
    int lastNodesLazyUpdates =
        lastNodesLazyUpdatePercentage == 0
            ? 0
            : sortedNodes.getSize() / 100 * lastNodesLazyUpdatePercentage;
    StopWatch lazySW = new StopWatch();

    // Recompute priority of uncontracted neighbors.
    // Without neighborupdates preparation is faster but we need them
    // to slightly improve query time. Also if not applied too often it decreases the shortcut
    // number.
    boolean neighborUpdate = true;
    if (neighborUpdatePercentage == 0) neighborUpdate = false;

    StopWatch neighborSW = new StopWatch();
    LevelGraphStorage lg = ((LevelGraphStorage) g);
    while (!sortedNodes.isEmpty()) {
      // periodically update priorities of ALL nodes
      if (periodicUpdate && counter > 0 && counter % periodicUpdatesCount == 0) {
        periodSW.start();
        sortedNodes.clear();
        int len = g.getNodes();
        for (int node = 0; node < len; node++) {
          if (g.getLevel(node) != 0) continue;

          int priority = oldPriorities[node] = calculatePriority(node);
          sortedNodes.insert(node, priority);
        }
        periodSW.stop();
        updateCounter++;
      }

      if (counter % logSize == 0) {
        // TODO necessary?
        System.gc();
        logger.info(
            Helper.nf(counter)
                + ", updates:"
                + updateCounter
                + ", nodes: "
                + Helper.nf(sortedNodes.getSize())
                + ", shortcuts:"
                + Helper.nf(newShortcuts)
                + ", dijkstras:"
                + Helper.nf(dijkstraCount)
                + ", t(dijk):"
                + (int) dijkstraSW.getSeconds()
                + ", t(period):"
                + (int) periodSW.getSeconds()
                + ", t(lazy):"
                + (int) lazySW.getSeconds()
                + ", t(neighbor):"
                + (int) neighborSW.getSeconds()
                + ", meanDegree:"
                + (long) meanDegree
                + ", algo:"
                + algo.getMemoryUsageAsString()
                + ", "
                + Helper.getMemInfo());
        dijkstraSW = new StopWatch();
        periodSW = new StopWatch();
        lazySW = new StopWatch();
        neighborSW = new StopWatch();
      }

      counter++;
      int polledNode = sortedNodes.pollKey();
      if (sortedNodes.getSize() < lastNodesLazyUpdates) {
        lazySW.start();
        int priority = oldPriorities[polledNode] = calculatePriority(polledNode);
        if (!sortedNodes.isEmpty() && priority > sortedNodes.peekValue()) {
          // current node got more important => insert as new value and contract it later
          sortedNodes.insert(polledNode, priority);
          lazySW.stop();
          continue;
        }
        lazySW.stop();
      }

      // contract!
      newShortcuts += addShortcuts(polledNode);
      g.setLevel(polledNode, level);
      level++;

      EdgeSkipIterator iter = vehicleAllExplorer.setBaseNode(polledNode);
      while (iter.next()) {
        int nn = iter.getAdjNode();
        if (g.getLevel(nn) != 0)
          // already contracted no update necessary
          continue;

        if (neighborUpdate && rand.nextInt(100) < neighborUpdatePercentage) {
          neighborSW.start();
          int oldPrio = oldPriorities[nn];
          int priority = oldPriorities[nn] = calculatePriority(nn);
          if (priority != oldPrio) sortedNodes.update(nn, oldPrio, priority);

          neighborSW.stop();
        }

        if (removesHigher2LowerEdges) lg.disconnect(vehicleAllTmpExplorer, iter);
      }
    }

    // Preparation works only once so we can release temporary data.
    // The preparation object itself has to be intact to create the algorithm.
    close();
    logger.info(
        "took:"
            + (int) allSW.stop().getSeconds()
            + ", new shortcuts: "
            + newShortcuts
            + ", "
            + prepareWeighting
            + ", "
            + prepareEncoder
            + ", removeHigher2LowerEdges:"
            + removesHigher2LowerEdges
            + ", dijkstras:"
            + dijkstraCount
            + ", t(dijk):"
            + (int) dijkstraSW.getSeconds()
            + ", t(period):"
            + (int) periodSW.getSeconds()
            + ", t(lazy):"
            + (int) lazySW.getSeconds()
            + ", t(neighbor):"
            + (int) neighborSW.getSeconds()
            + ", meanDegree:"
            + (long) meanDegree
            + ", initSize:"
            + initSize
            + ", periodic:"
            + periodicUpdatesPercentage
            + ", lazy:"
            + lastNodesLazyUpdatePercentage
            + ", neighbor:"
            + neighborUpdatePercentage);
  }
Example #5
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));
      }
    }
  }
Example #6
0
  @Override
  public GHResponse route(GHRequest request) {
    request.check();
    StopWatch sw = new StopWatch().start();
    GHResponse rsp = new GHResponse();

    if (!setSupportsVehicle(request.getVehicle())) {
      rsp.addError(
          new IllegalArgumentException(
              "Vehicle "
                  + request.getVehicle()
                  + " unsupported. Supported are: "
                  + getEncodingManager()));
      return rsp;
    }

    EdgeFilter edgeFilter = new DefaultEdgeFilter(encodingManager.getEncoder(request.getVehicle()));
    int from =
        index
            .findClosest(request.getFrom().lat, request.getFrom().lon, edgeFilter)
            .getClosestNode();
    int to =
        index.findClosest(request.getTo().lat, request.getTo().lon, edgeFilter).getClosestNode();
    String debug = "idLookup:" + sw.stop().getSeconds() + "s";

    if (from < 0)
      rsp.addError(new IllegalArgumentException("Cannot find point 1: " + request.getFrom()));

    if (to < 0)
      rsp.addError(new IllegalArgumentException("Cannot find point 2: " + request.getTo()));

    if (from == to) rsp.addError(new IllegalArgumentException("Point 1 is equal to point 2"));

    sw = new StopWatch().start();
    RoutingAlgorithm algo = null;

    if (chUsage) {
      if (request.getAlgorithm().equals("dijkstrabi")) algo = prepare.createAlgo();
      else if (request.getAlgorithm().equals("astarbi"))
        algo = ((PrepareContractionHierarchies) prepare).createAStar();
      else
        rsp.addError(
            new IllegalStateException(
                "Only dijkstrabi and astarbi is supported for LevelGraph (using contraction hierarchies)!"));

    } else {
      prepare =
          NoOpAlgorithmPreparation.createAlgoPrepare(
              graph,
              request.getAlgorithm(),
              encodingManager.getEncoder(request.getVehicle()),
              request.getType());
      algo = prepare.createAlgo();
    }

    if (rsp.hasErrors()) {
      return rsp;
    }
    debug += ", algoInit:" + sw.stop().getSeconds() + "s";

    sw = new StopWatch().start();
    Path path = algo.calcPath(from, to);
    debug +=
        ", "
            + algo.getName()
            + "-routing:"
            + sw.stop().getSeconds()
            + "s"
            + ", "
            + path.getDebugInfo();
    PointList points = path.calcPoints();
    simplifyRequest = request.getHint("simplifyRequest", simplifyRequest);
    if (simplifyRequest) {
      sw = new StopWatch().start();
      int orig = points.getSize();
      double minPathPrecision = request.getHint("douglas.minprecision", 1d);
      if (minPathPrecision > 0) {
        new DouglasPeucker().setMaxDistance(minPathPrecision).simplify(points);
      }
      debug +=
          ", simplify (" + orig + "->" + points.getSize() + "):" + sw.stop().getSeconds() + "s";
    }

    enableInstructions = request.getHint("instructions", enableInstructions);
    if (enableInstructions) {
      sw = new StopWatch().start();
      rsp.setInstructions(path.calcInstructions());
      debug += ", instructions:" + sw.stop().getSeconds() + "s";
    }
    return rsp.setPoints(points)
        .setDistance(path.getDistance())
        .setTime(path.getTime())
        .setDebugInfo(debug);
  }
  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");
    }
  }
  public void runShortestPathPerf(int runs, RoutingAlgorithm algo) throws Exception {
    BBox bbox = unterfrankenGraph.getBounds();
    double minLat = bbox.minLat, minLon = bbox.minLon;
    double maxLat = bbox.maxLat, maxLon = bbox.maxLon;
    if (unterfrankenGraph instanceof LevelGraph) {
      if (algo instanceof DijkstraBidirectionRef)
        algo = new PrepareContractionHierarchies().setGraph(unterfrankenGraph).createAlgo();
      //                algo = new
      // PrepareSimpleShortcuts().setGraph(unterfrankenGraph).createAlgo();
      else if (algo instanceof AStarBidirection)
        algo = new PrepareSimpleShortcuts().setGraph(unterfrankenGraph).createAStar();
      else
        // level graph accepts all algorithms but normally we want to use an optimized one
        throw new IllegalStateException(
            "algorithm which boosts query time for levelgraph not found " + algo);
      logger.info("[experimental] using shortcuts with " + algo);
    } else logger.info("running " + algo);

    Random rand = new Random(123);
    StopWatch sw = new StopWatch();

    // System.out.println("cap:" + ((GraphStorage) unterfrankenGraph).capacity());
    for (int i = 0; i < runs; i++) {
      double fromLat = rand.nextDouble() * (maxLat - minLat) + minLat;
      double fromLon = rand.nextDouble() * (maxLon - minLon) + minLon;
      //            sw.start();
      int from = idx.findID(fromLat, fromLon);
      double toLat = rand.nextDouble() * (maxLat - minLat) + minLat;
      double toLon = rand.nextDouble() * (maxLon - minLon) + minLon;
      int to = idx.findID(toLat, toLon);
      //            sw.stop();
      //                logger.info(i + " " + sw + " from (" + from + ")" + fromLat + ", " + fromLon
      // + " to (" + to + ")" + toLat + ", " + toLon);
      if (from == to) {
        logger.warn("skipping i " + i + " from==to " + from);
        continue;
      }

      algo.clear();
      sw.start();
      Path p = algo.calcPath(from, to);
      sw.stop();
      if (!p.found()) {
        // there are still paths not found cause of oneway motorways => only routable in one
        // direction
        // e.g. unterfrankenGraph.getLatitude(798809) + "," + unterfrankenGraph.getLongitude(798809)
        logger.warn(
            "no route found for i="
                + i
                + " !? "
                + "graph-from "
                + from
                + "("
                + fromLat
                + ","
                + fromLon
                + "), "
                + "graph-to "
                + to
                + "("
                + toLat
                + ","
                + toLon
                + ")");
        continue;
      }
      if (i % 20 == 0)
        logger.info(i + " " + sw.getSeconds() / (i + 1) + " secs/run"); // (" + p + ")");
    }
  }
Example #9
0
  @Override
  public GHResponse route(GHRequest request) {
    StopWatch sw = new StopWatch().start();
    double took = 0;
    try {
      String url =
          serviceUrl
              + "?point="
              + request.getFrom().lat
              + ","
              + request.getFrom().lon
              + "&point="
              + request.getTo().lat
              + ","
              + request.getTo().lon
              + "&type=json"
              + "&points_encoded="
              + pointsEncoded
              + "&min_path_precision="
              + request.getHint("douglas.minprecision", 1)
              + "&algo="
              + request.getAlgorithm();
      String str = downloader.downloadAsString(url);
      JSONObject json = new JSONObject(str);
      took = json.getJSONObject("info").getDouble("took");
      JSONArray paths = json.getJSONArray("paths");
      JSONObject firstPath = paths.getJSONObject(0);

      boolean is3D = false;
      if (firstPath.has("points_dim")) is3D = "3".equals(firstPath.getString("points_dim"));
      double distance = firstPath.getDouble("distance");
      int time = firstPath.getInt("time");
      PointList pointList;
      if (pointsEncoded) {
        pointList = WebHelper.decodePolyline(firstPath.getString("points"), 100, is3D);
      } else {
        JSONArray coords = firstPath.getJSONObject("points").getJSONArray("coordinates");
        pointList = new PointList(coords.length(), is3D);
        for (int i = 0; i < coords.length(); i++) {
          JSONArray arr = coords.getJSONArray(i);
          double lon = arr.getDouble(0);
          double lat = arr.getDouble(1);
          if (is3D) pointList.add(lat, lon, arr.getDouble(2));
          else pointList.add(lat, lon);
        }
      }
      GHResponse res = new GHResponse();
      if (instructions) {
        JSONArray instrArr = firstPath.getJSONArray("instructions");

        InstructionList il = new InstructionList();
        for (int instrIndex = 0; instrIndex < instrArr.length(); instrIndex++) {
          JSONObject jsonObj = instrArr.getJSONObject(instrIndex);
          double instDist = jsonObj.getDouble("distance");
          String text = jsonObj.getString("text");
          long instTime = jsonObj.getLong("time");
          int sign = jsonObj.getInt("sign");
          JSONArray iv = jsonObj.getJSONArray("interval");
          int from = iv.getInt(0);
          int to = iv.getInt(1);
          PointList instPL = new PointList(to - from, is3D);
          for (int j = from; j <= to; j++) {
            instPL.add(pointList, j);
          }

          // TODO way and payment type
          Instruction instr =
              new Instruction(sign, text, -1, -1, instPL).setDistance(instDist).setTime(instTime);
          il.add(instr);
        }
        res.setInstructions(il);
      }
      return res.setPoints(pointList).setDistance(distance).setMillis(time);
    } catch (Exception ex) {
      throw new RuntimeException(
          "Problem while fetching path " + request.getFrom() + "->" + request.getTo(), ex);
    } finally {
      logger.debug("Full request took:" + sw.stop().getSeconds() + ", API took:" + took);
    }
  }