将Google地图的航点指示转换为via-directions

时间:2015-08-04 22:17:30

标签: java google-maps

我正在尝试将Google地图路线的网址从具有多个航点的路线更改为删除这些中间航路点但路线保持不变的路线。

具体来自:https://www.google.nl/maps/dir/51.804323,5.8061076/51.8059489,5.7971745/51.8095767,5.8032703/@51.8068221,5.806553,16.5z/data=!4m2!4m1!3e2

于: https://www.google.nl/maps/dir/51.804323,5.8061076/51.8095767,5.8032703/@51.8069622,5.8023697,17z/data=!4m9!4m8!1m5!3m4!1m2!1d5.7971218!2d51.8060231!3s0x47c7061292e15b39:0x4d7bcd7484c71cf3!1m0!3e2

编辑:因为我必须在第二个网址中手动拖动路线,所以中间标记的坐标与第一个网址的坐标不完全相同;这种差异可以忽略不计。

这些URL的起始部分看起来非常明显,但是数据参数对我来说仍然不清楚(没有它的路线不正确)。我尝试了Google Maps API,但这些文件会返回XML或JSON文件,但我只需要使用相应的网址,我也可以使用Google地图的网络界面。

如何将第一个URL转换为第二个?

2 个答案:

答案 0 :(得分:2)

根据this site,在旧的网址方案中,应该有3种方式来添加一个起点或路线,它们是:

  

https://www.google.com/maps?dirflg=w&saddr=51.804323,5.8061076&daddr=51.8059489,5.7971745+to:51.8095767,5.8032703

     

https://www.google.com/maps?dirflg=w&saddr=51.804323,5.8061076&daddr=51.8095767,5.8032703&mrad=51.8059489,5.7971745

     

https://www.google.com/maps?dirflg=w&saddr=51.804323,5.8061076&daddr=51.8095767,5.8032703&via=51.8059489,5.7971745

但似乎他们放弃了对mrad和via的支持。并且对于使用,它显示地址,好像它将显示在新的url方案中。

对于新的URL方案..它似乎没有很多文档,所以我不确定谷歌是否希望你玩它。但是......这就是:如何用新方案来做。

根据this blog post

enter image description here

!xx是一个分隔符。看看你的网址:

data=
!4m9
!4m8
!1m5
!3m4
!1m2
!1d5.7971218
!2d51.8060231
!3s0x47c7061292e15b39:0x4d7bcd7484c71cf3
!1m0
!3e2

目前还不清楚它在做什么,但是,至少我们在!1d!2d字段中看到你的via lat和lng; 同样,十六进制格式的!3s看起来像某种lat / lng,可能是搜索区域。这就是dec 5172109373901724473:5583282063383403763

中的样子

嗯,简而言之,只需更改!1d!2d字段,它似乎工作正常。像这样: https://www.google.nl/maps/dir/51.804323,5.8061076/51.8095767,5.8032703/@51.8769532,5.8550939,7.58z/data=!4m9!4m8!1m5!3m4!1m2!1d5.871218!2d52.8060231!3s0x47c7061292e15b39:0x4d7bcd7484c71cf3!1m0!3e2

答案 1 :(得分:2)

因此,经过很长一段时间试图弄清楚URL方案是如何工作的,我终于想出了它是如何工作的(对于方向界面)。

网址包含以下步骤:

  1. 您从“https://www.google.nl/maps/dir/
  2. 开始
  3. 接下来是“[LAT],[LONG]”形式的起始坐标,相同格式的中间航点的坐标,然后是终点的坐标。所有这些坐标都用“/”字符分隔。
  4. 接着是“@ [LAT],[LONG],[ZOOM] /”,其中LAT LONG是视图框的坐标,ZOOM是缩放级别(更低意味着缩小更多)。
  5. 接着是“data =”,然后是“!4m [(5x + 4 + y)]!4m [(5x + 3 + y)]!”其中x是VIA点的数量,y是路线中的中间航点的数量。因此,如果你有一条从A到D的路线,中间目的地为B和C,VIA点为Q,W和R,你有x = 3和y = 2所以你得到字符串“!4m21!4m20”
  6. 接下来我们获得所有VIA积分。这在以下方案中完成:您追加“!1m [(5x)]”,其中x是当前航点与下一航点之间的VIA点数。所以“!1m5 ...... [数据] ......!1m0”意味着在起点和第一航点之间有一个VIA点,在第一个航点和终点之间没有VIA点。每个“!1m [(5x)]”之后是“!1d [LONG]!2d [LAT]!3s [COORDINATE]”的x个实例。我不完全确定COORDINATE的作用,但必须采用格式“0x [HEX]:0x [HEX]”,其中HEX是十六进制数;我只是为了这个数字0。这似乎适用于我的所有测试用例,似乎没有任何影响。
  7. 然后是“!1m0”。我认为有必要指出在最后一个航路点(终点)之后没有更多的VIA点,这是无用的信息,但仍然需要。
  8. 最后,我们得到最后一个看起来像“!3e [n]”的参数,其中n是一个离散变量来表示导航类型:n = 0用于驾车,n = 1用于骑自行车,n公共交通工具= 2步行,n = 3。
  9. 这主要是因为我通过无情地测试它而找到了关于URL方案的内容。您可以添加更多参数,但这需要更多的工作测试。

    最后,我将我的实现包含在将具有0个或更多航点和0个或更多VIA点的URL转换为仅包含VIA点的URL。如果您发现任何错误,请随时告诉我,以便我可以解决它们。

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.print("Enter URL: ");
        String originalURL = br.readLine();
    
        //get start of URL
        String start = "https://www.google.nl/maps/dir/";
    
        //get navigation type
        String type = "!3e1";
        Matcher t = getMatcher(originalURL, "!3e\\d");
        if (t.find()) {
            type = t.group();
        }
    
        //get viewbox parameter
        Matcher v = getMatcher(originalURL, "@[-]?[\\d]+\\.[\\d]+,[-]?[\\d]+.[\\d]+,[-]?[\\d]+[[.]+[\\d]+]*z");
        v.find();
        String viewbox = v.group();
    
        //get order of points when using VIA
        String data = originalURL.substring(originalURL.indexOf("/data=") + 6);
        ArrayList<String> order = new ArrayList<>();
        Matcher o = getMatcher(data, "!1m[\\d]+");
        while (o.find()) {
            order.add(o.group());
        }
        if (order.size() > 0) {
            //remove the last element which is always m0 as this should not be
            //displayed in the VIA-list
            order.remove(order.size() - 1);
        }
    
        //!1m2 does not represent the order but indicates that coordinates that are coming up
        order.removeIf(a -> a.equals("!1m2"));
    
        //get coordinates of via-points
        ArrayList<String> originalViaPoints = new ArrayList<>();
        Matcher c = getMatcher(data, "!1d[-]?[\\d]+.[\\d]+!2d[-]?[\\d]+.[\\d]+");
        while (c.find()) {
            String[] g = c.group().substring(3).split("!2d");
            originalViaPoints.add(g[1] + "," + g[0]);
        }
    
        //get coordinates of start, end and intermediate points
        originalURL = originalURL.substring(0, v.start());
        ArrayList<String> waypoints = new ArrayList<>();
        Matcher p = getMatcher(originalURL, "[-]?[\\d]+\\.[\\d]+,[-]?[\\d]+.[\\d]+");
        while (p.find()) {
            waypoints.add(p.group());
        }
        //start and end must be displayed seperately
        String bound = waypoints.get(0) + "/" + waypoints.get(waypoints.size() - 1);
    
        //add intermediate waypoints and via-points to a list of VIA points
        ArrayList<String> viaPoints = new ArrayList<>();
    
        //we have VIA points to process
        if (!order.isEmpty()) {
            int via_index = 0;
            int wp_index = 1;
            for (String step : order) {
                int iter = Integer.valueOf(step.substring(3)) / 5;
                for (int i = 0; i < iter; i++) {
                    viaPoints.add(originalViaPoints.get(via_index++));
                }
                viaPoints.add(waypoints.get(wp_index++));
            }
        } else //There are only waypoints in the URL
        {
            for (int i = 1; i < waypoints.size() - 1; i++) {
                viaPoints.add(waypoints.get(i));
            }
        }
    
        //calculate prefix according to the amount of nodes of the via points
        int nodes = viaPoints.size();
        String prefix = "!4m" + (5 * nodes + 4) + "!4m" + (5 * nodes + 3) + "!1m" + (5 * nodes);
    
        //get nodes string
        String viaString = "";
        for (String node : viaPoints) {
            viaString += "!3m4!1m2";
            String[] pieces = node.split(",");
            viaString += "!1d" + pieces[1]; //ALERT: the coordinates are flipped!
            viaString += "!2d" + pieces[0];
            viaString += "!3s0x0:0x0";
        }
    
        String url = start + bound + "/" + viewbox + "/data=" + prefix + viaString + "!1m0" + type;