Select to view content in your preferred language

ArcGIS Runtime Offline Mapping using qt c++ widgets

138
0
2 weeks ago
Labels (1)
KailashSubramaniyan
New Contributor

Hello everyone,

I've developed an application in Qt using the ArcGIS Runtime SDK. While the application functions well in online mode, I now require it to operate offline.

After conducting some research on offline mapping, I began constructing the application using the guidance provided in this reference: https://developers.arcgis.com/qt/cpp/sample-code/generate-offline-map/ .

I have successfully executed the application and observed several files generated in the designated location. However, I am uncertain whether these files are the correct ones for offline map functionality (please see the attached screenshot of the folder contents).

I have included my code for your review. Kindly advise on any mistakes I may have made.

Additionally, the sample code appears to only support creating offline maps for specific geometries (extents). Is it feasible to display/load maps offline based on regions or to encompass entire countries, incorporating both raster and vector files?

I am working with ArcGIS Free Developer License. Will offline mode works with ArcGIS Free License?

Thank you!

// H FILES

#ifndef OFFLINE_MAP_GENERATION_H
#define OFFLINE_MAP_GENERATION_H

#include <QWidget>
#include <QTemporaryDir>

#define DELHI_LAT 28.7041
#define DELHI_LON 77.1025

#define BENGALURU_LAT 12.9716
#define BENGALURU_LON 77.5946

#define CHENNAI_LAT 13.0843
#define CHENNAI_LON 80.2705

namespace Esri::ArcGISRuntime
{
class Map;
class MapGraphicsView;
class Portal;
class PortalItem;
class OfflineMapTask;
class Basemap;
class PortalItem;
class Portal;
class Error;
class GenerateOfflineMapJob;
class GenerateOfflineMapParameters;
class Envelope;
class Viewpoint;
class SpatialReference;
class Point;
class GeometryEngine;
} // namespace Esri::ArcGISRuntime

namespace Ui {
class offline_map_generation;
}

class offline_map_generation : public QWidget
{
Q_OBJECT

public:
explicit offline_map_generation(QWidget *parent = nullptr);
~offline_map_generation();

private slots:
void slot_portal_error(const Esri::ArcGISRuntime::Error& error);
void slot_portal_item_error(const Esri::ArcGISRuntime::Error& error);
void onGenerateOfflineMapParametersCompleted(const QUuid& taskId, const Esri::ArcGISRuntime::GenerateOfflineMapParameters& parameters);
void slot_map_offline_generator_job_has_error(const Esri::ArcGISRuntime::Error& error);
void slot_offline_map_generator_error_occured(const Esri::ArcGISRuntime::Error& error);
void on_pushButton_offlinemap_clicked();

private:
Ui::offline_map_generation *ui;

QString m_WebMapID;
Esri::ArcGISRuntime::Map *m_map = nullptr;
Esri::ArcGISRuntime::MapGraphicsView *m_mapView = nullptr;
Esri::ArcGISRuntime::OfflineMapTask *m_OfflineMapTask;
Esri::ArcGISRuntime::PortalItem *m_PortalItem;
Esri::ArcGISRuntime::Portal *m_Portal;
Esri::ArcGISRuntime::GenerateOfflineMapJob *m_offline_generator_job;

QTemporaryDir m_tempPath;

void generate_offline_map();
};


#endif // OFFLINE_MAP_GENERATION_H
// CPP

#include "offline_map_generation.h"
#include "ui_offline_map_generation.h"

#include "Map.h"
#include "MapGraphicsView.h"
#include "PortalItem.h"
#include "Portal.h"
#include "OfflineMapTask.h"
#include "Error.h"
#include "GenerateOfflineMapJob.h"
#include "GenerateOfflineMapParameters.h"
#include "Viewpoint.h"
#include "TaskWatcher.h"
#include "SpatialReference.h"
#include "Point.h"
#include "Envelope.h"
#include "GeometryEngine.h"

using namespace Esri::ArcGISRuntime;

offline_map_generation::offline_map_generation(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::offline_map_generation)
{
    ui->setupUi(this);

    m_WebMapID = "0807d723aa8e41428319524e75148522";
    bool loginRequired = false;
    m_Portal = new Portal(loginRequired, this);
    m_Portal->load();

    m_PortalItem = new PortalItem(m_Portal, m_WebMapID, this);

    connect(m_Portal, &Esri::ArcGISRuntime::Portal::errorOccurred, this, &offline_map_generation::slot_portal_error);
    connect(m_PortalItem, &Esri::ArcGISRuntime::PortalItem::errorOccurred, this, &offline_map_generation::slot_portal_item_error);

    m_map = new Map(m_PortalItem, this);

    m_mapView = new MapGraphicsView();
    m_mapView->setMap(m_map);

    m_OfflineMapTask = new OfflineMapTask(m_map, this);

    ui->widget->layout()->addWidget(m_mapView);
}

offline_map_generation::~offline_map_generation()
{
    delete ui;
}

void offline_map_generation::slot_portal_error(const Esri::ArcGISRuntime::Error& error)
{
    qDebug()<<"Portal Error";
    qDebug()<<"Error Type"<<error.errorType();
    qDebug()<<error.message();
    qDebug()<<error.additionalMessage();
}

void offline_map_generation::slot_portal_item_error(const Esri::ArcGISRuntime::Error &error)
{
    qDebug()<<"Portal Item Error";
    qDebug()<<"Error Type"<<error.errorType();
    qDebug()<<error.message();
    qDebug()<<error.additionalMessage();
}

void offline_map_generation::onGenerateOfflineMapParametersCompleted(const QUuid& taskId, const Esri::ArcGISRuntime::GenerateOfflineMapParameters& parameters)
{
    QString Path = "D:/offline_map";
    GenerateOfflineMapJob *generateJob = NULL;

    // Adjust as needed based on your map's scale

    generateJob = m_OfflineMapTask->generateOfflineMap(parameters, Path);
    if(generateJob == NULL)
    {
        qDebug()<<"Offline Map is not generated";
    }
    else
    {
        generateJob->start();
        qDebug()<<"Map generated in path"<<Path;
        connect(generateJob, &GenerateOfflineMapJob::errorOccurred, this, &offline_map_generation::slot_map_offline_generator_job_has_error);
    }

}

void offline_map_generation::generate_offline_map()
{

    Point corner1 = {CHENNAI_LON, CHENNAI_LAT, SpatialReference::wgs84()};
    Point corner2 = {DELHI_LAT, DELHI_LON, SpatialReference::wgs84()};

    const Envelope extent = Envelope(corner1, corner2);
    const Envelope mapExtent = geometry_cast<Envelope>(GeometryEngine::project(extent, SpatialReference::wgs84()));

    connect(m_OfflineMapTask, &Esri::ArcGISRuntime::OfflineMapTask::createDefaultGenerateOfflineMapParametersCompleted, this, &offline_map_generation::onGenerateOfflineMapParametersCompleted);
    connect(m_OfflineMapTask, &Esri::ArcGISRuntime::OfflineMapTask::errorOccurred, this, &offline_map_generation::slot_offline_map_generator_error_occured);

    m_OfflineMapTask->createDefaultGenerateOfflineMapParameters(mapExtent);
}

void offline_map_generation::on_pushButton_offlinemap_clicked()
{
    generate_offline_map();
}

void offline_map_generation::slot_map_offline_generator_job_has_error(const Esri::ArcGISRuntime::Error &error)
{
    qDebug()<<"Error in Job";
    qDebug()<<"Error Type"<<error.errorType();
    qDebug()<<error.message();
    qDebug()<<error.additionalMessage();
}

void offline_map_generation::slot_offline_map_generator_error_occured(const Esri::ArcGISRuntime::Error &error)
{
    qDebug()<<"Error in Map Generation";
    qDebug()<<"Error Type"<<error.errorType();
    qDebug()<<error.message();
    qDebug()<<error.additionalMessage();
}

 

KailashSubramaniyan_0-1718966084888.png

KailashSubramaniyan_1-1718966104695.png

KailashSubramaniyan_2-1718966127918.png

0 Kudos
0 Replies