Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,428 @@
/**
* @RDE_HEADER@
* Interface-Implementation of NuclearAgent
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "nuclear_agent_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <Symbology/sidc_codec.h>
// ESRI
// Qt
#include <QList>
#include <QPainter>
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<BasicPathObjectImpl> basicPathObj;
NuclearAgent::OptionalData optData;
};
QMap<int, ValueDataNA> m_cont; /// one polyline per subsidiary line
using MAP_IT_T = QMapIterator<int, ValueDataNA>;
// int m_drawOrder = 0;
bool hasPathObject(int key) const { return m_cont.contains(key); }
QList<int> 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<BasicPathObjectImpl>(static_cast<BasicPathObjectImpl *>(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<BasicPathObjectImpl> pathObj = vd.basicPathObj;
if (pathObj)
pathObj->setPositions(positions);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QList<int> 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<BasicPathObjectImpl> 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