Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# monitoring of the target areas
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(SRCS
|
||||
plugin.cpp
|
||||
plugin.h
|
||||
handler_artillerie_sound.cpp
|
||||
handler_artillerie_sound.h
|
||||
settings.cpp
|
||||
settings.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV cesPluginArtillerySound MODULE ${SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(cesPluginArtillerySound
|
||||
Qt5::Network
|
||||
Qt5::Widgets
|
||||
cesPluginInterface
|
||||
ngltools
|
||||
ngldb
|
||||
svcTabClient
|
||||
LtsCoordTrans
|
||||
# ProjectConfig
|
||||
svcCesDDSCommon
|
||||
)
|
||||
NGL_INSTALL_TARGET(cesPluginArtillerySound)
|
||||
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#include "handler_artillerie_sound.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <qmath.h>
|
||||
#include <math.h>
|
||||
|
||||
namespace CesArtillerySound
|
||||
{
|
||||
|
||||
HandlerArtillerieSound::HandlerArtillerieSound(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &buildingDataHandler,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_handlerBuildingData(buildingDataHandler)
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.ArtillerySound.HandlerArtillerieSound"))
|
||||
{
|
||||
}
|
||||
|
||||
HandlerArtillerieSound::~HandlerArtillerieSound()
|
||||
{
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerArtillerieSound::init()
|
||||
{
|
||||
|
||||
if (Settings::cesPlayArtillerieSounds())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "init with Artillerie-Sounds";
|
||||
auto dtcAes = m_ddsHandler->dtcAes();
|
||||
|
||||
dtcAes->enableExplosionSingle();
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::explosionSingleChanged,
|
||||
this, &HandlerArtillerieSound::onExplosionSingleChanged);
|
||||
|
||||
dtcAes->enableTechnicalArea();
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::technicalAreaChanged,
|
||||
this, &HandlerArtillerieSound::onTechnicalAreaChanged);
|
||||
}
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "init without Artillerie-Sounds";
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void HandlerArtillerieSound::onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType)
|
||||
{
|
||||
bool handleExplosion = false;
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
{
|
||||
m_explosionSingleState.remove(data.id());
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsRemoved)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Remove SingleExplosion";
|
||||
m_explosionSingleState.remove(data.id());
|
||||
return;
|
||||
}
|
||||
// Only handle transitions from prepared or fired to activated
|
||||
if ((m_explosionSingleState.value(data.id()) == AreaEffectSimulation::AesEffectState_def::EsPrepared ||
|
||||
m_explosionSingleState.value(data.id()) == AreaEffectSimulation::AesEffectState_def::EsFired) &&
|
||||
data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsActivated)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Handle SingleExplosion";
|
||||
handleExplosion = true;
|
||||
}
|
||||
m_explosionSingleState.insert(data.id(), data.effectStateId());
|
||||
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got ExplosionSingle State=" << data.effectStateId()
|
||||
<< " id=" << data.id();
|
||||
if (handleExplosion)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Handle ExplosionSingle (EsActivated) HandlerArtillerieSound";
|
||||
|
||||
auto assetPositions = m_handlerBuildingData->getAssetPositions();
|
||||
///////////////////////////////////////////////////////////////////
|
||||
/// Play Sound to each EGCU and OSGU volume depends on distance
|
||||
///////////////////////////////////////////////////////////////////
|
||||
INFO_LOG(m_logger) << "printAssetPositions: ";
|
||||
QHashIterator<int, CentralEffectSimulation::HandlerBuildingData::AssetPosition> i(assetPositions);
|
||||
while (i.hasNext())
|
||||
{
|
||||
i.next();
|
||||
INFO_LOG(m_logger) << "printAssetPositions: "
|
||||
<< i.key() << ": " << i.value().structureElementId
|
||||
<< " type = " << i.value().mountingPointType
|
||||
<< " hostname =" << i.value().hostname
|
||||
<< " pos=" << i.value().geoPosition
|
||||
<< " posUtm=" << i.value().positionUtm.x()
|
||||
<< "/" << i.value().positionUtm.y()
|
||||
<< " zone=" << i.value().zone;
|
||||
// Calculate the distance between the speaker and the explosion
|
||||
const QPointF posExplosionUtm = CentralEffectSimulation::geographic2Utm(data.impactPosition(), i.value().zone);
|
||||
const qreal distance = qSqrt(qPow(posExplosionUtm.x() - i.value().positionUtm.x(), 2) + qPow(posExplosionUtm.y() - i.value().positionUtm.y(), 2));
|
||||
int sound = Settings::cesSoundId();
|
||||
const qreal distanceThreshold = Settings::cesDistanceThreshold(); // [m]
|
||||
const qreal factor = Settings::cesFactor();
|
||||
const qreal cesReduceFactor = Settings::cesReduceFactor();
|
||||
INFO_LOG(m_logger) << "Distance to Explosion =" << distance
|
||||
<< " hostname =" << i.value().hostname
|
||||
<< " distanceThreshold=" << distanceThreshold
|
||||
<< " factor=" << factor;
|
||||
qreal volumePercent = 100;
|
||||
if (distance > distanceThreshold)
|
||||
volumePercent = factor * log10(distance) * cesReduceFactor;
|
||||
QString user = Settings::cesUser();
|
||||
QString passwd = Settings::cesPasswd();
|
||||
playSound(user, passwd, i.value().hostname, sound, volumePercent);
|
||||
}
|
||||
}
|
||||
|
||||
} // onExplosionSingleChanged
|
||||
|
||||
void HandlerArtillerieSound::playSound(QString &user, QString &passwd, const QString &host, int &sound, qreal &volume)
|
||||
{
|
||||
QUrl url;
|
||||
QString request = QStringLiteral("http://%1/hitsound.php?sound=%2&vol=%3")
|
||||
.arg(host)
|
||||
.arg(sound)
|
||||
.arg(volume);
|
||||
url.setUrl(request);
|
||||
url.setUserName(user);
|
||||
url.setPassword(passwd);
|
||||
DEBUG_LOG(m_logger) << "startRequest: " << url.toString();
|
||||
startRequest(url);
|
||||
}
|
||||
|
||||
void HandlerArtillerieSound::startRequest(const QUrl &requestedUrl)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "startRequest: " << requestedUrl.toString();
|
||||
m_httpRequestAborted = false;
|
||||
auto reply = m_qnam.get(QNetworkRequest(requestedUrl));
|
||||
connect(reply, &QNetworkReply::finished, this, &HandlerArtillerieSound::httpFinished);
|
||||
}
|
||||
|
||||
|
||||
void HandlerArtillerieSound::httpFinished()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "httpFinished";
|
||||
auto reply = qobject_cast<QNetworkReply *>(sender());
|
||||
if (!reply)
|
||||
return;
|
||||
|
||||
if (m_httpRequestAborted)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "httpRequestAborted";
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->error())
|
||||
{
|
||||
QNetworkRequest request = reply->request();
|
||||
QUrl url = request.url();
|
||||
ERROR_LOG(m_logger) << "reply->error: " << reply->errorString()
|
||||
<< " host=" << url.host()
|
||||
<< " query='" << url.query()
|
||||
<< "' '" << qUtf8Printable(url.toString()) << "'";
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Sucess
|
||||
|
||||
//parse the reply JSON and display result in the UI
|
||||
const QByteArray json(reply->readAll());
|
||||
DEBUG_LOG(m_logger) << "Sucess " << json;
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
|
||||
void HandlerArtillerieSound::onTechnicalAreaChanged(const AreaEffectSimulation::TechnicalArea &data, DataModification modType)
|
||||
{
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
{
|
||||
m_technicalAreas.remove(data.id());
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsRemoved)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Remove TechnicalArea";
|
||||
m_technicalAreas.remove(data.id());
|
||||
return;
|
||||
}
|
||||
if (data.type() == AreaEffectSimulation::AesTechnicalAreaType_def::TatSoundZone)
|
||||
{
|
||||
int zone = -1;
|
||||
m_technicalAreas.insert(data.id(), data);
|
||||
DEBUG_LOG(m_logger) << "Handle TechnicalArea HandlerArtillerieSound id=" << data.id();
|
||||
QPointF cornerButtomLeft = CentralEffectSimulation::geographic2Utm(data.area().cornerBottomLeft(), &zone);
|
||||
qreal x = cornerButtomLeft.x() + data.area().width() / 2;
|
||||
qreal y = cornerButtomLeft.y() + data.area().height() / 2;
|
||||
QPointF center(x, y);
|
||||
DEBUG_LOG(m_logger) << "Handle TechnicalArea HandlerArtillerieSound cornerButtomLeft = " << cornerButtomLeft.x() << "/" << cornerButtomLeft.y()
|
||||
<< " zone=" << zone;
|
||||
DEBUG_LOG(m_logger) << "Handle TechnicalArea HandlerArtillerieSound center = " << center.x() << "/" << center.y()
|
||||
<< " zone=" << zone;
|
||||
}
|
||||
} // onTechnicalAreaChanged
|
||||
|
||||
|
||||
} // namespace CesArtillerySound
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Handler for Blocked Areas
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2018-07-02
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CentralEffectSimulation/logger.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
#include <AreaEffectSimulation/aes_dtc.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <TrainingAreaBase/tab_ftc.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
// HTTP Request
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
namespace CesArtillerySound
|
||||
{
|
||||
|
||||
class HandlerArtillerieSound final
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit HandlerArtillerieSound(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &buildingDataHandler,
|
||||
QObject *parent);
|
||||
|
||||
~HandlerArtillerieSound();
|
||||
|
||||
bool init();
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType);
|
||||
void onTechnicalAreaChanged(const AreaEffectSimulation::TechnicalArea &data, DataModification modType);
|
||||
void httpFinished();
|
||||
|
||||
private:
|
||||
void playSound(QString &user, QString &passwd, const QString &host, int &sound, qreal &volume);
|
||||
void startRequest(const QUrl &requestedUrl);
|
||||
private: // attributes
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to DDS handler
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> m_handlerBuildingData;
|
||||
|
||||
QHash<int, AreaEffectSimulation::AesEffectState> m_explosionSingleState; // key = id, value = state
|
||||
QHash<int, AreaEffectSimulation::TechnicalArea> m_technicalAreas;
|
||||
QHash<int, QPointF> m_centerSoundArea; // key: TechnicalAreaId, value Center of SoundArea
|
||||
QHash<int, QPointF> m_egcus;
|
||||
QHash<int, QPointF> m_ogcus;
|
||||
|
||||
QNetworkAccessManager m_qnam;
|
||||
bool m_httpRequestAborted = false;
|
||||
|
||||
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
|
||||
|
||||
};
|
||||
} // namespace CesArtillerySound
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Handle Artillery Sound
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
#include "settings.h"
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <ngldb/db_service_handler.h>
|
||||
|
||||
namespace CesArtillerySound
|
||||
{
|
||||
|
||||
// 29.11.2024, Norbert Thoden:
|
||||
// a) das PluginHandling wurde vereinfacht, sprich 'nur' mainHandler übergeben statt explizit ddsHandler, dbhandler etc
|
||||
// b) Loggder überarbeiten (logger{h,cpp} und ces_export.h entsorgen
|
||||
// c) Bereinigung des Namensschema: CentralEffectSimulation2DPlugin -> CentralEffectSimulationArtillerySoundPlugin
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> CentralEffectSimulationArtillerySoundPlugin::createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
CentralEffectSimulation::MainHandler *mainHandler)
|
||||
{
|
||||
return std::make_shared<CesArtillerySoundInterfaceImpl>(pdp, dDSConnector, settings, mainHandler);
|
||||
}
|
||||
|
||||
//std::shared_ptr<CentralEffectSimulation::Plugin::Interface> CentralEffectSimulation2DPlugin::createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
// const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
// NGL::Settings *settings,
|
||||
// CentralEffectSimulation::MainHandler *mainHandler)
|
||||
//{
|
||||
// return std::make_shared<CesArtillerySoundInterfaceImpl>(pdp, dDSConnector, settings, mainHandler);
|
||||
//}
|
||||
|
||||
|
||||
CesArtillerySoundInterfaceImpl::CesArtillerySoundInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
CentralEffectSimulation::MainHandler *mainHandler)
|
||||
: m_pdp(pdp)
|
||||
, m_ddsConnector(dDSConnector)
|
||||
, m_ddsHandler(mainHandler->dds())
|
||||
, m_db(mainHandler->db())
|
||||
, m_handlerBuildingData(mainHandler->handlerBuildingData())
|
||||
, m_handlerParticipant(mainHandler->handlerParticipant())
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.ArtillerySound.CesArtillerySoundInterfaceImpl"))
|
||||
{
|
||||
Q_UNUSED(settings)
|
||||
}
|
||||
|
||||
CesArtillerySoundInterfaceImpl::~CesArtillerySoundInterfaceImpl()
|
||||
{
|
||||
m_handlerArtillerieSound.reset();
|
||||
}
|
||||
|
||||
|
||||
bool CesArtillerySoundInterfaceImpl::init(int domainId, int exerciseId)
|
||||
{
|
||||
m_domainId = domainId;
|
||||
m_exerciseId = exerciseId;
|
||||
INFO_LOG(m_logger) << "CentralEffectSimulation2DInterfaceImpl::init()"
|
||||
<< " m_domainId=" << m_domainId
|
||||
<< " m_exerciseId=" << m_exerciseId;
|
||||
|
||||
|
||||
|
||||
// initialize handlerArtillerieSound
|
||||
m_handlerArtillerieSound = std::make_shared<HandlerArtillerieSound>(m_ddsHandler,
|
||||
m_handlerBuildingData,
|
||||
this);
|
||||
|
||||
if (!m_handlerArtillerieSound->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation m_handlerArtillerieSound failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(m_logger) << "CentralEffectSimulation2DInterfaceImpl::init() return true";
|
||||
return true;
|
||||
}
|
||||
|
||||
} //namespace CesArtillerySound
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Plugin Artillery Sound
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "handler_artillerie_sound.h"
|
||||
|
||||
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
#include <CentralEffectSimulation/ces_plugin_interface.h>
|
||||
#include <CentralEffectSimulation/ces_plugin_interface.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
#include <CentralEffectSimulation/main_handler.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
|
||||
namespace CesArtillerySound
|
||||
{
|
||||
|
||||
// 29.11.2024, Norbert Thoden:
|
||||
// a) das PluginHandling wurde vereinfacht, sprich 'nur' mainHandler übergeben statt explizit ddsHandler, dbhandler etc
|
||||
// b) Loggder überarbeiten (logger{h,cpp} und ces_export.h entsorgen
|
||||
// c) Bereinigung des Namensschema: CentralEffectSimulation2DPlugin -> CentralEffectSimulationArtillerySoundPlugin
|
||||
|
||||
class CentralEffectSimulationArtillerySoundPlugin : public QObject, public CentralEffectSimulation::Plugin::Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "special:3:ces.CentralEffectSimulationArtillerySoundPlugin")
|
||||
Q_INTERFACES(CentralEffectSimulation::Plugin::Plugin)
|
||||
|
||||
public:
|
||||
CentralEffectSimulationArtillerySoundPlugin() = default;
|
||||
~CentralEffectSimulationArtillerySoundPlugin() = 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 CentralEffectSimulation2DPlugin : public QObject, public CentralEffectSimulation::Plugin::Plugin
|
||||
//{
|
||||
// Q_OBJECT
|
||||
// Q_PLUGIN_METADATA(IID "special:3:ces.CentralEffectSimulation2DPlugin")
|
||||
// Q_INTERFACES(CentralEffectSimulation::Plugin::Plugin)
|
||||
|
||||
//public:
|
||||
// CentralEffectSimulation2DPlugin() = default;
|
||||
// ~CentralEffectSimulation2DPlugin() = 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 CesArtillerySoundInterfaceImpl final : public CentralEffectSimulation::Plugin::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CesArtillerySoundInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
CentralEffectSimulation::MainHandler *mainHandler);
|
||||
~CesArtillerySoundInterfaceImpl();
|
||||
//bool init();
|
||||
const char *name() const override { return "CentralEffectSimulation2D"; }
|
||||
QString echo(const QString &/*message*/) override { return QString();}
|
||||
|
||||
private Q_SLOTS:
|
||||
bool init(int domainId, int exerciseId) override;
|
||||
private:
|
||||
|
||||
private:
|
||||
CentralEffectSimulation::Plugin::DataProvider *m_pdp;
|
||||
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler;
|
||||
std::shared_ptr<CentralEffectSimulation::DatabaseInterface> m_db;
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> m_handlerBuildingData; ///< Pointer to AES Building handler
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant; ///< Pointer to handler for all participants
|
||||
std::shared_ptr<HandlerArtillerieSound> m_handlerArtillerieSound; /// < Pointer to handler for Artillerie Sound
|
||||
|
||||
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
int m_domainId = 0;
|
||||
int m_exerciseId = 0;
|
||||
};
|
||||
|
||||
} // namespace CesArtillerySound
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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 CesArtillerySound
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Artillerie-Sounds:
|
||||
bool Settings::cesPlayArtillerieSounds()
|
||||
{
|
||||
return s()->settings()->value(QStringLiteral("CES_ARTILLERY_SOUND/playArtillerieSounds"), false).toBool();
|
||||
}
|
||||
|
||||
QString Settings::cesUser()
|
||||
{
|
||||
return s()->settings()->value(QStringLiteral("CES_ARTILLERY_SOUND/user"), QStringLiteral("katar")).toString();
|
||||
}
|
||||
|
||||
QString Settings::cesPasswd()
|
||||
{
|
||||
return s()->settings()->value(QStringLiteral("CES_ARTILLERY_SOUND/passwd"), QStringLiteral("mout11de")).toString();
|
||||
}
|
||||
|
||||
qreal Settings::cesDistanceThreshold()
|
||||
{
|
||||
return s()->settings()->value(QStringLiteral("CES_ARTILLERY_SOUND/distanceThreshold"), 1.415).toReal();
|
||||
}
|
||||
|
||||
qreal Settings::cesFactor()
|
||||
{
|
||||
return s()->settings()->value(QStringLiteral("CES_ARTILLERY_SOUND/factor"), 15.05).toReal();
|
||||
}
|
||||
|
||||
int Settings::cesSoundId()
|
||||
{
|
||||
return s()->settings()->value(QStringLiteral("CES_ARTILLERY_SOUND/soundId"), 1).toInt();
|
||||
}
|
||||
|
||||
qreal Settings::cesReduceFactor()
|
||||
{
|
||||
return s()->settings()->value(QStringLiteral("CES_ARTILLERY_SOUND/reduceFactor"), 1.0).toReal();
|
||||
}
|
||||
|
||||
} // namespace CesArtillerySound
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Settings for CentralEffectSimulation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <QString>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class Settings;
|
||||
}
|
||||
|
||||
namespace CesArtillerySound
|
||||
{
|
||||
namespace Settings
|
||||
{
|
||||
|
||||
NGL::Settings *settings();
|
||||
void setIniFile(const QString &ini);
|
||||
|
||||
// Artillerie-Sounds:
|
||||
bool cesPlayArtillerieSounds();
|
||||
QString cesUser();
|
||||
QString cesPasswd();
|
||||
qreal cesDistanceThreshold();
|
||||
qreal cesFactor();
|
||||
int cesSoundId();
|
||||
qreal cesReduceFactor();
|
||||
}
|
||||
|
||||
} // namespace CesArtillerySound
|
||||
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# monitoring of the target areas
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(SRCS
|
||||
plugin.cpp
|
||||
plugin.h
|
||||
handler_participant_borderline.cpp
|
||||
handler_participant_borderline.h
|
||||
handler_simulated_movement.cpp
|
||||
handler_simulated_movement.h
|
||||
simulation_movement.cpp
|
||||
simulation_movement.h
|
||||
# logger.cpp
|
||||
# logger.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV cesPluginBasic MODULE ${SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(cesPluginBasic
|
||||
Qt5::Network
|
||||
Qt5::Widgets
|
||||
cesPluginInterface
|
||||
ngldb
|
||||
svcCesDDSCommon
|
||||
# ProjectConfig
|
||||
|
||||
)
|
||||
NGL_INSTALL_TARGET(cesPluginBasic)
|
||||
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#include "handler_participant_borderline.h"
|
||||
|
||||
#include <QLineF>
|
||||
#include <QTimer>
|
||||
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
namespace CentralEffectSimulationBasic
|
||||
{
|
||||
|
||||
HandlerParticipantBorderline::HandlerParticipantBorderline(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_handlerParticipant(participantHandler)
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.Basic.HandlerParticipantBorderline"))
|
||||
{
|
||||
INFO_LOG(m_logger) << "HandlerParticipantBorderline::HandlerParticipantBorderline";
|
||||
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HandlerParticipantBorderline::~HandlerParticipantBorderline()
|
||||
{
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerParticipantBorderline::init()
|
||||
{
|
||||
INFO_LOG(m_logger) << "HandlerParticipantBorderline::init";
|
||||
auto dtcAes = m_ddsHandler->dtcAes();
|
||||
|
||||
dtcAes->waitForHistoricalDataBorderline(1000);
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::borderlineChanged,
|
||||
this, &HandlerParticipantBorderline::onBorderlineChanged);
|
||||
|
||||
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newIndoorPosition,
|
||||
this, &HandlerParticipantBorderline::onParticipantPositionChanged);
|
||||
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newOutdoorPosition,
|
||||
this, &HandlerParticipantBorderline::onParticipantPositionChanged);
|
||||
|
||||
// Get 'static' data for all Borderlines
|
||||
{
|
||||
auto cb = [this](const AreaEffectSimulation::Borderline & fa)
|
||||
{
|
||||
onBorderlineChanged(fa, DataModification::eAdded);
|
||||
};
|
||||
if (!dtcAes->borderlines(cb))
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(m_logger) << "HandlerParticipantBorderline::init() finished. ";
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HandlerParticipantBorderline::onBorderlineChanged(const AreaEffectSimulation::Borderline &data, DataModification modType)
|
||||
{
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eRemoved:
|
||||
DEBUG_LOG(m_logger) << " remove Borderline- data.id()=" << data.id();
|
||||
m_borderlines.remove(data.id());
|
||||
break;
|
||||
case DataModification::eAdded:
|
||||
case DataModification::eModified:
|
||||
{
|
||||
const AreaEffectSimulation::AesEffectState &effectState = data.effectStateId();
|
||||
switch (effectState.underlying())
|
||||
{
|
||||
case AreaEffectSimulation::AesEffectState_def::EsReceived:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsFired:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsCreated:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsPrepared:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsActivated:
|
||||
{
|
||||
BorderlineUtm borderline(data);
|
||||
DEBUG_LOG(m_logger) << "m_borderlines.insert id=" << data.id();
|
||||
m_borderlines.insert(data.id(), borderline);
|
||||
break;
|
||||
}
|
||||
case AreaEffectSimulation::AesEffectState_def::EsRemoved:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsExpired:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsPaused:
|
||||
m_borderlines.remove(data.id());
|
||||
break;
|
||||
case AreaEffectSimulation::AesEffectState_def::EsUnknown:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsError:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HandlerParticipantBorderline::intersect(const QPolygonF &polygonf, const QLineF &linef) const
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "line to check: " << CentralEffectSimulation::debug(linef.p1()) << " - " << CentralEffectSimulation::debug(linef.p2());
|
||||
QPointF a = polygonf.first();
|
||||
for (const QPointF &b : polygonf)
|
||||
{
|
||||
const QLineF segment(a, b);
|
||||
DEBUG_LOG(m_logger) << "segment:" << CentralEffectSimulation::debug(a) << " - " << CentralEffectSimulation::debug(b);
|
||||
if (QLineF::BoundedIntersection == linef.intersect(segment, nullptr))
|
||||
return true;
|
||||
a = b;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void HandlerParticipantBorderline::onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos)
|
||||
{
|
||||
// Bounding Box von der Linie
|
||||
DEBUG_LOG(m_logger) << "ParicipantStep "
|
||||
<< " participantId=" << partPos.participantId()
|
||||
<< " participantTypeId=" << partPos.participantTypeId()
|
||||
<< " Anzahl Borderlines=" << m_borderlines.size();
|
||||
|
||||
for (const BorderlineUtm &borderline : qAsConst(m_borderlines))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "borderline id = " << borderline.id
|
||||
<< ", Box bottomLeft = " << CentralEffectSimulation::debug(borderline.boundingBox.bottomLeft())
|
||||
<< ", topRight = " << CentralEffectSimulation::debug(borderline.boundingBox.topRight());
|
||||
const QPolygonF utmStepPoly = m_handlerParticipant->getParticipantStep(partPos.participantId(), borderline.zone);
|
||||
if (utmStepPoly.size() < 2)
|
||||
continue;
|
||||
|
||||
// Intersection von Polygon und Line: Polygon = Borderline, Line from last Participant pos to actual participant pos
|
||||
const QLineF utmStep(utmStepPoly[0], utmStepPoly[1]);
|
||||
const bool result = intersect(borderline.points, utmStep);
|
||||
DEBUG_LOG(m_logger) << "result intersection = " << result;
|
||||
if (result)
|
||||
{
|
||||
if (borderline.operatorId <= 0)
|
||||
sendParticipantEvent(borderline, partPos, ProjectDataManagement::EventType_def::CrossGlobalBorderline);
|
||||
else
|
||||
sendParticipantEvent(borderline, partPos, ProjectDataManagement::EventType_def::CrossLocalBorderline);
|
||||
}
|
||||
}
|
||||
} // end of onParticipantPositionChanged()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// ///////////////////////////////////
|
||||
// P D M (ProjectDataManagement)
|
||||
// ///////////////////////////////////
|
||||
// Search for corresponding aesItemView
|
||||
// Check for all participants wheter he is in the explosion area
|
||||
|
||||
|
||||
void HandlerParticipantBorderline::sendParticipantEvent(const BorderlineUtm &borderline,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
|
||||
const ProjectDataManagement::EventType eventType)
|
||||
{
|
||||
ParticipantManagement::TypeClass typeClass = m_handlerParticipant->typeClassFromTypeId(participantPosition.participantTypeId());
|
||||
|
||||
if (typeClass == ParticipantManagement::TypeClass_def::Unit ||
|
||||
typeClass == ParticipantManagement::TypeClass_def::SupportUnit ||
|
||||
typeClass == ParticipantManagement::TypeClass_def::SupportEntity ||
|
||||
typeClass == ParticipantManagement::TypeClass_def::Unknown)
|
||||
return;
|
||||
|
||||
int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantPosition.participantId());
|
||||
if (equipmentNumber <= 0)
|
||||
return;
|
||||
|
||||
CentralEffectSimulation::ParticipantEvent pe;
|
||||
DEBUG_LOG(m_logger) << "sendParticipantEvent participantId=" << participantPosition.participantId()
|
||||
<< " lat= " << participantPosition.pos().lat()
|
||||
<< " lon= " << participantPosition.pos().lon()
|
||||
<< " equipmentNumber=" << equipmentNumber
|
||||
<< " eventType=" << eventType;
|
||||
pe.id(m_ddsHandler->getParticipantEventId());
|
||||
pe.eventTypeId(eventType);
|
||||
pe.participantId(participantPosition.participantId());
|
||||
pe.eventTime(participantPosition.sampleTime());
|
||||
pe.aesItemId(borderline.id);
|
||||
pe.partyId(participantPosition.partyId());
|
||||
pe.aesName(borderline.name.toStdString());
|
||||
pe.equipmentNumber(equipmentNumber);
|
||||
pe.position(participantPosition.pos());
|
||||
|
||||
m_ddsHandler->dtsCes()->publish(pe);
|
||||
qint64 id = pe.id();
|
||||
QTimer::singleShot(1 * 60 * 1000, this, [id, this]() { m_ddsHandler->dtsCes()->removeParticipantEventByKey(id); });
|
||||
}
|
||||
|
||||
|
||||
HandlerParticipantBorderline::BorderlineUtm::BorderlineUtm(const AreaEffectSimulation::Borderline &bl)
|
||||
: id(bl.id())
|
||||
, operatorId(bl.operatorId())
|
||||
, partyId(bl.partyId().is_set() ? bl.partyId().get() : -1)
|
||||
, name(QString::fromStdString(bl.name()))
|
||||
{
|
||||
points.reserve(bl.segments().size());
|
||||
for (const Core::GeoPosition2D &pointGeo : bl.segments())
|
||||
points.push_back(CentralEffectSimulation::geographic2Utm(pointGeo, &zone));
|
||||
|
||||
boundingBox = points.boundingRect();
|
||||
// build Polygon:
|
||||
}
|
||||
|
||||
} // namespace CentralEffectSimulationBasic
|
||||
+86
@@ -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 <AreaEffectSimulation/aes_dtc.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
|
||||
|
||||
#include <QHash>
|
||||
#include <QRectF>
|
||||
#include <QPolygonF>
|
||||
|
||||
|
||||
// AES-Handling for participants
|
||||
namespace CentralEffectSimulationBasic
|
||||
{
|
||||
class HandlerParticipantBorderline final
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
struct BorderlineUtm
|
||||
{
|
||||
int id = 0;
|
||||
int zone = -1;
|
||||
int32_t operatorId = 0;
|
||||
int32_t partyId = -1;
|
||||
QPolygonF points;
|
||||
QRectF boundingBox;
|
||||
QString name;
|
||||
|
||||
BorderlineUtm() = default;
|
||||
explicit BorderlineUtm(const AreaEffectSimulation::Borderline &bl);
|
||||
};
|
||||
|
||||
public:
|
||||
HandlerParticipantBorderline(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~HandlerParticipantBorderline();
|
||||
|
||||
/**
|
||||
* Initialize the handler to manage information from player management
|
||||
*/
|
||||
bool init();
|
||||
|
||||
private Q_SLOTS:
|
||||
/**
|
||||
* Handle the signals from 'ParticipantHandler'
|
||||
*/
|
||||
void onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos);
|
||||
|
||||
/**
|
||||
* Handle the signals from 'AES'
|
||||
*/
|
||||
void onBorderlineChanged(const AreaEffectSimulation::Borderline &data, DataModification modType);
|
||||
|
||||
private: // methoden
|
||||
void sendParticipantEvent(const BorderlineUtm &borderline,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
|
||||
const ProjectDataManagement::EventType eventType);
|
||||
bool intersect(const QPolygonF &polygonf, const QLineF &linef) const;
|
||||
|
||||
private: // attributes
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant;
|
||||
|
||||
// AES-Values
|
||||
QHash<int, BorderlineUtm> m_borderlines; // key = aesItemId
|
||||
|
||||
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
|
||||
};
|
||||
} // namespace CentralEffectSimulationBasic
|
||||
|
||||
+310
@@ -0,0 +1,310 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
#include "handler_simulated_movement.h"
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
|
||||
#include <QTimer>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <ngldb/dbtransaction.h>
|
||||
|
||||
namespace CentralEffectSimulationBasic
|
||||
{
|
||||
|
||||
HandlerSimulatedMovement::HandlerSimulatedMovement(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::DatabaseInterface> &db,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, SimulatedMovementModifyRequestHandler(ddsHandler->ftsCes())
|
||||
, SimulatedMovementRemoveRequestHandler(ddsHandler->ftsCes())
|
||||
, SimulatedMovementRemoveByParticipantIdRequestHandler(ddsHandler->ftsCes())
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_handlerParticipant(participantHandler)
|
||||
, m_db(db)
|
||||
, m_jumpToStart(false)
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.Basic.HandlerSimulatedMovement"))
|
||||
{
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HandlerSimulatedMovement::~HandlerSimulatedMovement()
|
||||
{
|
||||
qDeleteAll(m_simulationMovements);
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerSimulatedMovement::init()
|
||||
{
|
||||
if (!loadSimulatedMovementFromDb())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} // end of init()
|
||||
|
||||
bool HandlerSimulatedMovement::loadSimulatedMovementFromDb()
|
||||
{
|
||||
QVector<CentralEffectSimulation::Database::CesSimulatedMovement> simMoveVec;
|
||||
if (!m_db->select(simMoveVec))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading data from database 'CesSimulatedMovement'";
|
||||
return false;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "loadSimulatedMovementFromDb size =" << simMoveVec.size();
|
||||
|
||||
QVector<CentralEffectSimulation::Database::CesSimulatedMovementSegment> simMoveSegVec;
|
||||
if (!m_db->select(simMoveSegVec))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading data from database 'CesSimulatedMovementSegment'";
|
||||
return false;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "loadSimulatedMovementSegmentsFromDb size =" << simMoveSegVec.size();
|
||||
|
||||
// add to internal buffer
|
||||
for (const CentralEffectSimulation::Database::CesSimulatedMovement &data : qAsConst(simMoveVec))
|
||||
{
|
||||
CentralEffectSimulation::SimulatedMovement request;
|
||||
request.id(data.id);
|
||||
request.name(data.name.toStdString());
|
||||
request.startTime(data.startTime);
|
||||
request.participantId(data.participantId);
|
||||
request.repeat(data.repeat);
|
||||
request.nextPoint(data.nextpoint);
|
||||
DEBUG_LOG(m_logger) << "Loading SimulatedMovement: " << request;
|
||||
|
||||
QMap <int, CentralEffectSimulation::Database::CesSimulatedMovementSegment> segDbMap; // QMap to get it sorted
|
||||
for (const CentralEffectSimulation::Database::CesSimulatedMovementSegment &segData : qAsConst(simMoveSegVec))
|
||||
{
|
||||
if (segData.simulatedMovementId == data.id)
|
||||
segDbMap.insert(segData.positionIndex, segData);
|
||||
}
|
||||
request.segments().reserve(segDbMap.size());
|
||||
CentralEffectSimulation::SimulatedMovementSegment seg;
|
||||
for (const CentralEffectSimulation::Database::CesSimulatedMovementSegment &segDb : qAsConst(segDbMap))
|
||||
{
|
||||
seg.delay(segDb.delay);
|
||||
seg.name(segDb.name.toStdString());
|
||||
seg.speed(segDb.speed);
|
||||
seg.position(Core::GeoPosition2D(segDb.position.x(),
|
||||
segDb.position.y()));
|
||||
request.segments().push_back(seg);
|
||||
}
|
||||
SimulationMovement *sm = new SimulationMovement(m_ddsHandler, m_db, m_handlerParticipant, request);
|
||||
m_simulationMovements.insert(sm->id(), sm);
|
||||
|
||||
publishSimulatedMovement(request);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerSimulatedMovement::insertInDb(const CentralEffectSimulation::SimulatedMovement &request)
|
||||
{
|
||||
CentralEffectSimulation::Database::CesSimulatedMovement newSimulatedMovement = SimulationMovement::toDb(request);
|
||||
|
||||
DBTransaction trans(m_db->database());
|
||||
|
||||
if (m_simulationMovements.contains(request.id()))
|
||||
newSimulatedMovement.nextpoint = m_simulationMovements.value(request.id())->getNextPoint();
|
||||
else // new Simulation
|
||||
newSimulatedMovement.nextpoint = 1;
|
||||
|
||||
if (!m_db->insert(newSimulatedMovement))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error adding 'CesSimulatedMovement' to database"));
|
||||
DEBUG_LOG(m_logger) << "newSimulatedMovement.id = " << newSimulatedMovement.id;
|
||||
|
||||
CentralEffectSimulation::Database::CesSimulatedMovementSegment newSegment;
|
||||
newSegment.simulatedMovementId = newSimulatedMovement.id;
|
||||
for (const CentralEffectSimulation::SimulatedMovementSegment &seg : request.segments())
|
||||
{
|
||||
newSegment.id = 0; // insert
|
||||
newSegment.delay = seg.delay();
|
||||
newSegment.speed = seg.speed();
|
||||
newSegment.name = QString::fromStdString(seg.name());
|
||||
newSegment.position = QPointF(seg.position().lon(), seg.position().lat());
|
||||
if (!m_db->insert(newSegment))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error adding 'CesSimulatedMovementSegment' to database"));
|
||||
|
||||
++newSegment.positionIndex;
|
||||
}
|
||||
|
||||
trans.commit();
|
||||
|
||||
DEBUG_LOG(m_logger) << "newSimulatedMovement.id=" << newSimulatedMovement.id << " request.id=" << request.id();
|
||||
return Core::FunctionReplyObject(newSimulatedMovement.id);
|
||||
} // end of insertInDb
|
||||
|
||||
Core::FunctionReplyObject HandlerSimulatedMovement::updateDb(const CentralEffectSimulation::SimulatedMovement &request)
|
||||
{
|
||||
CentralEffectSimulation::Database::CesSimulatedMovement newSimulatedMovement(SimulationMovement::toDb(request));
|
||||
if (!m_db->update(newSimulatedMovement))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error update 'CesSimulatedMovement' to database"));
|
||||
DEBUG_LOG(m_logger) << "newSimulatedMovement.id = " << newSimulatedMovement.id;
|
||||
|
||||
|
||||
// First remove all participant-segments
|
||||
m_db->removeCesSimulatedMovementSegmentBySimulatedMovementId(newSimulatedMovement.id);
|
||||
|
||||
// Insert new segments:
|
||||
CentralEffectSimulation::Database::CesSimulatedMovementSegment newSegment;
|
||||
newSegment.simulatedMovementId = newSimulatedMovement.id;
|
||||
for (const CentralEffectSimulation::SimulatedMovementSegment &seg : request.segments())
|
||||
{
|
||||
newSegment.id = 0; // insert
|
||||
newSegment.delay = seg.delay();
|
||||
newSegment.speed = seg.speed();
|
||||
newSegment.name = QString::fromStdString(seg.name());
|
||||
newSegment.position = QPointF(seg.position().lon(), seg.position().lat());
|
||||
if (!m_db->insert(newSegment))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error adding 'CesSimulatedMovementSegment' to database"));
|
||||
++newSegment.positionIndex;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "newSimulatedMovement.id=" << newSimulatedMovement.id << " request.id=" << request.id();
|
||||
return Core::FunctionReplyObject(newSimulatedMovement.id);
|
||||
} // end of updateDb
|
||||
|
||||
|
||||
Core::FunctionReplyObject HandlerSimulatedMovement::removeFromDb(const int32_t id)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "removeFromDb: id=" << id;
|
||||
if (!m_db->removeCesSimulatedMovement(id))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error remove 'CesSimulatedMovement' from database"));
|
||||
return Core::FunctionReplyObject(id);
|
||||
}
|
||||
|
||||
void HandlerSimulatedMovement::publishSimulatedMovement(const CentralEffectSimulation::SimulatedMovement &request)
|
||||
{
|
||||
INFO_LOG(m_logger) << "publishSimulatedMovement: " << request;
|
||||
m_ddsHandler->dtsCes()->publish(request);
|
||||
}
|
||||
|
||||
void HandlerSimulatedMovement::setParticipantAsSimulated(const int &participantId, const bool isSimulated)
|
||||
{
|
||||
if (participantId <= 0)
|
||||
return;
|
||||
ParticipantManagement::SetAsSimulated req(participantId,isSimulated);
|
||||
if (!m_ddsHandler->ftcPpm()->setAsSimulatedRequest(req, this))
|
||||
ERROR_LOG(m_logger) << "Error modify participant data participantId=" << participantId;
|
||||
}
|
||||
|
||||
void HandlerSimulatedMovement::onModifyParticipantDataReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
if (replyObject.error())
|
||||
WARNING_LOG(m_logger) << "onModifyParticipantDataReply: " << replyObject();
|
||||
}
|
||||
|
||||
void HandlerSimulatedMovement::onSetAsSimulatedReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
if (replyObject.error())
|
||||
WARNING_LOG(m_logger) << "onSetAsSimulatedReply: " << replyObject();
|
||||
}
|
||||
|
||||
void HandlerSimulatedMovement::onSimulatedMovementModifyRequest(const rti::core::SampleIdentity &cookie,
|
||||
const CentralEffectSimulation::SimulatedMovement &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onSimulatedMovementModifyRequest: " << request;
|
||||
m_jumpToStart = request.jumpToStart();
|
||||
|
||||
// we allow a modify with requestId = 0 and participantId != 0
|
||||
SimulationMovement *sm = findSimulationMovement(request.id(), request.participantId());
|
||||
if (sm)
|
||||
sm->setSimulatedMovementRequest(request);
|
||||
else
|
||||
sm = new SimulationMovement(m_ddsHandler, m_db, m_handlerParticipant, request);
|
||||
|
||||
// New Route
|
||||
if (request.jumpToStart())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sm->setJump(true)";
|
||||
sm->setJump(true);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject reply = request.id() > 0
|
||||
? updateDb(sm->simMovementData())
|
||||
: insertInDb(sm->simMovementData());
|
||||
|
||||
sm->setId(reply.id());
|
||||
m_simulationMovements[sm->id()] = sm;
|
||||
publishSimulatedMovement(request);
|
||||
|
||||
setParticipantAsSimulated(request.participantId(), true);
|
||||
|
||||
DEBUG_LOG(m_logger) << "simulatedMovementModifyReply id=" << reply.id();
|
||||
|
||||
m_ddsHandler->ftsCes()->simulatedMovementModifyReply(cookie, reply);
|
||||
} // end onSimulatedMovementModifyRequest
|
||||
|
||||
Core::FunctionReplyObject HandlerSimulatedMovement::removeSimulatedMovement(int32_t ddsId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "removeSimulatedMovement with id " << ddsId << ", " << m_simulationMovements.size();
|
||||
|
||||
if (ddsId <= 0)
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "remove participant simulation "));
|
||||
|
||||
auto reply = removeFromDb(ddsId);
|
||||
if (reply.error())
|
||||
return reply;
|
||||
|
||||
int participantId = -1;
|
||||
auto it = m_simulationMovements.find(ddsId);
|
||||
if (it != m_simulationMovements.end())
|
||||
{
|
||||
participantId = it.value()->participantId();
|
||||
delete it.value();
|
||||
m_simulationMovements.erase(it);
|
||||
}
|
||||
if (participantId == -1)
|
||||
WARNING_LOG(m_logger) << "Could not find movement simulation with id " << ddsId << ", " << m_simulationMovements.size();
|
||||
|
||||
setParticipantAsSimulated(participantId, false);
|
||||
return reply;
|
||||
}
|
||||
|
||||
void HandlerSimulatedMovement::onSimulatedMovementRemoveRequest(const rti::core::SampleIdentity &cookie,
|
||||
const Core::RemoveElementRequest &request)
|
||||
{
|
||||
Core::FunctionReplyObject reply = removeSimulatedMovement(request.id());
|
||||
if (reply.error())
|
||||
WARNING_LOG(m_logger) << reply();
|
||||
m_ddsHandler->ftsCes()->simulatedMovementRemoveReply(cookie, reply);
|
||||
|
||||
} // end onSimulatedMovementRemoveRequest
|
||||
|
||||
void HandlerSimulatedMovement::onSimulatedMovementRemoveByParticipantIdRequest(const rti::core::SampleIdentity &cookie,
|
||||
const CentralEffectSimulation::SimulatedMovementRemoveByParticipantId &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onSimulatedMovementRemoveByParticipantIdRequest: " << request;
|
||||
|
||||
int id = 0;
|
||||
for (const SimulationMovement *simMovement : qAsConst(m_simulationMovements))
|
||||
{
|
||||
if (simMovement->participantId() == request.participantId())
|
||||
{
|
||||
id = simMovement->id();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Core::FunctionReplyObject reply = removeSimulatedMovement(id);
|
||||
if (reply.error())
|
||||
WARNING_LOG(m_logger) << reply();
|
||||
m_ddsHandler->ftsCes()->simulatedMovementRemoveByParticipantIdReply(cookie, reply);
|
||||
}
|
||||
|
||||
|
||||
SimulationMovement *HandlerSimulatedMovement::findSimulationMovement(int id, int participantId)
|
||||
{
|
||||
if (id)
|
||||
return m_simulationMovements.value(id);
|
||||
for (SimulationMovement *s : qAsConst(m_simulationMovements))
|
||||
{
|
||||
if (s->participantId() == participantId)
|
||||
return s;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace CentralEffectSimulationBasic
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "simulation_movement.h"
|
||||
|
||||
#include <CentralEffectSimulation/logger.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/ces_dts.h>
|
||||
#include <CentralEffectSimulation/ces_fts.h>
|
||||
#include <CentralEffectSimulation/ces_db.h>
|
||||
#include <ParticipantManagement/ppm_ftc.h>
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
|
||||
#include <QHash>
|
||||
|
||||
|
||||
|
||||
|
||||
// Simulated movement for participants
|
||||
namespace CentralEffectSimulationBasic
|
||||
{
|
||||
|
||||
class HandlerSimulatedMovement final
|
||||
: public QObject
|
||||
, protected CentralEffectSimulation::Interface::Fts::SimulatedMovementModifyRequestHandler
|
||||
, protected CentralEffectSimulation::Interface::Fts::SimulatedMovementRemoveRequestHandler
|
||||
, protected CentralEffectSimulation::Interface::Fts::SimulatedMovementRemoveByParticipantIdRequestHandler
|
||||
, protected ParticipantManagement::Interface::Ftc::ModifyParticipantDataReplyHandler
|
||||
, protected ParticipantManagement::Interface::Ftc::SetAsSimulatedReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit HandlerSimulatedMovement(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::DatabaseInterface> &db,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~HandlerSimulatedMovement();
|
||||
|
||||
/**
|
||||
* Initialize the handler to manage information from player management
|
||||
*/
|
||||
bool init();
|
||||
void onModifyParticipantDataReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void onSetAsSimulatedReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
private: // methoden
|
||||
bool loadSimulatedMovementFromDb();
|
||||
void onSimulatedMovementModifyRequest(const rti::core::SampleIdentity &cookie,
|
||||
const CentralEffectSimulation::SimulatedMovement &request) override;
|
||||
void onSimulatedMovementRemoveRequest(const rti::core::SampleIdentity &cookie,
|
||||
const Core::RemoveElementRequest &request) override;
|
||||
void onSimulatedMovementRemoveByParticipantIdRequest(const rti::core::SampleIdentity &cookie,
|
||||
const CentralEffectSimulation::SimulatedMovementRemoveByParticipantId &request) override;
|
||||
Core::FunctionReplyObject insertInDb(const CentralEffectSimulation::SimulatedMovement &request);
|
||||
Core::FunctionReplyObject updateDb(const CentralEffectSimulation::SimulatedMovement &request);
|
||||
Core::FunctionReplyObject removeFromDb(const int32_t id);
|
||||
void publishSimulatedMovement(const CentralEffectSimulation::SimulatedMovement &request);
|
||||
void setParticipantAsSimulated(const int &participantId, const bool isSimulated);
|
||||
Core::FunctionReplyObject removeSimulatedMovement(int32_t ddsId);
|
||||
SimulationMovement *findSimulationMovement(int id, int participantId);
|
||||
|
||||
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::DatabaseInterface> m_db;
|
||||
|
||||
// Input-values for simulation
|
||||
QHash<int, SimulationMovement *> m_simulationMovements; // Key = SimulationMovement.id
|
||||
|
||||
int m_jumpToStart;
|
||||
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
|
||||
};
|
||||
} // namespace CentralEffectSimulationBasic
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Plugin CentralEffectSimulation Basic
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace CentralEffectSimulationBasic
|
||||
{
|
||||
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> CentralEffectSimulationBasicPlugin::createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
CentralEffectSimulation::MainHandler *mainHandler)
|
||||
{
|
||||
return std::make_shared<CesBasicInterfaceImpl>(pdp, dDSConnector, settings, mainHandler);
|
||||
}
|
||||
|
||||
|
||||
CesBasicInterfaceImpl::CesBasicInterfaceImpl(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.Basic.CesBasicInterfaceImpl"))
|
||||
{
|
||||
Q_UNUSED(settings)
|
||||
}
|
||||
|
||||
CesBasicInterfaceImpl::~CesBasicInterfaceImpl()
|
||||
{
|
||||
m_handlerParticipantBorderline.reset();
|
||||
m_handlerSimulatedMovement.reset();
|
||||
}
|
||||
|
||||
|
||||
bool CesBasicInterfaceImpl::init(int domainId, int exerciseId)
|
||||
{
|
||||
|
||||
m_domainId = domainId;
|
||||
m_exerciseId = exerciseId;
|
||||
INFO_LOG(m_logger) << "CesBasicInterfaceImpl::init()"
|
||||
<< " m_domainId=" << m_domainId
|
||||
<< " m_exerciseId=" << m_exerciseId;
|
||||
|
||||
|
||||
|
||||
|
||||
// initialize handlerParticipantBorderline
|
||||
m_handlerParticipantBorderline = std::make_shared<HandlerParticipantBorderline>(m_ddsHandler,
|
||||
m_handlerParticipant,
|
||||
this);
|
||||
|
||||
if (!m_handlerParticipantBorderline->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation HandlerParticipantBorderline failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// initialize handlerSimulatedMovement
|
||||
m_handlerSimulatedMovement = std::make_shared<HandlerSimulatedMovement>(m_ddsHandler,
|
||||
m_handlerParticipant,
|
||||
m_db,
|
||||
this);
|
||||
|
||||
if (!m_handlerSimulatedMovement->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation m_handlerSimulatedMovement failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(m_logger) << "CentralEffectSimulationBasicInterfaceImpl::init() return true";
|
||||
return true;
|
||||
}
|
||||
|
||||
QString CesBasicInterfaceImpl::echo(const QString &message)
|
||||
{
|
||||
|
||||
QString ret(QStringLiteral("<<<< %1 >>>> CesBasicInterfaceImpl::echo").arg(message));
|
||||
INFO_LOG(m_logger) << "CesBasicInterfaceImpl::echo return:" << ret;
|
||||
DEBUG_LOG(m_logger) << "DEBUG: CesBasicInterfaceImpl::echo return:" << ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} //namespace CentralEffectSimulationBasic
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Plugin CentralEffectSimulation Basic
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "handler_participant_borderline.h"
|
||||
#include "handler_simulated_movement.h"
|
||||
|
||||
#include <CentralEffectSimulation/logger.h>
|
||||
#include <CentralEffectSimulation/ces_plugin_interface.h>
|
||||
#include <CentralEffectSimulation/main_handler.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
|
||||
//namespace NGLDB
|
||||
//{
|
||||
//template <typename DB> class DbServiceHandler;
|
||||
//}
|
||||
|
||||
namespace CentralEffectSimulationBasic
|
||||
{
|
||||
//using DbHandler = NGLDB::DbServiceHandler<CentralEffectSimulation::DatabaseInterface>;
|
||||
|
||||
class CentralEffectSimulationBasicPlugin : public QObject, public CentralEffectSimulation::Plugin::Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "special:3:ces.CentralEffectSimulationBasicPlugin")
|
||||
Q_INTERFACES(CentralEffectSimulation::Plugin::Plugin)
|
||||
|
||||
public:
|
||||
CentralEffectSimulationBasicPlugin() = default;
|
||||
~CentralEffectSimulationBasicPlugin() = 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 CesBasicInterfaceImpl final : public CentralEffectSimulation::Plugin::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CesBasicInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
CentralEffectSimulation::MainHandler *mainHandler);
|
||||
~CesBasicInterfaceImpl();
|
||||
//bool init();
|
||||
const char *name() const override { return "CentralEffectSimulationBasic"; }
|
||||
QString echo(const QString &message) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
bool init(int domainId, int exerciseId) override;
|
||||
private:
|
||||
|
||||
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<HandlerParticipantBorderline> m_handlerParticipantBorderline; ///< Pointer to handler for check participants cross Borderline
|
||||
std::shared_ptr<HandlerSimulatedMovement> m_handlerSimulatedMovement; ///< Pointer to handler for Simulated Movement
|
||||
|
||||
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
int m_domainId = 0;
|
||||
int m_exerciseId = 0;
|
||||
};
|
||||
|
||||
} // namespace CentralEffectSimulationBasic
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
/**
|
||||
* Simulation for Movement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-12-13
|
||||
*/
|
||||
|
||||
#include "simulation_movement.h"
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <QDateTime>
|
||||
|
||||
namespace CentralEffectSimulationBasic
|
||||
{
|
||||
|
||||
SimulationMovement::SimulationMovement(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::DatabaseInterface> &db,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
const CentralEffectSimulation::SimulatedMovement &sml,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_db(db)
|
||||
, m_handlerParticipant(participantHandler)
|
||||
, m_moveTime(1)
|
||||
, m_actSegment()
|
||||
, m_newPos()
|
||||
, m_simStart(true)
|
||||
, m_zone(-1)
|
||||
, m_segTimer(new QTimer(this))
|
||||
, m_moveTimer(new QTimer(this))
|
||||
, m_simMovement(sml)
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.Basic.SimulationMovement"))
|
||||
{
|
||||
m_segTimer->setSingleShot(true);
|
||||
connect(m_segTimer, &QTimer::timeout, this, &SimulationMovement::startNewSegment);
|
||||
|
||||
m_moveTimer->setSingleShot(true);
|
||||
connect(m_moveTimer, &QTimer::timeout, this, &SimulationMovement::move);
|
||||
|
||||
setSimulatedMovementRequest(sml);
|
||||
}
|
||||
|
||||
SimulationMovement::~SimulationMovement()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Delete SimulatedMovement "
|
||||
<< " id=" << m_simMovement.id()
|
||||
<< " participantId= " << m_simMovement.participantId();
|
||||
m_ddsHandler->dtsCes()->removeSimulatedMovementByKey(m_simMovement.id());
|
||||
m_segTimer->stop();
|
||||
m_moveTimer->stop();
|
||||
}
|
||||
|
||||
void SimulationMovement::setSimulatedMovementRequest(const CentralEffectSimulation::SimulatedMovement &sml)
|
||||
{
|
||||
int nextPoint = m_simMovement.nextPoint();
|
||||
m_simMovement = sml;
|
||||
m_simMovement.nextPoint(nextPoint);
|
||||
|
||||
m_moveTime = 1;
|
||||
m_segTimer->stop();
|
||||
m_moveTimer->stop();
|
||||
|
||||
m_points.clear();
|
||||
m_segSpeed.clear();
|
||||
m_segDelay.clear();
|
||||
m_points.reserve(sml.segments().size());
|
||||
m_segSpeed.reserve(sml.segments().size());
|
||||
m_segDelay.reserve(sml.segments().size());
|
||||
|
||||
for (const CentralEffectSimulation::SimulatedMovementSegment &point : sml.segments())
|
||||
{
|
||||
const Core::GeoPosition2D &pointGeo = point.position();
|
||||
m_points.push_back(m_zone == -1 ? CentralEffectSimulation::geographic2Utm(pointGeo, &m_zone) : CentralEffectSimulation::geographic2Utm(pointGeo, m_zone));
|
||||
DEBUG_LOG(m_logger) << "pointGeo lat=" << pointGeo.lat() << " lon=" << pointGeo.lon()
|
||||
<< " point lat=" << point.position().lat() << " lon=" << point.position().lon()
|
||||
<< " utmPoint=" << CentralEffectSimulation::debug(m_points.last());
|
||||
m_segSpeed.append(point.speed());
|
||||
m_segDelay.append(point.delay());
|
||||
}
|
||||
|
||||
// Only start simulation in future
|
||||
DEBUG_LOG(m_logger) << "m_startTime - QDateTime::currentMSecsSinceEpoch()=" << m_simMovement.startTime() - QDateTime::currentMSecsSinceEpoch()
|
||||
<< " m_startTime=" << m_simMovement.startTime()
|
||||
<< " currentTime=" << QDateTime::currentMSecsSinceEpoch()
|
||||
<< " m_nextPoint=" << m_simMovement.nextPoint();
|
||||
|
||||
if (m_simMovement.nextPoint() > 0 && m_points.size() > m_simMovement.nextPoint())
|
||||
m_newPos = m_points[m_simMovement.nextPoint()].toPoint();
|
||||
|
||||
if (m_simMovement.startTime() - QDateTime::currentMSecsSinceEpoch() > 0)
|
||||
m_moveTimer->start(m_simMovement.startTime() - QDateTime::currentMSecsSinceEpoch());
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Service-Start";
|
||||
m_moveTimer->start(10); // Service-Start
|
||||
}
|
||||
}
|
||||
|
||||
void SimulationMovement::updateNextPointInDb()
|
||||
{
|
||||
if (m_simMovement.id() <= 0)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Internal error - id not set!";
|
||||
return;
|
||||
}
|
||||
CentralEffectSimulation::Database::CesSimulatedMovement dbSim = toDb(m_simMovement);
|
||||
m_db->update(dbSim);
|
||||
}
|
||||
|
||||
|
||||
void SimulationMovement::startNewSegment()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "simulate participantId = " << m_simMovement.participantId()
|
||||
<< " m_nextPoint = " << m_simMovement.nextPoint();
|
||||
|
||||
m_moveTime = 1;
|
||||
if (m_simMovement.nextPoint() < m_points.size())
|
||||
{
|
||||
QPointF p1;
|
||||
// Next segment
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData pos = m_handlerParticipant->position(m_simMovement.participantId());
|
||||
if (pos.participantId() == m_simMovement.participantId())
|
||||
{
|
||||
p1 = CentralEffectSimulation::geographic2Utm(pos.pos(), m_zone);
|
||||
DEBUG_LOG(m_logger) << "Next segment ParticipantPosition =" << CentralEffectSimulation::debug(p1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_simStart) // Wait for participantPosition
|
||||
{
|
||||
INFO_LOG(m_logger) << "Wait for participant position participantId =" << m_simMovement.participantId();
|
||||
m_segTimer->start(1000);
|
||||
return;
|
||||
}
|
||||
if (m_simMovement.nextPoint() > 0)
|
||||
{
|
||||
p1 = m_points.at(m_simMovement.participantId() - 1);
|
||||
DEBUG_LOG(m_logger) << "nextPoint>0 (" << m_simMovement.nextPoint() << ") ParticipantPosition =" << CentralEffectSimulation::debug(p1);
|
||||
}
|
||||
else
|
||||
{
|
||||
p1 = m_points.at(m_points.size() - 1);
|
||||
DEBUG_LOG(m_logger) << "nextPoint=" << m_simMovement.nextPoint() << " ParticipantPosition =" << CentralEffectSimulation::debug(p1);
|
||||
}
|
||||
}
|
||||
const QPointF &p2 = m_points.at(m_simMovement.nextPoint());
|
||||
m_actSegment.setPoints(p1, p2);
|
||||
int curDelay = m_segDelay.at(m_simMovement.nextPoint());
|
||||
DEBUG_LOG(m_logger) << "New Segment: p1 = " << CentralEffectSimulation::debug(p1) << " p2=" << CentralEffectSimulation::debug(p2)
|
||||
<< " delay =" << curDelay;
|
||||
m_moveTimer->start(curDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_simMovement.repeat())
|
||||
{
|
||||
m_simMovement.nextPoint(0);
|
||||
m_moveTimer->start(m_segDelay.at(m_simMovement.nextPoint()));
|
||||
}
|
||||
else
|
||||
m_simMovement.nextPoint(-1); // Invalid value
|
||||
}
|
||||
}
|
||||
|
||||
void SimulationMovement::setJump(bool jump)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Jump";
|
||||
if (jump)
|
||||
{
|
||||
m_simMovement.nextPoint(1);
|
||||
m_newPos = m_points.at(0);
|
||||
m_actSegment.setPoints(m_newPos,
|
||||
m_points.at(m_simMovement.nextPoint()));
|
||||
m_moveTime = 1;
|
||||
m_simStart = false;
|
||||
publishNewPos();
|
||||
DEBUG_LOG(m_logger) << "Jump done";
|
||||
}
|
||||
}
|
||||
|
||||
void SimulationMovement::publishSimulatedMovement()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << " m_nextPoint= " << m_simMovement.nextPoint();
|
||||
m_ddsHandler->dtsCes()->publish(m_simMovement);
|
||||
}
|
||||
|
||||
void SimulationMovement::publishNewPos()
|
||||
{
|
||||
TrainingAreaBase::EquipmentPosition participantPos;
|
||||
|
||||
LtsCoordTrans::UtmCoordinate utmPos;
|
||||
utmPos.zone = m_zone;
|
||||
utmPos.northp = true;
|
||||
utmPos.x = m_newPos.x();
|
||||
utmPos.y = m_newPos.y();
|
||||
const QPointF posGeo = utmPos.geographic();
|
||||
DEBUG_LOG(m_logger) << "participantPos zone=" << utmPos.zone
|
||||
<< " northp=" << utmPos.northp
|
||||
<< " x=" << utmPos.x
|
||||
<< " y=" << utmPos.y;
|
||||
|
||||
const Core::GeoPosition pos(Core::GeoPosition(posGeo.x(), posGeo.y(), 0));
|
||||
|
||||
participantPos.equipmentNumber(-m_simMovement.participantId()); // negative - treat as participantId
|
||||
participantPos.sampleTime(m_ddsHandler->currentPartitionTime());
|
||||
participantPos.position().position(pos);
|
||||
participantPos.position().reportingSource(Core::PositionReportingSource::MovementSimulation);
|
||||
|
||||
m_ddsHandler->dtsTab()->publish(participantPos);
|
||||
|
||||
}
|
||||
|
||||
void SimulationMovement::move()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "move";
|
||||
if (m_simMovement.nextPoint() < 0)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "move next point < 0";
|
||||
return;
|
||||
}
|
||||
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData partPos = m_handlerParticipant->position(m_simMovement.participantId());
|
||||
const QPointF participantPosUtm = CentralEffectSimulation::geographic2Utm(partPos.pos(), m_zone);
|
||||
if (partPos.participantId() != m_simMovement.participantId())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "move no ParticipantId=" << m_simMovement.participantId();
|
||||
m_moveTimer->start(1000);
|
||||
return;
|
||||
}
|
||||
if (!partPos.positionValid)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "move no ParticipantId=" << m_simMovement.participantId();
|
||||
m_moveTimer->start(1000);
|
||||
return;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << " pos=" << CentralEffectSimulation::debug(participantPosUtm);
|
||||
|
||||
QLineF step = m_actSegment;
|
||||
if (m_simStart)
|
||||
{
|
||||
m_actSegment.setPoints(participantPosUtm,
|
||||
m_points.at(m_simMovement.nextPoint()));
|
||||
step = m_actSegment;
|
||||
DEBUG_LOG(m_logger) << "m_simStart set m_actSegment"
|
||||
<< " p1: " << CentralEffectSimulation::debug(m_actSegment.p1())
|
||||
<< " p2: " << CentralEffectSimulation::debug(m_actSegment.p2());
|
||||
m_simStart = false;
|
||||
}
|
||||
|
||||
if (m_segSpeed[m_simMovement.nextPoint()] <= 0.0)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "move next point < 0";
|
||||
return;
|
||||
}
|
||||
|
||||
m_newPos = m_points[m_simMovement.nextPoint()];
|
||||
step.setLength(m_segSpeed[m_simMovement.nextPoint()] * m_moveTime);
|
||||
m_moveTime++;
|
||||
// ready criterion
|
||||
if (step.length() >= m_actSegment.length() + 0.1 ||
|
||||
step.length() < 0.1) // 0.1 Magic Number but 10 cm distance to Point is arrived
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "move ready step.length()=" << step.length()
|
||||
<< " m_actSegment.length()=" << m_actSegment.length();
|
||||
m_simMovement.nextPoint(m_simMovement.nextPoint() + 1);
|
||||
if (m_simMovement.nextPoint() >= m_points.size())
|
||||
{
|
||||
if (m_simMovement.repeat())
|
||||
m_simMovement.nextPoint(0);
|
||||
else
|
||||
{
|
||||
m_simMovement.nextPoint(-1); // Invalid value
|
||||
return;
|
||||
}
|
||||
}
|
||||
updateNextPointInDb();
|
||||
DEBUG_LOG(m_logger) << "ready move participantId = " << m_simMovement.participantId()
|
||||
<< " m_nextPoint =" << m_simMovement.nextPoint()
|
||||
<< " newPos =" << m_newPos.x() << "/" << m_newPos.y()
|
||||
<< " m_moveTime=" << m_moveTime
|
||||
<< " length=" << m_segSpeed[m_simMovement.nextPoint()] * m_moveTime
|
||||
<< " step.length=" << step.length()
|
||||
<< " m_segSpeed[m_nextPoint]=" << m_segSpeed[m_simMovement.nextPoint()]
|
||||
<< " m_moveTime=" << m_moveTime
|
||||
<< " m_actSegment.length=" << m_actSegment.length()
|
||||
<< " m_zone=" << m_zone;
|
||||
publishNewPos();
|
||||
startNewSegment();
|
||||
publishSimulatedMovement();
|
||||
return;
|
||||
}
|
||||
m_newPos = step.p2();
|
||||
DEBUG_LOG(m_logger) << "move participantId = " << m_simMovement.participantId()
|
||||
<< " m_nextPoint =" << m_simMovement.nextPoint()
|
||||
<< " newPos =" << m_newPos.x() << "/" << m_newPos.y()
|
||||
<< " m_moveTime=" << m_moveTime
|
||||
<< " length=" << m_segSpeed[m_simMovement.nextPoint()] * m_moveTime
|
||||
<< " step.length=" << step.length()
|
||||
<< " m_speed=" << m_segSpeed[m_simMovement.nextPoint()]
|
||||
<< " m_moveTime=" << m_moveTime
|
||||
<< " m_actSegment.length=" << m_actSegment.length()
|
||||
<< " m_zone=" << m_zone;
|
||||
publishNewPos();
|
||||
m_moveTimer->start(1000); // Calculate new position each second
|
||||
}
|
||||
|
||||
CentralEffectSimulation::Database::CesSimulatedMovement SimulationMovement::toDb(const CentralEffectSimulation::SimulatedMovement &ddsSimMovement)
|
||||
{
|
||||
CentralEffectSimulation::Database::CesSimulatedMovement ret;
|
||||
ret.id = ddsSimMovement.id();
|
||||
ret.name = QString::fromStdString(ddsSimMovement.name());
|
||||
ret.startTime = ddsSimMovement.startTime();
|
||||
ret.participantId = ddsSimMovement.participantId();
|
||||
ret.repeat = ddsSimMovement.repeat();
|
||||
ret.nextpoint = ddsSimMovement.nextPoint();
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Simulation for Movement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-12-13
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <CentralEffectSimulation/logger.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
#include <CentralEffectSimulation/ces_db.h>
|
||||
|
||||
#include <QLineF>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
namespace CentralEffectSimulationBasic
|
||||
{
|
||||
|
||||
class SimulationMovement : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SimulationMovement(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::DatabaseInterface> &db,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
const CentralEffectSimulation::SimulatedMovement &sml,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~SimulationMovement();
|
||||
void setSimulatedMovementRequest(const CentralEffectSimulation::SimulatedMovement &sml);
|
||||
int id() const { return m_simMovement.id(); }
|
||||
void setId(int id) { m_simMovement.id(id); }
|
||||
int participantId() const { return m_simMovement.participantId(); }
|
||||
|
||||
void setJump(bool jump);
|
||||
void setnextPoint(int nextPoint) { m_simMovement.nextPoint(nextPoint); }
|
||||
int getNextPoint() const { return m_simMovement.nextPoint(); }
|
||||
void publishSimulatedMovement();
|
||||
const CentralEffectSimulation::SimulatedMovement &simMovementData() const { return m_simMovement; }
|
||||
|
||||
static CentralEffectSimulation::Database::CesSimulatedMovement toDb(const CentralEffectSimulation::SimulatedMovement &ddsSimMovement);
|
||||
protected Q_SLOTS:
|
||||
void publishNewPos();
|
||||
void startNewSegment();
|
||||
void move();
|
||||
|
||||
protected:
|
||||
void updateNextPointInDb();
|
||||
|
||||
private:
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
|
||||
std::shared_ptr<CentralEffectSimulation::DatabaseInterface> m_db;
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant;
|
||||
|
||||
// Input Data
|
||||
QVector<QPointF> m_points;
|
||||
QVector<double> m_segSpeed;
|
||||
QVector<int> m_segDelay;
|
||||
// Dynamic Data
|
||||
int m_moveTime; /// Time starts for each segment new
|
||||
QLineF m_actSegment;
|
||||
QPointF m_newPos;
|
||||
bool m_simStart; /// Start of simulation
|
||||
int m_zone;
|
||||
QTimer *m_segTimer;
|
||||
QTimer *m_moveTimer;
|
||||
|
||||
CentralEffectSimulation::SimulatedMovement m_simMovement;
|
||||
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# monitoring of the target areas
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(SRCS
|
||||
plugin.cpp
|
||||
plugin.h
|
||||
ces_building_model.cpp
|
||||
ces_building_model.h
|
||||
handler_building_ownership.cpp
|
||||
handler_building_ownership.h
|
||||
handler_building_model.cpp
|
||||
handler_building_model.h
|
||||
handler_aes_data.cpp
|
||||
handler_aes_data.h
|
||||
handler_contamination.cpp
|
||||
handler_contamination.h
|
||||
# logger.cpp
|
||||
# logger.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV cesPluginCesBuildings MODULE ${SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(cesPluginCesBuildings
|
||||
PUBLIC
|
||||
Qt5::Network
|
||||
Qt5::Widgets
|
||||
LtsCoordinate
|
||||
cesPluginInterface
|
||||
ngldb
|
||||
svcCesDDSCommon
|
||||
# ProjectConfig
|
||||
|
||||
)
|
||||
NGL_INSTALL_TARGET(cesPluginCesBuildings)
|
||||
|
||||
+378
@@ -0,0 +1,378 @@
|
||||
/**
|
||||
* Building Model
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, ESZS, 2016-04-14
|
||||
*/
|
||||
|
||||
#include "ces_building_model.h"
|
||||
|
||||
#include <Buildings/BuildingControlUnit/VWM/vwm_xml_reader.h>
|
||||
#include <Buildings/BuildingControlUnit/VWM/vwm_math.h>
|
||||
#include <LtsUtilsCore/dds_vector.h>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include <QLineF>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
bool intersects(const QLineF &line1, const QLineF &line2)
|
||||
{
|
||||
const QPointF a = line1.p2() - line1.p1();
|
||||
const QPointF b = line2.p1() - line2.p2();
|
||||
const QPointF c = line1.p1() - line2.p1();
|
||||
const qreal denominator = a.y() * b.x() - a.x() * b.y();
|
||||
if (denominator == 0 || !std::isfinite(denominator))
|
||||
return false;
|
||||
const qreal reciprocal = 1 / denominator;
|
||||
const qreal na = (b.y() * c.x() - b.x() * c.y()) * reciprocal;
|
||||
if (na < 0 || na > 1)
|
||||
return false;
|
||||
const qreal nb = (a.x() * c.y() - a.y() * c.x()) * reciprocal;
|
||||
if (nb < 0 || nb > 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
/*************************************************************************************************
|
||||
* Static methods *
|
||||
*************************************************************************************************/
|
||||
|
||||
bool BuildingModel::isValid(const LtsUtils::QPoint3D &point)
|
||||
{
|
||||
return point != invalidPosition();
|
||||
}
|
||||
|
||||
bool BuildingModel::isValid(const Core::GeoPosition &point)
|
||||
{
|
||||
return !qFuzzyIsNull(point.lon()) && !qFuzzyIsNull(point.lat()) && point.z() > invalidGeoPosition().z();
|
||||
}
|
||||
|
||||
LtsUtils::QPoint3D BuildingModel::invalidPosition()
|
||||
{
|
||||
return BuildingControlUnit::VWM::Math::invalidPosition();
|
||||
}
|
||||
|
||||
Core::GeoPosition BuildingModel::invalidGeoPosition()
|
||||
{
|
||||
return Core::GeoPosition(0., 0., -10000.);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************************
|
||||
* Ctor, dtor and init *
|
||||
*************************************************************************************************/
|
||||
|
||||
BuildingModel::BuildingModel(QObject *parent)
|
||||
: QObject(parent)
|
||||
, BuildingControlUnit::VWM::Building()
|
||||
, m_logger(CentralEffectSimulation::getLogger(QStringLiteral("BuildingModel")))
|
||||
{
|
||||
}
|
||||
|
||||
BuildingModel::~BuildingModel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool BuildingModel::init(
|
||||
const InfrastructureManagement::MainFootprint &mfp, const InfrastructureManagement::MainStructureElement &mse,
|
||||
const QByteArray &vmd,
|
||||
const int buildingId
|
||||
)
|
||||
{
|
||||
m_buildingId = buildingId;
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, m_buildingId=" << m_buildingId;
|
||||
|
||||
m_angle = mse.angle() * M_PI / 180.;
|
||||
m_refPosGeo = mse.geoPosition();
|
||||
m_refPosUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(mse.geoPosition().lon(), mse.geoPosition().lat());
|
||||
m_refPos = {m_refPosUtm.x, m_refPosUtm.y, m_refPosGeo.z()};
|
||||
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, m_buildingId=" << m_buildingId
|
||||
<< ", m_angle=" << m_angle
|
||||
<< ", m_refPosGeo=" << m_refPosGeo
|
||||
<< ", m_refPos=" << m_refPos;
|
||||
|
||||
|
||||
for (const InfrastructureManagement::FootprintElement &footprintElement : qAsConst(mfp.elements()))
|
||||
m_footprint << QPointF(footprintElement.relPosition().offsetX(), footprintElement.relPosition().offsetY());
|
||||
if (m_footprint.isEmpty())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading MainFootprint for building " << m_buildingId;
|
||||
return false;
|
||||
} // if
|
||||
m_boundingRect = m_footprint.boundingRect();
|
||||
|
||||
// const std::vector<uint8_t> &data = vmd.vulnerabilityData();
|
||||
// QByteArray array = qUncompress(QByteArray::fromRawData(reinterpret_cast<const char*>(&data[0]), data.size()));
|
||||
if (!BuildingControlUnit::VWM::XmlReader::readBuilding(vmd, *this))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading VulnerabilityModelData for building " << m_buildingId;
|
||||
return false;
|
||||
} // if
|
||||
|
||||
m_height = DBL_MIN;
|
||||
const QMap<int, BuildingControlUnit::VWM::Room> &roomMap = rooms();
|
||||
for (const BuildingControlUnit::VWM::Room &room : qAsConst(roomMap))
|
||||
for (const BuildingControlUnit::VWM::OuterWall &outerWall : qAsConst(room.outerWalls()))
|
||||
for (const BuildingControlUnit::VWM::WallElement &wallElement : qAsConst(outerWall.elements()))
|
||||
for (const LtsUtils::QPoint3D &point : qAsConst(wallElement))
|
||||
if (point.z() > m_height)
|
||||
m_height = point.z();
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_buildingId=" << m_buildingId;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************************
|
||||
* Intersection calculations *
|
||||
*************************************************************************************************/
|
||||
|
||||
bool BuildingModel::hasIntersectionSimplified(const LtsUtils::QPoint3D &start, const LtsUtils::QPoint3D &end) const
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_buildingId=" << m_buildingId
|
||||
<< ", start=" << start << ", end=" << end;
|
||||
|
||||
// keep origin of QRect (topLeft) in mind:
|
||||
static const QLineF topLine = QLineF(m_boundingRect.topRight(), m_boundingRect.topLeft());
|
||||
static const QLineF leftLine = QLineF(m_boundingRect.topLeft(), m_boundingRect.bottomLeft());
|
||||
static const QLineF bottomLine = QLineF(m_boundingRect.bottomLeft(), m_boundingRect.bottomRight());
|
||||
static const QLineF rightLine = QLineF(m_boundingRect.bottomRight(), m_boundingRect.topRight());
|
||||
|
||||
// qCritical() << " topLine" << topLine;
|
||||
// qCritical() << " leftLine" << leftLine;
|
||||
// qCritical() << " bottomLine" << bottomLine;
|
||||
// qCritical() << " rightLine" << rightLine;
|
||||
|
||||
// qCritical() << " start.z()" << start.z();
|
||||
// qCritical() << " end.z()" << end.z();
|
||||
// qCritical() << " m_height" << m_height;
|
||||
|
||||
// over the building?
|
||||
if (start.z() > m_height && end.z() > m_height)
|
||||
return false;
|
||||
|
||||
const QPointF start2D(start.x(), start.y());
|
||||
const QPointF end2D(end.x(), end.y());
|
||||
const QLineF startToEnd = QLineF(start2D, end2D);
|
||||
|
||||
// qCritical() << " startToEnd" << startToEnd;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
QPointF dummy;
|
||||
if (startToEnd.intersects(topLine, &dummy) != QLineF::BoundedIntersection &&
|
||||
startToEnd.intersects(leftLine, &dummy) != QLineF::BoundedIntersection &&
|
||||
startToEnd.intersects(bottomLine, &dummy) != QLineF::BoundedIntersection &&
|
||||
startToEnd.intersects(rightLine, &dummy) != QLineF::BoundedIntersection &&
|
||||
!m_boundingRect.contains(start2D) && !m_boundingRect.contains(end2D))
|
||||
#else
|
||||
if (!intersects(startToEnd, topLine) && !intersects(startToEnd, leftLine) &&
|
||||
!intersects(startToEnd, bottomLine) && !intersects(startToEnd, rightLine) &&
|
||||
!m_boundingRect.contains(start2D) && !m_boundingRect.contains(end2D))
|
||||
#endif
|
||||
return false;
|
||||
|
||||
// qCritical() << " intersects done";
|
||||
|
||||
|
||||
QPolygonF poly;
|
||||
poly << start2D;
|
||||
poly << end2D;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||
if (!m_footprint.intersects(poly))
|
||||
#else
|
||||
if (m_footprint.intersected(poly).isEmpty())
|
||||
#endif
|
||||
return false;
|
||||
|
||||
// qCritical() << " hasIntersectionSimplified -> return true";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BuildingModel::hasIntersectionSimplified(const Core::GeoPosition &start, const Core::GeoPosition &end) const
|
||||
{
|
||||
return hasIntersectionSimplified(fromGeographic(start), fromGeographic(end));
|
||||
}
|
||||
|
||||
bool BuildingModel::hasIntersectionSimplified(const QVector<LtsUtils::QPoint3D> &trajectory) const
|
||||
{
|
||||
for (int i = 1; i < trajectory.size(); ++i)
|
||||
if (hasIntersectionSimplified(trajectory[i - 1], trajectory[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BuildingModel::hasIntersectionSimplified(const std::vector<Core::GeoPosition> &trajectory) const
|
||||
{
|
||||
for (unsigned int i = 1; i < trajectory.size(); ++i)
|
||||
if (hasIntersectionSimplified(trajectory[i - 1], trajectory[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool BuildingModel::hasIntersection(const LtsUtils::QPoint3D &start, const LtsUtils::QPoint3D &end) const
|
||||
{
|
||||
if (!hasIntersectionSimplified(start, end))
|
||||
return false;
|
||||
|
||||
bool bHasIntersection = BuildingControlUnit::VWM::Math::hasIntersection(start, end, rooms());
|
||||
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_buildingId=" << m_buildingId
|
||||
<< ", start=" << start << ", end=" << end
|
||||
<< ", rooms().size()" << rooms().size()
|
||||
<< ", bHasIntersection=" << bHasIntersection;
|
||||
return bHasIntersection;
|
||||
}
|
||||
|
||||
bool BuildingModel::hasIntersection(const Core::GeoPosition &start, const Core::GeoPosition &end) const
|
||||
{
|
||||
return hasIntersection(fromGeographic(start), fromGeographic(end));
|
||||
}
|
||||
|
||||
bool BuildingModel::hasIntersection(const QVector<LtsUtils::QPoint3D> &trajectory) const
|
||||
{
|
||||
for (int i = 1; i < trajectory.size(); ++i)
|
||||
if (hasIntersection(trajectory[i - 1], trajectory[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BuildingModel::hasIntersection(const std::vector<Core::GeoPosition> &trajectory) const
|
||||
{
|
||||
for (unsigned int i = 1; i < trajectory.size(); ++i)
|
||||
if (hasIntersection(trajectory[i - 1], trajectory[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Core::GeoPosition BuildingModel::intersection(const LtsUtils::QPoint3D &start, const LtsUtils::QPoint3D &end) const
|
||||
{
|
||||
const LtsUtils::QPoint3D point = BuildingControlUnit::VWM::Math::intersection(start, end, rooms());
|
||||
return !isValid(point) ? invalidGeoPosition() : toGeographic(point);
|
||||
}
|
||||
|
||||
Core::GeoPosition BuildingModel::intersection(const Core::GeoPosition &start, const Core::GeoPosition &end) const
|
||||
{
|
||||
return intersection(fromGeographic(start), fromGeographic(end));
|
||||
}
|
||||
|
||||
Core::GeoPosition BuildingModel::intersection(const QVector<LtsUtils::QPoint3D> &trajectory) const
|
||||
{
|
||||
for (int i = 1; i < trajectory.size(); ++i)
|
||||
{
|
||||
Core::GeoPosition pos = intersection(trajectory[i - 1], trajectory[i]);
|
||||
if (!isValid(pos))
|
||||
continue;
|
||||
return pos;
|
||||
} // for
|
||||
return {};
|
||||
}
|
||||
|
||||
Core::GeoPosition BuildingModel::intersection(const std::vector<Core::GeoPosition> &trajectory) const
|
||||
{
|
||||
for (unsigned int i = 1; i < trajectory.size(); ++i)
|
||||
{
|
||||
Core::GeoPosition pos = intersection(fromGeographic(trajectory[i - 1]), fromGeographic(trajectory[i]));
|
||||
if (!isValid(pos))
|
||||
continue;
|
||||
return pos;
|
||||
} // for
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************************
|
||||
* Coordinate transformations *
|
||||
*************************************************************************************************/
|
||||
|
||||
LtsUtils::QPoint3D BuildingModel::fromGeographic(const Core::GeoPosition &point) const
|
||||
{
|
||||
// qCritical() << " point.z = " << point.z();
|
||||
// qCritical() << " m_refPos = " << m_refPos.x() << " - " << m_refPos.y() << " - " << m_refPos.z();
|
||||
const LtsCoordTrans::UtmCoordinate utm = LtsCoordTrans::UtmCoordinate::fromGeographic(point.lon(), point.lat());
|
||||
// qCritical() << " utm = " << utm.mgrs(7);
|
||||
return toReference({utm.x, utm.y, point.z()});
|
||||
}
|
||||
|
||||
QVector<LtsUtils::QPoint3D> BuildingModel::fromGeographic(const std::vector<Core::GeoPosition> &points) const
|
||||
{
|
||||
QVector<LtsUtils::QPoint3D> ret;
|
||||
ret.reserve(points.size());
|
||||
for (const Core::GeoPosition &point : qAsConst(points))
|
||||
ret.append(fromGeographic(point));
|
||||
return ret;
|
||||
}
|
||||
|
||||
Core::GeoPosition BuildingModel::toGeographic(const LtsUtils::QPoint3D &point) const
|
||||
{
|
||||
const QPointF geoPos2D = m_refPosUtm.geographic(point.rotated(m_angle, LtsUtils::QPoint3D::Axis::Z).toPointF());
|
||||
return Core::GeoPosition(geoPos2D.x(), geoPos2D.y(), point.z() + m_refPos.z());
|
||||
}
|
||||
|
||||
std::vector<Core::GeoPosition> BuildingModel::toGeographic(const QVector<LtsUtils::QPoint3D> &points) const
|
||||
{
|
||||
std::vector<Core::GeoPosition> ret;
|
||||
ret.reserve(points.size());
|
||||
for (const LtsUtils::QPoint3D &point : qAsConst(points))
|
||||
ret.push_back(toGeographic(point));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
LtsUtils::QPoint3D BuildingModel::fromReference(const LtsUtils::QPoint3D &point) const
|
||||
{
|
||||
return point.rotated(m_angle, LtsUtils::QPoint3D::Axis::Z) + m_refPos;
|
||||
}
|
||||
|
||||
QVector<LtsUtils::QPoint3D> BuildingModel::fromReference(const QVector<LtsUtils::QPoint3D> &points) const
|
||||
{
|
||||
QVector<LtsUtils::QPoint3D> ret;
|
||||
ret.reserve(points.size());
|
||||
for (const LtsUtils::QPoint3D &point : qAsConst(points))
|
||||
ret.append(fromReference(point));
|
||||
return ret;
|
||||
}
|
||||
|
||||
LtsUtils::QPoint3D BuildingModel::toReference(const LtsUtils::QPoint3D &point) const
|
||||
{
|
||||
return (point - m_refPos).rotated(-m_angle, LtsUtils::QPoint3D::Axis::Z);
|
||||
}
|
||||
|
||||
QVector<LtsUtils::QPoint3D> BuildingModel::toReference(const QVector<LtsUtils::QPoint3D> &points) const
|
||||
{
|
||||
QVector<LtsUtils::QPoint3D> ret;
|
||||
ret.reserve(points.size());
|
||||
for (const LtsUtils::QPoint3D &point : qAsConst(points))
|
||||
ret.append(toReference(point));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************************
|
||||
* Overloaded operators *
|
||||
*************************************************************************************************/
|
||||
|
||||
bool BuildingModel::operator ==(const BuildingModel &other) const
|
||||
{
|
||||
return m_buildingId == other.m_buildingId;
|
||||
}
|
||||
|
||||
bool BuildingModel::operator !=(const BuildingModel &other) const
|
||||
{
|
||||
return m_buildingId != other.m_buildingId;
|
||||
}
|
||||
|
||||
} // namespace CesBuildings
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Building Model
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, ESZS, 2016-04-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <CentralEffectSimulation/logger.h>
|
||||
|
||||
#include <Buildings/BuildingControlUnit/VWM/vwm_building.h>
|
||||
#include <InfrastructureManagement/ism.hpp>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QPolygonF>
|
||||
|
||||
using namespace CentralEffectSimulation;
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BuildingModel
|
||||
//
|
||||
class BuildingModel
|
||||
: public QObject
|
||||
, public BuildingControlUnit::VWM::Building
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static bool isValid(const LtsUtils::QPoint3D &point);
|
||||
static bool isValid(const Core::GeoPosition &point);
|
||||
static LtsUtils::QPoint3D invalidPosition();
|
||||
static Core::GeoPosition invalidGeoPosition();
|
||||
|
||||
explicit BuildingModel(QObject *parent = nullptr);
|
||||
~BuildingModel();
|
||||
|
||||
bool init(const InfrastructureManagement::MainFootprint &mfp, const InfrastructureManagement::MainStructureElement &mse,
|
||||
const QByteArray &vmd,
|
||||
const int buildingId);
|
||||
|
||||
bool hasIntersectionSimplified(const LtsUtils::QPoint3D &start, const LtsUtils::QPoint3D &end) const;
|
||||
bool hasIntersectionSimplified(const Core::GeoPosition &start, const Core::GeoPosition &end) const;
|
||||
bool hasIntersectionSimplified(const QVector<LtsUtils::QPoint3D> &trajectory) const;
|
||||
bool hasIntersectionSimplified(const std::vector<Core::GeoPosition> &trajectory) const;
|
||||
|
||||
bool hasIntersection(const LtsUtils::QPoint3D &start, const LtsUtils::QPoint3D &end) const;
|
||||
bool hasIntersection(const Core::GeoPosition &start, const Core::GeoPosition &end) const;
|
||||
bool hasIntersection(const QVector<LtsUtils::QPoint3D> &trajectory) const;
|
||||
bool hasIntersection(const std::vector<Core::GeoPosition> &trajectory) const;
|
||||
|
||||
Core::GeoPosition intersection(const LtsUtils::QPoint3D &start, const LtsUtils::QPoint3D &end) const;
|
||||
Core::GeoPosition intersection(const Core::GeoPosition &start, const Core::GeoPosition &end) const;
|
||||
Core::GeoPosition intersection(const QVector<LtsUtils::QPoint3D> &trajectory) const;
|
||||
Core::GeoPosition intersection(const std::vector<Core::GeoPosition> &trajectory) const;
|
||||
|
||||
LtsUtils::QPoint3D fromGeographic(const Core::GeoPosition &point) const;
|
||||
QVector<LtsUtils::QPoint3D> fromGeographic(const std::vector<Core::GeoPosition> &points) const;
|
||||
Core::GeoPosition toGeographic(const LtsUtils::QPoint3D &point) const;
|
||||
std::vector<Core::GeoPosition> toGeographic(const QVector<LtsUtils::QPoint3D> &points) const;
|
||||
|
||||
LtsUtils::QPoint3D fromReference(const LtsUtils::QPoint3D &point) const;
|
||||
QVector<LtsUtils::QPoint3D> fromReference(const QVector<LtsUtils::QPoint3D> &points) const;
|
||||
LtsUtils::QPoint3D toReference(const LtsUtils::QPoint3D &point) const;
|
||||
QVector<LtsUtils::QPoint3D> toReference(const QVector<LtsUtils::QPoint3D> &points) const;
|
||||
|
||||
const int &buildingId() const { return m_buildingId; }
|
||||
const double &height() const { return m_height; }
|
||||
const double &angle() const { return m_angle; }
|
||||
const Core::GeoPosition &refPosGeo() const { return m_refPosGeo; }
|
||||
const LtsCoordTrans::UtmCoordinate &refPosUtm() const { return m_refPosUtm; }
|
||||
const LtsUtils::QPoint3D &refPos() const { return m_refPos; }
|
||||
const QPolygonF &footprint() const { return m_footprint; }
|
||||
const QRectF &boundingRect() const { return m_boundingRect; }
|
||||
|
||||
bool operator ==(const BuildingModel &other) const;
|
||||
bool operator !=(const BuildingModel &other) const;
|
||||
|
||||
private:
|
||||
int m_buildingId{0};
|
||||
double m_height{0.};
|
||||
double m_angle{0.};
|
||||
Core::GeoPosition m_refPosGeo;
|
||||
LtsCoordTrans::UtmCoordinate m_refPosUtm;
|
||||
LtsUtils::QPoint3D m_refPos; // UTM
|
||||
QPolygonF m_footprint;
|
||||
QRectF m_boundingRect;
|
||||
|
||||
LOGGER_T &m_logger;
|
||||
|
||||
}; // class BuildingModel
|
||||
|
||||
} // namespace CesBuildings
|
||||
+997
@@ -0,0 +1,997 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#include "handler_aes_data.h"
|
||||
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
|
||||
#include <QPainterPath>
|
||||
#include <QPointF>
|
||||
#include <QPolygonF>
|
||||
#include <QTimer>
|
||||
#include <QTransform>
|
||||
|
||||
#include <LtsUtilsCore/dds_bitarray.h>
|
||||
#include <LtsUtilsCore/qpoint3d.h>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
#define TIMEDIFFVALID 3000
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
HandlerAesData::HandlerAesData(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &buildingDataHandler,
|
||||
QObject *parent)
|
||||
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_handlerBuildingData(buildingDataHandler)
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.Buildings.HandlerAesData"))
|
||||
{
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HandlerAesData::~HandlerAesData()
|
||||
{
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HandlerAesData::init()
|
||||
{
|
||||
auto dtcAes = m_ddsHandler->dtcAes();
|
||||
|
||||
dtcAes->enableChargeEffect();
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::chargeEffectChanged,
|
||||
this, &HandlerAesData::onChargeEffectChanged);
|
||||
|
||||
dtcAes->enableExplosionSingle();
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::explosionSingleChanged,
|
||||
this, &HandlerAesData::onExplosionSingleChanged);
|
||||
|
||||
dtcAes->enableAirSupportImpact();
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::airSupportImpactChanged,
|
||||
this, &HandlerAesData::onAirSupportImpactChanged);
|
||||
|
||||
dtcAes->enableTriggeredImpacts();
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::triggeredImpactsChanged,
|
||||
this, &HandlerAesData::onTriggeredImpactsChanged);
|
||||
|
||||
dtcAes->waitForHistoricalDataAesItemView(1000);
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
|
||||
this, &HandlerAesData::onAesItemViewChanged);
|
||||
|
||||
dtcAes->enableEffects();
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::effectsChanged,
|
||||
this, &HandlerAesData::onEffectsChanged, Qt::UniqueConnection);
|
||||
|
||||
dtcAes->enableBoobyTrap();
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::boobyTrapChanged,
|
||||
this, &HandlerAesData::onBoobyTrapChanged, Qt::UniqueConnection);
|
||||
|
||||
// Get 'static' data for all AesItemView
|
||||
{
|
||||
auto cb = [this](const AreaEffectSimulation::AesItemView & aiv)
|
||||
{
|
||||
onAesItemViewChanged(aiv, DataModification::eAdded);
|
||||
};
|
||||
if (!dtcAes->aesItemViews(cb))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} // end of init()
|
||||
|
||||
|
||||
void HandlerAesData::onBoobyTrapChanged(const AreaEffectSimulation::BoobyTrap &data, DataModification modType)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onBoobyTrapChanged"
|
||||
<< " id=" << data.id()
|
||||
<< " impactPosition=" << data.impactPosition()
|
||||
<< " impactRadius=" << data.impactRadius()
|
||||
<< " effectStateId=" << data.effectStateId();
|
||||
|
||||
if (data.isDeleted()
|
||||
|| data.effectStateId() == AreaEffectSimulation::AesEffectState::EsRemoved
|
||||
|| modType == DataModification::eRemoved)
|
||||
return;
|
||||
|
||||
if (!data.triggered())
|
||||
return;
|
||||
|
||||
INFO_LOG(m_logger) << "HandlerParticipantBoobyTrap::onBoobyTrapChanged"
|
||||
<< " data.id=" << data.id()
|
||||
<< " effectStateId=" << data.effectStateId();
|
||||
|
||||
if (!data.effectStart().is_set())
|
||||
return;
|
||||
|
||||
if ((m_ddsHandler->currentPartitionTime() - (data.effectStart().get() + data.effectDuration())) > 2000)
|
||||
{
|
||||
INFO_LOG(m_logger) << "onBoobyTrap outdated";
|
||||
return;
|
||||
}
|
||||
AreaEffectSimulation::AesItemView itemView;
|
||||
AreaEffectSimulation::AesType aesType = AreaEffectSimulation::AesType_def::AtBoobyTrap;
|
||||
m_ddsHandler->dtcAes()->aesItemViewFromEntityId(data.id(), aesType, itemView);
|
||||
|
||||
checkBuildingsHit(itemView);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ///////////////////////////////////
|
||||
// A E S (AreaEffectSimulation)
|
||||
// ///////////////////////////////////
|
||||
|
||||
void HandlerAesData::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onAesItemViewChanged"
|
||||
<< " data.aesTypeId()=" << data.aesTypeId();
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got AesItemView: " << data.effectStateId();
|
||||
if (data.effectStateId() == AreaEffectSimulation::AesEffectState::EsExpired)
|
||||
{
|
||||
INFO_LOG(m_logger) << "AesEffectState_def::EsExpired"
|
||||
<< " currentPartitionTime=" << m_ddsHandler->currentPartitionTime()
|
||||
<< " effectStart=" << data.effectStart()
|
||||
<< " diff = " << m_ddsHandler->currentPartitionTime() - data.effectStart() ;
|
||||
if (m_ddsHandler->currentPartitionTime() == 0)
|
||||
return;
|
||||
|
||||
if ((data.aesTypeId() == AreaEffectSimulation::AesType_def::AtOffRouteMineSecondary)
|
||||
|| (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtBoobyTrapSecondary))
|
||||
{
|
||||
|
||||
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtOffRouteMineSecondary)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "AtOffRouteMineSecondary id=" << data.id() / 1000;
|
||||
auto offRouteMine = m_ddsHandler->dtcAes()->offRouteMine((int)(data.id() / 1000));
|
||||
if (!offRouteMine.effectStart().is_set())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "!offRouteMine.effectStart().is_set()";
|
||||
return;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << " currentPartitionTime=" << m_ddsHandler->currentPartitionTime()
|
||||
<< " effectStart=" << offRouteMine.effectStart()
|
||||
<< " effectDuration=" << offRouteMine.effectDuration()
|
||||
<< " diff = " << m_ddsHandler->currentPartitionTime() - (offRouteMine.effectStart().get() + offRouteMine.effectDuration()) ;
|
||||
|
||||
if ((m_ddsHandler->currentPartitionTime() - (offRouteMine.effectStart().get() + offRouteMine.effectDuration())) < 2000)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "AtBoobyTrapSecondary Mine wird ausgeloeset.";
|
||||
checkBuildingsHit(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "outdated return";
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtBoobyTrapSecondary)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "AtBoobyTrapSecondary id=" << data.id() / 1000;
|
||||
//auto offRouteMine = m_ddsHandler->dtcAes()->offRouteMine((int) (data.id() / 1000));
|
||||
auto boobyTrap = m_ddsHandler->dtcAes()->boobyTrap((int)(data.id() / 1000));
|
||||
if (!boobyTrap.effectStart().is_set())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "!offRouteMine.effectStart().is_set()";
|
||||
return;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << " currentPartitionTime=" << m_ddsHandler->currentPartitionTime()
|
||||
<< " effectStart=" << boobyTrap.effectStart()
|
||||
<< " effectDuration=" << boobyTrap.effectDuration()
|
||||
<< " diff = " << m_ddsHandler->currentPartitionTime() - (boobyTrap.effectStart().get() + boobyTrap.effectDuration()) ;
|
||||
|
||||
if ((m_ddsHandler->currentPartitionTime() - (boobyTrap.effectStart().get() + boobyTrap.effectDuration())) < 2000)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "AtBoobyTrapSecondary Mine wird ausgeloeset.";
|
||||
checkBuildingsHit(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "outdated return";
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "removeStates data";
|
||||
removeStates(data);
|
||||
DEBUG_LOG(m_logger) << "m_aesItemViewsUtm remove id" << data.aesItemId();
|
||||
m_aesItemViewsUtm.remove(data.aesItemId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandlerAesData::removeStates(const AreaEffectSimulation::AesItemView &data)
|
||||
{
|
||||
if (data.aesTypeId() != AreaEffectSimulation::AesType_def::AtExplosionArea)
|
||||
return;
|
||||
DEBUG_LOG(m_logger) << "Remove aesItemId=" << data.aesItemId();
|
||||
// remove State for each building
|
||||
for (CentralEffectSimulation::BitfieldStates &bfs : m_bitfieldStatesBld)
|
||||
bfs.remove(data.aesItemId());
|
||||
} // end removeStates
|
||||
|
||||
void HandlerAesData::calculateBuildingExplosion(const AreaEffectSimulation::ChargeStruct &chargeStruct,
|
||||
const Core::GeoPosition2D& impactPosition,
|
||||
const int id)
|
||||
{
|
||||
const double impactRadius = m_ddsHandler->chargeTypeRadius(chargeStruct);
|
||||
DEBUG_LOG(m_logger) << "Handle ExplosionSingle (EsActivated)"
|
||||
<< ", m_handlerBuildingData.getFootprints().size =" << m_handlerBuildingData->getFootprints().size();
|
||||
|
||||
QHash<int, CentralEffectSimulation::HandlerBuildingData::Footprint> footprints = m_handlerBuildingData->getFootprints();
|
||||
|
||||
// Bounding-Box-Check
|
||||
// QMap<int, Footprint> m_handlerBuildingData.getFootprints();
|
||||
for (const CentralEffectSimulation::HandlerBuildingData::Footprint &footprint : qAsConst(footprints))
|
||||
{
|
||||
|
||||
const Core::GeoPosition2D impactPosition2D(impactPosition.lon(), impactPosition.lat());
|
||||
if (inFootprint(impactPosition, footprint, impactRadius))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "ftc sendCESHitOnBuilding mseId = " << footprint.mseId
|
||||
<< " chargeTypeId = " << chargeStruct.chargeTypeId()
|
||||
<< " id = " << id
|
||||
<< " currentPartitionTime = " << m_ddsHandler->currentPartitionTime()
|
||||
<< " impactPosition2D.lon = " << impactPosition2D.lon()
|
||||
<< " impactPosition2D.lat = " << impactPosition2D.lat();
|
||||
|
||||
Buildings::SendCesHitOnBuildingRequest requestBld(
|
||||
footprint.mseId,
|
||||
chargeStruct.chargeTypeId(),
|
||||
m_ddsHandler->dtcPdm()->getBuildingChargeEffectByChargeTypeId(chargeStruct.chargeTypeId()).destructiveFactor(),
|
||||
m_ddsHandler->dtcPdm()->getBuildingChargeEffectByChargeTypeId(chargeStruct.chargeTypeId()).penetrationFactor(),
|
||||
id,
|
||||
m_ddsHandler->currentPartitionTime(),
|
||||
Core::GeoPosition(impactPosition2D.lon(), impactPosition2D.lat(), 0.0),
|
||||
QStringLiteral("properties").toStdString());
|
||||
m_ddsHandler->ftcBld()->sendCesHitOnBuildingRequest(requestBld, this);
|
||||
}
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "Not sendCESHitOnBuilding mseId = " << footprint.mseId;
|
||||
|
||||
DEBUG_LOG(m_logger) << "boundingBoxImpact.contains(footprint)";
|
||||
|
||||
} // for
|
||||
|
||||
}
|
||||
|
||||
void HandlerAesData::startTimer(int id, int msec) {
|
||||
auto *timer = new QTimer(this);
|
||||
|
||||
timer->setProperty("chargeEffectId", id);
|
||||
// Timeout-Slot mit echtem SLOT
|
||||
connect(timer, &QTimer::timeout, this, &HandlerAesData::onStartTimeReached);
|
||||
timer->start(msec);
|
||||
DEBUG_LOG(m_logger) << "Timer " << id << " gestartet fuer " << msec << " ms.";
|
||||
}
|
||||
|
||||
void HandlerAesData::onStartTimeReached()
|
||||
{
|
||||
if (!sender())
|
||||
return;
|
||||
|
||||
bool bOk;
|
||||
int chargeEffectId = sender()->property("chargeEffectId").toInt(&bOk);
|
||||
if (!bOk)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Timer " << chargeEffectId << " ausgeloest!";
|
||||
|
||||
// Timer stoppen und loeschen
|
||||
AreaEffectSimulation::ChargeEffect data = m_chargeEffects.value(chargeEffectId);
|
||||
AreaEffectSimulation::ChargeStruct chargeStruct(data.chargeTypeId(),data.igniterTypeId(), data.igniterFunctionId());
|
||||
calculateBuildingExplosion(chargeStruct, data.position(), data.id());
|
||||
sender()->deleteLater();
|
||||
m_chargeEffects.remove(chargeEffectId);
|
||||
}
|
||||
|
||||
void HandlerAesData::onChargeEffectChanged(const AreaEffectSimulation::ChargeEffect &data, DataModification modType)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "HandlerExplosions::onChargeEffectChanged";
|
||||
if (modType == DataModification::eRemoved)
|
||||
return;
|
||||
const long long effectStart = data.effectStart();
|
||||
|
||||
DEBUG_LOG(m_logger) << "HandlerExplosions::onChargeEffectChanged"
|
||||
<< ", effectStart=" << effectStart
|
||||
<< ", currentPartitionTime=" << m_ddsHandler->currentPartitionTime();
|
||||
|
||||
|
||||
// Startzeit in der Vergangenheit: aktuelle Zeit - 3 Sekunden
|
||||
if ( effectStart < m_ddsHandler->currentPartitionTime() - TIMEDIFFVALID )
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Startzeit in der Vergangenheit: aktuelle Zeit - 3 Sekunden";
|
||||
return;
|
||||
}
|
||||
// Startzeit entspricht der aktuellen Zeit
|
||||
if ( effectStart > m_ddsHandler->currentPartitionTime() - TIMEDIFFVALID
|
||||
&& effectStart < m_ddsHandler->currentPartitionTime() + data.effectDuration() )
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Startzeit entspricht der aktuellen Zeit";
|
||||
AreaEffectSimulation::ChargeStruct chargeStruct;
|
||||
chargeStruct.chargeTypeId(data.chargeTypeId());
|
||||
chargeStruct.igniterTypeId(data.igniterTypeId());
|
||||
calculateBuildingExplosion(chargeStruct, data.position(), data.id());
|
||||
}
|
||||
// Startzeit in der Zukunft:
|
||||
else if (effectStart > m_ddsHandler->currentPartitionTime() + data.effectDuration())
|
||||
{
|
||||
// Start mit Timer
|
||||
DEBUG_LOG(m_logger) << "Startzeit in der Zukunft"
|
||||
<< ", id :" << data.id()
|
||||
<< ", duration=" << effectStart - m_ddsHandler->currentPartitionTime();
|
||||
m_chargeEffects.insert(data.id(), data);
|
||||
startTimer(data.id(), effectStart - m_ddsHandler->currentPartitionTime());
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "END onChargeEffectChanged";
|
||||
|
||||
}
|
||||
|
||||
void HandlerAesData::onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType)
|
||||
{
|
||||
bool handleExplosion = false;
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
{
|
||||
m_explosionSingleState.remove(data.id());
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsRemoved)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Remove SingleExplosion";
|
||||
m_explosionSingleState.remove(data.id());
|
||||
return;
|
||||
}
|
||||
// Only handle transitions from prepared or fired to activated
|
||||
if ((m_explosionSingleState.value(data.id()) == AreaEffectSimulation::AesEffectState_def::EsPrepared ||
|
||||
m_explosionSingleState.value(data.id()) == AreaEffectSimulation::AesEffectState_def::EsFired) &&
|
||||
data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsActivated)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Handle SingleExplosion";
|
||||
handleExplosion = true;
|
||||
}
|
||||
m_explosionSingleState.insert(data.id(), data.effectStateId());
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got ExplosionSingle";
|
||||
if (handleExplosion)
|
||||
{
|
||||
calculateBuildingExplosion(data.chargeStruct(), data.impactPosition(), data.id());
|
||||
}
|
||||
} // onExplosionSingleChanged
|
||||
|
||||
void HandlerAesData::onAirSupportImpactChanged(const AreaEffectSimulation::AirSupportImpact &data, DataModification modType)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Got onAirSupportImpactChanged()";
|
||||
AreaEffectSimulation::ExplosionSingle esData;
|
||||
esData.id(data.id());
|
||||
esData.chargeStruct().chargeTypeId(data.chargeStruct().chargeTypeId());
|
||||
esData.impactPosition(data.impactPosition());
|
||||
esData.effectStateId(data.effectStateId());
|
||||
onExplosionSingleChanged(esData, modType);
|
||||
}
|
||||
|
||||
void HandlerAesData::onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType)
|
||||
{
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got TriggeredImpacts";
|
||||
preCalculateImpacts(data);
|
||||
}
|
||||
|
||||
void HandlerAesData::onEffectsChanged(const AreaEffectSimulation::Effects &effects, DataModification modType)
|
||||
{
|
||||
TRACE_LOG(m_logger) << " Got Effects " << effects;
|
||||
if (modType == DataModification::eRemoved)
|
||||
return;
|
||||
|
||||
if (effects.aesTypeId().underlying() != AreaEffectSimulation::AesType_def::AtExplosionClusterSingleExplosions)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << " Got typechecked effects " << effects;
|
||||
|
||||
// calculate for every building of our exercise:
|
||||
const QHash<int, CentralEffectSimulation::HandlerBuildingData::Footprint> &footprints = m_handlerBuildingData->getFootprints();
|
||||
for (const CentralEffectSimulation::HandlerBuildingData::Footprint &footprint : qAsConst(footprints))
|
||||
{
|
||||
calculateImpacts(effects, footprint);
|
||||
}
|
||||
}
|
||||
|
||||
// ///////////////////////////////////
|
||||
// I S M (InfrastructureManagement)
|
||||
// ///////////////////////////////////
|
||||
|
||||
|
||||
// ///////////////////////////////////
|
||||
// Calculations:
|
||||
// ///////////////////////////////////
|
||||
|
||||
bool HandlerAesData::inBoundingBox(const Core::GeoPosition2D& impactPosition,
|
||||
const CentralEffectSimulation::HandlerBuildingData::Footprint &footprint,
|
||||
const double impactRadius) const
|
||||
{
|
||||
const QPointF impactPos(CentralEffectSimulation::geographic2Utm(impactPosition, footprint.zone));
|
||||
const QPolygonF polyBldgRadius({QPointF(footprint.boundingBoxPolyUtm.bottomLeft().rx() - impactRadius,
|
||||
footprint.boundingBoxPolyUtm.bottomLeft().ry() + impactRadius),
|
||||
QPointF(footprint.boundingBoxPolyUtm.topRight().rx() + impactRadius,
|
||||
footprint.boundingBoxPolyUtm.bottomLeft().ry() + impactRadius),
|
||||
QPointF(footprint.boundingBoxPolyUtm.topRight().rx() + impactRadius,
|
||||
footprint.boundingBoxPolyUtm.topRight().ry() - impactRadius),
|
||||
QPointF(footprint.boundingBoxPolyUtm.bottomLeft().rx() - impactRadius,
|
||||
footprint.boundingBoxPolyUtm.topRight().ry() - impactRadius)});
|
||||
|
||||
return (polyBldgRadius.containsPoint(impactPos, Qt::OddEvenFill));
|
||||
}
|
||||
|
||||
bool HandlerAesData::inFootprint(const Core::GeoPosition2D &geoPosition,
|
||||
const CentralEffectSimulation::HandlerBuildingData::Footprint &footPrint,
|
||||
const double radius) const
|
||||
{
|
||||
if ( !inBoundingBox( geoPosition, footPrint, radius))
|
||||
return false;
|
||||
const QPointF impact(CentralEffectSimulation::geographic2Utm(geoPosition, footPrint.zone));
|
||||
|
||||
// NT: Folgendes raubt zu viele Zeilen beim tail. Daher nehme ich es raus.
|
||||
// if (m_logger.isDebugEnabled())
|
||||
// {
|
||||
// const QPointF utmBuilding(CentralEffectSimulation::geographic2Utm(footPrint.geoPosition, footPrint.zone));
|
||||
// DEBUG_LOG(m_logger) << "Impact (x/y)=" << CentralEffectSimulation::debug(impact - utmBuilding);
|
||||
// for (int i = 0; i < footPrint.polyUtm.length(); i++)
|
||||
// DEBUG_LOG(m_logger) << " poly (x/y)=" << CentralEffectSimulation::debug(footPrint.polyUtm[i] - utmBuilding);
|
||||
// }
|
||||
|
||||
// Check, if hit direct on building
|
||||
if (footPrint.polyUtm.containsPoint(impact, Qt::OddEvenFill))
|
||||
return true;
|
||||
|
||||
// Check, if hit in munition-radius
|
||||
QPainterPath ppFp;
|
||||
ppFp.addPolygon(footPrint.polyUtm);
|
||||
QPainterPath ppCircle;
|
||||
ppCircle.addEllipse(impact, radius, radius);
|
||||
return ppFp.intersects(ppCircle);
|
||||
}
|
||||
|
||||
void HandlerAesData::preCalculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data)
|
||||
{
|
||||
if (data.id() <= 0)
|
||||
return;
|
||||
DEBUG_LOG(m_logger) << "preCalculateImpacts";
|
||||
// Find AES ItemView and set Bounding-Box of Aes-Field
|
||||
|
||||
const int aesItemId = data.aesItemId();
|
||||
|
||||
// Search corresponding itemView. If not available no impact to participant.
|
||||
// Use dtcAes since sender (AES) publishes TriggeredImpacts and AesItemView
|
||||
//
|
||||
AreaEffectSimulation::AesItemView aesItemView;
|
||||
std::shared_ptr<AreaEffectSimulation::Interface::Dtc> dtcAes = m_ddsHandler->dtcAes();
|
||||
if (!dtcAes->aesItemViewFromEntityId(aesItemId, data.aesTypeId(), aesItemView))
|
||||
{
|
||||
static long msgCnt = 0;
|
||||
WARNING_LOG(m_logger) << "TriggeredExplosions.aesItemId=" << data.aesItemId() << " No aesItemView available"
|
||||
<< " (cnt=" << ++msgCnt << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
// Maybe ExlosionClusters Trajectory is hitting a building?
|
||||
// Vulnerability should be calculated
|
||||
|
||||
const QHash<int, CentralEffectSimulation::HandlerBuildingData::Footprint> &footprints = m_handlerBuildingData->getFootprints();
|
||||
for (const CentralEffectSimulation::HandlerBuildingData::Footprint &footprint : qAsConst(footprints))
|
||||
{
|
||||
calculateImpacts(data, aesItemView, footprint);
|
||||
} // for
|
||||
|
||||
}
|
||||
|
||||
void HandlerAesData::onSendCesHitOnBuildingReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
if (replyObject.error())
|
||||
WARNING_LOG(m_logger) << "Can not send hit on building to building service: " << replyObject()
|
||||
<< ", m_handlerBuildingData.getFootprints().size()" << m_handlerBuildingData->getFootprints().size();
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "onSendCesHitOnBuildingReply for id " << replyObject.id() << " success\n"
|
||||
<< " replyObject.str() = " << replyObject.str();
|
||||
}
|
||||
|
||||
void HandlerAesData::onSendCesHit3DonBuildingReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "m_handlerBuildingData.getFootprints() size " << m_handlerBuildingData->getFootprints().size();
|
||||
|
||||
if (replyObject.error())
|
||||
WARNING_LOG(m_logger) << "Can not send hit3D on building to building service: " << replyObject()
|
||||
<< ", m_handlerBuildingData.getFootprints().size()" << m_handlerBuildingData->getFootprints().size();
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "onSendCesHit3DonBuildingReply for id " << replyObject.id() << " success\n"
|
||||
<< " replyObject.str() = " << replyObject.str();
|
||||
}
|
||||
|
||||
void HandlerAesData::onSendCesHitInformationReply(const Core::FunctionReplyObject &reply)
|
||||
{
|
||||
if (reply.error())
|
||||
WARNING_LOG(m_logger) << "onSendCesHitInformationReply for id " << reply.id() << " failed: " << reply.str();
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "onSendCesHitInformationReply for id " << reply.id() << " successful";
|
||||
}
|
||||
|
||||
void HandlerAesData::onSetBuildingStatesReply(const Core::FunctionReplyObject &reply)
|
||||
{
|
||||
if (reply.error())
|
||||
WARNING_LOG(m_logger) << "onSetBuildingStatesReply for id " << reply.id() << " failed: " << reply.str();
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "onSetBuildingStatesReply for id " << reply.id() << " successful";
|
||||
}
|
||||
|
||||
// calculate impacts for one building
|
||||
void HandlerAesData::calculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data, const AreaEffectSimulation::AesItemView &aesItemView,
|
||||
const CentralEffectSimulation::HandlerBuildingData::Footprint &footprint)
|
||||
{
|
||||
const int aesItemId = data.aesItemId();
|
||||
bool bIsExplosionCluster = false;
|
||||
ProjectDataManagement::IgniterFunctionBase ignFuncBase = ProjectDataManagement::IgniterFunctionBase::IfbImpact;
|
||||
|
||||
// check for correct AES type artillery only
|
||||
|
||||
static QVector<AreaEffectSimulation::AesType_def::type> s_relevantTypes =
|
||||
{
|
||||
AreaEffectSimulation::AesType_def::AtExplosionArea,
|
||||
AreaEffectSimulation::AesType_def::AtExplosionSingle,
|
||||
AreaEffectSimulation::AesType_def::AtExplosionAreaSingleExplosions,
|
||||
};
|
||||
|
||||
if (data.aesTypeId().underlying() == AreaEffectSimulation::AesType_def::AtExplosionClusterSingleExplosions)
|
||||
{
|
||||
bIsExplosionCluster = true;
|
||||
ignFuncBase = igniterFunctionBaseExplosionCluster(aesItemId); // assume that fuseType does not differ within a single ExplosionArea
|
||||
DEBUG_LOG(m_logger) << "Calculate, bIsExplosionCluster = " << bIsExplosionCluster
|
||||
<< ", ignFuncBase = " << ignFuncBase;
|
||||
}
|
||||
else if (s_relevantTypes.contains(data.aesTypeId().underlying()))
|
||||
DEBUG_LOG(m_logger) << "Calculate";
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "No Calculation";
|
||||
return;
|
||||
}
|
||||
|
||||
if (aesItemId != aesItemView.aesItemId())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "mismatch: "
|
||||
<< ", TriggeredExplosions.aesItemId=" << data.aesItemId()
|
||||
<< ", AesItemView.aesItemId=" << aesItemView.aesItemId();
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "calculateImpacts mseId=" << footprint.mseId << " aesItemId " << aesItemId
|
||||
<< ", bIsExplosionCluster = " << bIsExplosionCluster;
|
||||
|
||||
// get position(s) of impact(s):
|
||||
|
||||
CentralEffectSimulation::BitfieldStates &bitfieldStates = m_bitfieldStatesBld[footprint.mseId];
|
||||
QSet<int> &bitfieldState = bitfieldStates[aesItemId];
|
||||
for (int i : qAsConst(bitfieldState))
|
||||
DEBUG_LOG(m_logger) << "bitfieldState for " << aesItemId << ": " << i;
|
||||
|
||||
for (int32_t bitFieldIdx = 0; bitFieldIdx < data.impactCount(); ++bitFieldIdx)
|
||||
{
|
||||
// no break, because every bit can be a hit
|
||||
if (LtsUtils::BitArray::testBit(data.bitfield(), bitFieldIdx))
|
||||
continue;
|
||||
|
||||
// get position of impact to corresponding bit
|
||||
if (aesItemView.form().size() <= size_t(bitFieldIdx))
|
||||
continue;
|
||||
|
||||
const Core::GeoPosition &impactPosition = aesItemView.form()[bitFieldIdx];
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION
|
||||
<< " impactPosition: lat/lon" << impactPosition.lat() << "/" << impactPosition.lon() << " z=" << impactPosition.z()
|
||||
<< " UTM=" << CentralEffectSimulation::debug(CentralEffectSimulation::geographic2Utm(impactPosition));
|
||||
|
||||
// check, if impact-pos + munition-radius touch the building
|
||||
// get radius of munition
|
||||
const double impactRadius = m_ddsHandler->chargeTypeRadius(aesItemView.chargeStruct());
|
||||
if (inFootprint(impactPosition, footprint, impactRadius))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "In Footprint of mseId = " << footprint.mseId;
|
||||
if (!bitfieldState.contains(bitFieldIdx))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "m_bitfieldStates.insert(aesItemId=" << aesItemId << ", bitfieldState)" << " bitFieldIdx=" << bitFieldIdx;
|
||||
bitfieldState.insert(bitFieldIdx);
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendCesHit mseId = " << footprint.mseId
|
||||
<< ", aesItemId=" << aesItemId
|
||||
<< ", bitFieldIdx= " << bitFieldIdx
|
||||
<< ", ignFuncBase = " << ignFuncBase;
|
||||
|
||||
if (! qFuzzyIsNull(impactPosition.z()))
|
||||
{
|
||||
// since HandlerBuildingModel::handleDetonationLocationRequest has already
|
||||
// calculated to fuseType, the impactPosition is the detonationLocation:
|
||||
Core::GeoPosition detonationLocation = impactPosition;
|
||||
//
|
||||
|
||||
double detonationDistance = 0;
|
||||
switch (ignFuncBase.underlying())
|
||||
{
|
||||
case ProjectDataManagement::IgniterFunctionBase::IfbProximity:
|
||||
detonationDistance = -5;
|
||||
break;
|
||||
case ProjectDataManagement::IgniterFunctionBase::IfbImpact:
|
||||
detonationDistance = 0;
|
||||
break;
|
||||
case ProjectDataManagement::IgniterFunctionBase::IfbDelay:
|
||||
detonationDistance = 5;
|
||||
break;
|
||||
default:
|
||||
// empty
|
||||
break;
|
||||
} // switch
|
||||
|
||||
Buildings::SendCesHit3DonBuildingRequest requestBld(
|
||||
footprint.mseId,
|
||||
aesItemView.chargeStruct().chargeTypeId(),
|
||||
m_ddsHandler->dtcPdm()->getBuildingChargeEffectByChargeTypeId(aesItemView.chargeStruct().chargeTypeId()).destructiveFactor(),
|
||||
m_ddsHandler->dtcPdm()->getBuildingChargeEffectByChargeTypeId(aesItemView.chargeStruct().chargeTypeId()).penetrationFactor(),
|
||||
aesItemId,
|
||||
m_ddsHandler->currentPartitionTime(),
|
||||
impactPosition,
|
||||
detonationLocation,
|
||||
detonationDistance,
|
||||
QStringLiteral("properties").toStdString());
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendCesHit3DonBuildingRequest for aesItemId=" << aesItemId
|
||||
<< " bitFieldIdx= " << bitFieldIdx
|
||||
<< ", requestBld= " << requestBld;
|
||||
|
||||
m_ddsHandler->ftcBld()->sendCesHit3DonBuildingRequest(requestBld, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// z-Value is 0 -> old / ! AtExplosionClusterSingleExplosions
|
||||
Buildings::SendCesHitOnBuildingRequest requestBld(
|
||||
footprint.mseId,
|
||||
aesItemView.chargeStruct().chargeTypeId(),
|
||||
m_ddsHandler->dtcPdm()->getBuildingChargeEffectByChargeTypeId(aesItemView.chargeStruct().chargeTypeId()).destructiveFactor(),
|
||||
m_ddsHandler->dtcPdm()->getBuildingChargeEffectByChargeTypeId(aesItemView.chargeStruct().chargeTypeId()).penetrationFactor(),
|
||||
aesItemId,
|
||||
m_ddsHandler->currentPartitionTime(),
|
||||
Core::GeoPosition(impactPosition.lon(), impactPosition.lat(), 0.0),
|
||||
QStringLiteral("properties").toStdString());
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendCesHitOnBuildingRequest for aesItemId=" << aesItemId
|
||||
<< " bitFieldIdx= " << bitFieldIdx
|
||||
<< ", impactPosition= " << impactPosition;
|
||||
|
||||
m_ddsHandler->ftcBld()->sendCesHitOnBuildingRequest(requestBld, this);
|
||||
} // if (impactPosition.z() > 0)
|
||||
|
||||
}
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "NOT in Footprint of mseId = " << footprint.mseId;
|
||||
// if (inFootprint(impactPosition
|
||||
} // foreach Impact
|
||||
} // for (int32_t bitFieldId
|
||||
}
|
||||
|
||||
void HandlerAesData::calculateImpacts(const AreaEffectSimulation::Effects &effects, const CentralEffectSimulation::HandlerBuildingData::Footprint &footprint)
|
||||
{
|
||||
if (effects.aesTypeId().underlying() != AreaEffectSimulation::AesType_def::AtExplosionClusterSingleExplosions)
|
||||
return;
|
||||
|
||||
const int aesItemId = effects.aesItemId();
|
||||
DEBUG_LOG(m_logger) << "calculateImpacts mseId=" << footprint.mseId << " data.aesItemId() " << aesItemId;
|
||||
|
||||
const AreaEffectSimulation::ExplosionCluster &ec = m_ddsHandler->dtcAes()->explosionCluster(effects.aesItemId());
|
||||
if (ec.id() != aesItemId)
|
||||
return;
|
||||
|
||||
const ProjectDataManagement::IgniterFunctionBase ignFuncBase = igniterFunctionBaseExplosionCluster(aesItemId);
|
||||
const double impactRadius = m_ddsHandler->chargeTypeRadius(ec.chargeStruct());
|
||||
|
||||
|
||||
CentralEffectSimulation::BitfieldStates &bitfieldStates = m_bitfieldStatesBld[footprint.mseId];
|
||||
QSet<int> &bitfieldState = bitfieldStates[aesItemId];
|
||||
|
||||
const std::vector<AreaEffectSimulation::SingleEffect> &singleEffectsRef = effects.singleEffects();
|
||||
int indexBitFieldIdx = -1;
|
||||
for (const AreaEffectSimulation::SingleEffect &singleEffect : qAsConst(singleEffectsRef))
|
||||
{
|
||||
++indexBitFieldIdx;
|
||||
|
||||
// just SesTriggered are relevant:
|
||||
if (singleEffect.singleEffectState() != AreaEffectSimulation::AesSingleEffectState_def::SesTriggered)
|
||||
continue;
|
||||
|
||||
// already processed?
|
||||
if (bitfieldState.contains(indexBitFieldIdx))
|
||||
continue;
|
||||
|
||||
// is building in range?
|
||||
const Core::GeoPosition &impactPositionGeo = singleEffect.position();
|
||||
if (!inFootprint(impactPositionGeo, footprint, impactRadius))
|
||||
continue;
|
||||
|
||||
|
||||
// Hier könnte man zunächst zwei-dimensional prüfen, ob ein anderes Bldg eine Verdeckung erzeugt zw.
|
||||
// a) Explosionsort (impactPosition) und
|
||||
// b) Grundriss (footprint) des Kandidaten
|
||||
// Diese Verdeckung würde die Wirkung auf den Kandidaten reduzieren.
|
||||
|
||||
// 2DpoylgonCentroid https://stackoverflow.com/questions/2792443/finding-the-centroid-of-a-polygon
|
||||
|
||||
const LtsCoordTrans::LtsCoordinate impactPos(impactPositionGeo);
|
||||
const QVector<int> &buildingIdsInBetween = findBuildingsBetween(impactPos, footprint);
|
||||
QString mseIdAsStr;
|
||||
for (auto mseId : buildingIdsInBetween)
|
||||
mseIdAsStr += QString(QStringLiteral("_coveredByMseId_%1;")).arg(mseId);
|
||||
DEBUG_LOG(m_logger) << "findBuildingsBetween returns mseIdAsStr =" << mseIdAsStr;
|
||||
|
||||
|
||||
const ProjectDataManagement::BuildingChargeEffect &bldgChargeEffect = m_ddsHandler->dtcPdm()->getBuildingChargeEffectByChargeTypeId(ec.chargeStruct().chargeTypeId());
|
||||
if (bldgChargeEffect.id() <= 0)
|
||||
ERROR_LOG(m_logger) << "getBuildingChargeEffectByChargeTypeId failed, chargeTypeId not found: =" << ec.chargeStruct().chargeTypeId();
|
||||
|
||||
|
||||
qint32 destructiveFactor = bldgChargeEffect.destructiveFactor();
|
||||
qint32 penetrationFactor = bldgChargeEffect.penetrationFactor();
|
||||
|
||||
if ((destructiveFactor <= 0) || (penetrationFactor <= 0))
|
||||
WARNING_LOG(m_logger) << "getBuildingChargeEffectByChargeTypeId failed, destructiveFactor or penetrationFactor invalid"
|
||||
<< ", destructiveFactor = " << destructiveFactor
|
||||
<< ", penetrationFactor = " << penetrationFactor;
|
||||
|
||||
|
||||
|
||||
if (!buildingIdsInBetween.empty())
|
||||
{
|
||||
destructiveFactor /= 2;
|
||||
penetrationFactor /= 2;
|
||||
}
|
||||
|
||||
QString properties = QStringLiteral("properties");
|
||||
properties += mseIdAsStr;
|
||||
|
||||
|
||||
const AreaEffectSimulation::AesZPlacement_def::type zPlacement = singleEffect.zPlacement().underlying();
|
||||
|
||||
if (zPlacement == AreaEffectSimulation::AesZPlacement_def::ZpDraped)
|
||||
{
|
||||
// z-Value is 0 -> old:
|
||||
Buildings::SendCesHitOnBuildingRequest requestBld(
|
||||
footprint.mseId,
|
||||
ec.chargeStruct().chargeTypeId(),
|
||||
destructiveFactor,
|
||||
penetrationFactor,
|
||||
aesItemId,
|
||||
m_ddsHandler->currentPartitionTime(),
|
||||
Core::GeoPosition(impactPositionGeo.lon(), impactPositionGeo.lat(), 0.0),
|
||||
properties.toStdString());
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendCesHitOnBuildingRequest for aesItemId=" << aesItemId
|
||||
<< " bitFieldIdx= " << indexBitFieldIdx
|
||||
<< ", impactPositionGeo= " << impactPositionGeo
|
||||
<< ", chargeTypeId= " << ec.chargeStruct().chargeTypeId()
|
||||
<< ", destructiveFactor= " << destructiveFactor
|
||||
<< ", penetrationFactor= " << penetrationFactor;
|
||||
m_ddsHandler->ftcBld()->sendCesHitOnBuildingRequest(requestBld, this);
|
||||
bitfieldState.insert(indexBitFieldIdx);
|
||||
|
||||
}
|
||||
else if (zPlacement == AreaEffectSimulation::AesZPlacement_def::ZpAbsolute)
|
||||
{
|
||||
// since HandlerBuildingModel::handleDetonationLocationRequest has already
|
||||
// calculated to ignFuncBase, the impactPosition is the detonationLocation:
|
||||
Core::GeoPosition detonationLocation = impactPositionGeo;
|
||||
|
||||
double detonationDistance = 0;
|
||||
switch (ignFuncBase.underlying())
|
||||
{
|
||||
case ProjectDataManagement::IgniterFunctionBase::IfbProximity:
|
||||
detonationDistance = -5;
|
||||
break;
|
||||
case ProjectDataManagement::IgniterFunctionBase::IfbImpact:
|
||||
detonationDistance = 0;
|
||||
break;
|
||||
case ProjectDataManagement::IgniterFunctionBase::IfbDelay:
|
||||
detonationDistance = 5;
|
||||
break;
|
||||
default:
|
||||
// empty
|
||||
break;
|
||||
} // switch
|
||||
|
||||
|
||||
|
||||
Buildings::SendCesHit3DonBuildingRequest requestBld(
|
||||
footprint.mseId,
|
||||
ec.chargeStruct().chargeTypeId(),
|
||||
destructiveFactor,
|
||||
penetrationFactor,
|
||||
aesItemId,
|
||||
m_ddsHandler->currentPartitionTime(),
|
||||
impactPositionGeo,
|
||||
detonationLocation,
|
||||
detonationDistance,
|
||||
properties.toStdString());
|
||||
|
||||
DEBUG_LOG(m_logger) << "SendCesHit3DonBuildingRequest for aesItemId=" << aesItemId
|
||||
<< " bitFieldIdx= " << indexBitFieldIdx
|
||||
<< ", impactPosition= " << impactPositionGeo
|
||||
<< ", zPlacement= " << zPlacement
|
||||
<< ", chargeTypeId= " << ec.chargeStruct().chargeTypeId()
|
||||
<< ", destructiveFactor= " << destructiveFactor
|
||||
<< ", penetrationFactor= " << penetrationFactor;
|
||||
|
||||
m_ddsHandler->ftcBld()->sendCesHit3DonBuildingRequest(requestBld, this);
|
||||
bitfieldState.insert(indexBitFieldIdx);
|
||||
|
||||
} // if
|
||||
} // for
|
||||
}
|
||||
|
||||
void HandlerAesData::checkBuildingsHit(const AreaEffectSimulation::AesItemView &data)
|
||||
{
|
||||
const int exerciseId = m_ddsHandler->getExerciseId();
|
||||
QPolygonF polyGeo;
|
||||
|
||||
DEBUG_LOG(m_logger) << "checkBuildingsHit " << ", aesItemId=" << data.aesItemId();
|
||||
|
||||
DEBUG_LOG(m_logger) << "AtBoobyTrapSecondary data.form().size()=" << data.form().size();
|
||||
// BoobyTrap
|
||||
polyGeo.reserve(data.form().size());
|
||||
for (const auto &pointGeo : qAsConst(data.form()))
|
||||
{
|
||||
QPointF point;
|
||||
point.setX(pointGeo.lon());
|
||||
point.setY(pointGeo.lat());
|
||||
DEBUG_LOG(m_logger) << "point= " << point.x() << "/" << point.y();
|
||||
polyGeo.append(point);
|
||||
}
|
||||
|
||||
bool completeEnclosed = false;
|
||||
bool isGroundLevel = true;
|
||||
const QVector<int> &buildingIdsInside = m_ddsHandler->dtcIsm()->getBuildingByPolygon(exerciseId, polyGeo, completeEnclosed, isGroundLevel);
|
||||
|
||||
DEBUG_LOG(m_logger) << "buildingsInside.size=" << buildingIdsInside.size()
|
||||
<< " exerciseId=" << exerciseId;
|
||||
// only include buildings within the radius
|
||||
|
||||
for (const int buildingId : qAsConst(buildingIdsInside))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << " BuildingId=" << buildingId;
|
||||
Buildings::Building tmpBldg;
|
||||
tmpBldg.buildingId(buildingId);
|
||||
|
||||
Core::GeoPosition impactPosition;
|
||||
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtBoobyTrapSecondary)
|
||||
{
|
||||
impactPosition.lat(m_ddsHandler->dtcAes()->boobyTrap(data.aesItemId()).impactPosition().lat());
|
||||
impactPosition.lon(m_ddsHandler->dtcAes()->boobyTrap(data.aesItemId()).impactPosition().lon());
|
||||
}
|
||||
else if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtOffRouteMineSecondary)
|
||||
{
|
||||
int zone = -1;
|
||||
LtsCoordTrans::UtmCoordinate bottomLeft = LtsCoordTrans::UtmCoordinate::fromGeographic(data.boundingBoxBottomLeft().lon(), data.boundingBoxBottomLeft().lat(), zone);
|
||||
LtsCoordTrans::UtmCoordinate topRight = LtsCoordTrans::UtmCoordinate::fromGeographic(data.boundingBoxTopRight().lon(), data.boundingBoxTopRight().lat(), zone);
|
||||
|
||||
|
||||
LtsCoordTrans::UtmCoordinate impactPosPoint(topRight.zone, ((topRight.x + bottomLeft.x) / 2), ((topRight.y + bottomLeft.y) / 2), true);
|
||||
impactPosPoint.zone = topRight.zone;
|
||||
|
||||
QPointF pointGeo = impactPosPoint.geographic();
|
||||
impactPosition.lon(pointGeo.x());
|
||||
impactPosition.lat(pointGeo.y());
|
||||
DEBUG_LOG(m_logger) << "impactPosition lon/lat=" << impactPosition.lon() << "/" << impactPosition.lat()
|
||||
<< " impactPosPoint.zone" << impactPosPoint.zone
|
||||
<< " impactPosPoint=" << impactPosPoint.x << "/" << impactPosPoint.y
|
||||
<< " topRight=" << topRight.x << "/" << topRight.y
|
||||
<< " bottomLeft" << bottomLeft.x << "/" << bottomLeft.y;
|
||||
}
|
||||
|
||||
Buildings::SendCesHitOnBuildingRequest requestBld(
|
||||
tmpBldg.buildingId(),
|
||||
data.chargeStruct().chargeTypeId(),
|
||||
m_ddsHandler->dtcPdm()->getBuildingChargeEffectByChargeTypeId(data.chargeStruct().chargeTypeId()).destructiveFactor(),
|
||||
m_ddsHandler->dtcPdm()->getBuildingChargeEffectByChargeTypeId(data.chargeStruct().chargeTypeId()).penetrationFactor(),
|
||||
data.aesItemId(),
|
||||
m_ddsHandler->currentPartitionTime(),
|
||||
impactPosition,
|
||||
QStringLiteral("properties").toStdString());
|
||||
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendCesHitOnBuildingRequest for aesItemId=" << data.aesItemId()
|
||||
<< ", impactPosition= " << impactPosition;
|
||||
m_ddsHandler->ftcBld()->sendCesHitOnBuildingRequest(requestBld, this);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<int> HandlerAesData::findBuildingsBetween(const LtsCoordTrans::LtsCoordinate &impactPosition,
|
||||
const CentralEffectSimulation::HandlerBuildingData::Footprint &targetFootprint)
|
||||
{
|
||||
QVector<int> buildingIdsInBetween;
|
||||
|
||||
// use zone of impactPosition
|
||||
const LtsCoordTrans::UtmCoordinate &impactPositionUTM = impactPosition.utmCoordinate();
|
||||
const int zone = impactPositionUTM.zone;
|
||||
|
||||
const LtsCoordTrans::LtsCoordinate targetFootprintPos =
|
||||
LtsCoordTrans::LtsCoordinate::fromUtm(targetFootprint.polyUtm.first(), targetFootprint.zone, 0.0);
|
||||
|
||||
DEBUG_LOG(m_logger) << "findBuildingsBetween" << " START impactPosition " << impactPositionUTM.mgrs()
|
||||
<< ", maybe effected mseId is = " << targetFootprint.mseId
|
||||
<< " with targetFootprintPos = " << targetFootprintPos.utmCoordinate().mgrs();
|
||||
|
||||
// line between a) impactPosition and b) targetFootprintPos
|
||||
QPolygonF impactToFootprintLineMetric;
|
||||
impactToFootprintLineMetric.reserve(2);
|
||||
|
||||
|
||||
// // a) impactPosition
|
||||
// impactToFootprintLineMetric.append(impactPosition.utmCoordinateAsPointF(zone));
|
||||
// // b) targetFootprintPos
|
||||
// impactToFootprintLineMetric.append(targetFootprintPos.utmCoordinateAsPointF(zone));
|
||||
|
||||
// a) impactPosition
|
||||
impactToFootprintLineMetric.append(impactPosition.toUtm<QPointF>());
|
||||
// b) targetFootprintPos
|
||||
impactToFootprintLineMetric.append(targetFootprintPos.toUtm<QPointF>(zone));
|
||||
|
||||
|
||||
|
||||
|
||||
// check all exercise specific footprints except our:
|
||||
const QHash<int, CentralEffectSimulation::HandlerBuildingData::Footprint> &allFootprintsOfEx = m_handlerBuildingData->getFootprints();
|
||||
buildingIdsInBetween.reserve(allFootprintsOfEx.size());
|
||||
for (const CentralEffectSimulation::HandlerBuildingData::Footprint &footprintToCheck : qAsConst(allFootprintsOfEx))
|
||||
{
|
||||
// do not check ourself
|
||||
if (footprintToCheck.mseId == targetFootprint.mseId)
|
||||
continue;
|
||||
|
||||
// check intersection of
|
||||
// line between a) impactPosition and b) targetFootprintPos
|
||||
// and footprint
|
||||
// QPolygonF is your friend :-)
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
|
||||
const bool intersects = impactToFootprintLineMetric.intersected(footprintToCheck.polyUtm).size() > 0;
|
||||
#else
|
||||
const bool intersects = impactToFootprintLineMetric.intersects(footprintToCheck.polyUtm);
|
||||
#endif
|
||||
|
||||
DEBUG_LOG(m_logger) << "findBuildingsBetween"
|
||||
<< " to mseId " << footprintToCheck.mseId
|
||||
<< " with curFpTargetPos " << impactPosition.utmCoordinate().mgrs()
|
||||
<< " -> intersects = " << intersects;
|
||||
|
||||
if (intersects)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "findBuildingsBetween"
|
||||
<< " regarding impactPosition " << impactPositionUTM.mgrs()
|
||||
<< " and mseId " << targetFootprint.mseId
|
||||
<< " is concealed/covered by footpriont of mseId = " << footprintToCheck.mseId;
|
||||
buildingIdsInBetween.append(footprintToCheck.mseId);
|
||||
}
|
||||
} // for
|
||||
|
||||
|
||||
return buildingIdsInBetween;
|
||||
}
|
||||
|
||||
} // namespace CesBuildings
|
||||
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CentralEffectSimulation/logger.h>
|
||||
|
||||
#include <AreaEffectSimulation/aes_dtc.h>
|
||||
#include <Buildings/bld_dtc.h>
|
||||
#include <Buildings/bld_ftc.h>
|
||||
#include <ProjectDataManagement/pdm_dtc.h>
|
||||
#include <TrainingAreaBase/tab_ftc.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
#include <CentralEffectSimulation/aes_item_view_utm.h>
|
||||
#include <LtsCoordinate/lts_coordinate.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QVector>
|
||||
#include <QPolygonF>
|
||||
#include <QTimer>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
class QPoint3D;
|
||||
}
|
||||
|
||||
// AES-Handling for buildings
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
|
||||
class HandlerAesData : public QObject
|
||||
, protected Buildings::Interface::Ftc::SendCesHitOnBuildingReplyHandler
|
||||
, protected Buildings::Interface::Ftc::SendCesHit3DonBuildingReplyHandler
|
||||
, protected TrainingAreaBase::Interface::Ftc::SendCesHitInformationReplyHandler
|
||||
, protected Buildings::Interface::Ftc::SetBuildingStatesReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HandlerAesData(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &buildingDataHandler,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~HandlerAesData();
|
||||
|
||||
/**
|
||||
* Initialize the handler to manage information from player management
|
||||
*/
|
||||
bool init();
|
||||
AreaEffectSimulation::AesItemView itemView(const int &aesId) const { return m_aesItemViews.value(aesId); }
|
||||
ProjectDataManagement::IgniterFunctionBase igniterFunctionBaseExplosionCluster(const int &aesId) const
|
||||
{
|
||||
auto chargeStruct = m_ddsHandler->dtcAes()->explosionCluster(aesId).chargeStruct();
|
||||
return m_ddsHandler->dtcPdm()->getChargeTypeIgniterTypeIgniterFunction(chargeStruct.chargeTypeId(),
|
||||
chargeStruct.igniterTypeId(),
|
||||
chargeStruct.igniterFunctionId()).igniterFunctionBaseId();
|
||||
}
|
||||
int chargeTypeId(const int &aesId) const
|
||||
{
|
||||
return m_ddsHandler->dtcAes()->explosionCluster(aesId).chargeStruct().chargeTypeId();
|
||||
}
|
||||
|
||||
protected:
|
||||
void onSendCesHitOnBuildingReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void onSendCesHit3DonBuildingReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void onSendCesHitInformationReply(const Core::FunctionReplyObject &reply) override final;
|
||||
void onSetBuildingStatesReply(const Core::FunctionReplyObject &reply) override final;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* Handle the signals from 'AES'
|
||||
*/
|
||||
void onChargeEffectChanged(const AreaEffectSimulation::ChargeEffect &data, DataModification modType);
|
||||
void onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType);
|
||||
void onAirSupportImpactChanged(const AreaEffectSimulation::AirSupportImpact &data, DataModification modType);
|
||||
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
|
||||
void onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType);
|
||||
void onEffectsChanged(const AreaEffectSimulation::Effects &effects, DataModification modType);
|
||||
void onBoobyTrapChanged(const AreaEffectSimulation::BoobyTrap &data, DataModification modType);
|
||||
void onStartTimeReached();
|
||||
|
||||
void removeStates(const AreaEffectSimulation::AesItemView &data);
|
||||
|
||||
//private: // structs
|
||||
|
||||
// typedef QHash<int, QSet<int>> BitfieldStates; shift to aes_item_view_utm.h
|
||||
|
||||
private: // methoden
|
||||
bool inFootprint(const Core::GeoPosition2D &geoPosition,
|
||||
const CentralEffectSimulation::HandlerBuildingData::Footprint &footPrint,
|
||||
const double radius) const;
|
||||
|
||||
bool inBoundingBox(const Core::GeoPosition2D& impactPosition,
|
||||
const CentralEffectSimulation::HandlerBuildingData::Footprint &footprint,
|
||||
const double impactRadius) const;
|
||||
|
||||
|
||||
void preCalculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data);
|
||||
void calculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data,
|
||||
const AreaEffectSimulation::AesItemView &aesItemView,
|
||||
const CentralEffectSimulation::HandlerBuildingData::Footprint &footprint);
|
||||
void calculateImpacts(const AreaEffectSimulation::Effects &effects,
|
||||
const CentralEffectSimulation::HandlerBuildingData::Footprint &footprint);
|
||||
|
||||
void checkBuildingsHit(const AreaEffectSimulation::AesItemView &data);
|
||||
|
||||
QVector<int> findBuildingsBetween(const LtsCoordTrans::LtsCoordinate &impactPosition,
|
||||
const CentralEffectSimulation::HandlerBuildingData::Footprint &targetFootprint);
|
||||
void calculateBuildingExplosion(const AreaEffectSimulation::ChargeStruct &chargeStruct, const Core::GeoPosition2D &impactPosition, const int id);
|
||||
void startTimer(int id, int msec);
|
||||
|
||||
private: // attributes
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> m_handlerBuildingData;
|
||||
|
||||
QHash<int, CentralEffectSimulation::BitfieldStates> m_bitfieldStatesBld; // key = mseId, value = BitfieldState
|
||||
|
||||
// AES-Values
|
||||
QHash<int, AreaEffectSimulation::AesItemView> m_aesItemViews; // key = aesItemId
|
||||
QHash<int, CentralEffectSimulation::AesItemViewUtm> m_aesItemViewsUtm; // key = aesItemId
|
||||
QHash<int, AreaEffectSimulation::AesEffectState> m_explosionSingleState; // key = id value = state
|
||||
|
||||
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
|
||||
QHash<int, AreaEffectSimulation::ChargeEffect> m_chargeEffects; // key = onChargeEffectChanged.id value ChargeEffect
|
||||
|
||||
};
|
||||
|
||||
} // namespace CesBuildings
|
||||
|
||||
+782
@@ -0,0 +1,782 @@
|
||||
/**
|
||||
* Handler for building models.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by biedziak_f, SLTE, 2021-03-23
|
||||
*/
|
||||
|
||||
#include "handler_building_model.h"
|
||||
|
||||
#include <CentralEffectSimulation/logger.h>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QVector3D>
|
||||
|
||||
// operator<<
|
||||
std::ostream &operator<< (std::ostream &stream, const QVector3D &value)
|
||||
{
|
||||
stream << "QPointF("
|
||||
<< QString::number(value.x(), 'f', 6) << "#"
|
||||
<< QString::number(value.y(), 'f', 6) << "#"
|
||||
<< QString::number(value.z(), 'f', 6) << "#lenght="
|
||||
<< QString::number(value.length(), 'f', 6)
|
||||
<< ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HandlerBuildingModel
|
||||
//
|
||||
|
||||
/*************************************************************************************************
|
||||
* Ctor, dtor and init *
|
||||
*************************************************************************************************/
|
||||
|
||||
HandlerBuildingModel::HandlerBuildingModel(
|
||||
const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler, const std::shared_ptr<HandlerAesData> &aesDataHandler, QObject *parent
|
||||
)
|
||||
: QObject(parent)
|
||||
, CentralEffectSimulation::Interface::Fts::GetLineBuildingIntersectionRequestHandler(ddsHandler->ftsCes())
|
||||
, CentralEffectSimulation::Interface::Fts::GetLineBuildingIntersectsRequestHandler(ddsHandler->ftsCes())
|
||||
, CentralEffectSimulation::Interface::Fts::DetonationLocationRequestHandler(ddsHandler->ftsCes())
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_aesDataHandler(aesDataHandler)
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.Buildings.HandlerBuildingModel"))
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
HandlerBuildingModel::~HandlerBuildingModel()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
bool HandlerBuildingModel::init()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> dtcIsm = m_ddsHandler->dtcIsm();
|
||||
|
||||
dtcIsm->waitForHistoricalDataMainStructureElement(1000);
|
||||
connect(dtcIsm.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
|
||||
this, &HandlerBuildingModel::onMainStructureElementChanged);
|
||||
|
||||
// get:
|
||||
dtcIsm->mainStructureElements([this](const InfrastructureManagement::MainStructureElement & data)
|
||||
{
|
||||
onMainStructureElementChanged(data, DataModification::eAdded);
|
||||
});
|
||||
|
||||
INFO_LOG(m_logger) << "HandlerBuildingModel is running."
|
||||
<< ", m_buildingModels.size() = " << m_buildingModels.size();
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
return true;
|
||||
}
|
||||
|
||||
HandlerBuildingModelInterface::LineBuildingIntersectionResult HandlerBuildingModel::getLineBuildingIntersection(
|
||||
const std::vector<Core::GeoPosition> &line, const std::string &requestIdOpt)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
CentralEffectSimulation::GetLineBuildingIntersectionRequest newRequest;
|
||||
newRequest.line(line);
|
||||
newRequest.requestId(requestIdOpt);
|
||||
|
||||
const bool justForLineOfSight = false;
|
||||
const CentralEffectSimulation::GetLineBuildingIntersectionReply &reply =
|
||||
getLineBuildingIntersectionInternal(newRequest, justForLineOfSight);
|
||||
|
||||
// convert reply to result:
|
||||
// compare HandlerBuildingModel::getLineBuildingIntersection()
|
||||
|
||||
LineBuildingIntersectionResult result;
|
||||
result.requestId = requestIdOpt;
|
||||
result.errorString = reply.errorString();
|
||||
result.errorParams = reply.errorParams();
|
||||
result.intersection = reply.intersection();
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
return result;
|
||||
}
|
||||
|
||||
HandlerBuildingModelInterface::LineBuildingIntersectsResult HandlerBuildingModel::getLineBuildingIntersects(const std::vector<Core::GeoPosition> &line, const std::string &requestIdOpt)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
CentralEffectSimulation::GetLineBuildingIntersectionRequest newRequest;
|
||||
newRequest.line(line);
|
||||
newRequest.requestId(requestIdOpt);
|
||||
|
||||
const bool justForLineOfSight = true;
|
||||
const CentralEffectSimulation::GetLineBuildingIntersectionReply &reply =
|
||||
getLineBuildingIntersectionInternal(newRequest, justForLineOfSight);
|
||||
|
||||
// convert reply to result:
|
||||
// compare HandlerBuildingModel::onGetLineBuildingIntersectsRequest()
|
||||
|
||||
LineBuildingIntersectsResult result;
|
||||
result.requestId = requestIdOpt;
|
||||
result.errorString = reply.errorString();
|
||||
result.errorParams = reply.errorParams();
|
||||
result.intersects = ! std::isnan(reply.intersection().lat()); // ! std::isnan
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
return result;
|
||||
}
|
||||
|
||||
void HandlerBuildingModel::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data, DataModification modType)
|
||||
{
|
||||
const int mseBldgId = data.id();
|
||||
|
||||
TRACE_LOG(m_logger) << "MainStructureElement === " << data;
|
||||
|
||||
// Always delete m_buildingModels-entry
|
||||
BuildingModel *buildingModelPtr = m_buildingModels.value((mseBldgId));
|
||||
delete buildingModelPtr;
|
||||
m_buildingModels.remove(mseBldgId);
|
||||
|
||||
if (modType == DataModification::eRemoved)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Building not added or modified id=" << mseBldgId;
|
||||
return;
|
||||
}
|
||||
|
||||
// skip "Outdoor Cameras / Announcement Units"
|
||||
if (data.structureElementTypeId() != InfrastructureManagement::StructureElementType_def::Building)
|
||||
return;
|
||||
|
||||
// Vor allem in der GUEZ-DB sind ca 23 Gebäude per Hand eingefügt. (Sakralbau, Bahnhof, Wasserwerk etc.)
|
||||
// Diese tragen die Description "Import von Hand".
|
||||
// Für diese steht natürlich kein Verwundungsmodell zur Verfügung.
|
||||
// Wie können wir diese erkennen und hier überspringen?
|
||||
// Ich habe keine bessere Möglichkeit gefunden als diese:
|
||||
const Core::GeoPosition &geoPos = data.geoPosition();
|
||||
if (qFuzzyIsNull(geoPos.z()))
|
||||
{
|
||||
INFO_LOG(m_logger) << "BuildingId " << mseBldgId
|
||||
<< " kann übersprungen werden, da von Hand importiert."
|
||||
<< ", name: '" << data.name() << "'"
|
||||
<< ", name: '" << data.description() << "'";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const int exerciseId = m_ddsHandler->getExerciseId();
|
||||
if (m_ddsHandler->dtcIsm()->isElementAssignedToExercise(data, exerciseId))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "BuildingId " << mseBldgId
|
||||
<< ", in Exercise";
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "BuildingId " << mseBldgId
|
||||
<< ", not in Exercise";
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "HandlerBuildingData::onMainStructureElementChanged() id=" << mseBldgId
|
||||
<< " properties=" << data.properties();
|
||||
|
||||
|
||||
// const QVector<int> buildingIds = m_ddsHandler->dtcIsm()->getBuildingIdsByExercise(exerciseId);
|
||||
// const QMap<int, InfrastructureManagement::VulnerabilityModelData> vulnerabilityModelData = m_ddsHandler->dtcIsm()->vulnerabilityModelDatas();
|
||||
// QMap<int, InfrastructureManagement::VulnerabilityModelData> vulnerabilityModelData;
|
||||
|
||||
// InfrastructureManagement::VulnerabilityModelData vulnerabilityModelDataEle;
|
||||
QByteArray vulnerabilityModelData = m_ddsHandler->dtcIsm()->getVulnerabilityModelData(data.id());
|
||||
TRACE_LOG(m_logger) << "vulnerabilityModelData=" << vulnerabilityModelData
|
||||
<< " id=" << data.id();
|
||||
|
||||
|
||||
// int id = -1;
|
||||
// for (auto vmdIt = vulnerabilityModelData.constBegin(); vmdIt != vulnerabilityModelData.constEnd(); ++vmdIt)
|
||||
// {
|
||||
// if (vmdIt.value().mainStructureElementId() == mseBldgId)
|
||||
// {
|
||||
// id = vmdIt.key();
|
||||
// vulnerabilityModelDataEle = m_ddsHandler->dtcIsm()->vulnerabilityModelDatas().value(id);
|
||||
// break;
|
||||
// } // if
|
||||
// } // for
|
||||
// if (id == -1)
|
||||
// {
|
||||
// WARNING_LOG(m_logger) << "Missing VulnerabilityModelData for building " << mseBldgId << ". Skip building.";
|
||||
// return;
|
||||
// } // if
|
||||
|
||||
const InfrastructureManagement::MainFootprint &mainFootprint = m_ddsHandler->dtcIsm()->getFootprintsByExerciseId(exerciseId).value(mseBldgId);
|
||||
|
||||
DEBUG_LOG(m_logger) << "BuildingId " << mseBldgId;
|
||||
|
||||
BuildingModel *buildingModel = new BuildingModel(this);
|
||||
const InfrastructureManagement::MainStructureElement &mse = data;
|
||||
if (!buildingModel->init(mainFootprint, mse, vulnerabilityModelData, mseBldgId))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Initializing BuildingModel failed for building " << mseBldgId << ". Skipping building.";
|
||||
return;
|
||||
}
|
||||
// if
|
||||
|
||||
INFO_LOG(m_logger) << "Inserting BuildingModel for building " << mseBldgId;
|
||||
m_buildingModels.insert(mseBldgId, buildingModel);
|
||||
|
||||
INFO_LOG(m_logger) << "onMainStructureElementChanged: "
|
||||
<< ", m_buildingModels.size() = " << m_buildingModels.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Intersection handling *
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
void HandlerBuildingModel::onGetLineBuildingIntersectionRequest(const rti::core::SampleIdentity &cookie,
|
||||
const CentralEffectSimulation::GetLineBuildingIntersectionRequest &request)
|
||||
{
|
||||
const int exerciseId = m_ddsHandler->getExerciseId();
|
||||
DEBUG_LOG(m_logger) << "START onGetLineBuildingIntersectionRequest" << ", exerciseId = " << exerciseId << ", request '" << request.requestId() << "'";
|
||||
|
||||
const bool justForLineOfSight = false;
|
||||
const CentralEffectSimulation::GetLineBuildingIntersectionReply &reply = getLineBuildingIntersectionInternal(request, justForLineOfSight);
|
||||
|
||||
// sendReply
|
||||
m_ddsHandler->ftsCes()->getLineBuildingIntersectionReply(cookie, reply);
|
||||
|
||||
DEBUG_LOG(m_logger) << "END onGetLineBuildingIntersectionRequest, request '" << request.requestId() << "'";
|
||||
}
|
||||
|
||||
void HandlerBuildingModel::onGetLineBuildingIntersectsRequest(const rti::core::SampleIdentity &cookie,
|
||||
const CentralEffectSimulation::GetLineBuildingIntersectsRequest &request)
|
||||
{
|
||||
const int exerciseId = m_ddsHandler->getExerciseId();
|
||||
DEBUG_LOG(m_logger) << "START onGetLineBuildingIntersectsRequest" << ", exerciseId = " << exerciseId << ", request '" << request.requestId() << "'";
|
||||
|
||||
|
||||
CentralEffectSimulation::GetLineBuildingIntersectionRequest newRequest;
|
||||
newRequest.line(request.line());
|
||||
newRequest.requestId(request.requestId());
|
||||
|
||||
const bool justForLineOfSight = true;
|
||||
const CentralEffectSimulation::GetLineBuildingIntersectionReply &reply = getLineBuildingIntersectionInternal(newRequest, justForLineOfSight);
|
||||
|
||||
// sendReply
|
||||
CentralEffectSimulation::GetLineBuildingIntersectsReply newReply;
|
||||
newReply.id(reply.id());
|
||||
newReply.errorString(reply.errorString());
|
||||
newReply.errorParams(reply.errorParams());
|
||||
newReply.requestId(reply.requestId());
|
||||
newReply.intersects(! std::isnan(reply.intersection().lat())); // ! std::isnan
|
||||
|
||||
m_ddsHandler->ftsCes()->getLineBuildingIntersectsReply(cookie, newReply);
|
||||
|
||||
DEBUG_LOG(m_logger) << "END onGetLineBuildingIntersectsRequest, request '" << request.requestId() << "'";
|
||||
}
|
||||
|
||||
|
||||
//LtsUtils::QPoint3D set_zValueToIfNegative(const LtsUtils::QPoint3D &pnt, double newZValue = 0.1)
|
||||
//{
|
||||
// return LtsUtils::QPoint3D(pnt.x(),
|
||||
// pnt.y(),
|
||||
// (pnt.z() > 0) ? pnt.z() : newZValue);
|
||||
//}
|
||||
|
||||
|
||||
CentralEffectSimulation::GetLineBuildingIntersectionReply HandlerBuildingModel::getLineBuildingIntersectionInternal(const CentralEffectSimulation::GetLineBuildingIntersectionRequest &request,
|
||||
bool justForLineOfSight,
|
||||
int *buildingIdOut,
|
||||
int *segmentIdxOfIntersectionPtrOut) const
|
||||
{
|
||||
static Core::GeoPosition s_invalidPos(std::nan(""), std::nan(""), std::nan(""));
|
||||
|
||||
const int exerciseId = m_ddsHandler->getExerciseId();
|
||||
|
||||
DEBUG_LOG(m_logger) << "START getLineBuildingIntersectionInternal" << ", exerciseId = " << exerciseId << ", request '" << request.requestId() << "'"
|
||||
<< ", request.line().size() = " << request.line().size();
|
||||
|
||||
CentralEffectSimulation::GetLineBuildingIntersectionReply reply;
|
||||
reply.requestId(request.requestId());
|
||||
// prepare invalid 'answer'
|
||||
reply.intersection(s_invalidPos);
|
||||
|
||||
// empty (poly-)line
|
||||
// (think of a trajectory)
|
||||
const std::vector<Core::GeoPosition> &polylineRef = request.line();
|
||||
if (polylineRef.size() < 2)
|
||||
{
|
||||
reply.errorString("insufficiant number of points");
|
||||
WARNING_LOG(m_logger) << "getLineBuildingIntersectionInternal" << ", exerciseId = " << exerciseId << ", request '" << request.requestId() << "'"
|
||||
<< ", error: '" << reply.errorString() << "'";
|
||||
return reply;
|
||||
}
|
||||
|
||||
QPolygonF polygon2D;
|
||||
polygon2D.reserve(polylineRef.size());
|
||||
for (const Core::GeoPosition &geoPos : qAsConst(polylineRef))
|
||||
polygon2D << QPointF(geoPos.lon(), geoPos.lat());
|
||||
|
||||
// Only the buildings where the line/trajectory flies over the building footprint are taken into account.
|
||||
bool completeEnclosed = false;
|
||||
bool isGroundLevel = false;
|
||||
const QVector<int> &relevantBuildings = m_ddsHandler->dtcIsm()->getBuildingByPolygon(exerciseId, polygon2D, completeEnclosed, isGroundLevel);
|
||||
|
||||
if (m_logger.isDebugEnabled())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "relevantBuildings.size=" << relevantBuildings.size();
|
||||
for (const int bldgId : qAsConst(relevantBuildings))
|
||||
DEBUG_LOG(m_logger) << "relevantBuilding: bldgId = " << bldgId;
|
||||
}
|
||||
|
||||
|
||||
double distance = DBL_MAX;
|
||||
uint lineSegmentIdx = 0;
|
||||
|
||||
//---------------------
|
||||
// We need to iterate over all items.
|
||||
// But we need access to current and also successor item!
|
||||
// If we like to avoid index operator, we can use following approach:
|
||||
//
|
||||
// iterate over all items, !!! BUT ONE !!!
|
||||
// for (lineIt = polylineRef.begin(); lineIt != polylineRef.end()-1; )
|
||||
// {
|
||||
// // Copy...
|
||||
// const Core::GeoPosition segStart = *lineIt;
|
||||
// // ...increment and ref
|
||||
// const Core::GeoPosition &segEnd = *(++lineIt);
|
||||
// ...
|
||||
//---------------------
|
||||
// but we prefer index operator here, because in total is better:
|
||||
// less copying of GeoPosition, iterator etc.
|
||||
//---------------------
|
||||
|
||||
for (lineSegmentIdx = 0; lineSegmentIdx < polylineRef.size() - 1; ++lineSegmentIdx)
|
||||
{
|
||||
const Core::GeoPosition &segStart = polylineRef[lineSegmentIdx];
|
||||
const Core::GeoPosition &segEnd = polylineRef[lineSegmentIdx + 1];
|
||||
|
||||
DEBUG_LOG(m_logger) << " lineSegmentIdx=" << lineSegmentIdx
|
||||
<< ", start=" << segStart
|
||||
<< " , end=" << segEnd;
|
||||
|
||||
int buildingId = -1; // for debugging purposes
|
||||
//for (BuildingModel *buildingModel : qAsConst(m_buildingModels))
|
||||
for (const int bldgId : qAsConst(relevantBuildings))
|
||||
{
|
||||
BuildingModel *buildingModel = m_buildingModels.value(bldgId, nullptr);
|
||||
if (!buildingModel)
|
||||
{
|
||||
WARNING_LOG(m_logger) << " buildingModel not found, bldgId=" << bldgId;
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << " buildingModel->buildingId=" << buildingModel->buildingId()
|
||||
<< " , HEIGHT = " << buildingModel-> height();
|
||||
|
||||
|
||||
// skip buildingModel, if damaged (>80%)
|
||||
auto dtcBld = m_ddsHandler->dtcBld();
|
||||
dtcBld->enableBuildingState();
|
||||
|
||||
const Buildings::BuildingState &buildingState = dtcBld->buildingState(bldgId);
|
||||
// if buildingState is not found, assume intact:
|
||||
if (/*(buildingState.id() == bldgId) && */(buildingState.damagePercent() >= 80))
|
||||
{
|
||||
WARNING_LOG(m_logger) << " buildingModel->buildingId=" << buildingModel->buildingId()
|
||||
<< ", lineSegmentIdx=" << lineSegmentIdx
|
||||
<< ", damagePercent > 80% (" << buildingState.damagePercent() << ")";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Do NOT
|
||||
// Do NOT
|
||||
// Do NOT
|
||||
|
||||
// Note:
|
||||
// Imagine following situation:
|
||||
// ______
|
||||
// | |
|
||||
// | Bldg |
|
||||
// | |
|
||||
// ----------
|
||||
// * ---/ ------ o
|
||||
// ---/ --------- Surface / BaseSurface / Soil
|
||||
|
||||
// * = Impact / Detonation
|
||||
// o = Player
|
||||
|
||||
// In that case, no intersection will re recognized :-(
|
||||
// To avoid this, lift zValue on building level by using set_zValueToIfNegative
|
||||
|
||||
// positions in the building's coordinate system in [m] (distance from reference position)
|
||||
// const LtsUtils::QPoint3D &relStart = set_zValueToIfNegative(buildingModel->fromGeographic(segStart), 0.1); // lift / lift_zValueToIfNegative
|
||||
// const LtsUtils::QPoint3D &relEnd = set_zValueToIfNegative(buildingModel->fromGeographic(segEnd), 0.1); // lift / lift_zValueToIfNegative
|
||||
|
||||
|
||||
// Do NOT
|
||||
// GUEZE-3166:
|
||||
// in case of U_BAHN, segStart and segEnd really have negative values.
|
||||
// It will lead to false results, if set_zValueToIfNegative is executed.
|
||||
// In the meantime, lineOfSightElevation is introduced.
|
||||
// Aceept the situation drawn above and assume, that lineOfSightElevation will do it.
|
||||
// Do NOT
|
||||
// Do NOT
|
||||
|
||||
|
||||
const LtsUtils::QPoint3D &relStart = buildingModel->fromGeographic(segStart); // lift / lift_zValueToIfNegative
|
||||
const LtsUtils::QPoint3D &relEnd = buildingModel->fromGeographic(segEnd); // lift / lift_zValueToIfNegative
|
||||
|
||||
DEBUG_LOG(m_logger) << " buildingModel->buildingId=" << buildingModel->buildingId()
|
||||
<< ", lineSegmentIdx=" << lineSegmentIdx;
|
||||
|
||||
DEBUG_LOG(m_logger) << " segStart=" << segStart << " relStart=" << relStart;
|
||||
DEBUG_LOG(m_logger) << " segEnd =" << segEnd << " relEnd=" << relEnd;
|
||||
|
||||
if (!buildingModel->hasIntersectionSimplified(relStart, relEnd)) // check height and footprint
|
||||
continue;
|
||||
|
||||
DEBUG_LOG(m_logger) << " buildingModel->buildingId=" << buildingModel->buildingId()
|
||||
<< ", lineSegmentIdx=" << lineSegmentIdx
|
||||
<< ", hasIntersectionSimplified was true";
|
||||
|
||||
const Core::GeoPosition &intersection = buildingModel->intersection(relStart, relEnd); // assume intersection and calculate
|
||||
|
||||
DEBUG_LOG(m_logger) << " buildingModel->buildingId=" << buildingModel->buildingId()
|
||||
<< ", lineSegmentIdx=" << lineSegmentIdx
|
||||
<< ", intersection = " << intersection;
|
||||
|
||||
if (!BuildingModel::isValid(intersection)) // no intersection
|
||||
continue;
|
||||
|
||||
DEBUG_LOG(m_logger) << " buildingModel->buildingId=" << buildingModel->buildingId()
|
||||
<< ", lineSegmentIdx=" << lineSegmentIdx
|
||||
<< ", has valid intersection = " << intersection;
|
||||
if (buildingIdOut)
|
||||
*buildingIdOut = buildingModel->buildingId();
|
||||
|
||||
// justForLineOfSight :
|
||||
if (justForLineOfSight)
|
||||
{
|
||||
reply.intersection(intersection);
|
||||
DEBUG_LOG(m_logger) << "END getLineBuildingIntersectionInternal, return due to justForLineOfSight " << request.requestId() << "'";
|
||||
return reply;
|
||||
}
|
||||
// : justForLineOfSight
|
||||
|
||||
const double dist = (relStart - buildingModel->fromGeographic(intersection)).length(); // distance to start of segment
|
||||
if (dist < distance) // new intersection is closer than the last one
|
||||
{
|
||||
if (buildingId == -1) // first intersection found
|
||||
DEBUG_LOG(m_logger) << "Building " << buildingModel->buildingId() << " was hit.";
|
||||
else // this building "covers" the last one found
|
||||
DEBUG_LOG(m_logger) << "Building " << buildingModel->buildingId() << " was hit prior to building " << buildingId << ".";
|
||||
buildingId = buildingModel->buildingId();
|
||||
distance = dist;
|
||||
reply.intersection(intersection);
|
||||
if (segmentIdxOfIntersectionPtrOut)
|
||||
*segmentIdxOfIntersectionPtrOut = lineSegmentIdx;
|
||||
|
||||
} // if
|
||||
|
||||
} // for (const int bldgId : qAsConst(relevantBuildings))
|
||||
} // for(lineIt = polylineRef.begin(); lineIt != polylineRef.end()-1; ++lineIt)
|
||||
|
||||
DEBUG_LOG(m_logger) << "END getLineBuildingIntersectionInternal, request '" << request.requestId() << "'"
|
||||
<< " buildingIdOut=" << *buildingIdOut;
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// DetonationLocationRequest handling *
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
void HandlerBuildingModel::onDetonationLocationRequest(
|
||||
const rti::core::SampleIdentity &cookie, const CentralEffectSimulation::DetonationLocationRequest &request
|
||||
)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Received DetonationLocationRequest for aesId: " << request.id();
|
||||
const CentralEffectSimulation::DetonationLocationReply reply = handleDetonationLocationRequest(request);
|
||||
if (!reply.errorString().empty())
|
||||
WARNING_LOG(m_logger) << "DetonationLocationRequest for aesId " << request.id() << " failed: " << reply.errorString();
|
||||
// if
|
||||
m_ddsHandler->ftsCes()->detonationLocationReply(cookie, reply);
|
||||
}
|
||||
|
||||
CentralEffectSimulation::DetonationLocationReply HandlerBuildingModel::handleDetonationLocationRequest(const CentralEffectSimulation::DetonationLocationRequest &request) const
|
||||
{
|
||||
const int exerciseId = m_ddsHandler->getExerciseId();
|
||||
DEBUG_LOG(m_logger) << " handleDetonationLocationRequest request=" << request
|
||||
<< ", m_buildingModels.size() = " << m_buildingModels.size();
|
||||
// AES::
|
||||
// ExplosionCluster most likely has serveral impacts and therefore several trajectories.
|
||||
// To differentiate between them, 'explosionIndex' is used (starting with 0)
|
||||
// CES:
|
||||
// To differentiate between a) explosionIndex and b) trajectoryIdx (segmentIdx)
|
||||
// const int explosionIndex = request.index();
|
||||
|
||||
// prepare reply and store some values from request:
|
||||
CentralEffectSimulation::DetonationLocationReply reply;
|
||||
reply.id(request.id()); // AES: aesItemId
|
||||
reply.index(request.index()); // AES: explosionIndex
|
||||
|
||||
if ( m_buildingModels.size() <= 0)
|
||||
return reply;
|
||||
|
||||
CentralEffectSimulation::GetLineBuildingIntersectionRequest lbRequest;
|
||||
lbRequest.requestId("handleDetonationLocationRequest");
|
||||
lbRequest.line(request.trajectory());
|
||||
|
||||
const std::vector<Core::GeoPosition>& reqTrajRef = request.trajectory();
|
||||
|
||||
if (reqTrajRef.size() < 2)
|
||||
{
|
||||
ERROR_LOG(m_logger) << " handleDetonationLocationRequest request.trajectory() invalid, size =" << reqTrajRef.size();
|
||||
return reply;
|
||||
}
|
||||
|
||||
// next step: determine detonationDistance according fuseType:
|
||||
double detonationDistance = 0;
|
||||
ProjectDataManagement::IgniterFunctionBase ignFuncBase = m_ddsHandler->getIgniterFunctionBaseFromChargeTypeId(request.chargeTypeId(),
|
||||
request.igniterTypeId(),
|
||||
request.igniterFunctionId());
|
||||
switch (ignFuncBase.underlying())
|
||||
{
|
||||
case ProjectDataManagement::IgniterFunctionBase::IfbProximity: detonationDistance = -5; break;
|
||||
case ProjectDataManagement::IgniterFunctionBase::IfbImpact: detonationDistance = 0; break;
|
||||
case ProjectDataManagement::IgniterFunctionBase::IfbDelay: detonationDistance = 5; break;
|
||||
default:
|
||||
// empty
|
||||
break;
|
||||
} // switch
|
||||
|
||||
// next step: find bldgIntersection
|
||||
const bool justForLineOfSight = false;
|
||||
int validSizeOfOriginalTraj = -1;
|
||||
int buildingId = -1;
|
||||
const CentralEffectSimulation::GetLineBuildingIntersectionReply &lbiReply =
|
||||
getLineBuildingIntersectionInternal(lbRequest, justForLineOfSight, &buildingId, &validSizeOfOriginalTraj);
|
||||
|
||||
const LtsCoordTrans::LtsCoordinate bldgIntersectionCoord(lbiReply.intersection());
|
||||
const bool bHasBuildingIntersection = BuildingModel::isValid(bldgIntersectionCoord.geoPosition());
|
||||
if (bHasBuildingIntersection)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "RESULT: Trajectory: hasBuildingIntersection YES, at: " << bldgIntersectionCoord.mgrs()
|
||||
<< " buildingId=" << buildingId;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "RESULT: Trajectory: hasBuildingIntersection NO";
|
||||
|
||||
const bool bIsInTrainingOrCentralArea = true;
|
||||
if (bIsInTrainingOrCentralArea)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "RESULT: integrate free area...";
|
||||
|
||||
// free area and FuseType_def::IfbDelay:
|
||||
// We can´t move the detonation point _below_ the surface.
|
||||
// That would be identical to a neagative 'startHat'
|
||||
// In other words: lineOfSightElevation would deliver LineOfSight::LOS_ERROR
|
||||
// so:
|
||||
if (detonationDistance > 0) // detonationDistance > 0 === FuseType_def::IfbDelay
|
||||
detonationDistance = 0;
|
||||
}
|
||||
} // if (bHasBuildingIntersection)
|
||||
|
||||
|
||||
// next step: integrate detonationDistance into trajectory to find the final detonationLocation:
|
||||
|
||||
// !!! assume that the requested trajectory ends directly on the ground !!!
|
||||
|
||||
LtsCoordTrans::LtsCoordinate detonationLocation;
|
||||
if (bHasBuildingIntersection)
|
||||
detonationLocation = bldgIntersectionCoord;
|
||||
else
|
||||
detonationLocation = LtsCoordTrans::LtsCoordinate(reqTrajRef.back());
|
||||
|
||||
// do we really have to do any calculations?
|
||||
if (qFuzzyIsNull(detonationDistance)) // depends on 'FuseType'
|
||||
{
|
||||
if (!bHasBuildingIntersection)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "detonationLocation on ground" << detonationLocation.geoPosition()
|
||||
<< std::fixed << std::setprecision(3)
|
||||
<< ", heightOverElevation = " << detonationLocation.heightOverElevation();
|
||||
Q_ASSERT_X(std::fabs(detonationLocation.heightOverElevation()) < 1.0, "handleDetonationLocationRequest", "heightOverElevation is to high");
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "Trajectory bAdjusted/bHasBuildingIntersection: " << bHasBuildingIntersection
|
||||
<< ", igniterFunctionBase: " << ignFuncBase
|
||||
<< ", detonationDistance: " << detonationDistance
|
||||
<< ", reqTrajRef.size():" << reqTrajRef.size() << " back: " << reqTrajRef.back()
|
||||
<< ", detonationLocation: " << detonationLocation.toString(true)
|
||||
<< ", buildingId: " << buildingId;
|
||||
|
||||
reply.position(detonationLocation.geoPosition());
|
||||
reply.buildingId(buildingId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// DetonationLocation
|
||||
// instead of backtrackTrajectory(), use simply resize and push_back(bldgIntersectionCoord)
|
||||
std::vector<Core::GeoPosition> trajectoryCopy = reqTrajRef;
|
||||
|
||||
DEBUG_LOG(m_logger) << "validSizeOfOriginalTraj is below zero: " << validSizeOfOriginalTraj << ", exerciseId " << exerciseId << ", buildingId=" << buildingId;
|
||||
|
||||
// in case of hasBuildingIntersection
|
||||
if (validSizeOfOriginalTraj > 0)
|
||||
{
|
||||
trajectoryCopy.resize(validSizeOfOriginalTraj);
|
||||
trajectoryCopy.push_back(bldgIntersectionCoord.geoPosition());
|
||||
}
|
||||
|
||||
// adjust detonationLocation by taking detonationDistance (!= 0) into account:
|
||||
detonationLocation = LtsCoordTrans::LtsCoordinate(calculateDetonationLocation(trajectoryCopy, detonationDistance));
|
||||
|
||||
DEBUG_LOG(m_logger) << "Trajectory bAdjusted/bHasBuildingIntersection: " << bHasBuildingIntersection
|
||||
<< ", igniterFunctionBase: " << ignFuncBase
|
||||
<< ", detonationDistance: " << detonationDistance
|
||||
<< ", trajectoryCopy.size()=" << trajectoryCopy.size() << " back: " << trajectoryCopy.back()
|
||||
<< ", detonationLocation: " << detonationLocation.toString(true)
|
||||
<< ", buildingId: " << buildingId;
|
||||
reply.buildingId(buildingId);
|
||||
reply.position(detonationLocation.geoPosition());
|
||||
}
|
||||
|
||||
// otherwise let reply.position be untouched.
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
Core::GeoPosition HandlerBuildingModel::calculateDetonationLocation(const std::vector<Core::GeoPosition> &trajectoryGeometry, double detonationDistance) const
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
const int geometrySize = trajectoryGeometry.size();
|
||||
if (geometrySize < 3)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << ", trajectoryGeometry not sufficiant";
|
||||
return {};
|
||||
}
|
||||
|
||||
// Z-Werte - absolute
|
||||
// geometrySize-3]; - see comment below
|
||||
// ^^^
|
||||
auto p1 = trajectoryGeometry[geometrySize - 3];
|
||||
LtsCoordTrans::UtmCoordinate utm1 = LtsCoordTrans::UtmCoordinate::fromGeographic(p1.lon(), p1.lat()); // ToDo: Zone des Bldgs?
|
||||
QVector3D segStart(utm1.x, utm1.y, p1.z());
|
||||
|
||||
auto p2 = trajectoryGeometry[geometrySize - 1];
|
||||
LtsCoordTrans::UtmCoordinate utm2 = LtsCoordTrans::UtmCoordinate::fromGeographic(p2.lon(), p2.lat()); // ToDo: Zone des Bldgs?
|
||||
QVector3D segEnd(utm2.x, utm2.y, p2.z());
|
||||
|
||||
QVector3D flightVec = segEnd - segStart;
|
||||
|
||||
INFO_LOG(m_logger) << "flightVec1 "
|
||||
<< ", utm1 " << utm1 << " , z " << p1.z()
|
||||
<< ", utm2 " << utm2 << " , z " << p2.z()
|
||||
<< ", flightVec " << flightVec;
|
||||
|
||||
// 'auto p1 = trajectoryGeometry[geometrySize-3];'
|
||||
// ^^^
|
||||
// Sometime the flightVec has a very small component, so it becomes zero and scaling to 5m will fail:
|
||||
// 2023-12-15 16:01:59.879 INFO CES::HandlerBuildingModel |#| Core::GeoPosition CesBuildings::HandlerBuildingModel::calculateDetonationLocation(const std::vector<Core::GeoPosition>&, double) const START (ation/Plugins/Buildings/handler_building_model.cpp:279)
|
||||
// 2023-12-15 16:01:59.879 ERROR CES::HandlerBuildingModel |#|
|
||||
// flightVec1 ,
|
||||
// utm1 UtmCoordinate(676943.27#5818641.5 zone=32) , z 98.19423,
|
||||
// utm2 UtmCoordinate(676943.29#5818641.7 zone=32) , z 98.072554,
|
||||
// flightVec QPointF(0.062500#0.000000#-0.121674#lenght=0.136787) (ation/Plugins/Buildings/handler_building_model.cpp:299)
|
||||
// ^^^^^^^^
|
||||
// 2023-12-15 16:01:59.879 ERROR CES::HandlerBuildingModel |#| flightVec2 ,
|
||||
// utm1 UtmCoordinate(676943.27#5818641.5 zone=32) , z 98.19423,
|
||||
// utm2 UtmCoordinate(676943.29#5818641.7 zone=32) , z 98.072554,
|
||||
// flightVec QPointF(2.284572#0.000000#-4.447553#lenght=5.000000), detonationLoc
|
||||
// ^^^^^^^^
|
||||
|
||||
|
||||
|
||||
// scale:
|
||||
const int distanceMeter = std::fabs(detonationDistance); // meter
|
||||
flightVec *= distanceMeter / flightVec.length();
|
||||
|
||||
// now put on impactPositon;
|
||||
QVector3D detonationLoc;
|
||||
if (detonationDistance > 0) // Delay
|
||||
detonationLoc = segEnd + flightVec; // 'extend'
|
||||
else
|
||||
detonationLoc = segEnd - flightVec; // 'reduce'
|
||||
|
||||
LtsCoordTrans::UtmCoordinate utmDeto(utm1.zone, detonationLoc.x(), detonationLoc.y());
|
||||
const QPointF &pointDeto = utmDeto.geographic();
|
||||
Core::GeoPosition geoPosDeto(pointDeto.x(), pointDeto.y(), detonationLoc.z());
|
||||
|
||||
DEBUG_LOG(m_logger) << "flightVec2 "
|
||||
<< ", utm1 " << utm1 << " , z " << p1.z()
|
||||
<< ", utm2 " << utm2 << " , z " << p2.z()
|
||||
<< ", flightVec " << flightVec
|
||||
<< ", detonationLoc " << detonationLoc
|
||||
<< ", utmDeto " << utmDeto;
|
||||
|
||||
return geoPosDeto;
|
||||
}
|
||||
|
||||
/*
|
||||
Core::GeoPosition HandlerBuildingModel::backtrackTrajectory(const std::vector<Core::GeoPosition> &trajectory,
|
||||
const Core::GeoPosition &position,
|
||||
double distancePerSegment) const
|
||||
{
|
||||
Core::GeoPosition startGeo = position;
|
||||
LtsCoordTrans::UtmCoordinate startUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(position.lon(), position.lat());
|
||||
LtsUtils::QPoint3D start(startUtm.x, startUtm.y, position.z());
|
||||
|
||||
double res = distancePerSegment;
|
||||
for (int i = trajectory.size() - 1; i > 0; --i)
|
||||
{
|
||||
const Core::GeoPosition &segmentStartGeo = trajectory[i];
|
||||
const Core::GeoPosition &segmentEndGeo = trajectory[i - 1];
|
||||
|
||||
const LtsCoordTrans::UtmCoordinate segmentStartUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(segmentStartGeo.lon(), segmentStartGeo.lat());
|
||||
const LtsCoordTrans::UtmCoordinate segmentEndUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(segmentEndGeo.lon(), segmentEndGeo.lat());
|
||||
|
||||
const LtsUtils::QPoint3D segmentStart(segmentStartUtm.x, segmentStartUtm.y, segmentStartGeo.z());
|
||||
const LtsUtils::QPoint3D segmentEnd(segmentEndUtm.x, segmentEndUtm.y, segmentEndGeo.z());
|
||||
|
||||
const LtsUtils::QPoint3D direction = (segmentEnd - segmentStart).normalized();
|
||||
if (LtsUtils::QPoint3D::dotProduct(start - segmentEnd, direction) > (segmentEnd - segmentStart).length()) // start is in a different trajectory segment
|
||||
continue;
|
||||
|
||||
const double length = (start - segmentEnd).length();
|
||||
if (length < res) // continue to next segment
|
||||
{
|
||||
res -= length;
|
||||
start = segmentEnd;
|
||||
continue;
|
||||
} // if
|
||||
|
||||
start += res * direction;
|
||||
startUtm.x = start.x();
|
||||
startUtm.y = start.y();
|
||||
const QPointF lonLat = startUtm.geographic();
|
||||
startGeo.lon(lonLat.x());
|
||||
startGeo.lat(lonLat.y());
|
||||
startGeo.z(start.z());
|
||||
return startGeo;
|
||||
} // for
|
||||
|
||||
WARNING_LOG(m_logger) << "Backtracing trajectory for proximity fuse type failed.";
|
||||
return startGeo;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
} // namespace CesBuildings
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Handler for building models.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by biedziak_f, SLTE, 2021-03-23
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ces_building_model.h"
|
||||
#include "handler_aes_data.h"
|
||||
|
||||
// for interface
|
||||
#include "../../proxy_building.h"
|
||||
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HandlerBuildingModel
|
||||
//
|
||||
|
||||
/**
|
||||
* @brief The HandlerBuildingModel class contains building and rooms geometry in detail.
|
||||
* Based on that LineOfSight operations could be offered.
|
||||
*/
|
||||
class HandlerBuildingModel final
|
||||
: public QObject
|
||||
, public HandlerBuildingModelInterface
|
||||
, protected CentralEffectSimulation::Interface::Fts::GetLineBuildingIntersectionRequestHandler
|
||||
, protected CentralEffectSimulation::Interface::Fts::GetLineBuildingIntersectsRequestHandler
|
||||
, protected CentralEffectSimulation::Interface::Fts::DetonationLocationRequestHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit HandlerBuildingModel(
|
||||
const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler, const std::shared_ptr<HandlerAesData> &aesDataHandler, QObject *parent = nullptr
|
||||
);
|
||||
~HandlerBuildingModel();
|
||||
|
||||
bool init();
|
||||
|
||||
const QMap<int, BuildingModel *> &buildingModels() const { return m_buildingModels; }
|
||||
|
||||
|
||||
/*! \name implementation of synchron calls of HandlerBuildingModel - LineOfSight etc*/
|
||||
//@{
|
||||
|
||||
///< LineOfSight: find exact intersection
|
||||
LineBuildingIntersectionResult getLineBuildingIntersection(const std::vector<Core::GeoPosition> &line,
|
||||
const std::string &requestIdOpt = {}) override;
|
||||
|
||||
///< LineOfSight: find if lingOfSight is given or not
|
||||
LineBuildingIntersectsResult getLineBuildingIntersects(const std::vector<Core::GeoPosition> &line,
|
||||
const std::string &requestIdOpt = {}) override;
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
///< LineOfSight: find exact intersection
|
||||
void onGetLineBuildingIntersectionRequest(const rti::core::SampleIdentity &cookie, const CentralEffectSimulation::GetLineBuildingIntersectionRequest &request) override final;
|
||||
|
||||
///< LineOfSight: find if lingOfSight is given or not
|
||||
void onGetLineBuildingIntersectsRequest(const rti::core::SampleIdentity &cookie, const CentralEffectSimulation::GetLineBuildingIntersectsRequest &request) override final;
|
||||
|
||||
///< special request for AreaEffectSimulation
|
||||
void onDetonationLocationRequest(const rti::core::SampleIdentity &cookie, const CentralEffectSimulation::DetonationLocationRequest &request) override final;
|
||||
|
||||
|
||||
private Q_SLOTS:
|
||||
/**
|
||||
* Handle MainStructureElement from 'ISM'
|
||||
*/
|
||||
void onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data, DataModification modType);
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
* \brief getLineBuildingIntersectionInternal
|
||||
* \param request more or less genral request
|
||||
* \param justForLineOfSight stop on first intersection or find exact intersection?
|
||||
* \param segmentIdxOfIntersectionPtrOut intersection of intersection
|
||||
* \return reply
|
||||
*/
|
||||
CentralEffectSimulation::GetLineBuildingIntersectionReply getLineBuildingIntersectionInternal(const CentralEffectSimulation::GetLineBuildingIntersectionRequest &request,
|
||||
bool justForLineOfSight = false,
|
||||
int *buildingIdOut = nullptr,
|
||||
int *segmentIdxOfIntersectionPtrOut = nullptr
|
||||
) const;
|
||||
|
||||
///< special request for AreaEffectSimulation
|
||||
CentralEffectSimulation::DetonationLocationReply handleDetonationLocationRequest(const CentralEffectSimulation::DetonationLocationRequest &request) const;
|
||||
Core::GeoPosition calculateDetonationLocation(const std::vector<Core::GeoPosition> &trajectoryGeometry, double detonationDistance) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler;
|
||||
std::shared_ptr<HandlerAesData> m_aesDataHandler;
|
||||
QMap<int, BuildingModel *> m_buildingModels; // key = buildingId
|
||||
|
||||
CentralEffectSimulation::LOGGER_T m_logger;
|
||||
|
||||
}; // class HandlerBuildingModel
|
||||
|
||||
} // namespace CesBuildings
|
||||
+413
@@ -0,0 +1,413 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#include "handler_building_ownership.h"
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <ngldb/dbtransaction.h>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
HandlerBuildingOwnership::HandlerBuildingOwnership(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &buildingDataHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::DatabaseInterface> &db,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, SetOwnershipRequestHandler(ddsHandler->ftsCes())
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_handlerParticipant(participantHandler)
|
||||
, m_handlerBuildingData(buildingDataHandler)
|
||||
, m_db(db)
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.Buildings.HandlerBuildingOwnership"))
|
||||
{
|
||||
INFO_LOG(m_logger) << "HandlerBuildingOwnership::HandlerBuildingOwnership";
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HandlerBuildingOwnership::~HandlerBuildingOwnership()
|
||||
{
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerBuildingOwnership::init()
|
||||
{
|
||||
INFO_LOG(m_logger) << "HandlerBuildingOwnership::init";
|
||||
auto dtcIsm = m_ddsHandler->dtcIsm();
|
||||
|
||||
DEBUG_LOG(m_logger) << "init";
|
||||
loadOwnershipsFromDb();
|
||||
|
||||
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newOutdoorPosition,
|
||||
this, &HandlerBuildingOwnership::onParticipantPositionChanged);
|
||||
|
||||
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newIndoorPosition,
|
||||
this, &HandlerBuildingOwnership::onParticipantPositionChanged);
|
||||
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newNotfightMode,
|
||||
this, &HandlerBuildingOwnership::onParticipantPositionChanged);
|
||||
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::participantLeavesBuilding,
|
||||
this, &HandlerBuildingOwnership::onParticipantLeavesBuilding);
|
||||
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newParticipantState,
|
||||
this, &HandlerBuildingOwnership::onParticipantPositionChanged);
|
||||
|
||||
dtcIsm->waitForHistoricalDataMainStructureElement(1000);
|
||||
connect(dtcIsm.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
|
||||
this, &HandlerBuildingOwnership::onMainStructureElementChanged);
|
||||
|
||||
// Get 'static' data for all MainStructureElements
|
||||
{
|
||||
auto cb = [this](const InfrastructureManagement::MainStructureElement & mse)
|
||||
{
|
||||
onMainStructureElementChanged(mse, DataModification::eAdded);
|
||||
};
|
||||
if (!dtcIsm->mainStructureElements(cb))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// ///////////////////////////////////
|
||||
// B L D (Buildings)
|
||||
// ///////////////////////////////////
|
||||
|
||||
void HandlerBuildingOwnership::onSetOwnershipRequest(const rti::core::SampleIdentity &cookie,
|
||||
const CentralEffectSimulation::SetOwnershipRequest &request)
|
||||
{
|
||||
INFO_LOG(m_logger) << "onSetOwnershipRequest: " << request;
|
||||
|
||||
// remove Ownership, if partyId == 0
|
||||
if (request.partyId() == 0)
|
||||
removeFromDbBuildingId(request.buildingId());
|
||||
|
||||
const QVector<int> floors = m_handlerBuildingData->getFloorsFromBuilding(request.buildingId());
|
||||
for (int floorId : floors)
|
||||
saveBuildingOwnership(floorId, request.partyId(), request.buildingId());
|
||||
|
||||
if (!floors.isEmpty())
|
||||
sendBuildingOwnership(request.buildingId());
|
||||
|
||||
m_ddsHandler->ftsCes()->setOwnershipReply(cookie, Core::FunctionReplyObject(request.buildingId()));
|
||||
}
|
||||
|
||||
void HandlerBuildingOwnership::onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos)
|
||||
{
|
||||
|
||||
const int participantId = partPos.participantId();
|
||||
INFO_LOG(m_logger) << "BuildingOwnership onParticipantPositionChanged participantId=" << participantId
|
||||
<< " vulnerabilityState=" << partPos.vulnerabilityState
|
||||
<< " buildingId=" << partPos.buildingId()
|
||||
<< " notfightMode=" << partPos.notfightMode;
|
||||
|
||||
// [GUEZE-2256] 3D Wirksim - Funktionsraum Nicht Kampffaehig
|
||||
// Teilnehmer, die den Status Nicht Kampffaehig haben, düfen nicht bei der Berechnung des Gebaeudebesitzes beruecksichtigt werden.
|
||||
if (partPos.notfightMode)
|
||||
return;
|
||||
|
||||
int floorId = m_handlerBuildingData->getFloorIdFromRoomId(partPos.roomId());
|
||||
if (partPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CatastrophicKill)
|
||||
m_participantFloor.remove(participantId);
|
||||
else
|
||||
m_participantFloor.insert(participantId, floorId);
|
||||
|
||||
int newOwnership = calculateOwnershipByParticipantId(participantId);
|
||||
checkAndSendOwnership(newOwnership, floorId);
|
||||
INFO_LOG(m_logger) << "END BuildingOwnership onParticipantPositionChanged participantId=" << participantId
|
||||
<< " vulnerabilityState=" << partPos.vulnerabilityState;
|
||||
} // end of onParticipantPositionChanged()
|
||||
|
||||
|
||||
// ///////////////////////////////////
|
||||
// I S M (InfrastructureManagement)
|
||||
// ///////////////////////////////////
|
||||
void HandlerBuildingOwnership::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data, DataModification modType)
|
||||
{
|
||||
INFO_LOG(m_logger) << "onMainStructureElementChanged id=" << data.id()
|
||||
<< " modelId =" << data.modelId();
|
||||
if (modType == DataModification::eRemoved || data.modelId() <= 0)
|
||||
{
|
||||
m_buildingOwnership.remove(data.id());
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonArray jsonArray = QJsonDocument::fromJson(QByteArray::fromStdString(data.properties())).object().value(QLatin1String("available_in_exercise")).toArray();
|
||||
DEBUG_LOG(m_logger) << "available_in_exercise jsonDocument.size()=" << jsonArray.size();
|
||||
QVector<int> result;
|
||||
result.reserve(jsonArray.size());
|
||||
|
||||
// Check if present in the current exercise and remove
|
||||
if (m_buildingOwnership.contains(data.id()))
|
||||
{
|
||||
int id = data.id();
|
||||
m_buildingOwnership.remove(id);
|
||||
m_ddsHandler->dtsCes()->removeBuildingOwnershipByKey(id);
|
||||
}
|
||||
|
||||
for (auto it = jsonArray.constBegin(); it != jsonArray.constEnd(); ++it)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "available_in_exercise jsonDocument=" << it->toInt();
|
||||
if (m_ddsHandler->getExerciseId() != it->toInt())
|
||||
continue;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got MainStructureElement"
|
||||
<< " data.id()=" << data.id()
|
||||
<< " data.modelId=" << data.modelId();
|
||||
if (!m_buildingOwnership.contains(data.id()))
|
||||
{
|
||||
// insert in m_buildingOwnership and publish to dds
|
||||
CentralEffectSimulation::BuildingOwnership bo;
|
||||
bo.buildingId(data.id());
|
||||
bo.sampleTime(QDateTime::currentMSecsSinceEpoch());
|
||||
updateOwnerships(&bo);
|
||||
m_buildingOwnership.insert(data.id(), bo);
|
||||
m_ddsHandler->dtsCes()->publish(bo);
|
||||
} // if
|
||||
} // for
|
||||
}
|
||||
|
||||
void HandlerBuildingOwnership::onParticipantLeavesBuilding(const int participantId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "BuildingOwnership onParticipantLeavesBuilding participantId=" << participantId;
|
||||
auto it = m_participantFloor.find(participantId);
|
||||
if (it == m_participantFloor.end())
|
||||
return;
|
||||
m_participantFloor.erase(it);
|
||||
|
||||
const int floorId = it.value();
|
||||
const int newOwnership = calculateOwnershipByFloorId(floorId);
|
||||
DEBUG_LOG(m_logger) << "newOwnership=" << newOwnership;
|
||||
if (newOwnership > 0)
|
||||
checkAndSendOwnership(newOwnership, floorId);
|
||||
} // end of onParticipantLeavesBuilding()
|
||||
|
||||
int HandlerBuildingOwnership::calculateOwnershipByParticipantId(const int participantId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "BuildingOwnership calculateOwnershipByParticipantId participantId=" << participantId;
|
||||
CentralEffectSimulation::HandlerParticipant::CesParticipantData partPos = m_handlerParticipant->position(participantId);
|
||||
return calculateOwnershipByFloorId(m_handlerBuildingData->getFloorIdFromRoomId(partPos.roomId()));
|
||||
}
|
||||
|
||||
int HandlerBuildingOwnership::calculateOwnershipByFloorId(const int floorId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "BuildingOwnership calculateOwnershipByFloorId floorId=" << floorId;
|
||||
int ownership = -1;
|
||||
if (floorId == -1)
|
||||
return ownership;
|
||||
|
||||
DEBUG_LOG(m_logger) << "calculateOwnership floorId = " << floorId;
|
||||
|
||||
QHash <int, int> partyCount; // key = Party, value= Count of Participants;
|
||||
// Suche alle Participants in der Etage
|
||||
for (auto it = m_participantFloor.cbegin(); it != m_participantFloor.cend(); ++it)
|
||||
{
|
||||
int iteratorFloor = it.value();
|
||||
int iteratorParticipant = it.key();
|
||||
if (floorId == iteratorFloor)
|
||||
{
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &localPartPos = m_handlerParticipant->position(iteratorParticipant);
|
||||
if (localPartPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState::CatastrophicKill)
|
||||
continue; // Don't count participants with catastrophic Kill
|
||||
const int partyId = localPartPos.partyId();
|
||||
++partyCount[partyId];
|
||||
}
|
||||
}
|
||||
// berechne daraus die Farbe der Partei
|
||||
int countParty = 0;
|
||||
for (auto it = partyCount.begin(); it != partyCount.end(); ++it)
|
||||
{
|
||||
if (it.value() > countParty)
|
||||
{
|
||||
countParty = it.value();
|
||||
ownership = it.key();
|
||||
}
|
||||
}
|
||||
return ownership;
|
||||
}
|
||||
|
||||
int HandlerBuildingOwnership::getOwnership(int buildingId, int floorId) const
|
||||
{
|
||||
INFO_LOG(m_logger) << "BuildingOwnership getOwnership buildingId=" << buildingId
|
||||
<< " floorId=" << floorId;
|
||||
auto itBldg = m_buildingOwnership.find(buildingId);
|
||||
if (itBldg == m_buildingOwnership.end())
|
||||
return -1;
|
||||
const CentralEffectSimulation::BuildingOwnership &bo = itBldg.value();
|
||||
for (const CentralEffectSimulation::Ownership &ownership : bo.ownerships())
|
||||
{
|
||||
if (ownership.floorId() == floorId)
|
||||
return ownership.partyId();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void HandlerBuildingOwnership::checkAndSendOwnership(const int newOwnership, const int floorId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "BuildingOwnership checkAndSendOwnership";
|
||||
if (floorId < 0) // outside building
|
||||
return;
|
||||
const int buildingId = m_handlerBuildingData->getBuildingIdFromFloorId(floorId);
|
||||
if (buildingId < 0)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not find building for floor with id " << floorId << " - ignoring";
|
||||
return;
|
||||
}
|
||||
// prüfe, ob sich die Farbe geändert hat.
|
||||
const int oldOwnership = getOwnership(buildingId, floorId);
|
||||
DEBUG_LOG(m_logger) << "checkAndSendOwnership buildingId = "
|
||||
<< buildingId
|
||||
<< " floorId=" << floorId
|
||||
<< " oldOwnership=" << oldOwnership
|
||||
<< " newOwnership=" << newOwnership;
|
||||
if (oldOwnership != newOwnership) // Kriterium zum Senden
|
||||
{
|
||||
// Wenn ja, Eintrag in der Verwaltung
|
||||
saveBuildingOwnership(floorId, newOwnership, buildingId);
|
||||
// und Meldung verschicken.
|
||||
sendBuildingOwnership(buildingId);
|
||||
DEBUG_LOG(m_logger) << "new Building Ownership";
|
||||
}
|
||||
}
|
||||
|
||||
void HandlerBuildingOwnership::updateOwnerships(CentralEffectSimulation::BuildingOwnership *bo)
|
||||
{
|
||||
INFO_LOG(m_logger) << "BuildingOwnership updateOwnerships";
|
||||
QMap <int, int> ownershipMap;
|
||||
|
||||
const QVector<int> floors = m_handlerBuildingData->getFloorsFromBuilding(bo->buildingId());
|
||||
DEBUG_LOG(m_logger) << "updateOwnerships floors.size= " << floors.size();
|
||||
for (const int floorId : floors)
|
||||
ownershipMap[floorId] = 0;
|
||||
|
||||
for (const CentralEffectSimulation::Ownership &ownership : bo->ownerships())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "updateOwnerships floorId=" << ownership.floorId() << ": " << ownership.partyId();
|
||||
ownershipMap[ownership.floorId()] = ownership.partyId();
|
||||
}
|
||||
|
||||
bo->ownerships().resize(0);
|
||||
bo->ownerships().reserve(ownershipMap.size());
|
||||
|
||||
CentralEffectSimulation::Ownership ownership;
|
||||
for (auto it = ownershipMap.cbegin(); it != ownershipMap.cend(); ++it)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << it.key() << ": " << it.value();
|
||||
ownership.floorId(it.key());
|
||||
ownership.partyId(it.value());
|
||||
bo->ownerships().push_back(ownership);
|
||||
}
|
||||
|
||||
}
|
||||
void HandlerBuildingOwnership::saveBuildingOwnership(int floorId, int partyId, int buildingId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "saveBuildingOwnership floorId: " << floorId
|
||||
<< ", partyId: " << partyId
|
||||
<< ", buildingId: " << buildingId;
|
||||
|
||||
// Vorhandenen Eintrag für das Gebäude suchen
|
||||
auto it = m_buildingOwnership.find(buildingId);
|
||||
if (it != m_buildingOwnership.end())
|
||||
{
|
||||
CentralEffectSimulation::BuildingOwnership &bo = *it;
|
||||
// Vorhanden Eintrag für das Stockwerk suchen:
|
||||
for (CentralEffectSimulation::Ownership &ownership : bo.ownerships())
|
||||
{
|
||||
if (ownership.floorId() == floorId)
|
||||
{
|
||||
ownership.partyId(partyId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Neuen Eintrag für das Stockwerk anlegen
|
||||
CentralEffectSimulation::Ownership ownership;
|
||||
ownership.floorId(floorId);
|
||||
ownership.partyId(partyId);
|
||||
bo.ownerships().push_back(std::move(ownership));
|
||||
m_buildingOwnership.insert(buildingId, bo);
|
||||
return;
|
||||
}
|
||||
|
||||
// Neuen Eintrag für das Gebäude anlegen
|
||||
CentralEffectSimulation::BuildingOwnership bo;
|
||||
CentralEffectSimulation::Ownership ownership;
|
||||
|
||||
bo.buildingId(buildingId);
|
||||
ownership.floorId(floorId);
|
||||
ownership.partyId(partyId);
|
||||
bo.ownerships().resize(1, ownership);
|
||||
m_buildingOwnership.insert(buildingId, bo);
|
||||
}
|
||||
|
||||
void HandlerBuildingOwnership::sendBuildingOwnership(int buildingId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "sendBuildingOwnership for building: " << buildingId;
|
||||
CentralEffectSimulation::BuildingOwnership bo = m_buildingOwnership.value(buildingId);
|
||||
bo.buildingId(buildingId);
|
||||
bo.sampleTime(QDateTime::currentMSecsSinceEpoch());
|
||||
updateOwnerships(&bo);
|
||||
m_ddsHandler->dtsCes()->publish(bo);
|
||||
insertInDb(bo);
|
||||
}
|
||||
// ///////////////////////////////////////////////////
|
||||
/// \brief HandlerConfigureAlarms::loadOwnershipsFromDb
|
||||
/// \return
|
||||
///
|
||||
bool HandlerBuildingOwnership::loadOwnershipsFromDb()
|
||||
{
|
||||
INFO_LOG(m_logger) << "HandlerBuildingOwnership::loadOwnershipsFromDb ";
|
||||
m_buildingOwnership.clear();
|
||||
auto cbBo = [this](const CentralEffectSimulation::Database::CesOwnership & bo)
|
||||
{
|
||||
saveBuildingOwnership(bo.floorId, bo.partyId, bo.buildingId);
|
||||
};
|
||||
if (!m_db->select(cbBo))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading data from database 'CesOwnership'";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandlerBuildingOwnership::removeFromDbBuildingId(const int buildingId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "HandlerBuildingOwnership::removeFromDbBuildingId buildingId: " << buildingId;
|
||||
m_db->removeCesOwnershipByBuildingId(buildingId);
|
||||
}
|
||||
|
||||
|
||||
void HandlerBuildingOwnership::insertInDb(const CentralEffectSimulation::BuildingOwnership &bo)
|
||||
{
|
||||
DBTransaction trans(m_db->database());
|
||||
|
||||
removeFromDbBuildingId(bo.buildingId());
|
||||
INFO_LOG(m_logger) << "insertInDb buildingId: " << bo.buildingId()
|
||||
<< ", bo.ownerships().size(): " << bo.ownerships().size();
|
||||
CentralEffectSimulation::Database::CesOwnership newOwnership;
|
||||
newOwnership.buildingId = bo.buildingId();
|
||||
for (const CentralEffectSimulation::Ownership &ownership : bo.ownerships())
|
||||
{
|
||||
newOwnership.id = 0;
|
||||
newOwnership.floorId = ownership.floorId();
|
||||
newOwnership.partyId = ownership.partyId();
|
||||
DEBUG_LOG(m_logger) << "ownership: floorId = " << newOwnership.floorId
|
||||
<< " partyId = " << newOwnership.partyId;
|
||||
if (!m_db->insert(newOwnership))
|
||||
ERROR_LOG(m_logger) << "Error adding 'CesOwnership' to database "
|
||||
<< " buildingId =" << newOwnership.buildingId
|
||||
<< " floorId = " << newOwnership.floorId
|
||||
<< " partyId = " << newOwnership.partyId;
|
||||
}
|
||||
|
||||
trans.commit();
|
||||
} // end of insertInDb
|
||||
|
||||
} // namespace CesBuildings
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* 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/ces_db.h>
|
||||
#include <CentralEffectSimulation/ces_fts.h>
|
||||
#include <Buildings/bld_dtc.h>
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
// AES-Handling for participants within buildings
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
class HandlerBuildingOwnership final
|
||||
: public QObject
|
||||
, protected CentralEffectSimulation::Interface::Fts::SetOwnershipRequestHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit HandlerBuildingOwnership(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &buildingDataHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::DatabaseInterface> &db,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~HandlerBuildingOwnership();
|
||||
|
||||
/**
|
||||
* Initialize the handler to manage information from player management
|
||||
*/
|
||||
bool init();
|
||||
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
/**
|
||||
* Handle MainStructureElement from 'ISM'
|
||||
*/
|
||||
void onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos);
|
||||
|
||||
/**
|
||||
* Handle MainStructureElement from 'ISM'
|
||||
*/
|
||||
void onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data, DataModification modType);
|
||||
|
||||
void onParticipantLeavesBuilding(const int participantId);
|
||||
|
||||
private: // methoden
|
||||
void onSetOwnershipRequest(const rti::core::SampleIdentity &cookie,
|
||||
const CentralEffectSimulation::SetOwnershipRequest &request) override;
|
||||
|
||||
int calculateOwnershipByParticipantId(const int participantId);
|
||||
int calculateOwnershipByFloorId(const int floorId);
|
||||
void checkAndSendOwnership(const int newOwnership, const int floorId);
|
||||
void saveBuildingOwnership(int floorId, int partyId, int buildingId);
|
||||
void sendBuildingOwnership(int buildingId);
|
||||
int getOwnership(int buildingId, int floorId) const;
|
||||
void updateOwnerships(CentralEffectSimulation::BuildingOwnership *bo);
|
||||
bool loadOwnershipsFromDb();
|
||||
void removeFromDbBuildingId(const int buildingId);
|
||||
void insertInDb(const CentralEffectSimulation::BuildingOwnership &bo);
|
||||
|
||||
private: // attributes
|
||||
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to DDS handler
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant;
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> m_handlerBuildingData;
|
||||
std::shared_ptr<CentralEffectSimulation::DatabaseInterface> m_db;
|
||||
|
||||
QHash <int, int> m_participantFloor; // key = ParicipantId, value= FloorId;
|
||||
QHash <int, CentralEffectSimulation::BuildingOwnership> m_buildingOwnership; // key BuildingId, Value= Message BuildingOwnership
|
||||
|
||||
CentralEffectSimulation::LOGGER_T m_logger;
|
||||
|
||||
};
|
||||
} // namespace CesBuildings
|
||||
|
||||
+519
@@ -0,0 +1,519 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#include "handler_contamination.h"
|
||||
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
|
||||
#include <QPainterPath>
|
||||
#include <QPolygonF>
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
HandlerContamination::HandlerContamination(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
QObject *parent)
|
||||
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.Buildings.Buildings"))
|
||||
{
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HandlerContamination::~HandlerContamination()
|
||||
{
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HandlerContamination::init()
|
||||
{
|
||||
auto dtcAes = m_ddsHandler->dtcAes();
|
||||
auto ftcBld = m_ddsHandler->ftcBld();
|
||||
auto dtcBld = m_ddsHandler->dtcBld();
|
||||
ftcBld->enableSetBuildingContaminationState();
|
||||
|
||||
////////////////////////////
|
||||
/// \brief Get 'static' data for all BCContaminations
|
||||
///
|
||||
dtcAes->waitForHistoricalDataBCContamination(1000);
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::bCContaminationChanged,
|
||||
this, &HandlerContamination::onBCContaminationChanged);
|
||||
|
||||
// Get 'static' data for all BCContaminations
|
||||
{
|
||||
auto cb = [this](const AreaEffectSimulation::BCContamination & bcc)
|
||||
{
|
||||
onBCContaminationChanged(bcc, DataModification::eAdded);
|
||||
};
|
||||
if (!dtcAes->bCContaminations(cb))
|
||||
return false;
|
||||
}
|
||||
////////////////////////////
|
||||
/// \brief Get 'static' data for all AesItemView
|
||||
///
|
||||
dtcAes->waitForHistoricalDataAesItemView(1000);
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
|
||||
this, &HandlerContamination::onAesItemViewChanged);
|
||||
|
||||
// Get 'static' data for all AesItemView
|
||||
{
|
||||
auto cb = [this](const AreaEffectSimulation::AesItemView & aiv)
|
||||
{
|
||||
onAesItemViewChanged(aiv, DataModification::eAdded);
|
||||
};
|
||||
if (!dtcAes->aesItemViews(cb))
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
/// \brief Get data for all Building States
|
||||
///
|
||||
dtcBld->waitForHistoricalDataBuildingState(1000);
|
||||
connect(dtcBld.get(), &Buildings::Interface::Dtc::buildingStateChanged,
|
||||
this, &HandlerContamination::onBuildingStateChanged);
|
||||
|
||||
// Get 'static' data for all buildingStates
|
||||
{
|
||||
auto cb = [this](const Buildings::BuildingState & bs)
|
||||
{
|
||||
onBuildingStateChanged(bs, DataModification::eAdded);
|
||||
};
|
||||
if (!dtcBld->buildingStates(cb))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
// ///////////////////////////////////
|
||||
// A E S (AreaEffectSimulation)
|
||||
// ///////////////////////////////////
|
||||
|
||||
void HandlerContamination::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
|
||||
{
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got AesItemView: " << data.effectStateId()
|
||||
<< " data.aesItemId()" << data.aesItemId()
|
||||
<< " data.aesTypeId()" << data.aesTypeId();
|
||||
switch (data.effectStateId().underlying())
|
||||
{
|
||||
case AreaEffectSimulation::AesEffectState_def::EsActivated:
|
||||
{
|
||||
double chargeHeight; // Alle Stockwerke beruecksichtigen
|
||||
double chargeDepression; // Alle Kellerraeume beruecksichtigen
|
||||
|
||||
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtNContamination)
|
||||
{
|
||||
chargeHeight = 500.0; // Alle Stockwerke beruecksichtigen
|
||||
chargeDepression = -1000.0; // Alle Kellerraeume beruecksichtigen
|
||||
DEBUG_LOG(m_logger) << "AtNContamination: chargeHeight=" << chargeHeight
|
||||
<< " chargeDepression=" << chargeDepression;
|
||||
}
|
||||
else
|
||||
{
|
||||
chargeHeight = m_aesBCContaminations.value(data.aesItemId()).upperOffset();
|
||||
chargeDepression = m_aesBCContaminations.value(data.aesItemId()).lowerOffset();
|
||||
DEBUG_LOG(m_logger) << "BCContaminations: chargeHeight=" << chargeHeight
|
||||
<< " chargeDepression=" << chargeDepression;
|
||||
}
|
||||
|
||||
if (data.aesTypeId() != AreaEffectSimulation::AesType_def::AtBCContamination
|
||||
&& data.aesTypeId() != AreaEffectSimulation::AesType_def::AtNContamination)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "return1: AesItemView: " << data.effectStateId();
|
||||
return;
|
||||
}
|
||||
|
||||
// Gebaeude die von einem sesshaften Kampfstoff betroffen sind, müssen als kontaminiert gelten.
|
||||
const ProjectDataManagement::VolatilityType volatilityType = m_ddsHandler->volatilityTypeId(data.chargeStruct());
|
||||
if (volatilityType != ProjectDataManagement::VolatilityType_def::Resident
|
||||
&& data.aesTypeId() != AreaEffectSimulation::AesType_def::AtNContamination)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "return2: AesItemView: " << data.effectStateId();
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "HandlerContamination::onAesItemViewChanged data.aesItemId=" << data.aesItemId();
|
||||
auto dtcIsm = m_ddsHandler->dtcIsm();
|
||||
// Form in UTM-Polygon wandeln
|
||||
int exerciseId = m_ddsHandler->getExerciseId();
|
||||
QPolygonF polygonGeo;
|
||||
|
||||
// Convert Form to UTM
|
||||
for (unsigned int i = 0; i < data.form().size(); i++)
|
||||
polygonGeo.append(QPointF(data.form()[i].lon(), data.form()[i].lat()));
|
||||
|
||||
bool completeEnclosed = true;
|
||||
bool isGroundLevel = false;
|
||||
const QVector<int> &buildingIds = dtcIsm.get()->getBuildingByPolygon(exerciseId, polygonGeo, completeEnclosed, isGroundLevel);
|
||||
DEBUG_LOG(m_logger) << "buildingIds.size=" << buildingIds.size();
|
||||
for (int buildingId : qAsConst(buildingIds))
|
||||
{
|
||||
calculateBuilding(buildingId, data, chargeHeight, chargeDepression);
|
||||
}
|
||||
//
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HandlerContamination::calculateBuilding(int buildingId,
|
||||
const AreaEffectSimulation::AesItemView &data,
|
||||
double chargeHeight,
|
||||
double chargeDepression)
|
||||
{
|
||||
auto dtcIsm = m_ddsHandler->dtcIsm();
|
||||
QVector<int> effectedRooms;
|
||||
QVector<int> effectedFloors;
|
||||
|
||||
if (data.aesTypeId() != AreaEffectSimulation::AesType_def::AtBCContamination
|
||||
&& data.aesTypeId() != AreaEffectSimulation::AesType_def::AtNContamination)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "return: NO BC-Contamination AesItemView: " << data.effectStateId();
|
||||
return;
|
||||
}
|
||||
|
||||
const ProjectDataManagement::VolatilityType volatilityType = m_ddsHandler->volatilityTypeId(data.chargeStruct());
|
||||
if ( volatilityType != ProjectDataManagement::VolatilityType_def::Resident
|
||||
&& data.aesTypeId() != AreaEffectSimulation::AesType_def::AtNContamination)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "buildingId=" << buildingId;
|
||||
effectedRooms.clear();
|
||||
effectedFloors = getEffectedFloors(buildingId, chargeHeight, chargeDepression);
|
||||
for (int effectedFloor : qAsConst(effectedFloors))
|
||||
effectedRooms += dtcIsm.get()->getRoomIdsFromFloorId(buildingId, effectedFloor);
|
||||
if (!effectedRooms.empty())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "effectedRooms.size=" << effectedRooms.size();
|
||||
ProjectDataManagement::VulnerabilityState vulnerabilityState = ProjectDataManagement::VulnerabilityState::CombatReady;
|
||||
|
||||
// [GUEZE-2752] N-Contamination: Only Contamionation inside Range1
|
||||
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtNContamination
|
||||
&& !isInsideRange1(buildingId, data.aesItemId()))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "!isInsideRange1 buildingId=" << buildingId;
|
||||
return;
|
||||
}
|
||||
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtBCContamination
|
||||
&& !isInsideBCContamination(buildingId, data.aesItemId()))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "AtBCContamination !isInsideRange buildingId=" << buildingId << "return";
|
||||
return;
|
||||
}
|
||||
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtNContamination
|
||||
&& isInsideInnerCircle(buildingId, data.aesItemId()))
|
||||
{
|
||||
constexpr int TIME_2_SECONDS = 2000;
|
||||
// Only actual explosion not old N-Fields
|
||||
if ( m_ddsHandler->dtcCore()->partitionTime().timeStamp() < (data.effectStart() + TIME_2_SECONDS))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "VulnerabilityState=CatastrophicKill";
|
||||
vulnerabilityState = ProjectDataManagement::VulnerabilityState::CatastrophicKill;
|
||||
}
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "setBuildingContaminationStateRequest buildingId=" << buildingId
|
||||
<< " data.aesTypeId()=" << data.aesTypeId()
|
||||
<< " isInsideInnerCircle(buildingId, data.aesItemId()=" << isInsideInnerCircle(buildingId, data.aesItemId());
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "isInsideInnerCircle buildingId=" << buildingId;
|
||||
setBuildingContaminationStateRequest(buildingId, data.aesItemId(), vulnerabilityState, effectedRooms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ///////////////////////////////////
|
||||
// B L D (Buildings)
|
||||
// ///////////////////////////////////
|
||||
void HandlerContamination::onBuildingStateChanged(const Buildings::BuildingState &data, DataModification modType)
|
||||
{
|
||||
|
||||
if (modType != DataModification::eAdded
|
||||
&& modType != DataModification::eModified)
|
||||
return;
|
||||
|
||||
INFO_LOG(m_logger) << "onBuildingStateChanged"
|
||||
<< " id=" << data.id()
|
||||
<< " aesId=" << data.aesId()
|
||||
<< " contaminationStates().size=" << data.contaminationStates().size();
|
||||
// Reset:
|
||||
if (data.contaminationStates().empty())
|
||||
m_contaminationState.remove(data.id());
|
||||
// If a building is reset in an area where there is an active nuclear weapon, it will not be recontaminated -> in this case,
|
||||
// regular checks should be carried out to see if the building needs to be contaminated
|
||||
// Buildings that have been reset or decontaminated will be recontaminated as long as the nuclear weapon is still present
|
||||
|
||||
const auto aesItemViews = m_ddsHandler->dtcAes()->aesItemViews();
|
||||
for (const auto &aesItemView : qAsConst(aesItemViews))
|
||||
{
|
||||
if (aesItemView.effectStateId() == AreaEffectSimulation::AesEffectState::EsActivated)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Wirkfeld aesItemView.id()=" << aesItemView.id()
|
||||
<< " aesItemView.aesItemId()=" << aesItemView.aesItemId()
|
||||
<< " fuer Gebaeude " << data.id() << " neu berechnen";
|
||||
|
||||
double chargeHeight = 0.0;
|
||||
double chargeDepression = 0.0;
|
||||
|
||||
if (aesItemView.aesTypeId() == AreaEffectSimulation::AesType_def::AtNContamination)
|
||||
{
|
||||
chargeHeight = 500.0; // Alle Stockwerke beruecksichtigen
|
||||
chargeDepression = -1000.0; // Alle Kellerraeume beruecksichtigen
|
||||
DEBUG_LOG(m_logger) << "AtNContamination: chargeHeight=" << chargeHeight
|
||||
<< " chargeDepression=" << chargeDepression;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_aesBCContaminations.contains(aesItemView.aesItemId()))
|
||||
{
|
||||
chargeHeight = m_aesBCContaminations.value(aesItemView.aesItemId()).upperOffset();
|
||||
chargeDepression = m_aesBCContaminations.value(aesItemView.aesItemId()).lowerOffset();
|
||||
DEBUG_LOG(m_logger) << "BCContaminations: chargeHeight=" << chargeHeight
|
||||
<< " chargeDepression=" << chargeDepression;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "BCContaminations: m_aesBCContaminations not contains:"<< aesItemView.aesItemId();
|
||||
}
|
||||
}
|
||||
|
||||
// [GUEZE-2527] Fehler bei A-Waffen und Dekontaminierung
|
||||
auto dtcIsm = m_ddsHandler->dtcIsm();
|
||||
int exerciseId = m_ddsHandler->getExerciseId();
|
||||
QPolygonF polygonGeo;
|
||||
polygonGeo.reserve(aesItemView.form().size());
|
||||
// Convert Form to UTM
|
||||
for (const auto point : aesItemView.form())
|
||||
polygonGeo.append(QPointF(point.lon(), point.lat()));
|
||||
bool completeEnclosed = true;
|
||||
bool isGroundLevel = false;
|
||||
|
||||
const QVector<int> &buildingIds = dtcIsm.get()->getBuildingByPolygon(exerciseId, polygonGeo, completeEnclosed, isGroundLevel);
|
||||
if (buildingIds.contains(data.id() ))
|
||||
calculateBuilding(data.id(), aesItemView, chargeHeight, chargeDepression);
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "Building not in Area BuildingId=" << data.id();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HandlerContamination::setBuildingContaminationStateRequest(int buildingId,
|
||||
int aesId,
|
||||
ProjectDataManagement::VulnerabilityState vulnerabilityState,
|
||||
QVector<int> rooms)
|
||||
{
|
||||
Buildings::ContaminationState contaminationState;
|
||||
|
||||
contaminationState.aesId(aesId);
|
||||
contaminationState.vulnerabilityState(vulnerabilityState);
|
||||
// contaminationState.vulne
|
||||
|
||||
DEBUG_LOG(m_logger) << "setBuildingContaminationStateRequest"
|
||||
<< " buildingId=" << buildingId
|
||||
<< " aesId=" << aesId
|
||||
<< " vulnerabilityState=" << vulnerabilityState
|
||||
<< " rooms.size=" << rooms.size();
|
||||
contaminationState.rooms().resize(rooms.size());
|
||||
for (int i = 0; i < rooms.size(); i++)
|
||||
{
|
||||
contaminationState.rooms()[i] = rooms[i];
|
||||
contaminationState.vulnerabilityState(vulnerabilityState);
|
||||
DEBUG_LOG(m_logger) << " room[" << i << "]=" << rooms[i];
|
||||
}
|
||||
|
||||
Buildings::SetBuildingContaminationStateRequest requestContamination(
|
||||
buildingId,
|
||||
contaminationState
|
||||
);
|
||||
// Senden, wenn fuer das Gebaeude noch keine Contamination vorhanden ist.
|
||||
if (!m_contaminationState.contains(buildingId))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Neue Kontamination BuildingId=" << buildingId
|
||||
<< " requestContamination aesId=" << requestContamination.contaminationState().aesId();
|
||||
|
||||
m_ddsHandler->ftcBld()->setBuildingContaminationStateRequest(requestContamination, this);
|
||||
m_contaminationState.insert(buildingId, requestContamination);
|
||||
return;
|
||||
}
|
||||
// Senden, wenn sich die Kontamination geaendert hat.
|
||||
Buildings::SetBuildingContaminationStateRequest lastRequestContamination = m_contaminationState.value(buildingId);
|
||||
if (lastRequestContamination != requestContamination)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Änderung der Kontamination BuildingId=" << buildingId
|
||||
<< " aesId=" << requestContamination.contaminationState().aesId();
|
||||
m_ddsHandler->ftcBld()->setBuildingContaminationStateRequest(requestContamination, this);
|
||||
m_contaminationState.insert(buildingId, requestContamination);
|
||||
return;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "Keine Änderung der Kontamination BuildingId=" << buildingId;
|
||||
}
|
||||
|
||||
QVector<int> HandlerContamination::getEffectedFloors(const int buildingId, const int chargeHeight, const int depression)
|
||||
{
|
||||
auto dtcIsm = m_ddsHandler->dtcIsm();
|
||||
DEBUG_LOG(m_logger) << "Contaminated-Building=" << buildingId
|
||||
<< " chargeHeight=" << chargeHeight
|
||||
<< " depression=" << depression;
|
||||
|
||||
const QVector<int> &floorIds = dtcIsm->getFloorIdsFromBuilding(buildingId);
|
||||
QVector<int> effectedFloorIds;
|
||||
effectedFloorIds.reserve(floorIds.size());
|
||||
for (int floorId : qAsConst(floorIds))
|
||||
{
|
||||
double halfFloorHeight = dtcIsm->getHalfFloorHeight(buildingId, floorId);
|
||||
DEBUG_LOG(m_logger) << " floorId=" << floorId
|
||||
<< " halfFloorHeight=" << halfFloorHeight
|
||||
<< " chargeHeight=" << chargeHeight
|
||||
<< " depression=" << depression;
|
||||
if (depression < 0) // Kellerraeme beruecksichtigen
|
||||
{
|
||||
if (halfFloorHeight > depression)
|
||||
DEBUG_LOG(m_logger) << "Checke Obergrenze";
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "halfFloorHeight > depression floorId=" << floorId << " continue";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (halfFloorHeight < 0) // Kellerraeume nicht beruecksichtigen
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "depression ist nicht < 0"
|
||||
<< " Kelleretagen nicht beruecksichtigen floorId=" << floorId << " continue";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (halfFloorHeight < chargeHeight)
|
||||
effectedFloorIds.append(floorId);
|
||||
}
|
||||
return effectedFloorIds;
|
||||
}
|
||||
|
||||
void HandlerContamination::onSetBuildingContaminationStateReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
if (replyObject.error())
|
||||
WARNING_LOG(m_logger) << "Can not send ContaminationStates on building to building service: " << replyObject();
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "onSetBuildingContaminationStateReply for id " << replyObject.id() << " success\n"
|
||||
<< " replyObject.str() = " << replyObject.str();
|
||||
}
|
||||
|
||||
void HandlerContamination::onBCContaminationChanged(const AreaEffectSimulation::BCContamination &data, DataModification modType)
|
||||
{
|
||||
if ((modType == DataModification::eRemoved)
|
||||
|| data.isDeleted())
|
||||
m_aesBCContaminations.remove(data.id());
|
||||
else
|
||||
m_aesBCContaminations.insert(data.id(), data);
|
||||
}
|
||||
|
||||
// Returns true if the building is in the inner circle at the time of impact and should fail as a result.
|
||||
// Liefert true, wenn sich das Gebaeude beim Einschlag im inneren Kreis befindet und daraufhin ausfallen soll.
|
||||
bool HandlerContamination::isInsideInnerCircle(int buildingId, int aesId)
|
||||
{
|
||||
InfrastructureManagement::MainStructureElement mse = m_ddsHandler->dtcIsm()->mainStructureElement(buildingId);
|
||||
AreaEffectSimulation::NContamination nContamination = m_ddsHandler->dtcAes()->nContamination(aesId);
|
||||
|
||||
DEBUG_LOG(m_logger) << "isInsideInnerCircle borderLengthInner=" << nContamination.borderLengthInner()
|
||||
<< " borderLengthOuter=" << nContamination.borderLengthOuter()
|
||||
<< " impactRadius=" << nContamination.impactRadius();
|
||||
|
||||
int zone = -1;
|
||||
const QPointF impactPositionUtm = CentralEffectSimulation::geographic2Utm(nContamination.impactPosition(), zone);
|
||||
DEBUG_LOG(m_logger) << "impactPositionUtm=" << impactPositionUtm.x() << "/" << impactPositionUtm.y()
|
||||
<< " zone=" << zone;
|
||||
const QPointF buildingPositionUtm = CentralEffectSimulation::geographic2Utm(mse.geoPosition(), zone);
|
||||
DEBUG_LOG(m_logger) << "buildingPositionUtm=" << buildingPositionUtm.x() << "/" << buildingPositionUtm.y();
|
||||
|
||||
double squareDistance = CentralEffectSimulation::getSquareDistance(impactPositionUtm, buildingPositionUtm);
|
||||
|
||||
if (squareDistance < nContamination.impactRadius() * nContamination.impactRadius())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "isInsideInnerCircle return true";
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "isInsideInnerCircle return false";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the building is in the inner circle at the time of impact and should fail as a result.
|
||||
// Liefert true, wenn sich das Gebaeude beim Einschlag im inneren Kreis befindet und daraufhin ausfallen soll.
|
||||
bool HandlerContamination::isInsideBCContamination(int buildingId, int aesId)
|
||||
{
|
||||
InfrastructureManagement::MainStructureElement mse = m_ddsHandler->dtcIsm()->mainStructureElement(buildingId);
|
||||
//AreaEffectSimulation::NContamination nContamination = m_ddsHandler->dtcAes()->nContamination(aesId);
|
||||
AreaEffectSimulation::BCContamination bcContamination = m_ddsHandler->dtcAes()->bCContamination(aesId);
|
||||
|
||||
DEBUG_LOG(m_logger) << " impactRadius=" << bcContamination.impactRadius();
|
||||
|
||||
int zone = -1;
|
||||
const QPointF impactPositionUtm = CentralEffectSimulation::geographic2Utm(bcContamination.impactPosition(), zone);
|
||||
DEBUG_LOG(m_logger) << "impactPositionUtm=" << impactPositionUtm.x() << "/" << impactPositionUtm.y()
|
||||
<< " zone=" << zone;
|
||||
const QPointF buildingPositionUtm = CentralEffectSimulation::geographic2Utm(mse.geoPosition(), zone);
|
||||
DEBUG_LOG(m_logger) << "buildingPositionUtm=" << buildingPositionUtm.x() << "/" << buildingPositionUtm.y();
|
||||
|
||||
double squareDistance = CentralEffectSimulation::getSquareDistance(impactPositionUtm, buildingPositionUtm);
|
||||
|
||||
if (squareDistance < bcContamination.impactRadius() * bcContamination.impactRadius())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "isInsideInnerCircle return true";
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "isInsideInnerCircle return false";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the building is located in range 1 at the time of impact and is to be contaminated as a result.
|
||||
// Liefert true, wenn sich das Gebaeude beim Einschlag im Bereich 1 befindet und daraufhin kontaminiert werden soll.
|
||||
bool HandlerContamination::isInsideRange1(int buildingId, int aesId)
|
||||
{
|
||||
InfrastructureManagement::MainStructureElement mse = m_ddsHandler->dtcIsm()->mainStructureElement(buildingId);
|
||||
AreaEffectSimulation::NContamination nContamination = m_ddsHandler->dtcAes()->nContamination(aesId);
|
||||
|
||||
DEBUG_LOG(m_logger) << "isInsideRange1 borderLengthInner=" << nContamination.borderLengthInner()
|
||||
<< " borderLengthOuter=" << nContamination.borderLengthOuter()
|
||||
<< " impactRadius=" << nContamination.impactRadius();
|
||||
|
||||
int zone = -1;
|
||||
const QPointF impactPositionUtm = CentralEffectSimulation::geographic2Utm(nContamination.impactPosition(), zone);
|
||||
DEBUG_LOG(m_logger) << "impactPositionUtm=" << impactPositionUtm.x() << "/" << impactPositionUtm.y()
|
||||
<< " zone=" << zone;
|
||||
const QPointF buildingPositionUtm = CentralEffectSimulation::geographic2Utm(mse.geoPosition(), zone);
|
||||
DEBUG_LOG(m_logger) << "buildingPositionUtm=" << buildingPositionUtm.x() << "/" << buildingPositionUtm.y();
|
||||
|
||||
double squareDistance = CentralEffectSimulation::getSquareDistance(impactPositionUtm, buildingPositionUtm);
|
||||
|
||||
if (squareDistance < nContamination.borderLengthInner() * nContamination.borderLengthInner())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "isInsideRange1 return true";
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "isInsideRange1 return false";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace CesBuildings
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CentralEffectSimulation/logger.h>
|
||||
|
||||
#include <AreaEffectSimulation/aes_dtc.h>
|
||||
#include <Buildings/bld_dtc.h>
|
||||
#include <Buildings/bld_ftc.h>
|
||||
#include <ProjectDataManagement/pdm_dtc.h>
|
||||
#include <TrainingAreaBase/tab_ftc.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QVector>
|
||||
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
class QPoint3D;
|
||||
}
|
||||
|
||||
// AES-Handling for buildings
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
|
||||
class HandlerContamination : public QObject
|
||||
, protected Buildings::Interface::Ftc::SetBuildingContaminationStateReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HandlerContamination(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~HandlerContamination();
|
||||
|
||||
bool init();
|
||||
|
||||
protected:
|
||||
void onSetBuildingContaminationStateReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
private slots:
|
||||
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
|
||||
void onBuildingStateChanged(const Buildings::BuildingState &data, DataModification modType);
|
||||
void onBCContaminationChanged(const AreaEffectSimulation::BCContamination &data, DataModification modType);
|
||||
|
||||
private:
|
||||
QVector<int> getEffectedFloors(const int buildingId, const int chargeHeight, const int depression);
|
||||
void setBuildingContaminationStateRequest(int buildingId,
|
||||
int aesId,
|
||||
ProjectDataManagement::VulnerabilityState vulnerabilityState,
|
||||
QVector<int> rooms);
|
||||
bool isInsideInnerCircle(int buildingId, int aesId);
|
||||
bool isInsideRange1(int buildingId, int aesId);
|
||||
bool isInsideBCContamination(int buildingId, int aesId);
|
||||
void calculateBuilding(int buildingId,
|
||||
const AreaEffectSimulation::AesItemView &data,
|
||||
double chargeHeight,
|
||||
double chargeDepression);
|
||||
|
||||
private:
|
||||
QHash<int, AreaEffectSimulation::BCContamination> m_aesBCContaminations; // key = aesItemId
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> m_handlerBuildingData;
|
||||
QMap<int, Buildings::SetBuildingContaminationStateRequest> m_contaminationState; // Key = BuildingId
|
||||
|
||||
CentralEffectSimulation::LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
} // namespace CesBuildings
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Plugin Building Ownership
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include <CentralEffectSimulation/proxy_building.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> CesBuildingsPlugin::createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
CentralEffectSimulation::MainHandler *mainHandler)
|
||||
{
|
||||
return std::make_shared<CesBuildingsInterfaceImpl>(pdp, dDSConnector, settings, mainHandler);
|
||||
}
|
||||
|
||||
|
||||
CesBuildingsInterfaceImpl::CesBuildingsInterfaceImpl(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_handlerBuildingData(m_mainHandler->handlerBuildingData())
|
||||
, m_handlerParticipant(m_mainHandler->handlerParticipant())
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.Buildings.CesBuildingsInterfaceImpl"))
|
||||
{
|
||||
Q_UNUSED(settings)
|
||||
}
|
||||
|
||||
CesBuildingsInterfaceImpl::~CesBuildingsInterfaceImpl()
|
||||
{
|
||||
m_handlerBuildingOwnership.reset();
|
||||
m_handlerAesData.reset();
|
||||
m_handlerContaminations.reset();
|
||||
}
|
||||
|
||||
|
||||
bool CesBuildingsInterfaceImpl::init(int domainId, int exerciseId)
|
||||
{
|
||||
m_domainId = domainId;
|
||||
m_exerciseId = exerciseId;
|
||||
INFO_LOG(m_logger) << "CesBuildingsInterfaceImpl::init()"
|
||||
<< " m_domainId=" << m_domainId
|
||||
<< " m_exerciseId=" << m_exerciseId;
|
||||
|
||||
|
||||
// initialize handlerBuildingOwnership
|
||||
INFO_LOG(m_logger) << "initialize handlerBuildingOwnership ----------------------------";
|
||||
m_handlerBuildingOwnership = std::make_shared<HandlerBuildingOwnership>(m_ddsHandler,
|
||||
m_handlerParticipant,
|
||||
m_handlerBuildingData,
|
||||
m_db,
|
||||
this);
|
||||
|
||||
|
||||
if (!m_handlerBuildingOwnership->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation m_handlerBuildingOwnership failed.";
|
||||
return false;
|
||||
}
|
||||
INFO_LOG(m_logger) << "end initialize handlerBuildingOwnership ----------------------------";
|
||||
|
||||
// initialize handlerAesData
|
||||
INFO_LOG(m_logger) << "initialize handlerAesData ----------------------------";
|
||||
m_handlerAesData = std::make_shared<HandlerAesData>(m_ddsHandler,
|
||||
m_handlerBuildingData,
|
||||
this);
|
||||
if (!m_handlerAesData->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation m_handlerAesData failed.";
|
||||
return false;
|
||||
}
|
||||
INFO_LOG(m_logger) << "end initialize HandlerAesData ----------------------------";
|
||||
|
||||
// initialize handlerAesData
|
||||
INFO_LOG(m_logger) << "initialize handlerContaminations ----------------------------";
|
||||
m_handlerContaminations = std::make_shared<HandlerContamination>(m_ddsHandler,
|
||||
this);
|
||||
|
||||
if (!m_handlerContaminations->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation m_handlerContaminations failed.";
|
||||
return false;
|
||||
}
|
||||
INFO_LOG(m_logger) << "end initialize HandlerContaminations ----------------------------";
|
||||
|
||||
|
||||
// initialize handlerBuildingModel
|
||||
INFO_LOG(m_logger) << "initialize handlerBuildingModel ----------------------------";
|
||||
m_handlerBuildingModel = std::make_shared<HandlerBuildingModel>(m_ddsHandler,
|
||||
m_handlerAesData,
|
||||
this);
|
||||
if (!m_handlerBuildingModel->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation m_handlerBuildingModel failed.";
|
||||
return false;
|
||||
}
|
||||
INFO_LOG(m_logger) << "end initialize handlerBuildingModel ----------------------------";
|
||||
|
||||
|
||||
// Maybe not all MainStructureElements are processed yet.
|
||||
// So give MainEventLoop time to finish their processing:
|
||||
|
||||
// suggest Qtimer::singleShot()
|
||||
QTimer::singleShot(1000, this, [this]()
|
||||
{
|
||||
std::shared_ptr<CentralEffectSimulation::ProxyBuilding> proxyBuilding = m_mainHandler->proxyBuilding();
|
||||
if (proxyBuilding)
|
||||
{
|
||||
INFO_LOG(m_logger) << "set_handlerBuildingModel ----------------------------";
|
||||
proxyBuilding->set_handlerBuildingModel(m_handlerBuildingModel);
|
||||
}
|
||||
});
|
||||
|
||||
INFO_LOG(m_logger) << "CesBuildingsInterfaceImpl::init() return true";
|
||||
return true;
|
||||
}
|
||||
|
||||
QString CesBuildingsInterfaceImpl::echo(const QString &message)
|
||||
{
|
||||
QString ret(QStringLiteral("<<<< %1 >>>> CentralEffectSimulationBuildingOwnershipInterfaceImpl::echo").arg(message));
|
||||
INFO_LOG(m_logger) << "CentralEffectSimulationBuildingOwnershipInterfaceImpl::echo return:" << ret;
|
||||
DEBUG_LOG(m_logger) << "DEBUG: CentralEffectSimulationBuildingOwnershipInterfaceImpl::echo return:" << ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} //namespace CesBuildings
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Plugin Building Ownership
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../proxy_building.h"
|
||||
|
||||
#include "handler_building_ownership.h"
|
||||
#include "handler_aes_data.h"
|
||||
#include "handler_building_model.h"
|
||||
#include "handler_contamination.h"
|
||||
|
||||
#include <CentralEffectSimulation/logger.h>
|
||||
#include <CentralEffectSimulation/ces_plugin_interface.h>
|
||||
#include <CentralEffectSimulation/main_handler.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
|
||||
namespace CesBuildings
|
||||
{
|
||||
|
||||
class CesBuildingsPlugin : public QObject, public CentralEffectSimulation::Plugin::Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "special:3:ces.CentralEffectSimulationBuildingOwnershipPlugin")
|
||||
Q_INTERFACES(CentralEffectSimulation::Plugin::Plugin)
|
||||
|
||||
public:
|
||||
CesBuildingsPlugin() = default;
|
||||
~CesBuildingsPlugin() = 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 CesBuildingsInterfaceImpl final : public CentralEffectSimulation::Plugin::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CesBuildingsInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
CentralEffectSimulation::MainHandler *mainHandler);
|
||||
~CesBuildingsInterfaceImpl();
|
||||
//bool init();
|
||||
const char *name() const override { return "CentralEffectSimulationBuildingOwnership"; }
|
||||
QString echo(const QString &message) override;
|
||||
|
||||
void set_handlerBuildingModel(CentralEffectSimulation::ProxyBuilding *proxy);
|
||||
|
||||
|
||||
private Q_SLOTS:
|
||||
bool init(int domainId, int exerciseId) override;
|
||||
private:
|
||||
|
||||
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::HandlerBuildingData> m_handlerBuildingData; ///< Pointer to AES Building handler
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant; ///< Pointer to handler for all participants
|
||||
std::shared_ptr<HandlerContamination> m_handlerContaminations;
|
||||
std::shared_ptr<HandlerBuildingOwnership> m_handlerBuildingOwnership; ///< Pointer to handler for Building Ownership
|
||||
std::shared_ptr<HandlerAesData> m_handlerAesData;
|
||||
std::shared_ptr<HandlerBuildingModel> m_handlerBuildingModel;
|
||||
|
||||
|
||||
CentralEffectSimulation::LOGGER_T m_logger;
|
||||
int m_domainId{0};
|
||||
int m_exerciseId{0};
|
||||
};
|
||||
|
||||
} // namespace CesBuildings
|
||||
@@ -0,0 +1,49 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
ADD_SUBDIRECTORY(Basic)
|
||||
|
||||
|
||||
IF(UNIX AND "${_pname}" STREQUAL "l400p2")
|
||||
MESSAGE("Install plugins for CES PROJECT=l400p2")
|
||||
ADD_SUBDIRECTORY(TargetAreas)
|
||||
ENDIF()
|
||||
|
||||
IF(UNIX AND "${_pname}" STREQUAL "ahtc")
|
||||
MESSAGE("Install plugins for CES PROJECT=ahtc")
|
||||
#ADD_SUBDIRECTORY(Ces2D)
|
||||
ADD_SUBDIRECTORY(GeoPairing)
|
||||
#ADD_SUBDIRECTORY(GasPipes)
|
||||
ADD_SUBDIRECTORY(Buildings)
|
||||
ENDIF()
|
||||
|
||||
|
||||
IF(UNIX AND "${_pname}" STREQUAL "guez")
|
||||
MESSAGE("Install plugins for CES PROJECT=guez")
|
||||
#ADD_SUBDIRECTORY(Ces2D) ## Ces2D is outdated
|
||||
ADD_SUBDIRECTORY(VirtualMines)
|
||||
ADD_SUBDIRECTORY(Buildings)
|
||||
ADD_SUBDIRECTORY(ParticipantBuildings)
|
||||
ADD_SUBDIRECTORY(GeoPairing)
|
||||
ADD_SUBDIRECTORY(ArtillerySound)
|
||||
#ADD_SUBDIRECTORY(Smart)
|
||||
ADD_SUBDIRECTORY(MineAreas)
|
||||
ADD_SUBDIRECTORY(NBC)
|
||||
ADD_SUBDIRECTORY(FunctionalAreas)
|
||||
ADD_SUBDIRECTORY(Explosions)
|
||||
ADD_SUBDIRECTORY(Jamming)
|
||||
ADD_SUBDIRECTORY(MissionPlan)
|
||||
ADD_SUBDIRECTORY(MineLayingArtillery)
|
||||
ENDIF()
|
||||
|
||||
|
||||
|
||||
IF(UNIX AND "${_pname}" STREQUAL "qatar")
|
||||
MESSAGE("Install plugins for CES PROJECT=qatar")
|
||||
ADD_SUBDIRECTORY(Ces2D)
|
||||
ADD_SUBDIRECTORY(Buildings)
|
||||
ENDIF()
|
||||
|
||||
#ADD_SUBDIRECTORY(ECHO)
|
||||
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# monitoring of the target areas
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(SRCS
|
||||
plugin.cpp
|
||||
plugin.h
|
||||
handler_aes_data.cpp
|
||||
handler_aes_data.h
|
||||
handler_participant_area.cpp
|
||||
handler_participant_area.h
|
||||
settings.cpp
|
||||
settings.h
|
||||
logger.cpp
|
||||
logger.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV cesPluginCes2D MODULE ${SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(cesPluginCes2D
|
||||
PUBLIC
|
||||
Qt5::Network
|
||||
Qt5::Widgets
|
||||
cesPluginInterface
|
||||
ngldb
|
||||
svcCesDDSCommon
|
||||
# ProjectConfig
|
||||
)
|
||||
NGL_INSTALL_TARGET(cesPluginCes2D)
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Export definitions
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hanna E. Rathje, SLSE, 2015-08-04
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef CES_COMMON_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define CES_COMMON_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_SVCCESCOMMON_LIB)
|
||||
# define CES_COMMON_EXPORT Q_DECL_EXPORT
|
||||
# ifndef WIN32
|
||||
# ifdef NDDSUSERDllExport
|
||||
# undef NDDSUSERDllExport
|
||||
# endif
|
||||
# define NDDSUSERDllExport Q_DECL_EXPORT
|
||||
# endif
|
||||
# else
|
||||
# define CES_COMMON_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CES_CLIENT_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define CES_CLIENT_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_SVCCESCLIENT_LIB)
|
||||
# define CES_CLIENT_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define CES_CLIENT_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CES_SERVER_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define CES_SERVER_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_SVCCESSERVER_LIB)
|
||||
# define CES_SERVER_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define CES_SERVER_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
@@ -0,0 +1,454 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#include "handler_aes_data.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
|
||||
#include <QPainterPath>
|
||||
#include <QPointF>
|
||||
#include <QPolygonF>
|
||||
#include <QTimer>
|
||||
#include <QTransform>
|
||||
|
||||
#include <LtsUtilsCore/dds_bitarray.h>
|
||||
#include <LtsUtilsCore/qpoint3d.h>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
|
||||
namespace Ces2D
|
||||
{
|
||||
|
||||
HandlerAesData::HandlerAesData(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &buildingDataHandler,
|
||||
QObject *parent)
|
||||
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_handlerBuildingData(buildingDataHandler)
|
||||
, m_logger(getLogger("HandlerAesData"))
|
||||
{
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HandlerAesData::~HandlerAesData()
|
||||
{
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HandlerAesData::init()
|
||||
{
|
||||
auto dtcAes = m_ddsHandler->dtcAes();
|
||||
auto dtcIsm = m_ddsHandler->dtcIsm();
|
||||
auto ftcTab = m_ddsHandler->ftcTab();
|
||||
dtcIsm->enableMainFootprint();
|
||||
dtcAes->enableAirSupportImpact();
|
||||
dtcAes->waitForHistoricalDataExplosionSingleCentral(20000);
|
||||
ftcTab->enableSendCesHitInformation();
|
||||
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::explosionSingleChanged,
|
||||
this, &HandlerAesData::onExplosionSingleChanged);
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::airSupportImpactChanged,
|
||||
this, &HandlerAesData::onAirSupportImpactChanged);
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::triggeredImpactsChanged,
|
||||
this, &HandlerAesData::onTriggeredImpactsChanged);
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
|
||||
this, &HandlerAesData::onAesItemViewChanged);
|
||||
connect(dtcIsm.get(), &InfrastructureManagement::Interface::Dtc::mainFootprintChanged,
|
||||
this, &HandlerAesData::onMainFootprintChanged);
|
||||
|
||||
// Get 'static' data for all MainFootprints
|
||||
{
|
||||
auto cb = [this](const InfrastructureManagement::MainFootprint & mfp)
|
||||
{
|
||||
onMainFootprintChanged(mfp, DataModification::eAdded);
|
||||
};
|
||||
if (!dtcIsm->mainFootprints(cb))
|
||||
return false;
|
||||
}
|
||||
// Get 'static' data for all AesItemView
|
||||
{
|
||||
auto cb = [this](const AreaEffectSimulation::AesItemView & aiv)
|
||||
{
|
||||
onAesItemViewChanged(aiv, DataModification::eAdded);
|
||||
};
|
||||
if (!dtcAes->aesItemViews(cb))
|
||||
return false;
|
||||
}
|
||||
|
||||
//Get AesNames for all Danger Areas
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::dangerAreaChanged,
|
||||
this, cbGetNames);
|
||||
dtcAes->dangerAreas(cbGetNames);
|
||||
|
||||
//Get AesNames for all Nuclear Contaminations
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::nContaminationChanged,
|
||||
this, cbGetNames);
|
||||
dtcAes->nContaminations(cbGetNames);
|
||||
|
||||
//Get AesNames for all Mine Areas
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::mineAreaChanged,
|
||||
this, cbGetNames);
|
||||
dtcAes->mineAreas(cbGetNames);
|
||||
|
||||
//Get AesNames for all Functionsl Areas
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::functionalAreaChanged,
|
||||
this, cbGetNames);
|
||||
dtcAes->functionalAreas(cbGetNames);
|
||||
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
// ///////////////////////////////////
|
||||
// A E S (AreaEffectSimulation)
|
||||
// ///////////////////////////////////
|
||||
|
||||
void HandlerAesData::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
|
||||
{
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got AesItemView: " << data.effectStateId();
|
||||
switch (data.effectStateId().underlying())
|
||||
{
|
||||
case AreaEffectSimulation::AesEffectState_def::EsUnknown:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsError:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsExpired:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsRemoved:
|
||||
removeStates(data);
|
||||
m_aesItemViews.remove(data.aesItemId());
|
||||
break;
|
||||
case AreaEffectSimulation::AesEffectState_def::EsPrepared:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsPaused:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsActivated:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsFired:
|
||||
m_aesItemViews.insert(data.aesItemId(), data);
|
||||
break;
|
||||
case AreaEffectSimulation::AesEffectState_def::EsCreated:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsReceived:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HandlerAesData::removeStates(const AreaEffectSimulation::AesItemView &data)
|
||||
{
|
||||
if (data.aesTypeId() != AreaEffectSimulation::AesType_def::AtExplosionArea)
|
||||
return;
|
||||
DEBUG_LOG(m_logger) << "Remove aesItemId=" << data.aesItemId();
|
||||
// remove State for each building
|
||||
for (BitfieldStates &bfs : m_bitfieldStatesBld)
|
||||
bfs.remove(data.aesItemId());
|
||||
} // end removeStates
|
||||
|
||||
void HandlerAesData::onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType)
|
||||
{
|
||||
bool handleExplosion = false;
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
{
|
||||
m_explosionSingleState.remove(data.id());
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsRemoved)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Remove SingleExplosion";
|
||||
m_explosionSingleState.remove(data.id());
|
||||
return;
|
||||
}
|
||||
// Only handle transitions from prepared to activated
|
||||
if (m_explosionSingleState.value(data.id()) == AreaEffectSimulation::AesEffectState_def::EsPrepared
|
||||
&& data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsActivated)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Handle SingleExplosion";
|
||||
handleExplosion = true;
|
||||
}
|
||||
m_explosionSingleState.insert(data.id(), data.effectStateId());
|
||||
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got ExplosionSingle";
|
||||
if (handleExplosion)
|
||||
{
|
||||
const double impactRadius = m_ddsHandler->chargeTypeRadius(data.chargeTypeId());
|
||||
DEBUG_LOG(m_logger) << "Handle ExplosionSingle (EsActivated)";
|
||||
|
||||
// Bounding-Box-Check
|
||||
// QMap<int, Footprint> m_footprints;
|
||||
for (const Footprint &footprint : qAsConst(m_footprints))
|
||||
{
|
||||
const QPointF impactPos(CentralEffectSimulation::geographic2Utm(data.impactPosition(), footprint.zone));
|
||||
const QPolygonF polyBldgRadius({QPointF(footprint.boundingBoxPolyUtm.bottomLeft().rx() - impactRadius,
|
||||
footprint.boundingBoxPolyUtm.bottomLeft().ry() + impactRadius),
|
||||
QPointF(footprint.boundingBoxPolyUtm.topRight().rx() + impactRadius,
|
||||
footprint.boundingBoxPolyUtm.bottomLeft().ry() + impactRadius),
|
||||
QPointF(footprint.boundingBoxPolyUtm.topRight().rx() + impactRadius,
|
||||
footprint.boundingBoxPolyUtm.topRight().ry() - impactRadius),
|
||||
QPointF(footprint.boundingBoxPolyUtm.bottomLeft().rx() - impactRadius,
|
||||
footprint.boundingBoxPolyUtm.topRight().ry() - impactRadius)});
|
||||
if (polyBldgRadius.containsPoint(impactPos, Qt::OddEvenFill))
|
||||
{
|
||||
//calculateImpacts(data, footprint.mseId);
|
||||
// check, if impact-pos + munition-radius touch the building
|
||||
// get radius of munition
|
||||
const Core::GeoPosition2D impactPosition(data.impactPosition().lon(), data.impactPosition().lat());
|
||||
if (inFootprint(impactPosition, impactRadius, footprint))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "ftc sendCESHitOnBuilding mseId = " << footprint.mseId
|
||||
<< " chargeTypeId = " << data.chargeTypeId()
|
||||
<< " id = " << data.id()
|
||||
<< " currentPartitionTime = " << m_ddsHandler->currentPartitionTime()
|
||||
<< " impactPosition.lon = " << impactPosition.lon()
|
||||
<< " impactPosition.lat = " << impactPosition.lat();
|
||||
|
||||
Buildings::SendCesHitOnBuildingRequest requestBld(
|
||||
footprint.mseId,
|
||||
data.chargeTypeId(),
|
||||
data.id(),
|
||||
m_ddsHandler->currentPartitionTime(),
|
||||
Core::GeoPosition(impactPosition.lon(), impactPosition.lat(), 0.0));
|
||||
m_ddsHandler->ftcBld()->sendCesHitOnBuildingRequest(requestBld, this);
|
||||
}
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "Not sendCESHitOnBuilding mseId = " << footprint.mseId;
|
||||
|
||||
DEBUG_LOG(m_logger) << "boundingBoxImpact.contains(footprint)";
|
||||
}
|
||||
} // for
|
||||
}
|
||||
} // onExplosionSingleChanged
|
||||
|
||||
void HandlerAesData::onAirSupportImpactChanged(const AreaEffectSimulation::AirSupportImpact &data, DataModification modType)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Got onAirSupportImpactChanged()";
|
||||
AreaEffectSimulation::ExplosionSingle esData;
|
||||
esData.id(data.id());
|
||||
esData.chargeTypeId(data.chargeTypeId());
|
||||
esData.impactPosition(data.impactPosition());
|
||||
esData.effectStateId(data.effectStateId());
|
||||
onExplosionSingleChanged(esData, modType);
|
||||
} // onExplosionSingleChanged
|
||||
|
||||
void HandlerAesData::onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType)
|
||||
{
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got TriggeredImpacts";
|
||||
preCalculateImpacts(data);
|
||||
}
|
||||
|
||||
// ///////////////////////////////////
|
||||
// I S M (InfrastructureManagement)
|
||||
// ///////////////////////////////////
|
||||
void HandlerAesData::onMainFootprintChanged(const InfrastructureManagement::MainFootprint &data, DataModification modType)
|
||||
{
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eAdded:
|
||||
case DataModification::eModified:
|
||||
DEBUG_LOG(m_logger) << "Got MainFootprint (Building)";
|
||||
calculateFootprint(data);
|
||||
break;
|
||||
case DataModification::eRemoved:
|
||||
m_footprints.remove(data.id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ///////////////////////////////////
|
||||
// Calculations:
|
||||
// ///////////////////////////////////
|
||||
|
||||
void HandlerAesData::calculateFootprint(const InfrastructureManagement::MainFootprint &mainFootprint)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Footprint: " << mainFootprint.id() << ": " << mainFootprint;
|
||||
DEBUG_LOG(m_logger) << "Footprint: " << " mainFootprint.elements().size()=" << mainFootprint.elements().size();
|
||||
|
||||
// If poly is Empty continue with next Footprint
|
||||
if (mainFootprint.elements().size() <= 0)
|
||||
return;
|
||||
|
||||
const InfrastructureManagement::MainStructureElement mse
|
||||
= m_handlerBuildingData->mainStructureElement(mainFootprint.id());
|
||||
if (mse.id() != mainFootprint.id())
|
||||
{
|
||||
// not (yet) there
|
||||
QTimer::singleShot(1000, this, [this, mainFootprint]() { calculateFootprint(mainFootprint); });
|
||||
return;
|
||||
}
|
||||
|
||||
// insert all Points to poly
|
||||
QPolygonF poly;
|
||||
poly.reserve(mainFootprint.elements().size());
|
||||
for (const InfrastructureManagement::FootprintElement &element : mainFootprint.elements())
|
||||
{
|
||||
const auto &relPos = element.relPosition();
|
||||
poly.push_back(QPointF(relPos.offsetX(), relPos.offsetY()));
|
||||
}
|
||||
|
||||
// rotate poly
|
||||
QTransform trans;
|
||||
trans.rotate(mse.angle());
|
||||
poly = trans.map(poly);
|
||||
|
||||
Footprint footprint;
|
||||
footprint.mseId = mainFootprint.id();
|
||||
footprint.geoPosition = mse.geoPosition();
|
||||
const QPointF utmFpPosition = CentralEffectSimulation::geographic2Utm(footprint.geoPosition, &footprint.zone);
|
||||
footprint.polyUtm.reserve(poly.size());
|
||||
for (const QPointF &point : qAsConst(poly))
|
||||
footprint.polyUtm.push_back(utmFpPosition + point);
|
||||
footprint.boundingBoxPolyUtm = footprint.polyUtm.boundingRect();
|
||||
|
||||
m_footprints.insert(footprint.mseId, footprint);
|
||||
}
|
||||
|
||||
bool HandlerAesData::inFootprint(const Core::GeoPosition2D &geoPosition, const double radius, const Footprint &footPrint) const
|
||||
{
|
||||
const QPointF impact(CentralEffectSimulation::geographic2Utm(geoPosition, footPrint.zone));
|
||||
|
||||
if (m_logger.isDebugEnabled())
|
||||
{
|
||||
const QPointF utmBuilding(CentralEffectSimulation::geographic2Utm(footPrint.geoPosition, footPrint.zone));
|
||||
DEBUG_LOG(m_logger) << "Impact (x/y)=" << CentralEffectSimulation::debug(impact - utmBuilding);
|
||||
for (int i = 0; i < footPrint.polyUtm.length(); i++)
|
||||
DEBUG_LOG(m_logger) << " poly (x/y)=" << CentralEffectSimulation::debug(footPrint.polyUtm[i] - utmBuilding);
|
||||
}
|
||||
|
||||
// Check, if hit direct on building
|
||||
if (footPrint.polyUtm.containsPoint(impact, Qt::OddEvenFill))
|
||||
return true;
|
||||
|
||||
// Check, if hit in munition-radius
|
||||
QPainterPath ppFp;
|
||||
ppFp.addPolygon(footPrint.polyUtm);
|
||||
QPainterPath ppCircle;
|
||||
ppCircle.addEllipse(impact, radius, radius);
|
||||
return ppFp.intersects(ppCircle);
|
||||
}
|
||||
|
||||
void HandlerAesData::preCalculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data)
|
||||
{
|
||||
if (data.id() <= 0)
|
||||
return;
|
||||
DEBUG_LOG(m_logger) << "preCalculateImpacts";
|
||||
// Find AES ItemView and set Bounding-Box of Aes-Field
|
||||
|
||||
// Search corresponding itemView and get boundingBox data in UTM
|
||||
const bool bFound = m_aesItemViews.contains(data.aesItemId());
|
||||
if (!bFound)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not find item view for aes with id " << data.aesItemId();
|
||||
return;
|
||||
}
|
||||
// Bounding-Box-Check
|
||||
// QMap<int, Footprint> m_footprints;
|
||||
for (const Footprint &footprint : qAsConst(m_footprints))
|
||||
{
|
||||
//if (boundingBoxImpact.contains(footprint.boundingBoxPolyUtm))
|
||||
calculateImpacts(data, footprint);
|
||||
} // for
|
||||
|
||||
}
|
||||
|
||||
void HandlerAesData::onSendCesHitOnBuildingReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
if (replyObject.error())
|
||||
WARNING_LOG(m_logger) << "Can not send hit on building to building service: " << replyObject();
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "onSendCesHitOnBuildingReply for id " << replyObject.id() << " success\n"
|
||||
<< " replyObject.str() = " << replyObject.str();
|
||||
}
|
||||
|
||||
void HandlerAesData::onSendCesHitInformationReply(const Core::FunctionReplyObject &reply)
|
||||
{
|
||||
if (reply.error())
|
||||
WARNING_LOG(m_logger) << "onSendCesHitInformationReply for id " << reply.id() << " failed: " << reply.str();
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "onSendCesHitInformationReply for id " << reply.id() << " successful";
|
||||
}
|
||||
|
||||
// calculate impacts for one building
|
||||
void HandlerAesData::calculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data, const Footprint &footprint)
|
||||
{
|
||||
// check for correct AES type artillery only
|
||||
switch (data.aesTypeId().underlying())
|
||||
{
|
||||
case AreaEffectSimulation::AesType_def::AtExplosionArea:
|
||||
case AreaEffectSimulation::AesType_def::AtExplosionSingle:
|
||||
case AreaEffectSimulation::AesType_def::AtExplosionAreaSingleExplosions:
|
||||
DEBUG_LOG(m_logger) << "Calculate";
|
||||
break;
|
||||
default:
|
||||
DEBUG_LOG(m_logger) << "No Calculation";
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "calculateImpacts mseId=" << footprint.mseId << " data.aesItemId() " << data.aesItemId();
|
||||
|
||||
|
||||
// get position(s) of impact(s):
|
||||
|
||||
// Search corresponding itemView. If not available no impact to participant.
|
||||
auto it = m_aesItemViews.constFind(data.aesItemId());
|
||||
if (it == m_aesItemViews.constEnd())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "TriggeredExplosions.aesItemId=" << data.aesItemId() << " No aesItemView available";
|
||||
return;
|
||||
}
|
||||
|
||||
BitfieldStates &bitfieldStates = m_bitfieldStatesBld[footprint.mseId];
|
||||
QSet<int> &bitfieldState = bitfieldStates[data.aesItemId()];
|
||||
for (int i : qAsConst(bitfieldState))
|
||||
DEBUG_LOG(m_logger) << "bitfieldState for " << data.aesItemId() << ": " << i;
|
||||
|
||||
const AreaEffectSimulation::AesItemView &aesItemView = *it;
|
||||
for (int32_t bitFieldIdx = 0; bitFieldIdx < data.impactCount(); ++bitFieldIdx)
|
||||
{
|
||||
// no break, because every bit can be a hit
|
||||
if (LtsUtils::BitArray::testBit(data.bitfield(), bitFieldIdx))
|
||||
continue;
|
||||
|
||||
// get position of impact to corresponding bit
|
||||
if (aesItemView.form().size() <= size_t(bitFieldIdx))
|
||||
continue;
|
||||
|
||||
const Core::GeoPosition2D &impactPosition = aesItemView.form()[bitFieldIdx];
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION
|
||||
<< " impactPosition: lat/lon" << impactPosition.lat() << "/" << impactPosition.lon()
|
||||
<< " UTM=" << CentralEffectSimulation::debug(CentralEffectSimulation::geographic2Utm(impactPosition));
|
||||
|
||||
// check, if impact-pos + munition-radius touch the building
|
||||
// get radius of munition
|
||||
const double impactRadius = m_ddsHandler->chargeTypeRadius(aesItemView.chargeTypeId());
|
||||
if (inFootprint(impactPosition, impactRadius, footprint))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "In Footprint mseId = " << footprint.mseId;
|
||||
if (!bitfieldState.contains(bitFieldIdx))
|
||||
{
|
||||
bitfieldState.insert(bitFieldIdx);
|
||||
|
||||
DEBUG_LOG(m_logger) << "m_bitfieldStates.insert(data.aesItemId()=" << data.aesItemId() << ", bitfieldState)" << " bitFieldIdx=" << bitFieldIdx;
|
||||
|
||||
DEBUG_LOG(m_logger) << "ftc sendCESHitOnBuilding mseId = " << footprint.mseId << " bitFieldIdx= " << bitFieldIdx ;
|
||||
Buildings::SendCesHitOnBuildingRequest requestBld(
|
||||
footprint.mseId,
|
||||
aesItemView.chargeTypeId(),
|
||||
aesItemView.aesItemId(),
|
||||
m_ddsHandler->currentPartitionTime(),
|
||||
Core::GeoPosition(impactPosition.lon(), impactPosition.lat(), 0.0));
|
||||
m_ddsHandler->ftcBld()->sendCesHitOnBuildingRequest(requestBld, this);
|
||||
}
|
||||
}
|
||||
} // foreach Impact
|
||||
}
|
||||
|
||||
} // namespace Ces2D
|
||||
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <AreaEffectSimulation/aes_dtc.h>
|
||||
#include <Buildings/bld_dtc.h>
|
||||
#include <Buildings/bld_ftc.h>
|
||||
#include <ProjectDataManagement/pdm_dtc.h>
|
||||
#include <TrainingAreaBase/tab_ftc.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QVector>
|
||||
#include <QPolygonF>
|
||||
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
class QPoint3D;
|
||||
}
|
||||
|
||||
// AES-Handling for buildings
|
||||
|
||||
namespace Ces2D
|
||||
{
|
||||
|
||||
|
||||
class HandlerAesData : public QObject
|
||||
, protected Buildings::Interface::Ftc::SendCesHitOnBuildingReplyHandler
|
||||
, protected TrainingAreaBase::Interface::Ftc::SendCesHitInformationReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HandlerAesData(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &buildingDataHandler,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~HandlerAesData();
|
||||
|
||||
/**
|
||||
* Initialize the handler to manage information from player management
|
||||
*/
|
||||
bool init();
|
||||
AreaEffectSimulation::AesItemView itemView(const int &aesId) const { return m_aesItemViews.value(aesId); }
|
||||
|
||||
protected:
|
||||
void onSendCesHitOnBuildingReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void onSendCesHitInformationReply(const Core::FunctionReplyObject &reply) override final;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* Handle the signals from 'AES'
|
||||
*/
|
||||
void onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType);
|
||||
void onAirSupportImpactChanged(const AreaEffectSimulation::AirSupportImpact &data, DataModification modType);
|
||||
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
|
||||
void onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType);
|
||||
|
||||
/**
|
||||
* Handle MainFootprint from 'ISM'
|
||||
*/
|
||||
void onMainFootprintChanged(const InfrastructureManagement::MainFootprint &data, DataModification modType);
|
||||
|
||||
void removeStates(const AreaEffectSimulation::AesItemView &data);
|
||||
|
||||
private: // structs
|
||||
struct Footprint
|
||||
{
|
||||
int mseId = -1;
|
||||
int zone = -1;
|
||||
Core::GeoPosition geoPosition;
|
||||
QPolygonF polyUtm;
|
||||
QRectF boundingBoxPolyUtm;
|
||||
|
||||
bool isValid() const { return mseId > 0; }
|
||||
};
|
||||
|
||||
typedef QHash<int, QSet<int>> BitfieldStates;
|
||||
|
||||
private: // methoden
|
||||
void handleExplosionSingleCentral(const AreaEffectSimulation::AesItemView &itemView);
|
||||
|
||||
void calculateFootprint(const InfrastructureManagement::MainFootprint &mainFootprint);
|
||||
|
||||
bool inFootprint(const Core::GeoPosition2D &geoPosition, const double radius, const Footprint &footPrint) const;
|
||||
|
||||
void preCalculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data);
|
||||
void calculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data, const Footprint &footprint);
|
||||
double getRadiusOfMunition(const int32_t chargeTypeId) const;
|
||||
|
||||
|
||||
private: // attributes
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> m_handlerBuildingData;
|
||||
|
||||
QHash<int, Footprint> m_footprints; // key = footprint.mseId
|
||||
QHash<int, BitfieldStates> m_bitfieldStatesBld; // key = mseId, value = BitfieldState
|
||||
|
||||
// AES-Values
|
||||
QHash<int, AreaEffectSimulation::AesItemView> m_aesItemViews; // key = aesItemId
|
||||
QHash<int, AreaEffectSimulation::AesEffectState> m_explosionSingleState; // key = id value = state
|
||||
|
||||
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
|
||||
|
||||
};
|
||||
|
||||
} // namespace Ces2D
|
||||
|
||||
+1537
File diff suppressed because it is too large.
Load diff
+163
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "logger.h"
|
||||
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/aes_item_view_utm.h>
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
#include <handler_aes_data.h>
|
||||
#include <handler_building_model.h>
|
||||
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QQueue>
|
||||
#include <QtCore/QPointF>
|
||||
#include <QtGui/QPolygonF>
|
||||
|
||||
// AES-Handling for participants
|
||||
namespace Ces2D
|
||||
{
|
||||
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,
|
||||
};
|
||||
QString toString(EffectType et);
|
||||
|
||||
struct ParticipantDistance
|
||||
{
|
||||
double squareDistance = 0;
|
||||
CentralEffectSimulation::HandlerParticipant::CesParticipantData participantPosition;
|
||||
};
|
||||
|
||||
class HandlerParticipantArea : public QObject
|
||||
, protected TrainingAreaBase::Interface::Ftc::SendCesHitReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HandlerParticipantArea(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
const std::shared_ptr<HandlerAesData> &aesDataHandler,
|
||||
const std::shared_ptr<HandlerBuildingModel> &buildingModelHandler,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~HandlerParticipantArea();
|
||||
|
||||
/**
|
||||
* Initialize the handler to manage information from player management
|
||||
*/
|
||||
bool init();
|
||||
|
||||
protected:
|
||||
void onSendCesHitReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
private Q_SLOTS:
|
||||
/**
|
||||
* Handle the signals from 'AES'
|
||||
*/
|
||||
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
|
||||
void onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType);
|
||||
void onExplosionAreaChanged(const AreaEffectSimulation::ExplosionArea &data, DataModification modType);
|
||||
void onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType);
|
||||
void onExplosionSingleCentralChanged(const AreaEffectSimulation::ExplosionSingleCentral &data, DataModification modType);
|
||||
void onDusSingleMineChanged(const AreaEffectSimulation::DusSingleMine &data, DataModification modType);
|
||||
void onBCContaminationChanged(const AreaEffectSimulation::BCContamination &data, DataModification modType);
|
||||
void onNContaminationChanged(const AreaEffectSimulation::NContamination &data, DataModification modType);
|
||||
|
||||
private: // methoden
|
||||
void calculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data);
|
||||
void calculateImpacts(const CentralEffectSimulation::AesItemViewUtm &itemView,
|
||||
const QVector<int> &impactsToCheck,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition);
|
||||
void calculateBcContamination(const CentralEffectSimulation::AesItemViewUtm &itemView);
|
||||
void calculateFunctionArea(const CentralEffectSimulation::AesItemViewUtm &itemView);
|
||||
void deleteFunctionalArea(const int aesItemId);
|
||||
void calculateAesParticipant(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos);
|
||||
void calculateSmartExplosion(const AreaEffectSimulation::ExplosionSingle &data,
|
||||
const QHash<int, CentralEffectSimulation::HandlerParticipant::CesParticipantData> &participantPositions,
|
||||
qint64 impactTime);
|
||||
bool inMineRadiusCheck(const CentralEffectSimulation::AesItemViewUtm &itemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition);
|
||||
|
||||
bool inCircle(const QPointF ¢erUtm, const double radius, const QPointF &pointUtm);
|
||||
bool inBoundingBoxCheck(const CentralEffectSimulation::AesItemViewUtm &itemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition);
|
||||
bool inFormCheck(const CentralEffectSimulation::AesItemViewUtm &itemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition);
|
||||
void sendCesHitRequest(const CentralEffectSimulation::AesItemViewUtm &itemView,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
|
||||
qint64 effectTime,
|
||||
int remaining,
|
||||
int mineFieldBitIndex = 0);
|
||||
void sendCesHitRequest(const AreaEffectSimulation::AesItemView &itemView,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
|
||||
qint64 effectTime,
|
||||
int remaining,
|
||||
int mineFieldBitIndex = 0);
|
||||
void sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &itemView,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
|
||||
const ProjectDataManagement::EventType eventType);
|
||||
void sendEffectTypeEvent(const CentralEffectSimulation::AesItemViewUtm &itemView,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
|
||||
EffectType effectType,
|
||||
int mineFieldBitIndex,
|
||||
qint64 effectTime);
|
||||
|
||||
bool eventMustBeSend(int aesItemId,
|
||||
int participantId,
|
||||
const ProjectDataManagement::EventType eventType);
|
||||
|
||||
bool effectTypeMustBeSend(int aesItemId,
|
||||
int participantId,
|
||||
EffectType effectType,
|
||||
int mineFieldBitIndex,
|
||||
bool insideBuilding);
|
||||
|
||||
ProjectDataManagement::EventType leaveEventTypeForAesType(AreaEffectSimulation::AesType aesTypeId);
|
||||
EffectType leaveEffectTypeForAesType(AreaEffectSimulation::AesType aesTypeId);
|
||||
EffectType effectTypeForNContaminationArea(const CentralEffectSimulation::AesItemViewUtm &itemView, const QPointF &participantPosUtmPoint, qint64 partPosSampleTime);
|
||||
EffectType effectTypeForBCContaminationArea(const CentralEffectSimulation::AesItemViewUtm &itemView, const QPointF &participantPosUtmPoint);
|
||||
|
||||
void aesItemViewRemoved(int aesItemId);
|
||||
private: // attributes
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant;
|
||||
std::shared_ptr<HandlerAesData> m_handlerAesData;
|
||||
std::shared_ptr<HandlerBuildingModel> m_handlerBuildingModel;
|
||||
|
||||
QHash<int32_t, int> m_aesItemId2partIdMap;
|
||||
QHash<int, AreaEffectSimulation::TriggeredImpacts> m_triggeredImpacts; // key = aesItemId
|
||||
|
||||
|
||||
// AES-Values
|
||||
QHash<int, CentralEffectSimulation::AesItemViewUtm> m_aesItemViews; // key = aesItemId
|
||||
QQueue<TrainingAreaBase::SendCesHitRequest> m_sendCesHitRequestQueue;
|
||||
QHash<int, AreaEffectSimulation::AesEffectState> m_explosionSingleStates; // key = id value = state
|
||||
QHash<int, AreaEffectSimulation::AesEffectState> m_explosionSingleCentralStates;
|
||||
QHash<int, QHash<int, QSet<ProjectDataManagement::EventType>>> m_eventStates; // QHash<aesItemId, QHash<participantId, QSet<EventType>>>
|
||||
QHash<int, QHash<int, QSet<EffectType>>> m_effectTypeStates; // QHash<aesItemId, QHash<participantId, QSet<effectStates>>>
|
||||
QHash<int, QHash<int, QSet<int>>> m_effectTypeBitFieldIndexes; // QHash<aesItemId, QHash<participantId, QSet<mineFieldBitIdx>>>
|
||||
|
||||
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
|
||||
};
|
||||
} // namespace Ces2D
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Building Config - logging facility
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace Ces2D
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "CES.";
|
||||
std::string loggerName;
|
||||
const size_t len = strlen(name);
|
||||
loggerName.reserve(sizeof(ns) + len);
|
||||
loggerName.append(ns, sizeof(ns) - 1);
|
||||
loggerName.append(name, len);
|
||||
|
||||
try
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
|
||||
getNGLLogger(loggerName);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Ces2D
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Logging for CentralEffectSimulation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
#include "ces_export.h"
|
||||
|
||||
namespace Ces2D
|
||||
{
|
||||
using LOGGER_T = NGL::INGLLogger &;
|
||||
|
||||
CES_COMMON_EXPORT LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
} // namespace Ces2D
|
||||
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Plugin Ces2D
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
#include "settings.h"
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <ngldb/db_service_handler.h>
|
||||
|
||||
namespace Ces2D
|
||||
{
|
||||
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> CentralEffectSimulation2DPlugin::createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::DatabaseInterface> &db,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &handlerParticipant,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &handlerBuildingData)
|
||||
{
|
||||
return std::make_shared<Ces2DInterfaceImpl>(pdp, dDSConnector, settings, ddsHandler, db, handlerParticipant, handlerBuildingData);
|
||||
}
|
||||
|
||||
|
||||
Ces2DInterfaceImpl::Ces2DInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::DatabaseInterface> &db,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &handlerParticipant,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &handlerBuildingData)
|
||||
: m_pdp(pdp)
|
||||
, m_ddsConnector(dDSConnector)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_db(db)
|
||||
, m_handlerBuildingData(handlerBuildingData)
|
||||
, m_handlerParticipant(handlerParticipant)
|
||||
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("CES.Plugin.CentralEffectSimulation2DInterfaceImpl"))
|
||||
{
|
||||
Q_UNUSED(settings)
|
||||
}
|
||||
|
||||
Ces2DInterfaceImpl::~Ces2DInterfaceImpl()
|
||||
{
|
||||
m_handlerAesData.reset();
|
||||
m_handlerBuildingModel.reset();
|
||||
m_handlerParticipantArea.reset();
|
||||
}
|
||||
|
||||
|
||||
bool Ces2DInterfaceImpl::init(int domainId, int exerciseId)
|
||||
{
|
||||
|
||||
m_domainId = domainId;
|
||||
m_exerciseId = exerciseId;
|
||||
INFO_LOG(m_logger) << "CentralEffectSimulation2DInterfaceImpl::init()"
|
||||
<< " m_domainId=" << m_domainId
|
||||
<< " m_exerciseId=" << m_exerciseId;
|
||||
|
||||
// initialize handlerAesData
|
||||
m_handlerAesData = std::make_shared<HandlerAesData>(m_ddsHandler,
|
||||
m_handlerBuildingData,
|
||||
this);
|
||||
|
||||
if (!m_handlerAesData->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation HandlerAesData failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(m_logger) << "initialize HandlerBuildingModel ----------------------------";
|
||||
m_handlerBuildingModel = std::make_shared<HandlerBuildingModel>(m_ddsHandler, m_handlerAesData, this);
|
||||
if (!m_handlerBuildingModel->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation HandlerBuildingModel failed.";
|
||||
return false;
|
||||
} // if
|
||||
|
||||
|
||||
// initialize handlerParticipantArea
|
||||
m_handlerParticipantArea = std::make_shared<HandlerParticipantArea>(m_ddsHandler,
|
||||
m_handlerParticipant,
|
||||
m_handlerAesData,
|
||||
m_handlerBuildingModel,
|
||||
this);
|
||||
|
||||
if (!m_handlerParticipantArea->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation HandlerParticipantArea failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(m_logger) << "CentralEffectSimulation2DInterfaceImpl::init() return true";
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Ces2DInterfaceImpl::echo(const QString &message)
|
||||
{
|
||||
|
||||
QString ret(QStringLiteral("<<<< %1 >>>> CentralEffectSimulation2DInterfaceImpl::echo").arg(message));
|
||||
INFO_LOG(m_logger) << "CentralEffectSimulation2DInterfaceImpl::echo return:" << ret;
|
||||
DEBUG_LOG(m_logger) << "DEBUG: CentralEffectSimulation2DInterfaceImpl::echo return:" << ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} //namespace Ces2D
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Plugin Ces2D
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "handler_aes_data.h"
|
||||
#include "handler_building_model.h"
|
||||
#include "handler_participant_area.h"
|
||||
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
#include <CentralEffectSimulation/ces_plugin_interface.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
|
||||
namespace Ces2D
|
||||
{
|
||||
//using DbHandler = NGLDB::DbServiceHandler<CentralEffectSimulation::DatabaseInterface>;
|
||||
|
||||
class CentralEffectSimulation2DPlugin : public QObject, public CentralEffectSimulation::Plugin::Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "special:3:ces.CentralEffectSimulation2DPlugin")
|
||||
Q_INTERFACES(CentralEffectSimulation::Plugin::Plugin)
|
||||
|
||||
public:
|
||||
CentralEffectSimulation2DPlugin() = default;
|
||||
~CentralEffectSimulation2DPlugin() = default;
|
||||
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::DatabaseInterface> &db,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &handlerParticipant,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &handlerBuildingData) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Ces2DInterfaceImpl final : public CentralEffectSimulation::Plugin::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Ces2DInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::DatabaseInterface> &db,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &handlerParticipant,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &handlerBuildingData);
|
||||
~Ces2DInterfaceImpl();
|
||||
//bool init();
|
||||
const char *name() const override { return "CentralEffectSimulation2D"; }
|
||||
QString echo(const QString &message) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
bool init(int domainId, int exerciseId) override;
|
||||
private:
|
||||
|
||||
private:
|
||||
CentralEffectSimulation::Plugin::DataProvider *m_pdp;
|
||||
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler;
|
||||
std::shared_ptr<CentralEffectSimulation::DatabaseInterface> m_db;
|
||||
std::shared_ptr<HandlerAesData> m_handlerAesData; ///< Pointer to AES Building handler
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> m_handlerBuildingData; ///< Pointer to AES Building handler
|
||||
std::shared_ptr<HandlerBuildingModel> m_handlerBuildingModel; ///< Pointer to Building Model Handler
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant; ///< Pointer to handler for all participants
|
||||
std::shared_ptr<HandlerParticipantArea> m_handlerParticipantArea; ///< Pointer to handler for participant outside from Buildings
|
||||
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
int m_domainId = 0;
|
||||
int m_exerciseId = 0;
|
||||
};
|
||||
|
||||
} // namespace Ces2D
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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 Ces2D
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Settings::CalculateCentralAes Settings::calculateCentralAes()
|
||||
{
|
||||
Settings::CalculateCentralAes value = static_cast<Settings::CalculateCentralAes>(s()->settings()->value(QStringLiteral("CES/calculateCentralAes"), 0).toInt());
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace Ces2D
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Settings for CentralEffectSimulation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <QString>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class Settings;
|
||||
}
|
||||
|
||||
namespace Ces2D
|
||||
{
|
||||
namespace Settings
|
||||
{
|
||||
enum CalculateCentralAes
|
||||
{
|
||||
NO_AES_CALCUALTION,
|
||||
AES_CALCUALTION,
|
||||
AES_CALCUALTION_ONLY_IN_WLS_AREA
|
||||
};
|
||||
|
||||
NGL::Settings *settings();
|
||||
void setIniFile(const QString &ini);
|
||||
CalculateCentralAes calculateCentralAes();
|
||||
}
|
||||
|
||||
} // namespace Ces2D
|
||||
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Commmunication with HlaApacheProxy
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(SRCS
|
||||
echoplugin.cpp
|
||||
echoplugin.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV cesPluginEcho MODULE ${SRCS})
|
||||
NGL_INSTALL_TARGET(cesPluginEcho)
|
||||
NGL_TARGET_LINK_LIBRARIES(cesPluginEcho
|
||||
Qt5::Core
|
||||
NGLLogger
|
||||
cesPluginInterface
|
||||
)
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Echo Plugin
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#include "echoplugin.h"
|
||||
#include <QDebug>
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace Echo
|
||||
{
|
||||
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> EchoPlugin::createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> dDSConnector,
|
||||
NGL::Settings *settings)
|
||||
{
|
||||
Q_UNUSED(dDSConnector);
|
||||
return std::make_shared<EchoInterfaceImpl>(pdp, settings);
|
||||
}
|
||||
|
||||
|
||||
EchoInterfaceImpl::EchoInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
|
||||
NGL::Settings *settings)
|
||||
: m_pdp(pdp)
|
||||
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("CES.Plugin.EchoInterfaceImpl"))
|
||||
{
|
||||
}
|
||||
|
||||
EchoInterfaceImpl::~EchoInterfaceImpl()
|
||||
{
|
||||
//cleanupProcess();
|
||||
}
|
||||
|
||||
bool EchoInterfaceImpl::init(int domainId, int exerciseId)
|
||||
{
|
||||
Q_UNUSED(domainId);
|
||||
Q_UNUSED(exerciseId);
|
||||
}
|
||||
|
||||
QString EchoInterfaceImpl::echo(const QString &message)
|
||||
{
|
||||
qDebug() << "return " << message;
|
||||
QString ret(QStringLiteral("<<<< %1 >>>>").arg(message));
|
||||
return ret;
|
||||
}
|
||||
|
||||
} //namespace Echo
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Echo Plugin
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <CentralEffectSimulation/ces_plugin_interface.h>
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
namespace Echo
|
||||
{
|
||||
class EchoPlugin : public QObject, public CentralEffectSimulation::Plugin::Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "special:3:ces.EchoPlugin")
|
||||
Q_INTERFACES(CentralEffectSimulation::Plugin::Plugin)
|
||||
|
||||
public:
|
||||
EchoPlugin() = default;
|
||||
~EchoPlugin() = default;
|
||||
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> dDSConnector,
|
||||
NGL::Settings *settings) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class EchoInterfaceImpl final : public CentralEffectSimulation::Plugin::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
EchoInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
NGL::Settings *settings);
|
||||
~EchoInterfaceImpl();
|
||||
bool init(int domainId, int exerciseId);
|
||||
const char *name() const override { return "ECHO"; }
|
||||
|
||||
QString echo(const QString &message);
|
||||
|
||||
private Q_SLOTS:
|
||||
private:
|
||||
|
||||
private:
|
||||
CentralEffectSimulation::Plugin::DataProvider *m_pdp;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
} // namespace Echo
|
||||
@@ -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
|
||||
+99
@@ -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
|
||||
|
||||
+1809
File diff suppressed because it is too large.
Load diff
+237
@@ -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 ¢erUtm, 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 ¢erUtm, 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
|
||||
|
||||
+417
@@ -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
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# monitoring of the target areas
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(SRCS
|
||||
plugin.cpp
|
||||
plugin.h
|
||||
handler_functional_area.cpp
|
||||
handler_functional_area.h
|
||||
supplytimer.cpp
|
||||
supplytimer.h
|
||||
# logger.cpp
|
||||
# logger.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV cesPluginCES_FunctionalAreas MODULE ${SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(cesPluginCES_FunctionalAreas
|
||||
PUBLIC
|
||||
Qt5::Network
|
||||
Qt5::Widgets
|
||||
cesPluginInterface
|
||||
ngldb
|
||||
svcCesDDSCommon
|
||||
# ProjectConfig
|
||||
)
|
||||
NGL_INSTALL_TARGET(cesPluginCES_FunctionalAreas)
|
||||
|
||||
+826
@@ -0,0 +1,826 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#include "handler_functional_area.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QDateTime>
|
||||
|
||||
#include <LtsUtilsCore/dds_bitarray.h>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <ProjectDataManagement/pdm_enums.hpp>
|
||||
|
||||
namespace dds
|
||||
{
|
||||
namespace core
|
||||
{
|
||||
inline uint qHash(ProjectDataManagement::EventType et)
|
||||
{
|
||||
return ::qHash(et.underlying());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace CES_FUNCTIONAL_AREA
|
||||
{
|
||||
inline uint qHash(EffectType et)
|
||||
{
|
||||
return ::qHash(int(et));
|
||||
}
|
||||
|
||||
QString toString(EffectType et)
|
||||
{
|
||||
switch (et)
|
||||
{
|
||||
case EffectType::Unknown: return QStringLiteral("Unknown");
|
||||
case EffectType::EffectiveMineRangeEnter: return QStringLiteral("EffectiveMineRangeEnter");
|
||||
case EffectType::EffectiveMineRangeLeave: return QStringLiteral("EffectiveMineRangeLeave");
|
||||
case EffectType::NContaminationLeave: return QStringLiteral("NContaminationLeave");
|
||||
case EffectType::NContaminationEnterArea1: return QStringLiteral("NContaminationEnterArea1");
|
||||
case EffectType::NContaminationEnterArea2: return QStringLiteral("NContaminationEnterArea2");
|
||||
case EffectType::NContaminationDetonation: return QStringLiteral("NContaminationDetonation");
|
||||
case EffectType::FunctionalAreaLeave: return QStringLiteral("FunctionalAreaLeave");
|
||||
case EffectType::FunctionalAreaEnter: return QStringLiteral("FunctionalAreaEnter");
|
||||
case EffectType::ExplosionArea: return QStringLiteral("ExplosionArea");
|
||||
case EffectType::ExplosionSingle: return QStringLiteral("ExplosionSingle");
|
||||
case EffectType::BCContaminationLeave: return QStringLiteral("BCContaminationLeave");
|
||||
case EffectType::BCContaminationEnterFloating: return QStringLiteral("BCContaminationEnterFloating");
|
||||
case EffectType::BCContaminationEnterResident: return QStringLiteral("BCContaminationEnterResident");
|
||||
case EffectType::BCContaminationEnterFloatingArea: return QStringLiteral("BCContaminationEnterFloatingArea");
|
||||
case EffectType::BeStillWarning: return QStringLiteral("BeStillWarning");
|
||||
}
|
||||
return QStringLiteral("Unknown (%1)").arg(int(et));
|
||||
}
|
||||
|
||||
|
||||
HandlerFunctionalAreas::HandlerFunctionalAreas(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &handlerBuildingData,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_handlerParticipant(participantHandler)
|
||||
, m_handlerBuildingData(handlerBuildingData)
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.FunctionalAreas.HandlerFunctionalAreas"))
|
||||
{
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HandlerFunctionalAreas::~HandlerFunctionalAreas()
|
||||
{
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerFunctionalAreas::init()
|
||||
{
|
||||
auto dtcAes = m_ddsHandler->dtcAes();
|
||||
dtcAes->waitForHistoricalDataFunctionalArea(2000);
|
||||
|
||||
dtcAes->waitForHistoricalDataAesItemView(1000);
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
|
||||
this, &HandlerFunctionalAreas::onAesItemViewChanged);
|
||||
|
||||
// TAB FTC
|
||||
m_ddsHandler->ftcTab()->enableDemandInit();
|
||||
|
||||
|
||||
|
||||
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newOutdoorPosition,
|
||||
this, &HandlerFunctionalAreas::onNewParticipantPosition);
|
||||
|
||||
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newIndoorPosition,
|
||||
this, &HandlerFunctionalAreas::onNewIndoorParticipantPosition);
|
||||
|
||||
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::restoreRadioReadinessChanged,
|
||||
this, &HandlerFunctionalAreas::onRestoreRadioReadinessChanged);
|
||||
|
||||
|
||||
// Get 'static' data for all onAesItemView
|
||||
{
|
||||
auto cb = [this](const AreaEffectSimulation::AesItemView & aiv)
|
||||
{
|
||||
onAesItemViewChanged(aiv, DataModification::eAdded);
|
||||
};
|
||||
if (!dtcAes->aesItemViews(cb))
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(m_logger) << "HandlerParticipantArea::init() finished.";
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HandlerFunctionalAreas::onSendCesHitReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onSendCesHitReply for id " << replyObject.id() << " success= " << replyObject.error();
|
||||
|
||||
if (replyObject.error())
|
||||
WARNING_LOG(m_logger) << "Can not send enter/leave Area to participant in training area: " << replyObject();
|
||||
|
||||
// Send next Request, if available
|
||||
if (!m_sendCesHitRequestQueue.isEmpty())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "m_sendCesAreaActionRequestQueue.size()=" << m_sendCesHitRequestQueue.size();
|
||||
m_sendCesHitRequestQueue.dequeue();
|
||||
// Send next Message
|
||||
if (!m_sendCesHitRequestQueue.isEmpty())
|
||||
{
|
||||
const auto &hr = m_sendCesHitRequestQueue.head();
|
||||
DEBUG_LOG(m_logger) << "sendCesHitRequest: " << hr;
|
||||
m_ddsHandler->ftcTab()->sendCesHitRequest(hr, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandlerFunctionalAreas::onDemandInitReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onDemandInitReply for id " << replyObject.id() << " success= " << replyObject.error();
|
||||
|
||||
if (replyObject.error())
|
||||
WARNING_LOG(m_logger) << "Can not send Init to participant in training area: " << replyObject();
|
||||
|
||||
// Send next Request, if available
|
||||
if (!m_sendInitRequestQueue.isEmpty())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "m_sendInitRequestQueue.size()=" << m_sendInitRequestQueue.size();
|
||||
m_sendInitRequestQueue.dequeue();
|
||||
// Send next Message
|
||||
if (!m_sendInitRequestQueue.isEmpty())
|
||||
{
|
||||
const auto &hr = m_sendInitRequestQueue.head();
|
||||
DEBUG_LOG(m_logger) << "demandInitRequest: " << hr;
|
||||
m_ddsHandler->ftcTab()->demandInitRequest(hr, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ///////////////////////////////////
|
||||
// A E S (AreaEffectSimulation)
|
||||
// ///////////////////////////////////
|
||||
void HandlerFunctionalAreas::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
|
||||
{
|
||||
const int aesItemId = data.aesItemId();
|
||||
const AreaEffectSimulation::AesEffectState &effectState = data.effectStateId();
|
||||
if (data.aesTypeId().underlying() != AreaEffectSimulation::AesType_def::AtFunctionalArea)
|
||||
return;
|
||||
|
||||
const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(data.aesItemId());
|
||||
|
||||
if (!fa.isCentral())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << " !isCentral"
|
||||
" Got AesItemView id: " << aesItemId
|
||||
<< ", type: " << data.aesTypeId()
|
||||
<< ", effectState: " << data.effectStateId()
|
||||
<< ", modType: " << modType;
|
||||
if (m_aesItemViews.contains(aesItemId))
|
||||
m_aesItemViews.remove(aesItemId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got AesItemView id: " << aesItemId
|
||||
<< ", type: " << data.aesTypeId()
|
||||
<< ", effectState: " << data.effectStateId()
|
||||
<< ", modType: " << modType;
|
||||
|
||||
|
||||
switch (effectState.underlying())
|
||||
{
|
||||
case AreaEffectSimulation::AesEffectState_def::EsPrepared:
|
||||
break;
|
||||
case AreaEffectSimulation::AesEffectState_def::EsActivated:
|
||||
{
|
||||
bool isSupplyTruck = false;
|
||||
if (fa.supplyMode() == AreaEffectSimulation::AesOperatingMode_def::OmWaitingTime)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "isSupplyTruck = true";
|
||||
isSupplyTruck = true;
|
||||
}
|
||||
auto aesItemViewUtm(CentralEffectSimulation::AesItemViewUtm::create(data, m_aesItemViews[data.aesItemId()], 0, isSupplyTruck));
|
||||
if (fa.participantId().is_set())
|
||||
aesItemViewUtm.participantId = fa.participantId().get();
|
||||
|
||||
if (!m_aesPolygonEncloseBuilding.contains(data.aesItemId()))
|
||||
{
|
||||
QVector<int> enclosedBuildings;
|
||||
QPolygonF polygon;
|
||||
polygon.reserve(data.form().size());
|
||||
for (size_t i = 0; i < data.form().size(); i++)
|
||||
{
|
||||
//QPointF point(itemView.form[i].x(), itemView.form[i].y());
|
||||
QPointF point(data.form().at(i).lon(), data.form().at(i).lat());
|
||||
polygon.append(point);
|
||||
}
|
||||
enclosedBuildings = m_handlerBuildingData->polygonEncloseBuildings(polygon);
|
||||
DEBUG_LOG(m_logger) << "enclosedBuildings.size=" << enclosedBuildings.size();
|
||||
// local memory for the results, so that the polygonEncloseBuildings method is only run once for each effective field
|
||||
// and not for each position report
|
||||
m_aesPolygonEncloseBuilding.insert(data.aesItemId(), enclosedBuildings);
|
||||
DEBUG_LOG(m_logger) << "insert enclosedBuildings.size=" << enclosedBuildings.size();
|
||||
}
|
||||
|
||||
calculateFunctionalArea(aesItemViewUtm);
|
||||
m_aesItemViews.insert(data.aesItemId(), aesItemViewUtm);
|
||||
DEBUG_LOG(m_logger) << "insert Functiona Area AesItemView id: " << aesItemId
|
||||
<< ", type: " << data.aesTypeId();
|
||||
break;
|
||||
} // case EsActivated
|
||||
case AreaEffectSimulation::AesEffectState_def::EsRemoved:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsExpired:
|
||||
{
|
||||
aesItemViewRemoved(aesItemId);
|
||||
m_aesPolygonEncloseBuilding.remove(aesItemId);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// do nothing
|
||||
break;
|
||||
} // switch effectStateId
|
||||
} // onAesItemViewChanged
|
||||
|
||||
void HandlerFunctionalAreas::calculateFunctionalArea(const CentralEffectSimulation::AesItemViewUtm &itemView)
|
||||
{
|
||||
bool inForm = false;
|
||||
DEBUG_LOG(m_logger) << "HandlerParticipantArea::calculateFunctionalArea aesItemId =" << itemView.aesItemId;
|
||||
const auto participantsMap = m_handlerParticipant->positions();
|
||||
for (const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos : participantsMap)
|
||||
{
|
||||
if (m_handlerParticipant->isOutdated(participantPos))
|
||||
continue;
|
||||
|
||||
DEBUG_LOG(m_logger) << "participant id= " << participantPos.participantId()
|
||||
<< " buildingId=" << participantPos.buildingId();
|
||||
|
||||
if ( participantPos.buildingId() ==0 )
|
||||
inForm = inFormCheck(itemView, participantPos);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < m_aesPolygonEncloseBuilding.value(itemView.aesItemId).size(); i++)
|
||||
{
|
||||
inForm = false;
|
||||
if (m_aesPolygonEncloseBuilding.value(itemView.aesItemId).at(i) == participantPos.buildingId())
|
||||
{
|
||||
inForm = true;
|
||||
m_handlerParticipant->setNotfightMode(participantPos.participantId(), true);
|
||||
DEBUG_LOG(m_logger) << "!m_aesPolygonEncloseBuilding buildingId=" << participantPos.buildingId()
|
||||
<< " aesId=" << itemView.aesItemId
|
||||
<< " in Form = true";
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "!m_aesPolygonEncloseBuilding buildingId=" << participantPos.buildingId()
|
||||
<< " aesId=" << itemView.aesItemId
|
||||
<< " in Form = false";
|
||||
}
|
||||
}
|
||||
}
|
||||
sendEnterLeave(itemView, participantPos.participantId(), inForm);
|
||||
}
|
||||
// for
|
||||
} // calculateFunctionalArea
|
||||
|
||||
|
||||
void HandlerFunctionalAreas::onNewParticipantPosition(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "++++++++ onNewParticipantPosition participantId=" << participantData.participantId();
|
||||
|
||||
if (m_handlerParticipant->isOutdated(participantData))
|
||||
return;
|
||||
|
||||
const int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantData.participantId());
|
||||
if (equipmentNumber <= 0)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "equipmentNumber <=0";
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "HandlerParticipantArea::calculateAesParticipant paricipantId: " << participantData.participantId();
|
||||
for (const CentralEffectSimulation::AesItemViewUtm &itemView : qAsConst(m_aesItemViews))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << " itemView: " << itemView.aesItemId << ", " << itemView.aesTypeId;
|
||||
switch (itemView.aesTypeId.underlying())
|
||||
{
|
||||
case AreaEffectSimulation::AesType_def::AtFunctionalArea:
|
||||
{
|
||||
///////////////////
|
||||
/// \brief [GUEZE-2256] 3D Wirksim - Funktionsraum Nicht Kampffähig
|
||||
/// Die Teilnehmer der Partei des Wirkfeldes werden nicht berücksichtig.
|
||||
///
|
||||
AreaEffectSimulation::FunctionalArea functionalArea = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
|
||||
DEBUG_LOG(m_logger) << "functionalArea Typ=" << functionalArea.functionalAreaTypeId()
|
||||
<< " itemView.partyId=" << itemView.partyId
|
||||
<< " participantData.partyId=" << participantData.partyId()
|
||||
<< " insideBuilding=" << participantData.insideBuilding();
|
||||
///////////////////
|
||||
bool inForm = inFormCheck(itemView, participantData);
|
||||
sendEnterLeave(itemView, participantData.participantId(), inForm);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// nothing
|
||||
break;
|
||||
} // switch
|
||||
} // for
|
||||
} // onNewParticipantPosition
|
||||
|
||||
void HandlerFunctionalAreas::onNewIndoorParticipantPosition(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "New Indoor Position paticipantId=" << participantData.participantId();
|
||||
|
||||
if (m_handlerParticipant->isOutdated(participantData))
|
||||
return;
|
||||
|
||||
const int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantData.participantId());
|
||||
if (equipmentNumber <= 0)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "equipmentNumber <=0";
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "HandlerParticipantArea::calculateAesParticipant paricipantId: " << participantData.participantId();
|
||||
for (const CentralEffectSimulation::AesItemViewUtm &itemView : qAsConst(m_aesItemViews))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << " itemView: " << itemView.aesItemId << ", " << itemView.aesTypeId;
|
||||
switch (itemView.aesTypeId.underlying())
|
||||
{
|
||||
case AreaEffectSimulation::AesType_def::AtFunctionalArea:
|
||||
{
|
||||
///////////////////
|
||||
/// \brief [GUEZE-2256] 3D Wirksim - Funktionsraum Nicht Kampffähig
|
||||
/// Die Teilnehmer der Partei des Wirkfeldes werden nicht berücksichtig.
|
||||
///
|
||||
AreaEffectSimulation::FunctionalArea functionalArea = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
|
||||
DEBUG_LOG(m_logger) << "functionalArea Typ=" << functionalArea.functionalAreaTypeId()
|
||||
<< " itemView.partyId=" << itemView.partyId
|
||||
<< " participantData.partyId=" << participantData.partyId()
|
||||
<< " insideBuilding=" << participantData.insideBuilding();
|
||||
{
|
||||
if ( (itemView.partyId == participantData.partyId())
|
||||
&& (functionalArea.functionalAreaTypeId() == 8)) // Funktionsraum Nicht Kampffaehig [GUEZE-2256]
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Position mit Funktionsraum Nicht Kampffähig hat die Partei des Wirkfeldes => nicht beruecksichtigen";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Check whether the position appears in the building list of the effective field.
|
||||
bool inForm = false;
|
||||
for (int i = 0; i < m_aesPolygonEncloseBuilding.value(itemView.aesItemId).size(); i++)
|
||||
{
|
||||
if (m_aesPolygonEncloseBuilding.value(itemView.aesItemId).at(i) == participantData.buildingId())
|
||||
{
|
||||
inForm = true;
|
||||
m_handlerParticipant->setNotfightMode(participantData.participantId(), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////
|
||||
sendEnterLeave(itemView, participantData.participantId(), inForm);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// nothing
|
||||
break;
|
||||
} // switch
|
||||
} // for
|
||||
|
||||
}
|
||||
|
||||
void HandlerFunctionalAreas::onRestoreRadioReadinessChanged(const int participantId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "HandlerArtillery::onRestoreRadioReadinessChanged participantId=" << participantId;
|
||||
m_supplyTimers.remove(participantId);
|
||||
removeParticipant(participantId);
|
||||
}
|
||||
|
||||
|
||||
// return true, if participant is inside of the bounding Box
|
||||
bool HandlerFunctionalAreas::inBoundingBoxCheck(const CentralEffectSimulation::AesItemViewUtm &itemView,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData)
|
||||
{
|
||||
if (itemView.effectStateId != AreaEffectSimulation::AesEffectState_def::EsActivated)
|
||||
return false;
|
||||
|
||||
// QRectF(topLeft, bottomRight) -> no need to mormalize, QRectF:contains() handles it correct
|
||||
|
||||
const QRectF boundingBoxImpact(itemView.boundingBoxBottomLeft,
|
||||
itemView.boundingBoxTopRight);
|
||||
|
||||
const QPointF participantPosUtmPoint = CentralEffectSimulation::geographic2Utm(participantData.pos(), itemView.zone);
|
||||
if (boundingBoxImpact.contains(participantPosUtmPoint))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "inBoundingBoxCheck Paricipant " << participantData.participantId()
|
||||
<< " inside AesItemView:" << itemView.aesItemId;
|
||||
return true;
|
||||
}
|
||||
TRACE_LOG(m_logger) << "inBoundingBoxCheck Paricipant " << participantData.participantId()
|
||||
<< " outside AesItemView:" << itemView.aesItemId;
|
||||
return false;
|
||||
}
|
||||
|
||||
// return true, if participant is inside of the form of AesItemView
|
||||
bool HandlerFunctionalAreas::inFormCheck(const CentralEffectSimulation::AesItemViewUtm &itemView,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData)
|
||||
{
|
||||
if (itemView.effectStateId != AreaEffectSimulation::AesEffectState_def::EsActivated)
|
||||
return false;
|
||||
|
||||
const QRectF boundingBox(itemView.boundingBoxBottomLeft,
|
||||
itemView.boundingBoxTopRight);
|
||||
const QPointF participantPosUtmPoint = CentralEffectSimulation::geographic2Utm(participantData.pos(), itemView.zone);
|
||||
const QString participantPosMgrs = CentralEffectSimulation::geographic2mgrs(participantData.pos(), itemView.zone);
|
||||
DEBUG_LOG(m_logger) << "inFormCheck start, paricipantId: " << participantData.participantId()
|
||||
<< ", aesItemId: " << itemView.aesItemId
|
||||
<< ", aesTypeId: " << itemView.aesTypeId
|
||||
<< ", form.size: " << itemView.form.size()
|
||||
<< ", Mgrs:" << participantPosMgrs;
|
||||
|
||||
if (boundingBox.contains(participantPosUtmPoint) &&
|
||||
itemView.form.containsPoint(participantPosUtmPoint, Qt::FillRule::OddEvenFill))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "inside AES form, paricipantId: " << participantData.participantId()
|
||||
<< ", aesItemId: " << itemView.aesItemId;
|
||||
return true;
|
||||
} // if inside
|
||||
|
||||
|
||||
// outside
|
||||
#if 0
|
||||
if (m_logger.isDebugEnabled())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "inFormCheck: Paricipant " << participantPosition.participantId << " outside AesItemView " << itemView.aesItemId;
|
||||
DEBUG_LOG(m_logger) << "ParticipantPos = " << debug(participantPosUtmPoint);
|
||||
for (const auto &itPos : itemView.form)
|
||||
DEBUG_LOG(m_logger) << "itemView =" << debug(itPos);
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send via TAB-Proxy to battlefield
|
||||
void HandlerFunctionalAreas::sendCesHitRequest(const CentralEffectSimulation::AesItemViewUtm &itemView,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData,
|
||||
ProjectDataManagement::EventType eventType)
|
||||
{
|
||||
qint64 effectTime = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
// qint64 mineFieldBitIndex = 0;
|
||||
int remaining = 0;
|
||||
|
||||
switch (eventType.underlying())
|
||||
{
|
||||
case ProjectDataManagement::EventType_def::EnterFunctionalArea:
|
||||
DEBUG_LOG(m_logger) << "-------------- EnterFunctionalArea itemView =" << itemView.aesItemId;
|
||||
remaining = 1;
|
||||
break;
|
||||
case ProjectDataManagement::EventType_def::LeaveFunctionalArea:
|
||||
remaining = 0;
|
||||
DEBUG_LOG(m_logger) << "-------------- LeaveFunctionalArea itemView =" << itemView.aesItemId;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (remaining < 0)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendCesHitRequest Settings::calculateCentralAes="
|
||||
<< " insideWlsArea=" << std::boolalpha << participantData.insideWlsArea()
|
||||
<< " isSmartChargeType=" << std::boolalpha << m_ddsHandler->isSmartChargeType(itemView.chargeStruct)
|
||||
<< " participantId=" << participantData.participantId();
|
||||
|
||||
const int equipNo = m_ddsHandler->participantId2EquipNo(participantData.participantId());
|
||||
DEBUG_LOG(m_logger) << " ftc sendCESHit to Participant participantId = " << participantData.participantId()
|
||||
<< " equipNo = " << equipNo
|
||||
<< " aesItemId =" << itemView.aesItemId;
|
||||
|
||||
// participantPosition.participantPosition == 0 -> send to all
|
||||
if (participantData.participantId() != 0 && equipNo <= 0)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "participantPosition.participantId != 0 && equipNo <= 0";
|
||||
return;
|
||||
}
|
||||
if (participantData.participantId() != 0 &&
|
||||
participantData.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CatastrophicKill)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "participantPosition.participantId != 0 CatastrophicKill)";
|
||||
return;
|
||||
}
|
||||
|
||||
const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
|
||||
|
||||
const TrainingAreaBase::TabPosition pos(participantData.pos(),
|
||||
Core::PositionReportingSource_def::Gps, // irrelevant
|
||||
participantData.buildingId(),
|
||||
participantData.roomId());
|
||||
const int medicTime = fa.medicTime() / 600000; //reserve 2 = medical treatment
|
||||
const int maintanceTime = fa.maintTime() / 600000; //reserve 1 = maintance time
|
||||
const int decontaminatonTime = fa.deconTime() / 600000; //reserve Munitionsart = decontaminaton time
|
||||
|
||||
const int operationModeDecontamination = fa.deconMode().underlying();
|
||||
const int operationModeMaintenance = fa.maintMode().underlying();
|
||||
const int operationModeMedical = fa.medicMode().underlying();
|
||||
|
||||
//const int originatorEquipNo = fa.medicTime()/60000; //reserve 2 = medical treatment
|
||||
//const int mineId = fa.maintTime()/60000; //reserve 1 = maintance time
|
||||
//const int chargeType = fa.deconTime()/1000; //reserve Munitionsart = decontaminaton time
|
||||
|
||||
const int originatorEquipNo = (operationModeMedical << 8) + medicTime; //reserve 2 = medical treatment
|
||||
const int mineId = (operationModeMaintenance << 8) + maintanceTime; //reserve 1 = maintance time
|
||||
const int chargeType = (operationModeDecontamination << 8) + decontaminatonTime; //reserve Munitionsart = decontaminaton time
|
||||
|
||||
TrainingAreaBase::SendCesHitRequest requestTab(
|
||||
equipNo, // equipmentNumber
|
||||
participantData.participantId(), // participantId
|
||||
chargeType, // chargeTypeId
|
||||
itemView.aesItemId, // aesId
|
||||
originatorEquipNo, // originatorEquipmentNumber
|
||||
remaining, // remainEffectPercent ( no protection outside Building )
|
||||
pos,
|
||||
effectTime, // effectTime
|
||||
eventType,
|
||||
itemView.partyId, // originPartyId
|
||||
mineId
|
||||
);
|
||||
DEBUG_LOG(m_logger) << " participantId=" << participantData.participantId()
|
||||
<< " chargeTypeId=" << itemView.chargeStruct.chargeTypeId();
|
||||
|
||||
|
||||
m_sendCesHitRequestQueue.enqueue(requestTab);
|
||||
if (m_sendCesHitRequestQueue.size() == 1)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "SendCesHitRequest: " << requestTab;
|
||||
m_ddsHandler->ftcTab()->sendCesHitRequest(requestTab, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HandlerFunctionalAreas::sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &itemView,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData,
|
||||
const ProjectDataManagement::EventType eventType)
|
||||
{
|
||||
ParticipantManagement::TypeClass typeClass = m_handlerParticipant->typeClassFromTypeId(participantData.participantTypeId());
|
||||
// can happen since the positions are collected for all participants (no check if it is a SupportEntity or similar)
|
||||
if (typeClass == ParticipantManagement::TypeClass_def::Unit ||
|
||||
typeClass == ParticipantManagement::TypeClass_def::SupportUnit ||
|
||||
typeClass == ParticipantManagement::TypeClass_def::SupportEntity ||
|
||||
typeClass == ParticipantManagement::TypeClass_def::Aircraft ||
|
||||
typeClass == ParticipantManagement::TypeClass_def::Vessel ||
|
||||
typeClass == ParticipantManagement::TypeClass_def::Unknown)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Participant with id " << participantData.participantId()
|
||||
<< " has invalid typeClass: " << typeClass
|
||||
<< " eventType: " << eventType;
|
||||
return;
|
||||
}
|
||||
|
||||
int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantData.participantId());
|
||||
if (equipmentNumber <= 0)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Not sending Event " << eventType << " for participant " << participantData.participantId()
|
||||
<< " - participant has no equipment number";
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendParticipantEvent" << eventType
|
||||
<< " participantId=" << participantData.participantId()
|
||||
<< " AesItemId=" << itemView.aesItemId;
|
||||
|
||||
const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
|
||||
|
||||
CentralEffectSimulation::ParticipantEvent pe;
|
||||
pe.id(m_ddsHandler->getParticipantEventId());
|
||||
|
||||
pe.eventTypeId(eventType.underlying());
|
||||
pe.participantId(participantData.participantId());
|
||||
pe.eventTime(participantData.sampleTime());
|
||||
pe.aesItemId(itemView.aesItemId);
|
||||
pe.partyId(participantData.partyId());
|
||||
pe.aesName(fa.name());
|
||||
pe.equipmentNumber(equipmentNumber);
|
||||
pe.vulnerability(participantData.vulnerabilityState.underlying());
|
||||
pe.position(participantData.pos());
|
||||
pe.friendlyFire(false);
|
||||
|
||||
INFO_LOG(m_logger) << "sendParticipantEvent: " << pe
|
||||
<< ", currentMSecsSinceEpoch = " << QDateTime::currentMSecsSinceEpoch()
|
||||
<< ", time difference = " << QDateTime::currentMSecsSinceEpoch() - pe.eventTime();
|
||||
m_ddsHandler->dtsCes()->publish(pe);
|
||||
|
||||
const auto id = pe.id();
|
||||
QTimer::singleShot(1 * 60 * 1000, this, [id, this]() { m_ddsHandler->dtsCes()->removeParticipantEventByKey(id); });
|
||||
}
|
||||
|
||||
|
||||
void HandlerFunctionalAreas::aesItemViewRemoved(int aesItemId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "aesItemViewRemoved aesItemId=" << aesItemId
|
||||
<< " m_cesEnterLeaveFunctionalArea.size=" << m_cesEnterLeaveFunctionalArea.size()
|
||||
<< " m_aesItemViews.size=" << m_aesItemViews.size();
|
||||
QHashIterator<QPair<int, int>, EnterLeaveType> i(m_cesEnterLeaveFunctionalArea);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
DEBUG_LOG(m_logger) << "Key: itemId=" << i.key().first << " participantId=" << i.key().second
|
||||
<< " EnterLeaveType=" << i.value().eventType;
|
||||
if (i.key().first == aesItemId )
|
||||
{
|
||||
DEBUG_LOG(m_logger) << " EnterLeaveType=" << i.value().eventType;
|
||||
CentralEffectSimulation::AesItemViewUtm itemView = m_aesItemViews.value(i.key().first);
|
||||
sendEnterLeave(itemView, i.key().second, false);
|
||||
m_cesEnterLeaveFunctionalArea.remove(i.key());
|
||||
}
|
||||
|
||||
}
|
||||
m_aesItemViews.remove(aesItemId);
|
||||
}
|
||||
|
||||
void HandlerFunctionalAreas::removeParticipant(int participantId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "removeParticipant participantId=" << participantId
|
||||
<< " m_cesEnterLeaveFunctionalArea.size=" << m_cesEnterLeaveFunctionalArea.size();
|
||||
QHashIterator<QPair<int, int>, EnterLeaveType> i(m_cesEnterLeaveFunctionalArea);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
DEBUG_LOG(m_logger) << "Key: itemId=" << i.key().first << " participantId=" << i.key().second
|
||||
<< " EnterLeaveType=" << i.value().eventType;
|
||||
if (i.key().second == participantId )
|
||||
{
|
||||
DEBUG_LOG(m_logger) << " EnterLeaveType=" << i.value().eventType;
|
||||
CentralEffectSimulation::AesItemViewUtm itemView = m_aesItemViews.value(i.key().first);
|
||||
//sendEnterLeave(itemView, i.key().second, false);
|
||||
m_cesEnterLeaveFunctionalArea.remove(i.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandlerFunctionalAreas::sendEnterLeave(const CentralEffectSimulation::AesItemViewUtm &itemView, int participantId, bool inForm)
|
||||
{
|
||||
QPair<int, int> key = QPair<int, int>(itemView.aesItemId, participantId);
|
||||
EnterLeaveType enterLeaveType;
|
||||
EnterLeaveType lastEnterLeaveType;
|
||||
|
||||
if (m_cesEnterLeaveFunctionalArea.contains(key))
|
||||
lastEnterLeaveType = m_cesEnterLeaveFunctionalArea.value(key);
|
||||
|
||||
DEBUG_LOG(m_logger) << "HandlerFunctionalAreas::sendEnterLeave "
|
||||
<< " aesItemId=" << itemView.aesItemId
|
||||
<< " participantId=" << participantId
|
||||
<< " inForm=" << inForm;
|
||||
|
||||
if (inForm)
|
||||
{
|
||||
enterLeaveType.eventType = ProjectDataManagement::EventType_def::EnterFunctionalArea;
|
||||
if (itemView.isSupplyTruck)
|
||||
{
|
||||
enterLeaveType.isAlreadySupplied = true;
|
||||
const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
|
||||
if (!lastEnterLeaveType.isAlreadySupplied)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendEnterLeave.startSupplyTimer"
|
||||
" m_cesEnterLeaveFunctionalArea.insert"
|
||||
<< " aesItemId=" << key.first
|
||||
<< " participantId=" << key.second
|
||||
<< " enterLeaveType=" << enterLeaveType.eventType;
|
||||
startSupplyTimer(participantId, itemView.aesItemId, fa.supplyTime());
|
||||
m_cesEnterLeaveFunctionalArea.insert(key, enterLeaveType);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
enterLeaveType.eventType = ProjectDataManagement::EventType_def::LeaveFunctionalArea;
|
||||
if (itemView.isSupplyTruck && lastEnterLeaveType.eventType == ProjectDataManagement::EventType_def::EnterFunctionalArea)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendEnterLeave.stopSupplyTimer";
|
||||
enterLeaveType.isAlreadySupplied = false;
|
||||
stopSupplyTimer(participantId);
|
||||
DEBUG_LOG(m_logger) << "sendEnterLeave.startSupplyTimer"
|
||||
" m_cesEnterLeaveFunctionalArea.insert"
|
||||
<< " aesItemId=" << key.first
|
||||
<< " participantId=" << key.second
|
||||
<< " enterLeaveType=" << enterLeaveType.eventType;
|
||||
m_cesEnterLeaveFunctionalArea.insert(key, enterLeaveType);
|
||||
}
|
||||
}
|
||||
|
||||
if ((inForm && lastEnterLeaveType.eventType != ProjectDataManagement::EventType_def::EnterFunctionalArea)
|
||||
|| (!inForm && lastEnterLeaveType.eventType == ProjectDataManagement::EventType_def::EnterFunctionalArea))
|
||||
{
|
||||
CentralEffectSimulation::HandlerParticipant::CesParticipantData cesParticipantData = m_handlerParticipant.get()->getParticipantPosition(participantId);
|
||||
sendParticipantEvent(itemView, cesParticipantData, enterLeaveType.eventType);
|
||||
|
||||
const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
|
||||
DEBUG_LOG(m_logger) << "fa.isCentral()=" << fa.isCentral()
|
||||
<< " isSupplyTruck=" << itemView.isSupplyTruck
|
||||
<< " eventType=" << m_cesEnterLeaveFunctionalArea.value(key).eventType
|
||||
<< " isAlreadySupplied=" << enterLeaveType.isAlreadySupplied;
|
||||
if (fa.isCentral() && !itemView.isSupplyTruck)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendCesHitRequest";
|
||||
sendCesHitRequest(itemView, cesParticipantData, enterLeaveType.eventType);
|
||||
}
|
||||
DEBUG_LOG(m_logger) << " m_cesEnterLeaveFunctionalArea.insert"
|
||||
<< " aesItemId=" << key.first
|
||||
<< " participantId=" << key.second
|
||||
<< " enterLeaveType=" << enterLeaveType.eventType;
|
||||
m_cesEnterLeaveFunctionalArea.insert(key, enterLeaveType);
|
||||
}
|
||||
|
||||
} // sendEnterLeave
|
||||
|
||||
void HandlerFunctionalAreas::startSupplyTimer(int participantId, int aesId, long time)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "startSupplyTimer="
|
||||
<< " participantId=" << participantId
|
||||
<< " aesId=" << aesId
|
||||
<< " time=" << time
|
||||
<< " ST participant" << m_aesItemViews[aesId].participantId;
|
||||
if (participantId == m_aesItemViews[aesId].participantId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "No supply for SupplyTruck";
|
||||
return;
|
||||
}
|
||||
if (m_supplyTimers.contains(participantId))
|
||||
{
|
||||
if (m_supplyTimers[participantId]->isActive())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "SupplyTimer isActive";
|
||||
return;
|
||||
}
|
||||
else
|
||||
m_supplyTimers.remove(participantId);
|
||||
}
|
||||
SupplyTimer *supplyTimer = new SupplyTimer(participantId,
|
||||
aesId, time);
|
||||
DEBUG_LOG(m_logger) << "supplyTimer->startTimer();";
|
||||
QObject::connect(supplyTimer, &SupplyTimer::timeToEffectTimeout,
|
||||
this, &HandlerFunctionalAreas::on_supplyFinished);
|
||||
m_supplyTimers.insert(participantId, supplyTimer);
|
||||
supplyTimer->startTimer();
|
||||
} // startSupplyTimer
|
||||
|
||||
void HandlerFunctionalAreas::stopSupplyTimer(int participantId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "stopSupplyTimer="
|
||||
<< "participantId=" << participantId;
|
||||
if (m_supplyTimers.contains(participantId))
|
||||
{
|
||||
if (m_supplyTimers[participantId]->isActive())
|
||||
return;
|
||||
}
|
||||
|
||||
} // startSupplyTimer
|
||||
|
||||
void HandlerFunctionalAreas::on_supplyFinished(int participantId, int aesId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "HandlerFunctionalAreas::on_supplyFinished participantId=" << participantId
|
||||
<< " aesId =" << aesId;
|
||||
|
||||
sendInitSupplyToTab(participantId,
|
||||
aesId);
|
||||
}
|
||||
|
||||
void HandlerFunctionalAreas::sendInitSupplyToTab(int participantId, int aesId)
|
||||
{
|
||||
const int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantId);
|
||||
if (equipmentNumber <= 0)
|
||||
return;
|
||||
int requestId = m_requestId++;
|
||||
int workstationId = 0;
|
||||
std::vector<int32_t> equipmentNumbers;
|
||||
equipmentNumbers.push_back(equipmentNumber);
|
||||
bool restockCharges = true;
|
||||
bool resetManipulation = false;
|
||||
bool resetVulnerabilityState = false;
|
||||
bool restockSanitationMaterial = false;
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendInitSupplyToTab"
|
||||
<< " participantId=" << participantId
|
||||
<< " aesId=" << aesId;
|
||||
TrainingAreaBase::DemandInitRequest demandInitRequest(
|
||||
requestId,
|
||||
workstationId,
|
||||
equipmentNumbers,
|
||||
restockCharges,
|
||||
resetManipulation,
|
||||
resetVulnerabilityState,
|
||||
restockSanitationMaterial
|
||||
);
|
||||
|
||||
m_sendInitRequestQueue.enqueue(demandInitRequest);
|
||||
if (m_sendInitRequestQueue.size() == 1)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendInitSupply: " << demandInitRequest;
|
||||
m_ddsHandler->ftcTab()->demandInitRequest(demandInitRequest, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace CES_FUNCTIONAL_AREA
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "supplytimer.h"
|
||||
|
||||
#include <CentralEffectSimulation/logger.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <CentralEffectSimulation/aes_item_view_utm.h>
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
#include <CentralEffectSimulation/handler_building_data.h>
|
||||
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QQueue>
|
||||
#include <QtCore/QPointF>
|
||||
#include <QtGui/QPolygonF>
|
||||
|
||||
// AES-Handling for participants
|
||||
namespace CES_FUNCTIONAL_AREA
|
||||
{
|
||||
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,
|
||||
};
|
||||
QString toString(EffectType et);
|
||||
|
||||
struct ParticipantDistance
|
||||
{
|
||||
double squareDistance = 0;
|
||||
CentralEffectSimulation::HandlerParticipant::CesParticipantData participantPosition;
|
||||
};
|
||||
|
||||
struct EnterLeaveType
|
||||
{
|
||||
ProjectDataManagement::EventType eventType = ProjectDataManagement::EventType_def::Unknown;
|
||||
bool isAlreadySupplied = false;
|
||||
};
|
||||
|
||||
|
||||
class HandlerFunctionalAreas : public QObject
|
||||
, protected TrainingAreaBase::Interface::Ftc::SendCesHitReplyHandler
|
||||
, protected TrainingAreaBase::Interface::Ftc::DemandInitReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HandlerFunctionalAreas(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &handlerBuildingData,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~HandlerFunctionalAreas();
|
||||
|
||||
/**
|
||||
* Initialize the handler to manage information from player management
|
||||
*/
|
||||
bool init();
|
||||
|
||||
protected:
|
||||
void onSendCesHitReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void onDemandInitReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
private Q_SLOTS:
|
||||
/**
|
||||
* Handle the signals from 'AES'
|
||||
*/
|
||||
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
|
||||
|
||||
private: // methoden
|
||||
void calculateFunctionalArea(const CentralEffectSimulation::AesItemViewUtm &itemView);
|
||||
void calculateDangerArea(const CentralEffectSimulation::AesItemViewUtm &itemView);
|
||||
void deleteDangerArea(const int aesItemId);
|
||||
void onNewParticipantPosition(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData);
|
||||
void onNewIndoorParticipantPosition(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData);
|
||||
void onRestoreRadioReadinessChanged(const int participantId);
|
||||
|
||||
bool inCircle(const QPointF ¢erUtm, const double radius, const QPointF &pointUtm);
|
||||
bool inBoundingBoxCheck(const CentralEffectSimulation::AesItemViewUtm &itemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData);
|
||||
bool inFormCheck(const CentralEffectSimulation::AesItemViewUtm &itemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData);
|
||||
void sendCesHitRequest(const CentralEffectSimulation::AesItemViewUtm &itemView,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData,
|
||||
ProjectDataManagement::EventType eventType);
|
||||
void sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &itemView,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData,
|
||||
const ProjectDataManagement::EventType eventType);
|
||||
|
||||
|
||||
ProjectDataManagement::EventType leaveEventTypeForAesType(AreaEffectSimulation::AesType aesTypeId);
|
||||
EffectType leaveEffectTypeForAesType(AreaEffectSimulation::AesType aesTypeId);
|
||||
EffectType effectTypeForNContaminationArea(const CentralEffectSimulation::AesItemViewUtm &itemView, const QPointF &participantPosUtmPoint, qint64 partPosSampleTime);
|
||||
EffectType effectTypeForBCContaminationArea(const CentralEffectSimulation::AesItemViewUtm &itemView, const QPointF &participantPosUtmPoint);
|
||||
|
||||
void aesItemViewRemoved(int aesItemId);
|
||||
void removeParticipant(int participantId);
|
||||
void sendEnterLeave(const CentralEffectSimulation::AesItemViewUtm &itemView, int participantId, bool inForm);
|
||||
void startSupplyTimer(int participantId, int aesId, long time);
|
||||
void stopSupplyTimer(int participantId);
|
||||
void on_supplyFinished(int participantId, int aesId);
|
||||
void sendInitSupplyToTab(int participantId, int aesId);
|
||||
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::HandlerBuildingData> m_handlerBuildingData;
|
||||
|
||||
|
||||
QHash<int32_t, int> m_aesItemId2partIdMap;
|
||||
|
||||
|
||||
// AES-Values
|
||||
QHash<int, CentralEffectSimulation::AesItemViewUtm> m_aesItemViews; // key = aesItemId
|
||||
QQueue<TrainingAreaBase::SendCesHitRequest> m_sendCesHitRequestQueue;
|
||||
QQueue<TrainingAreaBase::DemandInitRequest> m_sendInitRequestQueue;
|
||||
QHash<QPair<int, int>, EnterLeaveType> m_cesEnterLeaveFunctionalArea; // QPair < aesItemId, participantId> Last Event
|
||||
QHash<int, SupplyTimer *> m_supplyTimers; // participantId
|
||||
QHash<int, QVector<int>> m_aesPolygonEncloseBuilding; // key = aesItemId value = BuildingIds inside form
|
||||
int m_requestId = 1;
|
||||
|
||||
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
|
||||
};
|
||||
} // namespace CES_FUNCTIONAL_AREA
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Plugin CES Functional Area
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
#include "settings.h"
|
||||
|
||||
namespace CES_FUNCTIONAL_AREA
|
||||
{
|
||||
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> CesFunctionalAreaPlugin::createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
CentralEffectSimulation::MainHandler *mainHandler)
|
||||
{
|
||||
return std::make_shared<CES_FUNCTIONAL_AREAInterfaceImpl>(pdp, dDSConnector, settings, mainHandler);
|
||||
}
|
||||
|
||||
|
||||
CES_FUNCTIONAL_AREAInterfaceImpl::CES_FUNCTIONAL_AREAInterfaceImpl(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_handlerBuildingData(m_mainHandler->handlerBuildingData())
|
||||
, m_handlerParticipant(m_mainHandler->handlerParticipant())
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.FunctionalAreas.CES_FUNCTIONAL_AREAInterfaceImpl"))
|
||||
{
|
||||
Q_UNUSED(settings)
|
||||
}
|
||||
|
||||
CES_FUNCTIONAL_AREAInterfaceImpl::~CES_FUNCTIONAL_AREAInterfaceImpl()
|
||||
{
|
||||
m_handlerFunctionalAreas.reset();
|
||||
}
|
||||
|
||||
|
||||
bool CES_FUNCTIONAL_AREAInterfaceImpl::init(int domainId, int exerciseId)
|
||||
{
|
||||
m_domainId = domainId;
|
||||
m_exerciseId = exerciseId;
|
||||
INFO_LOG(m_logger) << "CES_FUNCTIONAL_AREAInterfaceImpl::init()"
|
||||
<< " m_domainId=" << m_domainId
|
||||
<< " m_exerciseId=" << m_exerciseId;
|
||||
|
||||
|
||||
|
||||
// initialize handlerFunctionalAreas
|
||||
m_handlerFunctionalAreas = std::make_shared<HandlerFunctionalAreas>(m_ddsHandler,
|
||||
m_handlerParticipant,
|
||||
m_handlerBuildingData,
|
||||
this);
|
||||
|
||||
if (!m_handlerFunctionalAreas->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation m_handlerFunctionalArea failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(m_logger) << "CES_FUNCTIONAL_AREAInterfaceImpl::init() return true";
|
||||
return true;
|
||||
}
|
||||
|
||||
QString CES_FUNCTIONAL_AREAInterfaceImpl::echo(const QString &message)
|
||||
{
|
||||
|
||||
QString ret(QStringLiteral("<<<< %1 >>>> CES_FUNCTIONAL_AREAInterfaceImpl::echo").arg(message));
|
||||
INFO_LOG(m_logger) << "CES_FUNCTIONAL_AREAInterfaceImpl::echo return:" << ret;
|
||||
DEBUG_LOG(m_logger) << "DEBUG: CES_FUNCTIONAL_AREAInterfaceImpl::echo return:" << ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} //namespace CES_FUNCTIONAL_AREA
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Plugin CES Functional Area
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <CentralEffectSimulation/logger.h>
|
||||
|
||||
#include "handler_functional_area.h"
|
||||
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
#include <CentralEffectSimulation/ces_plugin_interface.h>
|
||||
#include <CentralEffectSimulation/main_handler.h>
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
|
||||
namespace CES_FUNCTIONAL_AREA
|
||||
{
|
||||
|
||||
class CesFunctionalAreaPlugin : public QObject, public CentralEffectSimulation::Plugin::Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "special:3:ces.CesFunctionalAreaPlugin")
|
||||
Q_INTERFACES(CentralEffectSimulation::Plugin::Plugin)
|
||||
|
||||
public:
|
||||
CesFunctionalAreaPlugin() = default;
|
||||
~CesFunctionalAreaPlugin() = 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 CES_FUNCTIONAL_AREAInterfaceImpl final : public CentralEffectSimulation::Plugin::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CES_FUNCTIONAL_AREAInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
CentralEffectSimulation::MainHandler *mainHandler);
|
||||
~CES_FUNCTIONAL_AREAInterfaceImpl();
|
||||
//bool init();
|
||||
const char *name() const override { return "CesFunctionalAreaPlugin"; }
|
||||
QString echo(const QString &message) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
bool init(int domainId, int exerciseId) override;
|
||||
private:
|
||||
|
||||
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::HandlerBuildingData> m_handlerBuildingData;
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant; ///< Pointer to handler for all participants
|
||||
|
||||
std::shared_ptr<HandlerFunctionalAreas> m_handlerFunctionalAreas; ///< Pointer to handler for participant outside from Buildings
|
||||
|
||||
|
||||
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
|
||||
int m_domainId = 0;
|
||||
int m_exerciseId = 0;
|
||||
};
|
||||
|
||||
} // namespace CES_FUNCTIONAL_AREA
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* CES Target Timer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
|
||||
#include "supplytimer.h"
|
||||
|
||||
namespace CES_FUNCTIONAL_AREA
|
||||
{
|
||||
|
||||
|
||||
SupplyTimer::SupplyTimer(int participantId,
|
||||
int aesId,
|
||||
int timeToEffectInterval_msec)
|
||||
{
|
||||
m_participantId = participantId;
|
||||
m_aesId = aesId;
|
||||
m_timeToEffectInterval = timeToEffectInterval_msec;
|
||||
m_timer = new QTimer(this);
|
||||
|
||||
connect(m_timer, &QTimer::timeout,
|
||||
this, &SupplyTimer::myTimerSlot);
|
||||
// msec
|
||||
}
|
||||
void SupplyTimer::startTimer()
|
||||
{
|
||||
if (m_timer->isActive())
|
||||
return;
|
||||
m_timer->setSingleShot(true);
|
||||
m_timer->start(m_timeToEffectInterval);
|
||||
}
|
||||
void SupplyTimer::stopTimer()
|
||||
{
|
||||
m_timer->stop();
|
||||
}
|
||||
|
||||
void SupplyTimer::myTimerSlot()
|
||||
{
|
||||
emit timeToEffectTimeout(m_participantId, m_aesId);
|
||||
}
|
||||
} // namespace CES_FUNCTIONAL_AREA
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* CES Supply Truck Timer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
namespace CES_FUNCTIONAL_AREA
|
||||
{
|
||||
|
||||
class SupplyTimer: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
SupplyTimer(int participantId,
|
||||
int aesId,
|
||||
int timeToEffectInterval_msec);
|
||||
|
||||
void startTimer();
|
||||
void stopTimer();
|
||||
bool isActive() { return m_timer->isActive(); }
|
||||
int getParticipantId() { return m_aesId; }
|
||||
public slots:
|
||||
void myTimerSlot();
|
||||
|
||||
signals:
|
||||
void timeToEffectTimeout(int participantId, int targetParticipantId);
|
||||
private:
|
||||
QTimer *m_timer{nullptr};
|
||||
int m_participantId{0};
|
||||
int m_aesId{0};
|
||||
int m_timeToEffectInterval{0};
|
||||
};
|
||||
|
||||
} // namespace CES_FUNCTIONAL_AREA
|
||||
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# monitoring of the target areas
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(SRCS
|
||||
handler_participant_gas_pipe.cpp
|
||||
handler_participant_gas_pipe.h
|
||||
plugin.cpp
|
||||
plugin.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV cesPluginGasPipes MODULE ${SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(cesPluginGasPipes
|
||||
Qt5::Network
|
||||
Qt5::Widgets
|
||||
cesPluginInterface
|
||||
ngldb
|
||||
svcCesDDSCommon
|
||||
# ProjectConfig
|
||||
)
|
||||
NGL_INSTALL_TARGET(cesPluginGasPipes)
|
||||
|
||||
+408
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#include "handler_aes_data.h"
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
//#include "main_handler.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <QPainterPath>
|
||||
#include <QPointF>
|
||||
#include <QPolygonF>
|
||||
#include <QTimer>
|
||||
#include <QTransform>
|
||||
|
||||
#include <LtsUtilsCore/dds_bitarray.h>
|
||||
#include <LtsUtilsCore/qpoint3d.h>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
|
||||
namespace CentralEffectSimulationGasPipes
|
||||
{
|
||||
|
||||
HandlerAesData::HandlerAesData(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
QObject *parent)
|
||||
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_handlerBuildingData(buildingDataHandler)
|
||||
, m_logger(getLogger("HandlerAesData"))
|
||||
{
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HandlerAesData::~HandlerAesData()
|
||||
{
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HandlerAesData::init()
|
||||
{
|
||||
auto dtcAes = m_ddsHandler->dtcAes();
|
||||
auto ftcTab = m_ddsHandler->ftcTab();
|
||||
dtcAes->waitForHistoricalDataExplosionSingleCentral(20000);
|
||||
ftcTab->enableSendCesHitInformation();
|
||||
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
|
||||
this, &HandlerAesData::onAesItemViewChanged);
|
||||
|
||||
// Get 'static' data for all AesItemView
|
||||
{
|
||||
auto cb = [this](const AreaEffectSimulation::AesItemView & aiv)
|
||||
{
|
||||
onAesItemViewChanged(aiv, DataModification::eAdded);
|
||||
};
|
||||
if (!dtcAes->aesItemViews(cb))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
// ///////////////////////////////////
|
||||
// A E S (AreaEffectSimulation)
|
||||
// ///////////////////////////////////
|
||||
|
||||
void HandlerAesData::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
|
||||
{
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got AesItemView: " << data.effectStateId();
|
||||
switch (data.effectStateId().underlying())
|
||||
{
|
||||
case AreaEffectSimulation::AesEffectState_def::EsUnknown:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsError:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsExpired:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsRemoved:
|
||||
removeStates(data);
|
||||
m_aesItemViews.remove(data.aesItemId());
|
||||
break;
|
||||
case AreaEffectSimulation::AesEffectState_def::EsPrepared:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsPaused:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsActivated:
|
||||
m_aesItemViews.insert(data.aesItemId(), data);
|
||||
break;
|
||||
case AreaEffectSimulation::AesEffectState_def::EsCreated:
|
||||
case AreaEffectSimulation::AesEffectState_def::EsReceived:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HandlerAesData::removeStates(const AreaEffectSimulation::AesItemView &data)
|
||||
{
|
||||
if (data.aesTypeId() != AreaEffectSimulation::AesType_def::AtExplosionArea)
|
||||
return;
|
||||
DEBUG_LOG(m_logger) << "Remove aesItemId=" << data.aesItemId();
|
||||
} // end removeStates
|
||||
|
||||
void HandlerAesData::onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType)
|
||||
{
|
||||
bool handleExplosion = false;
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
{
|
||||
m_explosionSingleState.remove(data.id());
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsRemoved)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Remove SingleExplosion";
|
||||
m_explosionSingleState.remove(data.id());
|
||||
return;
|
||||
}
|
||||
// Only handle transitions from prepared to activated
|
||||
if (m_explosionSingleState.value(data.id()) == AreaEffectSimulation::AesEffectState_def::EsPrepared
|
||||
&& data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsActivated)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Handle SingleExplosion";
|
||||
handleExplosion = true;
|
||||
}
|
||||
m_explosionSingleState.insert(data.id(), data.effectStateId());
|
||||
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got ExplosionSingle";
|
||||
if (handleExplosion)
|
||||
{
|
||||
const double impactRadius = m_ddsHandler->chargeTypeRadius(data.chargeTypeId());
|
||||
DEBUG_LOG(m_logger) << "Handle ExplosionSingle (EsActivated)";
|
||||
|
||||
// Bounding-Box-Check
|
||||
// QMap<int, Footprint> m_footprints;
|
||||
for (const Footprint &footprint : qAsConst(m_footprints))
|
||||
{
|
||||
const QPointF impactPos(CentralEffectSimulation::geographic2Utm(data.impactPosition(), footprint.zone));
|
||||
const QPolygonF polyBldgRadius({QPointF(footprint.boundingBoxPolyUtm.bottomLeft().rx() - impactRadius,
|
||||
footprint.boundingBoxPolyUtm.bottomLeft().ry() + impactRadius),
|
||||
QPointF(footprint.boundingBoxPolyUtm.topRight().rx() + impactRadius,
|
||||
footprint.boundingBoxPolyUtm.bottomLeft().ry() + impactRadius),
|
||||
QPointF(footprint.boundingBoxPolyUtm.topRight().rx() + impactRadius,
|
||||
footprint.boundingBoxPolyUtm.topRight().ry() - impactRadius),
|
||||
QPointF(footprint.boundingBoxPolyUtm.bottomLeft().rx() - impactRadius,
|
||||
footprint.boundingBoxPolyUtm.topRight().ry() - impactRadius)});
|
||||
if (polyBldgRadius.containsPoint(impactPos, Qt::OddEvenFill))
|
||||
{
|
||||
//calculateImpacts(data, footprint.mseId);
|
||||
// check, if impact-pos + munition-radius touch the building
|
||||
// get radius of munition
|
||||
const Core::GeoPosition2D impactPosition(data.impactPosition().lon(), data.impactPosition().lat());
|
||||
if (inFootprint(impactPosition, impactRadius, footprint))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "ftc sendCESHitOnBuilding mseId = " << footprint.mseId
|
||||
<< " chargeTypeId = " << data.chargeTypeId()
|
||||
<< " id = " << data.id()
|
||||
<< " currentPartitionTime = " << m_ddsHandler->currentPartitionTime()
|
||||
<< " impactPosition.lon = " << impactPosition.lon()
|
||||
<< " impactPosition.lat = " << impactPosition.lat();
|
||||
|
||||
Buildings::SendCesHitOnBuildingRequest requestBld(
|
||||
footprint.mseId,
|
||||
data.chargeTypeId(),
|
||||
data.id(),
|
||||
m_ddsHandler->currentPartitionTime(),
|
||||
Core::GeoPosition(impactPosition.lon(), impactPosition.lat(), 0.0));
|
||||
m_ddsHandler->ftcBld()->sendCesHitOnBuildingRequest(requestBld, this);
|
||||
}
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "Not sendCESHitOnBuilding mseId = " << footprint.mseId;
|
||||
|
||||
DEBUG_LOG(m_logger) << "boundingBoxImpact.contains(footprint)";
|
||||
}
|
||||
} // for
|
||||
}
|
||||
} // onExplosionSingleChanged
|
||||
|
||||
void HandlerAesData::onAirSupportImpactChanged(const AreaEffectSimulation::AirSupportImpact &data, DataModification modType)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Got onAirSupportImpactChanged()";
|
||||
AreaEffectSimulation::ExplosionSingle esData;
|
||||
esData.id(data.id());
|
||||
esData.chargeTypeId(data.chargeTypeId());
|
||||
esData.impactPosition(data.impactPosition());
|
||||
esData.effectStateId(data.effectStateId());
|
||||
onExplosionSingleChanged(esData, modType);
|
||||
} // onExplosionSingleChanged
|
||||
|
||||
void HandlerAesData::onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType)
|
||||
{
|
||||
if (modType != DataModification::eAdded &&
|
||||
modType != DataModification::eModified)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got TriggeredImpacts";
|
||||
preCalculateImpacts(data);
|
||||
}
|
||||
|
||||
// ///////////////////////////////////
|
||||
// I S M (InfrastructureManagement)
|
||||
// ///////////////////////////////////
|
||||
void HandlerAesData::onMainFootprintChanged(const InfrastructureManagement::MainFootprint &data, DataModification modType)
|
||||
{
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eAdded:
|
||||
case DataModification::eModified:
|
||||
DEBUG_LOG(m_logger) << "Got MainFootprint (Building)";
|
||||
calculateFootprint(data);
|
||||
break;
|
||||
case DataModification::eRemoved:
|
||||
m_footprints.remove(data.id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ///////////////////////////////////
|
||||
// Calculations:
|
||||
// ///////////////////////////////////
|
||||
|
||||
void HandlerAesData::calculateFootprint(const InfrastructureManagement::MainFootprint &mainFootprint)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Footprint: " << mainFootprint.id() << ": " << mainFootprint;
|
||||
DEBUG_LOG(m_logger) << "Footprint: " << " mainFootprint.elements().size()=" << mainFootprint.elements().size();
|
||||
|
||||
// If poly is Empty continue with next Footprint
|
||||
if (mainFootprint.elements().size() <= 0)
|
||||
return;
|
||||
|
||||
const InfrastructureManagement::MainStructureElement mse
|
||||
= m_handlerBuildingData->mainStructureElement(mainFootprint.id());
|
||||
if (mse.id() != mainFootprint.id())
|
||||
{
|
||||
// not (yet) there
|
||||
QTimer::singleShot(1000, this, [this, mainFootprint]() { calculateFootprint(mainFootprint); });
|
||||
return;
|
||||
}
|
||||
|
||||
// insert all Points to poly
|
||||
QPolygonF poly;
|
||||
poly.reserve(mainFootprint.elements().size());
|
||||
for (const InfrastructureManagement::FootprintElement &element : mainFootprint.elements())
|
||||
{
|
||||
const auto &relPos = element.relPosition();
|
||||
poly.push_back(QPointF(relPos.offsetX(), relPos.offsetY()));
|
||||
}
|
||||
|
||||
// rotate poly
|
||||
QTransform trans;
|
||||
trans.rotate(mse.angle());
|
||||
poly = trans.map(poly);
|
||||
|
||||
Footprint footprint;
|
||||
footprint.mseId = mainFootprint.id();
|
||||
footprint.geoPosition = mse.geoPosition();
|
||||
const QPointF utmFpPosition = CentralEffectSimulation::geographic2Utm(footprint.geoPosition, &footprint.zone);
|
||||
footprint.polyUtm.reserve(poly.size());
|
||||
for (const QPointF &point : qAsConst(poly))
|
||||
footprint.polyUtm.push_back(utmFpPosition + point);
|
||||
footprint.boundingBoxPolyUtm = footprint.polyUtm.boundingRect();
|
||||
|
||||
m_footprints.insert(footprint.mseId, footprint);
|
||||
}
|
||||
|
||||
bool HandlerAesData::inFootprint(const Core::GeoPosition2D &geoPosition, const double radius, const Footprint &footPrint) const
|
||||
{
|
||||
const QPointF impact(CentralEffectSimulation::geographic2Utm(geoPosition, footPrint.zone));
|
||||
|
||||
if (m_logger.isDebugEnabled())
|
||||
{
|
||||
const QPointF utmBuilding(CentralEffectSimulation::geographic2Utm(footPrint.geoPosition, footPrint.zone));
|
||||
DEBUG_LOG(m_logger) << "Impact (x/y)=" << CentralEffectSimulation::debug(impact - utmBuilding);
|
||||
for (int i = 0; i < footPrint.polyUtm.length(); i++)
|
||||
DEBUG_LOG(m_logger) << " poly (x/y)=" << CentralEffectSimulation::debug(footPrint.polyUtm[i] - utmBuilding);
|
||||
}
|
||||
|
||||
// Check, if hit direct on building
|
||||
if (footPrint.polyUtm.containsPoint(impact, Qt::OddEvenFill))
|
||||
return true;
|
||||
|
||||
// Check, if hit in munition-radius
|
||||
QPainterPath ppFp;
|
||||
ppFp.addPolygon(footPrint.polyUtm);
|
||||
QPainterPath ppCircle;
|
||||
ppCircle.addEllipse(impact, radius, radius);
|
||||
return ppFp.intersects(ppCircle);
|
||||
}
|
||||
|
||||
void HandlerAesData::preCalculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data)
|
||||
{
|
||||
if (data.id() <= 0)
|
||||
return;
|
||||
DEBUG_LOG(m_logger) << "preCalculateImpacts";
|
||||
// Find AES ItemView and set Bounding-Box of Aes-Field
|
||||
|
||||
// Search corresponding itemView and get boundingBox data in UTM
|
||||
const bool bFound = m_aesItemViews.contains(data.aesItemId());
|
||||
if (!bFound)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not find item view for aes with id " << data.aesItemId();
|
||||
return;
|
||||
}
|
||||
// Bounding-Box-Check
|
||||
// QMap<int, Footprint> m_footprints;
|
||||
for (const Footprint &footprint : qAsConst(m_footprints))
|
||||
{
|
||||
//if (boundingBoxImpact.contains(footprint.boundingBoxPolyUtm))
|
||||
calculateImpacts(data, footprint);
|
||||
} // for
|
||||
|
||||
}
|
||||
|
||||
void HandlerAesData::onSendCesHitOnBuildingReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
if (replyObject.error())
|
||||
WARNING_LOG(m_logger) << "Can not send hit on building to building service: " << replyObject();
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "onSendCesHitOnBuildingReply for id " << replyObject.id() << " success\n"
|
||||
<< " replyObject.str() = " << replyObject.str();
|
||||
}
|
||||
|
||||
void HandlerAesData::onSendCesHitInformationReply(const Core::FunctionReplyObject &reply)
|
||||
{
|
||||
if (reply.error())
|
||||
WARNING_LOG(m_logger) << "onSendCesHitInformationReply for id " << reply.id() << " failed: " << reply.str();
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "onSendCesHitInformationReply for id " << reply.id() << " successful";
|
||||
}
|
||||
|
||||
// calculate impacts for one building
|
||||
void HandlerAesData::calculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data, const Footprint &footprint)
|
||||
{
|
||||
// check for correct AES type artillery only
|
||||
switch (data.aesTypeId().underlying())
|
||||
{
|
||||
case AreaEffectSimulation::AesType_def::AtExplosionArea:
|
||||
case AreaEffectSimulation::AesType_def::AtExplosionSingle:
|
||||
case AreaEffectSimulation::AesType_def::AtExplosionAreaSingleExplosions:
|
||||
DEBUG_LOG(m_logger) << "Calculate";
|
||||
break;
|
||||
default:
|
||||
DEBUG_LOG(m_logger) << "No Calculation";
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "calculateImpacts mseId=" << footprint.mseId << " data.aesItemId() " << data.aesItemId();
|
||||
|
||||
|
||||
// get position(s) of impact(s):
|
||||
|
||||
// Search corresponding itemView. If not available no impact to participant.
|
||||
auto it = m_aesItemViews.constFind(data.aesItemId());
|
||||
if (it == m_aesItemViews.constEnd())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "TriggeredExplosions.aesItemId=" << data.aesItemId() << " No aesItemView available";
|
||||
return;
|
||||
}
|
||||
|
||||
BitfieldStates &bitfieldStates = m_bitfieldStatesBld[footprint.mseId];
|
||||
QSet<int> &bitfieldState = bitfieldStates[data.aesItemId()];
|
||||
for (int i : qAsConst(bitfieldState))
|
||||
DEBUG_LOG(m_logger) << "bitfieldState for " << data.aesItemId() << ": " << i;
|
||||
|
||||
const AreaEffectSimulation::AesItemView &aesItemView = *it;
|
||||
for (int32_t bitFieldIdx = 0; bitFieldIdx < data.impactCount(); ++bitFieldIdx)
|
||||
{
|
||||
// no break, because every bit can be a hit
|
||||
if (LtsUtils::BitArray::testBit(data.bitfield(), bitFieldIdx))
|
||||
continue;
|
||||
|
||||
// get position of impact to corresponding bit
|
||||
if (aesItemView.form().size() <= size_t(bitFieldIdx))
|
||||
continue;
|
||||
|
||||
const Core::GeoPosition2D &impactPosition = aesItemView.form()[bitFieldIdx];
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION
|
||||
<< " impactPosition: lat/lon" << impactPosition.lat() << "/" << impactPosition.lon()
|
||||
<< " UTM=" << CentralEffectSimulation::debug(CentralEffectSimulation::geographic2Utm(impactPosition));
|
||||
|
||||
// check, if impact-pos + munition-radius touch the building
|
||||
// get radius of munition
|
||||
const double impactRadius = m_ddsHandler->chargeTypeRadius(aesItemView.chargeTypeId());
|
||||
if (inFootprint(impactPosition, impactRadius, footprint))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "In Footprint mseId = " << footprint.mseId;
|
||||
if (!bitfieldState.contains(bitFieldIdx))
|
||||
{
|
||||
bitfieldState.insert(bitFieldIdx);
|
||||
|
||||
DEBUG_LOG(m_logger) << "m_bitfieldStates.insert(data.aesItemId()=" << data.aesItemId() << ", bitfieldState)" << " bitFieldIdx=" << bitFieldIdx;
|
||||
|
||||
DEBUG_LOG(m_logger) << "ftc sendCESHitOnBuilding mseId = " << footprint.mseId << " bitFieldIdx= " << bitFieldIdx ;
|
||||
Buildings::SendCesHitOnBuildingRequest requestBld(
|
||||
footprint.mseId,
|
||||
aesItemView.chargeTypeId(),
|
||||
aesItemView.aesItemId(),
|
||||
m_ddsHandler->currentPartitionTime(),
|
||||
Core::GeoPosition(impactPosition.lon(), impactPosition.lat(), 0.0));
|
||||
m_ddsHandler->ftcBld()->sendCesHitOnBuildingRequest(requestBld, this);
|
||||
}
|
||||
}
|
||||
} // foreach Impact
|
||||
}
|
||||
|
||||
} // namespace CentralEffectSimulationGasPipes
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include "logger.h"
|
||||
|
||||
#include <AreaEffectSimulation/aes_dtc.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>
|
||||
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
class QPoint3D;
|
||||
}
|
||||
|
||||
// AES-Handling for gas pipes
|
||||
|
||||
namespace CentralEffectSimulationGasPipes
|
||||
{
|
||||
|
||||
|
||||
class HandlerAesData : public QObject
|
||||
, protected TrainingAreaBase::Interface::Ftc::SendCesHitInformationReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HandlerAesData(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~HandlerAesData();
|
||||
|
||||
/**
|
||||
* Initialize the handler to manage information from player management
|
||||
*/
|
||||
bool init();
|
||||
AreaEffectSimulation::AesItemView itemView(const int &aesId) const { return m_aesItemViews.value(aesId); }
|
||||
|
||||
protected:
|
||||
void onSendCesHitInformationReply(const Core::FunctionReplyObject &reply) override final;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* Handle the signals from 'AES'
|
||||
*/
|
||||
void onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType);
|
||||
void onAirSupportImpactChanged(const AreaEffectSimulation::AirSupportImpact &data, DataModification modType);
|
||||
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
|
||||
void onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType);
|
||||
|
||||
/**
|
||||
* Handle MainFootprint from 'ISM'
|
||||
*/
|
||||
void onMainFootprintChanged(const InfrastructureManagement::MainFootprint &data, DataModification modType);
|
||||
|
||||
void removeStates(const AreaEffectSimulation::AesItemView &data);
|
||||
|
||||
private: // structs
|
||||
struct Footprint
|
||||
{
|
||||
int mseId = -1;
|
||||
int zone = -1;
|
||||
Core::GeoPosition geoPosition;
|
||||
QPolygonF polyUtm;
|
||||
QRectF boundingBoxPolyUtm;
|
||||
|
||||
bool isValid() const { return mseId > 0; }
|
||||
};
|
||||
|
||||
typedef QHash<int, QSet<int>> BitfieldStates;
|
||||
|
||||
private: // methoden
|
||||
void handleExplosionSingleCentral(const AreaEffectSimulation::AesItemView &itemView);
|
||||
|
||||
void calculateFootprint(const InfrastructureManagement::MainFootprint &mainFootprint);
|
||||
|
||||
bool inFootprint(const Core::GeoPosition2D &geoPosition, const double radius, const Footprint &footPrint) const;
|
||||
|
||||
void preCalculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data);
|
||||
void calculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data, const Footprint &footprint);
|
||||
double getRadiusOfMunition(const int32_t chargeTypeId) const;
|
||||
|
||||
|
||||
private: // attributes
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
|
||||
|
||||
QHash<int, Footprint> m_footprints; // key = footprint.mseId
|
||||
|
||||
// AES-Values
|
||||
QHash<int, AreaEffectSimulation::AesItemView> m_aesItemViews; // key = aesItemId
|
||||
QHash<int, AreaEffectSimulation::AesEffectState> m_explosionSingleState; // key = id value = state
|
||||
|
||||
NGL::INGLLogger &m_logger; ///< Interface to the Logging-Facility
|
||||
|
||||
};
|
||||
|
||||
} // namespace CentralEffectSimulationGasPipes
|
||||
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#include "handler_participant_gas_pipe.h"
|
||||
|
||||
#include <QLineF>
|
||||
#include <QTimer>
|
||||
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
namespace CentralEffectSimulationGasPipes
|
||||
{
|
||||
|
||||
HandlerParticipantGasPipe::HandlerParticipantGasPipe(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_ddsHandler(ddsHandler)
|
||||
, m_handlerParticipant(participantHandler)
|
||||
// , m_handlerAesData(aesDataHandler)
|
||||
, m_gasPipes()
|
||||
, m_requestMap()
|
||||
, m_timer(new QTimer(this))
|
||||
, m_logger(CentralEffectSimulation::getLogger("Plugin.VirtualMines.HandlerParticipantGasPipe"))
|
||||
{
|
||||
m_timer->setSingleShot(true);
|
||||
connect(m_timer, &QTimer::timeout, this, &HandlerParticipantGasPipe::sendFtcCesHitRequestTimeout);
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HandlerParticipantGasPipe::~HandlerParticipantGasPipe()
|
||||
{
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool HandlerParticipantGasPipe::init()
|
||||
{
|
||||
INFO_LOG(m_logger) << "HandlerParticipantGasPipe::init";
|
||||
auto dtcAes = m_ddsHandler->dtcAes();
|
||||
dtcAes->waitForHistoricalDataGasPipe(2000);
|
||||
|
||||
dtcAes->enableAesItemView();
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
|
||||
this, &HandlerParticipantGasPipe::onAesItemViewChanged);
|
||||
|
||||
dtcAes->enableGasPipe();
|
||||
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::gasPipeChanged,
|
||||
this, &HandlerParticipantGasPipe::onGasPipeChanged);
|
||||
|
||||
//connect(m_handlerParticipant.get(), &HandlerParticipant::newIndoorPosition,
|
||||
// this, &HandlerParticipantGasPipe::onParticipantPositionChanged);
|
||||
//connect(m_handlerParticipant.get(), &HandlerParticipant::newOutdoorPosition,
|
||||
// this, &HandlerParticipantGasPipe::onParticipantPositionChanged);
|
||||
|
||||
// Get 'static' data for all onAesItemView
|
||||
{
|
||||
auto cb = [this](const AreaEffectSimulation::AesItemView & aiv)
|
||||
{
|
||||
onAesItemViewChanged(aiv, DataModification::eAdded);
|
||||
};
|
||||
if (!dtcAes->aesItemViews(cb))
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(m_logger) << "HandlerParticipantGasPipe::init() finished. ";
|
||||
return true;
|
||||
} // end of init()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// ///////////////////////////////////
|
||||
// A E S (AreaEffectSimulation)
|
||||
// ///////////////////////////////////
|
||||
void HandlerParticipantGasPipe::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
|
||||
{
|
||||
INFO_LOG(m_logger) << "HandlerParticipantGasPipe::onAesItemViewChanged";
|
||||
//
|
||||
if (data.aesTypeId() != AreaEffectSimulation::AesType_def::AtGasPipe)
|
||||
return;
|
||||
|
||||
|
||||
const int aesItemId = data.aesItemId();
|
||||
DEBUG_LOG(m_logger) << "Got AesItemView id: " << aesItemId
|
||||
<< ", type: " << data.aesTypeId()
|
||||
<< ", effectState: " << data.effectStateId()
|
||||
<< ", modType: " << modType;
|
||||
|
||||
if (modType == DataModification::eRemoved)
|
||||
{
|
||||
m_gasPipes.remove(aesItemId);
|
||||
return;
|
||||
}
|
||||
if (modType == DataModification::eAdded
|
||||
|| modType == DataModification::eModified)
|
||||
{
|
||||
|
||||
const AreaEffectSimulation::AesEffectState &effectState = data.effectStateId();
|
||||
switch (effectState.underlying())
|
||||
{
|
||||
case AreaEffectSimulation::AesEffectState_def::EsActivated:
|
||||
{
|
||||
CentralEffectSimulation::AesItemViewUtm prevData;
|
||||
const double impactRadius = 0;
|
||||
prevData.aesItemId = 0;
|
||||
|
||||
const CentralEffectSimulation::AesItemViewUtm gasPipeUtm = CentralEffectSimulation::AesItemViewUtm::create(data, prevData, impactRadius);
|
||||
m_gasPipes.insert(data.aesItemId(), gasPipeUtm);
|
||||
DEBUG_LOG(m_logger) << "Check each participant";
|
||||
// Check each participant
|
||||
const auto partPosMap = m_handlerParticipant->positions();
|
||||
for (const auto &participantPos : partPosMap)
|
||||
{
|
||||
if (m_handlerParticipant->isOutdated(participantPos))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "isOutdated participantId=" << participantPos.participantId();
|
||||
continue;
|
||||
}
|
||||
const CentralEffectSimulation::AesItemViewUtm gasPipe = m_gasPipes.value(data.aesItemId());
|
||||
calculateGasPipeParticipant(gasPipe, participantPos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "remove GasPipe";
|
||||
m_gasPipes.remove(aesItemId);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} // onAesItemViewChanged
|
||||
|
||||
|
||||
void HandlerParticipantGasPipe::onGasPipeChanged(const AreaEffectSimulation::GasPipe &data, DataModification modType)
|
||||
{
|
||||
INFO_LOG(m_logger) << "HandlerParticipantGasPipe::onGasPipeChanged id=" << data.id();
|
||||
if (modType == DataModification::eRemoved)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool HandlerParticipantGasPipe::insideGasPipeArea(const QPolygonF &polygonf, const QPointF &participantPos) const
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "pos to check: " << CentralEffectSimulation::debug(participantPos) ;
|
||||
return polygonf.containsPoint(participantPos, Qt::OddEvenFill);
|
||||
}
|
||||
|
||||
void HandlerParticipantGasPipe::calculateGasPipeParticipant(const CentralEffectSimulation::AesItemViewUtm &gasPipe,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition)
|
||||
{
|
||||
//const AesItemViewUtm gasPipe = m_gasPipes.value(itemView.aesItemId());
|
||||
const QPointF partPosGeo = CentralEffectSimulation::geographic2Utm(participantPosition.pos(), gasPipe.zone);
|
||||
|
||||
DEBUG_LOG(m_logger) << "calculateGasPipeParticipant itemView.id=" << gasPipe.aesItemId
|
||||
<< " participantId=" << participantPosition.participantId();
|
||||
|
||||
DEBUG_LOG(m_logger) << "gasPipe id = " << gasPipe.aesItemId
|
||||
<< ", Box bottomLeft = " << CentralEffectSimulation::debug(gasPipe.boundingBoxBottomLeft)
|
||||
<< ", topRight = " << CentralEffectSimulation::debug(gasPipe.boundingBoxTopRight);
|
||||
|
||||
const QPolygonF boundingBoxGasPipe({QPointF(gasPipe.boundingBoxBottomLeft.x(),
|
||||
gasPipe.boundingBoxBottomLeft.y()),
|
||||
QPointF(gasPipe.boundingBoxTopRight.x(),
|
||||
gasPipe.boundingBoxBottomLeft.y()),
|
||||
QPointF(gasPipe.boundingBoxTopRight.x(),
|
||||
gasPipe.boundingBoxTopRight.y()),
|
||||
QPointF(gasPipe.boundingBoxBottomLeft.x(),
|
||||
gasPipe.boundingBoxTopRight.y())
|
||||
});
|
||||
if (!boundingBoxGasPipe.containsPoint(partPosGeo, Qt::OddEvenFill))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "not in boundingBox";
|
||||
return;
|
||||
}
|
||||
const bool result = insideGasPipeArea(gasPipe.form, partPosGeo);
|
||||
DEBUG_LOG(m_logger) << "result gasPipe Explosion = " << result;
|
||||
if (result)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendParticipantEvent";
|
||||
sendParticipantEvent(gasPipe, participantPosition, ProjectDataManagement::EventType_def::HitGasPipe);
|
||||
DEBUG_LOG(m_logger) << "sendParticipantHit";
|
||||
sendParticipantHit(gasPipe, participantPosition, ProjectDataManagement::EventType_def::HitGasPipe);
|
||||
}
|
||||
}
|
||||
|
||||
void HandlerParticipantGasPipe::onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos)
|
||||
{
|
||||
bool result = false;
|
||||
// Bounding Box von der Linie
|
||||
DEBUG_LOG(m_logger) << "ParicipantPos "
|
||||
<< " participantId=" << partPos.participantId()
|
||||
<< " participantTypeId=" << partPos.participantTypeId()
|
||||
<< " participantPos: lat=" << partPos.pos().lat()
|
||||
<< " lon=" << partPos.pos().lon()
|
||||
<< " Anzahl GasPipes=" << m_gasPipes.size();
|
||||
|
||||
|
||||
for (const CentralEffectSimulation::AesItemViewUtm &gasPipe : qAsConst(m_gasPipes))
|
||||
{
|
||||
calculateGasPipeParticipant(gasPipe, partPos);
|
||||
|
||||
const QPointF partPosGeo = CentralEffectSimulation::geographic2Utm(partPos.pos(), gasPipe.zone);
|
||||
|
||||
DEBUG_LOG(m_logger) << "gasPipe id = " << gasPipe.aesItemId
|
||||
<< ", Box bottomLeft = " << CentralEffectSimulation::debug(gasPipe.boundingBoxBottomLeft)
|
||||
<< ", topRight = " << CentralEffectSimulation::debug(gasPipe.boundingBoxTopRight);
|
||||
|
||||
// if (!m_gasPipes.value(gasPipe.aesItemId).containsPoint(partPosGeo, Qt::OddEvenFill))
|
||||
// continue;
|
||||
result = insideGasPipeArea(gasPipe.form, partPosGeo);
|
||||
DEBUG_LOG(m_logger) << "result gasPipe Explosion = " << result<< gasPipe.aesItemId;
|
||||
if (result)
|
||||
sendParticipantEvent(gasPipe, partPos, ProjectDataManagement::EventType_def::HitGasPipe);
|
||||
}
|
||||
} // end of onParticipantPositionChanged()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// ///////////////////////////////////
|
||||
// P D M (ProjectDataManagement)
|
||||
// ///////////////////////////////////
|
||||
// Search for corresponding aesItemView
|
||||
// Check for all participants wheter he is in the explosion area
|
||||
|
||||
|
||||
void HandlerParticipantGasPipe::sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &gasPipe,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
|
||||
const ProjectDataManagement::EventType eventType)
|
||||
{
|
||||
ParticipantManagement::TypeClass typeClass = m_handlerParticipant->typeClassFromTypeId(participantPosition.participantTypeId());
|
||||
|
||||
if (typeClass == ParticipantManagement::TypeClass_def::Unit ||
|
||||
typeClass == ParticipantManagement::TypeClass_def::SupportUnit ||
|
||||
typeClass == ParticipantManagement::TypeClass_def::SupportEntity ||
|
||||
typeClass == ParticipantManagement::TypeClass_def::Unknown)
|
||||
return;
|
||||
|
||||
int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantPosition.participantId());
|
||||
if (equipmentNumber <= 0)
|
||||
return;
|
||||
|
||||
const AreaEffectSimulation::GasPipe &gp = m_ddsHandler->dtcAes()->gasPipe(gasPipe.aesItemId);
|
||||
|
||||
CentralEffectSimulation::ParticipantEvent pe;
|
||||
DEBUG_LOG(m_logger) << "sendParticipantEvent participantId=" << participantPosition.participantId()
|
||||
<< " lat= " << participantPosition.pos().lat()
|
||||
<< " lon= " << participantPosition.pos().lon()
|
||||
<< " equipmentNumber=" << equipmentNumber
|
||||
<< " eventType=" << eventType;
|
||||
pe.id(m_ddsHandler->getParticipantEventId());
|
||||
pe.eventTypeId(eventType);
|
||||
pe.participantId(participantPosition.participantId());
|
||||
pe.eventTime(participantPosition.sampleTime());
|
||||
pe.aesItemId(gasPipe.aesItemId);
|
||||
pe.partyId(participantPosition.partyId());
|
||||
pe.aesName(gp.name());
|
||||
pe.equipmentNumber(equipmentNumber);
|
||||
pe.position(participantPosition.pos());
|
||||
|
||||
m_ddsHandler->dtsCes()->publish(pe);
|
||||
qint64 id = pe.id();
|
||||
QTimer::singleShot(1 * 60 * 1000, this, [id, this]() { m_ddsHandler->dtsCes()->removeParticipantEventByKey(id); });
|
||||
}
|
||||
|
||||
void HandlerParticipantGasPipe::sendParticipantHit(const CentralEffectSimulation::AesItemViewUtm &gasPipe,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
|
||||
const ProjectDataManagement::EventType eventType)
|
||||
{
|
||||
|
||||
const int equipNo = m_ddsHandler->participantId2EquipNo(participantPosition.participantId());
|
||||
const int participantId = participantPosition.participantId();
|
||||
const int originatorEquipNo = 0;
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendParticipantHit participantId=" << participantId
|
||||
<< " equipmentNumber=" << equipNo;
|
||||
|
||||
Core::GeoPosition position;
|
||||
position.lat(participantPosition.pos().lat());
|
||||
position.lon(participantPosition.pos().lon());
|
||||
|
||||
const TrainingAreaBase::TabPosition pos(position, participantPosition.reportingSource(), 0, 0);
|
||||
//pos.position(position);
|
||||
//pos.reportingSource(participantPosition.reportingSource());
|
||||
|
||||
TrainingAreaBase::SendCesHitRequest requestTab(
|
||||
equipNo, // equipmentNumber
|
||||
participantId, // participantId
|
||||
gasPipe.chargeTypeId, // chargeTypeId
|
||||
gasPipe.aesItemId, // aesId
|
||||
originatorEquipNo, // originatorEquipmentNumber
|
||||
100, // IED heavy
|
||||
pos,
|
||||
gasPipe.effectStart, // effectTime
|
||||
eventType,
|
||||
gasPipe.partyId, // originPartyId
|
||||
0
|
||||
);
|
||||
m_requestMap.insert(equipNo, requestTab);
|
||||
if (!m_timer->isActive() && !m_requestMap.isEmpty())
|
||||
m_timer->start(1000);
|
||||
}
|
||||
|
||||
void HandlerParticipantGasPipe::onSendCesHitReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
//if (replyObject.error())
|
||||
// WARNING_LOG(m_logger) << "Can not send hit on participant to training area: " << replyObject();
|
||||
//else
|
||||
DEBUG_LOG(m_logger) << "onSendCesHitReply for id " << replyObject.id() << " success";
|
||||
}
|
||||
|
||||
void HandlerParticipantGasPipe::sendFtcCesHitRequestTimeout()
|
||||
{
|
||||
auto ftcTab = m_ddsHandler->ftcTab();
|
||||
for (const TrainingAreaBase::SendCesHitRequest &hr : qAsConst(m_requestMap))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendFtcCesHitRequestTimeout: " << hr;
|
||||
ftcTab->sendCesHitRequest(hr, this);
|
||||
}
|
||||
m_requestMap.clear();
|
||||
}
|
||||
} // namespace CentralEffectSimulationGasPipes
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Handler for player data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by gr, SLSE, 2017-02-20
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QRectF>
|
||||
#include <QPolygonF>
|
||||
|
||||
#include <CentralEffectSimulation/dds_handler.h>
|
||||
#include <handler_aes_data.h>
|
||||
#include <CentralEffectSimulation/aes_item_view_utm.h>
|
||||
|
||||
#include <AreaEffectSimulation/aes_dtc.h>
|
||||
#include <CentralEffectSimulation/handler_participant.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
// AES-Handling for participants
|
||||
namespace CentralEffectSimulationGasPipes
|
||||
{
|
||||
|
||||
class HandlerParticipantGasPipe final : public QObject
|
||||
, protected TrainingAreaBase::Interface::Ftc::SendCesHitReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HandlerParticipantGasPipe(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
|
||||
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
~HandlerParticipantGasPipe();
|
||||
|
||||
/**
|
||||
* Initialize the handler to manage information from player management
|
||||
*/
|
||||
bool init();
|
||||
|
||||
protected:
|
||||
void onSendCesHitReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
private Q_SLOTS:
|
||||
/**
|
||||
* Handle the signals from 'ParticipantHandler'
|
||||
*/
|
||||
void onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos);
|
||||
|
||||
/**
|
||||
* Handle the signals from 'AES'
|
||||
*/
|
||||
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
|
||||
|
||||
void onGasPipeChanged(const AreaEffectSimulation::GasPipe &data, DataModification modType);
|
||||
|
||||
/**
|
||||
* Send Hit to participant
|
||||
*/
|
||||
void sendFtcCesHitRequestTimeout();
|
||||
|
||||
private: // methoden
|
||||
void sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &gasPipe,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
|
||||
const ProjectDataManagement::EventType eventType);
|
||||
void sendParticipantHit(const CentralEffectSimulation::AesItemViewUtm &gasPipe,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
|
||||
const ProjectDataManagement::EventType eventType);
|
||||
|
||||
bool insideGasPipeArea(const QPolygonF &polygonf, const QPointF &participantPos) const;
|
||||
void calculateGasPipeParticipant(const CentralEffectSimulation::AesItemViewUtm &gasPipe,
|
||||
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition);
|
||||
|
||||
private: // attributes
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
|
||||
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant;
|
||||
// std::shared_ptr<HandlerAesData> m_handlerAesData;
|
||||
|
||||
// AES-Values
|
||||
QHash<int, CentralEffectSimulation::AesItemViewUtm> m_gasPipes; // key = aesItemId
|
||||
|
||||
QHash<int, TrainingAreaBase::SendCesHitRequest> m_requestMap; // Key = equipmentNumber
|
||||
QTimer *m_timer;
|
||||
|
||||
|
||||
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility};
|
||||
};
|
||||
} // namespace CentralEffectSimulationGasPipes
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Plugin Ces Virtual Mines
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include <ngldb/db_service_handler.h>
|
||||
|
||||
namespace CesGasPipes
|
||||
{
|
||||
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> CesGasPipesPlugin::createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
CentralEffectSimulation::MainHandler *mainHandler)
|
||||
{
|
||||
return std::make_shared<CesGasPipesInterfaceImpl>(pdp, dDSConnector, settings, mainHandler);
|
||||
}
|
||||
|
||||
|
||||
CesGasPipesInterfaceImpl::CesGasPipesInterfaceImpl(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.GasPipes.CesMinesInterfaceImpl"))
|
||||
{
|
||||
Q_UNUSED(settings)
|
||||
}
|
||||
|
||||
CesGasPipesInterfaceImpl::~CesGasPipesInterfaceImpl()
|
||||
{
|
||||
// m_handlerParticipantBoobyTrap.reset();
|
||||
// m_handlerParticipantOffRouteMine.reset();
|
||||
}
|
||||
|
||||
|
||||
bool CesGasPipesInterfaceImpl::init(int domainId, int exerciseId)
|
||||
{
|
||||
m_domainId = domainId;
|
||||
m_exerciseId = exerciseId;
|
||||
INFO_LOG(m_logger) << "CesGasPipesInterfaceImpl::init()"
|
||||
<< " m_domainId=" << m_domainId
|
||||
<< " m_exerciseId=" << m_exerciseId;
|
||||
|
||||
|
||||
|
||||
// // initialize handlerBoobyTrap
|
||||
// m_handlerParticipantBoobyTrap = std::make_shared<HandlerParticipantBoobyTrap>(m_ddsHandler,
|
||||
// m_handlerParticipant,
|
||||
// this);
|
||||
|
||||
// if (!m_handlerParticipantBoobyTrap->init())
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Initialisation m_handlerParticipantBoobyTrap failed.";
|
||||
// return false;
|
||||
// }
|
||||
|
||||
|
||||
// // initialize offRouteMine
|
||||
// m_handlerParticipantOffRouteMine = std::make_shared<HandlerParticipantOffRouteMine>(m_ddsHandler,
|
||||
// m_handlerParticipant,
|
||||
// this);
|
||||
|
||||
// if (!m_handlerParticipantOffRouteMine->init())
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Initialisation m_handlerParticipantOffRouteMine failed.";
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString CesGasPipesInterfaceImpl::echo(const QString &message)
|
||||
{
|
||||
|
||||
QString ret(QStringLiteral("<<<< %1 >>>> CesGasPipesInterfaceImpl::echo").arg(message));
|
||||
INFO_LOG(m_logger) << "CesGasPipesInterfaceImpl::echo return:" << ret;
|
||||
DEBUG_LOG(m_logger) << "DEBUG: CesGasPipesInterfaceImpl::echo return:" << ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} //namespace CesGasPipes
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Plugin Ces Virtual Mines
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#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 CesGasPipes
|
||||
{
|
||||
|
||||
class CesGasPipesPlugin : public QObject, public CentralEffectSimulation::Plugin::Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "special:3:ces.CesGasPipesPlugin")
|
||||
Q_INTERFACES(CentralEffectSimulation::Plugin::Plugin)
|
||||
|
||||
public:
|
||||
CesGasPipesPlugin() = default;
|
||||
~CesGasPipesPlugin() = 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 CesGasPipesInterfaceImpl final : public CentralEffectSimulation::Plugin::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CesGasPipesInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
|
||||
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
|
||||
NGL::Settings *settings,
|
||||
CentralEffectSimulation::MainHandler *mainHandler);
|
||||
~CesGasPipesInterfaceImpl();
|
||||
//bool init();
|
||||
const char *name() const override { return "CentralEffectGasPipes"; }
|
||||
QString echo(const QString &message) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
bool init(int domainId, int exerciseId) override;
|
||||
private:
|
||||
|
||||
private:
|
||||
CentralEffectSimulation::Plugin::DataProvider *m_pdp;
|
||||
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<HandlerParticipantBoobyTrap> m_handlerParticipantBoobyTrap; ///< Pointer to handler for BoobyTrap
|
||||
// std::shared_ptr<HandlerParticipantOffRouteMine> m_handlerParticipantOffRouteMine; ///< Pointer to handler for OffRouteMine
|
||||
|
||||
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
|
||||
int m_domainId = 0;
|
||||
int m_exerciseId = 0;
|
||||
};
|
||||
|
||||
} // namespace CesGasPipes
|
||||
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# monitoring of the target areas
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(SRCS
|
||||
plugin.cpp
|
||||
plugin.h
|
||||
handler_geopairing.cpp
|
||||
handler_geopairing.h
|
||||
settings.cpp
|
||||
settings.h
|
||||
GeoPairing/GeoPairing.cpp
|
||||
GeoPairing/GeoPairing.hpp
|
||||
logger.cpp
|
||||
logger.h
|
||||
)
|
||||
|
||||
# 22.11.2024, Norbert Thoden
|
||||
# cesPluginGeoPairing is a MODULE; not a SHARED
|
||||
# So NGL_ADD_LIBRARY2 SHARED with would create ./Plugins/GeoPairing/cesplugingeopairing_export.h,
|
||||
# but not with MODULE.
|
||||
# But is an export macro realy needed? -> No
|
||||
NGL_ADD_LIBRARY(AAR SV cesPluginGeoPairing MODULE ${SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(cesPluginGeoPairing
|
||||
Qt5::Network
|
||||
Qt5::Widgets
|
||||
cesPluginInterface
|
||||
ngldb
|
||||
svcCesDDSCommon
|
||||
# GeoParing stuff
|
||||
GBL_Types
|
||||
GBL_ConfigSystem
|
||||
FW_Ballistic
|
||||
svcCesGeoPairingImpl
|
||||
${SCHUSSTAFEL_LIBRARY}
|
||||
)
|
||||
NGL_INSTALL_TARGET(cesPluginGeoPairing)
|
||||
|
||||
ADD_SUBDIRECTORY(GBL_Global)
|
||||
ADD_SUBDIRECTORY(GBL_ConfigSystem)
|
||||
ADD_SUBDIRECTORY(GBL_Types)
|
||||
ADD_SUBDIRECTORY(FW_Ballistic)
|
||||
ADD_SUBDIRECTORY(GeoPairingImpl)
|
||||
ADD_SUBDIRECTORY(GeoPairing)
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
#include <GBL_Global/Types.hpp>
|
||||
#include <QString>
|
||||
|
||||
#include "DiscreteType.hpp"
|
||||
#include "PolygonParamType.hpp"
|
||||
#include "CWParamType.hpp"
|
||||
#include "StandardType.hpp"
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* This is the container class for ammunitions
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 10-Aug-2009 11:04:46
|
||||
*/
|
||||
struct Ammunition
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 10-Aug-2009 11:10:21
|
||||
*/
|
||||
struct AmmunInfoType
|
||||
{
|
||||
QString m_Name;
|
||||
/**
|
||||
* Caliber of the ammunition, usually the diameter
|
||||
*/
|
||||
Float64 m_Caliber = 0.0;
|
||||
/**
|
||||
* The nominal shooting range
|
||||
*/
|
||||
Float64 m_Range = 0.0;
|
||||
/**
|
||||
* The initial velocity
|
||||
*/
|
||||
Float64 m_Speed = 0.0;
|
||||
Float64 m_TimeOut = 0.0;
|
||||
/**
|
||||
* The calculation algorithm, can be "Generic", "PitonBressant" or "DAntonio"
|
||||
*/
|
||||
QString m_Algorithm;
|
||||
/**
|
||||
* Can be "OnTimer" or "OnDetonate"
|
||||
*/
|
||||
QString m_ReasonToDetonate;
|
||||
/**
|
||||
* This is the value of devivation of the ammunition (impact position variance)
|
||||
*/
|
||||
Float64 m_Deviation = 0.0;
|
||||
/**
|
||||
* This is the value of derivation of the ammunition (impact position right drift)
|
||||
*/
|
||||
Float64 m_Derivation = 0.0;
|
||||
};
|
||||
|
||||
DiscreteType m_DiscreteParams;
|
||||
PolygonParamType m_PolygonParams;
|
||||
Ammunition::AmmunInfoType m_AmmunInfo;
|
||||
StandardType m_StandardParams;
|
||||
CWParamType m_CWParams;
|
||||
};
|
||||
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Service Base
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
// siehe SF_munitionsart_et
|
||||
/*
|
||||
enum ammunitionTypeIndirectFire {
|
||||
UNKNOWN = 0,
|
||||
STEILFEUER_HE_AZ = 1,
|
||||
STEILFEUER_HE_DZ = 2,
|
||||
STEILFEUER_BOMBLET = 3,
|
||||
STEILFEUER_SM_ART = 4,
|
||||
NEBEL = 5,
|
||||
MOERSER = 9,
|
||||
MOERSER_AZ = 10,
|
||||
MOERSER_ANNZ = 11,
|
||||
FLAEFLU_BK = 20,
|
||||
FLAEFLU_RAKETE = 21,
|
||||
FLAEFLU_BOMBLET = 22,
|
||||
FLAEFLU_SB = 23,
|
||||
IGLA = 25,
|
||||
MK19_M430 = 111,
|
||||
MK19_M385 = 112
|
||||
};*/
|
||||
enum ammunitionTypeIndirectFire { // TODO clarify values
|
||||
UNKNOWN = 0,
|
||||
STEILFEUER_HE_AZ = 371,
|
||||
STEILFEUER_HE_DZ = 372,
|
||||
STEILFEUER_BOMBLET = 373,
|
||||
STEILFEUER_SM_ART = 374,
|
||||
NEBEL = 385,
|
||||
MOERSER = 381,
|
||||
MOERSER_AZ = 381,
|
||||
MOERSER_ANNZ = 381,
|
||||
FLAEFLU_BK = 471,
|
||||
FLAEFLU_RAKETE = 472,
|
||||
FLAEFLU_BOMBLET = 473,
|
||||
FLAEFLU_SB = 474,
|
||||
IGLA = 25,
|
||||
MK19_M430 = 27,
|
||||
MK19_M385 = 26
|
||||
};
|
||||
enum ammunitionTypeOSAG {
|
||||
UNKNOWN_OSAG = 0,
|
||||
MK19_M385_OSAG = 26,
|
||||
MK19_M430_OSAG = 27,
|
||||
M1A2_PRC_OSAG = 30,
|
||||
M1A2_PRX_OSAG = 31,
|
||||
VLAP_PRC_OSAG = 32,
|
||||
VLAP_PRX_OSAG = 33,
|
||||
SMK_OSAG = 34,
|
||||
CLUSTER_OSAG = 35,
|
||||
MORTAR_PRC_OSAG = 217,
|
||||
MORTAR_PRX_OSAG = 218
|
||||
};
|
||||
}
|
||||
Executable
+219
@@ -0,0 +1,219 @@
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// manual class headers
|
||||
#include "BallisticService.hpp"
|
||||
|
||||
// from cpp_includes
|
||||
#include "FireControlPiton.hpp"
|
||||
#include "TrajectoryDiscrete.hpp"
|
||||
#include "TrajectoryPiton.hpp"
|
||||
#include "FireControlAntonio.hpp"
|
||||
#include "TrajectoryDecoy.hpp"
|
||||
#include "FireControlBase.hpp"
|
||||
#include "FireControlDecoy.hpp"
|
||||
#include "TrajectoryBase.hpp"
|
||||
#include "TrajectoryAntonio.hpp"
|
||||
#include "FireControlDiscrete.hpp"
|
||||
#include "FireControlRungeKutta.hpp"
|
||||
#include "TrajectoryRungeKutta.hpp"
|
||||
#include "FireControlRungeKuttaSimple.hpp"
|
||||
#include "TrajectoryRungeKuttaSimple.hpp"
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
// ---------------------------------------------------------------
|
||||
// ## Constructors (generated)
|
||||
// ---------------------------------------------------------------
|
||||
BallisticService::BallisticService()
|
||||
: m_logger(CesGeoPairing::getLogger("Plugin.GeoPairing.BallisticService"))
|
||||
{}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// initializes the BallisticService with an Ammunition config
|
||||
// file
|
||||
// ---------------------------------------------------------------
|
||||
bool BallisticService::init(const QString &a_configPath,
|
||||
const QString &a_configFile,
|
||||
const QString &a_ammunitionFile)
|
||||
{
|
||||
m_Initialized = false;
|
||||
|
||||
m_configPath = a_configPath;
|
||||
m_configFile = a_configFile;
|
||||
m_ammunitionFile = a_ammunitionFile;
|
||||
|
||||
INFO_LOG(m_logger) << "init";
|
||||
|
||||
m_ammuConfig = N_ConfigSystem::AmmuConfig::getInstance();
|
||||
QString FileName = a_configPath + QLatin1Char('/') + a_ammunitionFile;
|
||||
INFO_LOG(m_logger) << "FileName=" << FileName;
|
||||
|
||||
m_ammuConfig->initFilename(FileName);
|
||||
|
||||
m_Initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Creates an interface of according to the given parameters
|
||||
// ---------------------------------------------------------------
|
||||
bool BallisticService::createInterfaceOf(IUnknown **app_interface, E_TypeOfInterface a_typeInterface, const QString &a_ammuName)
|
||||
{
|
||||
if (!m_Initialized)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Class is not initialized" ;
|
||||
return false;
|
||||
}
|
||||
|
||||
Ammunition *configuredAmmunition;
|
||||
E_TypeOfImpl e_impl = e_ImplBase;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Target Interface Pointer : " << app_interface ;
|
||||
DEBUG_LOG(m_logger) << "Searching in available ammunitions for " << a_ammuName ;
|
||||
|
||||
//iterate over all Ammunition nodes and find the corresponding Ammunition name
|
||||
bool bAmmunitionFound = false;
|
||||
//for (Ammunition *ammunition : m_BallisticConfiguration.m_Ammunition)
|
||||
//for (Ammunition *ammunition : m_ammuConfig->GetAmmunitions())
|
||||
QVector<N_Ballistic::Ammunition>* ammunitions = m_ammuConfig->GetAmmunitions();
|
||||
for ( int i = 0; i < ammunitions->size(); i++)
|
||||
{
|
||||
N_Ballistic::Ammunition ammunition = m_ammuConfig->GetAmmunitions()->at(i);
|
||||
//find ammunition
|
||||
configuredAmmunition = &ammunition;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Ammunition found: " << configuredAmmunition->m_AmmunInfo.m_Name ;
|
||||
|
||||
if (configuredAmmunition->m_AmmunInfo.m_Name == a_ammuName)
|
||||
{
|
||||
bAmmunitionFound = true;
|
||||
if (configuredAmmunition->m_AmmunInfo.m_Algorithm == QStringLiteral("DAntonio"))
|
||||
e_impl = e_ImplAntonio;
|
||||
else if (configuredAmmunition->m_AmmunInfo.m_Algorithm == QStringLiteral("Piton"))
|
||||
e_impl = e_ImplPiton;
|
||||
else if (configuredAmmunition->m_AmmunInfo.m_Algorithm == QStringLiteral("Discrete"))
|
||||
e_impl = e_ImplDiscrete;
|
||||
else if (configuredAmmunition->m_AmmunInfo.m_Algorithm == QStringLiteral("Decoy"))
|
||||
e_impl = e_ImplDecoy;
|
||||
else if (configuredAmmunition->m_AmmunInfo.m_Algorithm == QStringLiteral("RungeKutta"))
|
||||
e_impl = e_ImplRungeKutta;
|
||||
else if (configuredAmmunition->m_AmmunInfo.m_Algorithm == QStringLiteral("RungeKuttaSimple"))
|
||||
e_impl = e_ImplRungeKuttaSimple;
|
||||
else if (configuredAmmunition->m_AmmunInfo.m_Algorithm == QStringLiteral("Generic") ||
|
||||
configuredAmmunition->m_AmmunInfo.m_Algorithm == QStringLiteral("Standard") ||
|
||||
configuredAmmunition->m_AmmunInfo.m_Algorithm == QStringLiteral("Base"))
|
||||
e_impl = e_ImplBase;
|
||||
else
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Configured Algorithm not known :"
|
||||
<< configuredAmmunition->m_AmmunInfo.m_Algorithm;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bAmmunitionFound)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Desired ammunition was not found :" << a_ammuName ;
|
||||
return false;
|
||||
}
|
||||
|
||||
// find out which algorithm to use for the given ammunition
|
||||
switch (a_typeInterface)
|
||||
{
|
||||
case e_IFireControl:
|
||||
{
|
||||
FireControlBase *p_firecontrol = nullptr;
|
||||
switch (e_impl)
|
||||
{
|
||||
case e_ImplBase:
|
||||
p_firecontrol = new FireControlBase("FireControlBase");
|
||||
break;
|
||||
case e_ImplPiton:
|
||||
p_firecontrol = new FireControlPiton;
|
||||
break;
|
||||
case e_ImplAntonio:
|
||||
p_firecontrol = new FireControlAntonio;
|
||||
break;
|
||||
case e_ImplDiscrete:
|
||||
p_firecontrol = new FireControlDiscrete;
|
||||
break;
|
||||
case e_ImplDecoy:
|
||||
p_firecontrol = new FireControlDecoy;
|
||||
break;
|
||||
case e_ImplRungeKutta:
|
||||
p_firecontrol = new FireControlRungeKutta;
|
||||
break;
|
||||
case e_ImplRungeKuttaSimple:
|
||||
p_firecontrol = new FireControlRungeKuttaSimple;
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(m_logger) << "Implementation does not exist: " << e_impl ;
|
||||
*app_interface = nullptr;
|
||||
return false;
|
||||
}
|
||||
p_firecontrol->init(*configuredAmmunition);
|
||||
p_firecontrol->addRef();
|
||||
*app_interface = p_firecontrol;
|
||||
break;
|
||||
}
|
||||
case e_ITrajectory:
|
||||
{
|
||||
TrajectoryBase *p_trajectorybase = nullptr;
|
||||
switch (e_impl)
|
||||
{
|
||||
case e_ImplBase:
|
||||
p_trajectorybase = new TrajectoryBase("TrajectoryBase");
|
||||
break;
|
||||
case e_ImplPiton:
|
||||
p_trajectorybase = new TrajectoryPiton;
|
||||
break;
|
||||
case e_ImplAntonio:
|
||||
p_trajectorybase = new TrajectoryAntonio;
|
||||
break;
|
||||
case e_ImplDiscrete:
|
||||
p_trajectorybase = new TrajectoryDiscrete;
|
||||
break;
|
||||
case e_ImplDecoy:
|
||||
p_trajectorybase = new TrajectoryDecoy;
|
||||
break;
|
||||
case e_ImplRungeKutta:
|
||||
p_trajectorybase = new TrajectoryRungeKutta;
|
||||
break;
|
||||
case e_ImplRungeKuttaSimple:
|
||||
p_trajectorybase = new TrajectoryRungeKuttaSimple;
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(m_logger) << "Implementation does not exist: " << e_impl ;
|
||||
*app_interface = nullptr;
|
||||
return false;
|
||||
}
|
||||
p_trajectorybase->init(*configuredAmmunition);
|
||||
p_trajectorybase->addRef();
|
||||
*app_interface = p_trajectorybase;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ERROR_LOG(m_logger) << "Interface does not exist: " << a_typeInterface ;
|
||||
*app_interface = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace N_Ballistic
|
||||
Executable
+104
@@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
|
||||
// from stereotyped includes
|
||||
#include "IUnknown.hpp"
|
||||
#include "../logger.h"
|
||||
#include <GBL_ConfigSystem/ammuconfig.h>
|
||||
// manual class imports
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* The factory class for ballistic interfaces
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 07-Aug-2009 13:36:13
|
||||
*/
|
||||
class BallisticService
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 07-Aug-2009 13:45:18
|
||||
*/
|
||||
enum E_TypeOfImpl
|
||||
{
|
||||
e_ImplBase = 0,
|
||||
e_ImplPiton = 1,
|
||||
e_ImplAntonio = 2,
|
||||
e_ImplDiscrete = 3,
|
||||
e_ImplDecoy = 4,
|
||||
e_ImplRungeKutta = 5,
|
||||
e_ImplRungeKuttaSimple = 6
|
||||
};
|
||||
|
||||
/**
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 07-Aug-2009 13:43:40
|
||||
*/
|
||||
enum E_TypeOfInterface
|
||||
{
|
||||
e_IFireControl = 0,
|
||||
e_ITrajectory = 1,
|
||||
e_ITerrainInfo = 2
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* initializes the BallisticService with an Ammunition config file
|
||||
*
|
||||
* @param a_configFilename xml file name
|
||||
*/
|
||||
bool init(const QString &a_configPath,
|
||||
const QString &a_configFile,
|
||||
const QString &a_ammunitionFile);
|
||||
|
||||
/**
|
||||
* Creates an interface of according to the given parameters
|
||||
*
|
||||
* @param app_interface Interface pointer
|
||||
* @param a_typeInterface Type of desired interface
|
||||
* @param a_ammuName Name of ammunition
|
||||
*/
|
||||
bool createInterfaceOf(IUnknown **app_interface, E_TypeOfInterface a_typeInterface, const QString &a_ammuName);
|
||||
QString getConfigPath() const { return m_configPath; }
|
||||
QString getConfigFile() const { return m_configFile; }
|
||||
QString getAmmunitionFile() const { return m_ammunitionFile; }
|
||||
|
||||
|
||||
/**
|
||||
* ## Constructors (generated)
|
||||
*/
|
||||
BallisticService();
|
||||
|
||||
private:
|
||||
|
||||
bool m_Initialized = false;
|
||||
QString m_configPath;
|
||||
QString m_configFile;
|
||||
QString m_ammunitionFile;
|
||||
N_ConfigSystem::AmmuConfig *m_ammuConfig = nullptr;
|
||||
|
||||
CesGeoPairing::LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
#
|
||||
# CMake file für ballistische Berechnungen
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
SET(my_SRCS
|
||||
AmmunitionTypes.hpp
|
||||
BallisticService.cpp
|
||||
FireControlAntonio.cpp
|
||||
FireControlBase.cpp
|
||||
FireControlDiscrete.cpp
|
||||
FireControlPiton.cpp
|
||||
FireControlRungeKutta.cpp
|
||||
TrajectoryAntonio.cpp
|
||||
TrajectoryBase.cpp
|
||||
TrajectoryDecoy.cpp
|
||||
TrajectoryDiscrete.cpp
|
||||
TrajectoryPiton.cpp
|
||||
TrajectoryRungeKutta.cpp
|
||||
TrajectoryRungeKuttaSimple.cpp
|
||||
)
|
||||
|
||||
SET(my_HDRS
|
||||
Ammunition.hpp
|
||||
BallisticService.hpp
|
||||
CWParamType.hpp
|
||||
DiscreteType.hpp
|
||||
FireControlAntonio.hpp
|
||||
FireControlBase.hpp
|
||||
FireControlDecoy.hpp
|
||||
FireControlDiscrete.hpp
|
||||
FireControlPiton.hpp
|
||||
FireControlRungeKutta.hpp
|
||||
FireControlRungeKuttaSimple.hpp
|
||||
IBallisticConfigurator.hpp
|
||||
IFireControl.hpp
|
||||
ITrajectory.hpp
|
||||
IUnknown.hpp
|
||||
PolygonParamType.hpp
|
||||
StandardType.hpp
|
||||
TrajectoryAntonio.hpp
|
||||
TrajectoryBase.hpp
|
||||
TrajectoryDecoy.hpp
|
||||
TrajectoryDiscrete.hpp
|
||||
TrajectoryPiton.hpp
|
||||
TrajectoryRungeKutta.hpp
|
||||
TrajectoryRungeKuttaSimple.hpp
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV FW_Ballistic STATIC ${my_SRCS} ${my_HDRS})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(FW_Ballistic
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(FW_Ballistic
|
||||
GBL_ConfigSystem
|
||||
GBL_Global
|
||||
Qt5::Core
|
||||
NGLLogger
|
||||
GBL_Types
|
||||
svcCesCommon
|
||||
)
|
||||
NGL_INSTALL_TARGET(FW_Ballistic)
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
#include <QVector>
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* Representation of ballistic classes with CW values
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 22-Jul-2010 13:32:10
|
||||
*/
|
||||
struct CWParamType
|
||||
{
|
||||
QVector<double> m_CW;
|
||||
QVector<double> m_V0;
|
||||
QVector<double> m_XW;
|
||||
double m_Weight = 0.0;
|
||||
bool m_Valid = false;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
#include <GBL_Global/Types.hpp>
|
||||
|
||||
// manual class imports
|
||||
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* Discrete representation of ballistic values
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 10-Aug-2009 11:09:31
|
||||
*/
|
||||
class DiscreteType
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Container for DerivationType
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 10-Aug-2009 11:10:03
|
||||
*/
|
||||
struct DerivationType
|
||||
{
|
||||
Float64 m_CT2 = 0.0;
|
||||
Float64 m_CY = 0.0;
|
||||
Float64 m_C0 = 0.0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Container for AxisParamType
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 10-Aug-2009 11:09:50
|
||||
*/
|
||||
struct AxisParamType
|
||||
{
|
||||
Float64 m_CA = 0.0;
|
||||
Float64 m_CT2 = 0.0;
|
||||
Float64 m_CT1 = 0.0;
|
||||
Float64 m_CAlpha2 = 0.0;
|
||||
Float64 m_CAlpha1 = 0.0;
|
||||
Float64 m_CRho = 0.0;
|
||||
Float64 m_CV = 0.0;
|
||||
Float64 m_C0 = 0.0;
|
||||
|
||||
};
|
||||
|
||||
DiscreteType::AxisParamType m_YAxis;
|
||||
DiscreteType::AxisParamType m_ZAxis;
|
||||
DiscreteType::AxisParamType m_XAxis;
|
||||
DiscreteType::DerivationType m_Derivation;
|
||||
bool m_Valid = false;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+406
@@ -0,0 +1,406 @@
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// manual class headers
|
||||
#include "FireControlAntonio.hpp"
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
// ---------------------------------------------------------------
|
||||
// initializes the class with the ballistic configuration
|
||||
// ---------------------------------------------------------------
|
||||
bool FireControlAntonio::init(const Ammunition &a_ammunition)
|
||||
{
|
||||
m_Initialized = false;
|
||||
|
||||
TRACE_LOG(m_logger) << "FireControlAntonio::init : initialising..." ;
|
||||
|
||||
if (a_ammunition.m_StandardParams.m_Valid)
|
||||
{
|
||||
m_CRhoT = a_ammunition.m_StandardParams.m_Time.m_CRhoT;
|
||||
m_CRhoA = a_ammunition.m_StandardParams.m_Angle.m_CRhoA;
|
||||
INFO_LOG(m_logger) << "m_CRhoT : " << m_CRhoT ;
|
||||
INFO_LOG(m_logger) << "m_CRhoA : " << m_CRhoA ;
|
||||
m_UseStandard = true;
|
||||
m_InitialAmmuVelocityV0constX0 = a_ammunition.m_AmmunInfo.m_Speed;
|
||||
INFO_LOG(m_logger) << "m_InitialAmmuVelocityV0constX0 = " << m_InitialAmmuVelocityV0constX0 ;
|
||||
}
|
||||
else if (a_ammunition.m_PolygonParams.m_Valid)
|
||||
{
|
||||
m_InitialAX = a_ammunition.m_PolygonParams.m_InitialAX;
|
||||
INFO_LOG(m_logger) << "m_InitialAX : " << m_InitialAX ;
|
||||
int axcount = a_ammunition.m_PolygonParams.m_AX.size();
|
||||
for (int i = 0; i < axcount; i++)
|
||||
{
|
||||
m_AX.push_back(a_ammunition.m_PolygonParams.m_AX[i].m_Coeff);
|
||||
INFO_LOG(m_logger) << "AX " << a_ammunition.m_PolygonParams.m_AX[i].m_Index << " = " << a_ammunition.m_PolygonParams.m_AX[i].m_Coeff ;
|
||||
}
|
||||
int aycount = a_ammunition.m_PolygonParams.m_AY.size();
|
||||
for (int i = 0; i < aycount; i++)
|
||||
{
|
||||
m_AY.push_back(a_ammunition.m_PolygonParams.m_AY[i].m_Coeff);
|
||||
INFO_LOG(m_logger) << "AY " << a_ammunition.m_PolygonParams.m_AY[i].m_Index << " = " << a_ammunition.m_PolygonParams.m_AY[i].m_Coeff ;
|
||||
}
|
||||
m_UsePolynom = true;
|
||||
m_InitialAmmuVelocityV0constX0 = a_ammunition.m_AmmunInfo.m_Speed;
|
||||
INFO_LOG(m_logger) << "m_InitialAmmuVelocityV0constX0 = " << m_InitialAmmuVelocityV0constX0 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Parameters missing..." ;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!FireControlBase::init(a_ammunition))
|
||||
return false;
|
||||
|
||||
INFO_LOG(m_logger) << "FireControlAntonio::init : initialized successfully!" ;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the flight time of the projectile in seconds
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlAntonio::getFlightTime(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity)
|
||||
{
|
||||
if (m_UseStandard)
|
||||
return getFlightTimeStandard(a_distance, a_initialAmmuVelocity, a_terrainAngle, a_airDensity);
|
||||
if (m_UsePolynom)
|
||||
return getFlightTimePolynom(a_distance, a_initialAmmuVelocity, a_terrainAngle, a_airDensity);
|
||||
ERROR_LOG(m_logger) << "UseStandard or UsePolynom not set..." ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the firing angle of the projectile if the following
|
||||
// are given
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlAntonio::getFireAngle(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity)
|
||||
{
|
||||
if (m_UseStandard)
|
||||
return getFireAngleStandard(a_distance, a_initialAmmuVelocity, a_terrainAngle, a_airDensity);
|
||||
if (m_UsePolynom)
|
||||
return getFireAnglePolynom(a_distance, a_initialAmmuVelocity, a_terrainAngle, a_airDensity);
|
||||
ERROR_LOG(m_logger) << "UseStandard or UsePolynom not set..." ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the flight time of the projectile in seconds
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlAntonio::getFlightTimeStandard(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 &a_terrainAngle, const Float64 a_airDensity)
|
||||
{
|
||||
Float64 d_second;
|
||||
Float64 d_temp; // temp value
|
||||
Float64 d_laserDistY; // Y laser value
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "The class is not initialized" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (a_distance < 1.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_distance is not valid : " << a_distance ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_airDensity < 0.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_airDensity is not valid : " << a_airDensity ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_initialAmmuVelocity < 1.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_initialAmmuVelocity is not valid : " << a_initialAmmuVelocity ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_terrainAngle > M_PI_2 || a_terrainAngle < -M_PI_2)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_terrainAngle is not valid : " << a_terrainAngle ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// t = Xe /(v0 * cos(Gamma) * corr)
|
||||
// corr = 1 - cRhoT * Rho * Xe
|
||||
//
|
||||
// Gamma - terrain angle
|
||||
// Rho - air density
|
||||
// v0 - initial ammu velocity
|
||||
// cRhoT - parameter
|
||||
//----------------------------------------------------------
|
||||
d_laserDistY = a_distance * cos(a_terrainAngle);
|
||||
d_temp = 1.0 - (m_CRhoT * a_airDensity * d_laserDistY);
|
||||
d_second = d_laserDistY / (a_initialAmmuVelocity * cos(a_terrainAngle) * d_temp);
|
||||
|
||||
if (d_second < 0.0)
|
||||
d_second = 0.0;
|
||||
|
||||
return d_second;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the firing angle of the projectile if the following
|
||||
// are given
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlAntonio::getFireAngleStandard(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 &a_terrainAngle, const Float64 a_airDensity)
|
||||
{
|
||||
Float64 d_square; // square part of the function
|
||||
Float64 d_tan; // tangent value of the function
|
||||
N_Types::Radian64 o_tsi; // firing angle
|
||||
Float64 d_correction; // correction value
|
||||
Float64 d_temp; // temp value
|
||||
Float64 d_laserDistZ; // Z laser value
|
||||
Float64 d_laserDistY; // Y laser value
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "The class is not initialized" ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_distance < 1.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_distance is not valid : " << a_distance ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_airDensity < 0.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_airDensity is not valid : " << a_airDensity ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_initialAmmuVelocity < 1.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_initialAmmuVelocity is not valid : " << a_initialAmmuVelocity ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_terrainAngle > M_PI_2 || a_terrainAngle < -M_PI_2)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_terrainAngle is not valid : " << a_terrainAngle ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Tsi = atan((1/2) * ((Xe/c) - sqrt))
|
||||
// sqrt = pow((Xe/c), 2) - 4 * (Ye + c) / c
|
||||
// c = (9.81 * pow(Xe, 2) / ( 2 * pow(v0, 2))) / (corr1 * corr2)
|
||||
// corr1 = pow((1 - cRhoA * Rho * Xe), 2)
|
||||
// corr2 = 1 + cRhoT * Rho * Xe
|
||||
// Xe = D * cos(Gamma)
|
||||
//
|
||||
// Gamma - terrain angle
|
||||
// Rho - air density
|
||||
// v0 - initial ammu velocity
|
||||
// cRhoA, constA - constants
|
||||
//----------------------------------------------------------
|
||||
|
||||
d_laserDistZ = a_distance * sin(a_terrainAngle);
|
||||
d_laserDistY = a_distance * cos(a_terrainAngle);
|
||||
d_temp = 1 + (m_CRhoA * a_airDensity * d_laserDistY);
|
||||
|
||||
d_correction = N_SST::G * pow(d_laserDistY, Float64(2));
|
||||
d_correction /= (2.0 * pow(a_initialAmmuVelocity, Float64(2)));
|
||||
d_correction /= d_temp;
|
||||
d_temp = pow((1 - (m_CRhoT * a_airDensity * d_laserDistY)), Float64(2));
|
||||
d_correction /= d_temp;
|
||||
|
||||
d_square = pow((d_laserDistY / d_correction), Float64(2));
|
||||
d_square -= ((4.0 * (d_laserDistZ + d_correction)) / d_correction);
|
||||
d_square = sqrt(d_square);
|
||||
d_tan = (d_laserDistY / d_correction) - d_square;
|
||||
d_tan /= 2.0;
|
||||
o_tsi = atan(d_tan);
|
||||
o_tsi -= a_terrainAngle;
|
||||
|
||||
return o_tsi;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the flight time of the projectile in seconds
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlAntonio::getFlightTimePolynom(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 &a_terrainAngle, const Float64 a_airDensity)
|
||||
{
|
||||
if (!m_Initialized)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "The class is not initialized" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (a_distance < 1.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_distance is not valid : " << a_distance ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_airDensity < 0.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_airDensity is not valid : " << a_airDensity ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_initialAmmuVelocity < 1.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_initialAmmuVelocity is not valid : " << a_initialAmmuVelocity ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_terrainAngle > M_PI_2 || a_terrainAngle < -M_PI_2)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_terrainAngle is not valid : " << a_terrainAngle ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
Float64 d_time = 0;
|
||||
Float64 d_prevtime = 0;
|
||||
Float64 d_distance = 0; // Y laser value
|
||||
Float64 d_ax = 0; // ax coefficient
|
||||
|
||||
d_distance = a_distance * cos(a_terrainAngle);
|
||||
d_ax = m_InitialAX;
|
||||
|
||||
d_time = getTimeForAx(d_distance, d_ax, a_initialAmmuVelocity, a_airDensity);
|
||||
|
||||
int iteration_counter = 0;
|
||||
while (d_time - d_prevtime < 0.001)
|
||||
{
|
||||
iteration_counter++;
|
||||
d_prevtime = d_time;
|
||||
d_ax = getAxForTime(d_time);
|
||||
d_time = getTimeForAx(d_distance, d_ax, a_initialAmmuVelocity, a_airDensity);
|
||||
|
||||
if (iteration_counter > 20)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Iteration interupted at 20 loops..." ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return d_time;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the firing angle of the projectile if the following
|
||||
// are given
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlAntonio::getFireAnglePolynom(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 &a_terrainAngle, const Float64 a_airDensity)
|
||||
{
|
||||
if (!m_Initialized)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "The class is not initialized" ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_distance < 1.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_distance is not valid : " << a_distance ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_airDensity < 0.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_airDensity is not valid : " << a_airDensity ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_initialAmmuVelocity < 1.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_initialAmmuVelocity is not valid : " << a_initialAmmuVelocity ;
|
||||
return 0.0;
|
||||
}
|
||||
if (a_terrainAngle > M_PI_2 || a_terrainAngle < -M_PI_2)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "a_terrainAngle is not valid : " << a_terrainAngle ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
N_Types::Radian64 o_tsi; // firing angle
|
||||
Float64 d_correction; // correction value
|
||||
Float64 d_temp; // temp value
|
||||
Float64 d_time; // flight time
|
||||
Float64 d_distance; // effective distance
|
||||
Float64 d_ay;
|
||||
|
||||
d_distance = a_distance * cos(a_terrainAngle);
|
||||
|
||||
d_time = getFlightTimePolynom(d_distance, a_initialAmmuVelocity, a_terrainAngle, a_airDensity);
|
||||
d_ay = getAyForTime(d_time);
|
||||
|
||||
// g * x
|
||||
// tan tsi = -----------------------------
|
||||
// 2 * v0^2 * (1 - ay * p * x)^2
|
||||
|
||||
d_correction = N_SST::G * d_distance;
|
||||
d_correction /= (2.0 * pow(a_initialAmmuVelocity, Float64(2)));
|
||||
d_temp = pow((1 - (d_ay * a_airDensity * d_distance)), Float64(2));
|
||||
d_correction /= d_temp;
|
||||
|
||||
o_tsi = atan(d_correction);
|
||||
o_tsi -= a_terrainAngle;
|
||||
|
||||
return o_tsi;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlAntonio::getTimeForAx(Float64 a_distance, Float64 a_ax, Float64 a_velocity, Float64 a_airDensity)
|
||||
{
|
||||
Float64 d_time = 0;
|
||||
|
||||
// x
|
||||
// d_time = -----------------------
|
||||
// v0 * (1 - ax * p * x)
|
||||
|
||||
d_time = a_distance / a_velocity;
|
||||
d_time /= 1 - (a_ax * a_airDensity * a_distance);
|
||||
|
||||
return d_time;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlAntonio::getAxForTime(Float64 a_time) const
|
||||
{
|
||||
Float64 d_ax = 0;
|
||||
|
||||
//
|
||||
// ax = (ax0 * t^0) + (ax1 * t^1) + (ax2 * t^2) + (ax3 * t^3) ...
|
||||
//
|
||||
|
||||
for (unsigned int i = 0; i < m_AX.size(); i++)
|
||||
d_ax += m_AX[i] * pow(a_time, i);
|
||||
|
||||
return d_ax;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlAntonio::getAyForTime(Float64 a_time) const
|
||||
{
|
||||
Float64 d_ay = 0;
|
||||
|
||||
//
|
||||
// ay = (ay0 * t^0) + (ay1 * t^1) + (ay2 * t^2) + (ay3 * t^3) ...
|
||||
//
|
||||
|
||||
for (unsigned int i = 0; i < m_AY.size(); i++)
|
||||
d_ay += m_AY[i] * pow(a_time, i);
|
||||
|
||||
return d_ay;
|
||||
}
|
||||
|
||||
} // namespace N_Ballistic
|
||||
Executable
+153
@@ -0,0 +1,153 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// manual class imports
|
||||
#include "FireControlBase.hpp"
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* D'Antonio implementation for fire calculations
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 07-Aug-2009 15:01:21
|
||||
*/
|
||||
class FireControlAntonio : public FireControlBase
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* ## Constructors (generated)
|
||||
*/
|
||||
FireControlAntonio() : FireControlBase("FireControlAntonio") {}
|
||||
|
||||
/**
|
||||
* initializes the class with the ballistic configuration
|
||||
*
|
||||
* @param a_ammunition
|
||||
*/
|
||||
bool init(const Ammunition &a_ammunition) override;
|
||||
|
||||
/**
|
||||
* returns the flight time of the projectile in seconds
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
Float64 getFlightTime(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity) override;
|
||||
|
||||
/**
|
||||
* returns the firing angle of the projectile if the following are given
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
Float64 getFireAngle(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity) override;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* returns the flight time of the projectile in seconds
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
virtual Float64 getFlightTimeStandard(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 &a_terrainAngle, const Float64 a_airDensity);
|
||||
|
||||
/**
|
||||
* returns the firing angle of the projectile if the following are given
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
virtual Float64 getFireAngleStandard(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 &a_terrainAngle, const Float64 a_airDensity);
|
||||
|
||||
/**
|
||||
* returns the flight time of the projectile in seconds
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
virtual Float64 getFlightTimePolynom(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 &a_terrainAngle, const Float64 a_airDensity);
|
||||
|
||||
/**
|
||||
* returns the firing angle of the projectile if the following are given
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
virtual Float64 getFireAnglePolynom(const Float64 a_distance, const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64 &a_terrainAngle, const Float64 a_airDensity);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param a_distance
|
||||
* @param a_ax
|
||||
* @param a_velocity
|
||||
* @param a_airDensity
|
||||
*/
|
||||
static Float64 getTimeForAx(Float64 a_distance, Float64 a_ax, Float64 a_velocity, Float64 a_airDensity);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param a_time
|
||||
*/
|
||||
Float64 getAxForTime(Float64 a_time) const;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param a_time
|
||||
*/
|
||||
Float64 getAyForTime(Float64 a_time) const;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_CRhoT = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_CRhoA = 0;
|
||||
Float64 m_InitialAX = 0;
|
||||
std::vector<Float64> m_AX;
|
||||
std::vector<Float64> m_AY;
|
||||
|
||||
bool m_UseStandard = false;
|
||||
bool m_UsePolynom = false;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// manual class headers
|
||||
#include "FireControlBase.hpp"
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
FireControlBase::FireControlBase(const char *loggerName)
|
||||
: m_logger(CesGeoPairing::getLogger(loggerName))
|
||||
{
|
||||
}
|
||||
|
||||
FireControlBase::~FireControlBase()
|
||||
{
|
||||
deinit();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Using this function a reference to the interface is added.
|
||||
// ---------------------------------------------------------------
|
||||
SInt32 FireControlBase::addRef()
|
||||
{
|
||||
return m_MyRefCounter++;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Calling this function the reference from the interface may
|
||||
// be removed.
|
||||
// ---------------------------------------------------------------
|
||||
SInt32 FireControlBase::release()
|
||||
{
|
||||
--m_MyRefCounter;
|
||||
if (m_MyRefCounter <= 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return m_MyRefCounter;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// initializes the class with the ballistic configuration
|
||||
// ---------------------------------------------------------------
|
||||
bool FireControlBase::init(const Ammunition &a_ammunition)
|
||||
{
|
||||
m_Initialized = false;
|
||||
|
||||
if (a_ammunition.m_StandardParams.m_Valid)
|
||||
{
|
||||
TRACE_LOG(m_logger) << "FireControlBase::init : initialising StandardParams..." ;
|
||||
|
||||
m_InitialAmmuVelocityV0constX1 = a_ammunition.m_StandardParams.m_Speed.m_V0ConstX1;
|
||||
m_InitialAmmuVelocityV0constX0 = a_ammunition.m_StandardParams.m_Speed.m_V0ConstX0;
|
||||
|
||||
m_CrossWindConstX3 = a_ammunition.m_StandardParams.m_CrossWind.m_ConstX3;
|
||||
m_CrossWindConstX2 = a_ammunition.m_StandardParams.m_CrossWind.m_ConstX2;
|
||||
m_CrossWindConstX1 = a_ammunition.m_StandardParams.m_CrossWind.m_ConstX1;
|
||||
m_CrossWindConstX0 = a_ammunition.m_StandardParams.m_CrossWind.m_ConstX0;
|
||||
}
|
||||
|
||||
m_Initialized = true;
|
||||
|
||||
TRACE_LOG(m_logger) << "m_InitialAmmuVelocityV0constX1 : " << m_InitialAmmuVelocityV0constX1 ;
|
||||
TRACE_LOG(m_logger) << "m_InitialAmmuVelocityV0constX0 : " << m_InitialAmmuVelocityV0constX0 ;
|
||||
TRACE_LOG(m_logger) << "m_CrossWindConstX3 : " << m_CrossWindConstX3 ;
|
||||
TRACE_LOG(m_logger) << "m_CrossWindConstX2 : " << m_CrossWindConstX2 ;
|
||||
TRACE_LOG(m_logger) << "m_CrossWindConstX1 : " << m_CrossWindConstX1 ;
|
||||
TRACE_LOG(m_logger) << "m_CrossWindConstX0 : " << m_CrossWindConstX0 ;
|
||||
|
||||
TRACE_LOG(m_logger) << "FireControlBase::init : initialized successfully!" ;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the flight time of the projectile in seconds
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlBase::getFlightTime(const Float64 a_distance,
|
||||
const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64,
|
||||
const Float64)
|
||||
{
|
||||
Float64 d_second;
|
||||
Float64 d_temp; // temp value
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "The class is not initialized" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (a_distance < 1.0 || a_initialAmmuVelocity < 1.0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "The parameters are not correct" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
d_temp = a_distance * N_SST::G / pow(a_initialAmmuVelocity, Float64(2));
|
||||
d_second = 2 * a_initialAmmuVelocity / N_SST::G;
|
||||
d_second *= sin(0.5 * asin(d_temp));
|
||||
|
||||
if (d_second < 0.0)
|
||||
d_second = 0.0;
|
||||
|
||||
return d_second;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the firing angle of the projectile if the following
|
||||
// are given
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlBase::getFireAngle(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity)
|
||||
{
|
||||
N_Types::Radian64 o_tsi; // firing angle
|
||||
Float64 d_temp; // temp value
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "The class is not initialized" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if ((a_distance < 1.0) ||
|
||||
(a_airDensity < 0.0) ||
|
||||
(a_initialAmmuVelocity < 1.0) ||
|
||||
(a_terrainAngle > M_PI_2) ||
|
||||
(a_terrainAngle < -M_PI_2))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "The parameters are not correct" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
d_temp = a_distance * N_SST::G / pow(a_initialAmmuVelocity, Float64(2));
|
||||
o_tsi = asin(d_temp) / 2;
|
||||
|
||||
o_tsi -= a_terrainAngle;
|
||||
|
||||
return o_tsi;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// This function corrects the fire angle due to the cross wind,
|
||||
// if the following are given
|
||||
// ---------------------------------------------------------------
|
||||
N_Types::Radian64 FireControlBase::getCrossWindCorrection(const Float64 a_crossWind, const Float64 a_distance)
|
||||
{
|
||||
Float64 d_deviation; // deviation of the ammu due the cross wind of 1m/sec
|
||||
Float64 d_deviationTotal; // total deviation of the ammu due the cross wind
|
||||
N_Types::Radian64 d_traverse; // deviation angle
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "The class is not initialized" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (m_CrossWindConstX3 == 0 &&
|
||||
m_CrossWindConstX2 == 0 &&
|
||||
m_CrossWindConstX1 == 0 &&
|
||||
m_CrossWindConstX0 == 0)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "The class uses probably not initialized parameters" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
d_deviation = m_CrossWindConstX3 * pow(a_distance, Float64(3)) +
|
||||
m_CrossWindConstX2 * pow(a_distance, Float64(2)) +
|
||||
m_CrossWindConstX1 * a_distance +
|
||||
m_CrossWindConstX0;
|
||||
|
||||
d_deviationTotal = d_deviation * a_crossWind;
|
||||
|
||||
d_traverse = atan2(d_deviationTotal, a_distance);
|
||||
|
||||
return d_traverse;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the air density, provided the following are given
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlBase::getAirDensity(const Float64 a_atmosphericPressure, const Float64 a_airTemperature)
|
||||
{
|
||||
const Float64 d_FIXED_CONST = 0.348368; // fixed constant of the function
|
||||
Float64 d_kelvin;
|
||||
Float64 d_rho;
|
||||
|
||||
if ((a_atmosphericPressure <= 1.0) ||
|
||||
(a_airTemperature <= -N_SST::ZERO_CELSIUS_IN_KELVIN))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "The parameters are not correct, Pressure=" << a_atmosphericPressure << ", Temp=" << a_airTemperature ;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
d_kelvin = a_airTemperature + N_SST::ZERO_CELSIUS_IN_KELVIN;
|
||||
d_rho = d_FIXED_CONST * a_atmosphericPressure / d_kelvin;
|
||||
|
||||
return d_rho;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// This function corrects the fire angle due to the cross wind,
|
||||
// if the following are given
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlBase::getCrossWind(const N_Types::Coord3 &a_crossWind, const Float64 a_turretDir)
|
||||
{
|
||||
N_Types::Coord3 o_wind = a_crossWind;
|
||||
o_wind.rotateZ(-a_turretDir); // rotate back
|
||||
|
||||
return o_wind.getX();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the theritical initial ammu velocity of the
|
||||
// ammunition
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlBase::getInitialAmmuVelocity(const Float64 a_temperature)
|
||||
{
|
||||
const Float64 d_BASE_TEMPERATURE = 21.0; // deg.centigrade
|
||||
|
||||
Float64 f_InitialAmmuVelocity = m_InitialAmmuVelocityV0constX0;
|
||||
Float64 f_Celsius = a_temperature - d_BASE_TEMPERATURE;
|
||||
|
||||
f_InitialAmmuVelocity += (m_InitialAmmuVelocityV0constX1 * f_Celsius);
|
||||
|
||||
return f_InitialAmmuVelocity;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// deinitializes class
|
||||
// ---------------------------------------------------------------
|
||||
bool FireControlBase::deinit()
|
||||
{
|
||||
m_Initialized = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace N_Ballistic
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
#include "../logger.h"
|
||||
|
||||
// from stereotyped includes
|
||||
#include "IFireControl.hpp"
|
||||
#include "Ammunition.hpp"
|
||||
|
||||
// manual class imports
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* Base implementation for fire calculations
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 07-Aug-2009 15:01:07
|
||||
*/
|
||||
class FireControlBase : public IFireControl
|
||||
{
|
||||
public:
|
||||
|
||||
explicit FireControlBase(const char *loggerName);
|
||||
virtual ~FireControlBase();
|
||||
|
||||
|
||||
/**
|
||||
* Using this function a reference to the interface is added.
|
||||
*/
|
||||
SInt32 addRef();
|
||||
|
||||
/**
|
||||
* Calling this function the reference from the interface may be removed.
|
||||
*/
|
||||
SInt32 release();
|
||||
|
||||
/**
|
||||
* initializes the class with the ballistic configuration
|
||||
*
|
||||
* @param a_ammunition
|
||||
*/
|
||||
virtual bool init(const Ammunition &a_ammunition);
|
||||
|
||||
/**
|
||||
* returns the flight time of the projectile in seconds
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
virtual Float64 getFlightTime(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity);
|
||||
|
||||
/**
|
||||
* returns the firing angle of the projectile if the following are given
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
virtual Float64 getFireAngle(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity);
|
||||
|
||||
/**
|
||||
* This function corrects the fire angle due to the cross wind, if the following
|
||||
* are given
|
||||
*
|
||||
* @param a_crossWind wind speed
|
||||
* @param a_distance distance from gun
|
||||
*/
|
||||
N_Types::Radian64 getCrossWindCorrection(const Float64 a_crossWind, const Float64 a_distance);
|
||||
|
||||
/**
|
||||
* returns the air density, provided the following are given
|
||||
*
|
||||
* @param a_atmosphericPressure Pressure
|
||||
* @param a_airTemperature Temperature
|
||||
*/
|
||||
virtual Float64 getAirDensity(const Float64 a_atmosphericPressure, const Float64 a_airTemperature);
|
||||
|
||||
/**
|
||||
* This function corrects the fire angle due to the cross wind, if the following
|
||||
* are given
|
||||
*
|
||||
* @param a_crossWind Wind direction
|
||||
* @param a_turretDir Direction of Turret
|
||||
*/
|
||||
virtual Float64 getCrossWind(const N_Types::Coord3 &a_crossWind, const Float64 a_turretDir);
|
||||
|
||||
/**
|
||||
* returns the theritical initial ammu velocity of the ammunition
|
||||
*
|
||||
* @param a_temperature Temperature
|
||||
*/
|
||||
virtual Float64 getInitialAmmuVelocity(const Float64 a_temperature);
|
||||
|
||||
protected:
|
||||
|
||||
SInt32 m_MyRefCounter = 0;
|
||||
bool m_Initialized = false;
|
||||
/**
|
||||
* initial velocity constants
|
||||
*/
|
||||
Float64 m_InitialAmmuVelocityV0constX1 = 0;
|
||||
/**
|
||||
* initial velocity constants
|
||||
*/
|
||||
Float64 m_InitialAmmuVelocityV0constX0 = 0;
|
||||
/**
|
||||
* cross wind constants
|
||||
*/
|
||||
Float64 m_CrossWindConstX3 = 0;
|
||||
/**
|
||||
* cross wind constants
|
||||
*/
|
||||
Float64 m_CrossWindConstX2 = 0;
|
||||
/**
|
||||
* cross wind constants
|
||||
*/
|
||||
Float64 m_CrossWindConstX1 = 0;
|
||||
/**
|
||||
* cross wind constants
|
||||
*/
|
||||
Float64 m_CrossWindConstX0 = 0;
|
||||
/**
|
||||
* logger object
|
||||
*/
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
|
||||
/**
|
||||
* deinitializes class
|
||||
*/
|
||||
bool deinit();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// from stereotyped includes
|
||||
#include "FireControlBase.hpp"
|
||||
|
||||
// manual class imports
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* Decoy implementation for fire calculations
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 07-Aug-2009 15:01:59
|
||||
*/
|
||||
class FireControlDecoy : public FireControlBase
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* ## Constructors (generated)
|
||||
*/
|
||||
FireControlDecoy() : FireControlBase("FireControlDecoy") {}
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+185
@@ -0,0 +1,185 @@
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// manual class headers
|
||||
#include "FireControlDiscrete.hpp"
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// initializes the class with the ballistic configuration
|
||||
// ---------------------------------------------------------------
|
||||
bool FireControlDiscrete::init(const Ammunition &a_ammunition)
|
||||
{
|
||||
m_Initialized = false;
|
||||
|
||||
TRACE_LOG(m_logger) << "FireControlDiscrete::init : initialising..." ;
|
||||
|
||||
m_CT = a_ammunition.m_StandardParams.m_Time.m_CT;
|
||||
m_CV0T = a_ammunition.m_StandardParams.m_Time.m_CV0T;
|
||||
m_CRhoT = a_ammunition.m_StandardParams.m_Time.m_CRhoT;
|
||||
m_ConstT = a_ammunition.m_StandardParams.m_Time.m_ConstT;
|
||||
|
||||
m_CA = a_ammunition.m_StandardParams.m_Angle.m_CA;
|
||||
m_CV0A = a_ammunition.m_StandardParams.m_Angle.m_CV0A;
|
||||
m_CGammaA = a_ammunition.m_StandardParams.m_Angle.m_CGammaA;
|
||||
m_CRhoA = a_ammunition.m_StandardParams.m_Angle.m_CRhoA;
|
||||
m_ConstA = a_ammunition.m_StandardParams.m_Angle.m_ConstA;
|
||||
|
||||
if (!FireControlBase::init(a_ammunition))
|
||||
return false;
|
||||
|
||||
TRACE_LOG(m_logger) << "m_CT : " << m_CT ;
|
||||
TRACE_LOG(m_logger) << "m_CV0T : " << m_CV0T ;
|
||||
TRACE_LOG(m_logger) << "m_CRhoT : " << m_CRhoT ;
|
||||
TRACE_LOG(m_logger) << "m_ConstT : " << m_ConstT ;
|
||||
|
||||
TRACE_LOG(m_logger) << "m_CA : " << m_CA ;
|
||||
TRACE_LOG(m_logger) << "m_CV0A : " << m_CV0A ;
|
||||
TRACE_LOG(m_logger) << "m_CGammaA : " << m_CGammaA ;
|
||||
TRACE_LOG(m_logger) << "m_CRhoA : " << m_CRhoA ;
|
||||
TRACE_LOG(m_logger) << "m_ConstA : " << m_ConstA ;
|
||||
|
||||
TRACE_LOG(m_logger) << "FireControlDiscrete::init : initialized successfully!" ;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the flight time of the projectile in seconds
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlDiscrete::getFlightTime(const Float64 a_distance,
|
||||
const Float64 a_initialAmmuVelocity,
|
||||
const N_Types::Radian64,
|
||||
const Float64 a_airDensity)
|
||||
{
|
||||
Float64 d_second;
|
||||
Float64 d_exp;
|
||||
Float64 d_correction;
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "The class is not initialized" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if ((a_distance < 1.0) ||
|
||||
(a_airDensity < 0.0) ||
|
||||
(a_initialAmmuVelocity < 1.0))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "The parameters are not correct" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// The firing time of the ammunition is calculated using the
|
||||
// following formula:
|
||||
// T(x,v0,rho) = (1 / m_CT * rho * v0) *
|
||||
// (e**(d_cT * rho * x) -1) *
|
||||
// ((d_cV0T * v0) + (d_cRhoT * rho) + m_ConstT)
|
||||
// rho - air density -- kg/m**3
|
||||
// x - distance -- meter
|
||||
// T - firing time -- second
|
||||
// v0 - initial velocity -- meter per second.
|
||||
// m_VT - exponential constant for time
|
||||
// m_CV0T - initial velocity correction constant
|
||||
// m_CRhoT - air density correction constant
|
||||
// m_ConstT - function constant
|
||||
//----------------------------------------------------------
|
||||
|
||||
d_correction = ((m_CV0T * a_initialAmmuVelocity) +
|
||||
(m_CRhoT * a_airDensity) +
|
||||
m_ConstT);
|
||||
d_exp = (exp(m_CT * a_airDensity * a_distance)) - 1.0;
|
||||
d_second = (1.0 / (m_CT * a_airDensity * a_initialAmmuVelocity)) *
|
||||
(d_exp) *
|
||||
(d_correction);
|
||||
|
||||
if (d_second < 0.0)
|
||||
d_second = 0.0;
|
||||
|
||||
return d_second;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the firing angle of the projectile if the following
|
||||
// are given
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlDiscrete::getFireAngle(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity)
|
||||
{
|
||||
const Float64 d_FIXED_CONST = 4.905; // fixed constant of the function
|
||||
Float64 d_exp; // exponential patr of the function
|
||||
Float64 d_square; // square part of the function
|
||||
Float64 d_tan; // tangent value of the function
|
||||
N_Types::Radian64 o_tsi; // firing angle
|
||||
Float64 d_correction; // correction value
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "The class is not initialized" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if ((a_distance < 1.0) ||
|
||||
(a_airDensity < 0.0) ||
|
||||
(a_initialAmmuVelocity < 1.0) ||
|
||||
(a_terrainAngle > M_PI_2) ||
|
||||
(a_terrainAngle < -M_PI_2))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "The parameters are not correct" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// The firing angle of the ammunition is calculated using the formula:
|
||||
// A(x,gamma,v0,rho) = arctan((4.905/x) * ((1/d_cA*Rho*v0) *
|
||||
// ((e**(d_cA*Rho*x)-1) -- exp
|
||||
// )**2 -- square
|
||||
// ) -- arctan
|
||||
// * correction
|
||||
// correction =
|
||||
// ((d_cGammaA * gamma) +
|
||||
// (d_cV0A * v0) +
|
||||
// (d_cRhoA * Rho) +
|
||||
// (d_constA)
|
||||
// )
|
||||
// where:
|
||||
// rho - air density -- kg/m**3
|
||||
// x - distance -- meter
|
||||
// A - firing angle -- radian
|
||||
// gamma - angle to terrain -- radian
|
||||
// v0 - initial velocity
|
||||
// m_CA - exponential constant for angle
|
||||
// m_CGammaA - terrain angle correction constant for angle
|
||||
// m_CV0A; - initial velocity correction constant for angle
|
||||
// m_CRhoA; - air density correction constant for angle
|
||||
// m_ConstA; - function constant for angle
|
||||
//----------------------------------------------------------
|
||||
|
||||
d_exp = ((exp(m_CA * a_airDensity * a_distance)) - 1.0);
|
||||
d_square = pow(((1.0 / (m_CA * a_airDensity * a_initialAmmuVelocity)) * (d_exp)), Float64(2));
|
||||
d_tan = (d_FIXED_CONST / a_distance) * d_square;
|
||||
o_tsi = atan(d_tan);
|
||||
|
||||
d_correction = (m_CGammaA * a_terrainAngle) +
|
||||
(m_CV0A * a_initialAmmuVelocity) +
|
||||
(m_CRhoA * a_airDensity) +
|
||||
m_ConstA;
|
||||
|
||||
o_tsi = o_tsi * d_correction;
|
||||
|
||||
return o_tsi;
|
||||
}
|
||||
|
||||
} // namespace N_Ballistic
|
||||
Executable
+106
@@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// manual class imports
|
||||
#include "FireControlBase.hpp"
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* Discrete implementation for fire calculations
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 07-Aug-2009 15:01:42
|
||||
*/
|
||||
class FireControlDiscrete : public FireControlBase
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* ## Constructors (generated)
|
||||
*/
|
||||
FireControlDiscrete() : FireControlBase("FireControlDiscrete") {}
|
||||
|
||||
/**
|
||||
* initializes the class with the ballistic configuration
|
||||
*
|
||||
* @param a_ammunition
|
||||
*/
|
||||
bool init(const Ammunition &a_ammunition) override;
|
||||
|
||||
/**
|
||||
* returns the flight time of the projectile in seconds
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
Float64 getFlightTime(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity) override;
|
||||
|
||||
/**
|
||||
* returns the firing angle of the projectile if the following are given
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
Float64 getFireAngle(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity) override;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_CT = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_CV0T = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_CRhoT = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_ConstT = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_CA = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_CV0A = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_CRhoA = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_ConstA = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_CGammaA = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+164
@@ -0,0 +1,164 @@
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// manual class headers
|
||||
#include "FireControlPiton.hpp"
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// initializes the class with the ballistic configuration
|
||||
// ---------------------------------------------------------------
|
||||
bool FireControlPiton::init(const Ammunition &a_ammunition)
|
||||
{
|
||||
m_Initialized = false;
|
||||
|
||||
TRACE_LOG(m_logger) << "FireControlPiton::init : initialising..." ;
|
||||
|
||||
m_CRhoT = a_ammunition.m_StandardParams.m_Time.m_CRhoT;
|
||||
m_ConstT = a_ammunition.m_StandardParams.m_Time.m_ConstT;
|
||||
|
||||
m_CRhoA = a_ammunition.m_StandardParams.m_Angle.m_CRhoA;
|
||||
m_ConstA = a_ammunition.m_StandardParams.m_Angle.m_ConstA;
|
||||
|
||||
if (!FireControlBase::init(a_ammunition))
|
||||
return false;
|
||||
|
||||
TRACE_LOG(m_logger) << "m_CRhoT : " << m_CRhoT ;
|
||||
TRACE_LOG(m_logger) << "m_ConstT : " << m_ConstT ;
|
||||
TRACE_LOG(m_logger) << "m_CRhoA : " << m_CRhoA ;
|
||||
TRACE_LOG(m_logger) << "m_ConstA : " << m_ConstA ;
|
||||
|
||||
TRACE_LOG(m_logger) << "FireControlPiton::init : initialized successfully!" ;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the flight time of the projectile in seconds
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlPiton::getFlightTime(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity)
|
||||
{
|
||||
const Float64 d_THREE_OVER_TWO = 3.0 / 2.0;
|
||||
const Float64 d_TWO_OVER_NINE = 2.0 / 9.0;
|
||||
Float64 d_second;
|
||||
Float64 d_correction;
|
||||
Float64 d_temp; // temp value
|
||||
Float64 d_laserDistY; // Y laser value
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "The class is not initialized" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if ((a_distance < 1.0) ||
|
||||
(a_airDensity < 0.0) ||
|
||||
(a_initialAmmuVelocity < 1.0) ||
|
||||
(a_terrainAngle > M_PI_2) ||
|
||||
(a_terrainAngle < -M_PI_2))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "The parameters are not correct" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// t = (2.0 / (9.0 * v0 * cos(Gamma))) * corr1
|
||||
// corr1 = (pow(corr2, 2/3) - 1) / KT
|
||||
// corr2 = 1 + (3 * KT * Xe)
|
||||
// KT = cRhoT * Rho + constT
|
||||
// Gamma - terrain angle
|
||||
// Rho - air density
|
||||
// v0 - initial ammu velocity
|
||||
// cRhoT, constT - parameter
|
||||
//----------------------------------------------------------
|
||||
// f_LaserDistZ = a_Distance * sin(a_TerrainAngle);
|
||||
d_laserDistY = a_distance * cos(a_terrainAngle);
|
||||
d_temp = (m_CRhoT * a_airDensity) + m_ConstT;
|
||||
d_correction = 1 + (3.0 * d_temp * d_laserDistY);
|
||||
d_correction = pow(d_correction, d_THREE_OVER_TWO);
|
||||
d_correction -= 1.0;
|
||||
d_correction /= d_temp;
|
||||
|
||||
d_second = (d_TWO_OVER_NINE * d_correction) /
|
||||
(a_initialAmmuVelocity * cos(a_terrainAngle));
|
||||
|
||||
if (d_second < 0.0)
|
||||
d_second = 0.0;
|
||||
|
||||
return d_second;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the firing angle of the projectile if the following
|
||||
// are given
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlPiton::getFireAngle(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity)
|
||||
{
|
||||
Float64 d_square; // square part of the function
|
||||
Float64 d_tan; // tangent value of the function
|
||||
N_Types::Radian64 o_tsi; // firing angle
|
||||
Float64 d_correction; // correction value
|
||||
Float64 d_temp; // temp value
|
||||
Float64 d_laserDistZ; // Z laser value
|
||||
Float64 d_laserDistY; // Y laser value
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "The class is not initialized" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if ((a_distance < 1.0) ||
|
||||
(a_airDensity < 0.0) ||
|
||||
(a_initialAmmuVelocity < 1.0) ||
|
||||
(a_terrainAngle > M_PI_2) ||
|
||||
(a_terrainAngle < -M_PI_2))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "The parameters are not correct" ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Tsi = atan((1/2) * ((Xe/c) - sqrt))
|
||||
// sqrt = pow((Xe/c), 2) - 4 * (Ye + c) / c
|
||||
// c = 9.81 * pow(Xe, 2) * (1 + k + Xe) / ( 2 * pow(v0, 2))
|
||||
// k = cRhoA * Rho + constA
|
||||
// Xe = D * cos(Gamma)
|
||||
//
|
||||
// Gamma - terrain angle
|
||||
// Rho - air density
|
||||
// v0 - initial ammu velocity
|
||||
// cRhoA, constA - constants
|
||||
//----------------------------------------------------------
|
||||
|
||||
d_laserDistZ = a_distance * sin(a_terrainAngle);
|
||||
d_laserDistY = a_distance * cos(a_terrainAngle);
|
||||
d_temp = (m_CRhoA * a_airDensity) + m_ConstA;
|
||||
|
||||
d_correction = N_SST::G * pow(d_laserDistY, Float64(2)) * (1.0 + (d_temp * d_laserDistY));
|
||||
d_correction /= (2.0 * pow(a_initialAmmuVelocity, Float64(2)));
|
||||
|
||||
d_square = pow((d_laserDistY / d_correction), Float64(2));
|
||||
d_square -= ((4.0 * (d_laserDistZ + d_correction)) / d_correction);
|
||||
d_square = sqrt(d_square);
|
||||
d_tan = (d_laserDistY / d_correction) - d_square;
|
||||
d_tan /= 2.0;
|
||||
o_tsi = atan(d_tan);
|
||||
o_tsi -= a_terrainAngle;
|
||||
|
||||
return o_tsi;
|
||||
}
|
||||
|
||||
} // namespace N_Ballistic
|
||||
Executable
+86
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// manual class imports
|
||||
#include "FireControlBase.hpp"
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* Piton Bressant implementation for fire calculations
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 07-Aug-2009 15:01:30
|
||||
*/
|
||||
class FireControlPiton : public FireControlBase
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* ## Constructors (generated)
|
||||
*/
|
||||
FireControlPiton() : FireControlBase("FireControlPiton") {}
|
||||
|
||||
/**
|
||||
* initializes the class with the ballistic configuration
|
||||
*
|
||||
* @param a_ammunition
|
||||
*/
|
||||
bool init(const Ammunition &a_ammunition) override;
|
||||
|
||||
/**
|
||||
* returns the flight time of the projectile in seconds
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
Float64 getFlightTime(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity) override;
|
||||
|
||||
/**
|
||||
* returns the firing angle of the projectile if the following are given
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
Float64 getFireAngle(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity) override;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_CRhoT = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_CRhoA = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_ConstT = 0;
|
||||
/**
|
||||
* air density correction constant
|
||||
*/
|
||||
Float64 m_ConstA = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+88
@@ -0,0 +1,88 @@
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// manual class headers
|
||||
#include "FireControlRungeKutta.hpp"
|
||||
#include "TrajectoryRungeKutta.hpp"
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the flight time of the projectile in seconds
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlRungeKutta::getFlightTime(const Float64,
|
||||
const Float64,
|
||||
const N_Types::Radian64,
|
||||
const Float64)
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
ERROR_LOG(m_logger) << "This algorithm has no implementation for flight time" ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the firing angle of the projectile if the following
|
||||
// are given
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlRungeKutta::getFireAngle(const Float64,
|
||||
const Float64,
|
||||
const N_Types::Radian64,
|
||||
const Float64)
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
ERROR_LOG(m_logger) << "This algorithm has no implementation for fire angle" ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the air density, provided the following are given
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlRungeKutta::getAirDensity(const Float64 a_atmosphericPressure, const Float64 a_airTemperature)
|
||||
{
|
||||
const Float64 d_FIXED_CONST = 0.348368; // fixed constant of the function
|
||||
Float64 d_kelvin;
|
||||
Float64 d_rho;
|
||||
|
||||
if ((a_atmosphericPressure <= 1.0) ||
|
||||
(a_airTemperature <= -N_SST::ZERO_CELSIUS_IN_KELVIN))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "The parameters are not correct, Pressure=" << a_atmosphericPressure << ", Temp=" << a_airTemperature ;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
TrajectoryRungeKutta::m_Temp = a_airTemperature;
|
||||
DEBUG_LOG(m_logger) << "Temp for Trajectory set: " << TrajectoryRungeKutta::m_Temp ;
|
||||
|
||||
d_kelvin = a_airTemperature + N_SST::ZERO_CELSIUS_IN_KELVIN;
|
||||
d_rho = d_FIXED_CONST * a_atmosphericPressure / d_kelvin;
|
||||
|
||||
return d_rho;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// returns the theritical initial ammu velocity of the
|
||||
// ammunition
|
||||
// ---------------------------------------------------------------
|
||||
Float64 FireControlRungeKutta::getInitialAmmuVelocity(const Float64 a_temperature)
|
||||
{
|
||||
TrajectoryRungeKutta::m_TempWeapon = a_temperature;
|
||||
DEBUG_LOG(m_logger) << "Temp for Weapon set: " << TrajectoryRungeKutta::m_TempWeapon ;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
} // namespace N_Ballistic
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// from stereotyped includes
|
||||
#include "FireControlBase.hpp"
|
||||
|
||||
// manual class imports
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* RungeKutta implementation for fire calculations
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 22-Jul-2010 11:44:20
|
||||
*/
|
||||
class FireControlRungeKutta : public FireControlBase
|
||||
{
|
||||
public:
|
||||
|
||||
FireControlRungeKutta(const char *loggerName = nullptr)
|
||||
: FireControlBase(loggerName ? loggerName : "FireControlRungeKutta")
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* returns the flight time of the projectile in seconds
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
Float64 getFlightTime(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity) override;
|
||||
|
||||
/**
|
||||
* returns the firing angle of the projectile if the following are given
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
Float64 getFireAngle(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity) override;
|
||||
|
||||
/**
|
||||
* returns the air density, provided the following are given
|
||||
*
|
||||
* @param a_atmosphericPressure Pressure
|
||||
* @param a_airTemperature Temperature
|
||||
*/
|
||||
Float64 getAirDensity(const Float64 a_atmosphericPressure, const Float64 a_airTemperature) override;
|
||||
|
||||
/**
|
||||
* returns the theritical initial ammu velocity of the ammunition
|
||||
*
|
||||
* @param a_temperature Temperature
|
||||
*/
|
||||
Float64 getInitialAmmuVelocity(const Float64 a_temperature) override;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Lts/Services/CentralEffectSimulation/Plugins/GeoPairing/FW_Ballistic/FireControlRungeKuttaSimple.hpp
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// from stereotyped includes
|
||||
#include "FireControlRungeKutta.hpp"
|
||||
|
||||
// manual class imports
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* Simple RungeKutta implementation for fire calculations
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 22-Jul-2010 12:11:39
|
||||
*/
|
||||
class FireControlRungeKuttaSimple : public FireControlRungeKutta
|
||||
{
|
||||
public:
|
||||
|
||||
FireControlRungeKuttaSimple() : FireControlRungeKutta("FireControlRungeKuttaSimple") {}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// from stereotyped includes
|
||||
#include "Ammunition.hpp"
|
||||
|
||||
// manual class imports
|
||||
class QString;
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* This is the interface to the ballistic configuration mecanism
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 11-Aug-2009 16:14:34
|
||||
*/
|
||||
class IBallisticConfigurator
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~IBallisticConfigurator() = default;
|
||||
|
||||
/**
|
||||
* load the configfile and creates ammunition objects for all found entries
|
||||
*
|
||||
* @param a_configFilename
|
||||
* @param a_ammunitions
|
||||
*/
|
||||
virtual bool loadAmmunitions(const QString &a_configFilename, std::vector<Ammunition *> &a_ammunitions) = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// from stereotyped includes
|
||||
#include <GBL_Types/Radian64.hpp>
|
||||
#include <GBL_Types/Coord3.hpp>
|
||||
#include "IUnknown.hpp"
|
||||
|
||||
// manual class imports
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* Interface for fire control implementations
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 07-Aug-2009 13:37:13
|
||||
*/
|
||||
class IFireControl : public IUnknown
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* returns the flight time of the projectile in seconds
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
virtual Float64 getFlightTime(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity) = 0;
|
||||
|
||||
/**
|
||||
* returns the firing angle of the projectile if the following are given
|
||||
*
|
||||
* @param a_distance distance to the target
|
||||
* @param a_initialAmmuVelocity initial velocity
|
||||
* @param a_terrainAngle gun angle to terrain
|
||||
* @param a_airDensity air density
|
||||
*/
|
||||
virtual Float64 getFireAngle(const Float64 a_distance, const Float64 a_initialAmmuVelocity, const N_Types::Radian64 a_terrainAngle, const Float64 a_airDensity) = 0;
|
||||
|
||||
/**
|
||||
* This function corrects the fire angle due to the cross wind, if the following
|
||||
* are given
|
||||
*
|
||||
* @param a_crossWind wind speed
|
||||
* @param a_distance distance from gun
|
||||
*/
|
||||
virtual N_Types::Radian64 getCrossWindCorrection(const Float64 a_crossWind, const Float64 a_distance) = 0;
|
||||
|
||||
/**
|
||||
* returns the air density
|
||||
*
|
||||
* @param a_atmosphericPressure Pressure
|
||||
* @param a_airTemperature Temperature
|
||||
*/
|
||||
virtual Float64 getAirDensity(const Float64 a_atmosphericPressure, const Float64 a_airTemperature) = 0;
|
||||
|
||||
/**
|
||||
* This function corrects the fire angle due to the cross wind
|
||||
*
|
||||
* @param a_crossWind Wind direction
|
||||
* @param a_turretDir Direction of Turret
|
||||
*/
|
||||
virtual Float64 getCrossWind(const N_Types::Coord3 &a_crossWind, const Float64 a_turretDir) = 0;
|
||||
|
||||
/**
|
||||
* returns the theritical initial ammu velocity of the ammunition
|
||||
*
|
||||
* @param a_temperature Temperature
|
||||
*/
|
||||
virtual Float64 getInitialAmmuVelocity(const Float64 a_temperature) = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
// from stereotyped includes
|
||||
#include "IUnknown.hpp"
|
||||
#include <GBL_Types/Angle3.hpp>
|
||||
#include <GBL_Types/Coord3.hpp>
|
||||
|
||||
// manual class imports
|
||||
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* Interface for trajectory implementations
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 07-Aug-2009 13:36:55
|
||||
*/
|
||||
class ITrajectory : public IUnknown
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ITrajectory() = default;
|
||||
|
||||
/**
|
||||
* initializes the object with the following parameters
|
||||
*
|
||||
* @param a_gunPos Position of the gun
|
||||
* @param a_gunAngle Shooting angle of the gun
|
||||
* @param a_crossWind lateral wind
|
||||
* @param a_airDensity
|
||||
* @param a_initialAmmuSpeed ammunition speed
|
||||
*/
|
||||
virtual bool init(const N_Types::Coord3 &a_gunPos,
|
||||
const N_Types::Angle3 &a_gunAngle,
|
||||
const Float64 a_crossWind,
|
||||
const Float64 a_airDensity,
|
||||
const Float64 a_initialAmmuSpeed) = 0;
|
||||
|
||||
/**
|
||||
* calculates the next tracer point using the delta time
|
||||
*
|
||||
* @param a_deltaTime time difference to last call
|
||||
*/
|
||||
virtual bool move(const Float64 a_deltaTime) = 0;
|
||||
|
||||
/**
|
||||
* returns the current position of the tracer
|
||||
*/
|
||||
virtual const N_Types::Coord3 &getPosition() const = 0;
|
||||
|
||||
/**
|
||||
* returns the current orientation of the tracer
|
||||
*/
|
||||
virtual const N_Types::Angle3 &getOrient() const = 0;
|
||||
|
||||
/**
|
||||
* returns the acceleration/deceleration vector
|
||||
*/
|
||||
virtual const N_Types::Coord3 &getAccel() const = 0;
|
||||
|
||||
/**
|
||||
* returns the velocity vector
|
||||
*/
|
||||
virtual const N_Types::Coord3 &getVelocity() const = 0;
|
||||
|
||||
/**
|
||||
* this function returns the state of the tracer
|
||||
*/
|
||||
virtual bool isActive() const = 0;
|
||||
|
||||
/**
|
||||
* deactivate a tracer
|
||||
*/
|
||||
virtual void deactivate() = 0;
|
||||
|
||||
/**
|
||||
* sets an integer ID of the bullet, used for SimMunitionIDs
|
||||
*
|
||||
* @param a_id
|
||||
*/
|
||||
virtual void setID(SInt32 a_id) = 0;
|
||||
|
||||
/**
|
||||
* gets an integer ID of the bullet, used for SimMunitionIDs
|
||||
*/
|
||||
virtual SInt32 getID() const = 0;
|
||||
|
||||
/**
|
||||
* if a bullet detonates after a certain timeout, defined by the timeout in the
|
||||
* config file
|
||||
*/
|
||||
virtual bool IsDetonateOnTimer() const = 0;
|
||||
|
||||
/**
|
||||
* if a bullet detonates on either terrain or object impact
|
||||
*/
|
||||
virtual bool IsDetonateOnImpact() const = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
#include <GBL_Global/Types.hpp>
|
||||
|
||||
// manual class imports
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* Base Interface for all interfaces used in this package
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 07-Aug-2009 13:41:51
|
||||
*/
|
||||
class IUnknown
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~IUnknown() = default;
|
||||
|
||||
|
||||
/**
|
||||
* Using this function a reference to the interface is added.
|
||||
*/
|
||||
virtual SInt32 addRef() = 0;
|
||||
|
||||
/**
|
||||
* Calling this function the reference from the interface may be removed.
|
||||
*/
|
||||
virtual SInt32 release() = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
// **************************************************************************
|
||||
//
|
||||
// (C) Copyright 2009 Swiss SIMTEC AG
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// $HeadURL$
|
||||
// $LastChangedBy$
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
//
|
||||
// **************************************************************************
|
||||
|
||||
#include <GBL_Global/Types.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace N_Ballistic
|
||||
{
|
||||
|
||||
/**
|
||||
* Polygonal representation of ballistic values
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 10-Aug-2009 11:07:22
|
||||
*/
|
||||
struct PolygonParamType
|
||||
{
|
||||
/**
|
||||
* Container for PolyCoefficientType
|
||||
*
|
||||
* @author Daniel.Schmid
|
||||
* @version 1.0
|
||||
* @created 10-Aug-2009 11:08:15
|
||||
*/
|
||||
struct PolyCoefficientType
|
||||
{
|
||||
SInt32 m_Index = 0;
|
||||
Float64 m_Coeff = 0.0;
|
||||
|
||||
};
|
||||
|
||||
std::vector<PolyCoefficientType> m_AY;
|
||||
std::vector<PolyCoefficientType> m_AX;
|
||||
Float64 m_InitialAX = 0.0;
|
||||
bool m_Valid = false;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Loaded 100 of 16245 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user