Qt compilation of map comprehensive application 51 - offline Tile Map Download

Posted by servo on Fri, 14 Jan 2022 02:26:10 +0100

1, Foreword

The original intention of writing this offline map Downloader is to facilitate several programs that need offline maps and customer needs. Since the map program can support offline maps, how to obtain these offline tile map files is the key, and this is the key to this function. Get these tile picture files one by one, Can be drawn and combined into an offline map according to js function.

In fact, there are many kinds of offline map downloaders on the Internet, most of which are charged. The free ones either limit the number or level of tiles downloaded, or the downloaded tiles are watermarked, which looks ugly. Because offline maps are often needed, I got rid of this restriction and took some time to re study the principle of tile maps, An offline map Downloader is made. In fact, tile map download is not so complex. In fact, it is to build the address of the tile map to be requested from several open server addresses. After sending the request, the picture will be automatically returned to you. You only need to get the picture data and save it as a picture.

The steps of tile map download process are as follows:

  1. Get the range of visual area or administrative area.
  2. Get the latitude and longitude coordinates of the lower left corner and upper right corner of the area.
  3. Calculate the number of tiles of the corresponding level according to the level.
  4. Automatically generate the address to download the tile map and make a request.
  5. Parse the received data and save it as a picture.
  6. Update the download quantity and progress of the corresponding interface.
  7. You can select the corresponding saved directory, select all levels, stop downloading halfway, etc.
  8. You can choose whether to download street map or satellite map, etc.

2, Functional features

  1. Multi thread synchronous download of multi-level tile map without card interface.
  2. Multiple offline map download request addresses are built in, and one sending request is automatically selected at random.
  3. The download map type supports both street map and satellite map.
  4. Automatically calculate the number of downloaded tiles in the visual area or administrative area.
  5. The download level can be customized and selected.
  6. After each tile is downloaded, Chengdu sends a signal notification, and the parameters include the download time.
  7. The maximum download timeout can be set. If it exceeds the timeout, it will be discarded and jump to the next download task.
  8. The download progress, the number of tiles downloaded at the current level and the total number of tiles are displayed in real time.
  9. The download can be stopped during the download process, and the total time will be counted automatically after the download is completed.
  10. Built in longitude and latitude and screen coordinate mutual conversion function.
  11. At present, baidu maps are supported. Other maps such as Google maps, Tencent maps and Gaode maps can be customized.
  12. The function interface is friendly and unified, simple and convenient to use, just one class.
  13. Support any Qt version, any system and any compiler.

3, Experience address

  1. Experience address: https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A Extraction code: o05q file name: bin_map.zip
  2. Domestic sites: https://gitee.com/feiyangqingyun
  3. International sites: https://github.com/feiyangqingyun
  4. Personal homepage: https://blog.csdn.net/feiyangqingyun
  5. Zhihu homepage: https://www.zhihu.com/people/feiyangqingyun/

4, Renderings

5, Related code

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

    //Start timing
    QElapsedTimer time;
    time.start();

    //First judge whether the folder exists. If it does not exist, create a new folder
    QDir dir(dirName);
    if (!dir.exists()) {
        dir.mkpath(dirName);
    }

    //The local event cycle does not block the main interface
    QEventLoop eventLoop;

    //Set the timeout from 5.15. The timeout function comes with a default of 30 seconds
#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) {
        //Read all data and save it as a file
        QByteArray data = reply->readAll();
        QFile file(dirName + fileName);
        if (file.open(QFile::WriteOnly | QFile::Truncate)) {
            file.write(data);
            file.close();
        }
    } else {
        //You can increase the statistics of download failure by yourself
        error = true;
        qDebug() << TIMEMS << "Download error" << reply->errorString();
    }

    reply->deleteLater();
    int useTime = time.elapsed();
    emit finsh(url, fileName, zoom, useTime, error);
}

Topics: Qt