• 1324阅读
  • 0回复

Qt编写地图综合应用51-离线瓦片地图下载 [复制链接]

上一主题 下一主题
离线liudianwu
 

图酷模式  只看楼主 倒序阅读 楼主  发表于: 2022-01-14
## 一、前言
写这个离线地图下载器的初衷,就是为了方便自己的几个需要离线地图的程序,客户需求,既然地图程序已经可以支持离线地图,那如何获取到这些离线瓦片地图文件是个关键,而且这是这个功能的关键,拿到这些一张张的瓦片图片文件,才能根据js函数绘制组合成离线地图。

网上其实有很多各种各样的离线地图下载器,大部分都是要收费的,免费的要么是限制了下载的瓦片数量或者级别,要么是下载的瓦片图打上了水印,看起来很难看,由于经常需要用到离线地图,摆脱这个限制,特意花了点时间重新研究了瓦片地图的原理,做了个离线地图下载器,其实瓦片地图下载没有那么复杂,其实就是从开放的几个服务器地址组建要请求的瓦片地图的地址,发送请求以后会自动将图片返回给你,你只需要拿到图片数据保存成图片即可。

瓦片地图下载流程步骤如下:
1. 获取可视区域或者行政区域的范围。
2. 拿到区域的左下角右上角经纬度坐标。
3. 根据层级数计算对应层级的瓦片数。
4. 自动生成下载瓦片地图的地址并发出请求。
5. 解析收到的数据保存成图片。
6. 更新对应界面的下载数量和进度。
7. 可选择对应保存的目录、全选层级、中途停止下载等。
8. 可选择是下载街道图还是卫星图等。

## 二、功能特点
1. 多线程同步下载多级别瓦片地图,不卡界面。
2. 内置多个离线地图下载请求地址,自动随机选择一个发送请求。
3. 下载地图类型同时支持街道图和卫星图。
4. 自动计算可视区域或者行政区域的下载瓦片数量。
5. 下载的级别可以自定义范围和选择。
6. 每个瓦片下载完成都发送信号通知,参数包括下载用时。
7. 可设置下载最大超时时间,超过了则丢弃跳到下一个下载任务。
8. 实时显示下载进度,以及当前级别已经下载的瓦片数和总瓦片数。
9. 下载过程中可以停止下载,下载完成自动统计总用时。
10. 内置经纬度和屏幕坐标互相转换函数。
11. 目前支持百度地图,其他地图比如谷歌地图、腾讯地图、高德地图可以定制。
12. 函数接口友好和统一,使用简单方便,就一个类。
13. 支持任意Qt版本、任意系统、任意编译器。

## 三、体验地址
1. 体验地址:[https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A](https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A) 提取码:o05q  文件名:bin_map.zip
2. 国内站点:[https://gitee.com/feiyangqingyun](https://gitee.com/feiyangqingyun)
3. 国际站点:[https://github.com/feiyangqingyun](https://github.com/feiyangqingyun)
4. 个人主页:[https://blog.csdn.net/feiyangqingyun](https://blog.csdn.net/feiyangqingyun)
5. 知乎主页:[https://www.zhihu.com/people/feiyangqingyun/](https://www.zhihu.com/people/feiyangqingyun/)

## 四、效果图




## 五、相关代码
```c++
void MapDownload::download(const QString &path, int mapType, int downType, int xmin, int xmax, int ymin, int ymax, int zoom)
{
    for (int x = xmin; x <= xmax; x++) {
        for (int y = ymin; y <= ymax; y++) {
            if (stopped) {
                return;
            }

            QString url = getUrl(mapType, downType, x, y, zoom);
            QString dirName = QString("%1/%2/%3/").arg(path).arg(zoom).arg(x);
            QString fileName = QString("%1.jpg").arg(y);
            downloadImage(url, dirName, fileName, zoom);
        }
    }
}

void MapDownload::downloadBaiDu(const QString &path, int downType, int xmin, int xmax, int ymin, int ymax, int zoom)
{
    download(path, 0, downType, xmin, xmax, ymin, ymax, zoom);
}

void MapDownload::downloadTian(const QString &path, int downType, int xmin, int xmax, int ymin, int ymax, int zoom)
{
    download(path, 3, downType, xmin, xmax, ymin, ymax, zoom);
}

void MapDownload::downloadGoogle(const QString &path, int downType, int xmin, int xmax, int ymin, int ymax, int zoom)
{
    download(path, 4, downType, xmin, xmax, ymin, ymax, zoom);
}

void MapDownload::downloadImage(const QString &url, const QString &dirName, const QString &fileName, int zoom)
{
    if (url.isEmpty()) {
        return;
    }

    //启动计时
    QElapsedTimer time;
    time.start();

    //先判断文件夹是否存在,不存在则新建
    QDir dir(dirName);
    if (!dir.exists()) {
        dir.mkpath(dirName);
    }

    //局部的事件循环,不卡主界面
    QEventLoop eventLoop;

    //设置超时 5.15开始自带了超时时间函数 默认30秒
#if (QT_VERSION >= QT_VERSION_CHECK(5,15,0))
    manager->setTransferTimeout(timeout);
#else
    QTimer timer;
    connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
    timer.setSingleShot(true);
    timer.start(timeout);
#endif

    QNetworkReply *reply = manager->get(QNetworkRequest(QUrl(url)));
    connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
    eventLoop.exec();

    bool error = false;
    if (reply->bytesAvailable() > 0 && reply->error() == QNetworkReply::NoError) {
        //读取所有数据保存成文件
        QByteArray data = reply->readAll();
        QFile file(dirName + fileName);
        if (file.open(QFile::WriteOnly | QFile::Truncate)) {
            file.write(data);
            file.close();
        }
    } else {
        //可以自行增加下载失败的统计
        error = true;
        qDebug() << TIMEMS << "下载出错" << reply->errorString();
    }

    reply->deleteLater();
    int useTime = time.elapsed();
    emit finsh(url, fileName, zoom, useTime, error);
}
```
4条评分好评度+1贡献值+1金钱+10威望+1
20091001753 好评度 +1 - 2022-01-15
20091001753 贡献值 +1 - 2022-01-15
20091001753 威望 +1 - 2022-01-15
20091001753 金钱 +10 - 2022-01-15
欢迎关注微信公众号:Qt实战/Qt入门和进阶(各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发) QQ:517216493  WX:feiyangqingyun  QQ群:751439350
快速回复
限100 字节
 
上一个 下一个