/** * @RDE_HEADER@ * Interface-Implementation of NuclearAgent * $Id$ * $HeadURL$ * $Author$ */ // Own #include "nuclear_agent_impl.h" #include #include #include #include // ESRI // Qt #include #include namespace SituationMap { // to get access to 'init' using NAgentLocalBasicPathObject = LocalBasicPathObject; QImage renderImpactSymbol(const QColor &color, int size, bool filled) { QImage image(size, size, QImage::Format_ARGB32); image.fill(Qt::transparent); QPainter painter(&image); QPen pen(color); int penWidth = size/10; if (penWidth < 2) penWidth = 2; pen.setWidth(penWidth); painter.setPen(pen); const int sizeHalf = size / 2; QPointF center(sizeHalf, sizeHalf); // circle if (filled) painter.setBrush(color); painter.drawEllipse(center, sizeHalf * 0.5, sizeHalf * 0.5); // lines QLine newLine(0, sizeHalf, size / 4.0, sizeHalf); painter.drawLine(newLine); QTransform trans; trans.translate(sizeHalf, sizeHalf); trans.rotate(45); trans.translate(-sizeHalf, -sizeHalf); // 8 are required, one is already draw, so 7: for (int i=0; i<7; ++i) { newLine = trans.map(newLine); painter.drawLine(newLine); } painter.end(); return image; } class NuclearAgentImpl::Private { public: Private() = default; ~Private() = default; // ESRI data: // Esri::ArcGISRuntime::GraphicsOverlay *m_graphicsLayer = nullptr; // Own data: MapImpl *m_mapImpl{nullptr}; QString m_logicalLayer; QString m_debugInfo; // will be appended by consecutive number UniqueMapId m_uniqueMapId{INVALID_MAP_ID}; GraphicalObjectPictureMarker *m_centerImage{nullptr}; struct ValueDataNA { QSharedPointer basicPathObj; NuclearAgent::OptionalData optData; }; QMap m_cont; /// one polyline per subsidiary line using MAP_IT_T = QMapIterator; // int m_drawOrder = 0; bool hasPathObject(int key) const { return m_cont.contains(key); } QList keysInUse() const { return m_cont.keys(); } void remove(int key) { m_cont.remove(key); } void clear() { m_cont.clear(); } ValueDataNA getPathObject(int key, const OptionalData &optData = OptionalData()) { auto ret = m_cont.value(key); // copy if (ret.basicPathObj.isNull()) { QString debugInfo = QStringLiteral("%1#SubsidiaryLine(%2)").arg(m_debugInfo).arg(key); NAgentLocalBasicPathObject *temp = new NAgentLocalBasicPathObject(debugInfo); GraphicalObjectPathType pathType = GraphicalObjectPathType::Polyline; if (optData.closed) pathType = GraphicalObjectPathType::Polygon; bool success = temp->init(m_mapImpl, m_logicalLayer, pathType); temp->setUniqueId(m_uniqueMapId); if (success) ret.basicPathObj = QSharedPointer(static_cast(temp)); else temp->removeMySelf(); ret.optData.closed = optData.closed; } // transfer optional data (line|fill) to ret and then to container _if_ set: if (optData.lineStyle) ret.optData.lineStyle = optData.lineStyle; if (optData.fillStyle) ret.optData.fillStyle = optData.fillStyle; m_cont.insert(key, ret); return ret; } }; // class NuclearAgentImpl::Private //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // class NuclearAgentImpl //----------------------------------------------------------------------------- NuclearAgentImpl::NuclearAgentImpl(const QString &debugInfo) : NuclearAgent() // Interface , BaseClass(debugInfo) // Implementation , d(new Private) , m_logger(getLogger("NuclearAgentImpl")) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; m_fillColorAlpha = 200; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } NuclearAgentImpl::~NuclearAgentImpl() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; delete d->m_centerImage; delete d; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } void NuclearAgentImpl::setUniqueId(const UniqueMapId &uniqueId) { BaseClass::setUniqueId(uniqueId); d->m_uniqueMapId = m_uniqueMapId; } PositionCont NuclearAgentImpl::subsidiaryLine(int key) const { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; if (d->hasPathObject(key)) return d->getPathObject(key).basicPathObj->positions(); else return PositionCont(); } void NuclearAgentImpl::setSubsidiaryLine(int key, const PositionCont &positions, const OptionalData &optData) { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << ", key=" << key << ", closed=" << optData.closed << ", positions.size=" << positions.size(); Private::ValueDataNA vd = d->getPathObject(key, optData); QSharedPointer pathObj = vd.basicPathObj; if (pathObj) pathObj->setPositions(positions); TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } QList NuclearAgentImpl::subsidiaryKeysInUse() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; return d->keysInUse(); } void NuclearAgentImpl::removeSubsidiaryLine(int key) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; return d->remove(key); } void NuclearAgentImpl::removeSubsidiaryLines() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; return d->clear(); } Point3D NuclearAgentImpl::impactOrigin() const { return BaseClass::tacticalOrigin(); } void NuclearAgentImpl::setImpactOrigin(const Point3D &impactOrigin) { BaseClass::setTacticalOrigin(impactOrigin); } void NuclearAgentImpl::setDetonation(const Point3D &origin, double radius) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; BaseClass::setDetonation(origin, radius); TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } bool NuclearAgentImpl::hasDetonation() const { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; return BaseClass::hasDetonation(); } void NuclearAgentImpl::resetDetonation() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; BaseClass::resetDetonation(); TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } bool NuclearAgentImpl::updateViewImpl() { DEBUG_LOG(m_logger) << LOGFUNCTION << " START" << " symbol=" << m_symbol.value().sidc << " visibility=" << m_visibility << " visiTechn=" << m_visibilityTechnical << " visiTact=" << m_visibilityTactical; // centerImage: if (!d->m_centerImage) { d->m_centerImage = new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(), m_graphicsLayer, m_debugInfo + QLatin1String("#CenterImage"), m_uniqueMapId); } // if (partyChanged()) { // QImage img = renderImpactSymbol(partyColor(), 20, true); // filled QImage img = renderImpactSymbol(m_mainGraphicalObject->lineStyle().lineColor(), 20, true); // filled d->m_centerImage->setImage(img); } // m_centerImage->setScale(m_mainGraphicalObject->scale()); // do not scale centerImage, equal to mine of MineArea d->m_centerImage->setOrigin(m_tacticalOrigin.value().originTranslated()); d->m_centerImage->setVisibility(m_visibility && m_visibilityTechnical); bool success = BaseClass::updateViewImpl(); if (!success) { ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed"; return false; } if (nullptr == m_mainGraphicalObject) { ERROR_LOG(m_logger) << LOGFUNCTION << " no m_mainGraphicalObject"; return false; } // subsidiary : Private::MAP_IT_T mapIt(d->m_cont); while (mapIt.hasNext()) { mapIt.next(); const Private::ValueDataNA &vd = mapIt.value(); QSharedPointer pathObj = vd.basicPathObj; const OptionalData &optData = vd.optData; if (pathObj) { // pathObj->setDebugInfo(m_mainGraphicalObject->debugInfo()); // will overwrite complete string -> skip if (optData.lineStyle) pathObj->setLineStyle((*optData.lineStyle.data())); else pathObj->setLineStyle(m_mainGraphicalObject->lineStyle()); // transfer fillStyle only if relevant: if (pathObj->pathType() == GraphicalObjectPathType::Polygon) { if (optData.fillStyle) pathObj->setFillStyle((*optData.fillStyle.data())); else pathObj->setFillStyle(m_mainGraphicalObject->fillStyle()); } pathObj->setVisibility(m_visibility); pathObj->setVisibility(ObjectAppearance::Technical, m_visibilityTechnical); // Do not Transfer symbol. Only m_mainGraphicalObject uses ObjectAppearance::Tactical: // pathObj->setSymbol(this->symbol()); pathObj->setVisibility(ObjectAppearance::Tactical, false); pathObj->setPickable(m_mainGraphicalObject->pickable()); pathObj->setSelected(m_mainGraphicalObject->selected()); pathObj->setDrawOrder(m_internalDrawOrder); success = pathObj->updateView(); if (!success) { int key = mapIt.key(); ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed, key=" << key; } } } // while // : subsidiary // singleSceneMarker : updateSingleSceneMarker(m_visibility); // inclusive updateView() // : singleSceneMarker TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success; return success; } bool NuclearAgentImpl::init(MapImpl *mapImpl, const QString &logicalLayerName) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; if (mapImpl) { switch (mapImpl->symbologyType()) { case AdvancedSymbology::SymbologyType::APP6D: case AdvancedSymbology::SymbologyType::MIL2525D: m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10012500002719000000"); // SymbolSet = 25 271900 break; case AdvancedSymbology::SymbologyType::MIL2525C: m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUMPNR----"); // MIL2525D: 1388 GUMPNR---- -> Polygon (Radioactive Area U) // m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GUMPNZ----"); // MIL2525D: 0359 GUMPNZ---- -> Point (Nuclear Detonations Ground Zero U) break; case AdvancedSymbology::SymbologyType::APP6B: m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUCPBWR---"); // APP6B: 3935 GUCPBWR--- -> Polygon // m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GUCPBWP---"); // APP6B: 2871 GUCPBWP--- -> Point (Fallout Producing U) break; case AdvancedSymbology::SymbologyType::None: // empty break; } // switch } // if (mapImpl) bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon); setLineStyle(LineStyle(Qt::yellow, 2)); setFillStyle(FillStyle(Qt::yellow, FillPattern::Null)); if (!success) ERROR_LOG(m_logger) << LOGFUNCTION << " init failed"; // set some values to Private: d->m_mapImpl = m_mapImpl; d->m_logicalLayer = m_logicalLayerName; d->m_debugInfo = m_debugInfo; d->m_uniqueMapId = m_uniqueMapId; TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success; return success; } bool NuclearAgentImpl::onMapExtentChanged() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; bool successCenterImage = true; if (d->m_centerImage) { bool visiScale = m_visibilityScaleRange.scaleHasVisibility(m_mapImpl->scale()); d->m_centerImage->setVisibility(visiScale && m_visibility && m_visibilityTechnical); successCenterImage = d->m_centerImage->updateView(); } bool success = BaseClass::onMapExtentChanged() && successCenterImage; TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success; return success; } } // namespace SituationMap