基于Qt实现离线瓦片地图下载器

 更新时间:2022年01月14日 15:21:51   作者:feiyangqingyun  
这篇文章主要介绍了如何通过Qt实现离线瓦片地图下载器,文中的示例代码对我们学习或工作有一定的帮助,感兴趣的可以跟随小编一起学习一下

一、前言

写这个离线地图下载器的初衷,就是为了方便自己的几个需要离线地图的程序,客户需求,既然地图程序已经可以支持离线地图,那如何获取到这些离线瓦片地图文件是个关键,而且这是这个功能的关键,拿到这些一张张的瓦片图片文件,才能根据js函数绘制组合成离线地图。

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

瓦片地图下载流程步骤如下:

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

二、功能特点

多线程同步下载多级别瓦片地图,不卡界面。

内置多个离线地图下载请求地址,自动随机选择一个发送请求。

下载地图类型同时支持街道图和卫星图。

自动计算可视区域或者行政区域的下载瓦片数量。

下载的级别可以自定义范围和选择。

每个瓦片下载完成都发送信号通知,参数包括下载用时。

可设置下载最大超时时间,超过了则丢弃跳到下一个下载任务。

实时显示下载进度,以及当前级别已经下载的瓦片数和总瓦片数。

下载过程中可以停止下载,下载完成自动统计总用时。

内置经纬度和屏幕坐标互相转换函数。

目前支持百度地图,其他地图比如谷歌地图、腾讯地图、高德地图可以定制。

函数接口友好和统一,使用简单方便,就一个类。

支持任意Qt版本、任意系统、任意编译器。

三、体验地址

体验地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取码:o05q 文件名:bin_map.zip

国内站点:https://gitee.com/feiyangqingyun

国际站点:https://github.com/feiyangqingyun

四、效果图

五、相关代码

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);
}

到此这篇关于基于Qt实现离线瓦片地图下载器的文章就介绍到这了,更多相关Qt离线瓦片地图下载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 怎么用C++提取任意一张图片的特征(从内存读取数据)

    怎么用C++提取任意一张图片的特征(从内存读取数据)

    这篇文章主要介绍了用C++提取任意一张图片的特征(从内存读取数据)的相关资料,需要的朋友可以参考下
    2017-05-05
  • c语言中static修饰函数的方法及代码

    c语言中static修饰函数的方法及代码

    在本篇内容里小编给大家分享的是一篇关于c语言中static如何修饰函数的知识点内容,有需要朋友们可以跟着学习下。
    2021-10-10
  • C++begin和end运算符的返回迭代器的类型如何判断?

    C++begin和end运算符的返回迭代器的类型如何判断?

    今天小编就为大家分享一篇关于C++begin和end运算符的返回迭代器的类型如何判断?,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • C语言开发实现贪吃蛇游戏

    C语言开发实现贪吃蛇游戏

    这篇文章主要为大家详细介绍了C语言开发实现贪吃蛇游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • C++中的long long与__int64

    C++中的long long与__int64

    这篇文章主要介绍C++中的long long与__int64,在C++ Primer当中提到的64位的int只有long long,但是在实际各种各样的C++编译器当中,64位的int一直有两种标准.一种是long long,还有一种是__int64,非主流的VC甚至还支持_int64,下面文章将介绍具体内容,需要的朋友可以参考一下
    2021-11-11
  • C语言开发之归并排序详解及实例

    C语言开发之归并排序详解及实例

    这篇文章主要介绍了 C语言开发之归并排序详解及实例的相关资料,需要的朋友可以参考下
    2017-03-03
  • C++数组指针和二维数组详情

    C++数组指针和二维数组详情

    这篇文章主要介绍了C++数组指针和二维数组,指针数组和二维数组在应用中常用于函数传参,下面我们就来看看指针数组和二维数组在应用中的具体使用吧,需要的朋友可以参考一下
    2021-10-10
  • C++ 风靡一时的连连看游戏的实现流程详解

    C++ 风靡一时的连连看游戏的实现流程详解

    游戏“连连看”是源自台湾的桌面小游戏,自从流入大陆以来风靡一时,也吸引众多程序员开发出多种版本的“连连看”。这其中,顾芳编写的“阿达连连看”以其精良的制作广受好评,这也成为顾方“阿达系列软件”的核心产品。并于2004年,取得国家版权局的计算机软件登记证书
    2021-11-11
  • 详解C语言中的rename()函数和remove()函数的使用方法

    详解C语言中的rename()函数和remove()函数的使用方法

    这篇文章主要介绍了详解C语言中的rename()函数和remove()函数的使用方法,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • Linux环境g++编译GDAL动态库操作方法

    Linux环境g++编译GDAL动态库操作方法

    下面小编就为大家带来一篇Linux环境g++编译GDAL动态库操作方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05

最新评论