Files
qt5-legatus-legacy/Lts/Viewer/SituationMap/MapImpl/logical_layer.cpp
T
2026-08-13 18:33:10 +02:00

802 lines
28 KiB
C++
Executable File

/**
* @RDE_HEADER@
* MapLayer
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "logical_layer.h"
#include <Map/map.h>
#include <Symbology/symbol_dictionary.h>
#include <SymbologyImpl/symbol_dictionary_impl.h>
#include <Map/situation_map_utils.h>
// ESRI
#include <arcgis/Layer.h>
#include <arcgis/GraphicsOverlay.h>
#include <arcgis/DictionaryRenderer.h>
#include <arcgis/ArcGISTiledLayer.h>
#include <arcgis/LayerSceneProperties.h>
// Qt
// #include <QDebug>
#include <QTimer>
static_assert((int)SituationMap::SurfacePlacement::Draped == (int)Esri::ArcGISRuntime::SurfacePlacement::Draped, "SurfacePlacement mismatch");
static_assert((int)SituationMap::SurfacePlacement::Absolute == (int)Esri::ArcGISRuntime::SurfacePlacement::Absolute, "SurfacePlacement mismatch");
static_assert((int)SituationMap::SurfacePlacement::Relative == (int)Esri::ArcGISRuntime::SurfacePlacement::Relative, "SurfacePlacement mismatch");
namespace SituationMap
{
LogicalLayer::LogicalLayer(const QString &logicalName, QObject *parent)
: BaseClass(parent),
m_logicalName(logicalName),
m_logger(getLogger("LogicalLayer"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " m_logicalName='" << m_logicalName << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " m_logicalName='" << m_logicalName << "'";
}
LogicalLayer::~LogicalLayer()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " m_logicalName='" << m_logicalName << "'";
fini();
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " m_logicalName='" << m_logicalName << "'";
}
void LogicalLayer::init(SituationMap::Map *map,
Esri::ArcGISRuntime::LayerListModel *layerListModel,
Esri::ArcGISRuntime::GraphicsOverlayListModel *graphicsOverlayListModel)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_logicalName='" << m_logicalName << "'"
<< " layerListModel=" << layerListModel
<< " graphicsOverlayListModel=" << graphicsOverlayListModel;
m_map = map;
m_layerListModel = layerListModel;
m_graphicsOverlayListModel = graphicsOverlayListModel;
#ifdef LTS_DEBUG
// sometimes getCreateGraphicalOverlay() has no m_graphicsOverlayListModel - hmm
// happens for layer 'MountingfPoints'
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_logicalName='" << m_logicalName << "'"
<< " m_map=" << m_map
<< " m_map->isReady=" << m_map->isReady()
<< " layerListModel=" << layerListModel
<< " graphicsOverlayListModel=" << graphicsOverlayListModel;
Q_ASSERT(m_graphicsOverlayListModel);
#endif // LTS_DEBUG
// set default order of GraphicalOverlays: (from bottom to top)
setOrderOfGraphicalOverlays({ TechnicalLayerType::GraphicsLayer,
TechnicalLayerType::GraphicsLayer_Dict,
TechnicalLayerType::GraphicsLayer_3D_Extrusion,
TechnicalLayerType::GraphicsLayer_3D_Absolute });
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void LogicalLayer::fini()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_logicalName='" << m_logicalName << "'"
<< " layerListModel=" << m_layerListModel
<< " graphicsOverlayListModel=" << m_graphicsOverlayListModel;
// process Layer (e.g. Basemap)
// Esri::ArcGISRuntime::Layer
if (m_layer && m_layerListModel)
{
m_layerListModel->removeOne(m_layer);
delete m_layer;
m_layer = nullptr;
}
// process GraphicsOverlay
if (m_graphicsOverlayListModel)
{
for (Esri::ArcGISRuntime::GraphicsOverlay *graphicsOverlay : qAsConst(m_graphicalOverlays))
{
// do some checks :
{
const int numberOfCurrentObjects = graphicsOverlay->graphics()->size();
if (numberOfCurrentObjects != 0)
{
QString objectName;
Esri::ArcGISRuntime::Graphic* g = graphicsOverlay->graphics()->first();
if (g)
objectName = g->objectName();
ERROR_LOG(m_logger) << LOGFUNCTION
<< " Attention, removing GraphicsOverlay still having objects!!!"
<< ", graphicsOverlay='" << graphicsOverlay << "'"
<< ", numberOfCurrentObjects=" << numberOfCurrentObjects
<< ", m_logicalName='" << m_logicalName << "'"
<< ", objectName of first='" << objectName << "'";
}
TRACE_LOG(m_logger) << LOGFUNCTION << " m_logicalName='" << m_logicalName << "'"
<< " numberOfCurrentObjects=" << numberOfCurrentObjects;
}
// : do some checks
m_graphicsOverlayListModel->removeOne(graphicsOverlay);
delete graphicsOverlay;
}
}
// cleanup internal container:
m_graphicalOverlays.clear();
m_graphicOverlayContainer.clear();
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " m_logicalName='" << m_logicalName << "'"
<< " layerListModel=" << m_layerListModel
<< " graphicsOverlayListModel=" << m_graphicsOverlayListModel;
}
QString LogicalLayer::logicalName() const
{
return m_logicalName;
}
void LogicalLayer::setLogicalName(const QString &logicalName)
{
m_logicalName = logicalName;
}
LayerType LogicalLayer::layerType() const
{
return m_layerType;
}
void LogicalLayer::setLayerType(const LayerType &layerType)
{
m_layerType = layerType;
}
BasemapType LogicalLayer::basemapType() const
{
return m_basemapType;
}
void LogicalLayer::setBasemapType(const BasemapType &basemapType)
{
m_basemapType = basemapType;
}
RenderingMode LogicalLayer::renderingMode() const
{
return m_graphicsOverlayRenderingMode;
}
void LogicalLayer::setRenderingMode(RenderingMode renderingMode)
{
m_graphicsOverlayRenderingMode = renderingMode;
}
SurfacePlacement LogicalLayer::surfacePlacement() const
{
return m_surfacePlacement;
}
void LogicalLayer::setSurfacePlacement(SurfacePlacement surfacePlacement)
{
m_surfacePlacement = surfacePlacement;
}
const LayerParameter &LogicalLayer::layerParameter() const
{
return m_layerParameter;
}
void LogicalLayer::setLayerParameter(const LayerParameter &layerParameter)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_logicalName='" << m_logicalName << "'"
<< " layerParameter=" << layerParameter;
bool changed = (m_layerParameter != layerParameter);
m_layerParameter = layerParameter;
if (changed)
{
// apply LayerParameters (visible, opca, brightness....)
this->applyLayerParameterToEsri();
// trigger update of gui:
emit layerParameterChanged(m_logicalName, m_layerParameter);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " m_logicalName='" << m_logicalName << "'"
<< " changed=" << changed;
}
Esri::ArcGISRuntime::Layer *LogicalLayer::layer() const
{
return m_layer;
}
void LogicalLayer::setLayer(Esri::ArcGISRuntime::Layer *layer)
{
m_layer = layer;
// Handle errors of layer:
connect(m_layer, &Esri::ArcGISRuntime::Layer::errorOccurred,
this, &LogicalLayer::onLayerError, Qt::UniqueConnection);
// Handle doneLoading:
connect(m_layer, &Esri::ArcGISRuntime::Layer::doneLoading,
this, &LogicalLayer::onLayerDoneLoading, Qt::UniqueConnection);
connect(m_layer, &Esri::ArcGISRuntime::Layer::loadStatusChanged,
this, &LogicalLayer::onLayerLoadStatusChanged, Qt::UniqueConnection);
if (!m_layerListModel->contains(m_layer))
m_layerListModel->append(m_layer);
}
QList<Esri::ArcGISRuntime::GraphicsOverlay *> LogicalLayer::getCurrentGraphicalOverlaysOrdered() const
{
QList<Esri::ArcGISRuntime::GraphicsOverlay *> orderedLayerList;
for (TechnicalLayerType techType : m_orderOfGraphicalOverlays)
{
const QString &esriLayerName = LogicalLayer::createInternalLayerName(m_logicalName, techType);
if (!m_graphicOverlayContainer.contains(esriLayerName))
continue;
Esri::ArcGISRuntime::GraphicsOverlay *layer = m_graphicOverlayContainer[esriLayerName];
if (layer)
orderedLayerList.append(layer);
} // for
return orderedLayerList;
}
QList<QPair<QString, Esri::ArcGISRuntime::GraphicsOverlay *> > LogicalLayer::getCurrentGraphicalOverlaysOrderedWithName() const
{
QList<QPair<QString, Esri::ArcGISRuntime::GraphicsOverlay *> > ret;
for (TechnicalLayerType techType : qAsConst(m_orderOfGraphicalOverlays))
{
const QString &esriLayerName = LogicalLayer::createInternalLayerName(m_logicalName, techType);
if (!m_graphicOverlayContainer.contains(esriLayerName))
continue;
Esri::ArcGISRuntime::GraphicsOverlay *layer = m_graphicOverlayContainer[esriLayerName];
if (!layer)
continue;
QPair<QString, Esri::ArcGISRuntime::GraphicsOverlay *> foundPair(esriLayerName, layer);
ret.append(foundPair);
} // for
return ret;
}
int LogicalLayer::layerIndex() const
{
if (! m_layerListModel)
return -1;
return m_layerListModel->indexOf(m_layer);
}
Esri::ArcGISRuntime::GraphicsOverlay *LogicalLayer::getCreateGraphicalOverlay(const TechnicalLayerType &technicalLayerType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_logicalName='" << m_logicalName << "'"
<< " technicalLayerType=" << technicalLayerType;
// [GUEZE-496] RPL Nr 770: 3D Lagedarstellung Einfrieren der SW Appl.
// Layer renderer does not support multipoint graphics (V100.8)
// So turn back to 2 technical layers per logical layer. So The MineArea
// is on a TechnicalLayerType::GraphicsLayer and MineArea/IndicationContainer
// uses ONE GraphicalObjectPictureMarker/Esri::ArcGISRuntime::PictureMarkerSymbol
// with multiple coordinates (multipoint)
TechnicalLayerType technicalLayerTypeLocal = technicalLayerType;
if ((m_layerType == LayerType::Rubberband) ||
(m_layerType == LayerType::Overlay) ||
((m_layerType == LayerType::Operational) && (m_logicalName.compare(QStringLiteral("PlanEditorLayer")) == 0))
)
{
technicalLayerTypeLocal = TechnicalLayerType::GraphicsLayer_Dict;
}
if (! m_graphicsOverlayListModel)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " m_logicalName='" << m_logicalName << "'"
<< " no m_graphicsOverlayListModel";
#ifdef LTS_DEBUG
Q_ASSERT(m_graphicsOverlayListModel);
#endif // LTS_DEBUG
return nullptr;
}
if (! m_orderOfGraphicalOverlays.contains(technicalLayerTypeLocal))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " m_logicalName='" << m_logicalName << "'"
<< " not allowed: technicalLayerType=" << technicalLayerTypeLocal;
return nullptr;
}
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer = nullptr;
const QString &esriLayerName = LogicalLayer::createInternalLayerName(m_logicalName, technicalLayerTypeLocal);
// lookup in own container:
if (m_graphicOverlayContainer.contains(esriLayerName))
{
graphicsLayer = m_graphicOverlayContainer[esriLayerName];
// make sure, that layer is still valid (within esri/model):
if (graphicsLayer)
{
if (! m_graphicsOverlayListModel->contains(graphicsLayer))
{
m_graphicOverlayContainer.remove(esriLayerName);
graphicsLayer = nullptr;
}
}
}
// create if not found
if (! graphicsLayer)
{
INFO_LOG(m_logger) << LOGFUNCTION
<< " requested (logical) layername ='" << m_logicalName << "' not in esriMap"
<< ", create on demand..."
<< " (renderMode=" << m_graphicsOverlayRenderingMode << ")";
graphicsLayer = createGraphicLayer(technicalLayerTypeLocal, m_graphicsOverlayRenderingMode);
//
// post operations:
//
// apply LayerParameters (visible, opca, brightness....)
this->applyLayerParameterToEsri();
// trigger re-ordering
emit layerCreatedOnDemand(m_logicalName);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " technicalLayerType=" << technicalLayerType;
return graphicsLayer;
}
void LogicalLayer::onLayerError(const Esri::ArcGISRuntime::Error &error)
{
if (error.code() == 404)
DEBUG_LOG(m_logger) << LOGFUNCTION << " EsriError occured: " << error
<< ", layerName=" << m_layerParameter.url.toString();
else
ERROR_LOG(m_logger) << LOGFUNCTION << " EsriError occured: " << error
<< ", layerName=" << m_layerParameter.url.toString();
}
void LogicalLayer::onGraphicsOverlayLayerError(const Esri::ArcGISRuntime::Error &error)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " EsriError occured: " << error
<< ", layerName=" << m_layerParameter.url.toString();
}
void LogicalLayer::onRendererError(const Esri::ArcGISRuntime::Error &error)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " EsriError occured: " << error
<< ", layerName=" << m_layerParameter.url.toString();
}
void LogicalLayer::onLayerDoneLoading(const Esri::ArcGISRuntime::Error &loadError)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_logicalName='" << m_logicalName << "'";
if (!loadError.isEmpty())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " m_logicalName='" << m_logicalName << "'"
<< ", layerName = '" << m_layerParameter.url.toString() << "'"
<< ", loadError: " << loadError;
Esri::ArcGISRuntime::Layer *layer = qobject_cast<Esri::ArcGISRuntime::Layer *>(sender());
if (layer)
{
const int maxRetry = 2;
if (m_retryCounter<=maxRetry)
{
++m_retryCounter;
QTimer::singleShot(1000 + (m_retryCounter+1000), this, std::bind(&Esri::ArcGISRuntime::Layer::retryLoad, layer));
INFO_LOG(m_logger) << LOGFUNCTION << " schedule retryLoad for '" << m_logicalName << "'" << " (m_retryCounter=" << m_retryCounter << ")";
}
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " max number of retries (" << maxRetry << ") exceeded, give up" << ", m_logicalName='" << m_logicalName << "'";
}
return;
}
else
ERROR_LOG(m_logger) << LOGFUNCTION
<< " qobject_cast failed m_logicalName='" << m_logicalName << "'";
return;
}
Esri::ArcGISRuntime::Layer *layer = qobject_cast<Esri::ArcGISRuntime::Layer *>(sender());
if (!layer)
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " qobject_cast failed m_logicalName='" << m_logicalName << "'";
return;
}
// Esri::ArcGISRuntime::Item *item = layer->item();
// if (!item)
// FATAL_LOG(m_logger) << LOGFUNCTION << " no item!!!! " << m_logicalName << "'";
const QString layername(layer->name());
INFO_LOG(m_logger) << LOGFUNCTION << " esriLayer of LogicalLayer: '" << layername << "' is loaded now #1: ESRI-Layer: "
<< " minScale()=" << layer->minScale()
<< ", maxScale()=" << layer->maxScale()
<< " (m_retryCounter=" << m_retryCounter << ")";
// minScale, maxScale at 3D returns always '0' for basemaps, so skip
if ((m_layerType == LayerType::Basemap) && (m_map->mode() == Mode::Mode_2D))
{
if (!m_layerParameter.minScaleValid())
m_layerParameter.minScale = layer->minScale();
if (!m_layerParameter.minMaxScaleValid())
m_layerParameter.maxScale = layer->maxScale();
}
INFO_LOG(m_logger) << LOGFUNCTION << " esriLayer of LogicalLayer: '" << layername << "' is loaded now #2: LogicalLayer"
<< ", minScale = " << m_layerParameter.minScale
<< ", maxScale = " << m_layerParameter.maxScale;
Esri::ArcGISRuntime::ArcGISTiledLayer *arcGISTiledLayer = qobject_cast<Esri::ArcGISRuntime::ArcGISTiledLayer *>(sender());
if (arcGISTiledLayer)
{
const Esri::ArcGISRuntime::ArcGISMapServiceInfo &mapSvcInfo = arcGISTiledLayer->mapServiceInfo();
if (m_layerParameter.displayName.isEmpty()) // if not already set use mapName of Service
m_layerParameter.displayName = mapSvcInfo.mapName();
m_layerParameter.description = mapSvcInfo.description();
m_layerParameter.svcDescription = mapSvcInfo.serviceDescription();
} // if (arcGISTiledLayer)
DEBUG_LOG(m_logger) << LOGFUNCTION << " doneLoading: '" << layername << "'"
<< " new m_layerParameter:" << m_layerParameter;
// maybe the para weren`t applied because not loaded..
// so do it here (again);
applyLayerParameterToEsri();
// trigger reCalulation of minMaxScale:
emit layerDoneLoading(m_logicalName);
// trigger update of gui:
emit layerParameterChanged(m_logicalName, m_layerParameter);
DEBUG_LOG(m_logger) << LOGFUNCTION << " doneLoading: '" << layername << "'";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void LogicalLayer::onLayerLoadStatusChanged(const Esri::ArcGISRuntime::LoadStatus &loadStatus)
{
INFO_LOG(m_logger) << LOGFUNCTION << " START" << " m_logicalName='" << m_logicalName << "'"
<< " new loadStatus=" << loadStatus;
}
Esri::ArcGISRuntime::GraphicsOverlay *LogicalLayer::createGraphicLayer(const TechnicalLayerType &technicalLayerType,
RenderingMode renderingMode)
{
Esri::ArcGISRuntime::GraphicsOverlay *graphicalOverlay =
createGraphicLayerInternal(technicalLayerType, renderingMode);
if (technicalLayerType != TechnicalLayerType::GraphicsLayer_Dict)
return graphicalOverlay;
// get access to esri dictionary:
const AdvancedSymbology::SymbolDictionary &dict = m_map->symbolDictionary();
const AdvancedSymbology::SymbolDictionaryImpl &dictImpl = static_cast<const AdvancedSymbology::SymbolDictionaryImpl &>(dict);
Esri::ArcGISRuntime::DictionarySymbolStyle *esriDict = const_cast<Esri::ArcGISRuntime::DictionarySymbolStyle *>(dictImpl.getEsriSymbolDictionary());
if (!esriDict)
return graphicalOverlay;
// make sure, that dict is already loaded:
if (esriDict->loadStatus() == Esri::ArcGISRuntime::LoadStatus::Loaded)
{
// create renderer
Esri::ArcGISRuntime::DictionaryRenderer *dictRenderer =
new Esri::ArcGISRuntime::DictionaryRenderer(esriDict, this);
// Handle errors of DictionaryRenderer:
connect(dictRenderer, &Esri::ArcGISRuntime::DictionaryRenderer::errorOccurred,
this, &LogicalLayer::onRendererError);
dictRenderer->setTextVisible(true);
// set Renderer to layer:
// take care that the old one is deleted:
Esri::ArcGISRuntime::Renderer *oldRenderer = graphicalOverlay->renderer();
if (oldRenderer)
{
FATAL_LOG(m_logger) << LOGFUNCTION << " replace/destroy/remove old renderer, is this intended???";
oldRenderer->deleteLater(); // Qt-Doc: 'It is safe to call this function more than once;'
}
// assign new:
graphicalOverlay->setRenderer(dictRenderer);
INFO_LOG(m_logger) << LOGFUNCTION
<< " requested (logical) layername ='" << m_logicalName << "' -> with Renderer"
<< " of symbologyType=" << dict.symbologyType();
}
else
{
FATAL_LOG(m_logger) << LOGFUNCTION << " SymbolDictionary not loaded!!!";
FATAL_LOG(m_logger) << LOGFUNCTION << " SymbolDictionary not loaded!!!";
FATAL_LOG(m_logger) << LOGFUNCTION << " SymbolDictionary not loaded!!!";
// do not return 'nullptr' to avoid crash on further operations
}
return graphicalOverlay;
}
QString LogicalLayer::createInternalLayerName(const QString &logicalLayerName, const TechnicalLayerType &technicalLayerType)
{
return logicalLayerName + QLatin1Char('#') + toString(technicalLayerType);
}
Esri::ArcGISRuntime::GraphicsOverlay *LogicalLayer::createGraphicLayerInternal(const TechnicalLayerType &technicalLayerType,
RenderingMode renderingMode)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_logicalName='" << m_logicalName << "'"
<< " technicalLayerType=" << technicalLayerType
<< " m_graphicalOverlays.size()=" << m_graphicalOverlays.size()
<< " m_graphicsOverlayListModel.size()=" << m_graphicsOverlayListModel->size();
if (! m_graphicsOverlayListModel)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_graphicsOverlayListModel";
return nullptr;
}
const QString &esriLayername = createInternalLayerName(m_logicalName, technicalLayerType);
Esri::ArcGISRuntime::GraphicsOverlay *graphicalOverlay =
new Esri::ArcGISRuntime::GraphicsOverlay();
graphicalOverlay->setOverlayId(esriLayername);
static long s_counter = 0;
graphicalOverlay->setObjectName(QStringLiteral("GraphicsOverlay_%1_'%2'").arg(s_counter++).arg(esriLayername));
connect(graphicalOverlay, &Esri::ArcGISRuntime::GraphicsOverlay::destroyed, this, [this, graphicalOverlay] () {
INFO_LOG(m_logger) << " GraphicsOverlay is destroyed , objectName='" << graphicalOverlay->objectName() << "'";
});
// Extrusion requires
// a) GraphicsRenderingMode::Dynamic and
// b) SurfacePlacement::Relative
if (technicalLayerType == TechnicalLayerType::GraphicsLayer_3D_Extrusion)
{
graphicalOverlay->setRenderingMode(Esri::ArcGISRuntime::GraphicsRenderingMode::Dynamic);
} else {
switch (renderingMode)
{
case RenderingMode::Dynamic:
graphicalOverlay->setRenderingMode(Esri::ArcGISRuntime::GraphicsRenderingMode::Dynamic);
break;
case RenderingMode::Static:
graphicalOverlay->setRenderingMode(Esri::ArcGISRuntime::GraphicsRenderingMode::Static);
break;
default:
// empty
break;
}
}
#if ACRGIS_VERSION < 0x640500 // 100.5.0 / Update 5
// deprecated in V100.5, replaced by GeoView::setSelectionProperties()
graphicalOverlay->setSelectionColor(Qt::magenta);
#endif // ACRGIS_VERSION
m_graphicalOverlays.append(graphicalOverlay);
m_graphicsOverlayListModel->append(graphicalOverlay);
// store it for lookup in own container:
m_graphicOverlayContainer[esriLayername] = graphicalOverlay;
// set SurfacePlacement
Esri::ArcGISRuntime::LayerSceneProperties lsp = graphicalOverlay->sceneProperties();
// Extrusion requires
// a) GraphicsRenderingMode::Dynamic and
// b) SurfacePlacement::Relative
if (technicalLayerType == TechnicalLayerType::GraphicsLayer_3D_Extrusion)
lsp.setSurfacePlacement(Esri::ArcGISRuntime::SurfacePlacement::Relative);
else if (technicalLayerType == TechnicalLayerType::GraphicsLayer_3D_Absolute)
lsp.setSurfacePlacement(Esri::ArcGISRuntime::SurfacePlacement::Absolute);
else
lsp.setSurfacePlacement(static_cast<Esri::ArcGISRuntime::SurfacePlacement>(m_surfacePlacement)); // save due to static_assert
graphicalOverlay->setSceneProperties(lsp);
Esri::ArcGISRuntime::GraphicsRenderingMode esriRenderingMode = graphicalOverlay->renderingMode();
INFO_LOG(m_logger) << LOGFUNCTION << " created GraphicsOverlay: "
<< " logicalName='" << m_logicalName << "'"
<< " technicalLayerType=" << technicalLayerType
<< " esriLayerName='" << esriLayername << "'"
<< " esriRenderModeStr=" << esriRenderingMode // Check operator
<< " surfacePlacement=" << m_surfacePlacement
<< " curIdx=" << m_graphicsOverlayListModel->indexOf(graphicalOverlay)
<< " graphicalOverlay=" << graphicalOverlay;
// Handle errors of layer:
connect(graphicalOverlay, &Esri::ArcGISRuntime::GraphicsOverlay::errorOccurred,
this, &LogicalLayer::onGraphicsOverlayLayerError);
// GraphicsOverlay need no doneLoading :-)
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " m_logicalName='" << m_logicalName << "'"
<< " technicalLayerType=" << technicalLayerType
<< " m_graphicalOverlays.size()=" << m_graphicalOverlays.size()
<< " m_graphicsOverlayListModel.size()=" << m_graphicsOverlayListModel->size();
return graphicalOverlay;
}
void LogicalLayer::applyLayerParameterToEsri()
{
int graphicsOverlayListModelSize = -1;
if (m_graphicsOverlayListModel)
graphicsOverlayListModelSize = m_graphicsOverlayListModel->size();
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_logicalName='" << m_logicalName << "'"
<< " m_layer=" << m_layer
<< " m_graphicalOverlays.size()=" << m_graphicalOverlays.size()
<< " m_graphicsOverlayListModel.size()=" << graphicsOverlayListModelSize
<< " lp=" << m_layerParameter;
// process Layer (e.g. Basemap)
// Esri::ArcGISRuntime::Layer
Esri::ArcGISRuntime::Layer *esriLayer = m_layer;
if (esriLayer)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_logicalName='" << m_logicalName << "'"
<< " CURRENT loadStatus =" << esriLayer->loadStatus();
if (esriLayer->loadStatus() != Esri::ArcGISRuntime::LoadStatus::Loaded)
{
INFO_LOG(m_logger) << LOGFUNCTION << " not loaded yet, skip"
<< " m_logicalName='" << m_logicalName << "'"
<< " m_layer=" << m_layer
<< " lp=" << m_layerParameter;
return;
}
esriLayer->setVisible(m_layerParameter.visible);
esriLayer->setOpacity(m_layerParameter.opacity / 100.0f);
if (m_layerParameter.minScaleValid())
esriLayer->setMinScale(m_layerParameter.minScale);
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " minScale not valid, set to '0'"
<< " m_logicalName='" << m_logicalName << "'";
esriLayer->setMinScale(0);
}
// Sonderfall (leider)
// Für 3D wird maxScale hart auf '0' gesetzt, damit beim Neigen keine basemap
// (besser basemapkachel) ausgeblendet wird.
if ((m_layerType == LayerType::Basemap) &&
(m_map->mode() == Mode::Mode_3D)
)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " set maxScale to '0', because Basemap and Mode_3D for: "
<< "m_logicalName='" << m_logicalName << "'";
esriLayer->setMaxScale(0);
} else {
if (m_layerParameter.maxScaleValid())
esriLayer->setMaxScale(m_layerParameter.maxScale);
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " maxScale not valid, set to '0'"
<< " m_logicalName='" << m_logicalName << "'";
esriLayer->setMaxScale(0);
}
} // : Sonderfall
// for layer supporting bightness, contrast, gamma:
if (esriLayer->layerType() == Esri::ArcGISRuntime::LayerType::ArcGISTiledLayer)
{
Esri::ArcGISRuntime::ArcGISTiledLayer *tiledLayer =
static_cast<Esri::ArcGISRuntime::ArcGISTiledLayer *>(esriLayer);
tiledLayer->setBrightness(m_layerParameter.brightness);
tiledLayer->setContrast(m_layerParameter.contrast);
tiledLayer->setGamma(m_layerParameter.gamma);
}
} // if (esriLayer)
// process GraphicsOverlay
for (Esri::ArcGISRuntime::GraphicsOverlay *graphicsOverlay : qAsConst(m_graphicalOverlays))
{
graphicsOverlay->setVisible(m_layerParameter.visible);
graphicsOverlay->setOpacity(m_layerParameter.opacity / 100.0);
if (m_layerParameter.minScaleValid())
graphicsOverlay->setMinScale(m_layerParameter.minScale);
if (m_layerParameter.maxScaleValid())
graphicsOverlay->setMaxScale(m_layerParameter.maxScale);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " m_logicalName='" << m_logicalName << "'";
}
void LogicalLayer::setOrderOfGraphicalOverlays(const QVector<TechnicalLayerType> &orderOfGraphicalOverlays)
{
m_orderOfGraphicalOverlays = orderOfGraphicalOverlays;
}
//------------------------------------------------------------------------------
QLatin1String toString(const TechnicalLayerType &value)
{
switch (value)
{
case TechnicalLayerType::GraphicsLayer:
return QLatin1String("GraphicsLayer");
case TechnicalLayerType::GraphicsLayer_Dict:
return QLatin1String("GraphicsLayer_Dict");
case TechnicalLayerType::GraphicsLayer_3D_Extrusion:
return QLatin1String("GraphicsLayer_3DExtrusion");
case TechnicalLayerType::GraphicsLayer_3D_Absolute:
return QLatin1String("GraphicsLayer_3D_Absolute");
}
return QLatin1String("TechnicalLayerTypeERROR");
}
std::ostream &operator<<(std::ostream &stream, const TechnicalLayerType &value)
{
stream << toString(value).latin1();
return stream;
}
} // namespace SituationMap