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,415 @@
/**
* @RDE_HEADER@
* Interface-Implementation of SingleFire
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "single_fire_central_impl.h"
#include "single_fire_impl.h"
#include <MapImpl/map_impl.h>
#include <Map/party_id_to_color_functor.h>
#include <GraphicalObjects/graphical_object_ellipse.h>
#include <GraphicalObjects/tactical_appearance.h>
#include <Symbology/sidc_codec.h>
// ESRI
#include <arcgis/GraphicsOverlay.h>
#include <arcgis/GraphicListModel.h>
#include <arcgis/GeometryEngine.h>
// Qt
#include <QPainter>
#include <QPen>
#include <QVariantAnimation>
#include <QTimer>
namespace SituationMap
{
class MyAnimation : public QVariantAnimation
{
public:
MyAnimation(GraphicalObjectSceneMarker *detonationSceneMarker)
: m_detonationSceneMarker(detonationSceneMarker)
{}
~MyAnimation() = default;
void updateCurrentValue(const QVariant &value)
{
if (!m_detonationSceneMarker)
return;
fs = m_detonationSceneMarker->fillStyle();
col = fs.fillColor();
col.setAlphaF(value.toFloat());
fs.setFillColor(col);
m_detonationSceneMarker->setFillStyle(fs);
m_detonationSceneMarker->updateView();
}
private:
GraphicalObjectSceneMarker *m_detonationSceneMarker{nullptr};
FillStyle fs;
QColor col;
};
//-----------------------------------------------------------------------------
// class SingleFireCentralImpl
//-----------------------------------------------------------------------------
SingleFireCentralImpl::SingleFireCentralImpl(const QString &debugInfo)
: SingleFireCentral() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("SingleFireCentralImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_fillColorAlpha = 200;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
SingleFireCentralImpl::~SingleFireCentralImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_animation;
delete m_centerImage;
delete m_detonationPath;
delete m_detonationSceneMarker;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString SingleFireCentralImpl::toString() const
{
QString str;
str.append(BaseClass::toString());
str.append(BasicPathObjectImpl::toString());
return str;
}
Point3D SingleFireCentralImpl::impactOrigin() const
{
return BaseClass::tacticalOrigin();
}
void SingleFireCentralImpl::setImpactOrigin(const Point3D &impactOrigin)
{
BaseClass::setTacticalOrigin(impactOrigin);
}
void SingleFireCentralImpl::setDetonation(const SingleFireCentral::DetonationData &detonationData)
{
if (m_detonationOrigin.value().origin() != detonationData.m_origin)
m_detonationOrigin.refValue().setOrigin(detonationData.m_origin);
m_detonationRadius = detonationData.m_radius;
}
SingleFireCentral::DetonationData SingleFireCentralImpl::detonation() const
{
return {m_detonationOrigin.value().origin(), m_detonationRadius.value()};
}
bool SingleFireCentralImpl::startDetonationAnimation()
{
if (!m_detonationSceneMarker)
return false;
if (!m_animation)
{
m_animation = new MyAnimation(m_detonationSceneMarker);
m_animation->setDuration(500);
m_animation->setKeyValueAt(0.0 , 1.0);
m_animation->setKeyValueAt(0.2 , 0.5);
m_animation->setKeyValueAt(1.0 , 0.1);
// m_animation.setEasingCurve(QEasingCurve::InOutQuart);
}
m_animation->stop();
m_animation->start();
if (!m_symbol3D)
{
qCritical() << " ModelSceneSymbol: ....:";
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Runtime/Data/3D/Bristol/Collada/Bristol.dae")), 5.0); // works
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Proof_of_concept_Explosion_DAE/Proof_of_concept_Explosion_DAE_01.dae")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Proof_of_concept_Explosion_DAE/Proof_of_concept_Explosion_DAE_02_60FPS.dae")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Proof_of_concept_Explosion_DAE/Proof_of_concept_Explosion_DAE_Sampled.dae")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Proof_of_concept_Explosion_DAE/Proof_of_concept_Explosion_DAE_unbaked.dae")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Proof_of_concept_Explosion_DAE/Proof_of_concept_Explosion_3ds_NoAnimation.3ds")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Runtime/Data/3D/3dexport/explosion/explosionFBX.fbx")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Runtime/Data/3D/3dexport/JetAnim/jet anim.fbx")), 10.0); // works
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Runtime/Data/3D/bradley_low_3ds/bradle.3ds")), 10.0); // works
m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QStringLiteral("/shd/CTC/TOOLS/ArcGIS/Runtime/Data/3D/dolmus_3ds/dolmus.3ds")), 10.0);
QObject::connect(m_symbol3D, &Esri::ArcGISRuntime::ModelSceneSymbol::errorOccurred,
m_animation, [](const Esri::ArcGISRuntime::Error &loadError){
qCritical() << " Error: : isEmpty:" << loadError.isEmpty();
qCritical() << " Error: : code:" << loadError.code();
qCritical() << " Error: : loadError:" << loadError.message();
});
QObject::connect(m_symbol3D, &Esri::ArcGISRuntime::ModelSceneSymbol::doneLoading,
m_animation, [](const Esri::ArcGISRuntime::Error &loadError){
qCritical() << " ModelSceneSymbol: doneLoading: isEmpty:" << loadError.isEmpty();
qCritical() << " ModelSceneSymbol: doneLoading: code:" << loadError.code();
qCritical() << " ModelSceneSymbol: doneLoading: loadError:" << loadError.message();
});
m_symbol3D->load();
if (!m_graphic3D)
{
Point3D pos = m_detonationOrigin.value().originTranslated();
m_graphic3D = new Esri::ArcGISRuntime::Graphic( Esri::ArcGISRuntime::Point(pos.x(), pos.y(), 20, m_mapImpl->getEsriSpatialReference()), m_symbol3D);
m_graphicsLayer->graphics()->append(m_graphic3D);
}
}
return true;
}
AesEffectState SingleFireCentralImpl::aesState() const
{
return BaseClass::aesState();
}
void SingleFireCentralImpl::setAesState(AesEffectState aesState)
{
BaseClass::setAesState(aesState);
}
SymbolImage SingleFireCentralImpl::symbolImage() const
{
SymbolImage symImage = m_tacticalAppearance->symbolImage();
return symImage;
}
bool SingleFireCentralImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " positions =" << this->positions()
<< " radius =" << this->radius()
<< " partyId =" << this->partyId()
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
if (m_tacticalAppearance)
{
if (partyChanged())
m_symbol.refValue().color = partyColor();
}
// centerImage:
if (!m_centerImage)
{
m_centerImage =
new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#CenterImage"),
m_uniqueMapId);
}
if (partyChanged())
{
QImage img = SingleFireImpl::renderImpactSymbol(partyColor(), 20, true); // filled
m_centerImage->setImage(img);
}
// m_centerImage->setScale(m_mainGraphicalObject->scale()); // do not scale centerImage, equal to mine of MineArea
m_centerImage->setOrigin(m_tacticalOrigin.value().originTranslated());
m_centerImage->setVisibility(m_visibility && m_visibilityTechnical);
bool success = BaseClass::updateViewImpl(); // will call onMapExtentChanged and therefore m_centerImage->updateView
bool successDetonationSceneMarker = true;
switch (m_mapImpl->mode())
{
case Mode::Mode_2D:
successDetonationSceneMarker = updateDetonationPath();
break;
case Mode::Mode_3D:
successDetonationSceneMarker = updateDetonationSceneMarker();
break;
case Mode::Undefined:
// empty
break;
}
success = success && successDetonationSceneMarker;
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SingleFireCentralImpl::updateDetonationPath()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = true;
// do we have a detonationPoint / impactOrigin?
if (m_detonationOrigin.value().origin().isNull() && (m_detonationRadius.value() < 1.0))
{
delete m_detonationPath;
m_detonationPath = nullptr;
} else {
if (!m_detonationPath)
{
m_detonationPath =
new GraphicalObjectEllipse(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#DetonationEllipse"),
m_uniqueMapId);
}
{
EllipseParameters ellipsePara;
ellipsePara.setLengthX(m_detonationRadius.value());
ellipsePara.setLengthY(m_detonationRadius.value());
ellipsePara.setMaxSegmentLength(1);
ellipsePara.setMaxPointCount(30); // limit to 30 to reduce the number of vertices. If to high, keep performance impact to 3D in mind!!!
m_detonationPath->setEllipseParameters(ellipsePara);
}
m_detonationPath->setOrigin(m_detonationOrigin.value().originTranslated());
m_detonationPath->setPickable(m_pickable);
// path == 0; indicationCont == 1; Marker == 2
m_detonationPath->setDrawOrder(m_internalDrawOrder+2);
QColor col = partyColor();
m_detonationPath->setLineStyle(LineStyle(col, 2));
col.setAlphaF(col.alphaF() / 2.0);
m_detonationPath->setFillStyle(FillStyle(col,
m_mainGraphicalObject->fillStyle().fillPattern())); // take fillpattern
m_detonationPath->setScale(this->scale());
success = m_detonationPath->updateView();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SingleFireCentralImpl::updateDetonationSceneMarker()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = true;
// do we have a detonationPoint / impactOrigin?
if (m_detonationOrigin.value().origin().isNull() && (m_detonationRadius.value() < 1.0))
{
delete m_detonationSceneMarker;
m_detonationSceneMarker = nullptr;
} else {
if (!m_detonationSceneMarker)
{
m_detonationSceneMarker =
new GraphicalObjectSceneMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#DetonationSceneMarker"),
m_uniqueMapId);
}
m_detonationSceneMarker->setOrigin(m_detonationOrigin.value().originTranslated());
m_detonationSceneMarker->setDiameter(m_detonationRadius.value()*2.0);
m_detonationSceneMarker->setPickable(m_pickable);
// path == 0; indicationCont == 1; Marker == 2
m_detonationSceneMarker->setDrawOrder(m_internalDrawOrder+2);
QColor col = partyColor();
col.setAlphaF(col.alphaF() / 2.0);
m_detonationSceneMarker->setFillStyle(FillStyle(col, FillPattern::Solid));
success = m_detonationSceneMarker->updateView();
}
// DEBUG: Animation in a loop
startDetonationAnimation();
// check intersect
if (m_detonationSceneMarker && m_mainGraphicalObject ){
Esri::ArcGISRuntime::GeometryEngine* geoEngine = Esri::ArcGISRuntime::GeometryEngine::instance();
Esri::ArcGISRuntime::Geometry geoLine = m_mainGraphicalObject->getGraphicGeometry();
qCritical() << " geoLine " << geoLine.toJson();
Esri::ArcGISRuntime::Geometry geoSphere = m_detonationSceneMarker->getGraphicGeometry();
qCritical() << " geoSphere " << geoSphere.toJson();
Esri::ArcGISRuntime::Geometry resultGeometry =
geoEngine->intersection(geoLine, geoSphere);
qCritical() << " resultGeometry " << resultGeometry.toJson();
}
if (m_animation)
QObject::connect(m_animation, &QVariantAnimation::finished, [this]()
{
QTimer::singleShot(2000, m_animation, [this]() {
m_animation->start();
});
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SingleFireCentralImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polyline);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
setLineStyle(LineStyle(Qt::black, 2));
m_detonationOrigin.refValue().setMapObjectImpl(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SingleFireCentralImpl::onMapExtentChanged()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool successCenterImage = true;
bool visiScale = m_visibilityScaleRange.scaleHasVisibility(m_mapImpl->scale());
if (m_centerImage)
{
m_centerImage->setVisibility(visiScale && m_visibility && m_visibilityTechnical);
successCenterImage = m_centerImage->updateView();
}
bool successDetonationSceneMarker = true;
if (m_detonationSceneMarker)
{
m_detonationSceneMarker->setVisibility(visiScale && m_visibility && m_visibilityTechnical);
successCenterImage = m_detonationSceneMarker->updateView();
}
bool success = BaseClass::onMapExtentChanged() && successCenterImage && successDetonationSceneMarker;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap