623 lines
24 KiB
C++
Executable File
623 lines
24 KiB
C++
Executable File
/**
|
||
* @RDE_HEADER@
|
||
* TacticalAppearance
|
||
* $Id$
|
||
* $HeadURL$
|
||
* $Author$
|
||
*/
|
||
|
||
// Own
|
||
#include "tactical_appearance.h"
|
||
#include <MapImpl/map_impl.h>
|
||
#include <Symbology/symbol_dictionary.h>
|
||
#include <Symbology/sidc_builder_base.h>
|
||
#include <Symbology/sidc_codec.h>
|
||
#include <GraphicalObjects/graphical_object_picture_marker.h>
|
||
#include <Map/situation_map_utils.h> // operator<<
|
||
#include <Common/simple_value.h>
|
||
|
||
|
||
// ESRI
|
||
#include <arcgis/Map.h>
|
||
#include <arcgis/GraphicsOverlay.h>
|
||
#include <arcgis/PolygonBuilder.h>
|
||
#include <arcgis/PolylineBuilder.h>
|
||
#include <arcgis/MultipointBuilder.h>
|
||
|
||
// Qt
|
||
#include <QElapsedTimer>
|
||
|
||
|
||
namespace SituationMap
|
||
{
|
||
|
||
|
||
class TacticalAppearance::Private
|
||
{
|
||
public:
|
||
Private() = default;
|
||
~Private() = default;
|
||
|
||
// ESRI data:
|
||
MapImpl *m_mapImpl = nullptr;
|
||
QString m_logicalLayerName;
|
||
|
||
Esri::ArcGISRuntime::GraphicsOverlay *m_graphicOverlayTactical = nullptr;
|
||
AdvancedSymbology::SymbolDictionary *m_dictionary = nullptr;
|
||
AdvancedSymbology::SymbolResultWatcher m_symbolResultWatcher;
|
||
|
||
// OWN data:
|
||
SimpleValue<QString> m_uniqueDesignation;
|
||
SimpleValue<SymbolData> m_symbol;
|
||
|
||
|
||
AdvancedSymbology::SymbolDataToRender m_symDataToRender;
|
||
GraphicalObjectPictureMarker *m_pictureMarker = nullptr;
|
||
|
||
}; // class TacticalAppearance::Private
|
||
//-----------------------------------------------------------------------------
|
||
|
||
|
||
|
||
TacticalAppearance::TacticalAppearance(MapImpl *mapImpl,
|
||
const QString &logicalLayerName,
|
||
const QString &debugInfo,
|
||
const UniqueMapId &uniqueMapId)
|
||
: BaseClass(mapImpl->getEsriGeoView(), nullptr, debugInfo, uniqueMapId),
|
||
m_logger(getLogger("TacticalAppearance")),
|
||
d(new Private)
|
||
{
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
|
||
<< ", logicalLayerName='" << logicalLayerName << "'";
|
||
|
||
d->m_symDataToRender.sizeL = 100;
|
||
d->m_mapImpl = mapImpl;
|
||
d->m_logicalLayerName = logicalLayerName;
|
||
|
||
if (!m_graphicsLayer && d->m_mapImpl)
|
||
m_graphicsLayer = d->m_mapImpl->getGraphicsLayer(d->m_logicalLayerName);
|
||
|
||
if (!m_graphicsLayer)
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
||
<< " getGraphicsLayer failed";
|
||
}
|
||
|
||
if (d->m_mapImpl)
|
||
d->m_dictionary = &(d->m_mapImpl->symbolDictionary());
|
||
|
||
|
||
// lambda:
|
||
// m_symbolResultWatcher is canceled on destruction.
|
||
// So it`s safe that no signal will be fired afterwards.
|
||
// To avoid CLang warnings use m_symbolResultWatcher as context (3rd para), although it´s not intended.
|
||
// Better idea?
|
||
QObject::connect(&d->m_symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady, &d->m_symbolResultWatcher, [this]()
|
||
{
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
||
<< " resultReady...";
|
||
|
||
QSharedPointer<AdvancedSymbology::SymbolResult> symResult = d->m_symbolResultWatcher.symbolResult();
|
||
if (! symResult)
|
||
return; // should NEVER happen! (Which object should have triggered the signal???)
|
||
|
||
if (d->m_pictureMarker)
|
||
{
|
||
d->m_pictureMarker->setImage(symResult->symbolImage().image());
|
||
d->m_pictureMarker->updateView();
|
||
}
|
||
});
|
||
|
||
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
|
||
}
|
||
|
||
TacticalAppearance::~TacticalAppearance()
|
||
{
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
|
||
|
||
// abort pending call to SymbolDictionary::findSymbol:
|
||
d->m_symbolResultWatcher.cancel();
|
||
|
||
delete d->m_pictureMarker;
|
||
d->m_pictureMarker = nullptr;
|
||
|
||
removeGraphicFromGraphicOverlayTactical();
|
||
|
||
delete d;
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
|
||
}
|
||
|
||
void TacticalAppearance::removeGraphicFromGraphicOverlayTactical()
|
||
{
|
||
if (m_logger.isTraceEnabled())
|
||
{
|
||
if (m_graphic)
|
||
{
|
||
Esri::ArcGISRuntime::GraphicsOverlay *gOverlay = m_graphic->graphicsOverlay();
|
||
if (gOverlay)
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " START debugInfo='" << m_debugInfo << "'" << " name = '" << gOverlay->overlayId() << "'";
|
||
}
|
||
}
|
||
|
||
if (m_graphic && d->m_graphicOverlayTactical && d->m_graphicOverlayTactical->graphics())
|
||
d->m_graphicOverlayTactical->graphics()->removeOne(m_graphic);
|
||
|
||
delete m_graphic;
|
||
m_graphic = nullptr;
|
||
}
|
||
|
||
|
||
|
||
bool TacticalAppearance::useDictionaryRenderMode(const AdvancedSymbology::GeometryType &geomType) const
|
||
{
|
||
bool usePictureMarker = isSinglePoint() && (AdvancedSymbology::GeometryType::Point == geomType || AdvancedSymbology::GeometryType::Undefined == geomType);
|
||
return !usePictureMarker || symbol().useAlwaysDictionaryRenderer;
|
||
} // bool TacticalAppearance::useDictionaryRenderMode() const
|
||
|
||
|
||
bool TacticalAppearance::create()
|
||
{
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
|
||
<< " m_visibility = " << m_visibility;
|
||
|
||
bool success = true;
|
||
|
||
//
|
||
// Prepare / create :
|
||
//
|
||
// a) singlePoint / exactly one coordinate -> use pictureMarker
|
||
// or
|
||
// b) multiPoint / more than one coordinate -> m_graphic / DictionaryRenderer
|
||
|
||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
* This assumption doesn't work any more because some polyline and polygon symbols will have only one
|
||
* anchor point and the real geometry is defined by additional attributes like radius, with, length ...
|
||
*
|
||
* JT 2016/12/20
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||
|
||
if (m_graphicsLayer && m_visibility.value())
|
||
{
|
||
const SymbolData &symbolData_ref = d->m_symbol.value();
|
||
const QString &baseSymbolCode = AdvancedSymbology::SidcBuilderBase::concreteSidcToBaseSymbolCode(symbolData_ref.sidc);
|
||
const AdvancedSymbology::SymbolProperties &symbolProperties = d->m_dictionary->symbolProperties(baseSymbolCode);
|
||
AdvancedSymbology::GeometryType geomType = symbolProperties.geometryType();
|
||
|
||
if (useDictionaryRenderMode(geomType))
|
||
{
|
||
if (!d->m_graphicOverlayTactical)
|
||
d->m_graphicOverlayTactical = d->m_mapImpl->getGraphicsLayerDict(d->m_logicalLayerName);
|
||
|
||
if (!d->m_graphicOverlayTactical)
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
||
<< " getGraphicsLayerDict failed";
|
||
return false;
|
||
}
|
||
|
||
if (!m_graphic)
|
||
{
|
||
m_graphic = new Esri::ArcGISRuntime::Graphic();
|
||
m_graphic->setObjectName(m_debugInfo);
|
||
m_graphic->setZIndex(m_drawOrder.value());
|
||
|
||
// use attributeModel to store application obj id (SimWorld) at graphic
|
||
Esri::ArcGISRuntime::AttributeListModel *attLisModel = m_graphic->attributes();
|
||
if (attLisModel)
|
||
attLisModel->insertAttribute(QLatin1String(SituationMap::UniqueMapIdAttribute), m_uniqueMapId);
|
||
else
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " no AttributeListModel, debugInfo='" << m_debugInfo << "'" << " uniqueMapId=" << m_uniqueMapId;
|
||
|
||
// Adding an empty graphic leads to Segmentation fault.
|
||
// (in Esri_runtimecore::Map_renderer::Dictionary_renderer::derive_geometry)
|
||
|
||
bool successGraphic = addUpdateGraphic(); // CHECK
|
||
if (!successGraphic)
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " addUpdateGraphic failed, debugInfo='" << m_debugInfo << "'" << " uniqueMapId=" << m_uniqueMapId;
|
||
|
||
} // if (!m_graphic)
|
||
}
|
||
else
|
||
{
|
||
// m_graphic is needless now:
|
||
removeGraphicFromGraphicOverlayTactical();
|
||
}
|
||
|
||
}
|
||
|
||
// : Prepare / create
|
||
|
||
bool positionsEmpty = m_positions.value().isEmpty();
|
||
if (positionsEmpty)
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " positions empty";
|
||
|
||
success = success && !positionsEmpty;
|
||
|
||
if (!success)
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " create failed";
|
||
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
|
||
return success;
|
||
}
|
||
|
||
void TacticalAppearance::createPictureMarker()
|
||
{
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
|
||
if (!d->m_pictureMarker && d->m_mapImpl)
|
||
{
|
||
d->m_pictureMarker = new GraphicalObjectPictureMarker(d->m_mapImpl->getEsriGeoView()
|
||
, m_graphicsLayer
|
||
, m_debugInfo + QLatin1String("#PicMarkTacticalAppearance")
|
||
, m_uniqueMapId);
|
||
}
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
|
||
}
|
||
|
||
void TacticalAppearance::removePictureMarker()
|
||
{
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
|
||
delete d->m_pictureMarker;
|
||
d->m_pictureMarker = nullptr;
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
|
||
}
|
||
|
||
QString TacticalAppearance::uniqueDesignation() const
|
||
{
|
||
return d->m_uniqueDesignation.value();
|
||
}
|
||
void TacticalAppearance::setUniqueDesignation(const QString &uniqueDesignation)
|
||
{
|
||
d->m_uniqueDesignation = uniqueDesignation;
|
||
}
|
||
|
||
SymbolImage TacticalAppearance::symbolImage() const
|
||
{
|
||
SymbolImage symImage;
|
||
if (d->m_pictureMarker)
|
||
{
|
||
symImage.setImage(d->m_pictureMarker->image());
|
||
symImage.setValid(!symImage.image().isNull());
|
||
}
|
||
return symImage;
|
||
}
|
||
|
||
|
||
SymbolData TacticalAppearance::symbol() const
|
||
{
|
||
return d->m_symbol.value();
|
||
}
|
||
|
||
void TacticalAppearance::setSymbol(const SymbolData &symbol)
|
||
{
|
||
d->m_symbol = symbol;
|
||
}
|
||
|
||
bool TacticalAppearance::changed()
|
||
{
|
||
return BaseClass::changed()
|
||
|| d->m_uniqueDesignation.changed()
|
||
|| d->m_symbol.changed();
|
||
}
|
||
void TacticalAppearance::resetChanged()
|
||
{
|
||
BaseClass::resetChanged();
|
||
d->m_uniqueDesignation.reset();
|
||
d->m_symbol.reset();
|
||
}
|
||
|
||
Esri::ArcGISRuntime::Geometry TacticalAppearance::getGraphicGeometry() const
|
||
{
|
||
if (d->m_pictureMarker) return d->m_pictureMarker->getGraphicGeometry();
|
||
if (m_graphic) return m_graphic->geometry();
|
||
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << "Geometry is undefined";
|
||
|
||
return Esri::ArcGISRuntime::Geometry();
|
||
} // Esri::ArcGISRuntime::Geometry TacticalAppearance::getGraphicGeometry() const
|
||
|
||
|
||
bool TacticalAppearance::updateViewImpl()
|
||
{
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
|
||
<< " symbol='" << d->m_symbol.value().sidc << "'"
|
||
<< " visibility=" << m_visibility
|
||
<< " selected=" << m_selected
|
||
<< " origin=" << this->origin()
|
||
<< " scale=" << m_scale.value();
|
||
|
||
const SymbolData &symbolData_ref = d->m_symbol.value();
|
||
const QString &baseSymbolCode = AdvancedSymbology::SidcBuilderBase::concreteSidcToBaseSymbolCode(symbolData_ref.sidc);
|
||
const AdvancedSymbology::SymbolProperties &symbolProperties = d->m_dictionary->symbolProperties(baseSymbolCode);
|
||
AdvancedSymbology::GeometryType geomType = symbolProperties.geometryType();
|
||
|
||
if (geomType == AdvancedSymbology::GeometryType::Undefined)
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
||
<< " GeometryType::Undefined, symbolProperties failed!?!";
|
||
return false;
|
||
}
|
||
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
|
||
<< ", geomType=" << geomType
|
||
<< ", useDictionaryRenderMode(geomType)=" << useDictionaryRenderMode(geomType);
|
||
|
||
bool success = create();
|
||
|
||
if (!success)
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
||
<< " create failed";
|
||
return false;
|
||
}
|
||
|
||
if (useDictionaryRenderMode(geomType))
|
||
{
|
||
// real work:
|
||
if (m_positions.changed() || d->m_symbol.changed() || m_visibility.changed())
|
||
{
|
||
auto buildPointClusterGeometry = [this]() -> Esri::ArcGISRuntime::Geometry
|
||
{
|
||
QSharedPointer<Esri::ArcGISRuntime::MultipointBuilder> builder(new Esri::ArcGISRuntime::MultipointBuilder(spatialReference()));
|
||
Esri::ArcGISRuntime::PointCollection points(spatialReference());
|
||
const auto posCont = positions();
|
||
for (const auto &pos : posCont)
|
||
{
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
||
<< " addPoint:" << pos.x() << " - " << pos.y();
|
||
points.addPoint(pos.x(), pos.y());
|
||
}
|
||
builder->setPoints(&points);
|
||
return builder->toGeometry();
|
||
}; // buildPointClusterGeometry
|
||
|
||
Esri::ArcGISRuntime::Geometry geom;
|
||
|
||
switch (geomType)
|
||
{
|
||
case AdvancedSymbology::GeometryType::Undefined : break;
|
||
|
||
case AdvancedSymbology::GeometryType::Point :
|
||
case AdvancedSymbology::GeometryType::Polyline :
|
||
{
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " m_positions.count()=" << m_positions.value().count();
|
||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* If a PolylineBuilder is used here to create symbol geometry the construction appropriate symbol standard (MIL2525C / MIL2525D / App6)
|
||
* will not be done and the symbol is always a simple polyline. Using MultipointBuilder to build symbol geometry the result is based on
|
||
* underlying symbol standard.
|
||
* 2016/12/9 JT
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||
geom = buildPointClusterGeometry();
|
||
|
||
} break;
|
||
|
||
case AdvancedSymbology::GeometryType::Polygon :
|
||
{
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " m_positions.count()=" << m_positions.value().count();
|
||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
*
|
||
* Some symbols have polygon geometry and could have only one or two positions. In case of less than 3 positions do the same as for
|
||
* polylines and use MultipointBuilder to create the symbol geometry. In other case use PolygonBuilder.
|
||
* 2016/12/13 JT
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||
if (positions().size() > 2)
|
||
{
|
||
QSharedPointer<Esri::ArcGISRuntime::PolygonBuilder> builder(new Esri::ArcGISRuntime::PolygonBuilder(spatialReference()));
|
||
const auto posCont = positions();
|
||
for (const auto &pos : posCont)
|
||
{
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " addPoint:" << pos.x() << " - " << pos.y();
|
||
builder->addPoint(pos.x(), pos.y());
|
||
}
|
||
geom = builder->toGeometry();
|
||
}
|
||
else
|
||
geom = buildPointClusterGeometry();
|
||
|
||
} break;
|
||
|
||
} // switch
|
||
|
||
if (geom.isEmpty())
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " Geometry NOT OK -> fallback symbol" << " (geometryType was " << geomType << ")";
|
||
createPictureMarker();
|
||
d->m_pictureMarker->setDebugInfo(m_debugInfo + QLatin1String("#fallback"));
|
||
|
||
int size = symbolData_ref.size;
|
||
if (size < 10) size = 10;
|
||
if (size > 100) size = 100;
|
||
|
||
d->m_pictureMarker->setMarkerSymbol(MarkerSymbolType::Diamond, size, symbolData_ref.color);
|
||
d->m_pictureMarker->setOrigin(this->origin());
|
||
d->m_pictureMarker->setDrawOrder(m_drawOrder.value());
|
||
d->m_pictureMarker->updateView();
|
||
success = false;
|
||
}
|
||
else // geom is not empty
|
||
{
|
||
removePictureMarker();
|
||
|
||
if (m_graphic)
|
||
{
|
||
success = true;
|
||
|
||
// move to graphic:
|
||
m_graphic->setGeometry(geom);
|
||
|
||
// prepare rawAttributes for DictionaryRenderer:
|
||
|
||
QVariantMap rawAttributes = d->m_symbol.value().attributeMap;
|
||
|
||
// build from scratch to honor removed attributes:
|
||
// (Otherwise the will remain wrongly)
|
||
|
||
rawAttributes[QLatin1String(SituationMap::UniqueMapIdAttribute)] = m_uniqueMapId;
|
||
rawAttributes[QLatin1String(SituationMap::IsPickableAttribute)] = m_pickable.value(); // set pickable attribute JT 2016/12/21
|
||
|
||
rawAttributes[QLatin1String("_type")] = QLatin1String("position_report");
|
||
rawAttributes[QLatin1String("_action")] = QLatin1String("update");
|
||
rawAttributes[QLatin1String("sidc")] = AdvancedSymbology::SidcCodec::decodeRawSidc(d->m_symbol.value().sidc); // in case of MIL2525
|
||
rawAttributes[QLatin1String("sic")] = AdvancedSymbology::SidcCodec::decodeRawSidc(d->m_symbol.value().sidc); // in case of APP6
|
||
|
||
Esri::ArcGISRuntime::AttributeListModel * attributeModel = m_graphic->attributes();
|
||
if (attributeModel)
|
||
attributeModel->setAttributesMap(rawAttributes);
|
||
else
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " no AttributeListModel";
|
||
|
||
|
||
|
||
// // prepare rawAttributes for DictionaryRenderer:
|
||
// QVariantMap rawAttributes = d->m_symbol.value().attributeMap;
|
||
|
||
// rawAttributes[QLatin1String(SituationMap::IsPickableAttribute)] = m_pickable.value(); // set pickable attribute JT 2016/12/21
|
||
|
||
// rawAttributes[QLatin1String("_type")] = QLatin1String("position_report");
|
||
// rawAttributes[QLatin1String("_action")] = QLatin1String("update");
|
||
// rawAttributes[QLatin1String("sidc")] = AdvancedSymbology::SidcCodec::decodeRawSidc(d->m_symbol.value().sidc); // in case of MIL2525
|
||
// rawAttributes[QLatin1String("sic")] = AdvancedSymbology::SidcCodec::decodeRawSidc(d->m_symbol.value().sidc); // in case of APP6
|
||
// // move to graphic:
|
||
// m_graphic->setGeometry(geom);
|
||
|
||
// /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
// * Replace:
|
||
// * m_graphic->attributes()->setAttributesMap(rawAttributes);
|
||
// *
|
||
// * because it doesn't work anymore in ArcGISRuntime V100.2
|
||
// * JT, 2018/01/24
|
||
// * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||
|
||
// Esri::ArcGISRuntime::AttributeListModel * attributeModel = m_graphic->attributes();
|
||
// if (attributeModel)
|
||
// {
|
||
// if (!attributeModel->isEmpty())
|
||
// {
|
||
// for (auto it = rawAttributes.cbegin(); it != rawAttributes.cend(); ++it)
|
||
// {
|
||
// const QString &attrKey = it.key();
|
||
// if (attributeModel->containsAttribute(attrKey))
|
||
// {
|
||
// attributeModel->replaceAttribute(attrKey, rawAttributes[attrKey]);
|
||
// continue;
|
||
// }
|
||
// attributeModel->insertAttribute(attrKey, rawAttributes[attrKey]);
|
||
// }
|
||
// }
|
||
// else attributeModel->setAttributesMap(rawAttributes);
|
||
// }
|
||
|
||
// 2021-08, N. Thoden
|
||
// While switching back to the behaviour that one logical layer has
|
||
// 1st getGraphicsLayer and 2nd getGraphicsLayerDict [GUEZE-496],
|
||
// the tactical appereance of DangerArea and similar disappears.
|
||
// Reason: m_graphicsLayer and m_graphicOverlayTactical are different now!
|
||
// It seems like that in former versions (< V100.8) the graphic could
|
||
// be added to more than one Esri layer.
|
||
// Now (V100.8) adding to a second layer fails.
|
||
// But we can remove the m_graphic from the default m_graphicsLayer
|
||
// before adding the the desired one: m_graphicOverlayTactical
|
||
if (m_graphicsLayer->graphics()->contains(m_graphic))
|
||
m_graphicsLayer->graphics()->removeOne(m_graphic);
|
||
|
||
// add to graphicOverlayTactical:
|
||
if (! d->m_graphicOverlayTactical->graphics()->contains(m_graphic))
|
||
d->m_graphicOverlayTactical->graphics()->append(m_graphic);
|
||
|
||
bool successGraphic = d->m_graphicOverlayTactical->graphics()->contains(m_graphic);
|
||
if (!successGraphic)
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
||
<< " m_graphic not added to m_graphicOverlayTactical";
|
||
}
|
||
else
|
||
{
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
||
<< " no m_graphic";
|
||
// success = false;
|
||
success = true; // if the DictionaryRenderer is used, m_graphic is null and that is ok.
|
||
}
|
||
|
||
} // if (geom.isEmpty())
|
||
}
|
||
|
||
}
|
||
else // !useDictionaryRenderMode(geomType)
|
||
{
|
||
createPictureMarker();
|
||
d->m_pictureMarker->setOrigin(this->origin());
|
||
|
||
// real work:
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
||
<< " update geometry";
|
||
|
||
|
||
if (d->m_symbol.changed() || m_scale.changed())
|
||
{
|
||
if (d->m_dictionary)
|
||
{
|
||
int widthPixel = SituationMap::SymbolSizeLdefault;
|
||
widthPixel *= symbolData_ref.size * m_scale.value();
|
||
|
||
d->m_symDataToRender.sidc = symbolData_ref.sidc;
|
||
d->m_symDataToRender.fillColor = symbolData_ref.color;
|
||
d->m_symDataToRender.fillColorReplace = true;
|
||
d->m_symDataToRender.sizeL = widthPixel;
|
||
|
||
if (d->m_pictureMarker->image().isNull())
|
||
d->m_pictureMarker->setImage(d->m_dictionary->temporaryImage(d->m_symDataToRender.sizeL));
|
||
d->m_symbolResultWatcher.setSymbolResult(d->m_dictionary->fetchSymbol(d->m_symDataToRender));
|
||
success = true;
|
||
}
|
||
else
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
|
||
<< " visibility=" << m_visibility
|
||
<< " no dictionary";
|
||
}
|
||
|
||
}
|
||
|
||
if (d->m_pictureMarker)
|
||
{
|
||
d->m_pictureMarker->setDrawOrder(m_drawOrder.value());
|
||
d->m_pictureMarker->setVisibility(m_visibility.value());
|
||
d->m_pictureMarker->setSelected(m_selected.value());
|
||
d->m_pictureMarker->setPickable(m_pickable.value());
|
||
|
||
success = success && d->m_pictureMarker->updateView();
|
||
}
|
||
} // else !useDictionaryRenderMode(geomType)
|
||
|
||
|
||
if (d->m_pictureMarker)
|
||
{
|
||
d->m_pictureMarker->setOrigin(this->origin()); // to avoid incorrect number of positions..
|
||
d->m_pictureMarker->setVisibility(m_visibility.value());
|
||
d->m_pictureMarker->setSelected(m_selected.value());
|
||
success = d->m_pictureMarker->updateView() && success;
|
||
}
|
||
|
||
// in case of no pictureMarker:
|
||
if (m_graphic)
|
||
{
|
||
m_graphic->setZIndex(m_drawOrder.value());
|
||
m_graphic->setVisible(m_visibility.value());
|
||
m_graphic->setSelected(m_selected.value());
|
||
}
|
||
|
||
// reset flags
|
||
d->m_symbol.reset();
|
||
|
||
if (!success)
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " failure, debugInfo='" << m_debugInfo << "'";
|
||
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
|
||
<< " success = " << success
|
||
<< " visibility=" << m_visibility;
|
||
return success;
|
||
}
|
||
|
||
|
||
} // namespace SituationMap
|