Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,56 @@
|
||||
#
|
||||
# $Id: CMakeLists.txt 46327 2019-03-28 16:06:35Z hjl $
|
||||
# $HeadURL: svn://192.168.133.21/TDS/branches/product/features/3dws_devel/Lts/Plugins/ParticipantManagement/Gui/MSDL/CMakeLists.txt $
|
||||
# $Author: hjl $
|
||||
# Created by Hannes Fritsche, ESZS, 2024-08-05
|
||||
#
|
||||
|
||||
FIND_PACKAGE(KDReports REQUIRED)
|
||||
|
||||
SET(cds_gui_SRCS
|
||||
cds_building_model.cpp
|
||||
cds_building_model.h
|
||||
cds_calculations.cpp
|
||||
cds_calculations.h
|
||||
cds_create_simulation_dialog.cpp
|
||||
cds_create_simulation_dialog.h
|
||||
cds_create_simulation_gui_plugin.cpp
|
||||
cds_create_simulation_gui_plugin.h
|
||||
cds_plan_creator.cpp
|
||||
cds_plan_creator.h
|
||||
cds_participant_model.cpp
|
||||
cds_participant_model.h
|
||||
cds_pdf_creator.cpp
|
||||
cds_pdf_creator.h
|
||||
cds_simulation_dialog.cpp
|
||||
cds_simulation_dialog.h
|
||||
)
|
||||
|
||||
NGL_WRAP_UI(cds_gui_SRCS
|
||||
cds_create_simulation_dialog.ui
|
||||
cds_simulation_dialog.ui
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(WS CdsSimulationGuiPlugin MODULE ${cds_gui_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(CdsSimulationGuiPlugin
|
||||
CdsGuiPluginInterface
|
||||
IsmDataPluginInterface
|
||||
FlmDataPluginInterface
|
||||
KDReports::KDReports
|
||||
ltsCoordWidget
|
||||
LtsCoordTrans
|
||||
LtsSession
|
||||
LtsSessionData
|
||||
LtsWidgets
|
||||
NGLLogger
|
||||
ngltools
|
||||
PdmDataPluginInterface
|
||||
PpmDataPluginInterface
|
||||
Qt5::Widgets
|
||||
situationMap
|
||||
situationMapGeometryModel
|
||||
SituationMapGuiPluginInterface
|
||||
svcAesCommon
|
||||
)
|
||||
|
||||
NGL_INSTALL_TARGET(CdsSimulationGuiPlugin)
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The BuildingModel provices building data for SimulationDialog
|
||||
* $Id: ism_asset_list_dialog_model.h 58852 2023-02-01 11:28:56Z fritsche_h $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/3dws_devel/Lts/Plugins/InfrastructureManagement/Gui/ResourceManagement/AssetList/ism_asset_list_dialog_model.h $
|
||||
* $Author: fritsche_h $
|
||||
* Created by Hannes Fritsche, ESZS, 2024-09-20
|
||||
*/
|
||||
|
||||
#include "cds_building_model.h"
|
||||
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
|
||||
BuildingModel::BuildingModel(QObject *parent)
|
||||
: LtsWidgets::LtsAbstractTableModel<QString>(
|
||||
{
|
||||
tr("Name")
|
||||
},
|
||||
parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QVariant BuildingModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole || !indexIsValid(index))
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case NAME:
|
||||
return m_vecData.at(index.row());
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool BuildingModel::initModel(const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc, const QVector<int> &buildingIds)
|
||||
{
|
||||
m_vecData.clear();
|
||||
m_vecData.reserve(buildingIds.size());
|
||||
|
||||
if (!ismDtc->isMainStructureElementEnabled())
|
||||
{
|
||||
ismDtc->enableMainStructureElement();
|
||||
ismDtc->waitForHistoricalDataMainStructureElement(3000);
|
||||
}
|
||||
|
||||
for (int currentBuildingId : buildingIds)
|
||||
m_vecData.append(QString::fromStdString(ismDtc->mainStructureElement(currentBuildingId).name()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace CollateralDamageSimulation
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The BuildingModel provices building data for SimulationDialog
|
||||
* $Id: ism_asset_list_dialog_model.h 58852 2023-02-01 11:28:56Z fritsche_h $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/3dws_devel/Lts/Plugins/InfrastructureManagement/Gui/ResourceManagement/AssetList/ism_asset_list_dialog_model.h $
|
||||
* $Author: fritsche_h $
|
||||
* Created by Hannes Fritsche, ESZS, 2024-09-20
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
|
||||
class BuildingModel final : public LtsWidgets::LtsAbstractTableModel<QString>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BuildingModel(QObject *parent = nullptr);
|
||||
|
||||
enum Columns
|
||||
{
|
||||
NAME = 0
|
||||
};
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool initModel(const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc, const QVector<int> &buildingIds);
|
||||
|
||||
}; // class BuildingModel
|
||||
|
||||
} // namespace CollateralDamageSimulation
|
||||
+557
@@ -0,0 +1,557 @@
|
||||
/**
|
||||
* Namespace for calculations, needed by CollateralDamageSimulation
|
||||
* @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-09-03
|
||||
*/
|
||||
|
||||
#include "cds_calculations.h"
|
||||
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
#include <QPolygonF>
|
||||
#include <QLineF>
|
||||
|
||||
#include <MathUtils/simple_helper.h>
|
||||
|
||||
#include <AreaEffectSimulation/Utils/polygons.h>
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
namespace Calculations
|
||||
{
|
||||
|
||||
QHash<int, QPolygonF> getBuildingFootprints(const QVector<int> &buildingIds, const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc, const QPointF &impactPosition)
|
||||
{
|
||||
QHash<int, QPolygonF> footprints;
|
||||
|
||||
if (buildingIds.isEmpty())
|
||||
return footprints;
|
||||
|
||||
footprints.reserve(buildingIds.size());
|
||||
|
||||
for (int buildingId : buildingIds)
|
||||
{
|
||||
const QPolygonF &buildingFootprint = getBuildingFootprint(buildingId, ismDtc);
|
||||
|
||||
// if the impact position is within a building footprint, the building has to be ignored
|
||||
if (buildingFootprint.containsPoint(impactPosition, Qt::OddEvenFill))
|
||||
continue;
|
||||
|
||||
footprints.insert(buildingId, buildingFootprint);
|
||||
}
|
||||
|
||||
return footprints;
|
||||
}
|
||||
|
||||
QPolygonF getBuildingFootprint(int buildingId, const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc)
|
||||
{
|
||||
if (!ismDtc->isMainFootprintEnabled())
|
||||
{
|
||||
ismDtc->enableMainFootprint();
|
||||
ismDtc->waitForHistoricalDataMainFootprint(3000);
|
||||
}
|
||||
|
||||
if (!ismDtc->isMainStructureElementEnabled())
|
||||
{
|
||||
ismDtc->enableMainStructureElement();
|
||||
ismDtc->waitForHistoricalDataMainStructureElement(3000);
|
||||
}
|
||||
|
||||
QPolygonF footprint; // = absolute positions
|
||||
QVector<QPointF> relPositions;
|
||||
const InfrastructureManagement::MainFootprint &mainFootprint = ismDtc->mainFootprint(buildingId);
|
||||
|
||||
relPositions.reserve(mainFootprint.elements().size());
|
||||
|
||||
for (const InfrastructureManagement::FootprintElement &element : mainFootprint.elements())
|
||||
{
|
||||
const Core::RelativePosition &relPos = element.relPosition();
|
||||
|
||||
relPositions.append(QPointF(relPos.offsetX(), relPos.offsetY()));
|
||||
}
|
||||
|
||||
const InfrastructureManagement::MainStructureElement &mainStructureElement = ismDtc->mainStructureElement(buildingId);
|
||||
const Core::GeoPosition &geoPosition = mainStructureElement.geoPosition();
|
||||
const double angleRad = mainStructureElement.angle() * LtsCoordTrans::deg2rad();
|
||||
const QPointF referencePointGeo(geoPosition.lon(), geoPosition.lat());
|
||||
const LtsCoordTrans::UtmCoordinate referencePointUTM = LtsCoordTrans::UtmCoordinate::fromGeographic(referencePointGeo);
|
||||
const QPointF center;
|
||||
|
||||
footprint.reserve(relPositions.size());
|
||||
|
||||
for (const auto &relPosition : qAsConst(relPositions))
|
||||
{
|
||||
const QPointF relPositionRotate = SituationMap::MathUtils::rotate(relPosition, center, angleRad);
|
||||
const QPointF geoPositionRotate = referencePointUTM.geographic(relPositionRotate);
|
||||
|
||||
footprint.append(geoPositionRotate);
|
||||
}
|
||||
|
||||
return footprint;
|
||||
}
|
||||
|
||||
QVector<QPolygonF> getProtectionAreas(const QHash<int, QPolygonF> &buildingFootprints, double radius, const QPointF &impactPosition)
|
||||
{
|
||||
if (isPointInAnyPolygon(buildingFootprints, impactPosition))
|
||||
return {AreaEffectSimulation::Polygons::circle(impactPosition, radius)};
|
||||
|
||||
QPolygonF currentProtectionArea;
|
||||
QVector<QPolygonF> protectionAreas;
|
||||
|
||||
protectionAreas.reserve(buildingFootprints.size());
|
||||
|
||||
for (const QPolygonF ¤tFootprint : buildingFootprints)
|
||||
{
|
||||
currentProtectionArea.clear();
|
||||
currentProtectionArea.reserve(currentFootprint.size() + 360);
|
||||
|
||||
// take the visible points from the center
|
||||
for (const QPointF currentPoint : currentFootprint)
|
||||
{
|
||||
if (isPointVisible(impactPosition, currentPoint, currentFootprint))
|
||||
currentProtectionArea.append(currentPoint);
|
||||
}
|
||||
|
||||
// order the points by angle
|
||||
// each of the two sorting algorithms has a weakness if a point is present which is either directly left or right
|
||||
// of the impact position, so we have to choose one
|
||||
if (currentProtectionArea.boundingRect().center().x() < impactPosition.x())
|
||||
{
|
||||
// does not sort properly if there is a point directly right to center point
|
||||
std::sort(currentProtectionArea.begin(), currentProtectionArea.end(),
|
||||
[&impactPosition](const QPointF &a, const QPointF &b)
|
||||
{
|
||||
double angleA = QLineF(impactPosition, a).angle();
|
||||
double angleB = QLineF(impactPosition, b).angle();
|
||||
|
||||
return angleA > angleB;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// does not sort properly if there is a point directly left to center point
|
||||
std::sort(currentProtectionArea.begin(), currentProtectionArea.end(), [impactPosition](const QPointF &a, const QPointF &b)
|
||||
{
|
||||
double angleA = std::atan2(a.y() - impactPosition.y(), a.x() - impactPosition.x());
|
||||
double angleB = std::atan2(b.y() - impactPosition.y(), b.x() - impactPosition.x());
|
||||
|
||||
return angleA < angleB;
|
||||
});
|
||||
}
|
||||
|
||||
addOuterBounds(currentProtectionArea, impactPosition, radius);
|
||||
|
||||
protectionAreas.append(currentProtectionArea);
|
||||
}
|
||||
|
||||
return mergePolygons(protectionAreas);
|
||||
}
|
||||
|
||||
bool isPointVisible(const QPointF ¢er, const QPointF &point, const QPolygonF &polygon)
|
||||
{
|
||||
for (int i = 0; i < polygon.size(); ++i)
|
||||
{
|
||||
const QPointF ¤tPoint = polygon.at(i);
|
||||
const QPointF &nextPoint = polygon.at((i + 1) % polygon.size());
|
||||
|
||||
if (point == currentPoint || point == nextPoint)
|
||||
continue;
|
||||
|
||||
if (doLinesIntersect(center, point, currentPoint, nextPoint))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool doLinesIntersect(const QPointF &a1, const QPointF &a2, const QPointF &b1, const QPointF &b2)
|
||||
{
|
||||
auto ccw = [](const QPointF &A, const QPointF &B, const QPointF &C)
|
||||
{
|
||||
return ((C.y() - A.y()) * (B.x() - A.x())) > ((B.y() - A.y()) * (C.x() - A.x()));
|
||||
};
|
||||
|
||||
return ccw(a1, b1, b2) != ccw(a2, b1, b2) && ccw(a1, a2, b1) != ccw(a1, a2, b2);
|
||||
}
|
||||
|
||||
void addOuterBounds(QPolygonF &polygon, const QPointF ¢er, double radius)
|
||||
{
|
||||
QPolygonF circle = AreaEffectSimulation::Polygons::circle(center, radius);
|
||||
|
||||
LtsCoordTrans::UtmCoordinate startUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(getStartPosForOuterBounds(polygon, circle));
|
||||
LtsCoordTrans::UtmCoordinate endUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(getEndPosForOuterBounds(polygon, circle));
|
||||
LtsCoordTrans::UtmCoordinate centerUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(center);
|
||||
|
||||
double startRad = std::atan2(startUtm.y - centerUtm.y, startUtm.x - centerUtm.x);
|
||||
double endRad = std::atan2(endUtm.y - centerUtm.y, endUtm.x - centerUtm.x);
|
||||
double angleStep = 5.0 * M_PI / 180.0;
|
||||
|
||||
if (startRad > endRad)
|
||||
endRad += 2 * M_PI;
|
||||
|
||||
for (double angle = startRad; angle < endRad; angle += angleStep)
|
||||
{
|
||||
double x = centerUtm.x + radius * cos(angle);
|
||||
double y = centerUtm.y + radius * sin(angle);
|
||||
|
||||
polygon.prepend(LtsCoordTrans::UtmCoordinate(centerUtm.zone, x, y).geographic());
|
||||
}
|
||||
|
||||
if (endRad > startRad && fmod(endRad - startRad, angleStep) != 0)
|
||||
{
|
||||
double x = centerUtm.x + radius * cos(endRad);
|
||||
double y = centerUtm.y + radius * sin(endRad);
|
||||
|
||||
polygon.prepend(LtsCoordTrans::UtmCoordinate(centerUtm.zone, x, y).geographic());
|
||||
}
|
||||
}
|
||||
|
||||
ParticipantProtectionInfo getParticipantProtectionInfo(const QVector<int> &participantIds, const QVector<QPolygonF> &protectionAreas, const QVector<int> &undergroundBuildingIds, const QVector<int> &directlyHitBuildingIds, const QHash<int, QPolygonF> &buildingFootprints, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc, const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc)
|
||||
{
|
||||
ParticipantProtectionInfo participantProtectionInfo;
|
||||
|
||||
QHash<int, QPolygonF> directlyHitBuildingFootprints;
|
||||
directlyHitBuildingFootprints.reserve(directlyHitBuildingIds.size());
|
||||
|
||||
for (int buildingId : directlyHitBuildingIds)
|
||||
directlyHitBuildingFootprints.insert(buildingId, buildingFootprints.value(buildingId));
|
||||
|
||||
participantProtectionInfo.withoutProtection.reserve(participantIds.size());
|
||||
participantProtectionInfo.withProtection.reserve(participantIds.size());
|
||||
participantProtectionInfo.participantsInUnderground.reserve(participantIds.size());
|
||||
|
||||
if (!ppmDtc->isParticipantPositionEnabled())
|
||||
{
|
||||
ppmDtc->enableParticipantPosition();
|
||||
ppmDtc->waitForHistoricalDataParticipantPosition(3000);
|
||||
}
|
||||
|
||||
if (!ismDtc->isMainStructureElementEnabled())
|
||||
{
|
||||
ismDtc->enableMainStructureElement();
|
||||
ismDtc->waitForHistoricalDataMainStructureElement(3000);
|
||||
}
|
||||
|
||||
for (int currentParticipantId : participantIds)
|
||||
{
|
||||
const ParticipantManagement::ParticipantPosition ¤tPosition = ppmDtc->participantPosition(currentParticipantId);
|
||||
|
||||
if (undergroundBuildingIds.contains(currentPosition.buildingId()))
|
||||
{
|
||||
participantProtectionInfo.participantsInUnderground.append(currentParticipantId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (directlyHitBuildingIds.contains(currentPosition.buildingId()))
|
||||
{
|
||||
participantProtectionInfo.withoutProtection.append(currentParticipantId);
|
||||
continue;
|
||||
}
|
||||
|
||||
const QPointF geoPosition(currentPosition.pos().lon(), currentPosition.pos().lat());
|
||||
|
||||
if (isPointInAnyPolygon(directlyHitBuildingFootprints, geoPosition))
|
||||
{
|
||||
participantProtectionInfo.withoutProtection.append(currentParticipantId);
|
||||
continue;
|
||||
}
|
||||
|
||||
// participants in buildings are always protected
|
||||
if (currentPosition.roomId() != 0)
|
||||
{
|
||||
participantProtectionInfo.withProtection.append(currentParticipantId);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if a participant is in a protection area
|
||||
|
||||
for (const QPolygonF ¤tProtectionArea : protectionAreas)
|
||||
{
|
||||
if (currentProtectionArea.containsPoint(geoPosition, Qt::OddEvenFill))
|
||||
{
|
||||
participantProtectionInfo.withProtection.append(currentParticipantId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (participantProtectionInfo.withProtection.contains(currentParticipantId))
|
||||
continue;
|
||||
|
||||
// no protection
|
||||
participantProtectionInfo.withoutProtection.append(currentParticipantId);
|
||||
}
|
||||
|
||||
participantProtectionInfo.withoutProtection.squeeze();
|
||||
participantProtectionInfo.withProtection.squeeze();
|
||||
participantProtectionInfo.participantsInUnderground.squeeze();
|
||||
|
||||
return participantProtectionInfo;
|
||||
}
|
||||
|
||||
QPointF getStartPosForOuterBounds(const QPolygonF &polygon, const QPolygonF &circle)
|
||||
{
|
||||
if (circle.containsPoint(polygon.first(), Qt::OddEvenFill))
|
||||
return polygon.first();
|
||||
|
||||
QPointF firstInnerPoint = polygon.first();
|
||||
|
||||
int index = 0;
|
||||
|
||||
while (!circle.containsPoint(firstInnerPoint, Qt::OddEvenFill))
|
||||
{
|
||||
if (index >= polygon.size() - 1)
|
||||
return QPointF();
|
||||
|
||||
firstInnerPoint = polygon.at(++index);
|
||||
}
|
||||
|
||||
QPointF lastOuterPoint = polygon.at(index - 1);
|
||||
QLineF intersectionLine(firstInnerPoint, lastOuterPoint);
|
||||
|
||||
return firstIntersection(intersectionLine, circle);
|
||||
}
|
||||
|
||||
QPointF getEndPosForOuterBounds(const QPolygonF &polygon, const QPolygonF &circle)
|
||||
{
|
||||
if (circle.containsPoint(polygon.last(), Qt::OddEvenFill))
|
||||
return polygon.last();
|
||||
|
||||
QPointF firstInnerPoint = polygon.last();
|
||||
|
||||
int index = polygon.size();
|
||||
|
||||
while (!circle.containsPoint(firstInnerPoint, Qt::OddEvenFill))
|
||||
{
|
||||
if (index <= 0)
|
||||
return QPointF();
|
||||
|
||||
firstInnerPoint = polygon.at(--index);
|
||||
}
|
||||
|
||||
QPointF lastOuterPoint = polygon.at(index + 1);
|
||||
QLineF intersectionLine(firstInnerPoint, lastOuterPoint);
|
||||
|
||||
return firstIntersection(intersectionLine, circle);
|
||||
}
|
||||
|
||||
QPointF firstIntersection(const QLineF &line, const QPolygonF &circle)
|
||||
{
|
||||
QPointF prevPoint = circle.last();
|
||||
QPointF intersectionPoint;
|
||||
|
||||
for (int index = 0; index < circle.size(); ++index)
|
||||
{
|
||||
const QLineF edge(prevPoint, circle.at(index));
|
||||
|
||||
if (edge.intersects(line, &intersectionPoint) == QLineF::BoundedIntersection)
|
||||
return intersectionPoint;
|
||||
|
||||
prevPoint = circle.at(index);
|
||||
}
|
||||
|
||||
return QPointF();
|
||||
}
|
||||
|
||||
bool isPointInAnyPolygon(const QHash<int, QPolygonF> &polygons, const QPointF &point)
|
||||
{
|
||||
for (auto it = polygons.constBegin(); it != polygons.constEnd(); ++it)
|
||||
{
|
||||
const QPolygonF ¤tPolygon = it.value();
|
||||
|
||||
if (currentPolygon.containsPoint(point, Qt::OddEvenFill))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QVector<QPolygonF> mergePolygons(const QVector<QPolygonF> &geoPolygons)
|
||||
{
|
||||
if (geoPolygons.size() <= 1)
|
||||
return geoPolygons;
|
||||
|
||||
const double scaleFactor = 100000.0;
|
||||
// since geocoordinates are very small the result of QPolygonF::united is very imprecise.
|
||||
// the polygons therefore must be scaled up and later be scaled down again
|
||||
QVector<QPolygonF> mergedPolygons = getScaledPolygons(geoPolygons,scaleFactor);
|
||||
bool hasIntersection = true;
|
||||
|
||||
while (hasIntersection)
|
||||
{
|
||||
hasIntersection = false;
|
||||
|
||||
for (int outerIndex = 0; outerIndex < mergedPolygons.size(); ++outerIndex)
|
||||
{
|
||||
for (int innerIndex = outerIndex + 1; innerIndex < mergedPolygons.size(); ++innerIndex)
|
||||
{
|
||||
if (mergedPolygons.at(outerIndex).intersects(mergedPolygons.at(innerIndex)))
|
||||
{
|
||||
const QPolygonF mergedPolygon = mergedPolygons.at(outerIndex).united(mergedPolygons.at(innerIndex));
|
||||
|
||||
mergedPolygons[outerIndex] = mergedPolygon;
|
||||
mergedPolygons.removeAt(innerIndex);
|
||||
|
||||
hasIntersection = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hasIntersection)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return getScaledPolygons(mergedPolygons, 1.0 / scaleFactor);
|
||||
}
|
||||
|
||||
QVector<QPolygonF> getScaledPolygons(const QVector<QPolygonF> &polygons, double factor)
|
||||
{
|
||||
QVector<QPolygonF> scaledPolygons;
|
||||
QPolygonF scaledPolygon;
|
||||
|
||||
scaledPolygons.reserve(polygons.size());
|
||||
|
||||
for (const QPolygonF ¤tPolygon : polygons)
|
||||
{
|
||||
scaledPolygon.reserve(currentPolygon.size());
|
||||
|
||||
for (const QPointF ¤tPoint : currentPolygon)
|
||||
scaledPolygon.append(currentPoint * factor);
|
||||
|
||||
scaledPolygons.append(scaledPolygon);
|
||||
|
||||
scaledPolygon.clear();
|
||||
}
|
||||
|
||||
return scaledPolygons;
|
||||
}
|
||||
|
||||
QVector<int> getUndergroundBuildingIds(const QVector<int> &buildingIds, const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc)
|
||||
{
|
||||
if (!ismDtc->isMainStructureElementEnabled())
|
||||
{
|
||||
ismDtc->enableMainStructureElement();
|
||||
ismDtc->waitForHistoricalDataMainStructureElement(3000);
|
||||
}
|
||||
|
||||
QVector<int> undergroundBuildingIds;
|
||||
undergroundBuildingIds.reserve(buildingIds.size());
|
||||
|
||||
// since there is no indicator for underground buildings, we have to parse the buildings name and description
|
||||
// --> known underground buildings area Kanalisation and U-Bahn Tunnel
|
||||
const QString kanal = QStringLiteral("kanaele");
|
||||
const QString uBahn = QStringLiteral("bahn");
|
||||
|
||||
for (int currentBuildingId : buildingIds)
|
||||
{
|
||||
const InfrastructureManagement::MainStructureElement &building = ismDtc->mainStructureElement(currentBuildingId);
|
||||
const QString description = QString::fromStdString(building.description());
|
||||
const QString name = QString::fromStdString(building.name());
|
||||
|
||||
if (!(description.contains(kanal, Qt::CaseInsensitive) ||
|
||||
description.contains(uBahn, Qt::CaseInsensitive) ||
|
||||
name.contains(kanal, Qt::CaseInsensitive) ||
|
||||
name.contains(uBahn, Qt::CaseInsensitive)))
|
||||
continue;
|
||||
|
||||
undergroundBuildingIds.append(currentBuildingId);
|
||||
}
|
||||
|
||||
return undergroundBuildingIds;
|
||||
}
|
||||
|
||||
QList<QPointF> getGeoRect(const QPointF ¢er, double edgeLength)
|
||||
{
|
||||
QList<QPointF> geoRect;
|
||||
const LtsCoordTrans::UtmCoordinate utmCenter = LtsCoordTrans::UtmCoordinate::fromGeographic(center.x(), center.y());
|
||||
const QPointF topLeft(utmCenter.geographic(-(edgeLength / 2.0), edgeLength / 2.0));
|
||||
const QPointF topRight(utmCenter.geographic(edgeLength / 2.0, edgeLength / 2.0));
|
||||
const QPointF bottomRight(utmCenter.geographic(edgeLength / 2.0, -(edgeLength / 2.0)));
|
||||
const QPointF bottomLeft(utmCenter.geographic(-(edgeLength / 2.0), -(edgeLength / 2.0)));
|
||||
|
||||
geoRect.reserve(4);
|
||||
geoRect.append(topLeft);
|
||||
geoRect.append(topRight);
|
||||
geoRect.append(bottomRight);
|
||||
geoRect.append(bottomLeft);
|
||||
|
||||
return geoRect;
|
||||
}
|
||||
|
||||
QVector<int> getDirectlyHitBuildings(const QHash<int, QPolygonF> &footprints, const QPointF &impactPosition)
|
||||
{
|
||||
const double angleStep = 0.2;
|
||||
const int minimumHitCount = 12;
|
||||
QVector<int> directlyHitBuildingIds;
|
||||
|
||||
QHash<int, int> hitBuildingsCount; // <buildingId, hit count>
|
||||
|
||||
directlyHitBuildingIds.reserve(footprints.size());
|
||||
|
||||
QLineF ray(impactPosition, {impactPosition.x() + 1.0, impactPosition.y()});
|
||||
|
||||
for (double currentAngle = 0.0; currentAngle < 360; currentAngle += angleStep)
|
||||
{
|
||||
ray.setAngle(currentAngle);
|
||||
|
||||
int buildingId = getNearestBlockedBuildingId(ray, footprints);
|
||||
|
||||
if (buildingId == -1)
|
||||
continue;
|
||||
|
||||
if (!hitBuildingsCount.contains(buildingId))
|
||||
hitBuildingsCount.insert(buildingId, 0);
|
||||
|
||||
++hitBuildingsCount[buildingId];
|
||||
}
|
||||
|
||||
for (auto it = hitBuildingsCount.constBegin(); it != hitBuildingsCount.constEnd(); ++it)
|
||||
{
|
||||
if (it.value() >= minimumHitCount)
|
||||
directlyHitBuildingIds.append(it.key());
|
||||
}
|
||||
|
||||
directlyHitBuildingIds.squeeze();
|
||||
|
||||
return directlyHitBuildingIds;
|
||||
}
|
||||
|
||||
int getNearestBlockedBuildingId(const QLineF &ray, const QHash<int, QPolygonF> &buildings)
|
||||
{
|
||||
QMap<double, int> distances; // <distance, buildingId>
|
||||
|
||||
for (auto it = buildings.constBegin(); it != buildings.constEnd(); ++it)
|
||||
{
|
||||
const QPolygonF ¤tPolygon = it.value();
|
||||
|
||||
for (int i = 0; i < currentPolygon.count(); ++i)
|
||||
{
|
||||
const QPointF p1 = currentPolygon.at(i);
|
||||
const QPointF p2 = currentPolygon.at((i + 1) % currentPolygon.count());
|
||||
const QLineF currentEdge(p1, p2);
|
||||
|
||||
QPointF intersectionPoint;
|
||||
|
||||
if (ray.intersects(currentEdge, &intersectionPoint) != QLineF::BoundedIntersection)
|
||||
continue;
|
||||
|
||||
QLineF distanceLine(ray.p1(), intersectionPoint);
|
||||
|
||||
distances.insert(distanceLine.length(), it.key());
|
||||
}
|
||||
}
|
||||
|
||||
if (distances.isEmpty())
|
||||
return -1;
|
||||
|
||||
return distances.first();
|
||||
}
|
||||
|
||||
} // namespace Calculations
|
||||
} // namespace CollateralDamageSimulation
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Namespace for calculations, needed by CollateralDamageSimulation
|
||||
* @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-09-03
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QVector>
|
||||
#include <QRectF>
|
||||
#include <memory>
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
class MainStructureElement;
|
||||
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ParticipantManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
class QLineF;
|
||||
class QPointF;
|
||||
class QPolygonF;
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
namespace Calculations
|
||||
{
|
||||
struct ParticipantProtectionInfo
|
||||
{
|
||||
QVector<int> withProtection;
|
||||
QVector<int> withoutProtection;
|
||||
QVector<int> participantsInUnderground;
|
||||
};
|
||||
|
||||
QHash<int, QPolygonF> getBuildingFootprints(const QVector<int> &buildingIds, const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc, const QPointF &impactPosition);
|
||||
QVector<int> getDirectlyHitBuildings(const QHash<int, QPolygonF> &footprints, const QPointF &impactPosition);
|
||||
int getNearestBlockedBuildingId(const QLineF &ray, const QHash<int, QPolygonF> &buildings);
|
||||
QPolygonF getBuildingFootprint(int buildingId, const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc);
|
||||
QVector<QPolygonF> getProtectionAreas(const QHash<int, QPolygonF> &buildingFootprints, double radius, const QPointF &impactPosition);
|
||||
bool isPointVisible(const QPointF ¢er, const QPointF &point, const QPolygonF &polygon);
|
||||
bool doLinesIntersect(const QPointF &a1, const QPointF &a2, const QPointF &b1, const QPointF &b2);
|
||||
void addOuterBounds(QPolygonF &polygon, const QPointF ¢er, double radius);
|
||||
QPointF getStartPosForOuterBounds(const QPolygonF &polygon, const QPolygonF &circle);
|
||||
QPointF getEndPosForOuterBounds(const QPolygonF &polygon, const QPolygonF &circle);
|
||||
QPointF firstIntersection(const QLineF &line, const QPolygonF &circle);
|
||||
ParticipantProtectionInfo getParticipantProtectionInfo(const QVector<int> &participantIds,
|
||||
const QVector<QPolygonF> &protectionAreas,
|
||||
const QVector<int> &undergroundBuildingIds,
|
||||
const QVector<int> &directlyHitBuildingIds,
|
||||
const QHash<int, QPolygonF> &buildingFootprints,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc);
|
||||
bool isPointInAnyPolygon(const QHash<int, QPolygonF> &polygons, const QPointF &point);
|
||||
QVector<QPolygonF> mergePolygons(const QVector<QPolygonF> &geoPolygons);
|
||||
QVector<QPolygonF> getScaledPolygons(const QVector<QPolygonF> &polygons, double factor);
|
||||
QVector<int> getUndergroundBuildingIds(const QVector<int> &buildingIds, const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc);
|
||||
QList<QPointF> getGeoRect(const QPointF ¢er, double edgeLength);
|
||||
|
||||
} // namespace Calculations
|
||||
} // namespace CollateralDamageSimulation
|
||||
Executable
+451
@@ -0,0 +1,451 @@
|
||||
/**
|
||||
* @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-05
|
||||
*/
|
||||
|
||||
#include "cds_create_simulation_dialog.h"
|
||||
#include "ui_cds_create_simulation_dialog.h"
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
#include <Plugins/ProjectDataManagement/pdm_gui_plugin_interface.h>
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <PluginInterfaces/data_plugin_interface.h>
|
||||
|
||||
#include <FileManagement/Data/flm_data_plugin.h>
|
||||
#include <InfrastructureManagement/Data/ism_data_plugin.h>
|
||||
#include <ParticipantManagement/Data/ppm_data_plugin.h>
|
||||
#include <ProjectDataManagement/Data/pdm_data_plugin.h>
|
||||
#include <ProjectDataManagement/pdm_translation.h>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonValue>
|
||||
|
||||
#include <AreaEffectSimulation/Utils/polygons.h>
|
||||
|
||||
#include "cds_simulation_dialog.h"
|
||||
#include "cds_plan_creator.h"
|
||||
#include "cds_pdf_creator.h"
|
||||
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include "cds_calculations.h"
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
|
||||
CreateSimulationDialog::CreateSimulationDialog(QWidget *parent)
|
||||
: LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_ui(new Ui::CreateSimulationDialog)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->hide();
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setText(tr("Create"));
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("CDS_Create_Simulation_Dialog"));
|
||||
}
|
||||
|
||||
CreateSimulationDialog::~CreateSimulationDialog()
|
||||
{
|
||||
if (m_simulationDialog)
|
||||
{
|
||||
m_simulationDialog->closeRequest();
|
||||
}
|
||||
}
|
||||
|
||||
bool CreateSimulationDialog::init(LtsSession::LtsSession *session )
|
||||
{
|
||||
if (session == nullptr)
|
||||
return false;
|
||||
|
||||
m_session = session;
|
||||
|
||||
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(m_ismDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << " failed to get ismDtc";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getDtc<FileManagement::DataInterface>(m_flmDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << " failed to get flmDtc";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << " failed to get ppmDtc";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getDtc<ProjectDataManagement::DataInterface>(m_pdmDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << " failed to get pdmDtc";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc))
|
||||
return false;
|
||||
|
||||
if (!m_session->getForeignGuiInterface<ProjectDataManagement::ForeignGuiInterface>(m_pdmCbx))
|
||||
return false;
|
||||
|
||||
if (!m_planCreator)
|
||||
m_planCreator = new PlanCreator(this);
|
||||
|
||||
std::shared_ptr<FileManagement::Interface::Ftc> flmFtc;
|
||||
if (!m_session->getFtc<FileManagement::DataInterface>(flmFtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << " failed to get flmFtc";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_planCreator->init(m_ismDtc, m_ppmDtc, flmFtc);
|
||||
|
||||
if (!m_pdfCreator)
|
||||
m_pdfCreator = new PdfCreator(this);
|
||||
|
||||
m_pdfCreator->init(m_ismDtc, m_ppmDtc, flmFtc);
|
||||
|
||||
m_session = session;
|
||||
|
||||
fillCharges();
|
||||
|
||||
connect(m_ui->pbPosition, &QPushButton::clicked,
|
||||
this, &CreateSimulationDialog::onPositionClicked, Qt::UniqueConnection);
|
||||
connect(m_ui->pbClear, &QPushButton::clicked,
|
||||
m_ui->positionEdit, &LtsCoordWidget::LtsCoordWidget::clear, Qt::UniqueConnection);
|
||||
connect(m_ui->cbChargeTypes, qOverload<int>(&LtsWidgets::LtsComboBox::currentIndexChanged),
|
||||
this, &CreateSimulationDialog::onChargeTypeChanged, Qt::UniqueConnection);
|
||||
connect(m_ui->cbIgniterType, qOverload<int>(&LtsWidgets::LtsComboBox::currentIndexChanged),
|
||||
this, &CreateSimulationDialog::onIgniterTypeChanged, Qt::UniqueConnection);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CreateSimulationDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Create Simulation"));
|
||||
|
||||
m_uiRequirements->clear();
|
||||
m_uiRequirements->addRequirement( { m_ui->lblName, [this]() { return isNameValid(m_ui->leName->text()); } } );
|
||||
m_uiRequirements->addRequirement( { m_ui->lblPosition, [this]() { return !m_ui->positionEdit->coordinate().isNull(); } } );
|
||||
}
|
||||
|
||||
void CreateSimulationDialog::onChargeTypeChanged(int index)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
// update comboBox IgniterType:
|
||||
m_pdmCbx->fillIgniterComboBox(m_ui->cbIgniterType, m_ui->cbChargeTypes->currentData().toInt());
|
||||
drawDetonationArea();
|
||||
}
|
||||
|
||||
void CreateSimulationDialog::onIgniterTypeChanged(int index)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
drawDetonationArea();
|
||||
}
|
||||
|
||||
void CreateSimulationDialog::onPositionClicked()
|
||||
{
|
||||
if (!has2DMap())
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("no"));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_sitMapGuiIfc->getCoordinate(this,
|
||||
SLOT(onCoordinate(const QPointF &)),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void CreateSimulationDialog::onCoordinate(const QPointF &coordinate)
|
||||
{
|
||||
m_ui->positionEdit->setCoordinate(coordinate);
|
||||
drawDetonationArea();
|
||||
}
|
||||
|
||||
bool CreateSimulationDialog::apply()
|
||||
{
|
||||
const int folderId = getFolderId();
|
||||
const QPointF impactPosition = m_ui->positionEdit->coordinate();
|
||||
const QPolygonF detonationCircle = AreaEffectSimulation::Polygons::circle(impactPosition, getCurrentImpactRadius());
|
||||
const QVector<int> participantIdsInRange = m_ppmDtc->getParticipantsByPolygon(detonationCircle, false, false);
|
||||
QVector<int> buildingIdsInRange = m_ismDtc->getBuildingByPolygon(m_session->exerciseId(), detonationCircle, false, true);
|
||||
const QVector<int> undergroundBuildingIds = Calculations::getUndergroundBuildingIds(buildingIdsInRange, m_ismDtc);
|
||||
|
||||
// remove the underground buildings
|
||||
for (int undergroundBuildingId : undergroundBuildingIds)
|
||||
buildingIdsInRange.removeAll(undergroundBuildingId);
|
||||
buildingIdsInRange.squeeze();
|
||||
|
||||
const double lethalRadius = getLethalRadius();
|
||||
const double nonLethalRadius = getNonLethalRadius();
|
||||
const QHash<int, QPolygonF> buildingFootprints = Calculations::getBuildingFootprints(buildingIdsInRange, m_ismDtc, impactPosition);
|
||||
const QVector<int> directlyHitBuildingIds = Calculations::getDirectlyHitBuildings(buildingFootprints, impactPosition);
|
||||
const QVector<QPolygonF> protectionAreas = Calculations::getProtectionAreas(buildingFootprints,
|
||||
nonLethalRadius > lethalRadius ? nonLethalRadius : lethalRadius,
|
||||
impactPosition);
|
||||
Calculations::ParticipantProtectionInfo participantProtectionInfo = Calculations::getParticipantProtectionInfo(participantIdsInRange, protectionAreas, undergroundBuildingIds, directlyHitBuildingIds, buildingFootprints, m_ppmDtc, m_ismDtc);
|
||||
|
||||
if (!m_simulationDialog)
|
||||
{
|
||||
m_simulationDialog = new SimulationDialog(this);
|
||||
m_simulationDialog->init(directlyHitBuildingIds,
|
||||
participantProtectionInfo.withoutProtection,
|
||||
participantProtectionInfo.withProtection + participantProtectionInfo.participantsInUnderground,
|
||||
m_ismDtc,
|
||||
m_ppmDtc);
|
||||
addDialog(m_simulationDialog, menuGroup(), QLatin1String("Collateral Damage Simulation"), LtsWidgets::LayoutArea::eDialogTab);
|
||||
|
||||
connect(m_simulationDialog, &SimulationDialog::destroyed,
|
||||
this, [this]() {m_simulationDialog = nullptr; });
|
||||
}
|
||||
else
|
||||
{
|
||||
m_simulationDialog->init(directlyHitBuildingIds,
|
||||
participantProtectionInfo.withoutProtection,
|
||||
participantProtectionInfo.withProtection + participantProtectionInfo.participantsInUnderground,
|
||||
m_ismDtc,
|
||||
m_ppmDtc);
|
||||
focusDialog(menuGroup(), QLatin1String("Collateral Damage Simulation"), LtsWidgets::LayoutArea::eDialogTab);
|
||||
}
|
||||
|
||||
if (!m_planCreator)
|
||||
WARNING_LOG(m_logger) << "Plan Creator not present --> not possible to create a tactical plan.";
|
||||
else
|
||||
{
|
||||
m_planCreator->clear();
|
||||
m_planCreator->addProtectionAreas(protectionAreas);
|
||||
m_planCreator->addBuildings(buildingFootprints, directlyHitBuildingIds);
|
||||
m_planCreator->addDetonationArea(impactPosition, lethalRadius, nonLethalRadius);
|
||||
m_planCreator->addParticipantsWithoutProtection(participantProtectionInfo.withoutProtection);
|
||||
m_planCreator->addParticipantsWithProtection(participantProtectionInfo.withProtection);
|
||||
m_planCreator->addParticipantsInUnderground(participantProtectionInfo.participantsInUnderground);
|
||||
m_planCreator->save(m_ui->leName->text(), folderId, m_session->exerciseId());
|
||||
}
|
||||
|
||||
if (!m_pdfCreator)
|
||||
WARNING_LOG(m_logger) << "PDF Creator not present --> not possible to create PDF file.";
|
||||
else
|
||||
{
|
||||
QString positionText = LtsCoordTrans::mgrsFromGeographic(impactPosition.x(), impactPosition.y());
|
||||
|
||||
m_pdfCreator->clear();
|
||||
m_pdfCreator->addInformation(m_ui->leName->text(), m_ui->cbChargeTypes->currentText(), m_ui->cbIgniterType->currentText(), positionText);
|
||||
m_pdfCreator->addParticipantsWithoutProtection(participantProtectionInfo.withoutProtection);
|
||||
m_pdfCreator->addParticipantsWithProtection(participantProtectionInfo.withProtection);
|
||||
m_pdfCreator->addBuildings(directlyHitBuildingIds);
|
||||
m_pdfCreator->save(m_ui->leName->text(), folderId, m_session->exerciseId());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CreateSimulationDialog::has2DMap()
|
||||
{
|
||||
if (!m_sitMapGuiIfc || !m_session)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Not possible to draw on map without sitMapGuiIfc or session.";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_sitMapGuiIfc->mapMode() != SituationMap::MapMode::MapMode_2D)
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Only available in 2D mode"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CreateSimulationDialog::drawDetonationArea()
|
||||
{
|
||||
if (!has2DMap())
|
||||
return;
|
||||
|
||||
const QPointF centerCoordinate = m_ui->positionEdit->coordinate();
|
||||
|
||||
if (centerCoordinate == QPointF())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Not possible to draw detonation area. No position given.";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QVector<SituationMap::ForeignGuiInterface::PreviewCircleData> previewCircleDataVec;
|
||||
SituationMap::ForeignGuiInterface::PreviewCircleData circleData;
|
||||
|
||||
previewCircleDataVec.reserve(3);
|
||||
circleData.centerGeo = centerCoordinate;
|
||||
|
||||
// detonation point
|
||||
circleData.radius = 1.0;
|
||||
circleData.fillColor = Qt::black;
|
||||
circleData.lineWidth = 1;
|
||||
previewCircleDataVec.append(circleData);
|
||||
|
||||
// lethal radius
|
||||
circleData.radius = getLethalRadius();
|
||||
circleData.fillPattern = SituationMap::MapFillPattern::Null;
|
||||
circleData.lineWidth = 3;
|
||||
previewCircleDataVec.append(circleData);
|
||||
|
||||
// nonlethal radius
|
||||
const double nonLethalRadius = getNonLethalRadius();
|
||||
|
||||
if (nonLethalRadius > 0.0)
|
||||
{
|
||||
circleData.radius = nonLethalRadius;
|
||||
circleData.linePattern = SituationMap::MapLinePattern::Dash;
|
||||
previewCircleDataVec.append(circleData);
|
||||
}
|
||||
else
|
||||
previewCircleDataVec.squeeze();
|
||||
|
||||
m_sitMapGuiIfc->displayPreviewObjects(this, previewCircleDataVec);
|
||||
}
|
||||
|
||||
void CreateSimulationDialog::fillCharges()
|
||||
{
|
||||
m_ui->cbChargeTypes->clear();
|
||||
|
||||
if (!m_pdmDtc)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "no m_pdmDtc";
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace ProjectDataManagement;
|
||||
|
||||
const QVector<GearClass_def::type> gearClasses = { GearClass_def::AirSupport,
|
||||
GearClass_def::Artillery,
|
||||
GearClass_def::Mortar };
|
||||
|
||||
for (GearClass_def::type currentGearClass : gearClasses)
|
||||
{
|
||||
const QVector<ChargeType> &chargeTypes = m_pdmDtc->chargesForGearClass(currentGearClass);
|
||||
|
||||
for (const ChargeType ¤tChargeType : chargeTypes)
|
||||
{
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(QByteArray::fromRawData(currentChargeType.properties().c_str(), currentChargeType.properties().size())));
|
||||
const QJsonObject obj(doc.object());
|
||||
if (!obj.contains(QLatin1String("nasatId")))
|
||||
continue;
|
||||
m_ui->cbChargeTypes->addItem(QString::fromStdString(currentChargeType.name()), currentChargeType.id());
|
||||
}
|
||||
}
|
||||
|
||||
// update comboBox IgniterType:
|
||||
m_pdmCbx->fillIgniterComboBox(m_ui->cbIgniterType, m_ui->cbChargeTypes->currentData().toInt());
|
||||
}
|
||||
|
||||
double CreateSimulationDialog::getCurrentImpactRadius() const
|
||||
{
|
||||
const int chargeTypeId = m_ui->cbChargeTypes->currentData().toInt();
|
||||
const int igniterTypeId = m_ui->cbIgniterType->currentData().toInt();
|
||||
double impactRadius = m_pdmDtc->getChargeTypeIgniterTypeIgniterFunction(chargeTypeId, igniterTypeId, 0).impactRadius();
|
||||
|
||||
DEBUG_LOG(m_logger) << "got impact radius " << impactRadius << " for current charge type " << chargeTypeId << " and igniterTypeId " << igniterTypeId;
|
||||
|
||||
return impactRadius;
|
||||
}
|
||||
|
||||
double CreateSimulationDialog::getLethalRadius() const
|
||||
{
|
||||
const int currentChargeTypeId = m_ui->cbChargeTypes->currentData().toInt();
|
||||
const ProjectDataManagement::ChargeType ¤tChargeType = m_pdmDtc->chargeType(currentChargeTypeId);
|
||||
const QJsonObject properties = QJsonDocument::fromJson(QByteArray::fromStdString(currentChargeType.properties())).object();
|
||||
const QString keyImpactRadius = QStringLiteral("impactRadius");
|
||||
const QString keyCasEffects = QStringLiteral("casEffects");
|
||||
double lethalRadius = DBL_MAX;
|
||||
|
||||
if (properties.contains(keyCasEffects))
|
||||
{
|
||||
const QJsonArray casEffects = properties.value(keyCasEffects).toArray();
|
||||
|
||||
for (const QJsonValue ¤tCasEffect : casEffects)
|
||||
{
|
||||
QJsonObject currentCasEffectObj = currentCasEffect.toObject();
|
||||
double tmpRadius = currentCasEffectObj.value(keyImpactRadius).toDouble();
|
||||
|
||||
if (tmpRadius < lethalRadius)
|
||||
lethalRadius = tmpRadius;
|
||||
}
|
||||
}
|
||||
else
|
||||
lethalRadius = properties.value(keyImpactRadius).toDouble();
|
||||
|
||||
return lethalRadius;
|
||||
}
|
||||
|
||||
double CreateSimulationDialog::getNonLethalRadius() const
|
||||
{
|
||||
const int currentChargeTypeId = m_ui->cbChargeTypes->currentData().toInt();
|
||||
const ProjectDataManagement::ChargeType ¤tChargeType = m_pdmDtc->chargeType(currentChargeTypeId);
|
||||
const QJsonObject properties = QJsonDocument::fromJson(QByteArray::fromStdString(currentChargeType.properties())).object();
|
||||
const QString keyImpactRadius = QStringLiteral("impactRadius");
|
||||
const QString keyCasEffects = QStringLiteral("casEffects");
|
||||
double nonLethalRadius = 0.0;
|
||||
|
||||
if (!properties.contains(keyCasEffects))
|
||||
return 0.0;
|
||||
|
||||
const QJsonArray casEffects = properties.value(keyCasEffects).toArray();
|
||||
|
||||
if (casEffects.size() < 2)
|
||||
return 0.0;
|
||||
|
||||
for (const QJsonValue ¤tCasEffect : casEffects)
|
||||
{
|
||||
QJsonObject currentCasEffectObj = currentCasEffect.toObject();
|
||||
double tmpRadius = currentCasEffectObj.value(keyImpactRadius).toDouble();
|
||||
|
||||
if (tmpRadius > nonLethalRadius)
|
||||
nonLethalRadius = tmpRadius;
|
||||
}
|
||||
|
||||
return nonLethalRadius;
|
||||
}
|
||||
|
||||
int CreateSimulationDialog::getFolderId() const
|
||||
{
|
||||
int exeFolderId = m_flmDtc->getExerciseFolderId(m_session->exerciseId());
|
||||
return m_flmDtc->findFolder(exeFolderId, QStringLiteral("BDA"));
|
||||
}
|
||||
|
||||
bool CreateSimulationDialog::isNameValid(const QString &name) const
|
||||
{
|
||||
if (name.isEmpty())
|
||||
return false;
|
||||
|
||||
QStringList fileNames;
|
||||
const int folderId = getFolderId();
|
||||
|
||||
m_flmDtc->getAllFiles(FileManagement::FileType::Pdf, folderId, fileNames);
|
||||
if (fileNames.contains(name))
|
||||
return false;
|
||||
|
||||
fileNames.clear();
|
||||
m_flmDtc->getAllFiles(FileManagement::FileType::TacticalPlan, folderId, fileNames);
|
||||
if (fileNames.contains(name))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} //namespace CollateralDamageSimulation
|
||||
Executable
+122
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* @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-05
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
namespace FileManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
class Ftc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
class FootprintElement;
|
||||
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
|
||||
namespace ParticipantManagement
|
||||
{
|
||||
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ProjectDataManagement
|
||||
{
|
||||
class ForeignGuiInterface;
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
class ForeignGuiInterface;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CreateSimulationDialog;
|
||||
}
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
class PdfCreator;
|
||||
class PlanCreator;
|
||||
class SimulationDialog;
|
||||
|
||||
class CreateSimulationDialog : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CreateSimulationDialog(QWidget *parent = nullptr);
|
||||
|
||||
~CreateSimulationDialog();
|
||||
|
||||
bool init(LtsSession::LtsSession *session);
|
||||
|
||||
void retranslate() override final;
|
||||
|
||||
private slots:
|
||||
void onChargeTypeChanged(int index);
|
||||
void onIgniterTypeChanged(int index);
|
||||
void onPositionClicked();
|
||||
void onCoordinate(const QPointF &coordinate);
|
||||
|
||||
private: // methods
|
||||
bool apply() override;
|
||||
bool has2DMap();
|
||||
void drawDetonationArea();
|
||||
void fillCharges();
|
||||
double getCurrentImpactRadius() const;
|
||||
double getLethalRadius() const;
|
||||
double getNonLethalRadius() const;
|
||||
int getFolderId() const;
|
||||
bool isNameValid(const QString &name) const;
|
||||
|
||||
private: // attributes
|
||||
Ui::CreateSimulationDialog *m_ui;
|
||||
|
||||
LtsSession::LtsSession *m_session { nullptr };
|
||||
|
||||
SimulationDialog *m_simulationDialog { nullptr };
|
||||
|
||||
PlanCreator *m_planCreator { nullptr };
|
||||
PdfCreator *m_pdfCreator { nullptr };
|
||||
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
|
||||
std::shared_ptr<ProjectDataManagement::Interface::Dtc> m_pdmDtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
|
||||
std::shared_ptr<ProjectDataManagement::ForeignGuiInterface> m_pdmCbx;
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace CollateralDamageSimulation
|
||||
Executable
+122
@@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CreateSimulationDialog</class>
|
||||
<widget class="QWidget" name="CreateSimulationDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>482</width>
|
||||
<height>238</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">setwindowtitle in source</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lblPosition">
|
||||
<property name="text">
|
||||
<string>Position:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="2">
|
||||
<widget class="QLineEdit" name="leName"/>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Charge Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="lblIgniterType">
|
||||
<property name="text">
|
||||
<string>Igniter Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="LtsCoordWidget::LtsCoordWidget" name="positionEdit" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbClear">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/style/remove.svg</normaloff>:/style/remove.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbPosition">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/style/position.svg</normaloff>:/style/position.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lblName">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="LtsWidgets::LtsComboBox" name="cbChargeTypes"/>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="LtsWidgets::LtsComboBox" name="cbIgniterType"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsCoordWidget::LtsCoordWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsCoordTrans/lts_coord_widget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LtsWidgets::LtsComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>LtsWidgets/lts_combo_box.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Executable
+114
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for Collateral Damage Simulation
|
||||
* $Id: bat_gui_plugin.h 47123 2019-06-07 09:30:13Z ehrlicher $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/3dws_devel/Lts/Plugins/Battery/Gui/bat_gui_plugin.h $
|
||||
* $Author: ehrlicher $
|
||||
* Created by Hannes Fritsche, ESZS, 2024-08-05
|
||||
*/
|
||||
|
||||
#include "cds_create_simulation_gui_plugin.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
#include "cds_create_simulation_dialog.h"
|
||||
|
||||
#include <FileManagement/flm_data_plugin_interface.h>
|
||||
#include <InfrastructureManagement/Data/ism_data_plugin.h>
|
||||
#include <ParticipantManagement/Data/ppm_data_plugin.h>
|
||||
#include <ProjectDataManagement/Data/pdm_data_plugin.h>
|
||||
#include <SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
|
||||
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
|
||||
{
|
||||
return std::make_shared<InterfaceImpl>(session);
|
||||
}
|
||||
|
||||
bool GuiPlugin::availableInPartition(IDL::PartitionType partitionType) const
|
||||
{
|
||||
return partitionType == IDL::PartitionType::Exercise;
|
||||
}
|
||||
|
||||
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
|
||||
: GuiPluginBase::Interface(session, NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("CDS.SimulationGuiPlugin"))
|
||||
{}
|
||||
|
||||
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
||||
{
|
||||
QVector<LtsWidgets::PluginData> ret;
|
||||
|
||||
LtsWidgets::PluginData pluginData;
|
||||
|
||||
pluginData.menuGroup = tr("Collateral Damage Simulation");
|
||||
pluginData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
|
||||
pluginData.menuText = tr("Create Simulation");
|
||||
pluginData.identifier = QLatin1String("CdsCreateSimulationDialog");
|
||||
pluginData.menuIcon = QIcon(QLatin1String("icon:aes_impacts_sim.svg"));
|
||||
pluginData.createWidgetFunc = [this](QWidget * parent) -> LtsWidgets::LtsDialog *
|
||||
{
|
||||
CreateSimulationDialog *createSimulationDialog = new CreateSimulationDialog(parent);
|
||||
|
||||
createSimulationDialog->init(m_session);
|
||||
|
||||
return createSimulationDialog;
|
||||
};
|
||||
|
||||
ret.append(pluginData);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool InterfaceImpl::fetchInterfaces()
|
||||
{
|
||||
// map
|
||||
if (!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc))
|
||||
return false;
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// Project Data Management
|
||||
if (!m_session->getDtc<ProjectDataManagement::DataInterface>(m_pdmDtc))
|
||||
return false;
|
||||
|
||||
if (!m_pdmDtc->enableChargeType() ||
|
||||
!m_pdmDtc->enableGearType())
|
||||
return false;
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// Participant Management
|
||||
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
|
||||
return false;
|
||||
|
||||
if (!m_ppmDtc->enableParticipant() ||
|
||||
!m_ppmDtc->enableParticipantPosition())
|
||||
return false;
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// Infrastructure Management
|
||||
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(m_ismDtc))
|
||||
return false;
|
||||
|
||||
if (!m_ismDtc->enableMainFootprint() ||
|
||||
!m_ismDtc->enableMainStructureElement())
|
||||
return false;
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// File Management
|
||||
if (!m_session->getDtc<FileManagement::DataInterface>(m_flmDtc) ||
|
||||
!m_session->getFtc<FileManagement::DataInterface>(m_flmFtc))
|
||||
return false;
|
||||
|
||||
if (!m_flmDtc->enableFolder() ||
|
||||
!m_flmFtc->enableFileContentModify())
|
||||
return false;
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace CollateralDamageSimulation
|
||||
Executable
+90
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for Collateral Damage Simulation
|
||||
* $Id: bat_gui_plugin.h 47123 2019-06-07 09:30:13Z ehrlicher $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/3dws_devel/Lts/Plugins/Battery/Gui/bat_gui_plugin.h $
|
||||
* $Author: ehrlicher $
|
||||
* Created by Hannes Fritsche, ESZS, 2024-08-05
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <Plugins/CollateralDamageSimulation/cds_gui_plugin_interface.h>
|
||||
|
||||
namespace FileManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
class Ftc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ParticipantManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ProjectDataManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
class ForeignGuiInterface;
|
||||
}
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
|
||||
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
|
||||
{
|
||||
Q_PLUGIN_METADATA(IID "gui:3:cds.sim")
|
||||
Q_INTERFACES(GuiPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GuiPlugin() = default;
|
||||
~GuiPlugin() = default;
|
||||
|
||||
QString pluginName() override { return QLatin1String("CdsCreateSimulationGui"); }
|
||||
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
|
||||
bool availableInPartition(IDL::PartitionType partitionType) const override;
|
||||
|
||||
};
|
||||
|
||||
class InterfaceImpl final : public QObject, public GuiPluginBase::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InterfaceImpl(LtsSession::LtsSession *session);
|
||||
QVector<LtsWidgets::PluginData> getActions() override;
|
||||
bool fetchInterfaces() override;
|
||||
bool availableInPartition(IDL::PartitionType ) const override { return true; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
|
||||
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
std::shared_ptr<ProjectDataManagement::Interface::Dtc> m_pdmDtc;
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
|
||||
};
|
||||
|
||||
} // namespace CollateralDamageSimulation
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The ParticipantModel provices participant data for SimulationDialog
|
||||
* $Id: ism_asset_list_dialog_model.h 58852 2023-02-01 11:28:56Z fritsche_h $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/3dws_devel/Lts/Plugins/InfrastructureManagement/Gui/ResourceManagement/AssetList/ism_asset_list_dialog_model.h $
|
||||
* $Author: fritsche_h $
|
||||
* Created by Hannes Fritsche, ESZS, 2024-09-19
|
||||
*/
|
||||
|
||||
#include "cds_participant_model.h"
|
||||
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
|
||||
ParticipantModel::ParticipantModel(QObject *parent)
|
||||
: LtsWidgets::LtsAbstractTableModel<ParticipantManagement::Participant>(
|
||||
{
|
||||
tr("Party"),
|
||||
tr("Equipment Number"),
|
||||
tr("Designator"),
|
||||
tr("Tactical Identifier")
|
||||
},
|
||||
parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QVariant ParticipantModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole || !indexIsValid(index))
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
const ParticipantManagement::Participant &participant = m_vecData.at(index.row());
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case PARTY:
|
||||
{
|
||||
const int partyId = participant.partyId();
|
||||
|
||||
if (!m_partyCache.contains(partyId))
|
||||
m_partyCache.insert(partyId, m_ppmDtc->party(partyId));
|
||||
|
||||
const ParticipantManagement::Party &party = m_partyCache.value(partyId);
|
||||
|
||||
return QString::fromStdString(party.name());
|
||||
}
|
||||
case EQUIPMENT_NUMBER:
|
||||
return participant.equipmentNumber().is_set() ? participant.equipmentNumber().get() : 0;
|
||||
case DESIGNATOR:
|
||||
return QString::fromStdString(participant.designator());
|
||||
case TACTICAL_IDENTIFIER:
|
||||
return QString::fromStdString(participant.tacticalIdentifier());
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool ParticipantModel::initModel(const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc, const QVector<int> &participantIds)
|
||||
{
|
||||
m_partyCache.clear();
|
||||
|
||||
m_vecData.clear();
|
||||
m_vecData.reserve(participantIds.size());
|
||||
|
||||
m_ppmDtc = ppmDtc;
|
||||
|
||||
if (!m_ppmDtc->isParticipantEnabled())
|
||||
{
|
||||
m_ppmDtc->enableParticipant();
|
||||
m_ppmDtc->waitForHistoricalDataParticipant(3000);
|
||||
}
|
||||
|
||||
if (!m_ppmDtc->isPartyEnabled())
|
||||
{
|
||||
m_ppmDtc->enableParty();
|
||||
m_ppmDtc->waitForHistoricalDataParty(3000);
|
||||
}
|
||||
|
||||
for (int currentParticipantId : participantIds)
|
||||
m_vecData.append(m_ppmDtc->participant(currentParticipantId));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace CollateralDamageSimulation
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The ParticipantModel provices participant data for SimulationDialog
|
||||
* $Id: ism_asset_list_dialog_model.h 58852 2023-02-01 11:28:56Z fritsche_h $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/3dws_devel/Lts/Plugins/InfrastructureManagement/Gui/ResourceManagement/AssetList/ism_asset_list_dialog_model.h $
|
||||
* $Author: fritsche_h $
|
||||
* Created by Hannes Fritsche, ESZS, 2024-09-19
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
|
||||
namespace ParticipantManagement
|
||||
{
|
||||
class Participant;
|
||||
class Party;
|
||||
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
|
||||
class ParticipantModel final : public LtsWidgets::LtsAbstractTableModel<ParticipantManagement::Participant>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ParticipantModel(QObject *parent = nullptr);
|
||||
|
||||
enum Columns
|
||||
{
|
||||
PARTY = 0,
|
||||
EQUIPMENT_NUMBER = 1,
|
||||
DESIGNATOR = 2,
|
||||
TACTICAL_IDENTIFIER = 3
|
||||
};
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool initModel(const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc, const QVector<int> &participantIds);
|
||||
|
||||
private: // attributes
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
mutable QHash<int, ParticipantManagement::Party> m_partyCache;
|
||||
}; // class ParticipantModel
|
||||
|
||||
} // namespace CollateralDamageSimulation
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
The PdfCreator class creates a PDF file 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-26
|
||||
*/
|
||||
|
||||
#include "cds_pdf_creator.h"
|
||||
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <FileManagement/flm_ftc.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QTemporaryFile>
|
||||
#include <QDateTime>
|
||||
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <LtsUtilsCore/dds_vector.h>
|
||||
#include <LtsWidgets/lts_message_dialog.h>
|
||||
|
||||
#include <KDReports/KDReports.h>
|
||||
|
||||
#include <ngltools/ngltools_dtg.h>
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
|
||||
CollateralDamageSimulation::PdfCreator::PdfCreator(QWidget *parent)
|
||||
: QObject(parent)
|
||||
{}
|
||||
|
||||
PdfCreator::~PdfCreator()
|
||||
{
|
||||
if (m_report)
|
||||
{
|
||||
delete m_report;
|
||||
m_report = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PdfCreator::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_report != nullptr)
|
||||
{
|
||||
delete m_report;
|
||||
m_report = nullptr;
|
||||
}
|
||||
|
||||
m_report = new KDReports::Report();
|
||||
|
||||
m_ismDtc = ismDtc;
|
||||
m_ppmDtc = ppmDtc;
|
||||
m_flmFtc = flmFtc;
|
||||
}
|
||||
|
||||
void PdfCreator::addInformation(const QString &name, const QString &charge, const QString &igniterType, const QString &position)
|
||||
{
|
||||
if (!m_report)
|
||||
return;
|
||||
|
||||
KDReports::TextElement heading(tr("Collateral Damage Report"));
|
||||
heading.setBold(true);
|
||||
heading.setPointSize(24);
|
||||
|
||||
KDReports::TextElement nameText(tr("Name: %1").arg(name));
|
||||
KDReports::TextElement chargeText(tr("Charge: %1").arg(charge));
|
||||
KDReports::TextElement fuseText(tr("Igniter type: %1").arg(igniterType));
|
||||
KDReports::TextElement positionText(tr("Position: %1").arg(position));
|
||||
KDReports::TextElement time(tr("Time: %1").arg(DTG::toStringMSec(QDateTime::currentMSecsSinceEpoch())));
|
||||
|
||||
m_report->addElement(heading, Qt::AlignmentFlag::AlignCenter);
|
||||
m_report->addElement(nameText);
|
||||
m_report->addElement(chargeText);
|
||||
m_report->addElement(fuseText);
|
||||
m_report->addElement(positionText);
|
||||
m_report->addElement(time);
|
||||
}
|
||||
|
||||
void PdfCreator::addBuildings(const QVector<int> &buildingIds)
|
||||
{
|
||||
if (!m_report)
|
||||
return;
|
||||
|
||||
KDReports::TextElement tableHeading(tr("Buildings"));
|
||||
tableHeading.setBold(true);
|
||||
tableHeading.setPointSize(16.0);
|
||||
|
||||
m_report->addElement(tableHeading);
|
||||
|
||||
KDReports::TableElement table;
|
||||
table.setWidth(100, KDReports::Percent);
|
||||
table.setHeaderRowCount(1);
|
||||
|
||||
KDReports::TextElement nameHeader(tr("Name"));
|
||||
|
||||
table.cell(0, 0).addElement(nameHeader);
|
||||
|
||||
int row = 1;
|
||||
|
||||
for (int currentBuildingId : buildingIds)
|
||||
{
|
||||
const InfrastructureManagement::MainStructureElement ¤tBuilding = m_ismDtc->mainStructureElement(currentBuildingId);
|
||||
|
||||
KDReports::TextElement name(QString::fromStdString(currentBuilding.name()));
|
||||
|
||||
table.cell(row, 0).addElement(name);
|
||||
|
||||
++row;
|
||||
}
|
||||
|
||||
m_report->addElement(table);
|
||||
}
|
||||
|
||||
void PdfCreator::addParticipantsWithProtection(const QVector<int> &participantIds)
|
||||
{
|
||||
addParticipantTable(participantIds, tr("Participants with protection"));
|
||||
}
|
||||
|
||||
void PdfCreator::addParticipantsWithoutProtection(const QVector<int> &participantIds)
|
||||
{
|
||||
addParticipantTable(participantIds, tr("Participants without protection"));
|
||||
}
|
||||
|
||||
void PdfCreator::save(const QString &name, int folderId, int exerciseId)
|
||||
{
|
||||
QTemporaryFile saveFile;
|
||||
|
||||
saveFile.rename(QString(QStringLiteral("%1.pdf")).arg(saveFile.fileName()));
|
||||
|
||||
if (!saveFile.open())
|
||||
return;
|
||||
|
||||
m_report->exportToFile(saveFile.fileName());
|
||||
|
||||
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::Pdf);
|
||||
data.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
|
||||
data.lastModified(QDateTime::currentMSecsSinceEpoch());
|
||||
data.content(LtsUtils::convert<std::vector<uint8_t>>(saveFile.readAll()));
|
||||
data.exerciseId(exerciseId);
|
||||
|
||||
bool isModifyRequestOk = m_flmFtc->fileContentModifyRequest(data, [this](const Core::FunctionReplyObject &reply)
|
||||
{
|
||||
if (reply.error())
|
||||
warnSafeDidNotWork(QLatin1String("Could not save plan: %1").arg(QString::fromStdString(reply.str())));
|
||||
});
|
||||
|
||||
if (!isModifyRequestOk)
|
||||
warnSafeDidNotWork(QLatin1String("Could not save plan."));
|
||||
}
|
||||
|
||||
void PdfCreator::clear()
|
||||
{
|
||||
if (m_report != nullptr)
|
||||
{
|
||||
delete m_report;
|
||||
m_report = nullptr;
|
||||
}
|
||||
|
||||
m_report = new KDReports::Report();
|
||||
}
|
||||
|
||||
void PdfCreator::warnSafeDidNotWork(const QString &message) const
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(static_cast<QWidget*>(parent()), message, tr("Save failed"));
|
||||
}
|
||||
|
||||
void PdfCreator::addParticipantTable(const QVector<int> &participantIds, const QString &tableName)
|
||||
{
|
||||
if (!m_report)
|
||||
return;
|
||||
|
||||
KDReports::TextElement tableHeading(tableName);
|
||||
tableHeading.setBold(true);
|
||||
tableHeading.setPointSize(16.0);
|
||||
|
||||
m_report->addElement(tableHeading);
|
||||
|
||||
KDReports::TableElement table;
|
||||
table.setWidth(100, KDReports::Percent);
|
||||
table.setHeaderRowCount(1);
|
||||
|
||||
KDReports::TextElement partyHeader(tr("Party"));
|
||||
KDReports::TextElement equipmentNumberHeader(tr("Equipment No."));
|
||||
KDReports::TextElement designationHeader(tr("Designator"));
|
||||
KDReports::TextElement tacticalIdentifierHeader(tr("Tactical Identifier"));
|
||||
|
||||
table.cell(0, 0).addElement(partyHeader);
|
||||
table.cell(0, 1).addElement(equipmentNumberHeader);
|
||||
table.cell(0, 2).addElement(designationHeader);
|
||||
table.cell(0, 3).addElement(tacticalIdentifierHeader);
|
||||
|
||||
QHash<int, QString> partyNames;
|
||||
int row = 1;
|
||||
|
||||
for (int currentParticipantId : participantIds)
|
||||
{
|
||||
int column = 0;
|
||||
const ParticipantManagement::Participant ¤tParticipant = m_ppmDtc->participant(currentParticipantId);
|
||||
|
||||
if (!partyNames.contains(currentParticipant.partyId()))
|
||||
{
|
||||
const ParticipantManagement::Party &party = m_ppmDtc->party(currentParticipant.partyId());
|
||||
|
||||
partyNames.insert(party.id(), QString::fromStdString(party.name()));
|
||||
}
|
||||
|
||||
KDReports::TextElement party(partyNames.value(currentParticipant.partyId()));
|
||||
KDReports::TextElement equipmentNumber(QString::number(currentParticipant.equipmentNumber().is_set() ? currentParticipant.equipmentNumber().get() : 0));
|
||||
KDReports::TextElement designation(QString::fromStdString(currentParticipant.designator()));
|
||||
KDReports::TextElement tacticalIdentifier(QString::fromStdString(currentParticipant.tacticalIdentifier()));
|
||||
|
||||
table.cell(row, column++).addElement(party);
|
||||
table.cell(row, column++).addElement(equipmentNumber);
|
||||
table.cell(row, column++).addElement(designation);
|
||||
table.cell(row, column++).addElement(tacticalIdentifier);
|
||||
|
||||
++row;
|
||||
}
|
||||
|
||||
m_report->addElement(table);
|
||||
}
|
||||
|
||||
|
||||
} //namespace CollateralDamageSimulation
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
The PdfCreator class creates a PDF file 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-26
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <memory>
|
||||
|
||||
namespace KDReports
|
||||
{
|
||||
class Report;
|
||||
}
|
||||
|
||||
namespace FileManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Ftc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ParticipantManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
class PdfCreator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PdfCreator(QWidget *parent = nullptr);
|
||||
|
||||
~PdfCreator();
|
||||
|
||||
void 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);
|
||||
|
||||
void addInformation(const QString &name, const QString &charge, const QString &igniterType, const QString &position);
|
||||
void addBuildings(const QVector<int> &buildingIds);
|
||||
void addParticipantsWithProtection(const QVector<int> &participantIds);
|
||||
void addParticipantsWithoutProtection(const QVector<int> &participantIds);
|
||||
|
||||
void save(const QString &name, int folderId, int exerciseId);
|
||||
|
||||
void clear();
|
||||
|
||||
private: // methods
|
||||
void warnSafeDidNotWork(const QString &message) const;
|
||||
void addParticipantTable(const QVector<int> &participantIds, const QString &tableName);
|
||||
|
||||
private: // attributes
|
||||
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
|
||||
KDReports::Report *m_report { nullptr };
|
||||
};
|
||||
|
||||
|
||||
} // namespace CollateralDamageSimulation
|
||||
+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
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <QMap>
|
||||
#include <memory>
|
||||
#include <SymbologyXML/symbol_types.h>
|
||||
#include <ParticipantManagement/ppm_enums.hpp>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <SituationMap/GeometryModel/geometry_model.h>
|
||||
|
||||
namespace FileManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Ftc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
enum class ProtectionState
|
||||
{
|
||||
WithProtection = 2,
|
||||
WithoutProtection = 4,
|
||||
Underground = 5,
|
||||
};
|
||||
|
||||
|
||||
class PlanCreator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PlanCreator(QWidget *parent = nullptr);
|
||||
|
||||
~PlanCreator();
|
||||
|
||||
void 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);
|
||||
|
||||
void addBuildings(const QHash<int, QPolygonF> &buildingFootprints, const QVector<int> &directlyHitBuildings);
|
||||
void addProtectionAreas(const QVector<QPolygonF> &protectionAreas);
|
||||
void addDetonationArea(const QPointF &impactPosition, double lethalRadius, double nonLethalRadius = 0.0);
|
||||
void addParticipantsWithProtection(const QVector<int> &participantIds);
|
||||
void addParticipantsWithoutProtection(const QVector<int> &participantIds);
|
||||
void addParticipantsInUnderground(const QVector<int> &participantIds);
|
||||
|
||||
void save(const QString &name, int folderId, int exerciseId);
|
||||
|
||||
void clear();
|
||||
|
||||
private: // methods
|
||||
void warnSafeDidNotWork(const QString &message);
|
||||
void addBuilding(const QPolygonF &footprint, bool isDirectlyHit);
|
||||
void addParticipants(const QVector<int> &participantIds, ProtectionState protectionState);
|
||||
void addParticipant(int participantId, ProtectionState protectionState);
|
||||
void addProtectionArea(const QPolygonF &areaPolygon);
|
||||
SymbologyXML::SymbolTypes::t_affil partyRoleToSymbolAffiliation(const ParticipantManagement::Role &partyRole) const;
|
||||
|
||||
private: // attributes
|
||||
QList<SituationMap::GeometryModel::Node> m_protectionAreas;
|
||||
QList<SituationMap::GeometryModel::Node> m_directlyHitBuildings;
|
||||
|
||||
SituationMap::GeometryModel *m_geometryModel { nullptr };
|
||||
|
||||
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
|
||||
QMap<int, ParticipantManagement::Party> m_partyCache;
|
||||
};
|
||||
|
||||
|
||||
} // namespace CollateralDamageSimulation
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Dialog to show affected participants and builsings by an impact
|
||||
* @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-05
|
||||
*/
|
||||
|
||||
#include "cds_simulation_dialog.h"
|
||||
#include "ui_cds_simulation_dialog.h"
|
||||
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
|
||||
#include "cds_building_model.h"
|
||||
#include "cds_participant_model.h"
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
|
||||
SimulationDialog::SimulationDialog(QWidget *parent)
|
||||
: LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
|
||||
, m_ui(new Ui::SimulationDialog)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Situation_Kollateralschadensimulator"));
|
||||
}
|
||||
|
||||
void SimulationDialog::init(const QVector<int> &buildingsInRange, const QVector<int> &participantsWithoutProtection, const QVector<int> &participantsWithProtection, const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc)
|
||||
{
|
||||
// dds stuff
|
||||
if (!ismDtc->isMainStructureElementEnabled())
|
||||
{
|
||||
ismDtc->enableMainStructureElement();
|
||||
ismDtc->waitForHistoricalDataMainStructureElement(3000);
|
||||
}
|
||||
|
||||
if (!ppmDtc->isParticipantEnabled())
|
||||
{
|
||||
ppmDtc->enableParticipant();
|
||||
ppmDtc->waitForHistoricalDataParticipant(3000);
|
||||
}
|
||||
|
||||
if (!ppmDtc->isPartyEnabled())
|
||||
{
|
||||
ppmDtc->enableParty();
|
||||
ppmDtc->waitForHistoricalDataParty(3000);
|
||||
}
|
||||
|
||||
// participants without protection
|
||||
if (m_participantsWithoutProtectionModel != nullptr)
|
||||
{
|
||||
delete m_participantsWithoutProtectionModel;
|
||||
m_participantsWithoutProtectionModel = nullptr;
|
||||
}
|
||||
|
||||
m_participantsWithoutProtectionModel = new ParticipantModel(this);
|
||||
|
||||
m_participantsWithoutProtectionModel->initModel(ppmDtc, participantsWithoutProtection);
|
||||
|
||||
m_ui->ldvParticipantsWithoutProtection->setModel(m_participantsWithoutProtectionModel);
|
||||
|
||||
// participants with protection
|
||||
if (m_participantsWithProtectionModel != nullptr)
|
||||
{
|
||||
delete m_participantsWithProtectionModel;
|
||||
m_participantsWithProtectionModel = nullptr;
|
||||
}
|
||||
|
||||
m_participantsWithProtectionModel = new ParticipantModel(this);
|
||||
|
||||
m_participantsWithProtectionModel->initModel(ppmDtc, participantsWithProtection);
|
||||
|
||||
m_ui->ldvParticipantsWithProtection->setModel(m_participantsWithProtectionModel);
|
||||
|
||||
// buildings
|
||||
if (m_buildingModel != nullptr)
|
||||
{
|
||||
delete m_buildingModel;
|
||||
m_buildingModel = nullptr;
|
||||
}
|
||||
|
||||
m_buildingModel = new BuildingModel(this);
|
||||
|
||||
m_buildingModel->initModel(ismDtc, buildingsInRange);
|
||||
|
||||
m_ui->ldvBuildings->setModel(m_buildingModel);
|
||||
}
|
||||
|
||||
void SimulationDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Simulation"));
|
||||
}
|
||||
|
||||
} //namespace ParticipantManagement
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Dialog to show affected participants and builsings by an impact
|
||||
* @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-05
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
class QListWidget;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class SimulationDialog;
|
||||
}
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ParticipantManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace CollateralDamageSimulation
|
||||
{
|
||||
class BuildingModel;
|
||||
class ParticipantModel;
|
||||
|
||||
class SimulationDialog : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SimulationDialog(QWidget *parent = nullptr);
|
||||
|
||||
void init(const QVector<int> &buildingsInRange,
|
||||
const QVector<int> &participantsWithoutProtection,
|
||||
const QVector<int> &participantsWithProtection,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc);
|
||||
|
||||
void retranslate() override final;
|
||||
|
||||
private: // attributes
|
||||
ParticipantModel *m_participantsWithoutProtectionModel { nullptr };
|
||||
ParticipantModel *m_participantsWithProtectionModel { nullptr };
|
||||
BuildingModel *m_buildingModel { nullptr };
|
||||
|
||||
Ui::SimulationDialog *m_ui;
|
||||
};
|
||||
|
||||
} // namespace CollateralDamageSimulation
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SimulationDialog</class>
|
||||
<widget class="QWidget" name="SimulationDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>816</width>
|
||||
<height>280</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">setwindowtitle in source</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Affected Participants (protection):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Affected Participants (no protection):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Affected buildings:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="LtsDataView::LtsDataView" name="ldvParticipantsWithoutProtection" native="true"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="LtsDataView::LtsDataView" name="ldvParticipantsWithProtection" native="true"/>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="LtsDataView::LtsDataView" name="ldvBuildings" native="true"/>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="2">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3" rowspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsDataView::LtsDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsDataView/lts_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Reference in new issue
Block a user