249 lines
9.9 KiB
C++
Executable File
249 lines
9.9 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* ObjectMap for ExplosionCluster
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
*/
|
|
#pragma once
|
|
|
|
#include "aes_db.h"
|
|
#include "object_base.h"
|
|
#include <CentralEffectSimulation/ces_ftc.h>
|
|
#include <TrainingAreaBase/tab_ftc.h>
|
|
#include <Trajectory/trajectory_generator.h>
|
|
#include <LtsUtilsCore/qpoint3d.h>
|
|
#include <LtsCoordTrans/lts_coord_trans.h>
|
|
#include <Utils/firing_timer.h>
|
|
#include <Utils/aes_helper.h>
|
|
|
|
#include <QDateTime>
|
|
|
|
using DetonationLocationRequest = CentralEffectSimulation::DetonationLocationRequest;
|
|
using DetonationLocationReply = CentralEffectSimulation::DetonationLocationReply;
|
|
|
|
|
|
namespace AreaEffectSimulation
|
|
{
|
|
|
|
class ObjectExplosionCluster final
|
|
: public ObjectBaseTmpl<Database::AesExplosionCluster>
|
|
, protected CentralEffectSimulation::Interface::Ftc::DetonationLocationReplyHandler
|
|
{
|
|
Q_OBJECT
|
|
|
|
using BaseClass = ObjectBaseTmpl<Database::AesExplosionCluster>;
|
|
|
|
public:
|
|
|
|
constexpr static double s_defaultZ_Value = 100; // default Elevation for GUEZ / Altmark. Hopefully fine for other areas..
|
|
constexpr static double s_invalid_rotation_angle = -1000;
|
|
|
|
explicit ObjectExplosionCluster(MainHandler *mainHandler,
|
|
QObject *parent = nullptr);
|
|
~ObjectExplosionCluster();
|
|
|
|
bool isActivationTimeReached() const override
|
|
{
|
|
if (noTracjectoryRequired())
|
|
return BaseClass::isActivationTimeReached();
|
|
|
|
return false;
|
|
}
|
|
|
|
qint32 flightDurationMsec() const override { return m_data.flightDuration; }
|
|
|
|
bool isOnlyObjectNameModifiable() const override;
|
|
bool isObjectModifiable() const override; // is at least one parameter in the object modifyable
|
|
bool isFiringTimeReached() const override;
|
|
|
|
Core::FunctionReplyObject createObject(const Database::AesExplosionCluster &data);
|
|
Core::FunctionReplyObject updateObject(const Database::AesExplosionCluster &data) override;
|
|
Core::FunctionReplyObject removeObject() override;
|
|
|
|
Core::FunctionReplyObject checkObjectData(const Database::AesExplosionCluster &data) const;
|
|
|
|
/*!
|
|
* \brief removeObjectFromDb
|
|
* \details Removes the object from db, Used if the object is created but there are to much objects (amount border)
|
|
* \author Niklas Schmidt
|
|
* \return bool if the deletion was working
|
|
*/
|
|
bool removeObjectFromDb();
|
|
|
|
Core::FunctionReplyObject resumePause(const ExplosionClusterPauseResumeRequest &req);
|
|
Core::FunctionReplyObject targetPositionsModify(const TargetPositionsModifyRequest &req);
|
|
|
|
Core::FunctionReplyObject checkPreConditionsComplete();
|
|
Core::FunctionReplyObject checkPreConditions();
|
|
bool initialCalculations(QString *reasonOut = nullptr);
|
|
void abortPreStartTimer();
|
|
|
|
std::vector<Core::GeoPosition> form() const override { return m_aiv.form(); }
|
|
QPolygonF generateForm() override;
|
|
AesType aesType() const override { return AesType::AtExplosionArea; }
|
|
bool isCentral() const override { return m_data.isCentral; }
|
|
bool isExplosionClusterMarkedValid() const { return m_temporaryData.annotationString.empty(); }
|
|
void removeTopics();
|
|
void setCookie(const rti::core::SampleIdentity &cookie) {m_cookie = cookie;}
|
|
|
|
// Vulcano
|
|
bool isVulcano() const { return chargeTypeIdIsVulcano(m_data.chargeTypeId); }
|
|
|
|
// From HLA, no participantId -> -1;
|
|
// 0 is default. For ExplosionClusterDialog, a value of zero is an error!
|
|
// to skip trajectory, provied -1.
|
|
bool isOriginatorParticipantIdProvided() const { return m_data.participantId >= 0; } // !! >= !! For ExplosionClusterDialog, a value of zero is an error!
|
|
|
|
void setAirSupportSource(bool isAirSupportSource) { m_isAirSupportSource = isAirSupportSource; }
|
|
|
|
bool isMhpRotationProvided() const { return m_data.mhpRotationRequest > s_invalid_rotation_angle; }
|
|
|
|
bool noTracjectoryRequired() const { return (m_data.externalId > 0) || (m_data.participantId <= 0); }
|
|
void setAesProperty(QJsonObject property, bool pubish = true);
|
|
|
|
protected:
|
|
void setEffectState(AesEffectState newState) override;
|
|
void publishAiv();
|
|
|
|
protected Q_SLOTS:
|
|
void onPublishData() override;
|
|
void onDetonationLocationReply(const DetonationLocationReply &reply) override;
|
|
void checkNextFire();
|
|
// void checkNextSingleExplosion();
|
|
|
|
void onFiringTimerFiring(int currentFiringNumber, int totalAmmoCount);
|
|
void onFiringTimerImpact(int currentExplosionNumber, int totalAmmoCount);
|
|
void onFiringTimerStateChangeDelayedCommandAsInt(int cmdAsInt, int firedAmmoCount);
|
|
|
|
protected:
|
|
bool generateTrajectory(int explosionNumber, bool startDetonationLocationRequest = true, QString *reasonOut = nullptr);
|
|
bool generateTrajectoryVulcanoSpecific(int explosionNumber, const TrajectoryGeneratorVulcano::Options options, QString *reasonOut = nullptr);
|
|
double getElevationFor(const QPointF &originGeoRadiant, const QString &context) const;
|
|
|
|
void adjustTrajectoryToDetonationLocation(int explosionIndex, const Core::GeoPosition &intersectionLocation, const int buildingId);
|
|
// void setTrajectoryStartTime(int explosionIndex);
|
|
|
|
Core::FunctionReplyObject setupFiringOrigin();
|
|
bool getFiringUnitOrigin(const int firingParticipantId, LtsUtils::QPoint3D &firingOriginOut, QString *reasonOut = nullptr);
|
|
bool firingOriginIsValid(const LtsUtils::QPoint3D &firingOrigin, QString *reasonOut) const;
|
|
LtsUtils::QPoint3D getFiringCannonGeoPosition(int explosionIndex) const;
|
|
LtsUtils::QPoint3D getFiringCannonUtmPosition(int explosionIndex, int zoneToUse) const;
|
|
|
|
std::vector<Core::GeoPosition> generateGunToTargetForm(QString *reasonOut = nullptr);
|
|
void publishTrajectory(int explosionIndex);
|
|
void publishTrajectoryViaHandler(const TrajectoryTimeAware& trajectoryTimeAwareRef);
|
|
|
|
// void publishDetonationAiv();
|
|
|
|
private:
|
|
void dump(const char *file = nullptr, int lineNo = 0) const;
|
|
// void startSingleExplosionHandling();
|
|
// void stopSingleExplosionHandling(AesEffectState newState);
|
|
// qint64 impactDeltaMSec() const;
|
|
// int currentExplosionNumber() const;
|
|
|
|
DetonationLocationRequest detonationLocationRequest(int explosionIndex) const;
|
|
|
|
private:
|
|
QTimer *m_singleExplosionTriggerTimer{nullptr};
|
|
QTimer *m_preStartTimer{nullptr};
|
|
int m_lastSentTriggeredExplosionNumber;
|
|
int m_chargeCountUntilLastStart;
|
|
|
|
FiringTimer m_firingTimer;
|
|
|
|
ExplosionCluster m_explosionCluster;
|
|
AesItemView m_aiv; // AtExplosionCluster
|
|
AesItemView m_aiv2; // AtExplosionClusterSingleExplosions - SingleExplosions
|
|
bool m_aiv2HasChanged{true};
|
|
|
|
// Effects
|
|
Effects m_effects; // replacement for m_aiv2 & TriggeredImpacts
|
|
|
|
AesItemView m_aivGunToTargetTrajectory; // AtExplosionClusterGunToTargetLine
|
|
bool m_aivGunToTargetTrajectoryDirty{false};
|
|
|
|
bool m_isAirSupportSource{false};
|
|
|
|
QMap<int, QString> m_publisedTrajectoriesForDebug;
|
|
|
|
struct temporaryData
|
|
{
|
|
std::string annotationString;
|
|
std::vector<Core::GeoPosition2D> mhPoints;
|
|
double mhpWidth {0.0};
|
|
double mhpLength {0.0};
|
|
double mhpRotation {0.0};
|
|
|
|
long estimatedMaxFlightDurationMSec{0};
|
|
double calculatedFiringAngle {0}; // degree
|
|
double calculatedFiringSpeed {0}; // m/sec
|
|
double calculatedPeakHeightAbs {0};
|
|
long calculatedFlightDurationMsec {0};
|
|
double calculatedMhpRotationNorthDeg {0};
|
|
|
|
// center
|
|
LtsCoordTrans::UtmCoordinate m_firingUnitOriginUtm;
|
|
LtsUtils::QPoint3D m_firingUnitOriginUtmPoint3D;
|
|
std::vector<Core::GeoPosition> gunToTargetLine;
|
|
|
|
// single
|
|
std::vector<Core::GeoPosition> singleFiringPositions; // 1..4
|
|
|
|
bool isObjectModifiable{true}; // will be set to false via checkNextFire by m_preStartTimer
|
|
void reset()
|
|
{
|
|
annotationString.clear();
|
|
mhPoints.clear();
|
|
mhpWidth = 0.0;
|
|
mhpLength = 0.0;
|
|
mhpRotation = 0.0;
|
|
|
|
estimatedMaxFlightDurationMSec = 0;
|
|
calculatedFiringAngle = 0;
|
|
calculatedFiringSpeed = 0;
|
|
calculatedPeakHeightAbs = 0;
|
|
calculatedFlightDurationMsec = 0;
|
|
calculatedMhpRotationNorthDeg = 0;
|
|
|
|
gunToTargetLine.clear();
|
|
m_firingUnitOriginUtm = LtsCoordTrans::UtmCoordinate();
|
|
m_firingUnitOriginUtmPoint3D = LtsUtils::QPoint3D();
|
|
|
|
singleFiringPositions.clear();
|
|
|
|
isObjectModifiable = true;
|
|
}
|
|
|
|
Core::GeoPosition getFiringCannonGeoPosition(int explosionIndex) const
|
|
{
|
|
if (singleFiringPositions.empty())
|
|
return Core::GeoPosition(std::nan(""), std::nan(""), std::nan(""));
|
|
|
|
const int numberCannons = singleFiringPositions.size();
|
|
|
|
int curIdx = explosionIndex % numberCannons;
|
|
return singleFiringPositions[curIdx];
|
|
}
|
|
|
|
} m_temporaryData;
|
|
|
|
|
|
struct TracjectoryData
|
|
{
|
|
int index{-1};
|
|
int buildingId{-1}; // BuildingId, which has intersection with trajectory
|
|
std::vector<Core::GeoPosition> trajectoryGeometry;
|
|
TrajectoryTimeAware trajectoryTimeAware;
|
|
long flightDurationMSec{0}; // idealValue, intersection with building ist not considered
|
|
double peakHeightAbs{0};
|
|
};
|
|
int m_explosionIndex = 0;
|
|
rti::core::SampleIdentity m_cookie;
|
|
QHash<int, TracjectoryData> m_trajectoryCont; // key: explosionIndex (which is ExplosionNumber-1)
|
|
|
|
QHash<int, int> m_trajectoryHandlerExplosionIndexToTopicId; // key: explosionIndex ; value: id in context TrajectoryHandler
|
|
};
|
|
}
|