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,47 @@
#
# monitoring of the target areas
# $Id$
# $HeadURL$
# $Author$
#
#ADD_SUBDIRECTORY(UnitTests)
FIND_PACKAGE(ArcGIS REQUIRED)
SET(SRCS
plugin.cpp
plugin.h
../../aes_item_view_utm.cpp
../../aes_item_view_utm.h
handler_explosions.cpp
handler_explosions.h
handler_vulcano.cpp
handler_vulcano.h
expand_polygon.cpp
expand_polygon.h
isInCone.cpp
isInCone.h
settings.cpp
settings.h
line_of_sight.cpp
line_of_sight.h
)
NGL_ADD_LIBRARY(AAR SV cesPluginExplosions MODULE ${SRCS})
NGL_TARGET_LINK_LIBRARIES(cesPluginExplosions
Qt5::Core
ArcGIS::ArcGIS
Qt5::Network
Qt5::Widgets
NGLLogger
cesPluginInterface
ngldb
LtsCoordinate
svcCesDDSCommon
svcTabClient
svcAesClient
svcPdmClient
)
NGL_INSTALL_TARGET(cesPluginExplosions)
@@ -0,0 +1,62 @@
/**
* @RDE_HEADER@
* Extend a polygon by a distance of <double> meters.
* $Id$
* $HeadURL$
* $Author$
*/
#include "expand_polygon.h"
#include <CentralEffectSimulation/logger.h>
#include <arcgis/PolygonBuilder.h>
#include <arcgis/GeometryEngine.h>
namespace CesExplosions
{
namespace ExpandPolygon
{
QPolygonF bufferUtmPolygon(const QPolygonF &polygonUtmIn, const int zone, const double distance, double maxDeviation, QString *errorOut)
{
static CentralEffectSimulation::LOGGER_T logger = CentralEffectSimulation::getLogger("Plugin.Explosions.HandlerExplosions");
// return (polygonUtmIn);
Q_UNUSED(maxDeviation);
Esri::ArcGISRuntime::PolygonBuilder polygonBuilder(Esri::ArcGISRuntime::SpatialReference(32600 + zone));
DEBUG_LOG(logger) << "ExpandPolygon::bufferUtmPolygon";
for (const QPointF &pointUtm : qAsConst(polygonUtmIn))
polygonBuilder.addPoint(Esri::ArcGISRuntime::Point(pointUtm.x(), pointUtm.y(), 0));
const Esri::ArcGISRuntime::Geometry &esriGeometry = polygonBuilder.toGeometry();
const Esri::ArcGISRuntime::Polygon polyline =
Esri::ArcGISRuntime::GeometryEngine::buffer(esriGeometry, distance);
if (polyline.parts().isEmpty())
{
if (errorOut)
*errorOut = QStringLiteral("GeometryEngine::buffer failed (no parts");
return {};
}
const Esri::ArcGISRuntime::ImmutablePart &immutablePart = polyline.parts().part(0);
const int size = immutablePart.pointCount();
QPolygonF bufferedPoly;
bufferedPoly.reserve(size);
for (int i = 0; i < size; ++i)
{
const Esri::ArcGISRuntime::Point &esriP = immutablePart.point(i);
bufferedPoly.append(QPointF(esriP.x(), esriP.y()));
}
DEBUG_LOG(logger) << "ExpandPolygon return bufferedPoly size=" << bufferedPoly.size();
return bufferedPoly;
}
} // namespace ExpandPolygon
} // namespace CesExplosions
@@ -0,0 +1,23 @@
/**
* @RDE_HEADER@
* Extend a polygon by a distance of <double> meters.
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QPolygonF>
#include <QString>
namespace CesExplosions
{
namespace ExpandPolygon
{
QPolygonF bufferUtmPolygon(const QPolygonF &polygonUtmIn, const int zone, double distance, double maxDeviation = 1, QString *errorOut = nullptr);
} // namespace ExpandPolygon
} // namespace CesExplosions
@@ -0,0 +1,99 @@
/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2017-02-20
*/
#pragma once
#include "line_of_sight.h"
#include <CentralEffectSimulation/logger.h>
//#include <CentralEffectSimulation/dds_handler.h>
#include <CentralEffectSimulation/aes_item_view_utm.h>
#include <CentralEffectSimulation/handler_participant.h>
//#include <CentralEffectSimulation/proxy_building.h>
#include <QHash>
#include <QVector>
#include <QPolygonF>
// AES-Handling for Artillery
namespace CES_Artillery
{
enum class RANGE
{
LETHAL = 1,
NON_LETHAL = 2,
HAZARD_DISTANCE = 3,
OUTSIDE = 4
};
QString toString(RANGE range);
//------------------------------------------------------------------------------
// Helper class EnteredHarzardDistanceStorage
//------------------------------------------------------------------------------
class EnteredHarzardDistanceStorage final
{
public:
Q_DISABLE_COPY(EnteredHarzardDistanceStorage)
EnteredHarzardDistanceStorage();
~EnteredHarzardDistanceStorage();
void participantEnteringArea(int participantId, int areaId);
void participantLeavingArea(int participantId, int areaId);
bool hasParticipantAlreadyEnteredArea(int participantId, int areaId) const; ///< or isWithinArea?
void removeParticipant(int participantId);
void removeArea(int aesItemId);
QVector<int> allParticipantIdsOfArea(int areaId) const;
private:
class Private;
/**
* The private d->pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
};
//------------------------------------------------------------------------------
// Helper class HandledImpactsStorage
//------------------------------------------------------------------------------
class HandlerArtilleryLogic final
{
public:
using AES_ITEM_VIEW_UTM_CONST_ITER = QHash<int, CentralEffectSimulation::AesItemViewUtm>::const_iterator;
HandlerArtilleryLogic();
~HandlerArtilleryLogic() = default;
int checkPartEnterLeaveArea(HandlerArtilleryLogic::AES_ITEM_VIEW_UTM_CONST_ITER currentAreaIt,
const HandlerArtilleryLogic::AES_ITEM_VIEW_UTM_CONST_ITER &endingAreaIt,
CentralEffectSimulation::HandlerParticipant::POSITIONS_CONST_ITER currentParticipantIt,
const CentralEffectSimulation::HandlerParticipant::POSITIONS_CONST_ITER &endingParticipantIt);
QVector<double> chargeRanges(int chargeTypeId) const;
static RANGE getMostInnerRange(const QVector<double> &ranges, double currentDistance);
private: // attributes
// std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant;
// std::shared_ptr<CentralEffectSimulation::ProxyBuilding> m_proxyBuilding;
EnteredHarzardDistanceStorage m_enteredHazardDistanceStore; // which participant are in which areas (aesItemids)
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
};
} // namespace CES_Artillery
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,237 @@
/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2017-02-20
*/
#pragma once
#include "line_of_sight.h"
#include <CentralEffectSimulation/logger.h>
#include <CentralEffectSimulation/dds_handler.h>
#include <CentralEffectSimulation/aes_item_view_utm.h>
#include <CentralEffectSimulation/handler_participant.h>
#include <CentralEffectSimulation/proxy_building.h>
#include <AreaEffectSimulation/aes_ftc.h>
#include <AreaEffectSimulation/Utils/aes_helper.h>
#include <ProjectDataManagement/pdm_dtc.h>
#include <TrainingAreaBase/tab_ftc.h>
#include <QtCore/QObject>
#include <QtCore/QMap>
#include <QtCore/QHash>
#include <QtCore/QVector>
#include <QPolygonF>
#include <QQueue>
#include <QTimer>
// AES-Handling for Explosions
namespace CesExplosions
{
enum class EffectType
{
Unknown = 0,
EffectiveMineRangeEnter = 0xf0000 | 1, // AtMineAreaSingleMines = 15 = 0xf
EffectiveMineRangeLeave = 0xf0000 | 2, // AtMineAreaSingleMines = 15 = 0xf
NContaminationLeave = 0x10000 | 0, // AtNContamination = 1
NContaminationEnterArea1 = 0x10000 | 1,
NContaminationEnterArea2 = 0x10000 | 2,
NContaminationDetonation = 0x10000 | 255,
FunctionalAreaLeave = 0xc0000 | 0, // AtReconArea = 12 = 0xc
FunctionalAreaEnter = 0xc0000 | 1,
ExplosionArea = 0x30000 | 2, // AtExplosionArea = 3
ExplosionSingle = 0x40000 | 3, // AtExplosionSingle = 4
BCContaminationLeave = 0x20000 | 0, // AtBCContamination = 2
BCContaminationEnterFloating = 0x20000 | 1,
BCContaminationEnterResident = 0x20000 | 2,
BCContaminationEnterFloatingArea = 0x20000 | 3,
BeStillWarning = 11,
};
struct ParticipantDistance
{
double squareDistance = 0;
CentralEffectSimulation::HandlerParticipant::CesParticipantData participantPosition;
};
enum class RANGE
{
LETHAL = 1,
NON_LETHAL = 2,
HAZARD_DISTANCE = 3,
OUTSIDE = 4
};
QString toString(RANGE range);
//------------------------------------------------------------------------------
// Helper class HandledImpactsStorage
//------------------------------------------------------------------------------
class EnteredHarzardDistanceStorage final
{
public:
Q_DISABLE_COPY(EnteredHarzardDistanceStorage)
EnteredHarzardDistanceStorage();
~EnteredHarzardDistanceStorage();
void participantEnteringArea(int participantId, int areaId);
void participantLeavingArea(int participantId, int areaId);
bool hasParticipantAlreadyEnteredArea(int participantId, int areaId) const; ///< or isWithinArea?
void removeParticipant(int participantId);
void removeArea(int aesItemId);
QVector<int> allParticipantIdsOfArea(int areaId) const;
private:
class Private;
/**
* The private d->pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
};
//------------------------------------------------------------------------------
// class HandlerExplosions
//------------------------------------------------------------------------------
class HandlerExplosions : public QObject
, protected TrainingAreaBase::Interface::Ftc::SendCesHitReplyHandler
{
Q_OBJECT
public:
using AES_ITEM_VIEW_UTM_CONST_ITER = QHash<int, CentralEffectSimulation::AesItemViewUtm>::const_iterator;
explicit HandlerExplosions(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
const std::shared_ptr<CentralEffectSimulation::ProxyBuilding> &proxyBuilding,
QObject *parent = nullptr);
~HandlerExplosions();
/**
* Initialize the handler to manage information from player management
*/
bool init();
protected:
void onSendCesHitReply(const Core::FunctionReplyObject &replyObject) override final;
private slots:
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
void onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType);
void onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType);
void onEffectsChanged(const AreaEffectSimulation::Effects &effects, DataModification modType);
void onNewParticipantCesPosition(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData);
void onRestoreRadioReadinessChanged(const int participantId);
void onChargeEffectChanged(const AreaEffectSimulation::ChargeEffect &data, DataModification modType);
void onStartTimeReached();
private: // structs
private: // methoden
bool inBoundingBoxCheck(const CentralEffectSimulation::AesItemViewUtm &itemViewUtm,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition);
void calculateSmartEffect(const AreaEffectSimulation::Effects &effects);
void calculateSmartExplosion(const int32_t aesItemId,
const AreaEffectSimulation::ChargeStruct &chargeStruct,
int32_t partyId,
const Core::GeoPosition2D &impactPosition,
qint64 impactTime);
void calculateImpact(const AreaEffectSimulation::ChargeEffect &data);
void calculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data);
void calculateImpacts(const CentralEffectSimulation::AesItemViewUtm &itemView,
const QVector<int> &impactsToCheck,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition);
void calculateImpactsEffect(const CentralEffectSimulation::AesItemViewUtm &itemView,
const QVector<LtsCoordTrans::LtsCoordinate> &triggeredEffectsLtsCoord,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
Options lineOfSightOptions);
void calculateImpactsEffect_outdated(const CentralEffectSimulation::AesItemViewUtm &itemView,
const std::vector<Core::GeoPosition> &triggeredEffectsGeoPos,
const QVector<QPointF> &triggeredEffectsUtmPos,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
Options lineOfSightOptions);
bool inCircle(const QPointF &centerUtm, const double radius, const QPointF &pointUtm);
QVector<double> chargeRanges(const AreaEffectSimulation::ChargeStruct &chargeStruct) const;
int iedClassToEffect(int iedClass) const;
static RANGE getMostInnerRange(const QVector<double> &ranges, double currentDistance);
RANGE getMostInnerRange(double currentDistance, const AreaEffectSimulation::ChargeStruct &chargeStruct, int &retEffect);
int checkPartEnterLeaveArea(HandlerExplosions::AES_ITEM_VIEW_UTM_CONST_ITER currentAreaIt,
const AES_ITEM_VIEW_UTM_CONST_ITER &endingAreaIt,
CentralEffectSimulation::HandlerParticipant::POSITIONS_CONST_ITER currentParticipantIt,
const CentralEffectSimulation::HandlerParticipant::POSITIONS_CONST_ITER &endingParticipantIt);
void sendEffectTypeEvent(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
EffectType effectType,
qint64 effectTime);
void sendCesHitRequest(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const qint64 effectTime,
const int remaining,
const ProjectDataManagement::EventType eventType);
double getSquareDistance(const QPointF &centerUtm, const QPointF &pointUtm);
void sendEnterHazardDistance(const int participantId, const int aesItemId);
void sendLeaveHazardDistance(const int participantId, const int aesItemId, const int remaining);
void on_newHazardInfo(int participantId, int aesId);
void sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &item,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const ProjectDataManagement::EventType eventType);
void startTimer(int id, int msec);
private: // attributes
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant;
std::shared_ptr<CentralEffectSimulation::ProxyBuilding> m_proxyBuilding;
// AES-Values
// m_aesItemViewsUtm enthält die übergeordneteten Daten (extent) der Wirkfelder (z.B. für bbox check)
QHash<int, CentralEffectSimulation::AesItemViewUtm> m_aesItemViewsUtm; // key = aesItemId [GUEZE-2484]
// m_aesItemViewsImpactsUtm enthält die Coords für die Einschläge der ExplosionCluster / ClusterSingleExplosions
QHash<int, CentralEffectSimulation::AesItemViewUtm> m_aesItemViewsImpactsUtm; // key = aesItemId only for HIT [GUEZE-2484]
QQueue<TrainingAreaBase::SendCesHitRequest> m_sendCesHitRequestQueue;
#ifdef ORIGINATOR_AT_SENDCESHITREQUEST
// N. Thoden, 18.11.2024
// Wurde bis ca. 2022 bei onExlosionAreaChanged 'gefüllt'.
// Mit Umstellung auf ExplosionCluster (3D_wirksim in 2023/2024) scheinbar outdated.
QHash<int32_t, int> m_aesItemId2partIdMap; // Key = aesItemId value= participantId
#endif // ORIGINATOR_AT_SENDCESHITREQUEST
AreaEffectSimulation::HandledImpactsStorage m_handledImpactsStorage; // for ExplosionCluster and all former
EnteredHarzardDistanceStorage m_enteredHazardDistanceStore; // which participant are in which areas (aesItemids)
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
QHash<int, AreaEffectSimulation::ChargeEffect> m_chargeEffects; // key = onChargeEffectChanged.id value ChargeEffect
};
//Q_DECLARE_OPERATORS_FOR_FLAGS(Options)
} // namespace CesExplosions
@@ -0,0 +1,417 @@
/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2017-02-20
*/
#include "handler_vulcano.h"
#include "expand_polygon.h"
#include "isInCone.h"
#include "settings.h"
#include <LtsUtilsCore/dds_bitarray.h>
#include <LtsUtilsCore/qpoint3d.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <CentralEffectSimulation/handler_participant.h>
#include <QPainterPath>
#include <QPointF>
#include <QPolygonF>
#include <QVector>
#include <QTimer>
#include <QTransform>
#include <QDateTime>
#include <QVariant>
namespace CesExplosions
{
HandlerVulcano::HandlerVulcano(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
QObject *parent)
: QObject(parent)
, m_ddsHandler(ddsHandler)
, m_logger(CentralEffectSimulation::getLogger("Plugin.Explosions.HandlerVulcano"))
{
} // end of ctor()
//-----------------------------------------------------------------------------
HandlerVulcano::~HandlerVulcano()
{
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerVulcano::init()
{
auto dtcAes = m_ddsHandler->dtcAes();
auto ftcAes = m_ddsHandler->ftcAes();
auto dtcPpm = m_ddsHandler->dtcPpm();
ftcAes->enableTargetPositionsModify();
dtcAes->enableExplosionCluster();
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::explosionClusterChanged,
this, &HandlerVulcano::onExplosionClusterChanged);
dtcAes->enableTrajectoryTimeAware();
dtcPpm->enableDynamicParticipantData();
connect(dtcPpm.get(), &ParticipantManagement::Interface::Dtc::dynamicParticipantDataChanged,
this, &HandlerVulcano::onDynamicParticipantChanged);
float vulcanoViewAngleDeg = CesExplosions::Settings::vulcanoViewAngleDeg();
float vulcanoAttackAngleDeg = CesExplosions::Settings::vulcanoAttackAngleDeg();
float vulcanoAlphaDeg = CesExplosions::Settings::vulcanoMaximumDesignationAngleDeg();
DEBUG_LOG(m_logger) << "vulcanoViewAngleDeg=" << vulcanoViewAngleDeg
<< " vulcanoAttackAngleDeg=" << vulcanoAttackAngleDeg
<< " vulcanoAlphaDeg=" << vulcanoAlphaDeg;
return true;
} // end of init()
//-----------------------------------------------------------------------------
void HandlerVulcano::onTargetPositionsModifyReply(const Core::FunctionReplyObject &replyObject)
{
if (replyObject.error())
WARNING_LOG(m_logger) << "Can not send TargetPositionsRequest: " << replyObject();
else
DEBUG_LOG(m_logger) << "TargetPositionsRequest for id " << replyObject.id() << " success\n"
<< " replyObject.str() = " << replyObject.str();
}
// ///////////////////////////////////
// A E S (AreaEffectSimulation)
// ///////////////////////////////////
void HandlerVulcano::onExplosionClusterChanged(const AreaEffectSimulation::ExplosionCluster &data, DataModification modType)
{
// order checks by effort:
if ((modType == DataModification::eRemoved)
|| (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsExpired)
|| (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsActivated))
return;
if (!data.effectStart().is_set())
{
DEBUG_LOG(m_logger) << "No effectStart";
return;
}
// Kriterium fuer NASAT/MIDAS
if (m_ddsHandler->dtcPdm()->gearClassFromChargeTypeId(data.chargeStruct().chargeTypeId()) == ProjectDataManagement::GearClass_def::AirSupport)
return;
if (!m_ddsHandler->isLaserGuidable(data.chargeStruct()))
return;
if (!data.flightCurve().is_set() || !data.laserGuiding().is_set())
return;
const AreaEffectSimulation::FlightCurve &fcData = data.flightCurve().get();
const AreaEffectSimulation::LaserGuiding &lgData = data.laserGuiding().get();
DEBUG_LOG(m_logger) << "\n onExplosionClusterChanged id=" << data.id()
<< " AesEffectState=" << data.effectStateId()
<< " lcPrf=" << lgData.lcAttack()
<< " originalEffectDuration=" << data.originalEffectDuration()
<< " effectStart=" << data.effectStart();
DEBUG_LOG(m_logger) << "m_prfToAesId.insert(" << lgData.lcAttack() << ", " << data.id() << ")"
<< " tapTimepoint=" << lgData.tapTime()
<< " currentPartitionTime=" << m_ddsHandler->currentPartitionTime()
<< " Timer interval =" << lgData.tapTime() - m_ddsHandler->currentPartitionTime();
int aesId = data.id();
QTimer *timer = new QTimer(this);
timer->setSingleShot(true);
QObject::connect(timer, &QTimer::timeout,
this, &HandlerVulcano::onFiringTimeTimeout);
if (m_aesTimers.contains(data.id()))
{
m_aesTimers.value(data.id())->stop();
delete m_aesTimers.value(data.id());
m_aesTimers.remove(data.id());
}
m_aesTimers.insert(data.id(), timer);
timer->setProperty("aesId", aesId);
{
long long effectStart = data.effectStart().is_set() ? data.effectStart().get() : 0;
long long calculatedFlightDurationMSec = fcData.calculatedFlightDuration();
long long currentPartitionTime = m_ddsHandler->currentPartitionTime();
const int timerTimeout = effectStart - calculatedFlightDurationMSec - currentPartitionTime;
DEBUG_LOG(m_logger) << "Timer started mit Abflugzeit des Vulcano=" << timerTimeout;
if (timerTimeout >= 0)
timer->start(timerTimeout);
}
m_explosionCluster.insert(data.id(), data);
}
void HandlerVulcano::onFiringTimeTimeout()
{
DEBUG_LOG(m_logger) << "++++++++++++++ onFiringTimeTimeout";
QTimer *t = qobject_cast<QTimer *>(sender());
int aesId = t->property("aesId").toInt();
delete m_aesTimers.value(aesId);
m_aesTimers.remove(aesId);
DEBUG_LOG(m_logger) << "onTimerTimeout aesId=" << aesId;
const auto &myEC = m_explosionCluster.value(aesId);
if (myEC.id() != aesId)
return;
if (!myEC.flightCurve().is_set())
return;
const AreaEffectSimulation::FlightCurve &fcData = myEC.flightCurve().get();
//auto dtcPpm = m_ddsHandler->dtcPpm();
//auto participantId = dtcPpm.get()->getParticipantFromPrf(prf);
//auto dpd = dtcPpm.get()->dynamicParticipantData(participantId);
//DEBUG_LOG(m_logger) << "onTimerTimeout participantId=" << participantId;
QTimer *timer = new QTimer(this);
timer->setSingleShot(true);
QObject::connect(timer, &QTimer::timeout,
this, &HandlerVulcano::onTrajectoryTimeAwareTimeout);
if (m_aesTimers.contains(aesId))
{
m_aesTimers.value(aesId)->stop();
delete m_aesTimers.value(aesId);
m_aesTimers.remove(aesId);
}
m_aesTimers.insert(aesId, timer);
timer->setProperty("aesId", aesId);
auto dtcAes = m_ddsHandler->dtcAes();
const AreaEffectSimulation::TrajectoryTimeAware &trajectoryTimeAware = firstTrajectoryTimeAwareFromAesId(aesId);
if (trajectoryTimeAware.geometry().size() < 2)
{
DEBUG_LOG(m_logger) << "return";
return;
}
/* x | Tap (aka TapT)
// \ |
// \ |
// \ |
// \ |
// -------x | CloudBase (Tap_strich)
// \ |
// \ |
// ----------x | Impact
//
// ----------------| Surface
*/
const std::vector<Core::GeoPositionRelativeTime> &geometryRef = trajectoryTimeAware.geometry();
int calculatedFlightDurationMSec = fcData.calculatedFlightDuration();
// TAP' kann auch TAP sein -> Es ist immer der vorletzte Wert. = size() - 2.
int relTimeTap = geometryRef[geometryRef.size() - 2].relativeTime();
// Der letzte Wert ist immer der Einschlag = size() - 1.
int relTimeExplosion = geometryRef[geometryRef.size() - 1].relativeTime();
// Flugzeit zwischen TAP(') und Einschlag
int timeDiffTapToExplosion = relTimeExplosion - relTimeTap;
// Somit ist die absolute Zeit am TAP(') die Startzeit abzüglich der Flugzeit
int absTimeAtTap = myEC.effectStart().get() - timeDiffTapToExplosion;
// Und die ist in wieviel Sekunden?
int relTimeToTap = absTimeAtTap - m_ddsHandler->currentPartitionTime();
DEBUG_LOG(m_logger) << "timer->start timeout= " << relTimeToTap
<< " calculatedFlightDurationMSec= " << calculatedFlightDurationMSec;
if (relTimeToTap >= 0)
timer->start(relTimeToTap);
}
void HandlerVulcano::onTrajectoryTimeAwareTimeout()
{
QTimer *t = qobject_cast<QTimer *>(sender());
int aesId = t->property("aesId").toInt();
delete m_aesTimers.value(aesId);
m_aesTimers.remove(aesId);
DEBUG_LOG(m_logger) << "++++++++++++++ onTrajectoryTimeAwareTimeout aesId=" << aesId;
const auto &myEC = m_explosionCluster.value(aesId);
if (myEC.id() != aesId)
return;
if (!myEC.laserGuiding().is_set())
return;
const AreaEffectSimulation::LaserGuiding &lgData = myEC.laserGuiding().get();
const int prf = lgData.lcAttack();
const auto &dtcPpm = m_ddsHandler->dtcPpm();
const auto &dtcAes = m_ddsHandler->dtcAes();
auto participantId = dtcPpm->getParticipantFromPrf(prf);
auto dpd = dtcPpm->dynamicParticipantData(participantId);
const auto &designationsVec = dpd.designations();
DEBUG_LOG(m_logger) << "onTimerTimeout participantId=" << participantId;
for (const auto &designation : qAsConst(designationsVec))
{
if (designation.code() == prf && designation.outputPower() > 0)
{
const AreaEffectSimulation::TrajectoryTimeAware &trajectoryTimeAware = firstTrajectoryTimeAwareFromAesId(aesId);
const std::vector<Core::GeoPositionRelativeTime> &trajGeometry = trajectoryTimeAware.geometry();
DEBUG_LOG(m_logger) << "trajectoryTimeAware.geometry().size()=" << trajGeometry.size();
DEBUG_LOG(m_logger) << "Designation code=" << designation.code()
<< " prf=" << prf
<< " outputPower=" << designation.outputPower()
<< " designation.spotlocation=" << designation.spotLocation().lon() << "/" << designation.spotLocation().lat();
if (trajGeometry.size() < 2)
{
DEBUG_LOG(m_logger) << "return";
return;
}
const Core::GeoPosition topGeo = trajGeometry.at(trajGeometry.size() - 2);
const Core::GeoPosition bottomGeo = trajGeometry.at(trajGeometry.size() - 1);
const Core::GeoPosition2D pointToTestGeo = designation.spotLocation();
int zone = -1;
const QPointF &topPt = CentralEffectSimulation::geographic2Utm(topGeo, &zone);
const QPointF &bottomPt = CentralEffectSimulation::geographic2Utm(bottomGeo, &zone);
const QPointF &pointToTestPt = CentralEffectSimulation::geographic2Utm(pointToTestGeo, &zone);
const QVector3D top(topPt.x(), topPt.y(), topGeo.z());
DEBUG_LOG(m_logger) << "top=" << top.x() << "/" << top.y() << "/" << top.z() << " zone=" << zone;
const QVector3D bottom(bottomPt.x(), bottomPt.y(), bottomGeo.z());
DEBUG_LOG(m_logger) << "bottom=" << bottom.x() << "/" << bottom.y() << "/" << bottom.z() << " zone=" << zone;
const QVector3D pointToTest(pointToTestPt.x(), pointToTestPt.y(), designation.spotLocation().z());
DEBUG_LOG(m_logger) << "pointToTest=" << pointToTest.x() << "/" << pointToTest.y() << "/" << pointToTest.z() << " zone=" << zone;
float vulcanoViewAngleDeg = CesExplosions::Settings::vulcanoViewAngleDeg();
float vulcanoAttackAngleDeg = CesExplosions::Settings::vulcanoAttackAngleDeg();
DEBUG_LOG(m_logger) << "vulcanoViewAngleDeg=" << vulcanoViewAngleDeg
<< " vulcanoAttackAngleDeg=" << vulcanoAttackAngleDeg;
if (! isInCone(top, bottom, vulcanoAttackAngleDeg, pointToTest))
{
DEBUG_LOG(m_logger) << "Punkt ist ausserhalb des Attack Angles. ";
return;
}
const auto observerPos = dtcPpm->participantPosition(participantId).pos();
QPointF fePt = CentralEffectSimulation::geographic2Utm(trajGeometry.at(0), &zone);
QVector3D fe(fePt.x(), fePt.y(), 0);
QVector3D lp = pointToTest;
QPointF observerPt = CentralEffectSimulation::geographic2Utm(observerPos, &zone);
QVector3D observer(observerPt.x(), observerPt.y(), 0);
double angle = CesExplosions::Settings::vulcanoMaximumDesignationAngleDeg();
DEBUG_LOG(m_logger) << "isInAngle fe=" << fe.x() << "/" << fe.y()
<< ", lp=" << lp.x() << "/" << lp.y()
<< ", observer=" << observer.x() << "/" << observer.y()
<< ", angle=" << angle
<< ", zone=" << zone;
if (! isInCone(lp, fe, angle, observer))
{
DEBUG_LOG(m_logger) << "Keine neue Vulcano-Pos: Winkel ist zu gross. ";
return;
}
//designation.spotLocation()
Core::GeoPosition posVulcano = getTrajectoryPosFromTime(aesId, static_cast<long long>(m_ddsHandler->currentPartitionTime()));
AreaEffectSimulation::TargetPositionsModifyRequest posModify;
posModify.aesItemId(aesId);
posModify.positions().push_back(designation.spotLocation());
DEBUG_LOG(m_logger) << "targetPositionsModifyRequest z=" << posModify.positions().at(0).z()
<< " designation.z=" << designation.spotLocation().z()
<< " PosVulcano=" << posVulcano.lon() << "/" << posVulcano.lat();
m_ddsHandler->ftcAes()->targetPositionsModifyRequest(posModify, this);
return;
}
} // for
}
AreaEffectSimulation::TrajectoryTimeAware HandlerVulcano::firstTrajectoryTimeAwareFromAesId(int aesId)
{
// be aware of: [E01562-259] use originatorId, originatorTypeId (instead of aesItemId, aesTypeId)
const auto &dtcAes = m_ddsHandler->dtcAes();
const auto &trajectories = dtcAes->trajectoriesTimeAwareFromOriginatorIdAndType(aesId,
ProjectDataManagement::StateChangeOriginator::AreaEffectSimulation);
if (trajectories.empty())
{
DEBUG_LOG(m_logger) << "no trajectories found for originatorId/aesItemId " << aesId;
return {};
}
Q_ASSERT_X(trajectories.size() == 1, __FUNCTION__, "For Vulcano there should be just one trajectory");
const auto &trajectoryTimeAwareValue = trajectories[0];
return trajectoryTimeAwareValue;
}
Core::GeoPosition HandlerVulcano::getTrajectoryPosFromTime(int aesId, long long timeParam)
{
// be aware of: [E01562-259] use originatorId, originatorTypeId (instead of aesItemId, aesTypeId)
const auto &trajectoryTimeAwareValue = firstTrajectoryTimeAwareFromAesId(aesId);
const qint64 relTime = timeParam - trajectoryTimeAwareValue.trajectoryStartTime();
//trajectoryTimeAwareValue = trajectoryTimeAware(aesId);
DEBUG_LOG(m_logger) << " getTrajectoryPosFromTime aesId=" << aesId
<< " trajectoryTimeAwareValue.id=" << trajectoryTimeAwareValue.id()
<< " time=" << timeParam
<< " trajectoryStartTime=" << trajectoryTimeAwareValue.trajectoryStartTime()
<< " relTime=" << relTime;
if (trajectoryTimeAwareValue.geometry().empty())
{
DEBUG_LOG(m_logger) << "getTrajectoryPosFromTime no pos available";
return {};
}
Core::GeoPosition result;
int i = 0;
for (const auto &point : qAsConst(trajectoryTimeAwareValue.geometry()))
{
DEBUG_LOG(m_logger) << "time=" << point.relativeTime();
if ( (point.relativeTime() > relTime) && (i > 0))
{
// Beachte: Geschwindigkeit wird _NICHT_ beruecksichtigt
const Core::GeoPositionRelativeTime &geoPosRelTime = trajectoryTimeAwareValue.geometry()[i-1];
// avoid expensive operations like following
// result.lat() = trajectoryTimeAwareValue.geometry()[i -1].lat();
// result.lon() = trajectoryTimeAwareValue.geometry()[i -1].lon();
// result.z() = trajectoryTimeAwareValue.geometry()[i -1].z();
// and take benefits from downcasting
result = geoPosRelTime; // implicit downcast :-)
DEBUG_LOG(m_logger) << "found i=" << i
<< " result=" << result.lat() << "/" << result.lon() << "/" << result.z();
return result;
}
++i;
} // for
result = trajectoryTimeAwareValue.geometry().back();
DEBUG_LOG(m_logger) << " return last point result="
<< " result=" << result.lat() << "/" << result.lon() << "/" << result.z();
return result;
}
void HandlerVulcano::onDynamicParticipantChanged(const ParticipantManagement::DynamicParticipantData &data, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
DEBUG_LOG(m_logger) << "onDynamicParticipantChanged"
<< data.participantId()
<< data.designations().size();
if (data.designations().size() > 0)
{
for (const ParticipantManagement::LaserDesignation &designation : qAsConst(data.designations()))
{
DEBUG_LOG(m_logger) << "gearId=" << designation.gearId()
<< " code=" << designation.code()
<< " z=" << designation.spotLocation().z()
<< " outputPower=" << designation.outputPower();
}
}
}
} // namespace CesExplosions
@@ -0,0 +1,86 @@
/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2017-02-20
*/
#pragma once
#include <CentralEffectSimulation/logger.h>
#include <CentralEffectSimulation/dds_handler.h>
#include <CentralEffectSimulation/aes_item_view_utm.h>
#include <CentralEffectSimulation/handler_participant.h>
#include <AreaEffectSimulation/aes_dtc.h>
#include <AreaEffectSimulation/aes_ftc.h>
#include <ProjectDataManagement/pdm_dtc.h>
#include <QtCore/QObject>
#include <QtCore/QMap>
#include <QtCore/QHash>
#include <QtCore/QVector>
#include <QPolygonF>
#include <QQueue>
#include <QHash>
#include <QTimer>
namespace LtsUtils
{
class QPoint3D;
}
// AES-Handling for Explosions
namespace CesExplosions
{
//------------------------------------------------------------------------------
// class HandlerVulcano
//------------------------------------------------------------------------------
class HandlerVulcano : public QObject
, protected AreaEffectSimulation::Interface::Ftc::TargetPositionsModifyReplyHandler
{
Q_OBJECT
public:
typedef QHash<int, QSet<int>> BitfieldStates;
explicit HandlerVulcano(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
QObject *parent = nullptr);
~HandlerVulcano();
/**
* Initialize the handler to manage information from player management
*/
bool init();
protected:
void onTargetPositionsModifyReply(const Core::FunctionReplyObject &replyObject) override final;
private slots:
void onExplosionClusterChanged(const AreaEffectSimulation::ExplosionCluster &data, DataModification modType);
void onDynamicParticipantChanged(const ParticipantManagement::DynamicParticipantData &data, DataModification modType);
void onFiringTimeTimeout();
void onTrajectoryTimeAwareTimeout();
private: // functions
// firstTrajectoryTimeAwareFromAesId and getTrajectoryPosFromTime were initially created as AesDtcCustomFunction.
// But since they are very specific, they were moved to this place:
AreaEffectSimulation::TrajectoryTimeAware firstTrajectoryTimeAwareFromAesId(int aesId);
Core::GeoPosition getTrajectoryPosFromTime(int aesId, long long timeParam);
private: // attributes
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
// AES-Values
QHash<int, AreaEffectSimulation::ExplosionCluster> m_explosionCluster; // key = AesId
QHash<int, QTimer *> m_aesTimers; // key = aesId value= VulcanoTimer
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
};
} // namespace CesExplosions
@@ -0,0 +1,53 @@
#include <QVector3D>
#include "math.h"
/**
* \brief Jira GUEZE-2540: Methode zur Sichtbarkeitsbestimmung Stufe 1
* Funktion isInCone
*
* \param p1 Scheitelpunkt Kegel
* \param p2 Punkt auf Achse im Kegel
* \param angle Halber Oeffnungswinkel
* \param ptt Testpunkt
*
* \return b 1, falls Testpunkt im Kegel
* 0, sonst
*/
bool isInCone(const QVector3D top, const QVector3D bottom, const float angle, const QVector3D pointToTest)
{
QVector3D v1;
QVector3D v2;
float alpha;
float cosAlpha;
v1.setX(bottom.x() - top.x());
v1.setY(bottom.y() - top.y());
v1.setZ(bottom.z() - top.z());
v2.setX(pointToTest.x() - top.x());
v2.setY(pointToTest.y() - top.y());
v2.setZ(pointToTest.z() - top.z());
if ((v1.length() < 0.00001) || (v2.length() < 0.00001))
{
return false;
}
cosAlpha = (v1.x()*v2.x() + v1.y()*v2.y() + v1.z()*v2.z()) / (v1.length() * v2.length());
if (fabs(cosAlpha) > 0.99999)
{
alpha = 1.0;
}
else
{
alpha = acos(cosAlpha);
}
if (alpha < 3.14159265359 * fabs(angle) / 180.0)
{
return true;
}
else
{
return false;
}
}
@@ -0,0 +1,23 @@
/**
* Visibility determination
* $Id$
* $HeadURL$
* $Author$
* Created by Gerlinde Rudolphus, ESZS, 2016-04-14
*/
#include <QVector3D>
/**
* \brief Jira GUEZE-2540: Methode zur Sichtbarkeitsbestimmung Stufe 1
* Funktion isInCone
*
* \param p1 Scheitelpunkt Kegel
* \param p2 Punkt auf Achseim Kegel
* \param angle Halber Oeffnungswinkel
* \param ptt Testpunkt
*
* \return b 1, falls Testpunkt im Kegel
* 0, sonst
*/
bool isInCone(const QVector3D top, const QVector3D bottom, const float angle, const QVector3D pointToTest);
@@ -0,0 +1,217 @@
/**
* @RDE_HEADER@
* Calculate line of sight
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2024-11-03
*/
#include "line_of_sight.h"
#include <CentralEffectSimulation/logger.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <LtsElevation/lts_elevation_manager.h>
#include <QElapsedTimer>
namespace CesExplosions
{
CentralEffectSimulation::LOGGER_T getLocalLogger()
{
return CentralEffectSimulation::getLogger("Plugin.Explosions.LineOfSight");
}
bool lineOfSightBuilding(const LtsCoordTrans::LtsCoordinate &impactLtsCoord_absZ,
const LtsCoordTrans::LtsCoordinate &participantLtsCoord_absZ,
bool &bLosOut,
std::shared_ptr<CentralEffectSimulation::ProxyBuilding> proxyBuilding)
{
static CentralEffectSimulation::LOGGER_T logger = getLocalLogger();
TRACE_LOG(logger) << LOGFUNCTION << " START";
DEBUG_LOG(logger) << LOGFUNCTION << " impactCoord = " << impactLtsCoord_absZ.toString(true);
DEBUG_LOG(logger) << LOGFUNCTION << " participant = " << participantLtsCoord_absZ.toString(true);
if (!proxyBuilding || !proxyBuilding->isSet_handlerBuildingModel())
{
INFO_LOG(logger) << LOGFUNCTION << " proxyBuilding not working...";
return false;
}
// sp should be checked by isSet above:
std::shared_ptr<CesBuildings::HandlerBuildingModelInterface> sp = proxyBuilding->handlerBuildingModelInterface();
const CesBuildings::HandlerBuildingModelInterface::LineBuildingIntersectsResult &result =
sp->getLineBuildingIntersects({impactLtsCoord_absZ.geoPosition(), participantLtsCoord_absZ.geoPosition()});
bool success = false;
if (result.errorString.empty())
{
if (result.intersects)
DEBUG_LOG(logger) << "lineOfSightBuilding, res.intersect = " << "YES";
else
DEBUG_LOG(logger) << "lineOfSightBuilding, res.intersect = " << "NO";
bLosOut = !result.intersects;
success = true;
}
else
{
ERROR_LOG(logger) << LOGFUNCTION
<< " getLineBuildingIntersects failed"
<< ", impactCoord = " << impactLtsCoord_absZ.toString(true)
<< ", participantCoord = " << participantLtsCoord_absZ.toString(true)
<< ", res.errorString = '" << result.errorString << "'";
}
DEBUG_LOG(logger) << LOGFUNCTION
<< ", success = " << success
<< ", bLosOut = " << bLosOut;
TRACE_LOG(logger) << LOGFUNCTION << " END, success = " << success;
return success;
}
bool lineOfSightElevation(const LtsCoordTrans::LtsCoordinate &impactLtsCoord_absZ,
const LtsCoordTrans::LtsCoordinate &participantLtsCoord_absZ,
bool &bLosOut,
const int exerciseId)
{
static CentralEffectSimulation::LOGGER_T logger = getLocalLogger();
TRACE_LOG(logger) << LOGFUNCTION << " START";
DEBUG_LOG(logger) << LOGFUNCTION << " getExerciseId=" << exerciseId
<< ", impactCoord = " << impactLtsCoord_absZ.toString(true)
<< ", participantCoord = " << participantLtsCoord_absZ.toString(true);
//
// The very first instanciation should be done by the MainHandler:
//
static LtsElevation::LTS_ELEVATION_MANAGER_TYPE s_ltsElevationManager = nullptr;
if (!s_ltsElevationManager)
s_ltsElevationManager = LtsElevation::LtsElevationManager::getInstance(exerciseId);
if (!s_ltsElevationManager)
{
WARNING_LOG(logger) << LOGFUNCTION << " no LtsElevationManager could be create for exerciseId " << exerciseId;
return false;
}
if (s_ltsElevationManager->isValid())
DEBUG_LOG(logger) << LOGFUNCTION << " LtsElevationManager is valid for exerciseId = " << exerciseId;
else
{
WARNING_LOG(logger) << LOGFUNCTION << " LtsElevationManager is INVALID for exerciseId = " << exerciseId;
return false;
}
const LtsUtils::QPoint3D &start = impactLtsCoord_absZ.toGeoPoint3D();
const LtsUtils::QPoint3D &end = participantLtsCoord_absZ.toGeoPoint3D();
const LtsElevation::LineOfSight losEle = s_ltsElevationManager->lineOfSightCalculation(start, end);
bool success = false;
switch (losEle)
{
case LtsElevation::LineOfSight::LOS_UNDEFINED:
case LtsElevation::LineOfSight::LOS_ERROR:
case LtsElevation::LineOfSight::LOS_INVISIBLE:
success = true;
bLosOut = false;
break;
case LtsElevation::LineOfSight::LOS_VISIBLE:
success = true;
bLosOut = true;
break;
} // switch
DEBUG_LOG(logger) << LOGFUNCTION
<< ", success = " << success
<< ", losEle = " << losEle
<< ", bLosOut = " << bLosOut;
TRACE_LOG(logger) << LOGFUNCTION << " END, success = " << success << ", losEle = " << losEle;
return success;
}
bool lineOfSight_elevationAndBuilding(const int exerciseId,
const LtsCoordTrans::LtsCoordinate &impactLtsCoord_absZ,
const LtsCoordTrans::LtsCoordinate &participantLtsCoord_absZ,
Options lineOfSightOptions,
bool &bLosOut,
std::shared_ptr<CentralEffectSimulation::ProxyBuilding> proxyBuilding)
{
static CentralEffectSimulation::LOGGER_T logger = getLocalLogger();
// What shall happen, if exeBldgLos is SKIP or proxyBuilding is not availble?
bool success = true; // (BLDG_LOS_SKIP || no buildings) -> bLOS given :-)
bLosOut = true;
DEBUG_LOG(logger) << LOGFUNCTION << " impactCoord = " << impactLtsCoord_absZ.toString(true);
DEBUG_LOG(logger) << LOGFUNCTION << " participant = " << participantLtsCoord_absZ.toString(true);
//
// execute different LineOfSight operations:
// try to start with the cheapest. But which is cheap and which expensive?
// assume lineOfSightBuilding is expensive due to several buildings, rooms, walls...
//
DEBUG_LOG(logger) << LOGFUNCTION << " vor lineOfSightOptions.testFlag EXECUTE_ELEVATION_LOS_CALC"
<< " lineOfSightOptions.testFlag(Option::EXECUTE_ELEVATION_LOS_CALC)=" << lineOfSightOptions.testFlag(Option::EXECUTE_ELEVATION_LOS_CALC);
if (lineOfSightOptions.testFlag(Option::EXECUTE_ELEVATION_LOS_CALC) /*&& bLOS*/)
{
DEBUG_LOG(logger) << LOGFUNCTION << " lineOfSightOptions EXECUTE_ELEVATION_LOS_CALC";
QElapsedTimer timer;
DEBUG_LOG(logger) << LOGFUNCTION << " vor lineOfSightOptions start";
if (logger.isInfoEnabled())
timer.start();
if (lineOfSightElevation(impactLtsCoord_absZ,
participantLtsCoord_absZ,
bLosOut, exerciseId))
{
DEBUG_LOG(logger) << "---------------- lineOfSightElevation bLosOut=" << bLosOut;
if (!bLosOut)
{
DEBUG_LOG(logger) << "---------------- lineOfSightElevation return success";
return success;
}
DEBUG_LOG(logger) << "---------------- lineOfSightElevation continue with buildings";
}
else
return false;
INFO_LOG(logger) << " lineOfSightElevation took [ms] " << timer.elapsed();
}
else
DEBUG_LOG(logger) << "skip lineOfSightElevation due to option EXECUTE_ELEVATION_LOS_CALC";
DEBUG_LOG(logger) << LOGFUNCTION << " vor lineOfSightOptions.testFlag EXECUTE_BLDG_LOS_CALC";
if (lineOfSightOptions.testFlag(Option::EXECUTE_BLDG_LOS_CALC))
{
QElapsedTimer timer;
if (logger.isInfoEnabled())
timer.start();
if (lineOfSightBuilding(impactLtsCoord_absZ, participantLtsCoord_absZ,
bLosOut, proxyBuilding))
return success;
else
return false;
INFO_LOG(logger) << " lineOfSightBuilding took [ms] " << timer.elapsed();
}
else
DEBUG_LOG(logger) << "skip lineOfSightBuilding due to option EXECUTE_BLDG_LOS_CALC or previous non-LineOfSight";
return true;
}
} // namespace
@@ -0,0 +1,50 @@
/**
* @RDE_HEADER@
* Calculate line of sight
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2024-11-03
*/
#include <Core/core.hpp>
#include <LtsCoordinate/lts_coordinate.h>
#include <CentralEffectSimulation/proxy_building.h>
#include <QFlags>
#pragma once
namespace CesExplosions
{
// Options:
enum Option
{
EXECUTE_BLDG_LOS_CALC = 1, // 0000001
EXECUTE_ELEVATION_LOS_CALC = 2, // 0000010
// OptFutureUse1 = 4, // 0000100
// OptFutureUse2 = 8, // 0001000
};
Q_DECLARE_FLAGS(Options, Option)
/// brief calculate line of sight between two points
/// \param exerciseId: id from exercise
/// \param impactLtsCoord_absZ: Explosion Position (z = height == above MSL)
/// \param participantLtsCoord_absZ: Participant Position (z = height == above MSL)
/// \param lineOfSightOptions: Options which Calculation is relevant, building or terrain
/// \param bLosOut: Result of calculation: true = line of sight given; false: line of sight interrupted
/// \return true: no error in calculation
bool lineOfSight_elevationAndBuilding(const int exerciseId,
const LtsCoordTrans::LtsCoordinate &impactLtsCoord_absZ,
const LtsCoordTrans::LtsCoordinate &participantLtsCoord_absZ,
Options lineOfSightOptions,
bool &bLosOut,
std::shared_ptr<CentralEffectSimulation::ProxyBuilding> proxyBuilding);
Q_DECLARE_OPERATORS_FOR_FLAGS(Options)
}
@@ -0,0 +1,98 @@
/**
* Plugin Explosions
* $Id$
* $HeadURL$
* $Author$
* Created by Gerlinde Rudolphus, SLTE, 2024-01-05
*/
#include "plugin.h"
#include "settings.h"
#include <ngldb/db_service_handler.h>
#include <CentralEffectSimulation/main_handler.h>
namespace CesExplosions
{
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> CentralEffectSimulationExplosionsPlugin::createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
NGL::Settings *settings,
CentralEffectSimulation::MainHandler *mainHandler)
{
return std::make_shared<CesExplosionInterfaceImpl>(pdp, dDSConnector, settings, mainHandler);
}
CesExplosionInterfaceImpl::CesExplosionInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
NGL::Settings *settings,
CentralEffectSimulation::MainHandler *mainHandler)
: m_pdp(pdp)
, m_ddsConnector(dDSConnector)
, m_mainHandler(mainHandler)
, m_ddsHandler(m_mainHandler->dds())
, m_db(m_mainHandler->db())
, m_handlerParticipant(m_mainHandler->handlerParticipant())
, m_logger(CentralEffectSimulation::getLogger("Plugin.Explosions.HandlerExplosions"))
{
Q_UNUSED(settings)
DEBUG_LOG(m_logger) << "CesExplosionInterfaceImpl";
}
CesExplosionInterfaceImpl::~CesExplosionInterfaceImpl()
{
m_handlerExplosions.reset();
m_handlerVulcano.reset();
}
bool CesExplosionInterfaceImpl::init(int domainId, int exerciseId)
{
DEBUG_LOG(m_logger) << "CesExplosionInterfaceImpl init";
m_domainId = domainId;
m_exerciseId = exerciseId;
INFO_LOG(m_logger) << "CesExplosionsInterfaceImpl::init()"
<< " m_domainId=" << m_domainId
<< " m_exerciseId=" << m_exerciseId;
// initialize handlerExplosions
m_handlerExplosions = std::make_shared<HandlerExplosions>(m_ddsHandler,
m_handlerParticipant,
m_mainHandler->proxyBuilding(),
this);
if (!m_handlerExplosions->init())
{
ERROR_LOG(m_logger) << "Initialisation m_handlerExplosions failed.";
return false;
}
INFO_LOG(m_logger) << "CesExplosionsInterfaceImpl::init() return true";
// initialize handlerVulcano
m_handlerVulcano = std::make_shared<HandlerVulcano>(m_ddsHandler, this);
if (!m_handlerVulcano->init())
{
ERROR_LOG(m_logger) << "Initialisation m_handlerVulcano failed.";
return false;
}
INFO_LOG(m_logger) << "CesExplosionsInterfaceImpl::init() return true";
return true;
}
QString CesExplosionInterfaceImpl::echo(const QString &message)
{
QString ret(QStringLiteral("<<<< %1 >>>> CesExplosionsInterfaceImpl::echo").arg(message));
INFO_LOG(m_logger) << "CesExplosionsInterfaceImpl::echo return:" << ret;
DEBUG_LOG(m_logger) << "DEBUG: CesExplosionsInterfaceImpl::echo return:" << ret;
return ret;
}
} //namespace CesExplosions
@@ -0,0 +1,75 @@
/**
* Plugin Explosions
* $Id$
* $HeadURL$
* $Author$
* Created by Gerlinde Rudolphus, SLTE, 2024-01-05
*/
#pragma once
#include "handler_explosions.h"
#include "handler_vulcano.h"
#include <CentralEffectSimulation/logger.h>
#include <CentralEffectSimulation/ces_plugin_interface.h>
#include <CentralEffectSimulation/main_handler.h>
#include <CentralEffectSimulation/dds_handler.h>
#include <DDS/DDSConnector/dds_connector.h>
#include <QObject>
namespace CesExplosions
{
//using DbHandler = NGLDB::DbServiceHandler<CentralEffectSimulation::DatabaseInterface>;
class CentralEffectSimulationExplosionsPlugin : public QObject, public CentralEffectSimulation::Plugin::Plugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "special:3:ces.CentralEffectSimulationExplosionsPlugin")
Q_INTERFACES(CentralEffectSimulation::Plugin::Plugin)
public:
CentralEffectSimulationExplosionsPlugin() = default;
~CentralEffectSimulationExplosionsPlugin() = default;
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
NGL::Settings *settings,
CentralEffectSimulation::MainHandler *mainHandler) override;
};
class CesExplosionInterfaceImpl final : public CentralEffectSimulation::Plugin::Interface
{
Q_OBJECT
public:
CesExplosionInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
NGL::Settings *settings,
CentralEffectSimulation::MainHandler *mainHandler);
~CesExplosionInterfaceImpl();
//bool init();
const char *name() const override { return "CentralEffectSimulationExplosions"; }
QString echo(const QString &message) override;
private Q_SLOTS:
bool init(int domainId, int exerciseId) override;
private:
CentralEffectSimulation::Plugin::DataProvider *m_pdp{nullptr};
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
CentralEffectSimulation::MainHandler *m_mainHandler{nullptr};
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler;
std::shared_ptr<CentralEffectSimulation::DatabaseInterface> m_db;
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant; ///< Pointer to handler for all participants
std::shared_ptr<HandlerExplosions> m_handlerExplosions; ///< Pointer to handler for participant outside from Buildings
std::shared_ptr<HandlerVulcano> m_handlerVulcano; ///< Pointer to handler for participant outside from Buildings
CentralEffectSimulation::LOGGER_T &m_logger;
int m_domainId{0};
int m_exerciseId{0};
};
} // namespace CesExplosions
@@ -0,0 +1,60 @@
/**
* Settings for CentralEffectSimulation
* $Id$
* $HeadURL$
* $Author$
*/
#include "settings.h"
#include <QtCore/QSettings>
#include <QtCore/QVariant>
#include <nglsettings/nglsettings_settings.h>
#include <ngltools/ngltools_filesystem.h>
namespace CesExplosions
{
class NGLSettingsClass : public NGL::Settings
{
public:
NGLSettingsClass()
: NGL::Settings(s_iniFile.isEmpty() ? NGL::findProjectConfigFile() : s_iniFile)
{}
static void setIniFile(const QString &fn)
{
s_iniFile = fn;
}
static QString s_iniFile;
};
QString NGLSettingsClass::s_iniFile;
Q_GLOBAL_STATIC(NGLSettingsClass, s)
//-----------------------------------------------------------------------------
NGL::Settings *Settings::settings()
{
return s();
}
//-----------------------------------------------------------------------------
void Settings::setIniFile(const QString &ini)
{
NGLSettingsClass::setIniFile(ini);
}
//-----------------------------------------------------------------------------
float Settings::vulcanoViewAngleDeg()
{
return s()->settings()->value(QStringLiteral("CesExplosions/Vulcano/ViewAngle"), 12.0).toFloat();
}
float Settings::vulcanoAttackAngleDeg()
{
return s()->settings()->value(QStringLiteral("CesExplosions/Vulcano/AttackAngle"), 3.8).toFloat();
}
float Settings::vulcanoMaximumDesignationAngleDeg()
{
return s()->settings()->value(QStringLiteral("CesExplosions/Vulcano/MaximumDesignationAngle"), 60.0).toFloat();
}
} // namespace CesExplosions
@@ -0,0 +1,29 @@
/**
* Settings for CentralEffectSimulation
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QString>
namespace NGL
{
class Settings;
}
namespace CesExplosions
{
namespace Settings
{
NGL::Settings *settings();
void setIniFile(const QString &ini);
float vulcanoViewAngleDeg();
float vulcanoAttackAngleDeg();
float vulcanoMaximumDesignationAngleDeg();
}
} // namespace CesExplosions