zoukankan      html  css  js  c++  java
  • 基于OpenStreetMap计算驾车距离(Java)

    最近公司有个项目需要计算6000个点之间的驾车距离,第一时间想到的是利用Google的Distance Matrix API,但是免费Key每天只能计算2500个元素(元素 = 起点数量 * 终点数量),收费的话每1000个元素需要0.5刀,6000个点(接近3600w条边)基本就是1.8w刀。。。而且限制颇多,数据只允许本地缓存一个月,QPS限定100,每天查询元素上限10w,计算完客户早走了,基本不可用。

    然后就想到了开(免)源(费)的OpenStreetMap(简称OSM),OSM是一个开源的地图库,可以在http://download.geofabrik.de/下载各国家地图包,数据还是比较全的。

    有了地图数据,还需要一个寻路计算框架,找到了一个免费的库osm2po(http://osm2po.de/)

    下载osm2po以后修改demo.sh或demo.bat的地图路径为你自己的pbf文件地址:

    执行以后会启动一个Http服务器,默认地址http://localhost:8888/Osm2poService,打开就能看见地图界面了:

     
    随便寻个路,效果还可以,国内路线看起来和高德地图差不多
     
    Http访问方式只提供了这么些参数可以使用,并不是很完善,没有distance的选项,而且http的访问方式效率也不高,最好还是用Java API
     
    计算两点间距离可以直接用官网示例的DefaultRouter,很简单。
    多点距离在gis.stackexchange.com发现作者说有提供Distance Matrix API,emmm不错,看了下jar包的确是有一个TspDefaultMatrix的类,直接上代码:
    public static void main(String[] args) throws Exception {
        File graphFile = new File(args[0]);
        Graph graph = new Graph(graphFile);
    
        // Somewhere in Graph
        LatLon source = new LatLon(32.0452460989,118.8318873038);
        LatLon target = new LatLon(31.8870800000,118.8300200000);
    
        // additional params for DefaultRouter
        Properties params = new Properties();
        params.setProperty("findShortestPath", "true");
        params.setProperty("ignoreRestrictions", "false");
        params.setProperty("ignoreOneWays", "false");
        params.setProperty("heuristicFactor", "0.0"); // 0.0 Dijkstra, 1.0 good A*
    
        int[] vertexIds = findClosestVertexIds(graph, source, target);
        Log log = new Log(Log.LEVEL_DEBUG).addLogWriter(new LogConsoleWriter());
        TspDefaultMatrix matrix = new TspDefaultMatrix(graph, vertexIds, Float.MAX_VALUE, log, params);
    
        float[][] distances = matrix.getCosts();
        for (int i = 0; i < distances.length; i++) {
            for (int j = 0; j < distances.length; j++) {
                System.out.println(distances[i][j]);
            }
        }
    
        graph.close();
    }
    
    public static int[] findClosestVertexIds(Graph graph, LatLon... latLons) {
        int[] vertexIds = new int[latLons.length];
        for (int i = 0; i < latLons.length; i++) {
            // if failed, return -1
            vertexIds[i] = graph.findClosestVertexId(
                    (float) latLons[i].getLat(), (float) latLons[i].getLon());
        }
        return vertexIds;
    }

    算出来的结果21.01734公里,和高德地图完全吻合

    公司项目第一个使用的地方是一个鸟不拉屎的非洲小国家,除了主干道基本都是人踩出来的小路,固定地点寻路成功率也达到了83%以上,失败的情况一般谷歌地图也没路。国内道路好太多,估计95%成功率是OK的。

    实际测试1700个点,地图大小30M,生成有效数据240w条,堆内存使用6.5g,只用了60秒。
     
    ps:距离相近的点,得到的地图块id可能相同,传入TspDefaultMatrix会error,要做一个去重的映射处理。
  • 相关阅读:
    赤羽西二丁目14号
    080520 雨 大风
    游泳的梦
    poj1088 滑雪 解题报告
    sgu 183. Painting the balls 动态规划 难度:3
    POJ 1947 Rebuilding Roads 树形dp 难度:2
    POJ 2566 Bound Found 尺取 难度:1
    hdu4800 Josephina and RPG 解题报告
    POJ 2057 The Lost Home 树形dp 难度:2
    HDU 4791 Alice's Print Service 思路,dp 难度:2
  • 原文地址:https://www.cnblogs.com/kosho/p/9191602.html
Copyright © 2011-2022 走看看