服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - 基于Qt实现离线瓦片地图下载器

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

2022-08-24 14:14feiyangqingyun C/C++

这篇文章主要介绍了如何通过Qt实现离线瓦片地图下载器,文中的示例代码对我们学习或工作有一定的帮助,感兴趣的可以跟随小编一起学习一下

一、前言

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

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

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

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

二、功能特点

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

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

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

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

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

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

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

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

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

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

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

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

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

三、体验地址

体验地址:https://pan.baidu.com/s/15ZKAlptW-rDcNq8zlzdYLg  提取码:uyes 文件名:bin_map.zip

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

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

四、效果图

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

五、相关代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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离线瓦片地图下载内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/feiyangqingyun/article/details/122486695

延伸 · 阅读

精彩推荐
  • C/C++C++多态的实现机制深入理解

    C++多态的实现机制深入理解

    这篇文章主要介绍了C++多态的实现机制理解的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下...

    fk1213811992021-04-10
  • C/C++详解c/c++赋值函数(重载=号运算符)

    详解c/c++赋值函数(重载=号运算符)

    大家都知道c++里的各种运算符都是用函数实现的,比如=就等号函数,所以当用=给一个对象赋值的时候,实际调用的是=号所对应的=号函数。下面通过本文给...

    小石王11722021-07-01
  • C/C++C++ 实现求小于n的最大素数的实例

    C++ 实现求小于n的最大素数的实例

    这篇文章主要介绍了C++ 实现求小于n的最大素数的实例的相关资料,需要的朋友可以参考下...

    Renyi-Fan13292021-05-13
  • C/C++C语言单链表实现多项式相加

    C语言单链表实现多项式相加

    这篇文章主要为大家详细介绍了C语言单链表实现多项式相加,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    数星星的咚咚咚10402021-06-07
  • C/C++OpenCV利用霍夫变换进行直线检测

    OpenCV利用霍夫变换进行直线检测

    这篇文章主要为大家详细介绍了OpenCV利用霍夫变换进行直线检测,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    长相忆兮长相忆9472021-07-16
  • C/C++VC读配置文件实例

    VC读配置文件实例

    这篇文章主要介绍了VC读配置文件的方法,实例讲述了VC针对文件操作的技巧,需要的朋友可以参考下...

    C语言教程网8912021-02-14
  • C/C++C++ 程序流程结构详解

    C++ 程序流程结构详解

    这篇文章主要介绍了C++程序的程序流程结构以及关系和逻辑运算符讲解,是C++入门学习中的基础知识,需要的朋友可以参考下...

    最亲密如临大敌8092021-12-28
  • C/C++基于C语言扫雷游戏的设计与实现

    基于C语言扫雷游戏的设计与实现

    大家好,本篇文章主要讲的是基于C语言扫雷游戏的设计与实现,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览...

    Code_Cao6322022-07-09