Qml - load a tif map and use it offline, without any online base map?

3876
11
Jump to solution
09-03-2017 04:50 AM
AnatBen_Israel
New Contributor II

Hi, I have a tif (and tfw) map that I want to be able to use offline (QML).

I have managed to load the tif as a raster layer on top of an online map, but I want to avoid it.

I I try to remove the BasemapImagery {}, the raster doesn't load...

In addition, how do I load the tfw file?

This is my code:

ApplicationWindow {
      id: appWindow
      width: 850
      height: 650
      title: "MapsProj"

     

      Rectangle {
           id: rootRectangle
           clip: true
           width: 800
           height: 600

           property real scaleFactor: System.displayScaleFactor
           property var rasterLayer: null
           property string rasterFilePath: "file:///C:/Projects/Sample/Maps/map1.tif"

           MapView {
                id: mapView
                anchors.fill: parent

                Map {
                    id: map

                    BasemapImagery {}

                    RasterLayer {
                           Raster {
                                 path: ""
                     }

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

                            mapView.setViewpointCenterAndScale(fullExtent.center, 80000);
                     }
               }

         }

     }

     Rectangle {
          visible: addButton.visible
           anchors.centerIn: addButton
           radius: 8 * rootRectangle.scaleFactor
           height: addButton.height + (16 * rootRectangle.scaleFactor)
           width: addButton.width + (16 * rootRectangle.scaleFactor)
           color: "lightgrey"
           border.color: "darkgrey"
           border.width: 2 * rootRectangle.scaleFactor
           opacity: 0.75
     }

     Button {
           id: addButton
           anchors {
                   bottom: parent.bottom
                   horizontalCenter: parent.horizontalCenter
                   margins: 32 * rootRectangle.scaleFactor
             }

           text: "Add Raster"
           onClicked: {
                 rootRectangle.createAndAddRasterLayer(rootRectangle.rasterFilePath)

            }
      }

      function createAndAddRasterLayer(rasterUrl) {
          var newRaster = ArcGISRuntimeEnvironment.createObject("Raster", {path: rasterUrl});
          rasterLayer = ArcGISRuntimeEnvironment.createObject("RasterLayer", {raster: newRaster});

          rasterLayer.loadStatusChanged.connect(zoomToRaster);

          map.operationalLayers.clear();
          map.operationalLayers.append(rasterLayer);
     }

     function zoomToRaster(){
        if (rasterLayer === null)
              return;

        if (rasterLayer.loadStatus !== Enums.LoadStatusLoaded)
              return;

         mapView.setViewpointCenterAndScale(rasterLayer.fullExtent.center, 80000);
     }
  }
}

0 Kudos
1 Solution

Accepted Solutions
LukeSmallwood
Esri Contributor

Hi Anat,

If you want to load your raster data without an online baseman a good option is to use  the raster itself as a layer for a local basemap. If you change your code to declare the raster as one of the baseLayers of a new Basemap (Basemap QML Type | ArcGIS for Developers ) it should load the map at the extent of your data.

    Map {
            id: map
            Basemap {
                RasterLayer {
                    Raster {
                        path: rasterFilePath
                    }
                }
            }
        }

Because "baseLayers" is a default property of Basemap, declaring a layer (in this case RasterLayer) as a child item will automatically add it to the list of base layers.

When you load a .tif file the .tfw should be automatically read for position information - assuming the names match and they are in the same directory. If your raster in your example code is shown in the correct place then I think the .tfw has been loaded successfully. 

I hope that helps - any questions, let me know.

Luke

View solution in original post

0 Kudos
11 Replies
LukeSmallwood
Esri Contributor

Hi Anat,

If you want to load your raster data without an online baseman a good option is to use  the raster itself as a layer for a local basemap. If you change your code to declare the raster as one of the baseLayers of a new Basemap (Basemap QML Type | ArcGIS for Developers ) it should load the map at the extent of your data.

    Map {
            id: map
            Basemap {
                RasterLayer {
                    Raster {
                        path: rasterFilePath
                    }
                }
            }
        }

Because "baseLayers" is a default property of Basemap, declaring a layer (in this case RasterLayer) as a child item will automatically add it to the list of base layers.

When you load a .tif file the .tfw should be automatically read for position information - assuming the names match and they are in the same directory. If your raster in your example code is shown in the correct place then I think the .tfw has been loaded successfully. 

I hope that helps - any questions, let me know.

Luke

0 Kudos
AnatBen_Israel
New Contributor II

Hi Luke,

Thank you very much! Unfortunately, I guess I'm still missing something...

I've copied the raster layer center x,y from the initial implementation, and now my code is as follows:

            Map {
                id: map
                Basemap {
                    id: baseMap
                    RasterLayer {
                        Raster {
                            id: raster
                            path: "file:///C:/Projects/Sample/Maps/map1.tif"
                        }
                    }
                }
                onLoadStatusChanged: {
                    if (loadStatus !== Enums.LoadStatusLoaded)
                        return;
                    var centerPoint = Qt.point(34.89521560479882, 32.133239999999994)
                    mapView.setViewpointCenterAndScale(centerPoint, 80000);
                }
            }

It looks as if something is loaded because I get the "For developer use only" label, 
which is usually located on the map, but I don't see any map...
0 Kudos
LukeSmallwood
Esri Contributor

Hi Anat, 

You should be able to remove the "onLoadStatusChanged" block from your code. As the RasterLayer is the only layer in the basemap/map the app should automatically start at this extent.

You may find that the app is starting at a scale beyond the drawing scale of the raster - so try zooming in to see if it appears.

AnatBen_Israel
New Contributor II

Works perfect!! Thanks so much!

0 Kudos
LukeSmallwood
Esri Contributor

Also, this call

var centerPoint = Qt.point(34.89521560479882, 32.133239999999994)

is creating the incorrect type (I think its a QML Point). You should be creating an ArcGIS Point type by doing something like:

var centerPoint = GeometryEngine.project(ArcGISRuntimeEnvironment.createObject("Point", {x: 34.89521560479882, y: 32.133239999999994, spatialReference: sr})
0 Kudos
AnatBen_Israel
New Contributor II

Thanks! this is going to save me so much time...

0 Kudos
AnatBen_Israel
New Contributor II

Any idea why after all the above works, the panning doesn't work anymore?

even if I zoom in and I know I have more data beyond the visible window...

0 Kudos
LukeSmallwood
Esri Contributor

Do you mean that you are unable to pan outside of the extents of the raster data-set?

0 Kudos
AnatBen_Israel
New Contributor II

Not able to pan at all. I'm looking at a small window, smaller than my raster image.

I thought I would be able to pan, and when I get to the edges, get a blank area.

But I can't pan at all...

0 Kudos