基于Qt實現(xiàn)離線瓦片地圖下載器
一、前言
寫這個離線地圖下載器的初衷,就是為了方便自己的幾個需要離線地圖的程序,客戶需求,既然地圖程序已經(jīng)可以支持離線地圖,那如何獲取到這些離線瓦片地圖文件是個關(guān)鍵,而且這是這個功能的關(guān)鍵,拿到這些一張張的瓦片圖片文件,才能根據(jù)js函數(shù)繪制組合成離線地圖。
網(wǎng)上其實有很多各種各樣的離線地圖下載器,大部分都是要收費的,免費的要么是限制了下載的瓦片數(shù)量或者級別,要么是下載的瓦片圖打上了水印,看起來很難看,由于經(jīng)常需要用到離線地圖,擺脫這個限制,特意花了點時間重新研究了瓦片地圖的原理,做了個離線地圖下載器,其實瓦片地圖下載沒有那么復(fù)雜,其實就是從開放的幾個服務(wù)器地址組建要請求的瓦片地圖的地址,發(fā)送請求以后會自動將圖片返回給你,你只需要拿到圖片數(shù)據(jù)保存成圖片即可。
瓦片地圖下載流程步驟如下:
- 獲取可視區(qū)域或者行政區(qū)域的范圍。
- 拿到區(qū)域的左下角右上角經(jīng)緯度坐標。
- 根據(jù)層級數(shù)計算對應(yīng)層級的瓦片數(shù)。
- 自動生成下載瓦片地圖的地址并發(fā)出請求。
- 解析收到的數(shù)據(jù)保存成圖片。
- 更新對應(yīng)界面的下載數(shù)量和進度。
- 可選擇對應(yīng)保存的目錄、全選層級、中途停止下載等。
- 可選擇是下載街道圖還是衛(wèi)星圖等。
二、功能特點
多線程同步下載多級別瓦片地圖,不卡界面。
內(nèi)置多個離線地圖下載請求地址,自動隨機選擇一個發(fā)送請求。
下載地圖類型同時支持街道圖和衛(wèi)星圖。
自動計算可視區(qū)域或者行政區(qū)域的下載瓦片數(shù)量。
下載的級別可以自定義范圍和選擇。
每個瓦片下載完成都發(fā)送信號通知,參數(shù)包括下載用時。
可設(shè)置下載最大超時時間,超過了則丟棄跳到下一個下載任務(wù)。
實時顯示下載進度,以及當前級別已經(jīng)下載的瓦片數(shù)和總瓦片數(shù)。
下載過程中可以停止下載,下載完成自動統(tǒng)計總用時。
內(nèi)置經(jīng)緯度和屏幕坐標互相轉(zhuǎn)換函數(shù)。
目前支持百度地圖,其他地圖比如谷歌地圖、騰訊地圖、高德地圖可以定制。
函數(shù)接口友好和統(tǒng)一,使用簡單方便,就一個類。
支持任意Qt版本、任意系統(tǒng)、任意編譯器。
三、體驗地址
體驗地址:https://pan.baidu.com/s/15ZKAlptW-rDcNq8zlzdYLg 提取碼:uyes 文件名:bin_map.zip
國內(nèi)站點:https://gitee.com/feiyangqingyun
國際站點:https://github.com/feiyangqingyun
四、效果圖

五、相關(guān)代碼
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);
}
//局部的事件循環(huán),不卡主界面
QEventLoop eventLoop;
//設(shè)置超時 5.15開始自帶了超時時間函數(shù) 默認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) {
//讀取所有數(shù)據(jù)保存成文件
QByteArray data = reply->readAll();
QFile file(dirName + fileName);
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
file.write(data);
file.close();
}
} else {
//可以自行增加下載失敗的統(tǒng)計
error = true;
qDebug() << TIMEMS << "下載出錯" << reply->errorString();
}
reply->deleteLater();
int useTime = time.elapsed();
emit finsh(url, fileName, zoom, useTime, error);
}
到此這篇關(guān)于基于Qt實現(xiàn)離線瓦片地圖下載器的文章就介紹到這了,更多相關(guān)Qt離線瓦片地圖下載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++高性能服務(wù)器框架之協(xié)程調(diào)度模塊
這篇文章主要介紹了C++高性能服務(wù)器框架中的協(xié)程調(diào)度模塊,文中通過代碼示例介紹的非常詳細,對我們的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-06-06
C++異步數(shù)據(jù)交換實現(xiàn)方法介紹
這篇文章主要介紹了C++異步數(shù)據(jù)交換實現(xiàn)方法,異步數(shù)據(jù)交換,除了阻塞函數(shù) send() 和 recv() 之外,Boost.MPI 還支持與成員函數(shù) isend() 和 irecv() 的異步數(shù)據(jù)交換2022-11-11
C++ 中約瑟夫環(huán)替換計數(shù)器m(數(shù)組解決)
這篇文章主要介紹了C++ 中約瑟夫環(huán)替換計數(shù)器m(數(shù)組解決)的相關(guān)資料,需要的朋友可以參考下2017-05-05

