[Solved] How to get reasonable performance using ENC Layers

1347
5
Jump to solution
11-28-2018 11:59 AM
TMPTMP1
New Contributor II

I managed to get ENC layers working by starting from the default new C++ project and modifying as below. It works, which is great! However, as soon as the layers load, scrolling becomes impossible. I can't tell if it's slowing to a crawl or there's something about the layer interfering with the scroll but it kind of looks like it's a CPU issue. I'm using a 2018 Macbook Air, so machine performance should not be the bottleneck.

The SENC files seem to already be generated, and the data set is a rather small view of Providence and/or Boston harbor.

What's going on here and how do we fix it?

==========================

P.S. If anyone else is trying to get ENC working, here are the full working code sets.

C++ file:

// Copyright 2016 ESRI
//
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
//
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
//
// See the Sample code usage restrictions document for further information.
//

// C++ API headers
#include "Basemap.h"

// Other headers
#include "ArcGIS_QtWidgets.h"

#include "Map.h"
#include "MapGraphicsView.h"

#include "EncExchangeSet.h"
#include "EncLayer.h"
#include "EncFeature.h"
#include "EncCell.h"
#include "EncTextGroupVisibilitySettings.h"
#include "EncEnvironmentSettings.h"

using namespace Esri::ArcGISRuntime;

ArcGIS_QtWidgets::ArcGIS_QtWidgets(QWidget* parent /*=nullptr*/):
    QMainWindow(parent)
{
    // get EncDisplaySettings instance
    EncDisplaySettings* displaySettings = EncEnvironmentSettings::displaySettings();

    // set paths
    EncEnvironmentSettings::setSencDataPath("/Users/tmptmp/Documents/Charts/SENC");
    EncEnvironmentSettings::setResourcePath("/Users/tmptmp/Documents/Charts/hydrography");

    // create EncExchangeSet using paths
    encExchangeSet = new EncExchangeSet(QStringList(QStringList() << "/Users/tmptmp/Documents/Charts/ENC_ROOT_Boston_Harbor/CATALOG.031" << "/Users/tmptmp/Documents/Charts/ENC/US_REGION02/CATALOG.031"), this);

    connect(encExchangeSet, &EncExchangeSet::doneLoading, this, [this]{

        // get the list of EncDataset
        QList<EncDataset*> EncDatasets = encExchangeSet->datasets();

        // display the names of EncDataset
        for (EncDataset* EncDataset: EncDatasets)
        {

            // Create the cell and layer
            auto myEncLayer = new EncLayer(new EncCell(EncDataset));

            // Add the layer to the map
            m_map->operationalLayers()->append(myEncLayer);
            qDebug()<< "Loaded map: " << EncDataset->name();

        }

        qDebug()<< "Loaded all maps";
    });

    // Load the EncExchangeSet
    encExchangeSet->load();

    // get ENC text group visibility settings object
    EncTextGroupVisibilitySettings* encTextGroupVisibilitySettings = EncEnvironmentSettings::displaySettings()->textGroupVisibilitySettings();

    // set properties
    encTextGroupVisibilitySettings->setImportantText(false);
    encTextGroupVisibilitySettings->setNatureOfSeabed(false);

    // Create the Widget view
    m_mapView = new MapGraphicsView(this);

    connect(m_mapView, &MapGraphicsView::mousePressedAndHeld, this, [this](QMouseEvent& mouseEvent)
    {
        qDebug()<< "Mouse pressed";

      double tolerance = 5.0;
      bool returnPopupsOnly = false;
      int maximumResults = 5;
      m_mapView->identifyLayers(mouseEvent.x(), mouseEvent.y(), tolerance, returnPopupsOnly, maximumResults);
    });


    connect(m_mapView, &MapGraphicsView::identifyLayersCompleted, this, [](QUuid taskId, QList<Esri::ArcGISRuntime::IdentifyLayerResult*> identifyResults)
    {
      Q_UNUSED(taskId);
      for (int i = 0; i < identifyResults.size(); i++)
      {
        EncLayer* encLayer = dynamic_cast<EncLayer*>(identifyResults.at(i)->layerContent());
        if (encLayer)
        {
          qDebug() << "EncFeatures identified in EncLayer #" << i << ":";
          QList<GeoElement*>objects = identifyResults.at(i)->geoElements();
          for (int j = 0; j < objects.size(); j++)
          {
            EncFeature* encFeature = dynamic_cast<EncFeature*>(objects.at(j));
            if (encFeature)
            {
              qDebug() << "Found EncFeature: " << encFeature->description();
              QVariantMap map = encFeature->attributes()->attributesMap();
              qDebug() << " - Attributes: " << map;
            }
          }
        }
      }
    });

    // Create a map using the navigationVector Basemap
    m_map = new Map(Basemap::oceans(this), this);

    // Set map to map view
    m_mapView->setMap(m_map);

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

// destructor
ArcGIS_QtWidgets::~ArcGIS_QtWidgets()
{
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Header file:

// Copyright 2016 ESRI
//
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
//
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
//
// See the Sample code usage restrictions document for further information.
//

#ifndef ARCGIS_QTWIDGETS_H
#define ARCGIS_QTWIDGETS_H

namespace Esri
{
namespace ArcGISRuntime
{
class Map;
class MapGraphicsView;
}
}

#include <QMainWindow>

#include "EncExchangeSet.h"

class ArcGIS_QtWidgets : public QMainWindow
{
    Q_OBJECT
public:
    ArcGIS_QtWidgets(QWidget* parent = nullptr);
    ~ArcGIS_QtWidgets();

public slots:

private:
    Esri::ArcGISRuntime::EncExchangeSet*        encExchangeSet = nullptr;
    Esri::ArcGISRuntime::Map*                   m_map = nullptr;
    Esri::ArcGISRuntime::MapGraphicsView*       m_mapView = nullptr;
};

#endif // ARCGIS_QTWIDGETS_H
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Tags (3)
0 Kudos
1 Solution

Accepted Solutions
LucasDanzinger
Esri Frequent Contributor

I think you may be hitting a bug with our Qt Widgets view on Mac when using the track pad. Are you able to try one of the following other options to confirm this is the issue:

- use a mouse

- use the qt quick C++ template instead of qt widgets

- try a different platform

If that is indeed the issue, it is an issue in general with mouse interactions with widgets via the mac mouse track pad, and not with the ENC Layer performance

View solution in original post

5 Replies
LucasDanzinger
Esri Frequent Contributor

I think you may be hitting a bug with our Qt Widgets view on Mac when using the track pad. Are you able to try one of the following other options to confirm this is the issue:

- use a mouse

- use the qt quick C++ template instead of qt widgets

- try a different platform

If that is indeed the issue, it is an issue in general with mouse interactions with widgets via the mac mouse track pad, and not with the ENC Layer performance

TMPTMP1
New Contributor II

Good call! Using the mouse resolved the problem. 

I would normally have preferred to use C++/QML, but the comment at https://community.esri.com/thread/224697-display-enc-data-using-qml#comment-814673 dissuaded me. Do you have any information as to the nature of the bug, so that I can work around it until it's resolved?

0 Kudos
LucasDanzinger
Esri Frequent Contributor

You can actually still use C++ with QML UI - the issue mentioned in that link is with the QML API specifically. The difference is subtle, but important to understand. When you build a Runtime Qt app, you have 3 options:

- C++ w/ Qt Widgets for UI. This is what your sample is in, but it has this nasty trackpad bug. I do not know of any workaround for it other than using a mouse.

- C++ with Qt Quick (QML) for UI. This is what I am suggesting you use instead. If you use the new project wizard in Qt Creator, under the ArcGIS Section, you should see one that says "ArcGIS Runtime 100.4 Qt Quick C++ app". All of the code you have in your above sample can be transported over with very minimal changes (only changes required would be to use the MapQuickView instead of the MapGraphicsView)

- Pure QML implementation. This pattern uses no C++, and uses QML for both UI and business logic. This uses a separate API that we refer to as "the QML API", and this one is the one that has the bug you mentioned in the above link.

0 Kudos
TMPTMP1
New Contributor II

Thanks, and agreed on the differences between the approaches. I typically work in the C++/QML hybrid approach, however for most of what I want to do drawing with ArcGIS in C++ makes a lot less sense and is a lot less maintainable. C++ is where I would implement complex models and or view trees, but QML is a great place to load the map, add an icon or two, and draw a handful of circles and lines.

The only reason I could think of to draw the map in C++ is because an ENC tends to put a lot of information on the screen all at once and it's very important that the business back end optimize this information overload. Implementing the ENC with the C++ API seems to perform beautifully, should I expect the same performance in QML?

0 Kudos
LucasDanzinger
Esri Frequent Contributor

Yes, performance should be the same. Our QML types are all implemented in C++, so they should be just as fast and efficient. Our only slow downs we have seen have been in client code (not the API itself) - for example, if client code is looping through lots of graphics or results in QML/JS, it will often be slower than doing the same in C++.

0 Kudos