美文网首页
通过拼接实现高清地图的下载-高德-java实现

通过拼接实现高清地图的下载-高德-java实现

作者: 有时右逝 | 来源:发表于2020-09-11 16:48 被阅读0次

    背景

    地图功能是每个系统必备的功能之一,通常可以使用百度地图和高德地图来实现在线地图展示。
    但是将展示的地图下载到本地则是一件有挑战的事情。

    运行环境

    mac系统
    java 1.8
    其中标注的坐标原始数据是百度坐标,因此代码中进行了转换。

    参考代码

    参考代码

    需求

    某一天领导找我,说客户提出需要将系统里的在线地图下载到本地浏览。利用搜索引擎,找到一些思路,
    前端思路: 在线地图是canvas绘制的,可以将canvas转图片存储到本地。
    后端思路: 高德和百度均提供静态地图接口,但是存在尺寸限制、标注限制。因此需要程序自己切割下载,拼接地图。

    作为一名java后端开发,当然是选择后端解决方案。

    这里先说下我的需求:我需要一份地图,是杭州滨江地区的,地图需要标注一些位置。这些位置超过10个。因此无法直接使用高德地图接口下载。

    实现过程

    以高德地图为例,

    首先请注册高德开发者,申请密钥,如此才可以调用接口

    使用到的接口地址 https://lbs.amap.com/api/webservice/guide/api/staticmaps

    
        public final static String uurl = "http://restapi.amap.com/v3/staticmap?zoom=16&size=1024*1024&scale=1";// 高德地图api
    
            key = "你的密钥";
    
    

    解释下这个接口的参数。
    zoom 地图的缩放比。
    size 地图的尺寸
    scale 地图清晰度 1表示非高清。2表示高清。如果设定值为2 则 zoom将自动成为17 size将变成 2048

    由于下载高清地图,非常慢,以及内存容易溢出,因此这里修改非高清的参数。

    直接想要结果的,可以下载一份代码,自己跑一次

    这里先解释下思路:
    1、经纬度切割。 先确定你需要下载地图的经纬度范围。需要2个点即可。
    地图左上角、地图右下角。
    例如这里我的坐标是杭州滨江区。

            String top = "120.123754,30.232441";
            String end = "120.243745,30.141632";
    

    你需要决定将你的地图切割成多少块。
    这里我设定步长是

    // 按照0.01为步长,循环计算出所需获得的图片中心位置坐标
            int countX = (int) ((ex - sx) / 0.010999);// 如果ex - sx = 0,说明只有一列
            int countY = (int) ((sy - ey) / 0.00955);// 如果sy - ey = 0,说明只有一行
    

    其中0.010999 表示 横向的地图中心距离 0.00955 表示竖向的地图中心距离。

    这2个值 不能随意修改。和缩放比、清晰度存在关联。

    2、下载地图
    设定了步长后即可运行程序,下载地图碎片。下载有可能失败,请多次执行,直到数目完整。

    3、横向切割图片

    下载的地图碎片,多数情况存在重叠部分,因此需要切割。切割的规则是 第一张图片保持完整,从第二张图片开始切割重叠的部分,只保留不重叠的图片。因此需要确定起点是关键。

     for (int i = 1, j = 0; i <= allPng; i++) {
                System.out.println("正在截取");
                if (i == (j * count[1] + 1)) {
                    cutImage(path + "/getMaps/" + i + ".png", path + "/cuttedMaps/" + i + ".png", 0, 0, 1024, 1024);
                    j++;
                } else {
                    cutImage(path + "/getMaps/" + i + ".png", path + "/cuttedMaps/" + i + ".png", 1024 - 1024, 0, 1024,
                            1024);
                }
            }
    

    上图中的 1024-1024 表示计算切割的起点位置。

    这个重叠值如何确定,拿 1.png和2.png 对比确定。在打开ps工具手动数数偏差。 如果你重叠的像素是10 则这里应当是 10

    这里因为我给的步长十分精确,重叠为0 因此切割的起点位置从0开始。

    3、竖向切割

    和横向是同理的。需要人工通过ps确定 重叠的像素是多少.

    横向是比较第一张和第二张图片,但是竖向则需要 比较 第一列的第一张和 第二列的第一张图片。

    System.out.println("开始对图片进行第二次截取...");
            File f1 = new File(path + File.separator+"mergedMaps");
            String[] mergedImgs = f1.list();
            for (int i = 1; i <= mergedImgs.length; i++) {
                if (i != mergedImgs.length) {
                    cutImage(path + File.separator+"mergedMaps"+File.separator + i + ".png", path + "/cutteddMaps/" + i + ".png", 0, 0,
                            (count[1] - 1) * 1024 + 1024, 1024);
                } else {
                    cutImage(path + File.separator+"mergedMaps"+File.separator + i + ".png", path + "/cutteddMaps/" + i + ".png", 0, 0,
                            (count[1] - 1) * 1024 + 1024, 1024);
                }
            }
    

    4、合成

    正确设定步长、横竖的切割起点,即可正确拼接出想要的图片了。

    下载图片可能不完整,可以重复多次执行,

    以下是程序执行的效果。由于是16的缩放比,所以图是很大的。大小是 28MB

    image.png

    问题

    1、拼接的图片,出现错位?
    重叠值错误。请重新设定。
    2、图片没有重叠?
    步长太大,请重新设定。
    3、标注不完整,破碎
    这个问题非常常见,本人也卡在这里。主要原因是标注的点,正好处于分割线上,然后分割线存在重叠部分,切割的时候导致标注不完整。
    这里解决方案主要是,不断改变步长,确保地图水平恰好无缝可以拼接。也就是0重叠,但是线条吻合。传说中的完美分割,本人采用的就是该方案。
    另外一个就是 ,位于标注上的点,坐标进行偏移,确保位于重叠的右侧。这样不会被切割。也需要多次人工尝试。

    4、高清版本

    高清版本的参数和非高清的差异较大。主要是确保是 高清版本的地图碎片尺寸是固定的 2048

    而非高清的是 1024 因此需要注意修改参数。

    5、切割和合并提示文件不存在
    下载的地图不完整,多次运行程序即可。因为高德的该接口似乎很奇怪,经常会失败。

    代码下载

    提供2份代码

    滨江非高清版本
    https://download.csdn.net/download/douniwan123654/12838090

    滨江高清版本
    稍后发布,

    相关文章

      网友评论

          本文标题:通过拼接实现高清地图的下载-高德-java实现

          本文链接:https://www.haomeiwen.com/subject/rnxbektx.html