Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+305
@@ -0,0 +1,305 @@
|
||||
/**
|
||||
The PlanCreator class creates a tactical plan with the information given by a collateral damage simulation
|
||||
* @RDE_HEADER@
|
||||
* $Id: ppm_msdl_edit.h 52239 2020-10-05 11:33:12Z thoden $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/3dws_devel/Lts/Plugins/ParticipantManagement/Gui/MSDL/ppm_msdl_edit.h $
|
||||
* $Author: thoden $
|
||||
* Created by Hannes Fritsche, ESZS, 2024-08-20
|
||||
*/
|
||||
|
||||
#include "cds_plan_creator.h"
|
||||
|
||||
#include <GeometryModel/geometry_model.h>
|
||||
#include <GeometryModel/geometry_model_factory.h>
|
||||
#include <LtsUtilsCore/dds_vector.h>
|
||||
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <FileManagement/flm_ftc.h>
|
||||
|
||||
#include <QPolygonF>
|
||||
#include <QDateTime>
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
|
||||
#include <LtsWidgets/lts_message_dialog.h>
|
||||
|
||||
#include <AreaEffectSimulation/Utils/polygons.h>
|
||||
|
||||
#include "cds_calculations.h"
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
|
||||
CollateralDamageSimulation::PlanCreator::PlanCreator(QWidget *parent)
|
||||
: QObject(parent)
|
||||
{}
|
||||
|
||||
PlanCreator::~PlanCreator()
|
||||
{
|
||||
if (m_geometryModel != nullptr)
|
||||
{
|
||||
delete m_geometryModel;
|
||||
m_geometryModel = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PlanCreator::init(const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc, const std::shared_ptr<FileManagement::Interface::Ftc> &flmFtc)
|
||||
{
|
||||
if (m_geometryModel != nullptr)
|
||||
{
|
||||
delete m_geometryModel;
|
||||
m_geometryModel = nullptr;
|
||||
}
|
||||
|
||||
m_geometryModel = SituationMap::GeometryModelFactory::singleton()->create();
|
||||
|
||||
clear();
|
||||
|
||||
m_ismDtc = ismDtc;
|
||||
m_ppmDtc = ppmDtc;
|
||||
m_flmFtc = flmFtc;
|
||||
|
||||
if (!m_ppmDtc->isPartyEnabled())
|
||||
{
|
||||
m_ppmDtc->enableParty();
|
||||
m_ppmDtc->waitForHistoricalDataParty(3000);
|
||||
}
|
||||
|
||||
if (!m_ppmDtc->isParticipantPositionEnabled())
|
||||
{
|
||||
m_ppmDtc->enableParticipantPosition();
|
||||
m_ppmDtc->waitForHistoricalDataParticipantPosition(3000);
|
||||
}
|
||||
|
||||
if (!m_ppmDtc->isParticipantEnabled())
|
||||
{
|
||||
m_ppmDtc->enableParticipant();
|
||||
m_ppmDtc->waitForHistoricalDataParticipant(3000);
|
||||
}
|
||||
}
|
||||
|
||||
void PlanCreator::addBuildings(const QHash<int, QPolygonF> &buildingFootprints, const QVector<int> &directlyHitBuildings)
|
||||
{
|
||||
m_directlyHitBuildings.reserve(directlyHitBuildings.size());
|
||||
|
||||
for (auto it = buildingFootprints.constBegin(); it != buildingFootprints.constEnd(); ++it)
|
||||
addBuilding(it.value(), directlyHitBuildings.contains(it.key()));
|
||||
}
|
||||
|
||||
void PlanCreator::addProtectionAreas(const QVector<QPolygonF> &protectionAreas)
|
||||
{
|
||||
m_protectionAreas.reserve(protectionAreas.size());
|
||||
|
||||
for (const QPolygonF &protectionArea : protectionAreas)
|
||||
addProtectionArea(protectionArea);
|
||||
}
|
||||
|
||||
void PlanCreator::addParticipantsWithProtection(const QVector<int> &participantIds)
|
||||
{
|
||||
addParticipants(participantIds, ProtectionState::WithProtection);
|
||||
}
|
||||
|
||||
void PlanCreator::addParticipantsWithoutProtection(const QVector<int> &participantIds)
|
||||
{
|
||||
addParticipants(participantIds, ProtectionState::WithoutProtection);
|
||||
}
|
||||
|
||||
void PlanCreator::addParticipantsInUnderground(const QVector<int> &participantIds)
|
||||
{
|
||||
addParticipants(participantIds, ProtectionState::Underground);
|
||||
}
|
||||
|
||||
void PlanCreator::save(const QString &name, int folderId, int exerciseId)
|
||||
{
|
||||
if (!m_protectionAreas.isEmpty())
|
||||
m_geometryModel->reorderPrimitives(m_protectionAreas, SituationMap::GeometryModel::PrimitivOrder::Raise);
|
||||
|
||||
if (!m_directlyHitBuildings.isEmpty())
|
||||
m_geometryModel->reorderPrimitives(m_directlyHitBuildings, SituationMap::GeometryModel::PrimitivOrder::Raise);
|
||||
|
||||
FileManagement::FileContentModifyRequest data;
|
||||
|
||||
data.name(name.toStdString());
|
||||
data.isTemplate(false);
|
||||
data.isHidden(false);
|
||||
data.folderId(folderId);
|
||||
data.fileStatus(FileManagement::FileStatus::Valid);
|
||||
data.fileCategory(FileManagement::FileCategory::Exercise);
|
||||
data.fileType(FileManagement::FileType::TacticalPlan);
|
||||
data.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
|
||||
data.lastModified(QDateTime::currentMSecsSinceEpoch());
|
||||
data.content(LtsUtils::convert<std::vector<uint8_t>>(m_geometryModel->toByteArray()));
|
||||
data.exerciseId(exerciseId);
|
||||
|
||||
bool isModifyRequestOk = m_flmFtc->fileContentModifyRequest(data, [this](const Core::FunctionReplyObject &reply)
|
||||
{
|
||||
if (reply.error())
|
||||
warnSafeDidNotWork(tr("Could not save plan: %1").arg(QString::fromStdString(reply.str())));
|
||||
});
|
||||
|
||||
if (!isModifyRequestOk)
|
||||
warnSafeDidNotWork(tr("Could not save plan."));
|
||||
}
|
||||
|
||||
void PlanCreator::clear()
|
||||
{
|
||||
if (m_geometryModel == nullptr)
|
||||
return;
|
||||
|
||||
m_protectionAreas.clear();
|
||||
m_directlyHitBuildings.clear();
|
||||
|
||||
m_geometryModel->clearModel();
|
||||
m_partyCache.clear();
|
||||
}
|
||||
|
||||
void PlanCreator::warnSafeDidNotWork(const QString &message)
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(static_cast<QWidget*>(parent()), message, tr("Save failed"));
|
||||
}
|
||||
|
||||
void PlanCreator::addDetonationArea(const QPointF &impactPosition, double lethalRadius, double nonLethalRadius)
|
||||
{
|
||||
if (!m_geometryModel)
|
||||
return;
|
||||
|
||||
using namespace SituationMap;
|
||||
|
||||
QList<QPair<GeometryModel::Attribute, QVariant>> symbolAttributes;
|
||||
|
||||
// impact position
|
||||
symbolAttributes.reserve(4);
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::Fill, QVariant(true)));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::Close, QVariant(true)));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::FillColor, QVariant(QColor(Qt::black))));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::FillPattern, QVariant(static_cast<int>(GeometryModel::FillPattern::Solid))));
|
||||
|
||||
m_geometryModel->addPrimitive(GeometryModel::PrimitiveType::Polyline, AreaEffectSimulation::Polygons::circle(impactPosition, 1.0).toList(), symbolAttributes);
|
||||
|
||||
// lethal radius
|
||||
symbolAttributes.clear();
|
||||
|
||||
symbolAttributes.reserve(2);
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::Close, QVariant(true)));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::LineWidth, QVariant(3)));
|
||||
|
||||
m_geometryModel->addPrimitive(GeometryModel::PrimitiveType::Polyline, AreaEffectSimulation::Polygons::circle(impactPosition, lethalRadius).toList(), symbolAttributes);
|
||||
|
||||
// nonlethal radius
|
||||
if (nonLethalRadius == 0.0)
|
||||
return;
|
||||
|
||||
symbolAttributes.clear();
|
||||
|
||||
symbolAttributes.reserve(3);
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::Close, QVariant(true)));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::LineWidth, QVariant(3)));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::LineStyle, QVariant(static_cast<int>(GeometryModel::LineStyle::Dashed))));
|
||||
|
||||
m_geometryModel->addPrimitive(GeometryModel::PrimitiveType::Polyline, AreaEffectSimulation::Polygons::circle(impactPosition, nonLethalRadius).toList(), symbolAttributes);
|
||||
}
|
||||
|
||||
void PlanCreator::addBuilding(const QPolygonF &footprint, bool isDirectlyHit)
|
||||
{
|
||||
if (!m_geometryModel)
|
||||
return;
|
||||
|
||||
using namespace SituationMap;
|
||||
|
||||
QList<QPair<GeometryModel::Attribute, QVariant>> symbolAttributes;
|
||||
|
||||
symbolAttributes.reserve(4);
|
||||
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::Fill, QVariant(true)));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::Close, QVariant(true)));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::FillColor, QVariant(QColor(isDirectlyHit ? Qt::red : Qt::lightGray))));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::FillPattern, QVariant(static_cast<int>(GeometryModel::FillPattern::Solid))));
|
||||
|
||||
GeometryModel::Node node = m_geometryModel->addPrimitive(GeometryModel::PrimitiveType::Polyline, footprint.toList(), symbolAttributes);
|
||||
|
||||
if (isDirectlyHit)
|
||||
m_directlyHitBuildings.append(node);
|
||||
}
|
||||
|
||||
void PlanCreator::addParticipants(const QVector<int> &participantIds, ProtectionState protectionState)
|
||||
{
|
||||
for (int participantId: participantIds)
|
||||
addParticipant(participantId, protectionState);
|
||||
}
|
||||
|
||||
void PlanCreator::addParticipant(int participantId, ProtectionState protectionState)
|
||||
{
|
||||
if (!m_geometryModel)
|
||||
return;
|
||||
|
||||
using namespace SituationMap;
|
||||
|
||||
const ParticipantManagement::Participant &participant = m_ppmDtc->participant(participantId);
|
||||
const ParticipantManagement::ParticipantPosition &position = m_ppmDtc->participantPosition(participantId);
|
||||
|
||||
if (!m_partyCache.contains(participant.partyId()))
|
||||
m_partyCache.insert(participant.partyId(), m_ppmDtc->party(participant.partyId()));
|
||||
|
||||
QList<QPair<GeometryModel::Attribute, QVariant>> symbolAttributes;
|
||||
QPointF positionPoint(position.pos().lon(), position.pos().lat());
|
||||
const QList<QPointF> positionList = {positionPoint};
|
||||
|
||||
// participant
|
||||
symbolAttributes.reserve(2);
|
||||
|
||||
QString sidc = QString::fromStdString(participant.symbol());
|
||||
|
||||
if (sidc.size() > 16)
|
||||
sidc.replace(16, 1, QString::number(static_cast<int>(protectionState)));
|
||||
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::SIDC, QVariant(sidc)));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::ForceId, QVariant(participant.partyId())));
|
||||
|
||||
m_geometryModel->addPrimitive(GeometryModel::PrimitiveType::ParticipantSymbol, positionList, symbolAttributes);
|
||||
}
|
||||
|
||||
void PlanCreator::addProtectionArea(const QPolygonF &areaPolygon)
|
||||
{
|
||||
if (!m_geometryModel)
|
||||
return;
|
||||
|
||||
using namespace SituationMap;
|
||||
|
||||
QList<QPair<GeometryModel::Attribute, QVariant>> symbolAttributes;
|
||||
|
||||
symbolAttributes.reserve(4);
|
||||
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::Fill, QVariant(true)));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::Close, QVariant(true)));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::FillColor, QVariant(QGuiApplication::palette().color(QPalette::Link))));
|
||||
symbolAttributes.append(QPair<GeometryModel::Attribute, QVariant>(GeometryModel::Attribute::FillPattern, QVariant(static_cast<int>(GeometryModel::FillPattern::Diag2))));
|
||||
|
||||
m_protectionAreas.append(m_geometryModel->addPrimitive(GeometryModel::PrimitiveType::Polyline, areaPolygon.toList(), symbolAttributes));
|
||||
}
|
||||
|
||||
SymbologyXML::SymbolTypes::t_affil PlanCreator::partyRoleToSymbolAffiliation(const ParticipantManagement::Role &partyRole) const
|
||||
{
|
||||
switch (partyRole.underlying())
|
||||
{
|
||||
case ParticipantManagement::Role_def::Unknown:
|
||||
return SymbologyXML::SymbolTypes::UNKNOWN;
|
||||
case ParticipantManagement::Role_def::Friend:
|
||||
return SymbologyXML::SymbolTypes::FRIEND;
|
||||
case ParticipantManagement::Role_def::Neutral:
|
||||
return SymbologyXML::SymbolTypes::NEUTRAL;
|
||||
case ParticipantManagement::Role_def::Enemy:
|
||||
return SymbologyXML::SymbolTypes::ENEMY;
|
||||
case ParticipantManagement::Role_def::Pending:
|
||||
return SymbologyXML::SymbolTypes::PENDING;
|
||||
case ParticipantManagement::Role_def::AssumedFriend:
|
||||
return SymbologyXML::SymbolTypes::ASSUMED_FRIEND;
|
||||
case ParticipantManagement::Role_def::Suspect:
|
||||
return SymbologyXML::SymbolTypes::SUSPECT;
|
||||
default:
|
||||
return SymbologyXML::SymbolTypes::AFFIL_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace CollateralDamageSimulation
|
||||
Reference in new issue
Block a user