Map caching issue

352
1
04-16-2023 03:07 PM
Labels (2)
medvosa
New Contributor

Hi, i am trying to cacche maps to vbe available offline, i am using following qml app (modified example from docs):

 

 

/* Copyright 2020 Esri
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */


// You can run your app in Qt Creator by pressing Alt+Shift+R.
// Alternatively, you can run apps through UI using Tools > External > AppStudio > Run.
// AppStudio users frequently use the Ctrl+A and Ctrl+I commands to
// automatically indent the entirety of the .qml file.


import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtQuick.Controls.Material 2.1
import QtPositioning 5.3
import QtSensors 5.3

import ArcGIS.AppFramework 1.0
import Esri.ArcGISRuntime 100.9
//import Esri.ArcGISExtras 100.0


import "controls" as Controls

//------------------------------------------------------------------------------

App {
    id: app
    width: 414
    height: 736

    readonly property url outputTileCache: Qt.resolvedUrl("./../") + "TileCacheQml_%1.tpkx".arg(new Date().getTime().toString())

    property string statusText: "Ready"
    function units(value) {
        return AppFramework.displayScaleFactor * value
    }
    property real scaleFactor: AppFramework.displayScaleFactor
    property int baseFontSize : app.info.propertyValue("baseFontSize", 15 * scaleFactor) + (isSmallScreen ? 0 : 3)
    property bool isSmallScreen: (width || height) < units(400)

    Page{
        anchors.fill: parent
        header: ToolBar{
            id:header
            width: parent.width
            height: 50 * scaleFactor
            Material.background: "#8f499c"
            Controls.HeaderBar{}
        }
        Text{
            text:'hello world' + statusText
            color:'white'
        }

        // sample starts here ------------------------------------------------------------------
        contentItem: Rectangle{
            anchors.top:header.bottom
            MapView {
                   id: mapView
                   anchors.fill: parent

                   Component.onCompleted: {
                       // Set the focus on MapView to initially enable keyboard navigation
                       forceActiveFocus();
                   }

                   Map {
                       id: map

                       BasemapImageryWithLabelsVector {}
                       // Add an imagery basemap to the map and get the url of the raster baselayer once it has loaded
//                       Basemap {
//                           //initStyle: Enums.BasemapStyleArcGISImagery

//                           onLoadStatusChanged: {
//                               if (loadStatus !== Enums.LoadStatusLoaded)
//                                   return;

//                               exportTask.url = baseLayers.get(0).url;
//                           }
//                       }

                       initialViewpoint: ViewpointCenter {
                           center: Point {
                               x: -117
                               y: 35
                               spatialReference: SpatialReference { wkid: 4326 }
                           }
                           targetScale: 1e7
                       }
                   }
               }

               // Create ExportTileCacheTask
               //! [ExportTiles ExportTileCacheTask]

               ExportTileCacheTask {
                   id: exportTask
                   property var exportJob

                   onCreateDefaultExportTileCacheParametersStatusChanged: {
                       if (createDefaultExportTileCacheParametersStatus === Enums.TaskStatusCompleted) {
                           params = defaultExportTileCacheParameters;

                           // export the cache with the parameters
                           executeExportTileCacheTask(params);
                       }
                   }

                   function generateDefaultParameters(param) {
                       // generate the default parameters with the extent and map scales specified
                       let res = createDefaultExportTileCacheParameters(param, mapView.mapScale, mapView.mapScale/10);
                       console.log('generated', res)
                       return res;
                   }

                   function executeExportTileCacheTask(params) {
                       // execute the asynchronous task and obtain the job
                       exportJob = exportTask.exportTileCache(params, outputTileCache);

                       // check if job is valid
                       if (exportJob) {
                           // show the export window
                           exportWindow.visible = true;

                           // connect to the job's status changed signal to know once it is done
                           exportJob.statusChanged.connect(updateJobStatus);
                           exportJob.progressChanged.connect(updateExportProgress);

                           exportJob.start();
                       } else {
                           exportWindow.visible = true;
                           statusText = "Export failed 2";
                           exportWindow.hideWindow(5000);
                       }
                   }

                   function updateJobStatus() {
                       switch(exportJob.jobStatus) {
                       case Enums.JobStatusFailed:
                           statusText = "Export failed 1";
                           exportWindow.hideWindow(5000);
                           break;
                       case Enums.JobStatusNotStarted:
                           statusText = "Job not started";
                           break;
                       case Enums.JobStatusPaused:
                           statusText = "Job paused";
                           break;
                       case Enums.JobStatusStarted:
                           statusText = "In progress...";
                           break;
                       case Enums.JobStatusSucceeded:
                           statusText = "Adding TPKX...";
                           exportWindow.hideWindow(1500);
                           displayOutputTileCache(exportJob.result);
                           break;
                       default:
                           break;
                       }
                   }

                   function updateExportProgress() {
                       exportTileCacheProgress = exportJob.progress;
                   }

                   function displayOutputTileCache(tileCache) {
                       // create a new tiled layer from the output tile cache
                       const tiledLayer = ArcGISRuntimeEnvironment.createObject("ArcGISTiledLayer", { tileCache: tileCache } );

                       // create a new basemap with the tiled layer
                       const basemap = ArcGISRuntimeEnvironment.createObject("Basemap");
                       basemap.baseLayers.append(tiledLayer);

                       // set the new basemap on the map
                       map.basemap = basemap;

                       // zoom to the new layer and hide window once loaded
                       tiledLayer.loadStatusChanged.connect(()=> {
                            if (tiledLayer.loadStatus === Enums.LoadStatusLoaded) {
                                extentRectangle.visible = false;
                                downloadButton.visible = false;

                                const prevMapScale = mapView.mapScale;
                                mapView.setViewpointScale(prevMapScale * .5);
                                map.minScale = prevMapScale;
                                map.maxScale = prevMapScale / 10;
                            }
                        });
                   }

                   Component.onDestruction: {
                       if (exportJob) {
                           exportJob.statusChanged.disconnect(updateJobStatus);
                           exportJob.progressChanged.disconnect(updateExportProgress);
                       }
                   }
               }
               //! [ExportTiles ExportTileCacheTask]

               Rectangle {
                   id: extentRectangle
                   anchors.centerIn: parent
                   width: parent.width - (50)
                   height: parent.height - (125)
                   color: "transparent"
                   border {
                       color: "red"
                       width: 3
                   }
               }

               // Create the download button to export the tile cache
               Rectangle {
                   id: downloadButton
                   property bool pressed: false
                   anchors {
                       horizontalCenter: parent.horizontalCenter
                       bottom: parent.bottom
                       bottomMargin: 23
                   }

                   width: 130
                   height: 35
                   color: pressed ? "#959595" : "#D6D6D6"
                   radius: 5
                   border {
                       color: "#585858"
                       width: 1
                   }

                   Row {
                       anchors.fill: parent
                       spacing: 5
                       Text {
                           anchors.verticalCenter: parent.verticalCenter
                           text: "Export tiles"
                           font.pixelSize: 14
                           color: "#474747"
                       }
                   }

                   MouseArea {
                       anchors.fill: parent
                       onPressed: downloadButton.pressed = true
                       onReleased: downloadButton.pressed = false
                       onClicked: {
                           console.log('downloading')
                           let params = getRectangleEnvelope();

                           console.log('after')
//                           let params = exportTask.defaultExportTileCacheParameters;
                            console.log('executing', params)
                           // export the cache with the parameters`
                           function executeExportTileCacheTask(params) {
                               // execute the asynchronous task and obtain the job
                               console.log('tileCache:',  app.outputTileCache)
                               console.log('params:', params)
                               let exportJob = exportTask.exportTileCache(params, outputTileCache);
                               console.log('export job:', exportJob);

                               // check if job is valid
                               if (exportJob) {
                                   // show the export window
                                   exportWindow.visible = true;

                                   // connect to the job's status changed signal to know once it is done
                                   exportJob.statusChanged.connect(updateJobStatus);
                                   exportJob.progressChanged.connect(updateExportProgress);

                                   exportJob.start();
                               } else {
                                   exportWindow.visible = true;
                                   statusText = "Export failed 3";
                                   exportWindow.hideWindow(5000);
                               }
                           }
                           executeExportTileCacheTask(params);
                       }

                       function getRectangleEnvelope() {
                           const corner1 = mapView.screenToLocation(extentRectangle.x, extentRectangle.y);
                           const corner2 = mapView.screenToLocation((extentRectangle.x + extentRectangle.width), (extentRectangle.y + extentRectangle.height));
                           const envBuilder = ArcGISRuntimeEnvironment.createObject("EnvelopeBuilder");
                           envBuilder.setCorners(corner1, corner2);
                           console.log('before start');
//                           tileCacheExtent = GeometryEngine.project(envBuilder.geometry, Factory.SpatialReference.createWebMercator());
                           return exportTask.generateDefaultParameters(GeometryEngine.project(envBuilder.geometry, Factory.SpatialReference.createWebMercator()));
//                           console.log('generated default parameteres');
                       }
                   }
               }

               // Create a window to display the export window
               Rectangle {
                   id: exportWindow
                   anchors.fill: parent
                   color: "transparent"
                   visible: false
                   clip: true

                   Rectangle {
                       anchors.fill: parent
                       color: "#60000000"
                   }

                   MouseArea {
                       anchors.fill: parent
                       onClicked: mouse => mouse.accepted = true
                       onWheel: wheel => wheel.accepted = true
                   }

                   Rectangle {
                       anchors.centerIn: parent
                       width: 140
                       height: 145
                       color: "lightgrey"
                       opacity: 0.8
                       radius: 5
                       border {
                           color: "#4D4D4D"
                           width: 1
                       }

                       Column {
                           anchors {
                               fill: parent
                               margins: 10
                           }
                           spacing: 10

                           BusyIndicator {
                               anchors.horizontalCenter: parent.horizontalCenter
                           }

                           Text {
                               anchors.horizontalCenter: parent.horizontalCenter
                               text: statusText
                               font.pixelSize: 16
                           }

                           Text {
                               anchors.horizontalCenter: parent.horizontalCenter
                               text: 0/*exportTileCacheProgress*/ + "% Completed"
                               font.pixelSize: 16
                           }
                       }
                   }

                   Timer {
                       id: hideWindowTimer
                       onTriggered: exportWindow.visible = false;
                   }

                   function hideWindow(time) {
                       hideWindowTimer.interval = time;
                       hideWindowTimer.restart();
                   }
               }


        }
    }
    Controls.DescriptionPage{
        id:descPage
        visible: false
    }
}

//------------------------------------------------------------------------------

 

when i rty to click download buttoin i always encounter error labeled "Export error 3", i also checked what is exportJob equal to after i run let exportJob = exportTask.exportTileCache(params, outputTileCache);
it is always null
what might i be doing wrong here?

0 Kudos
1 Reply
Tanner_Yould
Esri Contributor

It's difficult to say for sure what's going wrong. I'm guessing it's something to do with how you're creating the ExportTileCacheParameters, but I can't say for certain. Can you share your entire application output? It looks like you have a lot of things logged to the console that may help me understand. Additionally, can you try putting the following in your ExportTileCacheTask? 

onErrorChanged: {
    console.log("Export task error:", exportTask.error.message, exportTask.error.additionalMessage);
}

That may help  illuminate the problem.

Looking forward to hearing back from you, thank you!

Tanner Yould
Samples Product Engineer
ArcGIS Maps SDK for Qt
Esri
0 Kudos