Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* Handler for one indirect fire single object
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "object_explosion_single_central.h"
|
||||
#include "special_area_provider.h"
|
||||
#include "handler_explosion_single_central.h"
|
||||
#include "Utils/polygons.h"
|
||||
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include <QPolygonF>
|
||||
|
||||
|
||||
using Utm = LtsCoordTrans::UtmCoordinate;
|
||||
|
||||
namespace AreaEffectSimulation
|
||||
{
|
||||
|
||||
ObjectExplosionSingleCentral::ObjectExplosionSingleCentral(MainHandler *mainHandler, QObject *parent)
|
||||
: ObjectBaseTmpl(mainHandler, QStringLiteral("ExplosionSingleCentral"), parent)
|
||||
{}
|
||||
|
||||
ObjectExplosionSingleCentral::~ObjectExplosionSingleCentral()
|
||||
{
|
||||
removeTopics();
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectExplosionSingleCentral::updateObject(const Database::AesExplosionSingleCentral &data)
|
||||
{
|
||||
Core::FunctionReplyObject ret = ObjectBaseTmpl::updateObject(data);
|
||||
if (ret.error() || (isOnlyObjectNameModifiable() && (data.id > 0))) // data.id > 0 -> negative values from oc always get a full update
|
||||
return ret;
|
||||
|
||||
// only allow some fields
|
||||
auto tmpData(m_data);
|
||||
tmpData.id = std::abs(data.id);
|
||||
tmpData.name = data.name;
|
||||
tmpData.effectStart = data.effectStart;
|
||||
tmpData.impactPosition = data.impactPosition;
|
||||
tmpData.participantId = data.participantId;
|
||||
tmpData.partyId = data.partyId;
|
||||
tmpData.chargeTypeId = data.chargeTypeId;
|
||||
tmpData.fireRequestTime = data.fireRequestTime;
|
||||
tmpData.altitude = data.altitude;
|
||||
tmpData.effectMarkingInTa = data.effectMarkingInTa;
|
||||
tmpData.firePurpose = data.firePurpose;
|
||||
tmpData.rotationAngle = data.rotationAngle;
|
||||
tmpData.effectStateId = data.effectStateId; // overwrite for oc
|
||||
|
||||
if (!m_mainHandler->db()->update(tmpData))
|
||||
return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error updating single explosion central with id %1 in database.")).arg(m_data.id);
|
||||
m_data = std::move(tmpData);
|
||||
|
||||
m_publishDataTimer->start();
|
||||
checkEnterNewState();
|
||||
|
||||
return Core::FunctionReplyObject(data.id); // data not m_data for the possible negative id in the oc-laptop
|
||||
}
|
||||
|
||||
double ObjectExplosionSingleCentral::chargeRadius() const
|
||||
{
|
||||
return m_mainHandler->dds()->pdmDtc()->impactRadius(m_data.chargeTypeId);
|
||||
}
|
||||
|
||||
void ObjectExplosionSingleCentral::onPublishData()
|
||||
{
|
||||
ObjectBaseTmpl::onPublishData();
|
||||
|
||||
if (!m_mainHandler->db()->update(m_data))
|
||||
ERROR_LOG(m_logger) << "Error updating AesIndirectFireSingleCentral-data in database";
|
||||
|
||||
ExplosionSingleCentral ddsData(m_data.id,
|
||||
m_data.name.toStdString(),
|
||||
effectState() == AesEffectState::EsRemoved,
|
||||
false,
|
||||
partitionTimeMSec(),
|
||||
m_data.chargeTypeId,
|
||||
m_data.effectDuration,
|
||||
toOptional(toMSec(m_data.effectStart)),
|
||||
m_data.effectStateId,
|
||||
toOptional(m_data.partyId),
|
||||
toOptional(m_data.participantId),
|
||||
m_data.effectMarkingInTa,
|
||||
m_data.externalId,
|
||||
m_data.isCentral,
|
||||
Core::GeoPosition2D(m_data.impactPosition.x(),
|
||||
m_data.impactPosition.y()),
|
||||
toMSec(m_data.fireRequestTime),
|
||||
m_data.altitude,
|
||||
m_data.firePurpose.toStdString(),
|
||||
// m_data.participantId,
|
||||
m_data.angle,
|
||||
m_data.fuseTypeId);
|
||||
|
||||
m_mainHandler->dds()->dts()->publish(ddsData);
|
||||
|
||||
const Trajectory trajectory = Polygons::explosionSingleCentralTrajectory(
|
||||
m_data, positionOf(m_data.participantId), m_mainHandler->explosionSingleCentralHandler().get()->elevationMap()
|
||||
);
|
||||
ddsVecFromPoly(trajectory.first, trajectory.second, m_trajectory);
|
||||
const DetonationLocationRequest request = detonationLocationRequest(trajectory);
|
||||
m_mainHandler->dds()->cesFtc()->detonationLocationRequest(request, this);
|
||||
}
|
||||
|
||||
QPointF ObjectExplosionSingleCentral::positionOf(int participantId)
|
||||
{
|
||||
Q_UNUSED(participantId);
|
||||
LtsCoordTrans::UtmCoordinate iPosition = LtsCoordTrans::UtmCoordinate::fromGeographic(m_data.impactPosition);
|
||||
return iPosition.geographic(QPointF(-500, -2000));
|
||||
}
|
||||
|
||||
void ObjectExplosionSingleCentral::publishTrajectoryAiv()
|
||||
{
|
||||
QPolygonF poly;
|
||||
poly << QPointF(m_trajectory.front().lon(), m_trajectory.front().lat());
|
||||
poly << QPointF(m_trajectory.back().lon(), m_trajectory.back().lat());
|
||||
const QRectF boundsTrajectory(poly.boundingRect());
|
||||
AesItemView aivTrajectory(m_aivTrajectory);
|
||||
aivTrajectory.aesItemId(m_data.id);
|
||||
aivTrajectory.chargeTypeId(m_data.chargeTypeId);
|
||||
aivTrajectory.form(m_trajectory);
|
||||
aivTrajectory.effectStart(toMSec(m_data.effectStart));
|
||||
aivTrajectory.boundingBoxBottomLeft(Core::GeoPosition2D(boundsTrajectory.bottomLeft().x(), boundsTrajectory.bottomLeft().y()));
|
||||
aivTrajectory.boundingBoxTopRight(Core::GeoPosition2D(boundsTrajectory.topRight().x(), boundsTrajectory.topRight().y()));
|
||||
aivTrajectory.aesTypeId(AesType::AtExplosionSingleCentralTrajectory);
|
||||
aivTrajectory.effectStateId(effectState());
|
||||
aivTrajectory.id(1000 * m_data.id + AesType::AtExplosionSingleCentralTrajectory);
|
||||
if (m_data.partyId != 0)
|
||||
aivTrajectory.partyId(m_data.partyId);
|
||||
|
||||
checkIsCentralAndPublish(aivTrajectory.form(), m_aivTrajectory.form(), m_data.isCentral);
|
||||
|
||||
if (aivTrajectory != m_aivTrajectory)
|
||||
{
|
||||
aivTrajectory.sampleTime(partitionTimeMSec());
|
||||
m_aivTrajectory = aivTrajectory;
|
||||
m_mainHandler->dds()->dts()->publish(aivTrajectory);
|
||||
emit newAiv(aivTrajectory);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectExplosionSingleCentral::publishDetonationAiv()
|
||||
{
|
||||
const Core::GeoPosition &geoPos = m_detonationLocation;
|
||||
Trajectory poly3DDetonation;
|
||||
poly3DDetonation.first << QPointF(geoPos.lon(), geoPos.lat());
|
||||
poly3DDetonation.first << QPointF(geoPos.lon(), geoPos.lat());
|
||||
poly3DDetonation.second << geoPos.z();
|
||||
poly3DDetonation.second << geoPos.z() + chargeRadius();
|
||||
const QRectF boundsDetonation(poly3DDetonation.first.boundingRect());
|
||||
AesItemView aivDetonation(m_aivDetonation);
|
||||
aivDetonation.aesItemId(m_data.id);
|
||||
aivDetonation.chargeTypeId(m_data.chargeTypeId);
|
||||
ddsVecFromPoly(poly3DDetonation.first, poly3DDetonation.second, aivDetonation.form());
|
||||
aivDetonation.effectStart(toMSec(m_data.effectStart));
|
||||
aivDetonation.boundingBoxBottomLeft(Core::GeoPosition2D(boundsDetonation.bottomLeft().x(), boundsDetonation.bottomLeft().y()));
|
||||
aivDetonation.boundingBoxTopRight(Core::GeoPosition2D(boundsDetonation.topRight().x(), boundsDetonation.topRight().y()));
|
||||
aivDetonation.aesTypeId(AesType::AtExplosionSingleCentral);
|
||||
aivDetonation.effectStateId(effectState());
|
||||
aivDetonation.id(1000 * m_data.id + AesType::AtExplosionSingleCentral);
|
||||
if (m_data.partyId != 0)
|
||||
aivDetonation.partyId(m_data.partyId);
|
||||
|
||||
if (aivDetonation != m_aivDetonation)
|
||||
{
|
||||
aivDetonation.sampleTime(partitionTimeMSec());
|
||||
m_aivDetonation = aivDetonation;
|
||||
m_mainHandler->dds()->dts()->publish(aivDetonation);
|
||||
emit newAiv(aivDetonation);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectExplosionSingleCentral::adjustTrajectoryToDetonationLocation(const Core::GeoPosition &detonationLocation)
|
||||
{
|
||||
if (m_trajectory.back() == detonationLocation) // no adjustment necessary
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Detonation location coincides with last point of trajectory for ID: " << m_data.id;
|
||||
return;
|
||||
} // if
|
||||
|
||||
const double distToOriginSquared = LtsCoordTrans::squareDistance(
|
||||
m_trajectory.front().lon(), m_trajectory.front().lat(), detonationLocation.lon(), detonationLocation.lat()
|
||||
);
|
||||
const double distTrajectorySquared = LtsCoordTrans::squareDistance(
|
||||
m_trajectory.back().lon(), m_trajectory.back().lat(), m_trajectory.front().lon(), m_trajectory.front().lat()
|
||||
);
|
||||
|
||||
if (distToOriginSquared > distTrajectorySquared)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Detonation location is outside of trajectory for ID: " << m_data.id;
|
||||
return;
|
||||
} // if
|
||||
|
||||
for (unsigned int i = m_trajectory.size() - 1; i > 0; --i)
|
||||
{
|
||||
const double distStartSegmentSquared = LtsCoordTrans::squareDistance(
|
||||
m_trajectory[i-1].lon(), m_trajectory[i-1].lat(), m_trajectory.front().lon(), m_trajectory.front().lat()
|
||||
);
|
||||
|
||||
if (distStartSegmentSquared > distToOriginSquared)
|
||||
{
|
||||
m_trajectory.pop_back();
|
||||
continue;
|
||||
} // if
|
||||
|
||||
m_trajectory.pop_back();
|
||||
m_trajectory.push_back(detonationLocation);
|
||||
return;
|
||||
} // for
|
||||
}
|
||||
|
||||
DetonationLocationRequest ObjectExplosionSingleCentral::detonationLocationRequest(const Trajectory &trajectory) const
|
||||
{
|
||||
DetonationLocationRequest req;
|
||||
req.aesItemId(m_data.id);
|
||||
req.chargeTypeId(m_data.chargeTypeId);
|
||||
req.trajectory().reserve(trajectory.first.size());
|
||||
for (int i = 0; i < trajectory.first.size(); ++i)
|
||||
req.trajectory().push_back(Core::GeoPosition(trajectory.first[i].x(), trajectory.first[i].y(), trajectory.second[i]));
|
||||
return req;
|
||||
}
|
||||
|
||||
void ObjectExplosionSingleCentral::onDetonationLocationReply(const DetonationLocationReply &reply)
|
||||
{
|
||||
if (reply.id() != m_data.id)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "ID mismatch: " << reply.id() << " != " << m_data.id;
|
||||
return;
|
||||
} // if
|
||||
|
||||
adjustTrajectoryToDetonationLocation(reply.position());
|
||||
m_detonationLocation = reply.position();
|
||||
|
||||
publishTrajectoryAiv();
|
||||
publishDetonationAiv();
|
||||
}
|
||||
|
||||
void ObjectExplosionSingleCentral::removeTopics()
|
||||
{
|
||||
auto dts = m_mainHandler->dds()->dts();
|
||||
dts->removeExplosionSingleByKey(m_data.id);
|
||||
dts->removeAesItemViewByKey(1000 * m_data.id + AesType::AtExplosionSingleCentral);
|
||||
emit removeAiv(m_data.id);
|
||||
}
|
||||
|
||||
QPolygonF ObjectExplosionSingleCentral::generateForm()
|
||||
{
|
||||
const Trajectory trajectory = Polygons::explosionSingleCentralTrajectory(
|
||||
m_data, positionOf(m_data.participantId), m_mainHandler->explosionSingleCentralHandler().get()->elevationMap()
|
||||
);
|
||||
ddsVecFromPoly(trajectory.first, trajectory.second, m_trajectory);
|
||||
|
||||
QPolygonF poly;
|
||||
poly << QPointF(m_trajectory.front().lon(), m_trajectory.front().lat());
|
||||
poly << QPointF(m_trajectory.back().lon(), m_trajectory.back().lat());
|
||||
|
||||
return poly;
|
||||
}
|
||||
|
||||
} // Namespace AreaEffectSimulation
|
||||
Reference in new issue
Block a user