Files
qt5-legatus-legacy/Lts/Plugins/AreaEffectSimulation/Gui/Explosion/aes_rocket_utility.cpp
T
torstenandCopilot 3028302f7b Qt6 Migration: Merge latest Qt5 devel content and apply migration fixes
- Merged 292 changed files from dlbo snapshot
- Fixed IDL enum collisions (PortType, PdmEventType)
- Fixed Grantlee template for C++11 scoped enums
- Fixed CMake VERSION_GREATER syntax
- Added missing directories (THP, LtsRestClient, etc.)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-15 18:20:51 +00:00

260 lines
10 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Namespace for rocket related functions
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Fritsche, ESZS, 2026-06-03
*/
#include "aes_rocket_utility.h"
#include <QComboBox>
#include <QJsonDocument>
#include <QJsonObject>
#include <QStandardItemModel>
#include <AreaEffectSimulation/aes.hpp>
#include <AreaEffectSimulation/Trajectory/trajectory_generator.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <LtsUtils/LtsUtilsCore/qpoint3d.h>
#include <ParticipantManagement/ppm_dtc.h>
#include <ProjectDataManagement/pdm_enums.hpp>
#include <Proxies/TrainingAreaBase/Plugins/AdlerJson/telegrams.h>
namespace AreaEffectSimulation
{
namespace RocketUtility
{
void enaDisaWirkmittel(QComboBox *wirkmittelCombobox, AesExplosionGeometry::type geometry)
{
if (wirkmittelCombobox == nullptr)
return;
const QStandardItemModel *cboModel = qobject_cast<QStandardItemModel *>(wirkmittelCombobox->model());
if (cboModel == nullptr)
return;
switch (geometry)
{
case AesExplosionGeometry::type::EgAimPoint:
case AesExplosionGeometry::type::EgPoint:
case AesExplosionGeometry::type::EgLine:
for (int indexCounter = 0; indexCounter < wirkmittelCombobox->count(); ++indexCounter)
{
const QVariant currentData = wirkmittelCombobox->itemData(indexCounter);
const ProjectDataManagement::GearClass::type currentGearClass = static_cast<ProjectDataManagement::GearClass::type>(currentData.toInt());
if (currentGearClass == ProjectDataManagement::GearClass::Rocket)
{
QStandardItem *item = cboModel->item(indexCounter);
if (item == nullptr)
continue;
item->setFlags(item->flags() | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
// we do not break the loop here because there may be more rocket wirkmittel in the future
}
}
return;
case AesExplosionGeometry::type::EgRadial:
case AesExplosionGeometry::type::EgArea:
{
const int currentIndex = wirkmittelCombobox->currentIndex();
for (int indexCounter = 0; indexCounter < wirkmittelCombobox->count(); ++indexCounter)
{
const QVariant currentData = wirkmittelCombobox->itemData(indexCounter);
const ProjectDataManagement::GearClass::type currentGearClass = static_cast<ProjectDataManagement::GearClass::type>(currentData.toInt());
if (currentGearClass == ProjectDataManagement::GearClass::Rocket)
{
QStandardItem *item = cboModel->item(indexCounter);
if (item == nullptr)
continue;
item->setFlags(item->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable);
// if rocket ist currently selected, we have to set another index
if (indexCounter == currentIndex && wirkmittelCombobox->count() > 1)
{
const int newIndex = currentIndex == 0 ? 1 : 0;
wirkmittelCombobox->setCurrentIndex(newIndex);
}
// we do not break the loop here because there may be more rocket wirkmittel in the future
}
}
return;
}
default:
return;
}
}
void addRocketPropertiesToRequest(EffectClusterModifyRequest &request, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc)
{
switch (request.explosionGeometry().underlying())
{
case AesExplosionGeometry::type::EgAimPoint:
case AesExplosionGeometry::type::EgPoint:
addRocketPropertiesForPointGeometry(request, ppmDtc);
return;
case AesExplosionGeometry::type::EgLine:
addRocketPropertiesForLinearGeometry(request, ppmDtc);
return;
case AesExplosionGeometry::type::EgRadial:
case AesExplosionGeometry::type::EgArea:
default:
return;
}
}
void addRocketPropertiesForLinearGeometry(EffectClusterModifyRequest &request, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc)
{
using namespace LtsCoordTrans;
AdlerJson::WirkmittelFeuerkommandoRakete wirkmittel;
AdlerJson::Treffpunkt treffpunkt;
wirkmittel.wirkzeit = 6;
const UtmCoordinate areaBottomLeftUtm = UtmCoordinate::fromGeographic(request.area().cornerBottomLeft().lon(), request.area().cornerBottomLeft().lat());
QTransform transform;
transform.translate(areaBottomLeftUtm.x, areaBottomLeftUtm.y);
transform.rotate(-request.area().rotation());
const double yLocal = request.area().height() / 2;
int mhpSliceCounter = 1;
for (EffectorData &currentEffector : request.effectors())
{
wirkmittel.geschoss.anzahl = currentEffector.chargeAmount();
treffpunkt.anzahl = wirkmittel.geschoss.anzahl;
// calculate local x
double xLocal = request.area().width() * (static_cast<double>(mhpSliceCounter++) / (request.effectors().size() + 1));
// transform local point to UTM
const QPointF localPoint(xLocal, yLocal);
const QPointF utmPoint = transform.map(localPoint);
// tranform utm point to geographic WGS84 coordinate
const UtmCoordinate currentUtm(areaBottomLeftUtm.zone, utmPoint.x(), utmPoint.y());
const QPointF mhpGeo = currentUtm.geographic();
// treffpunkt
currentEffector.mhpPosition().lon(mhpGeo.x());
currentEffector.mhpPosition().lat(mhpGeo.y());
treffpunkt.koordinate.koordinate.longitude = currentEffector.mhpPosition().lon() * LtsCoordTrans::rad2deg();
treffpunkt.koordinate.koordinate.latitude = currentEffector.mhpPosition().lat() * LtsCoordTrans::rad2deg();
wirkmittel.treffpunkte.clear();
wirkmittel.treffpunkte.append(treffpunkt);
QJsonObject wirkmittelObj;
AdlerJson::wirkmittelFeuerkommandoRaketeToJson(wirkmittelObj, wirkmittel);
currentEffector.properties(QJsonDocument(wirkmittelObj).toJson().toStdString());
// trajectory
const ParticipantManagement::ParticipantPosition &participantPosition = ppmDtc->participantPosition(currentEffector.participantId());
const LtsUtils::QPoint3D trajectoryStart(participantPosition.pos().lon(),
participantPosition.pos().lat(),
participantPosition.pos().z());
const LtsUtils::QPoint3D trajectoryEnd(currentEffector.mhpPosition().lon(),
currentEffector.mhpPosition().lat(),
currentEffector.mhpPosition().z()); // TODO
TrajectoryGeoPosition trajectoryWithoutTime;
TrajectoryGenerator::getInstance()->generateTrajectoryBiedziak(trajectoryStart, trajectoryEnd, 45.0, trajectoryWithoutTime);
currentEffector.flightTime(60000.0);
const double flightTimeStep = currentEffector.flightTime() / static_cast<double>(trajectoryWithoutTime.size());
double currentFlightTime = 0.0;
currentEffector.trajectoryRelative().clear(); // LS_711_akkumulierende_flugkurven_bei_rakete
const LtsCoordTrans::UtmCoordinate utmStartPos = LtsCoordTrans::UtmCoordinate::fromGeographic(participantPosition.pos().lon(), participantPosition.pos().lat());
for (const Core::GeoPosition &pos : trajectoryWithoutTime)
{
const LtsCoordTrans::UtmCoordinate utmCurrentPos = LtsCoordTrans::UtmCoordinate::fromGeographic(pos.lon(), pos.lat());
currentEffector.trajectoryRelative().emplace_back(utmCurrentPos.x - utmStartPos.x,
utmCurrentPos.y - utmStartPos.y, pos.z(), currentFlightTime);
currentFlightTime += flightTimeStep;
}
}
}
void addRocketPropertiesForPointGeometry(EffectClusterModifyRequest &request, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc)
{
using namespace LtsCoordTrans;
AdlerJson::WirkmittelFeuerkommandoRakete wirkmittel;
AdlerJson::Treffpunkt treffpunkt;
wirkmittel.wirkzeit = 6;
treffpunkt.anzahl = 1;
const UtmCoordinate areaBottomLeftUtm = UtmCoordinate::fromGeographic(request.area().cornerBottomLeft().lon(), request.area().cornerBottomLeft().lat());
const QPointF areaCenterGeo = areaBottomLeftUtm.geographic(request.area().width() / 2, request.area().height() / 2);
for (EffectorData &currentEffector : request.effectors())
{
wirkmittel.geschoss.anzahl = currentEffector.chargeAmount();
treffpunkt.anzahl = wirkmittel.geschoss.anzahl;
// treffpunkt
currentEffector.mhpPosition().lon(areaCenterGeo.x());
currentEffector.mhpPosition().lat(areaCenterGeo.y());
treffpunkt.koordinate.koordinate.longitude = currentEffector.mhpPosition().lon() * LtsCoordTrans::rad2deg();
treffpunkt.koordinate.koordinate.latitude = currentEffector.mhpPosition().lat() * LtsCoordTrans::rad2deg();
wirkmittel.treffpunkte.clear();
wirkmittel.treffpunkte.append(treffpunkt);
QJsonObject wirkmittelObj;
AdlerJson::wirkmittelFeuerkommandoRaketeToJson(wirkmittelObj, wirkmittel);
currentEffector.properties(QJsonDocument(wirkmittelObj).toJson().toStdString());
// trajectory
const ParticipantManagement::ParticipantPosition &participantPosition = ppmDtc->participantPosition(currentEffector.participantId());
const LtsUtils::QPoint3D trajectoryStart(participantPosition.pos().lon(),
participantPosition.pos().lat(),
participantPosition.pos().z());
const LtsUtils::QPoint3D trajectoryEnd(currentEffector.mhpPosition().lon(),
currentEffector.mhpPosition().lat(),
currentEffector.mhpPosition().z());
TrajectoryGeoPosition trajectoryWithoutTime;
TrajectoryGenerator::getInstance()->generateTrajectoryBiedziak(trajectoryStart, trajectoryEnd, 45.0, trajectoryWithoutTime);
currentEffector.flightTime(60000.0);
const double flightTimeStep = currentEffector.flightTime() / static_cast<double>(trajectoryWithoutTime.size());
double currentFlightTime = 0.0;
currentEffector.trajectoryRelative().clear(); // LS_711_akkumulierende_flugkurven_bei_rakete
const LtsCoordTrans::UtmCoordinate utmStartPos = LtsCoordTrans::UtmCoordinate::fromGeographic(participantPosition.pos().lon(), participantPosition.pos().lat());
for (const Core::GeoPosition &pos : trajectoryWithoutTime)
{
const LtsCoordTrans::UtmCoordinate utmCurrentPos = LtsCoordTrans::UtmCoordinate::fromGeographic(pos.lon(), pos.lat());
currentEffector.trajectoryRelative().emplace_back(utmCurrentPos.x - utmStartPos.x,
utmCurrentPos.y - utmStartPos.y, pos.z(), currentFlightTime);
currentFlightTime += flightTimeStep;
}
} // for (EffectorData &currentEffector : request.effectors())
}
} // namespace RocketUtility
} // namespace AreaEffectSimulation