/** * @RDE_HEADER@ * Namespace for rocket related functions * $Id$ * $HeadURL$ * $Author$ * Created by Hannes Fritsche, ESZS, 2026-06-03 */ #include "aes_rocket_utility.h" #include #include #include #include #include #include #include #include #include #include #include namespace AreaEffectSimulation { namespace RocketUtility { void enaDisaWirkmittel(QComboBox *wirkmittelCombobox, AesExplosionGeometry::type geometry) { if (wirkmittelCombobox == nullptr) return; const QStandardItemModel *cboModel = qobject_cast(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(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(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 &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 &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 ¤tEffector : request.effectors()) { wirkmittel.geschoss.anzahl = currentEffector.chargeAmount(); treffpunkt.anzahl = wirkmittel.geschoss.anzahl; // calculate local x double xLocal = request.area().width() * (static_cast(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(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 &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 ¤tEffector : 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(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 ¤tEffector : request.effectors()) } } // namespace RocketUtility } // namespace AreaEffectSimulation