/** * @RDE_HEADER@ * Interface-Implementation of AbstractMapObject * $Id$ * $HeadURL$ * $Author$ */ // Own #include "abstract_map_object_impl.h" #include "map_impl.h" #include "object_container_impl.h" #include #include #include #include #include #include #include #include // ESRI #include #include #include // Qt namespace SituationMap { struct ExtraData { QVector propertyNames; QVector propertyValues; }; AbstractMapObjectImpl::AbstractMapObjectImpl(const QString &debugInfo) : AbstractMapObject() , m_uniqueMapId(SituationMap::INVALID_MAP_ID) , m_logger(getLogger("AbstractMapObjectImpl")) { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo='" << debugInfo << "'"; m_debugInfo = debugInfo; TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " debugInfo='" << debugInfo << "'"; } // AbstractMapObjectImpl::AbstractMapObjectImpl AbstractMapObjectImpl::~AbstractMapObjectImpl() { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo << " uniqueMapId=" << m_uniqueMapId; delete m_mapConnector; m_mapConnector = nullptr; resetPin(); delete m_tacticalAppearance; m_tacticalAppearance = nullptr; delete m_mainGraphicalObjectText; m_mainGraphicalObjectText = nullptr; resetGraphicalObjectExtrusion(); delete m_mainGraphicalObject; m_mainGraphicalObject = nullptr; delete m_extraData; m_extraData = nullptr; TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " debugInfo=" << m_debugInfo << " uniqueMapId=" << m_uniqueMapId; } // AbstractMapObjectImpl::~AbstractMapObjectImpl void AbstractMapObjectImpl::removeMySelf() { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo; // To avoid accessing already deleted variables make some local copies 2016/01/08 JT QString debugInfo = m_debugInfo; UniqueMapId uid = m_uniqueMapId; SituationMap::LOGGER_T logger(m_logger); if (m_mapImpl) { TRACE_LOG(m_logger) << "removeObject, uniqueMapId = " << m_uniqueMapId; m_uniqueMapId = SituationMap::INVALID_MAP_ID; m_mapImpl->objectContainer().removeObject(uid); } else ERROR_LOG(m_logger) << LOGFUNCTION << " m_mapImpl does not exist."; // Attention CRASH here if AbstractMapObject is not been referenced by a RefPointer. In this case the this-object has been deleted immediately 2016/01/08 JT TRACE_LOG(logger) << LOGFUNCTION << " END" << " debugInfo=" << debugInfo; } bool AbstractMapObjectImpl::setProperty(const char *name, const QVariant &value) { // following setProperty/property approach is take from qt4.8.5: if (!m_extraData) m_extraData = new ExtraData; const int idx = m_extraData->propertyNames.indexOf(name); if (!value.isValid()) { if (idx == -1) return false; m_extraData->propertyNames.removeAt(idx); m_extraData->propertyValues.removeAt(idx); } else { if (idx == -1) { m_extraData->propertyNames.append(name); m_extraData->propertyValues.append(value); } else m_extraData->propertyValues[idx] = value; } return true; } QVariant AbstractMapObjectImpl::property(const char *name) const { if (!m_extraData) return QVariant(); const int i = m_extraData->propertyNames.indexOf(name); return m_extraData->propertyValues.value(i); } UniqueMapId AbstractMapObjectImpl::uniqueMapId() const { return m_uniqueMapId; } QString AbstractMapObjectImpl::debugInfo() const { return m_debugInfo; } void AbstractMapObjectImpl::setDebugInfo(const QString &debugInfo) { m_debugInfo = debugInfo; if (m_mainGraphicalObject) m_mainGraphicalObject->setDebugInfo(m_debugInfo + QLatin1String("#mainGO")); else ERROR_LOG(m_logger) << LOGFUNCTION << " no object"; if (m_mainGraphicalObjectText) m_mainGraphicalObjectText->setDebugInfo(m_debugInfo + QLatin1String("#Text")); if (m_tacticalAppearance) m_tacticalAppearance->setDebugInfo(m_debugInfo + QLatin1String("#TactApp")); } QString AbstractMapObjectImpl::toString() const { QString str; if (!m_debugInfo.isEmpty()) str.append(QStringLiteral("debugInfo='%1'").arg(m_debugInfo)); str.append(QStringLiteral("uniqueMapId='%1'").arg(m_uniqueMapId)); if ((m_mainGraphicalObjectText) && (! m_mainGraphicalObjectText->text().isEmpty()) ) str.append(QStringLiteral(" identifier='%1'").arg(m_mainGraphicalObjectText->text())); if (!m_logicalLayerName.isEmpty()) str.append(QStringLiteral(" logicalLayerName='%1'").arg(m_logicalLayerName)); str.append(QStringLiteral(" partyId=%1").arg(m_party.partyId.value())); str.append(QStringLiteral(" aesState=%1").arg(SituationMap::toString(m_aesState.value()))); if (m_mainGraphicalObject) str.append(QStringLiteral(" scale='%1'").arg(m_mainGraphicalObject->scale())); str.append(QStringLiteral(" visibility='%1'").arg(m_visibility)); str.append(QStringLiteral(" visibilityTech='%1'").arg(m_visibilityTechnical)); str.append(QStringLiteral(" visibilityTact='%1'").arg(m_visibilityTactical)); str.append(QStringLiteral(" visibilityTechGeo='%1'").arg(m_visibilityTechnicalGeometry)); str.append(QStringLiteral(" identiferVisible=%1").arg(m_identiferVisible.value())); str.append(QStringLiteral(" selected='%1'").arg(m_selected)); str.append(QStringLiteral(" pickable='%1'").arg(m_pickable)); str.append(QStringLiteral(" majorColor='%1'").arg(this->majorColor().name(QColor::HexArgb))); return str; } void AbstractMapObjectImpl::boundingBox(SituationMap::BoundingBox &) const { // leave it empty and invalid. Method has to be overloaded if required. } void AbstractMapObjectImpl::setForceMajorColor(const QColor &majorColor) { m_forcedMajorColor = majorColor; } QColor AbstractMapObjectImpl::majorColor() const { if (m_forcedMajorColor.isValid()) return m_forcedMajorColor; if (m_mainGraphicalObject) return m_mainGraphicalObject->lineStyle().lineColor(); return QColor(); } double AbstractMapObjectImpl::extrusionHeight() const { return m_extrusionHeight; } void AbstractMapObjectImpl::setExtrusionHeight(double extrusionHeight) { if (m_mapImpl->mode() != Mode::Mode_3D) return; m_extrusionHeight = extrusionHeight; if (extrusionHeightValid()) createGraphicalObjectExtrusion(); else resetGraphicalObjectExtrusion(); } bool AbstractMapObjectImpl::extrusionHeightValid() const { return !std::isnan(m_extrusionHeight); } const QString AbstractMapObjectImpl::extrusionColorName() const { return m_extrusionColorName; } void AbstractMapObjectImpl::setExtrusionColorName(const QString &extrusionColorName) { m_extrusionColorName = extrusionColorName; } QString AbstractMapObjectImpl::identifier() const { if (m_mainGraphicalObjectText) return m_mainGraphicalObjectText->text(); // else // ERROR_LOG(m_logger) << LOGFUNCTION // << " debugInfo=" << m_debugInfo // << " no object" // ; return QString(); } void AbstractMapObjectImpl::createGraphicalObjectText() { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo; if (!m_mainGraphicalObjectText) { m_mainGraphicalObjectText = new GraphicalObjectText(m_mapImpl->getEsriGeoView() , m_graphicsLayer , m_debugInfo + QLatin1String("#Text") , uniqueMapId()); // Set default text style for all MapObjects: m_mainGraphicalObjectText->setTextStyle(defaultTextStyle()); m_mainGraphicalObjectText->setXOffset(10); // use as initial default } TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " debugInfo=" << m_debugInfo; } void AbstractMapObjectImpl::createTacticalAppearance() { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo; if (!m_tacticalAppearance) { m_tacticalAppearance = new TacticalAppearance(m_mapImpl, m_logicalLayerName, m_debugInfo + QStringLiteral("#TactApp"), m_uniqueMapId ); } TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " debugInfo=" << m_debugInfo; } void AbstractMapObjectImpl::resetTacticalAppearanceDrawOrderOffset() { m_tacticalAppearanceDrawOrderOffset = 0; } void AbstractMapObjectImpl::createPin() { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo; if (!m_graphicalObjectPin) { m_graphicalObjectPin = new GraphicalObjectPath(SituationMap::GraphicalObjectPathType::Polyline, m_mapImpl->getEsriGeoView(), m_graphicsLayer, m_debugInfo + QStringLiteral("#Pin"), m_uniqueMapId ); } TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " debugInfo=" << m_debugInfo; } void AbstractMapObjectImpl::resetPin() { delete m_graphicalObjectPin; m_graphicalObjectPin = nullptr; } void AbstractMapObjectImpl::setIdentifier(const QString &identifier) { if (identifier.isEmpty()) { delete m_mainGraphicalObjectText; m_mainGraphicalObjectText = nullptr; } else { createGraphicalObjectText(); if (m_mainGraphicalObjectText) m_mainGraphicalObjectText->setText(identifier); } } bool AbstractMapObjectImpl::identifierVisible() const { return m_identiferVisible.value(); } void AbstractMapObjectImpl::setIdentifierVisible(bool identifierVisible) { m_identiferVisible = identifierVisible; } int AbstractMapObjectImpl::partyId() const { return m_party.partyId.value(); } bool AbstractMapObjectImpl::isPartyIdValid() const { return m_party.partyId.value() >= 0; } void AbstractMapObjectImpl::setPartyId(int partyId) { m_party.partyId = partyId; } bool AbstractMapObjectImpl::setPartyIdChanged(int partyId) { if ((partyId < 0) || (m_party.partyId.value() == partyId)) { m_party.partyId.setChanged(); return true; } return false; } const QColor &AbstractMapObjectImpl::partyColor() const { if (m_party.forcedPartyColor.value().isValid()) return m_party.forcedPartyColor.value(); if (m_party.partyId.changed() || m_party.useLightColor.changed() || !m_party.partyColor.isValid()) { m_party.partyColor = m_mapImpl->partyIdToColorFunctor().partyIdToColor(m_party.partyId.value(), m_party.useLightColor.value()); } return m_party.partyColor; } QColor AbstractMapObjectImpl::partyColor(int partyId, bool useLightColor) const { return m_mapImpl->partyIdToColorFunctor().partyIdToColor(partyId, useLightColor); } void AbstractMapObjectImpl::forcePartyColor(const QColor &partyColorToForce) { m_party.forcedPartyColor = partyColorToForce; } bool AbstractMapObjectImpl::useLightColor() const { return m_party.useLightColor.value(); } void AbstractMapObjectImpl::setUseLightColor(bool useLightColor) { m_party.useLightColor = useLightColor; } AdvancedSymbology::Role AbstractMapObjectImpl::partyRole(bool roleIdentityAssumed) const { return m_mapImpl->partyIdToColorFunctor().partyIdToRole(m_party.partyId.value(), roleIdentityAssumed); } AesEffectState AbstractMapObjectImpl::aesState() const { return m_aesState.value(); } void AbstractMapObjectImpl::setAesState(AesEffectState aesState) { m_aesState = aesState; } TextStyle AbstractMapObjectImpl::textStyle() const { if (m_mainGraphicalObjectText) return m_mainGraphicalObjectText->textStyle(); else return TextStyle(); } TextStyle &AbstractMapObjectImpl::rTextStyle() { createGraphicalObjectText(); return m_mainGraphicalObjectText->rTextStyle(); } void AbstractMapObjectImpl::setTextStyle(const TextStyle &textStyle) { createGraphicalObjectText(); m_mainGraphicalObjectText->setTextStyle(textStyle); } LineStyle AbstractMapObjectImpl::lineStyle() const { return (m_mainGraphicalObject) ? m_mainGraphicalObject->lineStyle() : LineStyle(); } LineStyle &AbstractMapObjectImpl::rLineStyle() { static LineStyle dummy; return (m_mainGraphicalObject) ? m_mainGraphicalObject->rLineStyle() : dummy; } void AbstractMapObjectImpl::setLineStyle(const LineStyle &lineStyle) { if (m_mainGraphicalObject) m_mainGraphicalObject->setLineStyle(lineStyle); } FillStyle AbstractMapObjectImpl::fillStyle() const { return (m_mainGraphicalObject) ? m_mainGraphicalObject->fillStyle() : FillStyle(); } FillStyle &AbstractMapObjectImpl::rFillStyle() { static FillStyle dummy; return (m_mainGraphicalObject) ? m_mainGraphicalObject->rFillStyle() : dummy; } void AbstractMapObjectImpl::setFillStyle(const FillStyle &fillStyle) { if (m_mainGraphicalObject) m_mainGraphicalObject->setFillStyle(fillStyle); } QString AbstractMapObjectImpl::layer() const { return logicalLayerName(); } void AbstractMapObjectImpl::setDrawOrder(int drawOrder) { m_drawOrder = drawOrder; m_internalDrawOrder = m_drawOrder * 10; } int AbstractMapObjectImpl::drawOrder() const { return m_drawOrder; } bool AbstractMapObjectImpl::visibility() const { return m_visibility; } void AbstractMapObjectImpl::setVisibility(bool visibility) { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo << " visi old=" << m_visibility; m_visibility = visibility; TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " debugInfo=" << m_debugInfo << " visi new=" << m_visibility; } bool AbstractMapObjectImpl::visibility(ObjectAppearance appearance) const { bool visi = true; switch (appearance) { case SituationMap::ObjectAppearance::Technical: visi = m_visibilityTechnical; break; case SituationMap::ObjectAppearance::Tactical: visi = m_visibilityTactical; break; } return visi; } void AbstractMapObjectImpl::setVisibility(ObjectAppearance appearance, bool visibility) { switch (appearance) { case SituationMap::ObjectAppearance::Technical: m_visibilityTechnical = visibility; break; case SituationMap::ObjectAppearance::Tactical: m_visibilityTactical = visibility; break; default: ERROR_LOG(m_logger) << LOGFUNCTION << " ObjectAppearance not found"; break; } TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo=" << m_debugInfo << " m_visibilityTechnical=" << m_visibilityTechnical << " m_visibilityTactical=" << m_visibilityTactical; } bool AbstractMapObjectImpl::visibilityOfGeometry() const { return m_visibilityTechnicalGeometry; } void AbstractMapObjectImpl::setVisibilityOfGeometry(bool visiGeometry) { m_visibilityTechnicalGeometry = visiGeometry; } bool AbstractMapObjectImpl::selected() const { return m_selected; } void AbstractMapObjectImpl::setSelected(bool selected) { m_selected = selected; } bool AbstractMapObjectImpl::pickable() const { return m_pickable; } void AbstractMapObjectImpl::setPickable(bool pickable) { m_pickable = pickable; } float AbstractMapObjectImpl::scale() const { return (m_mainGraphicalObject) ? m_mainGraphicalObject->scale() : 0.0f; } void AbstractMapObjectImpl::setScale(float scale) { if (!m_enableScale) return; // typically the mainGraphicalObject does NOT need any scale values, // but keep it similar to identifier, textStyle, fillStyle etc. // mainGraphicalObjectText will receive the value within ::updateView() if (m_mainGraphicalObject) m_mainGraphicalObject->setScale(scale); } bool AbstractMapObjectImpl::isScaleEnabled() const { return m_enableScale; } void AbstractMapObjectImpl::setScaleEnable(bool enabled) { m_enableScale = enabled; } SymbolData AbstractMapObjectImpl::symbol() const { return m_symbol.value(); } void AbstractMapObjectImpl::setSymbol(const SymbolData &symbol) { m_symbol = symbol; } void AbstractMapObjectImpl::reRenderSymbol() { m_symbol.setChanged(); } SymbolDataToRender AbstractMapObjectImpl::symbolDataToRender() const { return m_symbol.value().getDefaultRenderData(); } SymbolImage AbstractMapObjectImpl::symbolImage() const { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; return m_symbolImage; } QImage AbstractMapObjectImpl::previewImage() const { return previewImageTypical(); } QImage AbstractMapObjectImpl::previewImageTypical() const { return m_symbolImage.image(); } QImage AbstractMapObjectImpl::previewImageSpecific() const { return m_symbolImage.image(); } TextStyle AbstractMapObjectImpl::defaultTextStyle() { TextStyle ts; // Define default text style for all MapObjects ts.setTextOutlineColor(Qt::white); // Define default text style for all MapObjects ts.setTextOutlineWidth(0.5); // Define default text style for all MapObjects return ts; } bool AbstractMapObjectImpl::updateTacticalAppearance() { bool successTactAppearance = true; if (m_tacticalAppearance) { m_tacticalAppearance->setUniqueDesignation(identifier()); m_tacticalAppearance->setDrawOrder(m_internalDrawOrder + m_tacticalAppearanceDrawOrderOffset); // m_tacticalAppearanceDrawOrderOffset == 2 m_tacticalAppearance->setVisibility(m_visibility && m_visibilityTactical); m_tacticalAppearance->setSelected(m_selected); m_tacticalAppearance->setPickable(m_pickable); if (m_symbol.changed()) m_tacticalAppearance->setSymbol(m_symbol.value()); if (m_mainGraphicalObject) m_tacticalAppearance->setScale(m_mainGraphicalObject->scale()); else ERROR_LOG(m_logger) << LOGFUNCTION << " m_mainGraphicalObject missing!!!"; successTactAppearance = m_tacticalAppearance->updateView(); } return successTactAppearance; } void AbstractMapObjectImpl::createGraphicalObjectExtrusion() { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo; if (m_mapImpl->mode() != Mode::Mode_3D) return; if (!m_graphicalObjectExtrusion) { Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer = m_mapImpl->getGraphicsLayer3DExtrusion(m_logicalLayerName); if (!graphicsLayer) { ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'" << " getGraphicsLayer3DExtrusion failed"; return; } m_graphicalObjectExtrusion = new GraphicalObjectCube(m_mapImpl->getEsriGeoView(), graphicsLayer, // ESRI-Layer, not logical m_debugInfo + QStringLiteral("#GO3D"), m_uniqueMapId ); } TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " debugInfo=" << m_debugInfo; } void AbstractMapObjectImpl::resetGraphicalObjectExtrusion() { delete m_graphicalObjectExtrusion; m_graphicalObjectExtrusion = nullptr; } bool AbstractMapObjectImpl::updateGraphicalObjectExtrusion() { bool successGo3D = true; if (m_graphicalObjectExtrusion) { m_graphicalObjectExtrusion->setUniqueMapId(m_uniqueMapId); // geometry: if (m_mainGraphicalObject) m_graphicalObjectExtrusion->setPositions(m_mainGraphicalObject->positions()); // translated / maybe they are densified? m_graphicalObjectExtrusion->setDrawOrder(m_internalDrawOrder); m_graphicalObjectExtrusion->setVisibility(m_visibility && m_visibilityTechnical); m_graphicalObjectExtrusion->setSelected(m_selected); m_graphicalObjectExtrusion->setPickable(m_pickable); if (m_extrusionColorName.isEmpty()) { // Fallback const QColor &partyColor = m_mapImpl->partyIdToColorFunctor().partyIdToColor(m_party.partyId.value()); m_graphicalObjectExtrusion->setExtrusionColorName(partyColor.name()); } else { m_graphicalObjectExtrusion->setExtrusionColorName(m_extrusionColorName); } m_graphicalObjectExtrusion->setHeight(m_extrusionHeight); // scale....?? successGo3D = m_graphicalObjectExtrusion->updateView(); } return successGo3D; } bool AbstractMapObjectImpl::updatePin() { TRACE_LOG(m_logger) << LOGFUNCTION << " START, m_debugInfo=" << m_debugInfo; if (m_graphicalObjectPin) { m_graphicalObjectPin->setDrawOrder(m_internalDrawOrder + 5); // m_tacticalAppearanceDrawOrderOffset == 2 m_graphicalObjectPin->setVisibility(m_visibility); m_graphicalObjectPin->setSelected(m_selected); m_graphicalObjectPin->setPickable(m_pickable); if (m_mainGraphicalObject) { m_graphicalObjectPin->setLineStyle(LineStyle(Qt::black, 3, LinePattern::DashDotDot)); m_graphicalObjectPin->setScale(m_mainGraphicalObject->scale()); } else ERROR_LOG(m_logger) << LOGFUNCTION << " m_mainGraphicalObject missing!!!"; // // m_graphicalObjectPin->setPositions and updateView is called at GeoImageImpl::onMapExtentChanged() // } TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_debugInfo=" << m_debugInfo; return true; } void AbstractMapObjectImpl::updateIdentifierPosition() { m_identifierPositionCandidateTranslated = m_mainGraphicalObject->origin(); } bool AbstractMapObjectImpl::updateViewImplPre() { // // createTacticalAppearance onDemand // if (!m_symbol.value().sidc.isEmpty()) createTacticalAppearance(); // // partyId (and its resulting color) has priority to lineColor, fillColor: // if (isPartyIdValid() && partyChanged()) { const QColor &partyCol = partyColor(); if (m_mainGraphicalObject) { if (m_lineColorFromParty) m_mainGraphicalObject->rLineStyle().setLineColor(partyCol); QColor fillColor(partyCol); fillColor.setAlpha(m_fillColorAlpha); m_mainGraphicalObject->rFillStyle().setFillColor(fillColor); } if (m_mainGraphicalObjectText) m_mainGraphicalObjectText->rTextStyle().setTextColor(partyCol); // maybe continued for TacticalAppearance } // // if state!=Unknown -> its resulting pattern has priority to fillPattern: // if ((m_aesState.value() != AesEffectState::Unknown) && m_aesState.changed()) { if (m_mainGraphicalObject) { FillPattern pattern = m_mapImpl->partyIdToColorFunctor().aesStateToPattern(m_aesState.value()); m_mainGraphicalObject->rFillStyle().setFillPattern(pattern); } } return true; } inline bool isSurfacePlacementRelevant(Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer) { if (!graphicsLayer) return false; // maybe also SurfacePlacement::RelativeToScene ??? return (graphicsLayer->sceneProperties().surfacePlacement() == Esri::ArcGISRuntime::SurfacePlacement::Relative); } bool AbstractMapObjectImpl::updateViewImpl() { bool success = true; bool successTactAppearance = true; TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId << " m_pickable=" << m_pickable; // drawOrder : // The LayerOrder could be added if required like... // finalDrawOrder = m_mapImpl->layerFactory()-> indexOf(m_logicalLayerName); if (m_mainGraphicalObjectText) { m_mainGraphicalObjectText->setDrawOrder(m_internalDrawOrder + 2); // +2 to provide space for indicationCont (e.g. mines of MineField) m_mainGraphicalObjectText->setScale(m_mainGraphicalObject->scale()); } // : drawOrder if (m_mainGraphicalObject) { m_mainGraphicalObject->setDrawOrder(m_internalDrawOrder); m_mainGraphicalObject->setVisibility(m_visibility && m_visibilityTechnical && m_visibilityTechnicalGeometry); m_mainGraphicalObject->setSelected(m_selected); m_mainGraphicalObject->setPickable(m_pickable); success = m_mainGraphicalObject->updateView(); if (m_mainGraphicalObjectText) { this->updateIdentifierPosition(); m_mainGraphicalObjectText->setScale(m_mainGraphicalObject->scale()); // m_mainGraphicalObjectText->setSelected(m_selected); // Text should NEVER be selected m_mainGraphicalObjectText->setPickable(m_pickable); // mainGraphicalObjectText->updateView() will be called within following 'onMapExtentChanged()': // successGoText = m_mainGraphicalObjectText->updateView(); } } successTactAppearance = updateTacticalAppearance(); bool successGoExtrusion = true; if (m_graphicalObjectExtrusion && (m_mapImpl->mode() == Mode::Mode_3D)) { successGoExtrusion = updateGraphicalObjectExtrusion(); if (!successGoExtrusion) ERROR_LOG(m_logger) << LOGFUNCTION << " failure updateGraphicalObjectExtrusion " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId; } bool successUpdatePin = true; if (m_graphicalObjectPin && (this->mapImpl()->mode() == Mode::Mode_3D) && isSurfacePlacementRelevant(m_graphicsLayer)) { successUpdatePin = updatePin(); if (!successUpdatePin) ERROR_LOG(m_logger) << LOGFUNCTION << " failure0 (updatePin) " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId; } bool successMapExtendChanged = this->onMapExtentChanged(); if (!success) ERROR_LOG(m_logger) << LOGFUNCTION << " failure1 " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId; if (!successTactAppearance) ERROR_LOG(m_logger) << LOGFUNCTION << " failure2 " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId; if (!successGoExtrusion) ERROR_LOG(m_logger) << LOGFUNCTION << " failure3 " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId; if (!successMapExtendChanged) ERROR_LOG(m_logger) << LOGFUNCTION << " failure4 " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId; TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId; return success && successTactAppearance && successGoExtrusion && successUpdatePin && successMapExtendChanged; } bool AbstractMapObjectImpl::updateViewImplPost() { partyReset(); m_aesState.reset(); m_symbol.reset(); m_identiferVisible.reset(); if (m_updateObjectIndicator) { for (auto *ptr : qAsConst(m_originPositionChangedCb)) ptr->onOriginPositionChanged(); } m_updateObjectIndicator = false; return true; } int AbstractMapObjectImpl::numberOfValuesChanged() { int count = 0; if (m_party.changed()) { WARNING_LOG(m_logger) << LOGFUNCTION << " START "; ++count; } if (m_aesState.changed()) { WARNING_LOG(m_logger) << LOGFUNCTION << " START "; ++count; } if (m_symbol.changed()) { WARNING_LOG(m_logger) << LOGFUNCTION << " START "; ++count; } if (m_identiferVisible.changed()) { WARNING_LOG(m_logger) << LOGFUNCTION << " START "; ++count; } return count; } void AbstractMapObjectImpl::addChangedCallback(OriginPositionChangedCallback *cb) { m_originPositionChangedCb.push_back(cb); } void AbstractMapObjectImpl::removeChangedCallback(OriginPositionChangedCallback *cb) { m_originPositionChangedCb.removeAll(cb); } bool AbstractMapObjectImpl::init(MapImpl *mapImpl, const QString &logicalLayerName) { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo; bool success = true; if (mapImpl) m_mapImpl = mapImpl; else { success = false; ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo=" << m_debugInfo << " no mapImpl"; } m_mapConnector = new SituationMap::MapConnector(); success = success && m_mapConnector->connectMapObject(m_mapImpl, this); if (success) { success = this->setLogicalLayerName(logicalLayerName); if (!success) { ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo=" << m_debugInfo << " setLogicalLayerName failed" << ", logicalLayerName='" << logicalLayerName << "'"; } } else { ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo=" << m_debugInfo << " MapConnector->connectObject failed"; } // take static scaleHasVisibilityValue; m_visibilityScaleRange.setInitial(s_scaleHasVisibilityValue); // static mamber of interface class. TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " debugInfo=" << m_debugInfo << " success=" << success; return success; } void AbstractMapObjectImpl::setUniqueId(const UniqueMapId &uniqueId) { m_uniqueMapId = uniqueId; if (m_mainGraphicalObject) m_mainGraphicalObject->setUniqueMapId(m_uniqueMapId); if (m_mainGraphicalObjectText) m_mainGraphicalObjectText->setUniqueMapId(m_uniqueMapId); if (m_tacticalAppearance) m_tacticalAppearance->setUniqueMapId(m_uniqueMapId); } bool AbstractMapObjectImpl::onMapExtentChanged() { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo; bool success = true; // Some MapObjects like ParticipantImpl do NOT use m_mainGraphicalObjectText: if (m_mainGraphicalObjectText && m_mapImpl) { // hide identifier on zoom out??? // old approach: // double meterPerPixel = -1.0; // if (m_mapImpl) // meterPerPixel = m_mapImpl->pixelSize(); // bool textVisi = meterPerPixel < 3000; // new approach: // double curScale = m_mapImpl->scale(); // bool textVisi = m_visibilityScaleRange.scaleHasVisibility(curScale); // m_mainGraphicalObjectText->setVisibility(m_visibility && m_visibilityTechnical && textVisi); // TRACE_LOG(m_logger) << LOGFUNCTION << " START" // << " debugInfo=" << m_debugInfo << "'" // << " meterPerPixel=" << m_mapImpl->pixelSize() // << " newScale=" << m_mapImpl->scale() // << " newExtent = " << SituationMap::toString(m_mapImpl->extent()); // m_mainGraphicalObjectText->setVisibility(m_visibility && m_visibilityTechnical && textVisi); // do NOT hide identifier on zoom out: m_mainGraphicalObjectText->setVisibility(m_visibility && m_visibilityTechnical && m_identiferVisible.value()); m_mainGraphicalObjectText->setOrigin(m_identifierPositionCandidateTranslated); success = m_mainGraphicalObjectText->updateView(); } TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " debugInfo=" << m_debugInfo << "'" << " success=" << success; return true; } QString AbstractMapObjectImpl::logicalLayerName() const { return m_logicalLayerName; } bool AbstractMapObjectImpl::setLogicalLayerName(const QString &logicalLayerName) { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo='" << m_debugInfo << "'" << " logicalLayerName='" << logicalLayerName << "'"; m_logicalLayerName = logicalLayerName; bool success = false; m_graphicsLayer = m_mapImpl->getGraphicsLayer(logicalLayerName); if (m_graphicsLayer) success = true; else { ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo=" << m_debugInfo << "'" << ", no layer found"; } TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " debugInfo='" << m_debugInfo << "'" << " logicalLayerName='" << logicalLayerName << "'" << " success=" << success; return success; } bool AbstractMapObjectImpl::geometryIntersect(const MathUtils::GeometryEngine::Geometry &intersector_polyline) const { if (intersector_polyline.isEmpty()) return false; if (m_mainGraphicalObject) { Esri::ArcGISRuntime::GraphicsOverlay *esriLayer = m_mainGraphicalObject->graphicsLayer(); if ((esriLayer) && (esriLayer->isVisible())) { // former: if (m_mainGraphicalObject->visibility()) // MineField stores the ountline/boundary in m_mainGraphicalObject to transfer this to m_tacticalAppearance // That m_mainGraphicalObject is NOT visible, because of that fillPattern. // to 'find' that MineField, anaylze just m_visibility && m_visibilityTechnical, and not m_visibilityTechnicalGeometry if (m_visibility && m_visibilityTechnical) { if (MathUtils::GeometryEngine::intersect(m_mainGraphicalObject->getGraphicGeometry(), intersector_polyline)) return true; } } } // m_mainGraphicalObjectText if (m_tacticalAppearance) { Esri::ArcGISRuntime::GraphicsOverlay *esriLayer = m_tacticalAppearance->graphicsLayer(); if ((esriLayer) && (esriLayer->isVisible())) { if (m_tacticalAppearance->visibility()) { if (MathUtils::GeometryEngine::intersect(m_tacticalAppearance->getGraphicGeometry(), intersector_polyline)) return true; } } } return false; } // bool AbstractMapObjectImpl::geometryIntersect( const MathUtils::GeometryEngine::Geometry & geom ) bool AbstractMapObjectImpl::geometryIsInHull(const MathUtils::GeometryEngine::Geometry &hull_polygon) const { if (hull_polygon.isEmpty()) return false; if (m_mainGraphicalObject) { Esri::ArcGISRuntime::GraphicsOverlay *esriLayer = m_mainGraphicalObject->graphicsLayer(); if ((esriLayer) && (esriLayer->isVisible())) { // former: if (m_mainGraphicalObject->visibility()) // MineField stores the ountline/boundary in m_mainGraphicalObject to transfer this to m_tacticalAppearance // That m_mainGraphicalObject is NOT visible, because of that fillPattern. // to 'find' that MineField, anaylze just m_visibility && m_visibilityTechnical, and not m_visibilityTechnicalGeometry if (m_visibility && m_visibilityTechnical) { if (MathUtils::GeometryEngine::contains(m_mainGraphicalObject->getGraphicGeometry(), hull_polygon)) return true; } } } // m_mainGraphicalObjectText if (m_tacticalAppearance) { Esri::ArcGISRuntime::GraphicsOverlay *esriLayer = m_tacticalAppearance->graphicsLayer(); if ((esriLayer) && (esriLayer->isVisible())) { if (m_tacticalAppearance->visibility()) { if (MathUtils::GeometryEngine::contains(m_tacticalAppearance->getGraphicGeometry(), hull_polygon)) return true; } } } return false; } Esri::ArcGISRuntime::Geometry AbstractMapObjectImpl::getEsriGeometry() const { if (!m_mainGraphicalObject) return Esri::ArcGISRuntime::Geometry(); return m_mainGraphicalObject->getGraphicGeometry(); } } // namespace SituationMap