Select to view content in your preferred language

Image overlay on 2D map with ArcGIS Maps 200.7

115
4
Wednesday
Labels (3)
LeeCarter
Emerging Contributor

I've been waiting years for this capability, so when it appeared in Maps 200.7, I thought I should try it out, but I'm not having much success.

The setup/environment is:

  • ArcGIS Maps for Qt 200.7
  • Qt 6.8.3
  • VS: 2022

As the intended use is with an application that uses offline maps, I changed the DisplayMap sample (arcgis-maps-sdk-samples-qt-200.7.0.4560\CppWidgetsSamples\Maps\DisplayMap) to use an offline map and show a QImage using an ImageFrame and ImageOverlay.

Other than adding the additional include files needed, the code is unchanged except the DisplayMap constructor, which now looks like this:

DisplayMap::DisplayMap(QWidget* parent) :
  QWidget(parent)
{
    const QString tileBasemapFile("C:/MapData/Map.tpk");

    ArcGISTiledLayer* tileBasemapLayer = new ArcGISTiledLayer(new TileCache(tileBasemapFile, this), this);
    tileBasemapLayer->setName(tileBasemapFile);
    tileBasemapLayer->load();

    // Create a map using the offline basemap
    m_map = new Map(this);
    m_map->basemap()->baseLayers()->append(tileBasemapLayer);

    // Create a map view, and pass in the map
    m_mapView = new MapGraphicsView(m_map, this);

    // Create image
    QImage image(500, 500, QImage::Format_RGB32);
    image.fill(qRgb(255, 0, 0));

    // Define the envelope to be used for the image on the map
    const Envelope env(-50.0, -50.0, 50.0, 50.0);
    std::unique_ptr<ImageFrame> imageFrame = std::make_unique<ImageFrame>(image, env);
    ImageOverlay* imageOverlay = new ImageOverlay(imageFrame.get(), this);

    m_mapView->imageOverlays()->append(imageOverlay);

    // Set up the UI
    QVBoxLayout *vBoxLayout = new QVBoxLayout();
    vBoxLayout->addWidget(m_mapView);
    setLayout(vBoxLayout);
}

 

The use of std::unique_ptr<ImageFrame> was taken from the 3D scene sample code that uses ImageFrame/ImageOverlay.

The application runs, displays the basemap and allows panning/zooming as would be expected, but the ImageFrame (i.e. a big solid red area) is not shown.  The application shows as "Licensed for Developer Use Only", but applying a "lite" license code makes no difference to the application's appearance/behaviour other than the message being removed.

I've checked that the ImageOverlay reports that it is visible and the opacity is 1, also after being set as the frame for the ImageOverlay, the ImageFrame retrieved from the ImageOverlay reports the correct extent.

Any suggestions as to what I'm missing/doing wrong?

0 Kudos
4 Replies
TroyFoster
Frequent Contributor

https://doc.qt.io/qt-6/qimage.html#fill-2:~:text=If%20the%20depth%20of%20the%20image%20is%208%2C%20t....

You might need to set a value in the color table before the call to fill so that the Qimage works properly

https://doc.qt.io/qt-6/qimage.html#setColorTable

 

0 Kudos
bnoble0110
Esri Contributor

Hello @LeeCarter,

 

The issue you might be facing is a spatial reference mismatch between the `Envelope` you're setting up and your `Map` / `MapView`. I ran into this issue myself when first trying out this API. Here is a quick example I set up based on the code snippet you provided.

 

DisplayMap::DisplayMap(QWidget* parent /*=nullptr*/)
    : QMainWindow(parent)
{
  const QString tileBasemapFile("/Users/bri12415/ArcGIS/Runtime/Data/tpk/Campus.tpk");
  ArcGISTiledLayer* tileBasemapLayer = new ArcGISTiledLayer(new TileCache(tileBasemapFile, this), this);
  tileBasemapLayer->setName(tileBasemapFile);
  tileBasemapLayer->load();

  // Create a map using the offline basemap
  m_map = new Map(this);
  m_map->basemap()->baseLayers()->append(tileBasemapLayer);

  // Create a map view, and pass in the map
  m_mapView = new MapGraphicsView(m_map, this);

  qDebug() << m_mapView->spatialReference().toJson(); //WKID 102100
  qDebug() << m_map->spatialReference().toJson(); //WKID 102100

  // I used our `screenToLocation` API to figure out where on the map I'd like to display the red square
  connect(m_mapView, &MapGraphicsView::mouseClicked, this,
          [this](QMouseEvent& mouseEvent)
          {
            qDebug() << m_mapView->screenToLocation(mouseEvent.position().x(), mouseEvent.position().y()).toJson();
          });

  // Create image
  QImage image(500, 500, QImage::Format_RGB32);
  image.fill(qRgb(255, 0, 0));

  // Define the envelope to be used for the image on the map
  const Envelope env{-13046288, 4036452, -13046268, 4036472, SpatialReference(102100)};
  qDebug() << env.spatialReference().toJson(); //WKID 102100
  std::unique_ptr<ImageFrame> imageFrame = std::make_unique<ImageFrame>(image, env);
  ImageOverlay* imageOverlay = new ImageOverlay(imageFrame.get(), this);


  m_mapView->imageOverlays()->append(imageOverlay);

  // set the mapView as the central widget
  setCentralWidget(m_mapView);
}

 

 
 

bnoble0110_3-1746117685275.png

 

 

0 Kudos
TroyFoster
Frequent Contributor

Would connecting to the `errorOccurred` signal on either the mapview or image overlay help show when there is a spatial reference mismatch?

0 Kudos
LeeCarter
Emerging Contributor

Hi @bnoble0110,

Thank you for your response. It was indeed the complete lack of a SpatialReference that was the source of the problem.

When I first tried to add a spatial reference, I did the same as when creating Graphic objects to add to a GraphicsOverlay, i.e. I used SpatialReference::wgs84().  With the same basemap (where the map and map view are both webMercator spatial reference), the graphic(s) added to the graphics overlay work fine with wgs84 as the spatial reference for the geometry of the graphic objects, but the image frame added to the image overlay does not.  To make it work, I have to use SpatialReference::webMercator(), so I'm having to use GeometryEngine::project(...) to convert my Envelope from wgs84 to webMercator.

Why do graphics in graphics overlays work OK as wgs84 without needing to convert the spatial reference, but image frames in image overlays do not?  Is this "expected behaviour" or is (as it seems to me) something not quite right/as good as it could be with the way ImageFrame/ImageOverlays are working with 2D maps?

0 Kudos