Files
qt5-legatus-legacy/Lts/Services/EffectShowManagement/effect_show_explosion_cluster.cpp
T
2026-08-13 18:33:10 +02:00

240 lines
10 KiB
C++
Executable File

/**
* Handler for the HMI language
* $Id$
* $HeadURL$
* $Author$
*/
#include "effect_show_explosion_cluster.h"
namespace EffectShowManagement
{
EffectShowExplosionCluster::EffectShowExplosionCluster(const AreaEffectSimulation::ExplosionCluster &explosionCluster,
const std::shared_ptr<HandlerPdmData> &handlerPdmData)
: m_explosionCluster(explosionCluster)
, m_handlerPdmData(handlerPdmData)
, m_numOfEffectShows(0)
, m_logger(getLogger("EffectShowExplosionCluster"))
{
}
//=============================================================================
int EffectShowExplosionCluster::getNumOfEffectShows()
{
if (m_numOfEffectShows == 0)
calculateSquare();
return m_numOfEffectShows;
}
//=============================================================================
Database::EsmEffectShow EffectShowExplosionCluster::getEffectShow(int idx)
{
if (m_numOfEffectShows == 0)
calculateSquare();
Database::EsmEffectShow esmEffectShow;
if (!m_handlerPdmData->isSmoke(m_explosionCluster.chargeStruct()))
{
int indX = idx % m_areasWidth.numOfAreas;
int indY = idx / m_areasWidth.numOfAreas;
// calculate lower left position
double x_off = 0.0;
for (int i = 0; i < indX; ++i)
x_off += m_areasWidth.side(i);
double y_off = 0.0;
for (int i = 0; i < indY; ++i)
y_off += m_areasDepth.side(i);
LtsCoordTrans::UtmCoordinate lowerLeftPos = m_lowerLeftPos;
lowerLeftPos.x = lowerLeftPos.x + x_off;
lowerLeftPos.y = lowerLeftPos.y + y_off;
LtsCoordTrans::UtmCoordinate lowerLeftPosRotated = rotate(lowerLeftPos, m_lowerLeftPos, rotationRad());
// calculate center position
LtsCoordTrans::UtmCoordinate centerPos = lowerLeftPos;
centerPos.x = centerPos.x + m_areasWidth.side(indX) / 2.;
centerPos.y = centerPos.y + m_areasDepth.side(indY) / 2.;
LtsCoordTrans::UtmCoordinate centerPosRotated = rotate(centerPos, m_lowerLeftPos, rotationRad());
esmEffectShow.id = 0;
esmEffectShow.name = QStringLiteral("EXP");
esmEffectShow.startTime = m_explosionCluster.effectStart().is_set() ? m_explosionCluster.effectStart().get() : 0;
esmEffectShow.duration = m_explosionCluster.effectDuration();
esmEffectShow.centerPosition = centerPosRotated.geographic();
esmEffectShow.idAreaEffectSimulation = m_explosionCluster.id();
esmEffectShow.esmParticipantId = -1;
esmEffectShow.nameAreaEfffectSimulation = QString::fromStdString(m_explosionCluster.name());
esmEffectShow.numOfVolley = getNumberOfVolley();
esmEffectShow.shotsPerVolley = getShotsPerArea() / esmEffectShow.numOfVolley;
esmEffectShow.typeOfAmmunition = m_explosionCluster.chargeStruct().chargeTypeId();
// can there be more then 48 shoots?
if (esmEffectShow.shotsPerVolley > 48)
esmEffectShow.shotsPerVolley = 48;// (48 / esmEffectShow.numOfVolley);
if (esmEffectShow.shotsPerVolley <= 0)
esmEffectShow.shotsPerVolley = 1;
esmEffectShow.lowerLeftPosition = lowerLeftPosRotated.geographic();
esmEffectShow.areaWidth = m_areasWidth.side(indX);
esmEffectShow.areaDepth = m_areasDepth.side(indY);
esmEffectShow.areaRotation = m_explosionCluster.area().rotation() + 90;
DEBUG_LOG(m_logger) << "\nWidth: " << m_explosionCluster.area().width() << " Height: " << m_explosionCluster.area().height()
<< "\nRotated LL Pos: " << lowerLeftPosRotated.mgrs()
<< "\nRotated Center Pos: " << centerPosRotated.mgrs()
<< "\nOffset x,y: " << x_off << " , " << y_off
<< "\nSide x,y: " << m_areasWidth.side(indX) << " , " << m_areasDepth.side(indY)
<< "\nindX: " << indX << " grid " << m_areasWidth.numSideLength1 << ' ' << m_areasWidth.sideLength1 << ' ' << m_areasWidth.numSideLength2 << ' ' << m_areasWidth.sideLength2
<< "\nindY: " << indY << " grid " << m_areasDepth.numSideLength1 << ' ' << m_areasDepth.sideLength1 << ' ' << m_areasDepth.numSideLength2 << ' ' << m_areasDepth.sideLength2;
}
else
{
LtsCoordTrans::UtmCoordinate lowerLeftPos = m_lowerLeftPos; //unnötig?
LtsCoordTrans::UtmCoordinate lowerLeftPosRotated = rotate(lowerLeftPos, m_lowerLeftPos, rotationRad());
// calculate center position
LtsCoordTrans::UtmCoordinate centerPos = lowerLeftPosRotated;
centerPos.x = centerPos.x + m_explosionCluster.area().width() / 2.;
centerPos.y = centerPos.y + m_explosionCluster.area().height() / 2.;
LtsCoordTrans::UtmCoordinate centerPosRotated = rotate(centerPos, m_lowerLeftPos, rotationRad());
esmEffectShow.id = 0;
esmEffectShow.name = QStringLiteral("EXP");
esmEffectShow.startTime = m_explosionCluster.effectStart().is_set() ? m_explosionCluster.effectStart().get() : 0;
esmEffectShow.duration = m_explosionCluster.effectDuration();
esmEffectShow.centerPosition = centerPosRotated.geographic();
esmEffectShow.idAreaEffectSimulation = m_explosionCluster.id();
esmEffectShow.esmParticipantId = -1;
esmEffectShow.nameAreaEfffectSimulation = QString::fromStdString(m_explosionCluster.name());
esmEffectShow.typeOfAmmunition = m_explosionCluster.chargeStruct().chargeTypeId();
esmEffectShow.numOfVolley = 1;
esmEffectShow.shotsPerVolley = 1;
esmEffectShow.lowerLeftPosition = lowerLeftPosRotated.geographic();
esmEffectShow.areaWidth = m_explosionCluster.area().width();
esmEffectShow.areaDepth = m_explosionCluster.area().height();
esmEffectShow.areaRotation = m_explosionCluster.area().rotation() + 90;
DEBUG_LOG(m_logger) << "\nWidth: " << m_explosionCluster.area().width() << " Height: " << m_explosionCluster.area().height()
<< "\nRotated LL Pos: " << lowerLeftPosRotated.mgrs()
<< "\nRotated Center Pos: " << centerPosRotated.mgrs()
<< "\nSide x,y: " << m_explosionCluster.area().width() << " , " << m_explosionCluster.area().height();
}
return esmEffectShow;
}
//=============================================================================
void EffectShowExplosionCluster::updateEffectShow(Database::EsmEffectShow &data)
{
DEBUG_LOG(m_logger) << "update EffectSHow for (" << data.id << ")";
data.nameAreaEfffectSimulation = QString::fromStdString(m_explosionCluster.name());
data.startTime = m_explosionCluster.effectStart().is_set() ? m_explosionCluster.effectStart().get() : 0;
data.duration = m_explosionCluster.effectDuration();
if (data.shotsPerVolley > 48)
data.shotsPerVolley = 48;//(48 / data.numOfVolley);
if (data.shotsPerVolley <= 0)
data.shotsPerVolley = 1;
data.typeOfAmmunition = m_explosionCluster.chargeStruct().chargeTypeId();
}
//-----------------------------------------------------------------------------
void EffectShowExplosionCluster::calculateSquare()
{
Core::GeoPosition2D geoPos = m_explosionCluster.area().cornerBottomLeft();
m_lowerLeftPos = LtsCoordTrans::UtmCoordinate::fromGeographic(geoPos.lon(), geoPos.lat());
// Calculate squares.
m_areasWidth = getAreasSideLength(m_explosionCluster.area().width()); // Squares in x-direction
m_areasDepth = getAreasSideLength(m_explosionCluster.area().height()); // Squares in y-direction
m_numOfEffectShows = m_handlerPdmData->effectShowCount(m_explosionCluster.chargeStruct());
}
//static ----------------------------------------------------------------------
LtsCoordTrans::UtmCoordinate EffectShowExplosionCluster::rotate(const LtsCoordTrans::UtmCoordinate &p, const LtsCoordTrans::UtmCoordinate &c, double angle)
{
LtsCoordTrans::UtmCoordinate res = p; // copy zone, northp
res.x = ((p.x - c.x) * cos(angle)) - ((p.y - c.y) * sin(angle)) + c.x;
res.y = ((p.x - c.x) * sin(angle)) + ((p.y - c.y) * cos(angle)) + c.y;
return res;
}
//static ----------------------------------------------------------------------
EffectShowExplosionCluster::areas_t EffectShowExplosionCluster::getAreasSideLength(double sideLength)
{
areas_t res;
int sl = qRound(sideLength + 0.5);
int n50 = (sl < 25) ? 1 : (sl + 25) / 50; // number of 50m squares
int n300 = n50 / 6; // number of 300m squares
int len = n50 * 50; // length to be diveded into squares
res.numOfAreas = ((n300 * 6) == n50) ? n300 : n300 + 1; // number of areas at all
res.sideLength1 = (len / (res.numOfAreas * 50)) * 50;
res.numSideLength2 = (len - (res.numOfAreas * res.sideLength1)) / 50;
res.sideLength2 = res.sideLength1 + 50;
res.numSideLength1 = res.numOfAreas - res.numSideLength2;
//qCritical() << "sl = " << sl << " n50= " << n50 << " n300 = " << n300 << " len = "
// << len << " numOfAreas = " << res.numOfAreas << " sideLength1 = " << res.sideLength1;
return res;
}
//-----------------------------------------------------------------------------
int EffectShowExplosionCluster::getNumberOfVolley() const
{
const int v = getShotsPerArea();
return getNumberOfVolley(v);
}
//-----------------------------------------------------------------------------
int EffectShowExplosionCluster::getShotsPerArea() const
{
if (!m_numOfEffectShows)
return 0;
int v = m_explosionCluster.impactCount(); //cannonCount() * m_explosionCluster.cannonRounds();
return v / m_numOfEffectShows; //split even across all effect shows
}
int EffectShowExplosionCluster::getShotsPerArea(int areas) const
{
if (areas == 0)
return 0;
int v = m_explosionCluster.impactCount();//cannonCount() * m_explosionCluster.cannonRounds();
return v / areas;
}
int EffectShowExplosionCluster::getNumberOfVolley(int v)
{
if (v < 3) // <= 0 should not happen but did...
return qMax(1, v);
if (v <= 25)
return 3;
if (v <= 50)
return 6;
if (v <= 100)
return 9;
if (v <= 150)
return 12;
if (v <= 200)
return 15;
return 18;
}
//-----------------------------------------------------------------------------
double EffectShowExplosionCluster::rotationRad() const
{
return -m_explosionCluster.area().rotation() * LtsCoordTrans::deg2rad();
}
//-----------------------------------------------------------------------------
} // Namespace EffectShowManagement