Adds initial intermediate qt6 porting state

This commit is contained in:
torsten committed 2026-08-17 17:54:56 +02:00
1 parent 99136e9460
commit d176b5e0d7
11247 files changed
+1891537

No files matched your search

@@ -0,0 +1,197 @@
#include "explosion_single_central_to_map.h"
#include "pdm_handler.h"
#include <Map/bounding_box.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <ParticipantManagement/Data/ppm_data_plugin.h>
namespace SituationMap
{
ExplosionSingleCentral2SituationMap::ExplosionSingleCentral2SituationMap(PdmHandler *pdmHandler, ObjectFactory &objFac, const QString &layername, const char *loggerName)
: BaseClass(objFac, layername, loggerName)
, m_pdmHandler(pdmHandler)
{
}
bool ExplosionSingleCentral2SituationMap::init(PluginProvider *pluginProvider)
{
if (!BaseClass::init(pluginProvider) ||
!pluginProvider->ppmDtc())
return false;
m_ppmDtc = pluginProvider->ppmDtc();
return true;
}
bool ExplosionSingleCentral2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (! m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::explosionSingleCentralChanged,
this, &ExplosionSingleCentral2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->explosionSingleCentrals([this](const AreaEffectSimulation::ExplosionSingleCentral & data)
{
handleChanged(data, DataModification::eAdded);
});
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &ExplosionSingleCentral2SituationMap::itemViewChangedESC, Qt::UniqueConnection);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
void ExplosionSingleCentral2SituationMap::itemViewChangedESC(const AreaEffectSimulation::AesItemView &data, DataModification mod)
{
if (mod != DataModification::eAdded && mod != DataModification::eModified)
return;
if (data.aesTypeId() != AreaEffectSimulation::AesType::AtExplosionSingleCentral)
return;
const int32_t simId = data.aesItemId();
if (simId < 0)
return;
const auto uniqueMapId = this->simId2UniqueMapId(simId);
if (!isUniqueMapIdValid(uniqueMapId))
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " skip due to invalid map id";
return;
}
RefPointer<MAP_TYPE> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (!mapObj.valid())
{
WARNING_LOG(m_logger) << "Can not find map object for aes item with simId " << simId;
return;
}
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtExplosionSingleCentral, itemView))
{
updateDetonation(itemView, mapObj);
if (!mapObj->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " aesItemId = " << data.aesItemId() << " updateView failed";
}
}
bool ExplosionSingleCentral2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
const int32_t simId = ddsData.id();
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
int partyId = -1;
if (ddsData.participantId().is_set())
{
const int pId = ddsData.participantId().get();
const ParticipantManagement::Participant &participant = m_ppmDtc->participant(pId);
if (participant.id() == pId)
partyId = participant.partyId();
}
else
{
if (ddsData.partyId().is_set())
partyId = ddsData.partyId().get();
}
if (partyId < 0 )
partyId = 0;
mapObj->setPartyId(partyId);
const bool changeToActive = (ddsData.effectStateId().underlying()==AreaEffectSimulation::AesEffectState_def::EsActivated) &&
(static_cast<int>(mapObj->aesState()) < static_cast<int>(AreaEffectSimulation::AesEffectState_def::EsActivated));
mapObj->setAesState(effectState2aesState(ddsData.effectStateId().underlying()));
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtExplosionSingleCentralTrajectory, itemView))
this->updateGeometry(itemView, mapObj);
else
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtExplosionSingle) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
const Core::GeoPosition2D &impactPos2D = ddsData.impactPosition();
mapObj->setImpactOrigin(Point3D(impactPos2D.lon(), impactPos2D.lat(), 0.0));
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtExplosionSingleCentral, itemView))
updateDetonation(itemView, mapObj);
if (changeToActive)
mapObj->startDetonationAnimation();
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool ExplosionSingleCentral2SituationMap::updateDetonation(const AreaEffectSimulation::AesItemView &itemView, RefPointer<Aes2SituationMap::MAP_TYPE> mapObj)
{
const int32_t simId = itemView.aesItemId();
if (simId < 0)
return false;
if (itemView.form().size() != 2)
return false;
const Core::GeoPosition &form0 = itemView.form().front();
const Core::GeoPosition &form1 = itemView.form().back();
SingleFireCentral::DetonationData dd;
dd.m_origin = Point3D(form0.lon(), form0.lat(), form0.z());
const LtsCoordTrans::UtmCoordinate utm0 = LtsCoordTrans::UtmCoordinate::fromGeographic(form0.lon(), form0.lat());
const LtsCoordTrans::UtmCoordinate utm1 = LtsCoordTrans::UtmCoordinate::fromGeographic(form1.lon(), form1.lat());
dd.m_radius = (LtsUtils::QPoint3D(utm0.x, utm0.y, form0.z()) - LtsUtils::QPoint3D(utm1.x, utm1.y, form1.z())).length();
mapObj->setDetonation(dd);
return true;
}
}
@@ -0,0 +1,57 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/single_fire_central.h>
#include <QObject>
namespace SituationMap
{
class PdmHandler;
class ExplosionSingleCentral2SituationMap;
template <>
struct Aes2SituationMapTraits<ExplosionSingleCentral2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::ExplosionSingleCentral;
using MAP_TYPE = SituationMap::SingleFireCentral;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtExplosionSingleCentralTrajectory;
};
class ExplosionSingleCentral2SituationMap final : public Aes2SituationMap<ExplosionSingleCentral2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<ExplosionSingleCentral2SituationMap>;
using BaseClass::BaseClass;
ExplosionSingleCentral2SituationMap(PdmHandler *pdmHandler,
ObjectFactory &objFac,
const QString &layername,
const char *loggerName);
bool init(PluginProvider *pluginProvider) override;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::ExplosionSingleCentral &data)> &cb) const
{
return m_aesDtc->explosionSingleCentrals(cb);
}
protected:
void itemViewChangedESC(const AreaEffectSimulation::AesItemView &data, DataModification mod);
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool updateDetonation(const AreaEffectSimulation::AesItemView &itemView,
RefPointer<MAP_TYPE> mapObj);
PdmHandler *m_pdmHandler = nullptr;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
};
}
@@ -0,0 +1,301 @@
#pragma once
#include "unified_map_object_data.h"
#include "plugin_provider.h"
#include "map_object_type.h"
#include "resource_manager_mode.h"
#include <Map/situation_map_types.h>
#include <Common/situation_map_logging.h>
#include <Common/ref_pointer.h>
#include <Plugins/ProjectDataManagement/pdm_data_plugin_interface.h>
#include <QObject>
#include <QPointer>
namespace SituationMap
{
class AbstractMapObject;
class AirSupportImpact2SituationMap;
class Building2SituationMap;
class BuildingHitlineInfo2SituationMap;
class BuildingOutline;
class GeoImage;
class BuildingContamination;
class BuildingOwnership;
class GuezIed2SituationMap;
class GuezNasat9Liner2SituationMap;
class HitlineInfo2SituationMap;
class Map;
class TrainingAreaToSituationMap;
class SpecialAreaToSituationMap;
class MountingPointToMap;
class SoundAreaToMap;
class MSEPointToMap;
class MSEBridgeToMap;
class MovementTrackManager;
class Participant;
class Participant2SituationMap;
class PdmHandler;
class Sim2SituationMapBase;
class ShootbackAreaToSituationMap;
class Polygon;
class EmergencyCallToMap;
class ChargeEffectToMap;
class SingleFire;
class AdapterDds : public QObject
{
Q_OBJECT
public:
explicit AdapterDds(QObject *parent = nullptr);
virtual ~AdapterDds();
bool init(Map *map, PluginProvider *pluginProvider, QPointer<SituationMap::MovementTrackManager> &movementTrackMgr, bool resourceMode);
bool initRenderer3D_AesExtrusion();
bool initRenderer3D_AesCentral_Booby(const QString &layernameAesCentral, const QVector<int> &aesTypesForReRunIfPartyColorChanges);
bool assignUniqueValueRendererAesCentral(const QString &layername);
bool assignUniqueValueRendererAesCentral3DExtrusion(const QString &layername);
bool run();
bool isRunning() const;
bool stop();
void clearObjects();
ResourceManagerMode resourceManagerMode() const;
bool setResourceManagerMode(ResourceManagerMode rmm);
bool showExpiredEmergencyCalls(bool bShowExpired);
bool uniqueMapId2SimId(UniqueMapId uniqueMapIdIn, int32_t &simIdOut);
bool unifiedMapObjectData(UniqueMapId uniqueMapIdIn, UnifiedMapObjectData &umodOut) const;
UniqueMapId simId2UniqueMapIdParticipant(int32_t simId) const;
RefPointer<Participant> simId2Participant(int32_t simId);
QPointer<MovementTrackManager> movementTrackManager() const { return m_movementTrackManager; }
UniqueMapId simId2UniqueMapIdAes(int32_t simId) const;
RefPointer<AbstractMapObject> simId2Aes(int32_t simId);
UniqueMapId simId2UniqueMapIdBuilding(int32_t simId) const;
RefPointer<BuildingOutline> simId2Building(int32_t simId);
UniqueMapId simId2UniqueMapIdBridge(int32_t simId) const;
RefPointer<BuildingOutline> simId2Bridge(int32_t simId);
UniqueMapId simId2UniqueMapIdMountingPoint(int32_t simId) const;
RefPointer<GeoImage> simId2MountingPoint(int32_t simId);
UniqueMapId simId2UniqueMapIdGuezIed(int32_t simId) const;
RefPointer<Participant> simId2GuezIed(int32_t simId);
UniqueMapId simId2UniqueMapIdChargeEffect(int32_t simId) const;
RefPointer<SingleFire> simId2ChargeEffect(int32_t simId);
UniqueMapId simId2UniqueMapIdTrainingArea(int32_t simId) const;
RefPointer<SituationMap::Polygon> simId2TrainingArea(int32_t simId);
UniqueMapId simId2UniqueMapIdSpecialArea(int32_t simId) const;
RefPointer<SituationMap::Polygon> simId2SpecialArea(int32_t simId);
UniqueMapId simId2UniqueMapIdShootbackArea(int32_t simId) const;
RefPointer<SituationMap::Polygon> simId2ShootbackArea(int32_t simId);
UniqueMapId simId2UniqueMapId(MapObjectType mot, int32_t simId) const;
QVector<UniqueMapId> simIds2UniqueMapIds(MapObjectType mot, QVector<int32_t> simIds) const;
RefPointer<AbstractMapObject> simId2MapObject(MapObjectType mot, int32_t simId);
Sim2SituationMapBase *situationMapBase(MapObjectType mot) const;
bool setMapObjectSelected(MapObjectType mot, const QVector<int> &entityIds, bool selection = true);
bool clearMapObjectSelection(MapObjectType mot = MapObjectType::MOT_Undefined);
bool isBuildingOwnershipSupported() const;
bool isBuildingOwnershipVisible() const;
bool setBuildingOwnershipVisible(bool visible);
bool isBuildingContaminationSupported() const;
bool isBuildingContaminationVisible() const;
bool setBuildingContaminationVisible(bool visible);
bool enableFireEventFlashing(bool enable);
bool isFireEventFlashingEnabled() const;
bool setOwnPositionVisible(bool enable);
bool isOwnPositionVisible() const;
Q_SIGNALS:
void mapObjectChanged(UniqueMapId uniqueMapId);
void mapObjectRemoved(UniqueMapId uniqueMapId);
void participantPositionChanged(const int32_t participantId, const Point3D &newPos);
void resourceManagerModeChanged(ResourceManagerMode newMode);
public Q_SLOTS:
void restart() { stop(); run(); }
void restartIfRunning()
{
if (!this->isRunning())
return;
restart();
}
void onSymbolDictionaryChanged();
bool onMapObjectClicked(const RefPointer<AbstractMapObject> &mapObject);
bool onMapObjectClicked(UniqueMapId uniqueMapId);
bool onMapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds);
void onMapObjectChangedUpdateDrawOrder(UniqueMapId uniqueMapId);
void onMapObjectRemoved(UniqueMapId uniqueMapId);
private slots:
void onParticipantOwnPositionChanged(const Point3D &newPos, int64_t sampleTime);
private:
void startChangedDelayTimer();
void startOwnPositionOutdatedTimer();
QList<Sim2SituationMapBase *> listOfSim2Map() const;
QList<Sim2SituationMapBase *> listOfAes2Map() const;
private:
bool m_isShowOwnPosition{true};
bool m_isRunning{false};
QTimer *m_changedDelayTimer{nullptr};
QTimer *m_ownPositionOutdatedTimer{nullptr};
QPointer<Map> m_map;
PdmHandler *m_pdmHandler{nullptr};
PluginProvider *m_pluginProvider{nullptr};
QSharedPointer<Participant2SituationMap> m_particpants;
QMap<int32_t, long> m_participantId2uniqueMapId;
QPointer<SituationMap::MovementTrackManager> m_movementTrackManager;
QSharedPointer<HitlineInfo2SituationMap> m_hitlineInfo2SituationMap;
QSharedPointer<BuildingHitlineInfo2SituationMap> m_bldHitlineInfo2SituationMap;
QMap<int, Sim2SituationMapBase *> m_aes2MapCont;
QMap<UniqueMapId, qint64> m_startTimeMap;
QSharedPointer<ChargeEffectToMap> m_chargeEffects;
QSharedPointer<EmergencyCallToMap> m_emergencyCalls;
QSharedPointer<TrainingAreaToSituationMap> m_trainingAreas;
QSharedPointer<BuildingOwnership> m_buildingOwnership;
QSharedPointer<BuildingContamination> m_buildingContamination;
QSharedPointer<MountingPointToMap> m_mountingPoints;
QSharedPointer<SoundAreaToMap> m_soundAreas;
QSharedPointer<Building2SituationMap> m_buildings;
QSharedPointer<MSEPointToMap> m_msePoints;
QSharedPointer<MSEBridgeToMap> m_mseBridges;
QSharedPointer<SpecialAreaToSituationMap> m_specialAreas;
QSharedPointer<GuezIed2SituationMap> m_guezIeds;
QSharedPointer<GuezNasat9Liner2SituationMap> m_guezNasat9Liner;
QSharedPointer<ShootbackAreaToSituationMap> m_shootbackAreas;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,548 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/FilterManagement/flt_data_plugin_interface.h>
#include <Plugins/FilterManagement/flt_aes_plugin_interface.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <AreaEffectSimulation/aes_data_plugin_interface.h>
#include <AreaEffectSimulation/aes_info_gui_plugin_interface.h>
#include <FilterManagement/flt_data_plugin_aes_display_filter.h>
#include <Map/abstract_effect_simulation.h>
namespace SituationMap
{
inline PositionCont form2PosCont(const std::vector<Core::GeoPosition2D> &form)
{
PositionCont ret;
ret.reserve(form.size());
for (const auto &pos : form)
ret.push_back({pos.lon(), pos.lat(), 0.0});
return ret;
}
inline PositionCont form2PosCont(const std::vector<Core::GeoPosition> &form)
{
PositionCont ret;
ret.reserve(form.size());
for (const auto &pos : form)
ret.push_back({pos.lon(), pos.lat(), pos.z()});
return ret;
}
inline PositionCont form2PosCont(const QPolygonF &form)
{
PositionCont ret;
ret.reserve(form.size());
for (const auto &pos : form)
ret.push_back({pos.x(), pos.y(), 0.0});
return ret;
}
inline SituationMap::AesEffectState effectState2aesState(AreaEffectSimulation::AesEffectState effectState)
{
SituationMap::AesEffectState aesState = AesEffectState::Unknown;
switch (effectState.underlying())
{
case AreaEffectSimulation::AesEffectState_def::EsUnknown:
case AreaEffectSimulation::AesEffectState_def::EsError:
case AreaEffectSimulation::AesEffectState_def::EsExpired:
case AreaEffectSimulation::AesEffectState_def::EsRemoved:
case AreaEffectSimulation::AesEffectState_def::EsPaused:
case AreaEffectSimulation::AesEffectState_def::EsReceived:
case AreaEffectSimulation::AesEffectState_def::EsCreated:
aesState = AesEffectState::Created;
break;
case AreaEffectSimulation::AesEffectState_def::EsFired:
case AreaEffectSimulation::AesEffectState_def::EsPrepared:
aesState = AesEffectState::Prepared;
break;
case AreaEffectSimulation::AesEffectState_def::EsActivated:
aesState = AesEffectState::Activated;
break;
}
return aesState;
}
template <typename SUPER>
struct Aes2SituationMapTraits;
template <typename SUPER>
class Aes2SituationMap : public Sim2SituationMap<typename Aes2SituationMapTraits<SUPER>::DDS_TYPE, typename Aes2SituationMapTraits<SUPER>::MAP_TYPE>
, protected FilterManagement::AesDisplayFilter::FilterChangedCallback
, protected DdsFilterHandling<typename Aes2SituationMapTraits<SUPER>::MAP_TYPE>
{
public:
using DDS_TYPE = typename Aes2SituationMapTraits<SUPER>::DDS_TYPE;
using MAP_TYPE = typename Aes2SituationMapTraits<SUPER>::MAP_TYPE;
using BaseClass = Sim2SituationMap<DDS_TYPE, MAP_TYPE>;
using FilterClass = DdsFilterHandling<MAP_TYPE>;
Aes2SituationMap(ObjectFactory &objFac,
const QString &layername,
const char *loggerName)
: BaseClass(objFac, layername, 0, loggerName)
, FilterClass(loggerName, this)
{}
Aes2SituationMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
{}
~Aes2SituationMap()
{
if (m_displayFilter)
m_displayFilter->removeChangedCallback(this);
}
void setIsVisibleByExternalCallback(const std::function<bool(int32_t, bool&)> &isVisibleByExternalCallback)
{
m_isVisibleByExternalCallback = isVisibleByExternalCallback;
}
int32_t getSimId(const DDS_TYPE &ddsData) const override
{
return ddsData.id();
}
virtual bool init(PluginProvider *pluginProvider)
{
if (!pluginProvider ||
!pluginProvider->aesDtc())
return false;
m_pluginProvider = pluginProvider;
m_aesDtc = m_pluginProvider->aesDtc();
m_aesInfoIfc = m_pluginProvider->aesInfoIfc();
FilterClass::init(pluginProvider);
auto fltAesIfc = m_pluginProvider->fltAesIfc();
if (fltAesIfc)
{
m_displayFilter = fltAesIfc->aesFilterForOperator(m_pluginProvider->operatorId(),
m_pluginProvider->workspaceId());
if (m_displayFilter)
m_displayFilter->addChangedCallback(this);
}
m_pluginProvider->disconnect(this);
QObject::connect(m_pluginProvider, &PluginProvider::partitionTimeChanged,
this, &Aes2SituationMap::partitionTimeChanged);
QObject::connect(m_pluginProvider, &PluginProvider::workspaceIdChanged,
this, &Aes2SituationMap::onWorkspaceIdChanged);
#ifdef USE_OBJECTAPPEARANCE_VECTOR
m_objectAppearanceVisibility += ObjectAppearance::Technical;
#endif
return true;
}
bool run() override
{
QObject::connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &Aes2SituationMap::itemViewChanged, Qt::UniqueConnection);
return true;
}
void stop() override
{
QObject::disconnect(m_pluginProvider, &PluginProvider::partitionTimeChanged,
this, &Aes2SituationMap::partitionTimeChanged);
m_aesDtc->disconnect(this);
}
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override
{
auto sp = m_aesInfoIfc.lock();
if (!sp)
return false;
const QVector<int32_t> &simIds = this->uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
sp->showInfoWindow(simIds, Aes2SituationMapTraits<SUPER>::aesType);
return true;
}
qint64 startTime(UniqueMapId uniqueMapId) const override
{
if (!m_aesDtc)
return -1;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return -1;
return effectStartTimeFromSimId(simIdOut);
}
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override
{
if (!m_aesDtc)
return false;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
umodOut.m_participantData.m_typeName = QObject::tr("Area Effect Simulation");
RefPointer<MAP_TYPE> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_image = mapObj->previewImage();
const SUPER *derived = static_cast<const SUPER*>(this);
const auto cb = [simIdOut, &umodOut](const DDS_TYPE &data) -> bool
{
if (data.id() == simIdOut)
{
if (data.partyId().is_set())
umodOut.m_partyId = data.partyId().get();
umodOut.m_description1 = QString::fromStdString(data.name());
return true;
}
return false;
};
return derived->iterateAesData(cb);
}
protected:
void onWorkspaceIdChanged(const QString &newWorkspaceId) override
{
if (m_displayFilter)
m_displayFilter->removeChangedCallback(this);
m_displayFilter = nullptr;
auto fltAesIfc = m_pluginProvider->fltAesIfc();
if (!fltAesIfc)
return;
const auto opId = m_pluginProvider->operatorId();
const auto wsId = m_pluginProvider->workspaceId();
FilterClass::onWorkspaceIdChanged(newWorkspaceId);
m_displayFilter = fltAesIfc->aesFilterForOperator(opId, wsId);
if (m_displayFilter)
m_displayFilter->addChangedCallback(this);
}
qint64 effectStartTimeFromSimId(int simId) const
{
qint64 effectStart = -1;
const SUPER *derived = static_cast<const SUPER*>(this);
const auto cb = [simId, &effectStart](const DDS_TYPE &data) -> bool
{
if (data.id() == simId)
{
if (data.effectStart().is_set())
effectStart = data.effectStart().get();
return true;
}
return false;
};
derived->iterateAesData(cb);
return effectStart;
}
void visibilityFilterChanged(AreaEffectSimulation::AesType aesType)
{
if (Aes2SituationMapTraits<SUPER>::aesType != aesType)
return;
SUPER *derived = static_cast<SUPER*>(this);
const auto cb = [derived](const DDS_TYPE &data) -> bool
{
derived->updateVisibility(data);
return false;
};
derived->iterateAesData(cb);
}
bool isElapsed(const DDS_TYPE &ddsData) const override
{
const AreaEffectSimulation::AesEffectState &aesEffectState = ddsData.effectStateId();
if (ddsData.isDeleted())
return true;
if (aesEffectState == AreaEffectSimulation::AesEffectState_def::EsRemoved)
return true;
if (aesEffectState == AreaEffectSimulation::AesEffectState_def::EsExpired)
{
if (!ddsData.effectStart().is_set())
return true;
const auto effectEnd = ddsData.effectStart().get() + ddsData.effectDuration();
const auto afterGlow = m_displayFilter ? m_displayFilter->maxAfterglowDurationMSec() : 0;
return (m_pluginProvider->partitionTime() > effectEnd + afterGlow);
}
return false;
}
void partitionTimeChanged()
{
const int partitionTimeSec = m_pluginProvider->partitionTime() / 1000;
bool bCleanup = (partitionTimeSec % 10) == 0;
SUPER *derived = static_cast<SUPER*>(this);
const auto cb = [this, bCleanup](const DDS_TYPE &data) -> bool
{
if (data.isDeleted())
return false;
if (data.effectStateId() != AreaEffectSimulation::AesEffectState_def::EsExpired)
return false;
if (bCleanup)
{
if (!m_simId2UniqueMapId.contains(getSimId(data)))
return false;
if (isElapsed(data))
this->removeElement(data);
return false;
}
this->updateVisibility(data);
return false;
};
derived->iterateAesData(cb);
}
void itemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification mod)
{
if (mod != DataModification::eAdded && mod != DataModification::eModified)
return;
if (data.aesTypeId() != Aes2SituationMapTraits<SUPER>::aesType)
return;
const auto uniqueMapId = this->simId2UniqueMapId(data.aesItemId());
if (!isUniqueMapIdValid(uniqueMapId))
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " skip due to invalid map id";
return;
}
RefPointer<MAP_TYPE> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (!mapObj.valid())
{
WARNING_LOG(m_logger) << "Can not find map object for aes item with id " << data.aesItemId();
return;
}
updateGeometry(data, mapObj);
}
public:
void updateVisibility()
{
onAesDisplayFilterChanged(Aes2SituationMapTraits<SUPER>::aesType);
}
protected:
void updateVisibility(const DDS_TYPE &data)
{
const auto uniqueMapId = this->simId2UniqueMapId(getSimId(data));
if (!isUniqueMapIdValid(uniqueMapId))
{
return;
}
if (isElapsed(data))
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " skip due to isElapsed map id/simId: " << data.id();
return;
}
RefPointer<MAP_TYPE> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (!mapObj.valid())
{
WARNING_LOG(m_logger) << "Can not find map object for aes item with id " << getSimId(data);
return;
}
updateVisibility(data, mapObj);
}
virtual bool updateVisibility(const DDS_TYPE &data, RefPointer<MAP_TYPE> mapObj)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << this->getSimId(data);
if (!mapObj)
return false;
bool isReferenced = false;
bool isVisibleByExternal = true;
if (m_isVisibleByExternalCallback)
{
isVisibleByExternal = false;
isReferenced = m_isVisibleByExternalCallback(this->getSimId(data), isVisibleByExternal);
DEBUG_LOG(m_logger) << " simId = " << this->getSimId(data)
<< " isReferenced = " << isReferenced
<< " isVisibleByExternal = " << isVisibleByExternal;
if (!isReferenced)
isVisibleByExternal = true;
}
bool bIsVisibleByFilter = true;
if (!isReferenced && m_displayFilter)
{
bIsVisibleByFilter = isVisibleByFilter(data);
}
#ifdef USE_OBJECTAPPEARANCE_VECTOR
Q_FOREACH(const auto appearance, m_objectAppearanceVisibility)
{
const bool bOldVisibility = mapObj->visibility(appearance);
if (bOldVisibility != isVisibile)
{
mapObj->setVisibility(appearance, isVisibile);
changed = true;
mapObj->updateView();
DEBUG_LOG(m_logger) << "Set visibility for object " << data.id() << " to " << (isVisibile ? "visible" : "invisible");
}
}
#else
{
bool isVisibile = isVisibleByExternal && bIsVisibleByFilter;
const bool bOldVisibility = mapObj->visibility();
if (bOldVisibility != isVisibile)
{
mapObj->setVisibility(isVisibile);
mapObj->updateView();
DEBUG_LOG(m_logger) << "Set visibility for object " << data.id() << " to " << (isVisibile ? "visible" : "invisible");
this->emit_visibilityHasChangedSignal();
}
}
#endif
return true;
}
virtual bool isVisibleByFilter(const DDS_TYPE &data) const
{
if (!m_displayFilter)
return true;
const auto es = data.effectStart().is_set() ? data.effectStart().get() : 0;
const auto partyId = data.partyId().is_set() ? data.partyId().get() : -1;
bool isVisibleByFilter = partyId > 0 ? FilterClass::m_currentSymbolSettings.symbolSettings.symbolPartyAppearance.value(partyId).isVisible : true;
if (isVisibleByFilter)
isVisibleByFilter = m_displayFilter->isVisible(Aes2SituationMapTraits<SUPER>::aesType,
data.effectStateId(),
data.chargeStruct().chargeTypeId(),
partyId,
data.isCentral(),
es,
data.effectDuration(),
m_pluginProvider->partitionTime());
return isVisibleByFilter;
}
protected:
virtual void onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType) override
{
if (Aes2SituationMapTraits<SUPER>::aesType != aesType.underlying())
return;
SUPER *derived = static_cast<SUPER*>(this);
const auto cb = [this](const DDS_TYPE &data) -> bool
{
if (data.isDeleted())
return false;
this->updateVisibility(data);
return false;
};
derived->iterateAesData(cb);
}
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override
{
if (FilterClass::m_currentSymbolSettings.symbolSettings.symbolPartyAppearance !=
newSas.symbolSettings.symbolPartyAppearance)
return true;
return (FilterClass::m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale);
}
void handleSymbolAppearanceSettings(RefPointer<MAP_TYPE> &mapObj) override
{
mapObj->setScale(FilterClass::m_currentSymbolSettings.symbolSettings.symbolScale);
}
void symbolAppearanceSettingsChangedPostOperation() override
{
TRACE_LOG(m_logger) << LOGFUNCTION << " symbolAppearanceSettingsChangedPostOperation START";
updateVisibility();
}
public:
virtual bool updateGeometry(const AreaEffectSimulation::AesItemView &data,
RefPointer<MAP_TYPE> mapObj)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START" << " data.aesTypeId()=" << data.aesTypeId()
<< ", m_debugInfo " << mapObj->debugInfo();
mapObj->setPositions(form2PosCont(data.form()));
if (!mapObj->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " aesItemId = " << data.aesItemId() << " updateView failed";
return true;
}
protected:
using BaseClass::m_simId2UniqueMapId;
using BaseClass::m_logger;
std::shared_ptr<AreaEffectSimulation::Interface::Dtc> m_aesDtc;
std::weak_ptr<AreaEffectSimulation::ForeignInfoGuiInterface> m_aesInfoIfc;
PluginProvider *m_pluginProvider = nullptr;
std::shared_ptr<FilterManagement::AesDisplayFilter> m_displayFilter;
std::function<bool(int32_t, bool&)> m_isVisibleByExternalCallback = nullptr;
#ifdef USE_OBJECTAPPEARANCE_VECTOR
QVector<ObjectAppearance> m_objectAppearanceVisibility;
#endif
};
}
@@ -0,0 +1,84 @@
#include "air_support_impact_to_map.h"
#include "pdm_handler.h"
#include <Map/bounding_box.h>
namespace SituationMap
{
AirSupportImpact2SituationMap::AirSupportImpact2SituationMap(PdmHandler *pdmHandler, ObjectFactory &objFac, const QString &layername, const char *loggerName)
: BaseClass(objFac, layername, loggerName)
, m_pdmHandler(pdmHandler)
{
}
bool AirSupportImpact2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (! m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::airSupportImpactChanged,
this, &AirSupportImpact2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->airSupportImpacts([this](const AreaEffectSimulation::AirSupportImpact & data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool AirSupportImpact2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
const int32_t simId = ddsData.id();
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
mapObj->setAesState(effectState2aesState(ddsData.effectStateId().underlying()));
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtAirSupportImpact, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtAirSupportImpact) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
const Core::GeoPosition2D &impactPos2D = ddsData.impactPosition();
mapObj->setImpactOrigin(Point3D(impactPos2D.lon(), impactPos2D.lat(), 0.0));
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,51 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/single_fire.h>
#include <QObject>
namespace SituationMap
{
class PdmHandler;
class AirSupportImpact2SituationMap;
template <>
struct Aes2SituationMapTraits<AirSupportImpact2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::AirSupportImpact;
using MAP_TYPE = SituationMap::SingleFire;
static const AreaEffectSimulation::AesType::type aesType = AreaEffectSimulation::AesType::AtAirSupportImpact;
};
class AirSupportImpact2SituationMap final : public Aes2SituationMap<AirSupportImpact2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<AirSupportImpact2SituationMap>;
using BaseClass::BaseClass;
AirSupportImpact2SituationMap(PdmHandler *pdmHandler,
ObjectFactory &objFac,
const QString &layername,
const char *loggerName);
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::AirSupportImpact &data)> &cb) const
{
return m_aesDtc->airSupportImpacts(cb);
}
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
PdmHandler *m_pdmHandler = nullptr;
};
}
@@ -0,0 +1,150 @@
#include "alarm_to_map.h"
#include <Map/object_factory.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <QPainter>
#include <sstream>
using namespace SituationMap;
QImage renderEmergencyCallSymbol()
{
int size = 200;
QImage image(size, size, QImage::Format_ARGB32);
image.fill(Qt::transparent);
QPainter painter(&image);
painter.setRenderHint(QPainter::Antialiasing);
QPen pen(Qt::white);
pen.setWidth(10);
painter.setPen(pen);
painter.setBrush(QBrush(Qt::red));
painter.drawEllipse(QPointF(image.rect().center()),
image.rect().width() * 0.45,
image.rect().height() * 0.45);
painter.setPen(QPen(Qt::white));
QFont font = painter.font();
font.setBold(true);
font.setPixelSize(75);
painter.setFont(font);
QPointF pos(image.width() * 0.125,
image.height() * 0.625);
painter.drawText(pos, QLatin1String("SOS"));
return image;
}
bool AlarmToMap::init(PluginProvider *pluginProvider)
{
if (!pluginProvider)
return false;
m_pluginProvider = pluginProvider;
DEBUG_LOG(m_logger) << LOGFUNCTION << " exerciseId=" << m_pluginProvider->exerciseId();
m_almDtc = m_pluginProvider->almDtc();
FilterClass::init(m_pluginProvider);
return true;
}
bool AlarmToMap::run()
{
DEBUG_LOG(m_logger) << "Starting to run";
this->stop();
if (m_almDtc)
{
connect(m_almDtc.get(), &AlarmManagement::Interface::Dtc::notificationChanged,
this, &AlarmToMap::handleChanged, Qt::UniqueConnection);
m_almDtc->notifications([this](const AlarmManagement::Notification & data)
{
handleChanged(data, DataModification::eAdded);
});
}
return true;
}
void AlarmToMap::stop()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << "Stopping";
if (m_almDtc)
m_almDtc->disconnect(this);
}
bool AlarmToMap::isElapsed(const Sim2SituationMap::DDS_T &data) const
{
DEBUG_LOG(m_logger) << " isElapsed";
if (data.eventType().underlying() != ProjectDataManagement::EventType_def::EmergencyCall)
return true;
return false;
}
int32_t AlarmToMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool AlarmToMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData, RefPointer<Sim2SituationMap::MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION
<< ", id " << ddsData.id();
mapObj->setPickable(false);
mapObj->setDrawOrder(-1);
mapObj->setIdentifier(QStringLiteral("SOS_%1").arg(ddsData.equipmentNumber()));
TextStyle textStyle;
textStyle.setSize(20);
textStyle.setTextColor(Qt::red);
textStyle.setTextOutlineColor(Qt::white);
textStyle.setTextOutlineWidth(5);
mapObj->setTextStyle(textStyle);
const Core::GeoPosition &geoPos = ddsData.position();
mapObj->setOrigin(Point3D(geoPos.lon(), geoPos.lat(), geoPos.z()));
mapObj->setProxyImage(renderEmergencyCallSymbol(), QSize(50, 50));
emit alarmUpdated(mapObj->identifier(), Point3D(geoPos.lon(), geoPos.lat(), geoPos.z()));
return true;
}
@@ -0,0 +1,63 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/AlarmManagement/alm_data_plugin_interface.h>
#include <MapObjects/geo_image.h>
namespace SituationMap
{
class AlarmToMap final : public Sim2SituationMap<AlarmManagement::Notification, SituationMap::GeoImage>
, protected DdsFilterHandling<SituationMap::GeoImage>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<AlarmManagement::Notification, SituationMap::GeoImage>;
using FilterClass = DdsFilterHandling<SituationMap::GeoImage>;
public:
AlarmToMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
, m_pluginProvider(nullptr)
{}
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override;
protected:
bool isElapsed(const Sim2SituationMap::DDS_T &data) const override;
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const DDS_T &ddsData, RefPointer<MAP_T> mapObj) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale);
}
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override
{
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
}
signals:
void alarmUpdated(const QString &name, const Point3D &geoPosition);
private:
PluginProvider *m_pluginProvider;
std::shared_ptr<AlarmManagement::Interface::Dtc> m_almDtc;
};
}
@@ -0,0 +1,106 @@
#include "bccontamination_to_map.h"
#include <ProjectDataManagement/pdm_dtc.h>
namespace SituationMap
{
bool BCContamination2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::bCContaminationChanged,
this, &BCContamination2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->bCContaminations([this](const AreaEffectSimulation::BCContamination &data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool BCContamination2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
else
{
mapObj->setLineStyle(LineStyle(Qt::yellow, 2));
mapObj->setFillStyle(FillStyle(Qt::yellow, FillPattern::Null));
}
mapObj->setAesState(effectState2aesState(ddsData.effectStateId().underlying()));
const int32_t simId = ddsData.id();
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtBCContamination, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtBCContamination) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
const Core::GeoPosition2D& impactPos2D = ddsData.impactPosition();
mapObj->setImpactOrigin(Point3D(impactPos2D.lon(), impactPos2D.lat(), 0.0));
if (ddsData.partyId().is_set())
{
int height = ddsData.upperOffset();
if (height > 0)
mapObj->setExtrusionHeight(height);
else
mapObj->setExtrusionHeight();
}
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,45 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/single_fire.h>
#include <QObject>
#include <memory>
namespace SituationMap
{
class BCContamination2SituationMap;
template <>
struct Aes2SituationMapTraits<BCContamination2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::BCContamination;
using MAP_TYPE = SituationMap::SingleFire;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtBCContamination;
};
class BCContamination2SituationMap final : public Aes2SituationMap<BCContamination2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<BCContamination2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::BCContamination &data)> &cb) const
{
return m_aesDtc->bCContaminations(cb);
}
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
};
}
@@ -0,0 +1,362 @@
#include "booby_traps_to_map.h"
#include <Map/object_factory.h>
#include <Map/map.h>
namespace SituationMap
{
bool BoobyTrap2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
return false;
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::boobyTrapChanged,
this, &BoobyTrap2SituationMap::handleChanged, Qt::UniqueConnection);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &BoobyTrap2SituationMap::onAesItemViewChanged, Qt::UniqueConnection);
m_aesDtc->boobyTraps([this](const AreaEffectSimulation::BoobyTrap &data)
{
handleChanged(data, DataModification::eAdded);
});
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
connect(m_pluginProvider, &PluginProvider::partitionTimeChanged,
this, &BoobyTrap2SituationMap::onPartitionTimeChanged, Qt::UniqueConnection);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
void BoobyTrap2SituationMap::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, " << " data.aesTypeId()=" << data.aesTypeId() << " modType=" << modType;
if (data.aesTypeId() != AreaEffectSimulation::AesType::AtBoobyTrapSecondary)
return;
if (modType == DataModification::eRemoved)
return;
const int32_t simId = data.aesItemId();
if (simId < 0)
return;
updateSecondary(simId);
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " data.aesTypeId()=" << data.aesTypeId() << " modType=" << modType;
}
void BoobyTrap2SituationMap::onPartitionTimeChanged(qint64 newPartitionTime)
{
updateAllDetonationSpheres(newPartitionTime);
}
void BoobyTrap2SituationMap::updateAllDetonationSpheres(qint64 newPartitionTime)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< ", m_simId2UniqueMapId.size = " << m_simId2UniqueMapId.size();
QMapIterator<int32_t, UniqueMapId> it(m_simId2UniqueMapId);
while (it.hasNext())
{
it.next();
const UniqueMapId uniqueMapId = it.value();
RefPointer<MAP_T> mapObj = m_objFac.get<MAP_T>(uniqueMapId);
if (!mapObj.valid())
continue;
const int simId = it.key();
const AreaEffectSimulation::BoobyTrap &boobyTrap = m_aesDtc->boobyTrap(simId);
if (boobyTrap.id() != simId)
continue;
if (updateDetonationSphere3D(mapObj, boobyTrap, newPartitionTime))
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " updateView failed";
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
}
bool BoobyTrap2SituationMap::updateDetonationSphere3D(RefPointer<Sim2SituationMap::MAP_T> mapObj, const AreaEffectSimulation::BoobyTrap &data, qint64 newPartitionTime)
{
const int32_t simId = data.id();
if (!mapObj)
return false;
bool bUpdateRequired = false;
const bool bDesiredNewState = data.triggered() && ((newPartitionTime - data.sampleTime() < 5000));
TRACE_LOG(m_logger) << LOGFUNCTION << ", START" << " simId = " << simId
<< ", sampleTime " << data.sampleTime()
<< ", bDesiredNewState " << bDesiredNewState;
#ifdef RENDERER_APPROACH
if (mapObj->has3DMarkerRenderer() && !bDesiredNewState)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << ", START REMOVE " << " simId = " << simId;
mapObj->set3DMarkerRenderer(Point3D(), QVariantMap());
bUpdateRequired = true;
}
else if (!mapObj->has3DMarkerRenderer() && bDesiredNewState)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << ", START ADD " << " simId = " << simId;
const Core::GeoPosition2D &geoPos = data.impactPosition();
Point3D markerOrigin(geoPos.lon(), geoPos.lat(), 0);
QVariantMap attribMap;
QString attribValue;
const QColor &majorColor = mapObj->majorColor();
attribValue = QString(QStringLiteral("Impact_Color_%1")).arg(majorColor.name());
attribMap.insert(QStringLiteral("IMPACT_COLOR"), attribValue);
double radius = std::max(data.impactRadius(), 10.0);
attribValue = QString(QStringLiteral("Impact_Radius_%1")).arg(radius);
attribMap.insert(QStringLiteral("IMPACT_RADIUS"), attribValue);
LayerFactory::UniqueValueDataAesCentral::TYPE type{LayerFactory::UniqueValueDataAesCentral::TYPE::SPHERE};
if (data.centralAngle().is_set())
type = LayerFactory::UniqueValueDataAesCentral::TYPE::CONE;
attribValue = QString(QStringLiteral("Impact_Type_%1")).arg(LayerFactory::toString(type));
attribMap.insert(QStringLiteral("IMPACT_TYPE"), attribValue);
int heading = 0;
if (data.rotationAngle().is_set())
heading = static_cast<int>(data.rotationAngle().get());
attribMap.insert(QStringLiteral("HEADING"), ((heading+90)%360));
attribMap.insert(QStringLiteral("PITCH"), 0);
attribMap.insert(QStringLiteral("ROLL"), 90);
mapObj->set3DMarkerRenderer(markerOrigin, attribMap);
bUpdateRequired = true;
}
#else
if (mapObj->has3DMarkerSceneSymbol() && !bDesiredNewState)
{
FATAL_LOG(m_logger) << LOGFUNCTION << ", START REMOVE " << " simId = " << simId;
mapObj->set3DMarkerSceneSymbol(Point3D(), {});
bUpdateRequired = true;
}
else if (!mapObj->has3DMarkerSceneSymbol() && bDesiredNewState)
{
FATAL_LOG(m_logger) << LOGFUNCTION << ", START ADD " << " simId = " << simId;
const Core::GeoPosition2D &geoPos = data.impactPosition();
Point3D markerOrigin(geoPos.lon(), geoPos.lat(), 0);
VirtualMine::SceneSymbolData ssData;
const QColor &majorColor = mapObj->majorColor();
ssData.color = majorColor;
ssData.radius = std::max(data.impactRadius(), 10.0);
ssData.cone = data.centralAngle().is_set();
int heading = 0;
if (data.rotationAngle().is_set())
heading = static_cast<int>(data.rotationAngle().get());
ssData.heading = (heading+90)%360;
ssData.pitch = 0.0;
ssData.roll = 90;
mapObj->set3DMarkerSceneSymbol(markerOrigin, ssData);
}
#endif
TRACE_LOG(m_logger) << LOGFUNCTION << ", END" << " simId = " << simId;
return bUpdateRequired;
}
bool BoobyTrap2SituationMap::updateSecondary(int32_t simId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << ", START" << " simId = " << simId;
if (simId < 0)
return false;
RefPointer<MAP_T> mapObj = this->getMapObjectOfSimId(simId);
if (!mapObj.valid())
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " getMapObjectOfSimId failed"
<< " simId = " << simId << " (maybe expired)";
return false;
}
AreaEffectSimulation::AesItemView dataAesItemView;
AreaEffectSimulation::BoobyTrap trap;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtBoobyTrapSecondary, dataAesItemView))
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " AesItemViewForSecondary found :-) ";
trap = m_aesDtc->boobyTrap(dataAesItemView.aesItemId());
} else {
ERROR_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " no AesItemViewForSecondary found. :-( ";
}
if ((dataAesItemView.aesItemId() == simId) &&
(trap.id() == simId) &&
trap.triggered())
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " setSubsidiaryLine";
VirtualMine::OptionalData optData;
optData.closed = true;
mapObj->setSubsidiaryLine(0,
form2PosCont(dataAesItemView.form()), optData);
} else {
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " removeSubsidiaryLine";
mapObj->removeSubsidiaryLine(0);
}
if (!mapObj->updateView()) {
ERROR_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " updateView failed";
return false;
}
TRACE_LOG(m_logger) << LOGFUNCTION << ", END" << " simId = " << simId
<< " trap.triggered(" << trap.triggered();
return true;
}
bool BoobyTrap2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
mapObj->setAesState(effectState2aesState(ddsData.effectStateId().underlying()));
const int32_t simId = ddsData.id();
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtBoobyTrap, itemView))
{
this->updateGeometry(itemView, mapObj);
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
updateDetonationSphere3D(mapObj, ddsData, m_pluginProvider->partitionTime());
}
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtBoobyTrap) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
updateSecondary(simId);
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool BoobyTrap2SituationMap::isVisibleByFilter(const DDS_TYPE &data) const
{
if (!m_displayFilter)
return true;
const auto es = data.effectStart().is_set() ? data.effectStart().get() : 0;
const auto partyId = data.partyId().is_set() ? data.partyId().get() : -1;
bool isVisibleByFilter = partyId > 0 ? FilterClass::m_currentSymbolSettings.symbolSettings.symbolPartyAppearance.value(partyId).isVisible : true;
if (isVisibleByFilter)
isVisibleByFilter = m_displayFilter->isVisible(AreaEffectSimulation::AesType_def::AtMineArea,
data.effectStateId(),
data.chargeStruct().chargeTypeId(),
partyId,
data.isCentral(),
es,
data.effectDuration(),
m_pluginProvider->partitionTime());
return isVisibleByFilter;
}
void BoobyTrap2SituationMap::onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType)
{
if ((AreaEffectSimulation::AesType_def::AtBoobyTrap != aesType.underlying()) &&
(AreaEffectSimulation::AesType_def::AtMineArea != aesType.underlying()))
return;
const auto cb = [this](const DDS_TYPE &data) -> bool
{
if (data.isDeleted())
return false;
this->updateVisibility(data);
return false;
};
iterateAesData(cb);
}
}
@@ -0,0 +1,61 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/virtual_mine.h>
#include <QObject>
namespace SituationMap
{
class BoobyTrap2SituationMap;
template <>
struct Aes2SituationMapTraits<BoobyTrap2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::BoobyTrap;
using MAP_TYPE = SituationMap::VirtualMine;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtBoobyTrap;
};
class BoobyTrap2SituationMap final : public Aes2SituationMap<BoobyTrap2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<BoobyTrap2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::BoobyTrap &data)> &cb) const
{
return m_aesDtc->boobyTraps(cb);
}
protected Q_SLOTS:
void onPartitionTimeChanged(qint64 newPartitionTime);
protected:
void updateAllDetonationSpheres(qint64 newPartitionTime);
protected Q_SLOTS:
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
protected:
bool updateDetonationSphere3D(RefPointer<MAP_T> mapObj, const AreaEffectSimulation::BoobyTrap &data, qint64 newPartitionTime);
bool updateSecondary(int32_t simId);
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool isVisibleByFilter(const DDS_TYPE &data) const override;
void onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType) override;
};
}
@@ -0,0 +1,79 @@
#include "borderline_to_map.h"
#include <Map/object_factory.h>
namespace SituationMap
{
bool Borderline2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
return false;
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::borderlineChanged,
this, &Borderline2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->borderlines([this](const AreaEffectSimulation::Borderline &data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool Borderline2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
LineStyle ls = mapObj->lineStyle();
ls.setLineWidth(2);
mapObj->setLineStyle(ls);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
const int32_t simId = ddsData.id();
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtBorderline, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtBorderline) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,53 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/polyline.h>
#include <QObject>
namespace SituationMap
{
class Borderline2SituationMap;
template <>
struct Aes2SituationMapTraits<Borderline2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::Borderline;
using MAP_TYPE = SituationMap::Polyline;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtBorderline;
};
class Borderline2SituationMap final : public Aes2SituationMap<Borderline2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<Borderline2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool isElapsed(const DDS_TYPE &ddsData) const override
{
return (ddsData.operatorId() > 0 && m_pluginProvider->operatorId() != ddsData.operatorId());
}
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::Borderline &data)> &cb) const
{
return m_aesDtc->borderlines(cb);
}
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
};
}
@@ -0,0 +1,659 @@
#include "building_contamination.h"
#include <Map/map.h>
#include <Map/object_factory.h>
#include <MapObjects/cube.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <MathUtils/simple_helper.h>
#include <functional>
#define USE_BUFFER_APPROACH
#ifdef USE_BUFFER_APPROACH
# include <arcgis/PolygonBuilder.h>
# include <arcgis/GeometryEngine.h>
#endif
namespace SituationMap
{
class BuildingContamination::Private
{
public:
explicit Private() = default;
~Private() = default;
QMap<int32_t, Buildings::BuildingState> m_buildingStateData;
Map *m_map = nullptr;
QMap<QPair<int, int>, UniqueMapId> m_bldgFlr2UniqueMapId;
bool m_visible = false;
int m_drawOrder = 0;
static QPair<int, int> createKey(int buildingId, int floorId)
{
return {buildingId, floorId};
}
static int buildingIdOfKey(const QPair<int, int> &keyData)
{
return keyData.first;
}
RefPointer<Cube> getCreateCube(int buildingId, int floorId)
{
const QPair<int, int> &key = createKey(buildingId, floorId);
const UniqueMapId uniqueMapId = m_bldgFlr2UniqueMapId.value(key, INVALID_MAP_ID);
if (!SituationMap::isUniqueMapIdValid(uniqueMapId))
{
const QString &layernameForCubes = m_map->layerFactory().layernameForCubes();
const QString &key_debugInfo = QStringLiteral("bldg_%1-flr%2").arg(buildingId).arg(floorId);
RefPointer<Cube> cube =
m_map->objectFactory().create<Cube>(layernameForCubes, key_debugInfo);
if (cube.valid())
m_bldgFlr2UniqueMapId[key] = cube->uniqueMapId();
return cube;
}
return m_map->objectFactory().get<Cube>(uniqueMapId);
}
void removeCube(int buildingId = -1)
{
QMutableMapIterator<QPair<int, int>, UniqueMapId> mapIt(m_bldgFlr2UniqueMapId);
while (mapIt.hasNext())
{
mapIt.next();
const QPair<int, int> &key = mapIt.key();
int curBuildingId = buildingIdOfKey(key);
if ((buildingId < 0) ||
(buildingId == curBuildingId)
)
{
UniqueMapId uMapId = mapIt.value();
SituationMap::AbstractMapObject *mapObj = m_map->objectFactory().idToMapObject(uMapId);
if (mapObj)
mapObj->removeMySelf();
mapIt.remove();
}
}
}
bool updateVisibility(int buildingId = -1)
{
bool success = true;
QMutableMapIterator<QPair<int, int>, UniqueMapId> mapIt(m_bldgFlr2UniqueMapId);
while (mapIt.hasNext())
{
mapIt.next();
const QPair<int, int> &key = mapIt.key();
int curBuildingId = buildingIdOfKey(key);
if ((buildingId < 0) ||
(buildingId == curBuildingId)
)
{
UniqueMapId uMapId = mapIt.value();
SituationMap::AbstractMapObject *mapObj = m_map->objectFactory().idToMapObject(uMapId);
if (mapObj)
{
mapObj->setVisibility(m_visible);
if (!mapObj->updateView())
success = false;
}
}
}
return success;
}
};
BuildingContamination::BuildingContamination(int drawOrder, QObject *parent)
: BaseClass(parent)
, m_logger(getLogger("BuildingContamination"))
, d(new Private())
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->m_drawOrder = drawOrder;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
BuildingContamination::~BuildingContamination()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
this->stop();
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool BuildingContamination::init(Map *map, PluginProvider *pluginProvider)
{
d->m_map = map;
if (!d->m_map)
return false;
if (!pluginProvider ||
!pluginProvider->cesDtc() ||
!pluginProvider->ismDtc())
return false;
m_bldDtc = pluginProvider->bldDtc();
m_ismDtc = pluginProvider->ismDtc();
return true;
}
void BuildingContamination::removeAllObjects()
{
d->removeCube();
}
bool BuildingContamination::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!d->m_map)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_map";
return false;
}
if (!m_bldDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_bldDtc";
return false;
}
m_bldDtc->disconnect(this);
qRegisterMetaType<Buildings::BuildingState>("Buildings::BuildingState");
connect(m_bldDtc.get(), &Buildings::Interface::Dtc::buildingStateChanged,
this, &BuildingContamination::onBuildingStateChanged, Qt::QueuedConnection);
m_bldDtc->buildingStates([this](const Buildings::BuildingState & data)
{
onBuildingStateChanged(data, DataModification::eAdded);
});
if (false)
{
std::function<void(int, int, int)> fTriggerBuilding = [this](int partyId, int buildingId, int floorId)
{
const PositionCont &absPositionsGeo = retrieveBuildingGeometry(buildingId, floorId);
QMap<int, double> floorHeights = retrieveBuildingAbsHeight(buildingId);
RefPointer<Cube> cube = d->getCreateCube(buildingId, floorId);
if (!cube)
ERROR_LOG(m_logger) << LOGFUNCTION << " no cube created";
cube->setVisibility(d->m_visible);
cube->setDrawOrder(d->m_drawOrder);
cube->setPartyId(partyId);
cube->setPositions(absPositionsGeo);
const double height = floorHeights.value(floorId, 2.5 * floorId);
cube->setHeight(height);
bool success = cube->updateView();
INFO_LOG(m_logger) << LOGFUNCTION << " cube->updateView " << success;
};
fTriggerBuilding(24, 5, 1);
fTriggerBuilding(-1, 5, 2);
fTriggerBuilding(89, 5, 3);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void BuildingContamination::stop()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_bldDtc->disconnect(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool BuildingContamination::isVisible() const
{
return d->m_visible;
}
bool BuildingContamination::setVisible(bool visible)
{
d->m_visible = visible;
bool succ = d->updateVisibility();
return succ;
}
void BuildingContamination::onBuildingStateChanged(const Buildings::BuildingState &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
const int buildingId = data.id();
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
updateBuilding(buildingId);
break;
case DataModification::eRemoved:
d->removeCube(buildingId);
break;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void BuildingContamination::onResetBuildingState()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->removeCube();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void BuildingContamination::updateBuilding(int buildingId)
{
DEBUG_LOG(m_logger) << "update Building " << buildingId;
const Buildings::BuildingState &bos = m_bldDtc->buildingState(buildingId);
d->m_buildingStateData[buildingId] = bos;
const auto contaminations = bos.contaminationStates();
DEBUG_LOG(m_logger) << "Statecount " << contaminations.size();
QSet<int> contaminatedFloors;
for (const Buildings::ContaminationState &contaminationState : contaminations)
{
QSet<int> rooms;
for (const auto &room : contaminationState.rooms())
{
rooms.insert(room);
}
DEBUG_LOG(m_logger) << "contaminated rooms " << rooms.size();
for (int room : rooms)
{
int floorIdContamination = findFloorIdByRoomId(room);
if ( floorIdContamination == -1)
continue;
contaminatedFloors.insert(floorIdContamination);
}
}
DEBUG_LOG(m_logger) << "contaminated floors " << contaminatedFloors.size();
QMap<int, double> floorHeights = retrieveBuildingAbsHeight(buildingId);
QMapIterator<int, double> mapIt(floorHeights);
int floorCounter = 0;
while (mapIt.hasNext())
{
mapIt.next();
const int floorId = mapIt.key();
const double height = mapIt.value();
const bool isContaminaed = contaminatedFloors.contains(floorId);
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " floorId=" << floorId
<< " height=" << height
<< " partyId=" << isContaminaed;
const PositionCont &absPositionsGeo = retrieveBuildingGeometry(buildingId, ++floorCounter);
RefPointer<Cube> cube = d->getCreateCube(buildingId, floorId);
cube->setVisibility(d->m_visible);
cube->setDrawOrder(d->m_drawOrder);
cube->setPartyId(-1);
if(isContaminaed)
{
cube->setPartyId(-2);
QColor col(Qt::yellow);
cube->setForceMajorColor(col.name());
}
cube->setPositions(absPositionsGeo);
cube->setHeight(height);
if (!cube->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " cube->updateView() failed";
}
}
int BuildingContamination::findFloorIdByRoomId(int roomId) noexcept(false)
{
auto roomToFloorCache = m_roomToFloorCache.constFind(roomId);
if (roomToFloorCache != m_roomToFloorCache.constEnd())
{
return roomToFloorCache.value();
}
InfrastructureManagement::StructureElement roomSe;
if (!m_ismDtc->getStructureElementById(roomId, roomSe))
{
ERROR_LOG(m_logger) << "getStructureElementById roomId=" << roomId << " not found";
return -1;
}
const std::vector<int32_t> path = roomSe.path();
for (const int parentSeId : path)
{
InfrastructureManagement::StructureElement parentSe;
if (!getRoom(parentSeId, parentSe))
continue;
if (parentSe.structureElementTypeId().underlying() != InfrastructureManagement::StructureElementType_def::Floor)
continue;
m_roomToFloorCache.insert(roomId, parentSeId);
return parentSeId;
}
throw QStringLiteral("findFloorId: floor id for room %1 not found").arg(roomSe.id());
}
bool BuildingContamination::getRoom(int roomSeId, InfrastructureManagement::StructureElement &roomSe)
{
auto it = m_roomStructureElementCache.find(roomSeId);
if (it != m_roomStructureElementCache.end())
{
roomSe = *it;
return true;
}
if (m_ismDtc->getStructureElementById(roomSeId, roomSe))
{
m_roomStructureElementCache.insert(roomSeId, roomSe);
return true;
}
return false;
}
PositionCont BuildingContamination::retrieveBuildingGeometry(int buildingId, int floorId) const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " buildingId=" << buildingId
<< " floorId=" << floorId;
if (!m_ismDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_ismDtc";
return PositionCont();
}
QVector<QPointF> relPositions;
{
const InfrastructureManagement::MainFootprint &mainFootprint = m_ismDtc->mainFootprint(buildingId);
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " mainFootprint.elements().size()=" << mainFootprint.elements().size();
relPositions.reserve(mainFootprint.elements().size());
for (const InfrastructureManagement::FootprintElement &element : mainFootprint.elements())
{
const auto &relPos = element.relPosition();
relPositions += QPointF(relPos.offsetX(), relPos.offsetY());
}
}
#ifndef USE_BUFFER_APPROACH
{
const double distance = 0.5 + (100 - floorId) * 0.01;
const QPolygonF &massPoly = relPositions.toVector();
const QPointF &massCenterPoint = massPoly.boundingRect().center();
const double massCenterPointX = massCenterPoint.x();
const double massCenterPointY = massCenterPoint.y();
QMutableListIterator<QPointF> listIt(relPositions);
while (listIt.hasNext())
{
QPointF &relPosition = listIt.next();
if (relPosition.x() < massCenterPointX)
relPosition.rx() -= distance;
else
relPosition.rx() += distance;
if (relPosition.y() < massCenterPointY)
relPosition.ry() -= distance;
else
relPosition.ry() += distance;
}
}
#endif
PositionCont absPositionsGeo;
const InfrastructureManagement::MainStructureElement &mse = m_ismDtc->mainStructureElement(buildingId);
const Core::GeoPosition &geoPosition = mse.geoPosition();
const QPointF &referencePointGeo = QPointF(geoPosition.lon(), geoPosition.lat());
const LtsCoordTrans::UtmCoordinate &referencePointUTM = LtsCoordTrans::UtmCoordinate::fromGeographic(referencePointGeo);
const double angleRad = mse.angle() * LtsCoordTrans::deg2rad();
const QPointF center;
absPositionsGeo.reserve(relPositions.size());
for (const auto &relPosition : qAsConst(relPositions))
{
const QPointF &relPositionRotate = MathUtils::rotate(relPosition, center, angleRad);
const QPointF &pGeo = referencePointUTM.geographic(relPositionRotate);
absPositionsGeo.append(Point3D::fromQPointF(pGeo));
}
#ifdef USE_BUFFER_APPROACH
{
const double distance = (100 - floorId) * 0.01;
Esri::ArcGISRuntime::PolygonBuilder polygonBuilder(Esri::ArcGISRuntime::SpatialReference::wgs84());
constexpr double rad2deg = LtsCoordTrans::rad2deg();
for (const Point3D &point : qAsConst(absPositionsGeo))
polygonBuilder.addPoint(Esri::ArcGISRuntime::Point(point.x() * rad2deg,
point.y() * rad2deg,
point.z()));
const Esri::ArcGISRuntime::Geometry &esriGeometry = polygonBuilder.toGeometry();
const Esri::ArcGISRuntime::Polygon &polyline =
Esri::ArcGISRuntime::GeometryEngine::bufferGeodetic(esriGeometry,
distance,
Esri::ArcGISRuntime::LinearUnitId::Meters,
0.1,
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic);
if (polyline.parts().isEmpty())
return absPositionsGeo;
const Esri::ArcGISRuntime::ImmutablePart &immutablePart = polyline.parts().part(0);
const Esri::ArcGISRuntime::ImmutablePointCollection &pointCollection = immutablePart.points();
const int size = pointCollection.size();
INFO_LOG(m_logger) << " pointCollection.size = " << pointCollection.size()
<< " - buildingId = " << buildingId
<< ", mse.name = " << mse.name();
absPositionsGeo.clear();
absPositionsGeo.reserve(size);
for (const Esri::ArcGISRuntime::Point &esriP : pointCollection)
{
absPositionsGeo.append(Point3D(esriP.x() * LtsCoordTrans::deg2rad(),
esriP.y() * LtsCoordTrans::deg2rad(),
esriP.z()));
}
}
#endif
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return absPositionsGeo;
}
QMap<int, double> BuildingContamination::retrieveBuildingAbsHeight(int buildingId) const
{
QMap<int, double> floorHeights;
const InfrastructureManagement::MainStructureElement &mse = m_ismDtc->mainStructureElement(buildingId);
for (const InfrastructureManagement::StructureElement &element : mse.elements())
{
if (element.structureElementTypeId() != InfrastructureManagement::StructureElementType::Floor)
continue;
const int floorId = element.id();
double height = element.geoPosition().z();
floorHeights[floorId] = height;
}
{
QMutableMapIterator<int, double> mapIt(floorHeights);
while (mapIt.hasNext())
{
QMap<int, double>::iterator curFloor = mapIt.next();
if (mapIt.hasNext())
{
QMap<int, double>::iterator upperFloor = mapIt.peekNext();
curFloor.value() = upperFloor.value();
}
else
curFloor.value() += 2.0;
}
}
return floorHeights;
}
}
@@ -0,0 +1,85 @@
#pragma once
#include "plugin_provider.h"
#include <Map/situation_map_types.h>
#include <Common/situation_map_logging.h>
#include <Plugins/Buildings/bld_data_plugin_interface.h>
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <QObject>
#include <QMap>
namespace SituationMap
{
class Map;
class BuildingContamination : public QObject
{
Q_OBJECT
using BaseClass = QObject;
public:
explicit BuildingContamination(int drawOrder, QObject *parent = nullptr);
~BuildingContamination();
bool init(Map *map, PluginProvider *pluginProvider);
void clearInterfaces();
void removeAllObjects();
void clearObjects() { removeAllObjects(); }
bool run();
void stop();
bool isVisible() const;
bool setVisible(bool visible);
Q_SIGNALS:
protected Q_SLOTS:
void onBuildingStateChanged(const Buildings::BuildingState &data, DataModification modType);
void onResetBuildingState();
protected:
void updateBuilding(int buildingId);
int findFloorIdByRoomId(int roomId);
bool getRoom(int roomSeId, InfrastructureManagement::StructureElement &roomSe);
PositionCont retrieveBuildingGeometry(int buildingId, int floorId) const;
QMap<int, double> retrieveBuildingAbsHeight(int buildingId) const;
private:
LOGGER_T m_logger;
QMap<int , int > m_roomToFloorCache;
QMap<int , InfrastructureManagement::StructureElement > m_roomStructureElementCache;
class Private;
Private *d = nullptr;
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
};
}
@@ -0,0 +1,657 @@
#include "building_ownership.h"
#include <Map/map.h>
#include <Map/object_factory.h>
#include <MapObjects/cube.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <MathUtils/simple_helper.h>
#include <unordered_map>
#include <functional>
#define USE_BUFFER_APPROACH
#ifdef USE_BUFFER_APPROACH
# include <arcgis/PolygonBuilder.h>
# include <arcgis/GeometryEngine.h>
#endif
namespace SituationMap
{
class BuildingGeometryCache
{
struct KEY_T
{
KEY_T(int buildingId = -1, int floorId = -1)
: m_buildingId(buildingId), m_floorId(floorId)
{}
int m_buildingId{-1};
int m_floorId{-1};
bool operator<(const KEY_T &other) const
{
return m_buildingId < other.m_buildingId
|| ((m_buildingId == other.m_buildingId) && (m_floorId < other.m_floorId));
}
};
public:
BuildingGeometryCache() = default;
~BuildingGeometryCache() = default;
void init(BuildingOwnership *buildingOwnership)
{
m_buildingOwnership = buildingOwnership;
}
PositionCont retrieveBuildingGeometry(int buildingId, int floorId) const
{
const KEY_T key(buildingId, floorId);
loadGeometry(key);
return m_cacheGeometry[key];
};
QMap<int, double> retrieveBuildingAbsHeight(int buildingId) const
{
loadAbsHeight(buildingId);
return m_cacheAbsHeight[buildingId];
};
private:
void loadGeometry(const KEY_T &key) const
{
if (m_cacheGeometry.contains(key))
return;
m_cacheGeometry[key] = m_buildingOwnership->retrieveBuildingGeometryInternal(key.m_buildingId, key.m_floorId);
}
void loadAbsHeight(int buildingId) const
{
if (m_cacheAbsHeight.contains(buildingId))
return;
m_cacheAbsHeight[buildingId] = m_buildingOwnership->retrieveBuildingAbsHeightInternal(buildingId);
}
private:
BuildingOwnership *m_buildingOwnership{nullptr};
mutable QMap<KEY_T, PositionCont> m_cacheGeometry;
mutable QMap<int, QMap<int, double>> m_cacheAbsHeight;
};
class BuildingOwnership::Private
{
public:
explicit Private() = default;
~Private() = default;
QMap<int32_t, CentralEffectSimulation::BuildingOwnership> m_ownershipData;
BuildingGeometryCache m_buildingGeometryCache;
Map *m_map = nullptr;
QMap<QPair<int, int>, UniqueMapId> m_bldgFlr2UniqueMapId;
bool m_visible = false;
int m_drawOrder = 0;
static QPair<int, int> createKey(int buildingId, int floorId)
{
return {buildingId, floorId};
}
static int buildingIdOfKey(const QPair<int, int> &keyData)
{
return keyData.first;
}
RefPointer<Cube> getCreateCube(int buildingId, int floorId)
{
const QPair<int, int> &key = createKey(buildingId, floorId);
const UniqueMapId uniqueMapId = m_bldgFlr2UniqueMapId.value(key, INVALID_MAP_ID);
if (!SituationMap::isUniqueMapIdValid(uniqueMapId))
{
const QString &layernameForCubes = m_map->layerFactory().layernameForCubes();
const QString &key_debugInfo = QStringLiteral("bldg_%1-flr%2").arg(buildingId).arg(floorId);
RefPointer<Cube> cube =
m_map->objectFactory().create<Cube>(layernameForCubes, key_debugInfo);
if (cube.valid())
m_bldgFlr2UniqueMapId[key] = cube->uniqueMapId();
return cube;
}
return m_map->objectFactory().get<Cube>(uniqueMapId);
}
void removeCube(int buildingId = -1)
{
QMutableMapIterator<QPair<int, int>, UniqueMapId> mapIt(m_bldgFlr2UniqueMapId);
while (mapIt.hasNext())
{
mapIt.next();
const QPair<int, int> &key = mapIt.key();
int curBuildingId = buildingIdOfKey(key);
if ((buildingId < 0) ||
(buildingId == curBuildingId)
)
{
UniqueMapId uMapId = mapIt.value();
SituationMap::AbstractMapObject *mapObj = m_map->objectFactory().idToMapObject(uMapId);
if (mapObj)
mapObj->removeMySelf();
mapIt.remove();
}
}
}
bool updateVisibility(int buildingId = -1)
{
bool success = true;
QMutableMapIterator<QPair<int, int>, UniqueMapId> mapIt(m_bldgFlr2UniqueMapId);
while (mapIt.hasNext())
{
mapIt.next();
const QPair<int, int> &key = mapIt.key();
int curBuildingId = buildingIdOfKey(key);
if ((buildingId < 0) ||
(buildingId == curBuildingId)
)
{
UniqueMapId uMapId = mapIt.value();
SituationMap::AbstractMapObject *mapObj = m_map->objectFactory().idToMapObject(uMapId);
if (mapObj)
{
mapObj->setVisibility(m_visible);
if (!mapObj->updateView())
success = false;
}
}
}
return success;
}
};
BuildingOwnership::BuildingOwnership(int drawOrder, QObject *parent)
: BaseClass(parent)
, m_logger(getLogger("BuildingOwnership"))
, d(new Private())
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->m_drawOrder = drawOrder;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
BuildingOwnership::~BuildingOwnership()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
this->stop();
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool BuildingOwnership::init(Map *map, PluginProvider *pluginProvider)
{
d->m_map = map;
if (!d->m_map)
return false;
if (!pluginProvider ||
!pluginProvider->cesDtc() ||
!pluginProvider->ismDtc())
return false;
m_cesDtc = pluginProvider->cesDtc();
m_ismDtc = pluginProvider->ismDtc();
d->m_buildingGeometryCache.init(this);
return true;
}
void BuildingOwnership::removeAllObjects()
{
d->removeCube();
}
bool BuildingOwnership::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!d->m_map)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_map";
return false;
}
if (!m_cesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_cesDtc";
return false;
}
m_cesDtc->disconnect(this);
qRegisterMetaType<CentralEffectSimulation::BuildingOwnership>("CentralEffectSimulation::BuildingOwnership");
connect(m_cesDtc.get(), &CentralEffectSimulation::Interface::Dtc::buildingOwnershipChanged,
this, &BuildingOwnership::onBuildingOwnershipChanged, Qt::QueuedConnection);
m_cesDtc->buildingOwnerships([this](const CentralEffectSimulation::BuildingOwnership & data)
{
onBuildingOwnershipChanged(data, DataModification::eAdded);
});
if (false)
{
std::function<void(int, int, int)> fTriggerBuilding = [this](int partyId, int buildingId, int floorId)
{
const PositionCont &absPositionsGeo = retrieveBuildingGeometry(buildingId, floorId);
QMap<int, double> floorHeights = retrieveBuildingAbsHeight(buildingId);
RefPointer<Cube> cube = d->getCreateCube(buildingId, floorId);
if (!cube)
ERROR_LOG(m_logger) << LOGFUNCTION << " no cube created";
cube->setVisibility(d->m_visible);
cube->setDrawOrder(d->m_drawOrder);
cube->setPartyId(partyId);
cube->setPositions(absPositionsGeo);
const double height = floorHeights.value(floorId, 2.5 * floorId);
cube->setHeight(height);
bool success = cube->updateView();
INFO_LOG(m_logger) << LOGFUNCTION << " cube->updateView " << success;
};
fTriggerBuilding(24, 5, 1);
fTriggerBuilding(-1, 5, 2);
fTriggerBuilding(89, 5, 3);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void BuildingOwnership::stop()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_cesDtc->disconnect(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool BuildingOwnership::isVisible() const
{
return d->m_visible;
}
bool BuildingOwnership::setVisible(bool visible)
{
d->m_visible = visible;
bool succ = d->updateVisibility();
return succ;
}
void BuildingOwnership::onBuildingOwnershipChanged(const CentralEffectSimulation::BuildingOwnership &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
const int buildingId = data.buildingId();
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
updateBuilding(buildingId);
break;
case DataModification::eRemoved:
d->removeCube(buildingId);
break;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void BuildingOwnership::onResetBuildingOwnership()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->removeCube();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void BuildingOwnership::updateBuilding(int buildingId)
{
const CentralEffectSimulation::BuildingOwnership &bos = m_cesDtc->buildingOwnership(buildingId);
d->m_ownershipData[buildingId] = bos;
const auto &ownerships = bos.ownerships();
QMap<int, int> floor2Party;
for (const CentralEffectSimulation::Ownership &ownership : ownerships)
if (ownership.partyId() > 0)
floor2Party[ownership.floorId()] = ownership.partyId();
const QMap<int, double> &floorHeights = retrieveBuildingAbsHeight(buildingId);
QMapIterator<int, double> mapIt(floorHeights);
int floorCounter = 0;
while (mapIt.hasNext())
{
mapIt.next();
const int floorId = mapIt.key();
const double height = mapIt.value();
const int partyId = floor2Party.value(floorId, -1);
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " floorId=" << floorId
<< " height=" << height
<< " partyId=" << partyId;
const PositionCont &absPositionsGeo = retrieveBuildingGeometry(buildingId, ++floorCounter);
RefPointer<Cube> cube = d->getCreateCube(buildingId, floorId);
cube->setVisibility(d->m_visible);
cube->setDrawOrder(d->m_drawOrder);
cube->setPartyId(partyId);
cube->setPositions(absPositionsGeo);
cube->setHeight(height);
if (!cube->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " cube->updateView() failed";
}
}
PositionCont BuildingOwnership::retrieveBuildingGeometry(int buildingId, int floorId) const
{
return d->m_buildingGeometryCache.retrieveBuildingGeometry(buildingId, floorId);
}
PositionCont BuildingOwnership::retrieveBuildingGeometryInternal(int buildingId, int floorId) const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " buildingId=" << buildingId
<< " floorId=" << floorId;
if (!m_ismDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_ismDtc";
return PositionCont();
}
QVector<QPointF> relPositions;
{
const InfrastructureManagement::MainFootprint &mainFootprint = m_ismDtc->mainFootprint(buildingId);
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " mainFootprint.elements().size()=" << mainFootprint.elements().size();
relPositions.reserve(mainFootprint.elements().size());
const auto &fpElements = mainFootprint.elements();
for (const InfrastructureManagement::FootprintElement &element : fpElements)
{
const auto &relPos = element.relPosition();
relPositions += QPointF(relPos.offsetX(), relPos.offsetY());
}
}
#ifndef USE_BUFFER_APPROACH
{
const double distance = 0.5 + (100 - floorId) * 0.01;
const QPolygonF &massPoly = relPositions.toVector();
const QPointF &massCenterPoint = massPoly.boundingRect().center();
const double massCenterPointX = massCenterPoint.x();
const double massCenterPointY = massCenterPoint.y();
QMutableListIterator<QPointF> listIt(relPositions);
while (listIt.hasNext())
{
QPointF &relPosition = listIt.next();
if (relPosition.x() < massCenterPointX)
relPosition.rx() -= distance;
else
relPosition.rx() += distance;
if (relPosition.y() < massCenterPointY)
relPosition.ry() -= distance;
else
relPosition.ry() += distance;
}
}
#endif
PositionCont absPositionsGeo;
const InfrastructureManagement::MainStructureElement &mse = m_ismDtc->mainStructureElement(buildingId);
const Core::GeoPosition &geoPosition = mse.geoPosition();
const QPointF &referencePointGeo = QPointF(geoPosition.lon(), geoPosition.lat());
const LtsCoordTrans::UtmCoordinate referencePointUTM = LtsCoordTrans::UtmCoordinate::fromGeographic(referencePointGeo);
const double angleRad = mse.angle() * LtsCoordTrans::deg2rad();
const QPointF center;
absPositionsGeo.reserve(relPositions.size());
for (const auto &relPosition : qAsConst(relPositions))
{
const QPointF &relPositionRotate = MathUtils::rotate(relPosition, center, angleRad);
const QPointF &pGeo = referencePointUTM.geographic(relPositionRotate);
absPositionsGeo.append(Point3D::fromQPointF(pGeo));
}
#ifdef USE_BUFFER_APPROACH
{
const double distance = (100 - floorId) * 0.01;
Esri::ArcGISRuntime::PolygonBuilder polygonBuilder(Esri::ArcGISRuntime::SpatialReference::wgs84());
constexpr double rad2deg = LtsCoordTrans::rad2deg();
for (const Point3D &point : qAsConst(absPositionsGeo))
polygonBuilder.addPoint(Esri::ArcGISRuntime::Point(point.x() * rad2deg,
point.y() * rad2deg,
point.z()));
const Esri::ArcGISRuntime::Geometry &esriGeometry = polygonBuilder.toGeometry();
const Esri::ArcGISRuntime::Polygon polyline =
Esri::ArcGISRuntime::GeometryEngine::bufferGeodetic(esriGeometry,
distance,
Esri::ArcGISRuntime::LinearUnitId::Meters,
0.1,
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic);
if (polyline.parts().isEmpty())
return absPositionsGeo;
const Esri::ArcGISRuntime::ImmutablePart &immutablePart = polyline.parts().part(0);
const Esri::ArcGISRuntime::ImmutablePointCollection &pointCollection = immutablePart.points();
const int size = pointCollection.size();
absPositionsGeo.clear();
absPositionsGeo.reserve(size);
for (const Esri::ArcGISRuntime::Point &esriP : pointCollection)
{
absPositionsGeo.append(Point3D(esriP.x() * LtsCoordTrans::deg2rad(),
esriP.y() * LtsCoordTrans::deg2rad(),
esriP.z()));
}
}
#endif
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return absPositionsGeo;
}
QMap<int, double> BuildingOwnership::retrieveBuildingAbsHeight(int buildingId) const
{
return d->m_buildingGeometryCache.retrieveBuildingAbsHeight(buildingId);
}
QMap<int, double> BuildingOwnership::retrieveBuildingAbsHeightInternal(int buildingId) const
{
QMap<int, double> floorHeights;
const InfrastructureManagement::MainStructureElement &mse = m_ismDtc->mainStructureElement(buildingId);
for (const InfrastructureManagement::StructureElement &element : mse.elements())
{
if (element.structureElementTypeId() != InfrastructureManagement::StructureElementType::Floor)
continue;
const int floorId = element.id();
double height = element.geoPosition().z();
floorHeights[floorId] = height;
}
{
QMutableMapIterator<int, double> mapIt(floorHeights);
while (mapIt.hasNext())
{
QMap<int, double>::iterator curFloor = mapIt.next();
if (mapIt.hasNext())
{
QMap<int, double>::iterator upperFloor = mapIt.peekNext();
curFloor.value() = upperFloor.value();
}
else
curFloor.value() += 2.0;
}
}
return floorHeights;
}
}
@@ -0,0 +1,84 @@
#pragma once
#include "plugin_provider.h"
#include <Map/situation_map_types.h>
#include <Common/situation_map_logging.h>
#include <Plugins/CentralEffectSimulation/ces_data_plugin_interface.h>
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <QObject>
#include <QMap>
namespace SituationMap
{
class Map;
class BuildingOwnership : public QObject
{
Q_OBJECT
using BaseClass = QObject;
public:
explicit BuildingOwnership(int drawOrder, QObject *parent = nullptr);
~BuildingOwnership();
bool init(Map *map, PluginProvider *pluginProvider);
void clearInterfaces();
void removeAllObjects();
void clearObjects() { removeAllObjects(); }
bool run();
void stop();
bool isVisible() const;
bool setVisible(bool visible);
Q_SIGNALS:
protected Q_SLOTS:
void onBuildingOwnershipChanged(const CentralEffectSimulation::BuildingOwnership &data, DataModification modType);
void onResetBuildingOwnership();
protected:
friend class BuildingGeometryCache;
void updateBuilding(int buildingId);
PositionCont retrieveBuildingGeometry(int buildingId, int floorId) const;
PositionCont retrieveBuildingGeometryInternal(int buildingId, int floorId) const;
QMap<int, double> retrieveBuildingAbsHeight(int buildingId) const;
QMap<int, double> retrieveBuildingAbsHeightInternal(int buildingId) const;
private:
LOGGER_T m_logger;
class Private;
Private *d = nullptr;
std::shared_ptr<CentralEffectSimulation::Interface::Dtc> m_cesDtc;
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
};
}
@@ -0,0 +1,435 @@
#include "buildinghitlineinfo_to_map.h"
#include "pdm_handler.h"
#include <Map/object_factory.h>
#include <QTimer>
#include <QJsonObject>
#include <QJsonDocument>
namespace SituationMap
{
BuildingHitlineInfo2SituationMap::BuildingHitlineInfo2SituationMap(PdmHandler *pdmHandler,
Participant2SituationMap *participant2SituationMap,
ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
, m_pdmHandler(pdmHandler)
, m_participant2SituationMap(participant2SituationMap)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
BuildingHitlineInfo2SituationMap::~BuildingHitlineInfo2SituationMap()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
int32_t BuildingHitlineInfo2SituationMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool BuildingHitlineInfo2SituationMap::init(PluginProvider *pluginProvider)
{
if (!pluginProvider ||
!pluginProvider->bldDtc())
return false;
m_pluginProvider = pluginProvider;
m_bldDtc = pluginProvider->bldDtc();
m_bldBuildingInfoIfc = pluginProvider->bldInfoIfc();
m_ismDtc = pluginProvider->ismDtc();
if (!m_bldDtc)
return false;
if (!m_ismDtc)
return false;
FilterClass::init(m_pluginProvider);
connect(m_pluginProvider, &PluginProvider::partitionTimeChanged,
this, &BuildingHitlineInfo2SituationMap::onPartitionTimeChanged);
m_exerciseId = m_pluginProvider->exerciseId();
m_buildingHeight.clear();
m_ismDtc->waitForHistoricalDataMainStructureElement(5000);
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
this, &BuildingHitlineInfo2SituationMap::onMainStructureElementChanged);
m_ismDtc->mainStructureElements([this](const InfrastructureManagement::MainStructureElement & data)
{
onMainStructureElementChanged(data, DataModification::eAdded);
});
return true;
}
bool BuildingHitlineInfo2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_bldDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_bldDtc.get(), &Buildings::Interface::Dtc::buildingHitLineInfoChanged,
this, &BuildingHitlineInfo2SituationMap::onBuildingHitLineInfoChanged);
m_bldDtc->buildingHitLineInfos([this](const Sim2SituationMap::DDS_T & ddsData)
{
onBuildingHitLineInfoChanged(ddsData, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void BuildingHitlineInfo2SituationMap::stop()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (m_bldDtc)
m_bldDtc->disconnect(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool BuildingHitlineInfo2SituationMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
if (!m_bldBuildingInfoIfc)
return false;
const QVector<qint32> &hitLineIds = uniqueMapIds2SimIds(uniqueMapIds);
if (hitLineIds.isEmpty())
return true;
m_bldBuildingInfoIfc->showHitLineInfoWindow(hitLineIds);
return true;
}
QString BuildingHitlineInfo2SituationMap::chargeTypeIdentifier(const int32_t originatorChargeTypeId) const
{
if (!m_pdmHandler)
return QStringLiteral("ctId_%1").arg(originatorChargeTypeId);
QString chargeTypeString = m_pdmHandler->trChargeTypeShortName(originatorChargeTypeId);
if (chargeTypeString.isEmpty())
return QStringLiteral("ctId_%1").arg(originatorChargeTypeId);
return chargeTypeString;
}
bool BuildingHitlineInfo2SituationMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_bldDtc)
return false;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
RefPointer<MAP_T> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_image = mapObj->previewImage();
const auto cb = [this, simIdOut, &umodOut](const Sim2SituationMap::DDS_T & ddsData) -> bool
{
if (ddsData.id() == simIdOut)
{
umodOut.m_partyId = ddsData.originatorPartyId();
const int32_t originatorChargeTypeId = ddsData.chargeTypeId();
umodOut.m_description1 = chargeTypeIdentifier(originatorChargeTypeId);
return true;
}
return false;
};
std::function<bool(const Sim2SituationMap::DDS_T &ddsData)> cb1 = cb;
return m_bldDtc->buildingHitLineInfos(cb1);
}
bool BuildingHitlineInfo2SituationMap::onBuildingHitLineInfoChanged(const Sim2SituationMap::DDS_T &ddsData,
DataModification modType)
{
const bool bIsValid = !isElapsed(ddsData);
if (bIsValid)
updateDdsDataContainer(ddsData, modType);
return handleChanged(ddsData, modType);
}
void BuildingHitlineInfo2SituationMap::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &mse, DataModification modType)
{
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
if (mse.modelId() != 0 && m_ismDtc->isElementAssignedToExercise(mse, m_exerciseId))
{
DEBUG_LOG(m_logger) << "m_buildingHeight.insert id=" << mse.id() << " z=" << mse.geoPosition().z();
m_buildingHeight.insert(mse.id(), mse.geoPosition().z());
}
break;
}
case DataModification::eRemoved:
m_buildingHeight.remove(mse.id());
break;
}
}
bool isValidPos(const Core::GeoPosition &pos)
{
if (qFuzzyIsNull(pos.lat()) && qFuzzyIsNull(pos.lon()))
return false;
return !std::isnan(pos.lat()) && !std::isnan(pos.lon());
}
bool BuildingHitlineInfo2SituationMap::isElapsed(const Sim2SituationMap::DDS_T &data) const
{
DEBUG_LOG(m_logger) << " isElapsed";
{
const Core::GeoPosition &startGeoPos = data.originatorPos();
if (!isValidPos(startGeoPos))
return true;
const Core::GeoPosition &endGeoPos = data.buildingPos();
if (!isValidPos(endGeoPos))
return true;
}
return false;
}
bool BuildingHitlineInfo2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
const qint32 hitlineId = ddsData.id();
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " id=" << hitlineId;
mapObj->setVisibility(SituationMap::ObjectAppearance::Tactical, false);
mapObj->rLineStyle().setLineWidth(3);
LineStyle ls = mapObj->lineStyle();
const SpecialChargeType sct = m_pdmHandler->isSpecialChargeType(ddsData.chargeTypeId());
switch (sct)
{
case SpecialChargeType::LRF:
ls.setLinePattern(LinePattern::Dot);
break;
case SpecialChargeType::LTD:
ls.setLinePattern(LinePattern::Solid);
break;
case SpecialChargeType::NoneSpecial:
default:
ls.setLinePattern(LinePattern::Dash);
}
mapObj->setLineStyle(ls);
mapObj->setPartyId(ddsData.originatorPartyId());
const int32_t originatorChargeTypeId = ddsData.chargeTypeId();
mapObj->setIdentifier(chargeTypeIdentifier(originatorChargeTypeId));
const Core::GeoPosition &startGeoPos = ddsData.originatorPos();
const Core::GeoPosition &endGeoPos = ddsData.buildingPos();
int bldgId = ddsData.buildingId();
double buildingHeight = m_buildingHeight.value(bldgId, 0);
mapObj->setStartAndEndPoint(Point3D(startGeoPos.lon(), startGeoPos.lat(), startGeoPos.z()),
Point3D(endGeoPos.lon(), endGeoPos.lat(), endGeoPos.z()-buildingHeight));
handleSymbolAppearanceSettings(mapObj, ddsData);
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " id=" << hitlineId;
return true;
}
void BuildingHitlineInfo2SituationMap::onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part part)
{
if ((part != FilterManagement::SymbolAppearanceSettings::Part::All) &&
(part != FilterManagement::SymbolAppearanceSettings::Part::Symbol))
return;
const bool relevant = symbolAppearanceSettingsChangesAreRelevant(m_symbolAppearanceSettings->settings());
m_currentSymbolSettings = m_symbolAppearanceSettings->settings();
if (!relevant)
return;
handleSymbolAppearanceSettings();
}
bool BuildingHitlineInfo2SituationMap::symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const
{
return qFuzzyCompare(m_currentSymbolSettings.symbolSettings.symbolScale, newSas.symbolSettings.symbolScale) ||
(m_currentSymbolSettings.symbolSettings.symbolPartyAppearance != newSas.symbolSettings.symbolPartyAppearance) ||
(m_currentSymbolSettings.symbolSettings.hitLineDisplayLengthMSec != newSas.symbolSettings.hitLineDisplayLengthMSec) ||
(m_currentSymbolSettings.symbolSettings.lrfLineDisplayLengthMSec != newSas.symbolSettings.lrfLineDisplayLengthMSec) ||
(m_currentSymbolSettings.symbolSettings.ltdLineDisplayLengthMSec != newSas.symbolSettings.ltdLineDisplayLengthMSec);
}
void BuildingHitlineInfo2SituationMap::handleSymbolAppearanceSettings()
{
for (const Buildings::BuildingHitLineInfo &buildingHitline : qAsConst(m_ddsDataContainer))
{
const UniqueMapId uniqueMapId = m_simId2UniqueMapId.value(buildingHitline.id(), INVALID_MAP_ID);
if (uniqueMapId == INVALID_MAP_ID)
{
WARNING_LOG(m_logger) << LOGFUNCTION << "Found a buildingHitline which is in internal map but has no map object...: " << buildingHitline.id();
continue;
}
RefPointer<MAP_T> mapObj = m_objFac.get<MAP_T>(uniqueMapId);
if (!mapObj.valid())
continue;
handleSymbolAppearanceSettings(mapObj, buildingHitline);
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " updateView failed,"
<< " mapObj = " << mapObj->debugInfo();
}
}
void BuildingHitlineInfo2SituationMap::handleSymbolAppearanceSettings(RefPointer<MAP_T> mapObj, const Sim2SituationMap::DDS_T &ddsData)
{
const FilterManagement::SymbolAppearanceSettings::Settings &filterSettings = m_symbolAppearanceSettings->settings();
mapObj->setScale(filterSettings.symbolSettings.symbolScale);
bool bUncertain = false;
const bool isVisi = isVisible(ddsData, &bUncertain);
if (bUncertain)
{
QTimer::singleShot(200, this, [this, ddsData]()
{
RefPointer<MAP_T> mapObj = getMapObjectOfSimId(ddsData.id());
if (!mapObj.valid())
return;
handleSymbolAppearanceSettings(mapObj, ddsData);
});
}
if (mapObj->visibility() != isVisi)
{
mapObj->setVisibility(isVisi);
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " updateView failed,"
<< " mapObj = " << mapObj->debugInfo();
}
}
bool BuildingHitlineInfo2SituationMap::isVisible(const Sim2SituationMap::DDS_T &ddsData, bool *bUncertain) const
{
return visibleBySymbolPartyAppearance(ddsData) &&
visibleByHitLineDisplayLength(m_pluginProvider->partitionTime(), ddsData) &&
visibleByParticipants(ddsData, bUncertain);
}
bool BuildingHitlineInfo2SituationMap::visibleBySymbolPartyAppearance(const Sim2SituationMap::DDS_T &ddsData) const
{
const FilterManagement::SymbolAppearanceSettings::Settings &filterSettings = m_symbolAppearanceSettings->settings();
const auto spa = filterSettings.symbolSettings.symbolPartyAppearance.value(ddsData.originatorPartyId());
return spa.isVisible;
}
bool BuildingHitlineInfo2SituationMap::visibleByParticipants(const Sim2SituationMap::DDS_T &ddsData, bool *bUncertain) const
{
if (!m_participant2SituationMap)
return true;
bool bParticipantExists = true;
bool bRet = m_participant2SituationMap->isParticipantVisible(ddsData.originatorParticipantId(), &bParticipantExists);
if (!bParticipantExists && bUncertain)
*bUncertain = true;
return bRet;
}
bool BuildingHitlineInfo2SituationMap::visibleByHitLineDisplayLength(const qint64 newPartitionTime, const DDS_T &ddsData) const
{
qint64 displayLength = m_currentSymbolSettings.symbolSettings.hitLineDisplayLengthMSec;
const SpecialChargeType sct = m_pdmHandler->isSpecialChargeType(ddsData.chargeTypeId());
switch (sct)
{
case SpecialChargeType::LRF:
displayLength = m_currentSymbolSettings.symbolSettings.lrfLineDisplayLengthMSec;
break;
case SpecialChargeType::LTD:
displayLength = m_currentSymbolSettings.symbolSettings.ltdLineDisplayLengthMSec;
break;
case SpecialChargeType::NoneSpecial:
default:
break;
}
if (displayLength < 0)
return true;
return (newPartitionTime - ddsData.sampleTime()) <= displayLength;
}
void BuildingHitlineInfo2SituationMap::onPartitionTimeChanged()
{
handleSymbolAppearanceSettings();
}
}
@@ -0,0 +1,97 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include "participant_to_map.h"
#include <Buildings/bld_dtc.h>
#include <MapObjects/hit_line.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <Plugins/Buildings/bld_info_gui_plugin_interface.h>
#include <Plugins/FilterManagement/flt_data_plugin_interface.h>
#include <FilterManagement/flt_dtc.h>
#include <memory>
namespace SituationMap
{
class PdmHandler;
class BuildingHitlineInfo2SituationMap final : public Sim2SituationMap<Buildings::BuildingHitLineInfo, SituationMap::HitLine>
, protected DdsFilterHandling<SituationMap::HitLine>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<Buildings::BuildingHitLineInfo, SituationMap::HitLine>;
using FilterClass = DdsFilterHandling<SituationMap::HitLine>;
public:
BuildingHitlineInfo2SituationMap(PdmHandler *pdmHandler,
Participant2SituationMap *participant2SituationMap,
ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName);
~BuildingHitlineInfo2SituationMap();
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override;
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
QString chargeTypeIdentifier(const int32_t originatorChargeTypeId) const;
protected Q_SLOTS:
bool onBuildingHitLineInfoChanged(const Sim2SituationMap::DDS_T &ddsData, DataModification modType = DataModification::eAdded);
void onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &mse, DataModification modType);
protected:
bool isElapsed(const Sim2SituationMap::DDS_T &data) const override;
bool isVisible(const Sim2SituationMap::DDS_T &ddsData, bool *bUncertain) const;
bool visibleBySymbolPartyAppearance(const Sim2SituationMap::DDS_T &ddsData) const;
bool visibleByParticipants(const Sim2SituationMap::DDS_T &ddsData, bool *bUncertain) const;
bool visibleByHitLineDisplayLength(const qint64 newPartitionTime, const Sim2SituationMap::DDS_T &ddsData) const;
void onPartitionTimeChanged();
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
void onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part part) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override;
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override
{
if (!mapObj.valid())
return;
const int simId = m_uniqueMapId2SimId.value(mapObj->uniqueMapId());
handleSymbolAppearanceSettings(mapObj, m_ddsDataContainer.value(simId));
}
void handleSymbolAppearanceSettings();
void handleSymbolAppearanceSettings(RefPointer<MAP_T> mapObj, const Sim2SituationMap::DDS_T &ddsData);
private:
PluginProvider *m_pluginProvider = nullptr;
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
std::shared_ptr<Buildings::ForeignInfoGuiInterface> m_bldBuildingInfoIfc;
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
PdmHandler *m_pdmHandler = nullptr;
QPointer<Participant2SituationMap> m_participant2SituationMap;
int m_exerciseId{-1};
QHash < int32_t, double > m_buildingHeight;
};
}
@@ -0,0 +1,420 @@
#include "buildings_to_map.h"
#include <Map/object_factory.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <MathUtils/simple_helper.h>
#include <Common/PluginInterfaces/gui_plugin_interface.h>
#include <Plugins/Buildings/bld_info_gui_plugin_interface.h>
#include <ProjectDataManagement/pdm_to_string.h>
#include <InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <QPolygonF>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
namespace SituationMap
{
int32_t Building2SituationMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool Building2SituationMap::init(PluginProvider *pluginProvider, bool enableDamageVisualization)
{
if (!pluginProvider ||
!pluginProvider->ismDtc())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no pluginProvider";
return false;
}
m_enableDamageVisualization = enableDamageVisualization;
m_pluginProvider = pluginProvider;
m_ismDtc = pluginProvider->ismDtc();
m_ismGuiIfc = pluginProvider->ismGuiIfc();
m_bldDtc = pluginProvider->bldDtc();
m_bldInfoIfc = pluginProvider->bldInfoIfc();
FilterClass::init(m_pluginProvider);
return true;
}
bool Building2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_ismDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
m_mseIdWithoutValidFootprint.clear();
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainFootprintChanged,
this, &Building2SituationMap::onMainFootprintChanged);
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
this, &Building2SituationMap::onMainStructureElementChanged);
m_ismDtc->mainStructureElements([this](const InfrastructureManagement::MainStructureElement & data)
{
onMainStructureElementChanged(data, DataModification::eAdded);
});
if (m_bldDtc)
connect(m_bldDtc.get(), &Buildings::Interface::Dtc::buildingStateChanged,
this, &Building2SituationMap::onBuildingStateChanged);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool Building2SituationMap::isElapsed(const InfrastructureManagement::MainStructureElement &ddsData) const
{
if (BaseClass::isElapsed(ddsData))
return true;
const InfrastructureManagement::StructureElementType::inner_enum set = ddsData.structureElementTypeId().underlying();
if ((set == InfrastructureManagement::StructureElementType_def::MeteoDataUnit) ||
(set == InfrastructureManagement::StructureElementType_def::RadioStation) ||
(set == InfrastructureManagement::StructureElementType_def::ApproachingPoint)
)
return true;
const qint32 mseId = ddsData.id();
const InfrastructureManagement::MainFootprint &mainFootprint = m_ismDtc->mainFootprint(mseId);
if (mainFootprint.elements().size() < 3)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " mainFootprint with id=" << mseId << " is not sufficiant."
<< " mainFootprint.elements().size() = " << mainFootprint.elements().size();
if (!m_mseIdWithoutValidFootprint.contains(mseId))
{
INFO_LOG(m_logger) << LOGFUNCTION << " Save for future mainFootPrintChanged..."
<< " (m_mseIdWithoutValidFootprint.size()=" << m_mseIdWithoutValidFootprint.size();
m_mseIdWithoutValidFootprint.append(mseId);
}
return true;
}
return false;
}
bool Building2SituationMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
if (!m_bldInfoIfc)
return false;
const QVector<int32_t> &simIds = uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
if (m_ismGuiIfc && m_ismGuiIfc->isInSelectionMode())
return true;
m_bldInfoIfc->showInfoWindow(simIds);
return true;
}
bool Building2SituationMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_ismDtc)
return false;
int32_t buildingId = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, buildingId))
return false;
umodOut = UnifiedMapObjectData();
umodOut.m_participantData.m_typeName = tr("Building");
umodOut.m_buildingData.buildingId = buildingId;
RefPointer<MAP_T> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_image = mapObj->previewImage();
if (m_bldDtc)
{
const Buildings::BuildingState &bldgState = m_bldDtc->buildingState(buildingId);
if (bldgState.id() == buildingId)
{
umodOut.m_participantData.m_vulnerabilityState = bldgState.vulnerabilityState().underlying();
umodOut.m_participantData.m_vulnerabilityString = ProjectDataManagement::toString(bldgState.vulnerabilityState());
}
}
umodOut.m_description1 = m_ismDtc->getBuildingDisplayName(buildingId);
return true;
}
void Building2SituationMap::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data,
DataModification modType)
{
const bool isResourceMgr = m_pluginProvider->appId() == LtsAppDescriptor::App::ResourceManager;
bool assignedToExercise = isResourceMgr || (m_ismDtc->isElementAssignedToExercise(data, m_pluginProvider->exerciseId()));
if (modType == DataModification::eAdded && !assignedToExercise)
return;
if (modType == DataModification::eModified && !assignedToExercise)
{
const int32_t simId = getSimId(data);
if (m_simId2UniqueMapId.contains(simId))
modType = DataModification::eRemoved;
else
return;
}
handleChanged(data, modType);
}
void Building2SituationMap::onMainFootprintChanged(const InfrastructureManagement::MainFootprint &data, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
if (data.elements().size() < 3)
return;
const int32_t mseId = data.id();
if (m_mseIdWithoutValidFootprint.contains(mseId))
{
const InfrastructureManagement::MainStructureElement &mseData = m_ismDtc->mainStructureElement(mseId);
if (mseData.id() == mseId)
{
m_mseIdWithoutValidFootprint.removeAll(mseId);
onMainStructureElementChanged(mseData, DataModification::eAdded);
}
}
}
void Building2SituationMap::onBuildingStateChanged(const Buildings::BuildingState &data, DataModification modType)
{
Q_UNUSED(modType);
if (!m_enableDamageVisualization)
return;
const int buildingId = data.id();
auto it = m_simId2UniqueMapId.constFind(buildingId);
if (it == m_simId2UniqueMapId.constEnd())
return;
const UniqueMapId uniqueMapId = it.value();
RefPointer<Sim2SituationMap::MAP_T> mapObj = m_objFac.get<Sim2SituationMap::MAP_T>(uniqueMapId);
if (!mapObj)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " not found in objFac"
<< " simId/buildingId = " << buildingId
<< " uniqueMapId = " << uniqueMapId ;
return;
}
if (!updateBldgDamage(mapObj, buildingId))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " updateBldgDamage failed, "
<< " simId/buildingId = " << buildingId
<< " uniqueMapId = " << uniqueMapId;
return;
}
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " updateView failed,"
<< " mapObj = " << mapObj->debugInfo();
}
bool Building2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " id=" << ddsData.id()
<< " name=" << ddsData.name()
<< " geoPosition=" << ddsData.geoPosition()
<< " angle=" << ddsData.angle();
mapObj->setForceMajorColor(Qt::black);
mapObj->setVisibility(ObjectAppearance::Tactical, false);
const qint32 buildingId = getSimId(ddsData);
int zoneOut = -1;
bool isGroundLevel = false;
const QPolygonF &absUtmPositions2D = m_ismDtc->getUtmFootprintById(buildingId, zoneOut, isGroundLevel);
const Core::GeoPosition &geoPosition = ddsData.geoPosition();
const QPointF referencePointGeo(geoPosition.lon(), geoPosition.lat());
PositionCont absPositionsGeo;
absPositionsGeo.reserve(absUtmPositions2D.size());
for (const QPointF &absPosition : qAsConst(absUtmPositions2D))
{
const LtsCoordTrans::UtmCoordinate utmPos(zoneOut, absPosition.x(), absPosition.y());
const QPointF &pGeo = utmPos.geographic();
absPositionsGeo.append(Point3D::fromQPointF(pGeo));
}
DEBUG_LOG(m_logger) << "absPositionsGeo = " << absPositionsGeo;
mapObj->setPositions(absPositionsGeo);
TextStyle ts = mapObj->textStyle();
ts.setHorizontalAlignment(HorizontalAlignment::Center);
mapObj->setTextStyle(ts);
mapObj->setIdentifier(m_ismDtc->getBuildingDisplayName(ddsData));
if (m_enableDamageVisualization && m_bldDtc)
{
updateBldgDamage(mapObj, buildingId);
}
mapObj->setMarker(Point3D::fromQPointF(referencePointGeo));
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool Building2SituationMap::updateBldgDamage(RefPointer<MAP_T> mapObj, qint32 buildingId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, buildingId=" << buildingId;
if (!m_bldDtc)
return false;
if (!mapObj)
return false;
const Buildings::BuildingState &bldgState = m_bldDtc->buildingState(buildingId);
const bool bIsContaminated = !bldgState.contaminationStates().empty();
LineStyle ls = mapObj->lineStyle();
if (bIsContaminated)
ls.setLineColor(Qt::yellow);
else
ls.setLineColor(Qt::black);
mapObj->setLineStyle(ls);
FillStyle fs = mapObj->fillStyle();
fs.setFillPattern(FillPattern::Solid);
int damagePercent = bldgState.damagePercent();
if (bldgState.id() != buildingId)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId/buildingId = " << buildingId
<< " not found!! (mapObj = " << mapObj->debugInfo() << ")";
damagePercent = 0;
}
double opacity = 1.0;
if (damagePercent < 1)
opacity = 0.0;
else if (damagePercent < 20)
opacity = 0.2;
else if (damagePercent < 40)
opacity = 0.4;
else if (damagePercent < 60)
opacity = 0.6;
else if (damagePercent < 80)
opacity = 0.8;
QColor col = QColor(125, 125, 125, 125);
if (opacity > 0.1)
{
col = Qt::red;
col.setAlphaF(opacity);
}
fs.setFillColor(col);
mapObj->setFillStyle(fs);
emit mapObjectChanged(mapObj->uniqueMapId());
TRACE_LOG(m_logger) << LOGFUNCTION << " END, buildingId=" << buildingId
<< ", damagePercent=" << damagePercent
<< ", fillStyle=" << mapObj->fillStyle()
<< ", uniqueMapId=" << mapObj->uniqueMapId();
return true;
}
bool Building2SituationMap::symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale) ||
(m_currentSymbolSettings.symbolSettings.showBuildingOutline != newSas.symbolSettings.showBuildingOutline) ||
(m_currentSymbolSettings.symbolSettings.showBuildingIdentifier != newSas.symbolSettings.showBuildingIdentifier);
}
void Building2SituationMap::handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj)
{
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
mapObj->setVisibility(m_currentSymbolSettings.symbolSettings.showBuildingOutline);
mapObj->setIdentifierVisible(m_currentSymbolSettings.symbolSettings.showBuildingIdentifier);
}
}
@@ -0,0 +1,83 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <Buildings/bld_dtc.h>
#include <MapObjects/building_outline.h>
namespace Buildings
{
class ForeignInfoGuiInterface;
}
namespace SituationMap
{
class Building2SituationMap final : public Sim2SituationMap<InfrastructureManagement::MainStructureElement, SituationMap::BuildingOutline>
, protected DdsFilterHandling<SituationMap::BuildingOutline>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<InfrastructureManagement::MainStructureElement, SituationMap::BuildingOutline>;
using FilterClass = DdsFilterHandling<SituationMap::BuildingOutline>;
public:
explicit Building2SituationMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
{}
bool init(PluginProvider *pluginProvider, bool enableDamageVisualization);
bool run() override;
void stop() override
{
if (m_ismDtc)
m_ismDtc->disconnect(this);
if (m_bldDtc)
m_bldDtc->disconnect(this);
}
bool isElapsed(const InfrastructureManagement::MainStructureElement &ddsData) const override;
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
protected Q_SLOTS:
void onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data,
DataModification modType = DataModification::eAdded);
void onMainFootprintChanged(const InfrastructureManagement::MainFootprint &data,
DataModification modType = DataModification::eAdded);
void onBuildingStateChanged(const Buildings::BuildingState &data, DataModification modType);
protected:
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool updateBldgDamage(RefPointer<MAP_T> mapObj, qint32 buildingId);
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override;
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override;
private:
PluginProvider *m_pluginProvider = nullptr;
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
std::shared_ptr<InfrastructureManagement::ForeignResourceManagementGuiInterface> m_ismGuiIfc;
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
std::shared_ptr<Buildings::ForeignInfoGuiInterface> m_bldInfoIfc;
bool m_enableDamageVisualization = false;
mutable QVector<int> m_mseIdWithoutValidFootprint;
};
}
@@ -0,0 +1,785 @@
#include "charge_effect_to_map.h"
#include "aes_to_situation_map_tmpl.h"
#include <AreaEffectSimulation/Utils/polygons.h>
#include <GuezIedManagement/gim_dtc.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <Map/map.h>
#include <ParticipantManagement/Data/ppm_data_plugin.h>
#include <ProjectDataManagement/pdm_dtc.h>
#include <QTimer>
#define ADD_UNIQUE_MAP_ID_TO_NOTIFIY(uniqueMapId) addUniqueMapIdToNotifiy(uniqueMapId, __FILE__, __LINE__)
#ifdef LTS_DEBUG
#endif
#ifdef BENCHMARK
#define BENCHMARK_SETUP_AND_START() \
QElapsedTimer elapsedTimer; \
elapsedTimer.start();
#define BENCHMARK_RUN
#define BENCHMARK_ALL_NOTIFIED
#else
#define BENCHMARK_SETUP_AND_START()
#endif
namespace SituationMap
{
static int s_effect3dMaxDisplayDuration = 5000;
ChargeEffectToMap::ChargeEffectToMap(ObjectFactory &objFac, const QString &layername, int drawOrder, const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName), FilterClass(loggerName, this), m_pluginProvider(nullptr), m_notifyTimer(new QTimer(this))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_notifyTimer->setInterval(100);
m_notifyTimer->setSingleShot(true);
connect(m_notifyTimer, &QTimer::timeout, this, &ChargeEffectToMap::updateAllNotifiedItems);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
ChargeEffectToMap::~ChargeEffectToMap()
{
DEBUG_LOG(m_logger) << " [ChargeEffectToMap] Dtor called! ";
if (m_displayFilter)
m_displayFilter->removeChangedCallback(this);
}
bool ChargeEffectToMap::init(PluginProvider *pluginProvider)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!pluginProvider)
return false;
m_pluginProvider = pluginProvider;
FilterClass::init(m_pluginProvider);
auto fltAesIfc = pluginProvider->fltAesIfc();
if (fltAesIfc)
{
m_displayFilter = fltAesIfc->aesFilterForOperator(pluginProvider->operatorId(), pluginProvider->workspaceId());
if (m_displayFilter)
m_displayFilter->addChangedCallback(this);
}
onAesDisplayFilterChanged(AreaEffectSimulation::AesType_def::AtExplosionArea);
connect(m_pluginProvider, &PluginProvider::partitionTimeChanged, this, &ChargeEffectToMap::onPartitionTimeChanged, Qt::UniqueConnection);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool ChargeEffectToMap::run()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " Starting to run";
this->stop();
if (!m_pluginProvider->aesDtc())
return false;
m_pluginProvider->aesDtc()->enableEffectCluster();
m_pluginProvider->aesDtc()->enableChargeEffect();
m_pluginProvider->aesDtc()->enableTrajectoryTimeAware();
connect(m_pluginProvider->aesDtc().get(),
&AreaEffectSimulation::Interface::Dtc::chargeEffectChanged,
this,
&ChargeEffectToMap::onChargeEffectChanged,
Qt::UniqueConnection);
connect(m_pluginProvider->aesDtc().get(),
&AreaEffectSimulation::Interface::Dtc::trajectoryTimeAwareChanged,
this,
&ChargeEffectToMap::onTracjectoryChanged,
Qt::UniqueConnection);
m_pluginProvider->aesDtc()->chargeEffects([this](const AreaEffectSimulation::ChargeEffect &data) { handleChanged(data, DataModification::eAdded); });
m_pluginProvider->aesDtc()->trajectoryTimeAwares([this](const AreaEffectSimulation::TrajectoryTimeAware &data)
{ onTracjectoryChanged(data, DataModification::eAdded); });
onAesDisplayFilterChanged(AreaEffectSimulation::AesType_def::AtExplosionArea);
return true;
}
void ChargeEffectToMap::stop()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (m_pluginProvider->aesDtc())
m_pluginProvider->aesDtc()->disconnect(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool ChargeEffectToMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
if (!m_pluginProvider->aesInfoIfc())
return false;
const QVector<int32_t> &simIds = uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
for (int chargeEffectId : simIds)
m_pluginProvider->aesInfoIfc()->showChargeEffectInfoWindow(chargeEffectId);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
int ChargeEffectToMap::getPartyIdFromOriginator(const int originatorId, const int originatorType) const
{
int partyId = -1;
switch (originatorType)
{
case ProjectDataManagement::StateChangeOriginator::Participant:
{
const auto &participant = m_pluginProvider->ppmDtc()->participant(originatorId);
partyId = participant.partyId();
break;
}
case ProjectDataManagement::StateChangeOriginator::Party:
{
partyId = originatorId;
break;
}
case ProjectDataManagement::StateChangeOriginator::AreaEffectSimulation:
{
AreaEffectSimulation::AesItem aesItem;
if (m_pluginProvider->aesDtc()->aesItemFromId(originatorId, aesItem))
partyId = aesItem.partyId().get();
break;
}
case ProjectDataManagement::StateChangeOriginator::DusMine:
{
partyId = m_pluginProvider->aesDtc()->partyForDusMine(originatorId);
break;
}
case ProjectDataManagement::StateChangeOriginator::Unknown:
case ProjectDataManagement::StateChangeOriginator::ObserverController:
case ProjectDataManagement::StateChangeOriginator::Initialization:
case ProjectDataManagement::StateChangeOriginator::ExerciseControl:
{
partyId = 1;
break;
}
case ProjectDataManagement::StateChangeOriginator::ImprovisedExplosiveDevice:
{
auto guezIedDtc = m_pluginProvider->gimDtc();
if (guezIedDtc)
{
const GuezIedManagement::Ied &gIed = guezIedDtc->iedForEquipmentNumber(originatorId);
if (gIed.id() > 0)
partyId = gIed.partyId();
}
break;
}
case ProjectDataManagement::StateChangeOriginator::WoundTreatmentDevice:
case ProjectDataManagement::StateChangeOriginator::MedicalTimeout:
case ProjectDataManagement::StateChangeOriginator::MaintainanceDevice:
case ProjectDataManagement::StateChangeOriginator::Sanitation:
default:
DEBUG_LOG(m_logger) << LOGFUNCTION << " originator state change for " << originatorType << " not (yet) implemented >>> "
<< ", originatorId = " << originatorId;
break;
}
return (partyId < 0) ? 0 : partyId;
}
bool ChargeEffectToMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_pluginProvider->aesDtc())
return false;
int simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
RefPointer<MAP_T> mapObj = m_objFac.get<MAP_T>(uniqueMapId);
if (mapObj.valid())
umodOut.m_image = mapObj->previewImage();
const auto cb = [simIdOut, &umodOut](const AreaEffectSimulation::ChargeEffect &data) -> bool
{
if (data.id() == simIdOut)
{
QString desc = QStringLiteral("id: %1\time: %2");
umodOut.m_description1 = desc.arg(data.id()).arg(QDateTime::fromMSecsSinceEpoch(data.sampleTime()).toString());
return true;
}
return false;
};
std::function<bool(const AreaEffectSimulation::ChargeEffect &data)> cb1 = cb;
return m_pluginProvider->aesDtc()->chargeEffects(cb1);
}
void ChargeEffectToMap::onPartitionTimeChanged(qint64 newPartitionTime)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, newPartitionTime=" << newPartitionTime << ", exerciseId = " << m_pluginProvider->exerciseId()
<< ", workspaceId = " << m_pluginProvider->workspaceId() << ", this=" << this;
updateAllTrajectories();
updateAllChargeEffects();
}
bool ChargeEffectToMap::updateElementImpl(const DDS_T &ddsData, RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START ";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setPickable(true);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
const int partyId = getPartyIdFromOriginator(ddsData.originatorId(), ddsData.originatorTypeId().underlying());
mapObj->setPartyId(partyId);
const bool bIsSmoke = m_pluginProvider->pdmDtc()->isSmoke(ddsData.chargeTypeId(), ddsData.igniterTypeId(), ddsData.igniterFunctionId());
if (bIsSmoke)
mapObj->forcePartyColor(Qt::darkYellow);
const Core::GeoPosition &impactGeoPos = ddsData.position();
const Point3D origin = LtsUtils::QPoint3D(impactGeoPos.lon(), impactGeoPos.lat(), impactGeoPos.z());
double impactRadius = m_pluginProvider->pdmDtc()->impactRadius(ddsData.chargeTypeId(), ddsData.igniterTypeId(), ddsData.igniterFunctionId());
if (impactRadius <= 5)
impactRadius = 5;
const auto polygon = form2PosCont(AreaEffectSimulation::Polygons::circle(origin.toPointF(), impactRadius));
mapObj->setPositions(polygon);
const AreaEffectSimulation::AesEffectState effectState = ddsData.state().underlying();
mapObj->setAesState(effectState2aesState(effectState.underlying()));
updateVisibility(mapObj, ddsData);
TRACE_LOG(m_logger) << LOGFUNCTION << " END ";
return true;
}
bool ChargeEffectToMap::isElapsed(const DDS_T &data) const
{
Q_UNUSED(data)
bool bIsElapsed = false;
return bIsElapsed;
}
int32_t ChargeEffectToMap::getSimId(const DDS_T &ddsData) const { return ddsData.id(); }
bool ChargeEffectToMap::removeElement(const int32_t simId) { return BaseClass::removeElement(simId); }
bool ChargeEffectToMap::iterateAesData(const std::function<bool(const AreaEffectSimulation::ChargeEffect &)> &cb) const
{
if (!m_pluginProvider)
return false;
return m_pluginProvider->aesDtc()->chargeEffects(cb);
}
void ChargeEffectToMap::onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part part)
{
if ((part != FilterManagement::SymbolAppearanceSettings::Part::All) && (part != FilterManagement::SymbolAppearanceSettings::Part::Symbol))
return;
const bool relevant = symbolAppearanceSettingsChangesAreRelevant(m_symbolAppearanceSettings->settings());
m_currentSymbolSettings = m_symbolAppearanceSettings->settings();
if (!relevant)
return;
updateAllChargeEffects();
}
bool ChargeEffectToMap::symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const
{
DEBUG_LOG(m_logger) << "[symbolAppearanceSettingsChangesAreRelevant] : currSas.symScale: " << m_currentSymbolSettings.symbolSettings.symbolScale
<< " newSas.symScale: " << newSas.symbolSettings.symbolScale;
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale)
|| (m_currentSymbolSettings.symbolSettings.symbolPartyAppearance != newSas.symbolSettings.symbolPartyAppearance);
}
void ChargeEffectToMap::handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj)
{
if (!mapObj.valid())
return;
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
const int simId = m_uniqueMapId2SimId.value(mapObj->uniqueMapId());
const auto &data = m_pluginProvider->aesDtc()->chargeEffect(simId);
if (data.id() <= 0)
{
WARNING_LOG(m_logger) << "[handleSymbolAppearanceSettings] data id is invalid! mapObjUniqueId: " << mapObj->uniqueMapId();
return;
}
this->updateVisibility(mapObj, data);
}
void ChargeEffectToMap::updateAllChargeEffects()
{
const auto cb = [this](const Sim2SituationMap::DDS_T &data) -> bool
{
if (isElapsed(data))
return false;
const UniqueMapId uniqueMapId = this->m_simId2UniqueMapId.value(data.id(), INVALID_MAP_ID);
if (uniqueMapId == INVALID_MAP_ID)
{
WARNING_LOG(m_logger) << " [updateAllChargeEffects] !!! Found a ChargeEffect which is in internal map but has no map object...: data.id: " << data.id();
return false;
}
RefPointer<MAP_T> mapObj = m_objFac.get<MAP_T>(uniqueMapId);
if (!mapObj.valid())
{
WARNING_LOG(m_logger) << " [updateAllChargeEffects] !!! invalid map object...: data.id: " << data.id();
return false;
}
this->updateVisibility(mapObj, data);
return false;
};
iterateAesData(cb);
}
void ChargeEffectToMap::updateVisibility(RefPointer<MAP_T> &mapObj, const Sim2SituationMap::DDS_T &data)
{
if (!mapObj.valid())
return;
const FilterManagement::SymbolAppearanceSettings::Settings &filterSettings = m_symbolAppearanceSettings->settings();
const bool isVisi = isVisible(data);
INFO_LOG(m_logger) << " [updateVisibility]: >> data.id: " << data.id() << " is visible? " << isVisi;
if (isVisi)
{
updateGunToTargetLine_SimpleOnSurface(mapObj, data);
updateAllTrajectories();
updateImpacts2D3D(mapObj, data);
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
updateDetonation3D(mapObj, data, isVisi);
}
mapObj->setScale(filterSettings.symbolSettings.symbolScale);
mapObj->setVisibility(isVisi);
ADD_UNIQUE_MAP_ID_TO_NOTIFIY(mapObj->uniqueMapId());
}
void ChargeEffectToMap::updateGunToTargetLine_SimpleOnSurface(RefPointer<MAP_T> &mapObj, const DDS_T &data)
{
const Core::GeoPosition2D &impactPos2D = data.position();
const Point3D origin = LtsUtils::QPoint3D(impactPos2D.lon(), impactPos2D.lat(), .0);
bool bDisplayFilterShowGTL = true;
if (m_displayFilter)
bDisplayFilterShowGTL = m_displayFilter->showExplosionClusterGunToTargetLine();
if (bDisplayFilterShowGTL)
{
Point3D originatorPos;
Point3D targetPos;
if (data.originatorTypeId() == ProjectDataManagement::StateChangeOriginator::Participant)
{
const auto &ppPos = m_pluginProvider->ppmDtc()->participantPosition(data.originatorId());
originatorPos = Point3D(ppPos.pos().lon(), ppPos.pos().lat(), ppPos.pos().z());
targetPos = origin;
}
mapObj->setGunToTargetLineSurface(originatorPos, targetPos);
}
else
{
mapObj->setGunToTargetLineSurface(Point3D(), Point3D());
}
}
bool ChargeEffectToMap::updateSingleTrajectory(const AreaEffectSimulation::TrajectoryTimeAware &traj, bool considerTime)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (traj.originatorTypeId() != ProjectDataManagement::StateChangeOriginator::ChargeEffect)
return false;
const int32_t simId = traj.originatorId();
if (!m_simId2UniqueMapId.contains(simId))
return false;
bool bDisplayFilterShowTRJ = true;
if (m_displayFilter)
bDisplayFilterShowTRJ = m_displayFilter->showExplosionClusterTrajectory();
const qint64 partitionTimeMsec = m_pluginProvider->partitionTime();
DEBUG_LOG(m_logger) << LOGFUNCTION << " START "
<< ", simId=" << simId << ", traj=" << traj << ", considerTime=" << considerTime
<< ", partitionTimeMsec - traj.trajectoryStartTime() = " << partitionTimeMsec - traj.trajectoryStartTime();
if (traj.trajectoryStartTime() > partitionTimeMsec)
return false;
RefPointer<MAP_T> mapObj = this->getMapObjectOfSimId(simId);
if (!mapObj.valid())
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " getMapObjectOfSimId failed"
<< " simId=" << simId;
return false;
}
bool bHasChanged = false;
const bool moIsVisibleByFilter = true;
const int index = 0;
if (bDisplayFilterShowTRJ && moIsVisibleByFilter)
{
const std::vector<Core::GeoPositionRelativeTime> &geometry = traj.geometry();
const PositionCont &curPath = mapObj->trajectory(index);
if (geometry.size() > static_cast<size_t>(curPath.size()))
{
PositionCont posCont;
posCont.reserve(geometry.size());
for (const Core::GeoPositionRelativeTime &posTime : qAsConst(geometry))
{
if (considerTime && ((traj.trajectoryStartTime() + posTime.relativeTime()) > partitionTimeMsec))
break;
posCont.append(Point3D(posTime.lon(), posTime.lat(), posTime.z()));
}
DEBUG_LOG(m_logger) << "update trajectory, simId=" << simId << ", index=" << index << ", posCont.size() " << posCont.size();
if (posCont.size() == 1)
posCont.clear();
bHasChanged = mapObj->setTrajectory(index, posCont);
}
}
else
{
bHasChanged = mapObj->setTrajectory(index, {});
}
if (bHasChanged)
ADD_UNIQUE_MAP_ID_TO_NOTIFIY(mapObj->uniqueMapId());
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void ChargeEffectToMap::updateAllTrajectories()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
BENCHMARK_SETUP_AND_START();
#ifdef BENCHMARK_ALL_TRAC
FATAL_LOG(m_logger) << LOGFUNCTION << " trajectoryTimeAwares took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_uniqueMapIdsToUpdate.size() << ", size "
<< m_aesDtc->trajectoryTimeAwares().size()
#endif
auto cb
= [this](const AreaEffectSimulation::TrajectoryTimeAware &traj) { updateSingleTrajectory(traj); };
m_pluginProvider->aesDtc()->trajectoryTimeAwares(cb);
#ifdef BENCHMARK_ALL_TRAC
FATAL_LOG(m_logger) << LOGFUNCTION << " All took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_uniqueMapIdsToUpdate.size() << ", size "
<< m_aesDtc->trajectoryTimeAwares().size()
#endif
TRACE_LOG(m_logger)
<< LOGFUNCTION << " END";
}
void ChargeEffectToMap::updateImpacts2D3D(RefPointer<MAP_T> &mapObj, const DDS_T &data)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
static QVector<AreaEffectSimulation::AesEffectState_def::type> relevantEffectStates
= {AreaEffectSimulation::AesEffectState_def::EsActivated, AreaEffectSimulation::AesEffectState_def::EsFired};
const bool bDisplayDueToEffectState = relevantEffectStates.contains(data.state().underlying());
if (bDisplayDueToEffectState)
{
const Core::GeoPosition &impactGeoPos = data.position();
const Point3D &origin = LtsUtils::QPoint3D(impactGeoPos.lon(), impactGeoPos.lat(), impactGeoPos.z());
const Core::ZReference zReference = data.zReference();
switch (zReference.underlying())
{
case Core::ZReference_def::ZrDrapedOnGround:
mapObj->setImpacts({origin});
break;
case Core::ZReference_def::ZrUndefined:
case Core::ZReference_def::ZrAbsolute:
mapObj->setImpactsAbsoluteHeight({origin});
break;
default:
ERROR_LOG(m_logger) << LOGFUNCTION << " ZReference not supported";
break;
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void ChargeEffectToMap::updateDetonation3D(RefPointer<MAP_T> &mapObj, const DDS_T &data, bool isChargeEffectVisible)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START ";
const int32_t simId = data.id();
const AreaEffectSimulation::AesEffectState effectState = data.state();
bool bHasChanged = false;
bool bDisplay = isChargeEffectVisible;
const qint64 partitionTimeMsec = m_pluginProvider->partitionTime();
if (bDisplay && m_displayFilter)
bDisplay = m_displayFilter->showExplosionClusterDetonationSphere();
static QVector<AreaEffectSimulation::AesEffectState_def::type> relevantEffectStates
= {AreaEffectSimulation::AesEffectState_def::EsActivated, AreaEffectSimulation::AesEffectState_def::EsFired, AreaEffectSimulation::AesEffectState_def::EsExpired};
bDisplay = bDisplay && relevantEffectStates.contains(effectState.underlying());
const qint64 age = partitionTimeMsec - data.effectStart() + data.effectDuration();
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, simId=" << simId << ", bDisplay=" << bDisplay<<" effectState: "<<data.state()<<" age[msec]: "<<age;
if (bDisplay && age <= s_effect3dMaxDisplayDuration)
{
double impactRadius = m_pluginProvider->pdmDtc()->impactRadius(data.chargeTypeId(), data.igniterTypeId(), data.igniterFunctionId());
if (impactRadius <= 5)
impactRadius = 5;
const Core::GeoPosition &effectGeoPos = data.position();
const Point3D &origin = Point3D(effectGeoPos.lon(), effectGeoPos.lat(), effectGeoPos.z());
const Core::ZReference &zRef = data.zReference();
switch (zRef.underlying())
{
case Core::ZReference_def::ZrDrapedOnGround:
if (mapObj->setDetonationsDraped({origin}, std::round(impactRadius)))
bHasChanged = true;
break;
case Core::ZReference_def::ZrUndefined:
case Core::ZReference_def::ZrAbsolute:
if (mapObj->setDetonationsAbsolute({origin}, std::round(impactRadius)))
bHasChanged = true;
break;
default:
ERROR_LOG(m_logger) << LOGFUNCTION << " ZReference not supported";
}
}
else
{
if (mapObj->setDetonationsDraped({}, 1))
bHasChanged = true;
if (mapObj->setDetonationsAbsolute({}, 1))
bHasChanged = true;
}
if (bHasChanged)
ADD_UNIQUE_MAP_ID_TO_NOTIFIY(mapObj->uniqueMapId());
TRACE_LOG(m_logger) << LOGFUNCTION << " END ";
}
bool ChargeEffectToMap::isVisible(const DDS_T &data) const
{
bool isVisible = visibleBySymbolPartyAppearance(data) && visibleByAesFilter(data);
return isVisible;
}
bool ChargeEffectToMap::visibleBySymbolPartyAppearance(const DDS_T &data) const
{
const FilterManagement::SymbolAppearanceSettings::Settings &filterSettings = m_symbolAppearanceSettings->settings();
const int partyId = getPartyIdFromOriginator(data.originatorId(), data.originatorTypeId().underlying());
const auto spa = filterSettings.symbolSettings.symbolPartyAppearance.value(partyId);
return spa.isVisible;
}
bool ChargeEffectToMap::visibleByAesFilter(const DDS_T &data) const
{
if (!m_displayFilter)
return true;
switch (data.state().underlying())
{
case AreaEffectSimulation::AesEffectState_def::EsError:
case AreaEffectSimulation::AesEffectState_def::EsUnknown:
case AreaEffectSimulation::AesEffectState_def::EsRemoved:
case AreaEffectSimulation::AesEffectState_def::EsReceived:
case AreaEffectSimulation::AesEffectState_def::EsFired:
DEBUG_LOG(m_logger) << "[visibleByAesFilter] set unvisible id: " << data.id() << ", state:" << data.state();
return false;
case AreaEffectSimulation::AesEffectState_def::EsCreated:
DEBUG_LOG(m_logger) << "[visibleByAesFilter][EsCreated] created visible: " << m_effectStateStruct.displayCreated;
return m_effectStateStruct.displayCreated;
case AreaEffectSimulation::AesEffectState_def::EsPrepared:
DEBUG_LOG(m_logger) << "[visibleByAesFilter][EsPrepared] prepared visible? " << m_effectStateStruct.displayPrepared;
return m_effectStateStruct.displayPrepared;
case AreaEffectSimulation::AesEffectState_def::EsActivated:
case AreaEffectSimulation::AesEffectState_def::EsPaused:
DEBUG_LOG(m_logger) << "[visibleByAesFilter] [active/paused] visible? " << m_effectStateStruct.displayActivated;
return m_effectStateStruct.displayActivated;
case AreaEffectSimulation::AesEffectState_def::EsExpired:
{
auto timeTriggered = data.sampleTime();
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtExplosionClusterSingleExplosions);
const auto afterGlow = m_effectStateStruct.expiredAfterglowDurationMSec;
DEBUG_LOG(m_logger) << "[visibleByAesFilter] [EsExpired] >>> partitionTime: " << m_pluginProvider->partitionTime() << " timeTriggered: " << timeTriggered
<< " afterGlow: " << afterGlow << " timeTriggered + afterGlow: " << timeTriggered + afterGlow;
return (m_pluginProvider->partitionTime() < timeTriggered + afterGlow);
}
}
return true;
}
void ChargeEffectToMap::onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType)
{
DEBUG_LOG(m_logger) << "[ChargeEffectToMap] onAesDisplayFilterChanged aes Type: " << aesType;
if (!m_displayFilter
|| ((AreaEffectSimulation::AesType_def::AtExplosionCluster != aesType.underlying())
&& (AreaEffectSimulation::AesType_def::AtExplosionArea != aesType.underlying())))
return;
m_effectStateStruct = m_displayFilter->effectStateFilter(AreaEffectSimulation::AesType_def::AtExplosionArea);
updateAllChargeEffects();
}
void ChargeEffectToMap::onChargeEffectChanged(const DDS_T &data, DataModification modType)
{
INFO_LOG(m_logger) << "[onChargeEffectChanged] >>> " << data.id() << " name: " << data.name() << " originId: " << data.originatorId()
<< " originTypeId: " << data.originatorTypeId().underlying() << " chargeTypeId: " << data.chargeTypeId() << " state: " << data.state();
this->handleChanged(data, modType);
}
bool ChargeEffectToMap::onTracjectoryChanged(const AreaEffectSimulation::TrajectoryTimeAware &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, modType=" << modType;
Q_UNUSED(modType);
updateSingleTrajectory(data);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, modType=" << modType;
return true;
}
void ChargeEffectToMap::updateAllNotifiedItems()
{
BENCHMARK_SETUP_AND_START();
std::string localLoggerName = m_logger.getLoggerName() + ".update";
LOGGER_T logger = m_logger.getNGLLogger(localLoggerName);
INFO_LOG(logger) << LOGFUNCTION << " m_uniqueMapIdsToUpdate.size() = " << m_uniqueMapIdsToUpdate.size();
for (int uniqueMapId : qAsConst(m_uniqueMapIdsToUpdate))
{
if (!m_uniqueMapId2SimId.contains(uniqueMapId))
continue;
RefPointer<MAP_T> mapObj = getMapObjectOfUniqueMapId(uniqueMapId);
if (!mapObj.valid())
continue;
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " updateView failed for " << mapObj->debugInfo();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_uniqueMapIdsToUpdate.size()=" << m_uniqueMapIdsToUpdate.size();
#ifdef BENCHMARK_ALL_NOTIFIED
FATAL_LOG(m_logger) << LOGFUNCTION << " took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_uniqueMapIdsToUpdate.size();
#endif
m_uniqueMapIdsToUpdate.clear();
}
void ChargeEffectToMap::addUniqueMapIdToNotifiy(int uniqueMapId, const char *file, int lineNo)
{
std::string localLoggerName = m_logger.getLoggerName() + ".update";
LOGGER_T logger = m_logger.getNGLLogger(localLoggerName);
if (logger.isDebugEnabled())
{
const int simId = m_uniqueMapId2SimId.value(uniqueMapId, -1);
DEBUG_LOG(logger) << "START ******* addUniqueMapIdToNotifiy: uniqueMapId = " << uniqueMapId << " (simId=" << simId << "), caller= " << file << ":" << lineNo;
}
if (uniqueMapId > 0)
m_uniqueMapIdsToUpdate.insert(uniqueMapId);
if (!m_notifyTimer->isActive())
m_notifyTimer->start();
}
}
@@ -0,0 +1,94 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <FilterManagement/flt_data_plugin_aes_display_filter.h>
#include <MapObjects/area_fire.h>
#include <QObject>
namespace SituationMap
{
class PdmHandler;
class ChargeEffectToMap final : public Sim2SituationMap<AreaEffectSimulation::ChargeEffect, SituationMap::AreaFire>
, protected FilterManagement::AesDisplayFilter::FilterChangedCallback
, protected DdsFilterHandling<SituationMap::AreaFire>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<AreaEffectSimulation::ChargeEffect, SituationMap::AreaFire>;
using FilterClass = DdsFilterHandling<SituationMap::AreaFire>;
public:
explicit ChargeEffectToMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName);
~ChargeEffectToMap();
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override;
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
int getPartyIdFromOriginator(const int originatorId, const int originatorType) const;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData, RefPointer<MAP_T> mapObj) override;
bool isElapsed(const Sim2SituationMap::DDS_T &data) const override;
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool removeElement(const int32_t simId) override;
bool iterateAesData(const std::function<bool (const AreaEffectSimulation::ChargeEffect &)> &cb) const;
void onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part part) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override;
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override;
void updateAllChargeEffects();
void updateVisibility(RefPointer<MAP_T> &mapObj, const DDS_T &data);
void updateGunToTargetLine_SimpleOnSurface(RefPointer<MAP_T> &mapObj, const DDS_T &data);
bool updateSingleTrajectory(const AreaEffectSimulation::TrajectoryTimeAware &traj, bool considerTime = true);
void updateAllTrajectories();
void updateImpacts2D3D(RefPointer<MAP_T> &mapObj, const DDS_T &data);
void updateDetonation3D(RefPointer<MAP_T> &mapObj, const DDS_T &data, bool isChargeEffectVisible = true);
bool isVisible(const Sim2SituationMap::DDS_T &data) const;
bool visibleBySymbolPartyAppearance(const Sim2SituationMap::DDS_T &data) const;
bool visibleByAesFilter(const Sim2SituationMap::DDS_T &data) const;
protected Q_SLOTS:
void onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType) override;
void onChargeEffectChanged(const DDS_T &data, DataModification modType);
bool onTracjectoryChanged(const AreaEffectSimulation::TrajectoryTimeAware &data, DataModification modType);
void updateAllNotifiedItems();
void addUniqueMapIdToNotifiy(int uniqueMapId, const char *file, int lineNo);
void onPartitionTimeChanged(qint64 newPartitionTime);
protected:
PluginProvider *m_pluginProvider;
std::shared_ptr<FilterManagement::AesDisplayFilter> m_displayFilter;
FilterManagement::AesDisplayFilter::EffectStateStruct m_effectStateStruct;
QTimer *m_notifyTimer{nullptr};
QSet<int> m_uniqueMapIdsToUpdate;
};
}
@@ -0,0 +1,74 @@
#include "danger_area_to_map.h"
#include <Map/object_factory.h>
namespace SituationMap
{
bool DangerArea2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
return false;
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::dangerAreaChanged,
this, &DangerArea2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->dangerAreas([this](const AreaEffectSimulation::DangerArea & data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool DangerArea2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
mapObj->setAesState(effectState2aesState(ddsData.effectStateId().underlying()));
const int32_t simId = ddsData.id();
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtDangerArea, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtDangerArea) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,42 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/danger_area.h>
#include <QObject>
namespace SituationMap
{
class DangerArea2SituationMap;
template <>
struct Aes2SituationMapTraits<DangerArea2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::DangerArea;
using MAP_TYPE = SituationMap::DangerArea;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtDangerArea;
};
class DangerArea2SituationMap final : public Aes2SituationMap<DangerArea2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<DangerArea2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::DangerArea &data)> &cb) const
{
return m_aesDtc->dangerAreas(cb);
}
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
};
}
@@ -0,0 +1,136 @@
#include "dus_single_mine_to_map.h"
#include <AreaEffectSimulation/Utils/polygons.h>
#include <AreaEffectSimulation/Utils/ddsdbconvert.h>
#include <LtsUtilsCore/dds_bitarray.h>
#include <SituationMap/Symbology/sidc_codec.h>
namespace SituationMap
{
bool DusSingleMine2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::dusSingleMineChanged,
this, &DusSingleMine2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->dusSingleMines([this](const AreaEffectSimulation::DusSingleMine & data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool DusSingleMine2SituationMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
auto sp = m_aesInfoIfc.lock();
if (!sp)
return false;
const QVector<int32_t> &simIds = this->uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
sp->showInfoWindow(simIds, Aes2SituationMapTraits<DusSingleMine2SituationMap>::aesType);
return true;
}
bool DusSingleMine2SituationMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
umodOut = UnifiedMapObjectData();
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
RefPointer<MAP_T> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_symDataToRender = mapObj->symbolDataToRender();
const std::function<bool(const AreaEffectSimulation::DusSingleMine &data)> cb = [simIdOut, &umodOut](const AreaEffectSimulation::DusSingleMine & data) -> bool
{
if (data.id() == simIdOut)
{
umodOut.m_description2 = QString::number(data.mineId());
return true;
}
return false;
};
return m_aesDtc->dusSingleMines(cb);
}
bool DusSingleMine2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
SymbolData symData;
symData.sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapObj->symbologyType(), "10011500002103000000");
symData.color = Qt::yellow;
symData.size = 1.0;
mapObj->setSymbol(symData);
mapObj->setOrigin(Point3D(ddsData.position().lon(), ddsData.position().lat(), .0));
mapObj->setTextModifier(Participant::TextModifier::M_HigherFormation, QString::number(ddsData.mineId()));
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool DusSingleMine2SituationMap::symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale) ||
(m_currentSymbolSettings.symbolSettings.symbolTransparency != newSas.symbolSettings.symbolTransparency)
;
}
void DusSingleMine2SituationMap::handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj)
{
mapObj->setUserSymbolOpacity(1.0f - m_currentSymbolSettings.symbolSettings.symbolTransparency);
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
}
}
@@ -0,0 +1,57 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/participant.h>
#include <QObject>
namespace SituationMap
{
class DusSingleMine2SituationMap;
template <>
struct Aes2SituationMapTraits<DusSingleMine2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::DusSingleMine;
using MAP_TYPE = SituationMap::Participant;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtDusSingleMine;
};
class DusSingleMine2SituationMap final : public Aes2SituationMap<DusSingleMine2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<DusSingleMine2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const DDS_TYPE &data)> &cb) const
{
return m_aesDtc->dusSingleMines(cb);
}
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool updateSingleMines(const int simId,
RefPointer<MAP_T> mapObj);
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override;
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override;
protected Q_SLOTS:
};
}
@@ -0,0 +1,592 @@
#include "effect_cluster_to_map.h"
#include "pdm_handler.h"
#include <LtsUtilsCore/dds_bitarray.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <AreaEffectSimulation/Utils/polygons.h>
#include <ParticipantManagement/ppm_dtc.h>
#include <Map/map.h>
#define ADD_UNIQUE_MAP_ID_TO_NOTIFIY(uniqueMapId) addUniqueMapIdToNotifiy(uniqueMapId, __FILE__, __LINE__)
#ifdef LTS_DEBUG
#endif
#ifdef BENCHMARK
# define BENCHMARK_SETUP_AND_START() QElapsedTimer elapsedTimer; elapsedTimer.start();
# define BENCHMARK_RUN
# define BENCHMARK_ALL_NOTIFIED
#else
# define BENCHMARK_SETUP_AND_START()
#endif
namespace SituationMap
{
EffectCluster2SituationMap::EffectCluster2SituationMap(PdmHandler *pdmHandler, ObjectFactory &objFac, const QString &layername, int drawOrder, const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, m_notifyTimer(new QTimer(this))
, m_pdmHandler(pdmHandler)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_notifyTimer->setInterval(100);
m_notifyTimer->setSingleShot(true);
connect(m_notifyTimer, &QTimer::timeout,
this, &EffectCluster2SituationMap::updateAllNotifiedItems);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
EffectCluster2SituationMap::~EffectCluster2SituationMap()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_notifyTimer->stop();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool EffectCluster2SituationMap::run()
{
QTimer::singleShot(1000, this, &EffectCluster2SituationMap::runDelayed);
return true;
}
bool EffectCluster2SituationMap::runDelayed()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
BENCHMARK_SETUP_AND_START();
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::effectClusterChanged,
this, &EffectCluster2SituationMap::onEffectClusterChanged, Qt::UniqueConnection);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &EffectCluster2SituationMap::onAesItemViewChanged, Qt::UniqueConnection);
m_aesDtc->effectClusters([this](const AreaEffectSimulation::EffectCluster &data)
{
onEffectClusterChanged(data, DataModification::eAdded);
});
#ifdef BENCHMARK_RUN
FATAL_LOG(m_logger) << LOGFUNCTION << " EffectClusters took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
#ifdef BENCHMARK_RUN
FATAL_LOG(m_logger) << LOGFUNCTION << " trajectoryTimeAwares took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
#ifdef BENCHMARK_RUN
FATAL_LOG(m_logger) << LOGFUNCTION << " all took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
void EffectCluster2SituationMap::stop()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_notifyTimer->stop();
if (m_aesDtc)
m_aesDtc->disconnect(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool EffectCluster2SituationMap::updateVisibility(const Aes2SituationMap::DDS_TYPE &ddsData, RefPointer<Aes2SituationMap::MAP_TYPE> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, simId=" << getSimId(ddsData);
if (!BaseClass::updateVisibility(ddsData, mapObj))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " BaseClass::updateVisibility failed, simId=" << getSimId(ddsData);
return false;
}
const int32_t simId = ddsData.id();
const AreaEffectSimulation::AesEffectState effectState = ddsData.effectStateId().underlying();
bool bIsMode3D = false;
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
bIsMode3D = true;
{
bool bDisplayFilterShowGTL = true;
if (m_displayFilter)
bDisplayFilterShowGTL = m_displayFilter->showExplosionClusterGunToTargetLine();
const bool bDisplayFilterShowGFK = bDisplayFilterShowGTL && bIsMode3D
;
AreaEffectSimulation::AesItemView itemViewGunToTargetLine;
const std::vector<Core::GeoPosition>& form = itemViewGunToTargetLine.form();
if (bDisplayFilterShowGTL || bDisplayFilterShowGFK)
m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtEffectClusterGunToTargetLine, itemViewGunToTargetLine);
if (bDisplayFilterShowGTL && (form.size() >= 2))
mapObj->setGunToTargetLineSurface(Point3D(form.front().lon(), form.front().lat(), 0.0),
Point3D(form.back().lon() , form.back().lat() , 0.0));
else
mapObj->setGunToTargetLineSurface(Point3D(), Point3D());
if (bIsMode3D)
{
if (bDisplayFilterShowGFK)
{
PositionCont gunToTargetPath;
gunToTargetPath.reserve(static_cast<int>(form.size()));
for (const Core::GeoPosition& item : qAsConst(form))
gunToTargetPath.append(Point3D(item.lon(), item.lat(), item.z()));
mapObj->setGunToTargetTrajectory3D(gunToTargetPath);
} else {
mapObj->setGunToTargetTrajectory3D({});
}
}
}
{
bool bDisplayFilterShowMHP = true;
if (m_displayFilter)
bDisplayFilterShowMHP = m_displayFilter->showExplosionClusterMeanHitPoint();
PositionCont mhps;
mhps.reserve(static_cast<int>(ddsData.effectors().size()));
for (const auto &effector : qAsConst(ddsData.effectors()))
{
const Core::GeoPosition &mhpPos = effector.mhpPosition();
mhps.append(Point3D(mhpPos.lon(), mhpPos.lat(), mhpPos.z()));
}
if (bDisplayFilterShowMHP)
{
QColor impactsColor;
const auto &chargeStruct = ddsData.chargeStruct();
const bool bIsSmoke = m_pluginProvider->pdmDtc()->isSmoke(chargeStruct.chargeTypeId(), chargeStruct.igniterTypeId(), chargeStruct.igniterFunctionId());
if (bIsSmoke)
impactsColor = Qt::darkYellow;
mapObj->setScheduledImpacts(mhps, impactsColor);
}
else
{
mapObj->setScheduledImpacts({});
}
}
ADD_UNIQUE_MAP_ID_TO_NOTIFIY(mapObj->uniqueMapId());
return true;
}
bool EffectCluster2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
BENCHMARK_SETUP_AND_START();
const int32_t simId = ddsData.id();
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
const AreaEffectSimulation::AesEffectState effectState = ddsData.effectStateId().underlying();
mapObj->setAesState(effectState2aesState(effectState));
LineStyle ls = mapObj->lineStyle();
ls.setLinePattern(LinePattern::Solid);
mapObj->setLineStyle(ls);
#ifdef BENCHMARK_UPDATE_ELEMENT
FATAL_LOG(m_logger) << LOGFUNCTION << " part1 took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtEffectCluster, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtEffectCluster) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
#ifdef BENCHMARK_UPDATE_ELEMENT
FATAL_LOG(m_logger) << LOGFUNCTION << " aesItemViewFromEntityId took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
#ifdef BENCHMARK_UPDATE_ELEMENT
FATAL_LOG(m_logger) << LOGFUNCTION << " updateAllTracjectories took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
updateVisibility(ddsData, mapObj);
#ifdef BENCHMARK_UPDATE_ELEMENT
FATAL_LOG(m_logger) << LOGFUNCTION << " all took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool EffectCluster2SituationMap::updateGeometry(const AreaEffectSimulation::AesItemView &aesItemView, RefPointer<AreaFire> mapObj)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
const int simId = aesItemView.aesItemId();
auto it = m_ddsDataContainer.find(simId);
if (it != m_ddsDataContainer.end())
updateNonLethalArea(mapObj, *it, aesItemView);
return BaseClass::updateGeometry(aesItemView, mapObj);
}
bool EffectCluster2SituationMap::removeElement(const int32_t simId)
{
return BaseClass::removeElement(simId);
}
bool EffectCluster2SituationMap::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &aesItemView, DataModification modType)
{
Q_UNUSED(modType);
const int simId = aesItemView.aesItemId();
TRACE_LOG(m_logger) << LOGFUNCTION << " START, simId=" << simId;
bool success = false;
if (aesItemView.aesTypeId() == AreaEffectSimulation::AesType::AtEffectClusterGunToTargetLine)
{
RefPointer<MAP_T> mapObj = this->getMapObjectOfSimId(simId);
if (mapObj.valid())
updateVisibility(m_ddsDataContainer.value(simId), mapObj);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool EffectCluster2SituationMap::updateGunToTargetLineAndTrajectory(const AreaEffectSimulation::AesItemView &itemView,
RefPointer<Sim2SituationMap::MAP_T> mapObj)
{
const std::vector<Core::GeoPosition>& formRef = itemView.form();
TRACE_LOG(m_logger) << LOGFUNCTION << " START, form.size = " << formRef.size();
if (formRef.size() >= 2)
{
mapObj->setGunToTargetLineSurface(Point3D(formRef.front().lon(), formRef.front().lat(), 0.0),
Point3D(formRef.back().lon() , formRef.back().lat() , 0.0));
} else {
mapObj->setGunToTargetLineSurface(Point3D(), Point3D());
}
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
{
PositionCont gunToTargetPath;
gunToTargetPath.reserve(static_cast<int>(formRef.size()));
for (const Core::GeoPosition& item : qAsConst(formRef))
gunToTargetPath.append(Point3D(item.lon(), item.lat(), item.z()));
mapObj->setGunToTargetTrajectory3D(gunToTargetPath);
}
ADD_UNIQUE_MAP_ID_TO_NOTIFIY(mapObj->uniqueMapId());
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
PositionCont circleE(const QPointF &center_geo, qreal radius, int steps= 72)
{
const LtsCoordTrans::UtmCoordinate &centerUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(center_geo);
PositionCont poly;
if (steps < 6)
steps = 6;
poly.reserve(steps);
for (int i = 0; i < 360; i += (360 / steps))
{
double angle = double(i) * LtsCoordTrans::deg2rad();
const QPointF &pointGeo = centerUtm.geographic(QPointF(cos(angle) * radius, sin(angle) * radius));
poly.push_back(Point3D(pointGeo.x(), pointGeo.y(), 0.0));
}
return poly;
}
bool EffectCluster2SituationMap::updateNonLethalArea(RefPointer<Sim2SituationMap::MAP_T> mapObj,
const AreaEffectSimulation::EffectCluster &EffectCluster,
const AreaEffectSimulation::AesItemView &aesItemView)
{
if (!m_pdmHandler)
return false;
if (EffectCluster.id() != aesItemView.aesItemId())
return false;
const int chargeTypeId = EffectCluster.chargeStruct().chargeTypeId();
const ProjectDataManagement::GearClass &gc = m_pdmHandler->gearClassFromChargeTypeId(chargeTypeId);
if (gc.underlying() == ProjectDataManagement::GearClass_def::AirSupport)
{
const QVector<ProjectDataManagement::CasEffect> &casEffectsVec = m_pdmHandler->casEffects(EffectCluster.chargeStruct());
if (casEffectsVec.size() >= 2)
{
const ProjectDataManagement::CasEffect &ce = casEffectsVec[1];
const double impactRadius = ce.impactRadius();
const AreaEffectSimulation::Area &areaRef = EffectCluster.area();
const Core::GeoPosition2D &blGeo = aesItemView.boundingBoxBottomLeft();
const QPointF &centerGeo = AreaEffectSimulation::Polygons::bottomLeft2CenterPoint(QPointF(blGeo.lon(), blGeo.lat()),
areaRef.width(), areaRef.height(), areaRef.rotation());
updateNonLethalArea(mapObj, centerGeo, impactRadius);
}
} else {
updateNonLethalArea(mapObj);
}
return true;
}
bool EffectCluster2SituationMap::updateNonLethalArea(RefPointer<Sim2SituationMap::MAP_T> mapObj, const QPointF &centerGeo, double radius)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, radius = " << radius;
if (!mapObj)
return false;
if (radius <= 0)
{
mapObj->setNonLethalArea({});
} else {
const PositionCont &nonLethalAreaPolygon = circleE(centerGeo, radius);
mapObj->setNonLethalArea(nonLethalAreaPolygon);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void EffectCluster2SituationMap::updateAllNotifiedItems()
{
BENCHMARK_SETUP_AND_START();
std::string localLoggerName = m_logger.getLoggerName() + ".update";
LOGGER_T logger = m_logger.getNGLLogger(localLoggerName);
INFO_LOG(logger) << LOGFUNCTION << " m_uniqueMapIdsToUpdate.size() = " << m_uniqueMapIdsToUpdate.size();
for (int uniqueMapId : qAsConst(m_uniqueMapIdsToUpdate))
{
if (!m_uniqueMapId2SimId.contains(uniqueMapId))
continue;
RefPointer<MAP_T> mapObj = getMapObjectOfUniqueMapId(uniqueMapId);
if (!mapObj.valid())
continue;
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " updateView failed for "<< mapObj->debugInfo();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_uniqueMapIdsToUpdate.size()=" << m_uniqueMapIdsToUpdate.size();
#ifdef BENCHMARK_ALL_NOTIFIED
FATAL_LOG(m_logger) << LOGFUNCTION << " took " << elapsedTimer.elapsed() << " [ms]" << ", size " << m_uniqueMapIdsToUpdate.size();
#endif
m_uniqueMapIdsToUpdate.clear();
}
void EffectCluster2SituationMap::addUniqueMapIdToNotifiy(int uniqueMapId, const char *file, int lineNo)
{
std::string localLoggerName = m_logger.getLoggerName() + ".update";
LOGGER_T logger = m_logger.getNGLLogger(localLoggerName);
if (logger.isDebugEnabled())
{
const int simId = m_uniqueMapId2SimId.value(uniqueMapId, -1);
DEBUG_LOG(logger) << "START ******* addUniqueMapIdToNotifiy: uniqueMapId = " << uniqueMapId << " (simId=" << simId << "), caller= " << file << ":" << lineNo;
}
if (uniqueMapId > 0)
m_uniqueMapIdsToUpdate.insert(uniqueMapId);
if (!m_notifyTimer->isActive())
m_notifyTimer->start();
}
AreaEffectSimulation::AesType EffectCluster2SituationMap::aesTypeFromGearClassChargeType(const DDS_TYPE &data)const
{
static QMap<int, AreaEffectSimulation::AesType> s_aesTypeMap;
if (s_aesTypeMap.contains(data.chargeStruct().chargeTypeId()))
return s_aesTypeMap[data.chargeStruct().chargeTypeId()];
const ProjectDataManagement::GearClass &gc = m_pdmHandler->gearClassFromChargeTypeId(data.chargeStruct().chargeTypeId());
switch (gc.underlying())
{
case ProjectDataManagement::GearClass::AirSupport:
s_aesTypeMap[data.chargeStruct().chargeTypeId()] = AreaEffectSimulation::AesType::AtAirSupportImpact;
break;
case ProjectDataManagement::GearClass::Artillery:
case ProjectDataManagement::GearClass::Mortar:
case ProjectDataManagement::GearClass::Rocket:
s_aesTypeMap[data.chargeStruct().chargeTypeId()] = AreaEffectSimulation::AesType::AtExplosionArea;
break;
default:
return AreaEffectSimulation::AesType::AtUnknown;
}
return s_aesTypeMap[data.chargeStruct().chargeTypeId()];
}
void EffectCluster2SituationMap::onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType)
{
TRACE_LOG(m_logger) << " onAesDisplayFilterChanged, aesType =" << aesType
<< ", this " << this;
if ((AreaEffectSimulation::AesType_def::AtEffectCluster != aesType.underlying()) &&
(AreaEffectSimulation::AesType_def::AtExplosionArea != aesType.underlying()) &&
(AreaEffectSimulation::AesType_def::AtAirSupportImpact != aesType.underlying()))
return;
const auto cb = [this](const DDS_TYPE &data) -> bool
{
if (isElapsed(data))
return false;
this->updateVisibility(data);
return false;
};
iterateAesData(cb);
}
bool EffectCluster2SituationMap::isVisibleByFilter(const Aes2SituationMap::DDS_TYPE &data) const
{
if (!m_displayFilter)
return true;
const auto es = data.effectStart().is_set() ? data.effectStart().get() : 0;
const auto partyId = data.partyId().is_set() ? data.partyId().get() : -1;
bool isVisibleByFilter = partyId > 0 ? FilterClass::m_currentSymbolSettings.symbolSettings.symbolPartyAppearance.value(partyId).isVisible : true;
if (isVisibleByFilter)
{
AreaEffectSimulation::AesType aestype = aesTypeFromGearClassChargeType(data);
if (aestype == AreaEffectSimulation::AesType::AtUnknown)
{
WARNING_LOG(m_logger) << " Only AES TYPE explosion Cluster, AirSupportImpact, Explosion area will be displayed";
aestype = AreaEffectSimulation::AesType::AtExplosionArea;
}
isVisibleByFilter = m_displayFilter->isVisible(aestype,
data.effectStateId(),
data.chargeStruct().chargeTypeId(),
partyId,
data.isCentral(),
es,
data.effectDuration(),
m_pluginProvider->partitionTime());
}
return isVisibleByFilter;
}
bool EffectCluster2SituationMap::onEffectClusterChanged(const AreaEffectSimulation::EffectCluster &EffectCluster, DataModification modType)
{
updateDdsDataContainer(EffectCluster, modType);
return BaseClass::handleChanged(EffectCluster, modType);
}
}
@@ -0,0 +1,87 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/area_fire.h>
#include <QSet>
#include <QTimer>
namespace SituationMap
{
class PdmHandler;
class EffectCluster2SituationMap;
template <>
struct Aes2SituationMapTraits<EffectCluster2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::EffectCluster;
using MAP_TYPE = SituationMap::AreaFire;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtEffectCluster;
};
class EffectCluster2SituationMap final : public Aes2SituationMap<EffectCluster2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<EffectCluster2SituationMap>;
using BaseClass::BaseClass;
explicit EffectCluster2SituationMap(PdmHandler *pdmHandler,
ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName);
virtual ~EffectCluster2SituationMap();
bool run() override;
void stop() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::EffectCluster &data)> &cb) const
{
return m_aesDtc->effectClusters(cb);
}
using BaseClass::updateVisibility;
bool updateVisibility(const DDS_TYPE &ddsData, RefPointer<MAP_TYPE> mapObj) override;
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool updateGeometry(const AreaEffectSimulation::AesItemView &aesItemView,
RefPointer<SituationMap::AreaFire> mapObj) override;
bool removeElement(const int32_t simId) override;
void onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType) override;
bool isVisibleByFilter(const DDS_TYPE &data) const override;
AreaEffectSimulation::AesType aesTypeFromGearClassChargeType(const Aes2SituationMap::DDS_TYPE &data) const;
protected Q_SLOTS:
bool runDelayed();
bool onEffectClusterChanged(const AreaEffectSimulation::EffectCluster &EffectCluster, DataModification modType);
bool onAesItemViewChanged(const AreaEffectSimulation::AesItemView &aesItemView, DataModification modType);
bool updateGunToTargetLineAndTrajectory(const AreaEffectSimulation::AesItemView &itemView, RefPointer<Sim2SituationMap::MAP_T> mapObj);
bool updateNonLethalArea(RefPointer<Sim2SituationMap::MAP_T> mapObj,
const AreaEffectSimulation::EffectCluster &EffectCluster,
const AreaEffectSimulation::AesItemView &aesItemView);
bool updateNonLethalArea(RefPointer<Sim2SituationMap::MAP_T> mapObj, const QPointF &centerGeo = QPointF(), double radius = 0);
void updateAllNotifiedItems();
void addUniqueMapIdToNotifiy(int uniqueMapId, const char *file, int lineNo);
protected:
QTimer *m_notifyTimer{nullptr};
QSet<int> m_uniqueMapIdsToUpdate;
PdmHandler *m_pdmHandler{nullptr};
};
}
@@ -0,0 +1,266 @@
#include "emergency_call_to_map.h"
#include <Map/object_factory.h>
#include <Map/map.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Common/LtsAppDescriptor/lts_app_descriptor.h>
#include <QDateTime>
#include <QPainter>
#include <QDebug>
#include <sstream>
using namespace SituationMap;
static QImage renderEmergencySymbol(bool bExpired)
{
int size = 200;
QImage image(size, size, QImage::Format_ARGB32);
image.fill(Qt::transparent);
QPainter painter(&image);
painter.setRenderHint(QPainter::Antialiasing);
QPen pen(Qt::white);
pen.setWidth(10);
painter.setPen(pen);
if (bExpired)
painter.setBrush(QBrush(Qt::gray));
else
painter.setBrush(QBrush(Qt::red));
painter.drawEllipse(QPointF(image.rect().center()),
image.rect().width() * 0.45,
image.rect().height() * 0.45);
painter.setPen(QPen(Qt::white));
QFont font = painter.font();
font.setBold(true);
font.setPixelSize(75);
painter.setFont(font);
QPointF pos(image.width() * 0.125,
image.height() * 0.625);
painter.drawText(pos, QLatin1String("SOS"));
return image;
}
bool EmergencyCallToMap::init(PluginProvider *pluginProvider)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!pluginProvider)
return false;
m_pluginProvider = pluginProvider;
DEBUG_LOG(m_logger) << LOGFUNCTION << " exerciseId=" << m_pluginProvider->exerciseId();
m_almDtc = m_pluginProvider->almDtc();
m_almInfoIfc = m_pluginProvider->almInfoIfc();
FilterClass::init(m_pluginProvider);
const bool bIsReplay = m_pluginProvider->isReplayPartition();
const bool bIsSnapshot = m_pluginProvider->appId() == LtsAppDescriptor::App::Snapshot;
if (bIsReplay && !bIsSnapshot)
{
bool success = false;
if (m_objFac.map())
success = m_objFac.map()->layerFactory().switchEmergencyCallLayerOff();
DEBUG_LOG(m_logger) << LOGFUNCTION << ", switchEmergencyCallLayerOff _OFF_ ; success = " << success;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool EmergencyCallToMap::run()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " Starting to run";
this->stop();
if (m_almDtc)
{
connect(m_almDtc.get(), &AlarmManagement::Interface::Dtc::almEmergencyCallChanged,
this, &EmergencyCallToMap::handleChanged, Qt::UniqueConnection);
m_almDtc->almEmergencyCalls([this](const AlarmManagement::AlmEmergencyCall & data)
{
handleChanged(data, DataModification::eAdded);
});
}
return true;
}
void EmergencyCallToMap::stop()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " Stopping";
if (m_almDtc)
m_almDtc->disconnect(this);
}
bool EmergencyCallToMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_almInfoIfc)
return false;
const QVector<int32_t> &simIds = uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
m_almInfoIfc->showEmergencyCallInfoWindows(simIds);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool EmergencyCallToMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_almDtc)
return false;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
RefPointer<MAP_T> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_image = mapObj->previewImage();
const auto cb = [ simIdOut, &umodOut](const AlarmManagement::AlmEmergencyCall & data) -> bool
{
if (data.id() == simIdOut)
{
umodOut.m_equipmentNumber = data.issi();
QString desc = QStringLiteral("id: %1\ntime: %2");
umodOut.m_description1 = desc.arg(data.id()).arg(QDateTime::fromMSecsSinceEpoch(data.sampleTime()).toString());
return true;
}
return false;
};
std::function<bool(const AlarmManagement::AlmEmergencyCall &data)> cb1 = cb;
return m_almDtc->almEmergencyCalls(cb1);
}
void EmergencyCallToMap::showExpired(bool showExpired)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, showExpired=" << showExpired;
bool change = m_showExpired != showExpired;
if (change)
{
m_showExpired = showExpired;
run();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, showExpired=" << showExpired;
}
bool EmergencyCallToMap::isElapsed(const Sim2SituationMap::DDS_T &data) const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool bIsValid = m_showExpired || !data.expired();
DEBUG_LOG(m_logger) << LOGFUNCTION
<< ", id: "<< data.id()
<< ", issi: "<< data.issi()
<< ", data.expired: " << data.expired()
<< ", m_showExpired: " << m_showExpired
<< " -> bIsValid=" << bIsValid;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, bIsValid=" << bIsValid;
return !bIsValid;
}
int32_t EmergencyCallToMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool EmergencyCallToMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData, RefPointer<Sim2SituationMap::MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << ", id " << ddsData.id();
mapObj->setPickable(true);
mapObj->setDrawOrder(1);
mapObj->setIdentifier(QStringLiteral("SOS_%1").arg(ddsData.issi()));
TextStyle textStyle;
textStyle.setSize(20);
if (ddsData.expired())
textStyle.setTextColor(Qt::gray);
else
textStyle.setTextColor(Qt::red);
textStyle.setTextOutlineColor(Qt::white);
textStyle.setTextOutlineWidth(5);
mapObj->setTextStyle(textStyle);
const Core::GeoPosition2D &geoPos = ddsData.position();
mapObj->setOrigin(Point3D(geoPos.lon(), geoPos.lat(), 0.0));
mapObj->setProxyImage(renderEmergencySymbol(ddsData.expired()), QSize(50, 50));
mapObj->setPinEnabled(true);
forceEmergencyCallLayerVisibility();
emit emergencyCallUpdated(mapObj->identifier(), Point3D(geoPos.lon(), geoPos.lat(), 0));
return true;
}
void EmergencyCallToMap::forceEmergencyCallLayerVisibility()
{
if (!m_pluginProvider)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " EmergencyCallLayer: failed due to missing pluginProvider!!!";
return;
}
const bool bIsLive = !m_pluginProvider->isReplayPartition();
if (bIsLive)
{
bool success = false;
if (m_objFac.map())
success = m_objFac.map()->layerFactory().switchEmergencyCallLayerOn();
DEBUG_LOG(m_logger) << LOGFUNCTION << ", switchEmergencyCallLayerOn _ON_ ; success = " << success;
}
}
@@ -0,0 +1,73 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/AlarmManagement/alm_data_plugin_interface.h>
#include <Plugins/AlarmManagement/alm_info_gui_plugin_interface.h>
#include <MapObjects/geo_image.h>
namespace SituationMap
{
class EmergencyCallToMap final : public Sim2SituationMap<AlarmManagement::AlmEmergencyCall, SituationMap::GeoImage>
, protected DdsFilterHandling<SituationMap::GeoImage>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<AlarmManagement::AlmEmergencyCall, SituationMap::GeoImage>;
using FilterClass = DdsFilterHandling<SituationMap::GeoImage>;
public:
EmergencyCallToMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
, m_pluginProvider(nullptr)
{}
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override;
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
void showExpired(bool showExpired);
protected:
bool isElapsed(const Sim2SituationMap::DDS_T &data) const override;
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const DDS_T &ddsData, RefPointer<MAP_T> mapObj) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale);
}
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override
{
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
}
void forceEmergencyCallLayerVisibility();
signals:
void emergencyCallUpdated(const QString &name, const SituationMap::Point3D &geoPosition);
private:
PluginProvider *m_pluginProvider;
bool m_showExpired{false};
std::shared_ptr<AlarmManagement::Interface::Dtc> m_almDtc;
std::shared_ptr<AlarmManagement::ForeignInfoGuiInterface> m_almInfoIfc;
};
}
@@ -0,0 +1,180 @@
#include "explosion_area_to_map.h"
#include <LtsUtilsCore/dds_bitarray.h>
namespace SituationMap
{
bool ExplosionArea2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::explosionAreaChanged,
this, &ExplosionArea2SituationMap::handleChanged, Qt::UniqueConnection);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::triggeredImpactsChanged,
this, &ExplosionArea2SituationMap::onTriggeredImpactsChanged, Qt::UniqueConnection);
m_aesDtc->explosionAreas([this](const AreaEffectSimulation::ExplosionArea &data)
{
handleChanged(data, DataModification::eAdded);
});
m_aesDtc->triggeredImpactss([this](const AreaEffectSimulation::TriggeredImpacts &data)
{
onTriggeredImpactsChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool ExplosionArea2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
const int32_t simId = ddsData.id();
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
const AreaEffectSimulation::AesEffectState effectState = ddsData.effectStateId().underlying();
mapObj->setAesState(effectState2aesState(effectState));
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtExplosionArea, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtExplosionArea) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool ExplosionArea2SituationMap::onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (data.aesTypeId() != AreaEffectSimulation::AesType::AtExplosionAreaSingleExplosions)
return false;
if (modType == DataModification::eRemoved)
{
return false;
}
const int32_t simId = data.aesItemId();
RefPointer<MAP_T> mapObj = this->getMapObjectOfSimId(simId);
if (!mapObj.valid())
{
INFO_LOG(m_logger) << LOGFUNCTION
<< " getMapObjectOfSimId failed"
<< " simId=" << simId;
return false;
}
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtExplosionAreaSingleExplosions, itemView))
{
const PositionCont &posCont = form2PosCont(itemView.form());
const auto &bitField = data.bitfield();
int32_t impactCount = data.impactCount();
if (impactCount != posCont.size())
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " size mismatch"
<< " impactCount=" << impactCount
<< " posCont.size()=" << posCont.size() ;
mapObj->setImpacts(posCont);
}
else
{
PositionCont posContImpacts;
posContImpacts.reserve(posCont.size());
for (int i = 0; i < posCont.size(); ++i)
{
if (!LtsUtils::BitArray::testBit(bitField, i))
posContImpacts.append(posCont.at(i));
}
mapObj->setImpacts(posContImpacts);
}
if (!mapObj->updateView())
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " updateView failed";
return false;
}
} else {
ERROR_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView(AtExplosionAreaSingleExplosions) found"
<< " simId=" << simId;
return false;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,46 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/area_fire.h>
#include <QObject>
namespace SituationMap
{
class ExplosionArea2SituationMap;
template <>
struct Aes2SituationMapTraits<ExplosionArea2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::ExplosionArea;
using MAP_TYPE = SituationMap::AreaFire;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtExplosionArea;
};
class ExplosionArea2SituationMap final : public Aes2SituationMap<ExplosionArea2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<ExplosionArea2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::ExplosionArea &data)> &cb) const
{
return m_aesDtc->explosionAreas(cb);
}
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
protected Q_SLOTS:
bool onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType);
};
}
@@ -0,0 +1,996 @@
#include "explosion_cluster_to_map.h"
#include "pdm_handler.h"
#include <LtsUtilsCore/dds_bitarray.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <AreaEffectSimulation/Utils/polygons.h>
#include <ParticipantManagement/ppm_dtc.h>
#include <Map/map.h>
#define ADD_UNIQUE_MAP_ID_TO_NOTIFIY(uniqueMapId) addUniqueMapIdToNotifiy(uniqueMapId, __FILE__, __LINE__)
#ifdef LTS_DEBUG
#endif
#ifdef BENCHMARK
# define BENCHMARK_SETUP_AND_START() QElapsedTimer elapsedTimer; elapsedTimer.start();
# define BENCHMARK_RUN
# define BENCHMARK_ALL_NOTIFIED
#else
# define BENCHMARK_SETUP_AND_START()
#endif
namespace SituationMap
{
static int s_effect3dMaxDisplayDuration = 5000;
ExplosionCluster2SituationMap::ExplosionCluster2SituationMap(PdmHandler *pdmHandler, ObjectFactory &objFac, const QString &layername, int drawOrder, const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, m_notifyTimer(new QTimer(this))
, m_pdmHandler(pdmHandler)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_notifyTimer->setInterval(100);
m_notifyTimer->setSingleShot(true);
connect(m_notifyTimer, &QTimer::timeout,
this, &ExplosionCluster2SituationMap::updateAllNotifiedItems);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
ExplosionCluster2SituationMap::~ExplosionCluster2SituationMap()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_notifyTimer->stop();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool ExplosionCluster2SituationMap::run()
{
QTimer::singleShot(1000, this, &ExplosionCluster2SituationMap::runDelayed);
return true;
}
bool ExplosionCluster2SituationMap::runDelayed()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
BENCHMARK_SETUP_AND_START();
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::explosionClusterChanged,
this, &ExplosionCluster2SituationMap::onExplosionClusterChanged, Qt::UniqueConnection);
m_aesDtc->enableEffects();
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::effectsChanged,
this, &ExplosionCluster2SituationMap::onEffectssChanged, Qt::UniqueConnection);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::trajectoryTimeAwareChanged,
this, &ExplosionCluster2SituationMap::onTracjectoryChanged, Qt::UniqueConnection);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &ExplosionCluster2SituationMap::onAesItemViewChanged, Qt::UniqueConnection);
m_aesDtc->explosionClusters([this](const AreaEffectSimulation::ExplosionCluster &data)
{
onExplosionClusterChanged(data, DataModification::eAdded);
});
#ifdef BENCHMARK_RUN
FATAL_LOG(m_logger) << LOGFUNCTION << " explosionClusters took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
m_aesDtc->trajectoryTimeAwares([this](const AreaEffectSimulation::TrajectoryTimeAware &data)
{
onTracjectoryChanged(data, DataModification::eAdded);
});
#ifdef BENCHMARK_RUN
FATAL_LOG(m_logger) << LOGFUNCTION << " trajectoryTimeAwares took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
connect(m_pluginProvider, &PluginProvider::partitionTimeChanged,
this, &ExplosionCluster2SituationMap::onPartitionTimeChanged, Qt::UniqueConnection);
#ifdef BENCHMARK_RUN
FATAL_LOG(m_logger) << LOGFUNCTION << " all took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
void ExplosionCluster2SituationMap::stop()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_notifyTimer->stop();
if (m_aesDtc)
m_aesDtc->disconnect(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool ExplosionCluster2SituationMap::updateVisibility(const Aes2SituationMap::DDS_TYPE &ddsData, RefPointer<Aes2SituationMap::MAP_TYPE> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, simId=" << getSimId(ddsData);
if (!BaseClass::updateVisibility(ddsData, mapObj))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " BaseClass::updateVisibility failed, simId=" << getSimId(ddsData);
return false;
}
const int32_t simId = ddsData.id();
const AreaEffectSimulation::AesEffectState effectState = ddsData.effectStateId().underlying();
bool bIsMode3D = false;
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
bIsMode3D = true;
{
bool bDisplayFilterShowGTL = true;
if (m_displayFilter)
bDisplayFilterShowGTL = m_displayFilter->showExplosionClusterGunToTargetLine();
const bool bDisplayFilterShowGFK = bDisplayFilterShowGTL && bIsMode3D &&
((effectState.underlying() != AreaEffectSimulation::AesEffectState_def::EsActivated) &&
(effectState.underlying() != AreaEffectSimulation::AesEffectState_def::EsExpired));
AreaEffectSimulation::AesItemView itemViewGunToTargetLine;
const std::vector<Core::GeoPosition>& form = itemViewGunToTargetLine.form();
if (bDisplayFilterShowGTL || bDisplayFilterShowGFK)
m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtExplosionClusterGunToTargetLine, itemViewGunToTargetLine);
if (bDisplayFilterShowGTL && (form.size() >= 2))
mapObj->setGunToTargetLineSurface(Point3D(form.front().lon(), form.front().lat(), 0.0),
Point3D(form.back().lon() , form.back().lat() , 0.0));
else
mapObj->setGunToTargetLineSurface(Point3D(), Point3D());
if (bIsMode3D)
{
if (bDisplayFilterShowGFK)
{
PositionCont gunToTargetPath;
gunToTargetPath.reserve(form.size());
for (const Core::GeoPosition& item : qAsConst(form))
gunToTargetPath.append(Point3D(item.lon(), item.lat(), item.z()));
mapObj->setGunToTargetTrajectory3D(gunToTargetPath);
} else {
mapObj->setGunToTargetTrajectory3D({});
}
}
}
updateAllTracjectories(simId);
{
bool bDisplayFilterShowMHP = true;
if (m_displayFilter)
bDisplayFilterShowMHP = m_displayFilter->showExplosionClusterMeanHitPoint();
if (bDisplayFilterShowMHP)
mapObj->setScheduledImpacts(form2PosCont(ddsData.mhPoints()));
else
mapObj->setScheduledImpacts({});
}
if (bIsMode3D)
updateEffects3DAllItems(simId);
ADD_UNIQUE_MAP_ID_TO_NOTIFIY(mapObj->uniqueMapId());
return true;
}
bool ExplosionCluster2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
BENCHMARK_SETUP_AND_START();
const int32_t simId = ddsData.id();
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
const AreaEffectSimulation::AesEffectState effectState = ddsData.effectStateId().underlying();
mapObj->setAesState(effectState2aesState(effectState));
LineStyle ls = mapObj->lineStyle();
if (ddsData.annotationString().empty())
ls.setLinePattern(LinePattern::Solid);
else
ls.setLinePattern(LinePattern::Dash);
mapObj->setLineStyle(ls);
#ifdef BENCHMARK_UPDATE_ELEMENT
FATAL_LOG(m_logger) << LOGFUNCTION << " part1 took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtExplosionCluster, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtExplosionCluster) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
#ifdef BENCHMARK_UPDATE_ELEMENT
FATAL_LOG(m_logger) << LOGFUNCTION << " aesItemViewFromEntityId took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
if (ddsData.partyId().is_set())
{
mapObj->setExtrusionHeight(20);
}
updateAllTracjectories(simId);
AreaEffectSimulation::Effects effectsOut;
m_aesDtc->effectsFromEntityId(simId, AreaEffectSimulation::AesType::AtExplosionClusterSingleExplosions, effectsOut);
onEffectssChanged(effectsOut, DataModification::eAdded);
#ifdef BENCHMARK_UPDATE_ELEMENT
FATAL_LOG(m_logger) << LOGFUNCTION << " updateAllTracjectories took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
updateVisibility(ddsData, mapObj);
#ifdef BENCHMARK_UPDATE_ELEMENT
FATAL_LOG(m_logger) << LOGFUNCTION << " all took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_simId2UniqueMapId.size();
#endif
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool ExplosionCluster2SituationMap::updateGeometry(const AreaEffectSimulation::AesItemView &aesItemView, RefPointer<AreaFire> mapObj)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
const int simId = aesItemView.aesItemId();
auto it = m_ddsDataContainer.find(simId);
if (it != m_ddsDataContainer.end())
updateNonLethalArea(mapObj, *it, aesItemView);
return BaseClass::updateGeometry(aesItemView, mapObj);
}
bool ExplosionCluster2SituationMap::removeElement(const int32_t simId)
{
return BaseClass::removeElement(simId);
}
bool ExplosionCluster2SituationMap::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &aesItemView, DataModification modType)
{
Q_UNUSED(modType);
const int simId = aesItemView.aesItemId();
TRACE_LOG(m_logger) << LOGFUNCTION << " START, simId=" << simId;
bool success = false;
if (aesItemView.aesTypeId() == AreaEffectSimulation::AesType::AtExplosionClusterGunToTargetLine)
{
RefPointer<MAP_T> mapObj = this->getMapObjectOfSimId(simId);
if (mapObj.valid())
updateVisibility(m_ddsDataContainer.value(simId), mapObj);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool ExplosionCluster2SituationMap::onEffectssChanged(const AreaEffectSimulation::Effects &effects, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", effects = " << effects
<< ", modType = " << modType;
if (effects.aesTypeId() != AreaEffectSimulation::AesType::AtExplosionClusterSingleExplosions)
return false;
const int aesItemId = effects.aesItemId();
const int simId = aesItemId;
RefPointer<MAP_T> mapObj = this->getMapObjectOfSimId(simId);
if (!mapObj.valid())
{
INFO_LOG(m_logger) << LOGFUNCTION
<< " getMapObjectOfSimId failed"
<< " simId=" << simId;
return false;
}
const std::vector<AreaEffectSimulation::SingleEffect> &singleEffectsRef = effects.singleEffects();
PositionCont posContImpactsDraped, posContImpactsAbsolute;
posContImpactsDraped.reserve(singleEffectsRef.size());
posContImpactsAbsolute.reserve(singleEffectsRef.size());
for (const AreaEffectSimulation::SingleEffect &se : qAsConst(singleEffectsRef))
{
if (se.singleEffectState().underlying() != AreaEffectSimulation::AesSingleEffectState_def::SesTriggered)
continue;
switch (se.zPlacement().underlying())
{
case AreaEffectSimulation::AesZPlacement_def::ZpDraped:
posContImpactsDraped.append({se.position().lon(), se.position().lat(), se.position().z()});
break;
case AreaEffectSimulation::AesZPlacement_def::ZpAbsolute:
posContImpactsAbsolute.append({se.position().lon(), se.position().lat(), se.position().z()});
break;
case AreaEffectSimulation::AesZPlacement_def::ZpRelative:
break;
}
}
mapObj->setImpacts(posContImpactsDraped);
mapObj->setImpactsAbsoluteHeight(posContImpactsAbsolute);
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
updateEffects3DSingleItem(effects);
ADD_UNIQUE_MAP_ID_TO_NOTIFIY(mapObj->uniqueMapId());
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< ", impacts = " << effects
<< ", modType = " << modType;
return true;
}
bool ExplosionCluster2SituationMap::updateGunToTargetLineAndTrajectory(const AreaEffectSimulation::AesItemView &itemView,
RefPointer<Sim2SituationMap::MAP_T> mapObj)
{
const std::vector<Core::GeoPosition>& formRef = itemView.form();
TRACE_LOG(m_logger) << LOGFUNCTION << " START, form.size = " << formRef.size();
if (formRef.size() >= 2)
{
mapObj->setGunToTargetLineSurface(Point3D(formRef.front().lon(), formRef.front().lat(), 0.0),
Point3D(formRef.back().lon() , formRef.back().lat() , 0.0));
} else {
mapObj->setGunToTargetLineSurface(Point3D(), Point3D());
}
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
{
PositionCont gunToTargetPath;
gunToTargetPath.reserve(formRef.size());
for (const Core::GeoPosition& item : qAsConst(formRef))
gunToTargetPath.append(Point3D(item.lon(), item.lat(), item.z()));
mapObj->setGunToTargetTrajectory3D(gunToTargetPath);
}
ADD_UNIQUE_MAP_ID_TO_NOTIFIY(mapObj->uniqueMapId());
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool ExplosionCluster2SituationMap::onTracjectoryChanged(const AreaEffectSimulation::TrajectoryTimeAware &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, modType=" << modType;
Q_UNUSED(modType);
updateSingleTracjectory(data);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, modType=" << modType;
return true;
}
PositionCont circle(const QPointF &center_geo, qreal radius, int steps= 72)
{
const LtsCoordTrans::UtmCoordinate &centerUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(center_geo);
PositionCont poly;
if (steps < 6)
steps = 6;
poly.reserve(steps);
for (int i = 0; i < 360; i += (360 / steps))
{
double angle = double(i) * LtsCoordTrans::deg2rad();
const QPointF &pointGeo = centerUtm.geographic(QPointF(cos(angle) * radius, sin(angle) * radius));
poly.push_back(Point3D(pointGeo.x(), pointGeo.y(), 0.0));
}
return poly;
}
bool ExplosionCluster2SituationMap::updateNonLethalArea(RefPointer<Sim2SituationMap::MAP_T> mapObj,
const AreaEffectSimulation::ExplosionCluster &explosionCluster,
const AreaEffectSimulation::AesItemView &aesItemView)
{
if (!m_pdmHandler)
return false;
if (explosionCluster.id() != aesItemView.aesItemId())
return false;
const int chargeTypeId = explosionCluster.chargeStruct().chargeTypeId();
const ProjectDataManagement::GearClass &gc = m_pdmHandler->gearClassFromChargeTypeId(chargeTypeId);
if (gc.underlying() == ProjectDataManagement::GearClass_def::AirSupport)
{
const QVector<ProjectDataManagement::CasEffect> &casEffectsVec = m_pdmHandler->casEffects(explosionCluster.chargeStruct());
if (casEffectsVec.size() >= 2)
{
const ProjectDataManagement::CasEffect &ce = casEffectsVec[1];
const double impactRadius = ce.impactRadius();
const AreaEffectSimulation::Area &areaRef = explosionCluster.area();
const Core::GeoPosition2D &blGeo = aesItemView.boundingBoxBottomLeft();
const QPointF &centerGeo = AreaEffectSimulation::Polygons::bottomLeft2CenterPoint(QPointF(blGeo.lon(), blGeo.lat()),
areaRef.width(), areaRef.height(), areaRef.rotation());
updateNonLethalArea(mapObj, centerGeo, impactRadius);
}
} else {
updateNonLethalArea(mapObj);
}
return true;
}
bool ExplosionCluster2SituationMap::updateNonLethalArea(RefPointer<Sim2SituationMap::MAP_T> mapObj, const QPointF &centerGeo, double radius)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, radius = " << radius;
if (!mapObj)
return false;
if (radius <= 0)
{
mapObj->setNonLethalArea({});
} else {
const PositionCont &nonLethalAreaPolygon = circle(centerGeo, radius);
mapObj->setNonLethalArea(nonLethalAreaPolygon);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool ExplosionCluster2SituationMap::updateSingleTracjectory(const AreaEffectSimulation::TrajectoryTimeAware &traj, bool considerTime)
{
if (traj.originatorTypeId() != ProjectDataManagement::StateChangeOriginator::AreaEffectSimulation)
return false;
const int32_t simId = traj.originatorId();
if (!m_simId2UniqueMapId.contains(simId))
return false;
bool bDisplayFilterShowTRJ = true;
if (m_displayFilter)
bDisplayFilterShowTRJ = m_displayFilter->showExplosionClusterTrajectory();
const int32_t index = traj.index();
TRACE_LOG(m_logger) << LOGFUNCTION << " START, traj=" << traj
<< ", simId=" << simId
<< ", index=" << index
<< ", considerTime=" << considerTime;
DEBUG_LOG(m_logger) << "START"
<< ", simId=" << simId
<< ", index=" << index
<< ", considerTime=" << considerTime;
const qint64 partitionTimeMsec = m_pluginProvider->partitionTime();
if (traj.trajectoryStartTime() > partitionTimeMsec)
return false;
RefPointer<MAP_T> mapObj = this->getMapObjectOfSimId(simId);
if (!mapObj.valid())
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " getMapObjectOfSimId failed"
<< " simId=" << simId;
return false;
}
bool bHasChanged = false;
const bool moIsVisibleByFilter = isVisibleByFilter(m_ddsDataContainer.value(simId));
if (bDisplayFilterShowTRJ && moIsVisibleByFilter)
{
const std::vector<Core::GeoPositionRelativeTime>& geometry = traj.geometry();
const PositionCont &curPath = mapObj->trajectory(index);
if (geometry.size() > static_cast<size_t>(curPath.size()))
{
PositionCont posCont;
posCont.reserve(geometry.size());
for (const Core::GeoPositionRelativeTime& posTime : qAsConst(geometry))
{
if (considerTime && ((traj.trajectoryStartTime() + posTime.relativeTime()) > partitionTimeMsec) )
break;
posCont.append(Point3D(posTime.lon(), posTime.lat(), posTime.z()));
}
INFO_LOG(m_logger) << "update trajectory, simId=" << simId
<< ", index=" << index
<< ", posCont.size() " << posCont.size();
if (posCont.size() == 1)
posCont.clear();
bHasChanged = mapObj->setTrajectory(index, posCont);
}
} else {
bHasChanged = mapObj->setTrajectory(index, {});
}
if (bHasChanged)
ADD_UNIQUE_MAP_ID_TO_NOTIFIY(mapObj->uniqueMapId());
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool ExplosionCluster2SituationMap::updateAllTracjectories(int simToRestrict)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
BENCHMARK_SETUP_AND_START();
#ifdef BENCHMARK_ALL_TRAC
FATAL_LOG(m_logger) << LOGFUNCTION << " trajectoryTimeAwares took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_uniqueMapIdsToUpdate.size()
<< ", size " << m_aesDtc->trajectoryTimeAwares().size()
#endif
auto cb = [this, simToRestrict](const AreaEffectSimulation::TrajectoryTimeAware &traj)
{
if (traj.originatorTypeId() != ProjectDataManagement::StateChangeOriginator::AreaEffectSimulation)
return;
const int aesItemId = traj.originatorId();
if ((simToRestrict < 0) || (simToRestrict == aesItemId))
updateSingleTracjectory(traj);
};
m_aesDtc->trajectoryTimeAwares(cb);
#ifdef BENCHMARK_ALL_TRAC
FATAL_LOG(m_logger) << LOGFUNCTION << " All took " << elapsedTimer.elapsed() << " [ms]"
<< ", size " << m_uniqueMapIdsToUpdate.size()
<< ", size " << m_aesDtc->trajectoryTimeAwares().size()
#endif
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool ExplosionCluster2SituationMap::updateEffects3DSingleItem(const AreaEffectSimulation::Effects &effects)
{
if (effects.aesTypeId() != AreaEffectSimulation::AesType_def::AtExplosionClusterSingleExplosions)
return false;
const int32_t simId = effects.aesItemId();
if (!m_simId2UniqueMapId.contains(simId))
return false;
RefPointer<MAP_T> mapObj = this->getMapObjectOfSimId(simId);
if (!mapObj.valid())
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " getMapObjectOfSimId failed"
<< " simId=" << simId;
return false;
}
bool bHasChanged = false;
const qint64 partitionTimeMsec = m_pluginProvider->partitionTime();
bool bDisplayFilterShowDetoSphere = true;
if (m_displayFilter)
bDisplayFilterShowDetoSphere = m_displayFilter->showExplosionClusterDetonationSphere();
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, simId=" << simId
<< ", bDisplayFilterShowDetoSphere=" << bDisplayFilterShowDetoSphere
<< ", partitionTimeMsec=" << partitionTimeMsec;
if (bDisplayFilterShowDetoSphere)
{
const std::vector<AreaEffectSimulation::SingleEffect> &singleEffectsRef = effects.singleEffects();
PositionCont posContImpactsDraped, posContImpactsAbsolute;
posContImpactsDraped.reserve(singleEffectsRef.size());
posContImpactsAbsolute.reserve(singleEffectsRef.size());
int i = 0;
for (const AreaEffectSimulation::SingleEffect &se : qAsConst(singleEffectsRef))
{
++i;
if (se.singleEffectState().underlying() != AreaEffectSimulation::AesSingleEffectState_def::SesTriggered)
continue;
const qint64 age = partitionTimeMsec - se.singleEffectTime();
const Core::GeoPosition &singleEffectPosGeo = se.position();
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId=" << simId << ", SingleEffect, i = " << i
<< ", age = " << age << ", s_effect3dMaxDisplayDuration = " << s_effect3dMaxDisplayDuration
<< ", singleEffectPosGeo = " << singleEffectPosGeo;
if (age > s_effect3dMaxDisplayDuration)
continue;
switch (se.zPlacement().underlying())
{
case AreaEffectSimulation::AesZPlacement_def::ZpDraped:
posContImpactsDraped.append({singleEffectPosGeo.lon(), singleEffectPosGeo.lat(), singleEffectPosGeo.z()});
break;
case AreaEffectSimulation::AesZPlacement_def::ZpAbsolute:
posContImpactsAbsolute.append({singleEffectPosGeo.lon(), singleEffectPosGeo.lat(), singleEffectPosGeo.z()});
break;
case AreaEffectSimulation::AesZPlacement_def::ZpRelative:
break;
}
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId=" << simId << ", posContImpactsDraped : " << posContImpactsDraped.size() << " von " << singleEffectsRef.size();
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId=" << simId << ", posContImpactsAbsolute: " << posContImpactsAbsolute.size() << " von " << singleEffectsRef.size();
double impactRadius = 5;
auto it = m_ddsDataContainer.find(simId);
if (it != m_ddsDataContainer.end())
impactRadius = m_pdmHandler->impactRadius(it->chargeStruct(), 5);
if (mapObj->setDetonationsDraped(posContImpactsDraped, impactRadius))
bHasChanged = true;
if (mapObj->setDetonationsAbsolute(posContImpactsAbsolute, impactRadius))
bHasChanged = true;
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId=" << simId
<< " impactRadius = " << impactRadius
<< ", bHasChanged = " << bHasChanged;
} else {
if (mapObj->setDetonationsDraped({}, 1))
bHasChanged = true;
if (mapObj->setDetonationsAbsolute({}, 1))
bHasChanged = true;
}
if (bHasChanged)
ADD_UNIQUE_MAP_ID_TO_NOTIFIY(mapObj->uniqueMapId());
return true;
}
bool ExplosionCluster2SituationMap::updateEffects3DAllItems(int simToRestrict)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
auto cb = [this, simToRestrict](const AreaEffectSimulation::Effects &effect)
{
if ((simToRestrict < 0) || (simToRestrict == effect.aesItemId()))
updateEffects3DSingleItem(effect);
};
m_aesDtc->effectss(cb);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void ExplosionCluster2SituationMap::updateAllNotifiedItems()
{
BENCHMARK_SETUP_AND_START();
std::string localLoggerName = m_logger.getLoggerName() + ".update";
LOGGER_T logger = m_logger.getNGLLogger(localLoggerName);
INFO_LOG(logger) << LOGFUNCTION << " m_uniqueMapIdsToUpdate.size() = " << m_uniqueMapIdsToUpdate.size();
for (int uniqueMapId : qAsConst(m_uniqueMapIdsToUpdate))
{
if (!m_uniqueMapId2SimId.contains(uniqueMapId))
continue;
RefPointer<MAP_T> mapObj = getMapObjectOfUniqueMapId(uniqueMapId);
if (!mapObj.valid())
continue;
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " updateView failed for "<< mapObj->debugInfo();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_uniqueMapIdsToUpdate.size()=" << m_uniqueMapIdsToUpdate.size();
#ifdef BENCHMARK_ALL_NOTIFIED
FATAL_LOG(m_logger) << LOGFUNCTION << " took " << elapsedTimer.elapsed() << " [ms]" << ", size " << m_uniqueMapIdsToUpdate.size();
#endif
m_uniqueMapIdsToUpdate.clear();
}
void ExplosionCluster2SituationMap::addUniqueMapIdToNotifiy(int uniqueMapId, const char *file, int lineNo)
{
std::string localLoggerName = m_logger.getLoggerName() + ".update";
LOGGER_T logger = m_logger.getNGLLogger(localLoggerName);
if (logger.isDebugEnabled())
{
const int simId = m_uniqueMapId2SimId.value(uniqueMapId, -1);
DEBUG_LOG(logger) << "START ******* addUniqueMapIdToNotifiy: uniqueMapId = " << uniqueMapId << " (simId=" << simId << "), caller= " << file << ":" << lineNo;
}
if (uniqueMapId > 0)
m_uniqueMapIdsToUpdate.insert(uniqueMapId);
if (!m_notifyTimer->isActive())
m_notifyTimer->start();
}
void ExplosionCluster2SituationMap::onPartitionTimeChanged(qint64 newPartitionTime)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, newPartitionTime=" << newPartitionTime
<< ", exerciseId = " << m_pluginProvider->exerciseId()
<< ", workspaceId = " << m_pluginProvider->workspaceId()
<< ", this=" << this;
updateAllTracjectories();
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
updateEffects3DAllItems();
}
AreaEffectSimulation::AesType ExplosionCluster2SituationMap::aesTypeFromGearClassChargeType(const DDS_TYPE &data)const
{
static QMap<int, AreaEffectSimulation::AesType> s_aesTypeMap;
if (s_aesTypeMap.contains(data.chargeStruct().chargeTypeId()))
return s_aesTypeMap[data.chargeStruct().chargeTypeId()];
const ProjectDataManagement::GearClass &gc = m_pdmHandler->gearClassFromChargeTypeId(data.chargeStruct().chargeTypeId());
switch (gc.underlying())
{
case ProjectDataManagement::GearClass::AirSupport:
s_aesTypeMap[data.chargeStruct().chargeTypeId()] = AreaEffectSimulation::AesType::AtAirSupportImpact;
break;
case ProjectDataManagement::GearClass::Artillery:
case ProjectDataManagement::GearClass::Mortar:
case ProjectDataManagement::GearClass::Rocket:
s_aesTypeMap[data.chargeStruct().chargeTypeId()] = AreaEffectSimulation::AesType::AtExplosionArea;
break;
default:
return AreaEffectSimulation::AesType::AtUnknown;
}
return s_aesTypeMap[data.chargeStruct().chargeTypeId()];
}
void ExplosionCluster2SituationMap::onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType)
{
TRACE_LOG(m_logger) << "START onAesDisplayFilterChanged, aesType =" << aesType
<< ", this " << this;
if ((AreaEffectSimulation::AesType_def::AtExplosionCluster != aesType.underlying()) &&
(AreaEffectSimulation::AesType_def::AtExplosionArea != aesType.underlying()) &&
(AreaEffectSimulation::AesType_def::AtAirSupportImpact != aesType.underlying()))
return;
const auto cb = [this](const DDS_TYPE &data) -> bool
{
if (isElapsed(data))
return false;
this->updateVisibility(data);
return false;
};
iterateAesData(cb);
TRACE_LOG(m_logger) << "END onAesDisplayFilterChanged, aesType =" << aesType
<< ", this " << this;
}
bool ExplosionCluster2SituationMap::isVisibleByFilter(const Aes2SituationMap::DDS_TYPE &data) const
{
if (!m_displayFilter)
return true;
const auto es = data.effectStart().is_set() ? data.effectStart().get() : 0;
const auto partyId = data.partyId().is_set() ? data.partyId().get() : -1;
bool isVisibleByFilter = partyId > 0 ? FilterClass::m_currentSymbolSettings.symbolSettings.symbolPartyAppearance.value(partyId).isVisible : true;
if (isVisibleByFilter)
{
AreaEffectSimulation::AesType aestype = aesTypeFromGearClassChargeType(data);
if (aestype == AreaEffectSimulation::AesType::AtUnknown)
{
WARNING_LOG(m_logger) << " Only AES TYPE explosion Cluster, AirSupportImpact, Explosion area will be displayed";
aestype = AreaEffectSimulation::AesType::AtExplosionArea;
}
isVisibleByFilter = m_displayFilter->isVisible(aestype,
data.effectStateId(),
data.chargeStruct().chargeTypeId(),
partyId,
data.isCentral(),
es,
data.effectDuration(),
m_pluginProvider->partitionTime());
}
return isVisibleByFilter;
}
bool ExplosionCluster2SituationMap::onExplosionClusterChanged(const AreaEffectSimulation::ExplosionCluster &explosionCluster, DataModification modType)
{
updateDdsDataContainer(explosionCluster, modType);
return BaseClass::handleChanged(explosionCluster, modType);
}
}
@@ -0,0 +1,98 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/area_fire.h>
#include <QSet>
#include <QTimer>
namespace SituationMap
{
class PdmHandler;
class ExplosionCluster2SituationMap;
template <>
struct Aes2SituationMapTraits<ExplosionCluster2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::ExplosionCluster;
using MAP_TYPE = SituationMap::AreaFire;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtExplosionCluster;
};
class ExplosionCluster2SituationMap final : public Aes2SituationMap<ExplosionCluster2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<ExplosionCluster2SituationMap>;
using BaseClass::BaseClass;
explicit ExplosionCluster2SituationMap(PdmHandler *pdmHandler,
ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName);
virtual ~ExplosionCluster2SituationMap();
bool run() override;
void stop() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::ExplosionCluster &data)> &cb) const
{
return m_aesDtc->explosionClusters(cb);
}
using BaseClass::updateVisibility;
bool updateVisibility(const DDS_TYPE &ddsData, RefPointer<MAP_TYPE> mapObj) override;
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool updateGeometry(const AreaEffectSimulation::AesItemView &aesItemView,
RefPointer<SituationMap::AreaFire> mapObj) override;
bool removeElement(const int32_t simId) override;
void onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType) override;
bool isVisibleByFilter(const DDS_TYPE &data) const override;
AreaEffectSimulation::AesType aesTypeFromGearClassChargeType(const Aes2SituationMap::DDS_TYPE &data) const;
protected Q_SLOTS:
bool runDelayed();
bool onExplosionClusterChanged(const AreaEffectSimulation::ExplosionCluster &explosionCluster, DataModification modType);
bool onAesItemViewChanged(const AreaEffectSimulation::AesItemView &aesItemView, DataModification modType);
bool onEffectssChanged(const AreaEffectSimulation::Effects &effects, DataModification modType);
bool updateGunToTargetLineAndTrajectory(const AreaEffectSimulation::AesItemView &itemView, RefPointer<Sim2SituationMap::MAP_T> mapObj);
bool onTracjectoryChanged(const AreaEffectSimulation::TrajectoryTimeAware &data, DataModification modType);
bool updateNonLethalArea(RefPointer<Sim2SituationMap::MAP_T> mapObj,
const AreaEffectSimulation::ExplosionCluster &explosionCluster,
const AreaEffectSimulation::AesItemView &aesItemView);
bool updateNonLethalArea(RefPointer<Sim2SituationMap::MAP_T> mapObj, const QPointF &centerGeo = QPointF(), double radius = 0);
bool updateSingleTracjectory(const AreaEffectSimulation::TrajectoryTimeAware &traj, bool considerTime = true);
bool updateAllTracjectories(int simToRestrict = -1);
bool updateEffects3DSingleItem(const AreaEffectSimulation::Effects& effects);
bool updateEffects3DAllItems(int simToRestrict = -1);
void updateAllNotifiedItems();
void addUniqueMapIdToNotifiy(int uniqueMapId, const char *file, int lineNo);
void onPartitionTimeChanged(qint64 newPartitionTime);
protected:
QTimer *m_notifyTimer{nullptr};
QSet<int> m_uniqueMapIdsToUpdate;
PdmHandler *m_pdmHandler{nullptr};
};
}
@@ -0,0 +1,90 @@
#include "explosion_single_to_map.h"
#include "pdm_handler.h"
#include <Map/bounding_box.h>
namespace SituationMap
{
ExplosionSingle2SituationMap::ExplosionSingle2SituationMap(PdmHandler *pdmHandler, ObjectFactory &objFac, const QString &layername, const char *loggerName)
: BaseClass(objFac, layername, loggerName)
, m_pdmHandler(pdmHandler)
{
}
bool ExplosionSingle2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (! m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::explosionSingleChanged,
this, &ExplosionSingle2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->explosionSingles([this](const AreaEffectSimulation::ExplosionSingle &data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool ExplosionSingle2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
const int32_t simId = ddsData.id();
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
mapObj->setAesState(effectState2aesState(ddsData.effectStateId().underlying()));
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtExplosionSingle, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtExplosionSingle) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
const Core::GeoPosition2D& impactPos2D = ddsData.impactPosition();
mapObj->setImpactOrigin(Point3D(impactPos2D.lon(), impactPos2D.lat(), 0.0));
if (m_pdmHandler && m_pdmHandler->isSmart(ddsData.chargeStruct()))
mapObj->setImpactType(SingleFire::ImpactType::doubleImpact);
else
mapObj->setImpactType(SingleFire::ImpactType::normalImpact);
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,51 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/single_fire.h>
#include <QObject>
namespace SituationMap
{
class PdmHandler;
class ExplosionSingle2SituationMap;
template <>
struct Aes2SituationMapTraits<ExplosionSingle2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::ExplosionSingle;
using MAP_TYPE = SituationMap::SingleFire;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtExplosionSingle;
};
class ExplosionSingle2SituationMap final : public Aes2SituationMap<ExplosionSingle2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<ExplosionSingle2SituationMap>;
using BaseClass::BaseClass;
ExplosionSingle2SituationMap(PdmHandler *pdmHandler,
ObjectFactory &objFac,
const QString &layername,
const char *loggerName);
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::ExplosionSingle &data)> &cb) const
{
return m_aesDtc->explosionSingles(cb);
}
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
PdmHandler *m_pdmHandler = nullptr;
};
}
@@ -0,0 +1,95 @@
#include "functional_area_to_map.h"
#include <Map/object_factory.h>
#include <Map/bounding_box.h>
namespace SituationMap
{
bool FunctionalArea2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
return false;
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::functionalAreaChanged,
this, &FunctionalArea2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->functionalAreas([this](const AreaEffectSimulation::FunctionalArea &data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool FunctionalArea2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
mapObj->setAesState(effectState2aesState(ddsData.effectStateId().underlying()));
const int32_t simId = ddsData.id();
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtFunctionalArea, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtFunctionalArea) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
if (ddsData.pointSymbol().is_set())
{
const QString pointSymbolSidc = QString::fromStdString(ddsData.pointSymbol().get());
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " pointSymbolSidc ='" << pointSymbolSidc << "'"
<< " simId=" << simId ;
mapObj->setPointSymbolSidc(pointSymbolSidc);
SituationMap::BoundingBox bbox;
mapObj->boundingBox(bbox);
Point3D center;
if (bbox.isValid())
{
center = bbox.center();
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " center ='" << center << "'"
<< " simId=" << simId ;
}
mapObj->setPointSymbolOrigin(center);
}
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,46 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/functional_area.h>
#include <QObject>
namespace SituationMap
{
class FunctionalArea2SituationMap;
template <>
struct Aes2SituationMapTraits<FunctionalArea2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::FunctionalArea;
using MAP_TYPE = SituationMap::FunctionalArea;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtFunctionalArea;
};
class FunctionalArea2SituationMap final : public Aes2SituationMap<FunctionalArea2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<FunctionalArea2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::FunctionalArea &data)> &cb) const
{
return m_aesDtc->functionalAreas(cb);
}
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
};
}
@@ -0,0 +1,70 @@
#include "gas_pipe_to_map.h"
#include <LtsUtilsCore/dds_bitarray.h>
namespace SituationMap
{
bool GasPipe2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::gasPipeChanged,
this, &GasPipe2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->gasPipes([this](const AreaEffectSimulation::GasPipe &data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool GasPipe2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
const int32_t simId = ddsData.id();
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtGasPipe, itemView))
{
this->updateGeometry(itemView, mapObj);
} else {
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtGasPipe) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,42 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/polygon.h>
#include <QObject>
namespace SituationMap
{
class GasPipe2SituationMap;
template <>
struct Aes2SituationMapTraits<GasPipe2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::GasPipe;
using MAP_TYPE = SituationMap::Polygon;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtGasPipe;
};
class GasPipe2SituationMap final : public Aes2SituationMap<GasPipe2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<GasPipe2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::GasPipe &data)> &cb) const
{
return m_aesDtc->gasPipes(cb);
}
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
};
}
@@ -0,0 +1,471 @@
#include "guez_ied_to_map.h"
#include <Map/object_factory.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <MathUtils/simple_helper.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Symbology/sidc_codec.h>
#include <Symbology/sidc_builder_base.h>
#include <FilterManagement/flt_aes_plugin_interface.h>
namespace SituationMap
{
GuezIed2SituationMap::GuezIed2SituationMap(ObjectFactory &objFac, const QString &layername, int drawOrder, const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
, m_pluginProvider(nullptr)
{
}
GuezIed2SituationMap::~GuezIed2SituationMap()
{
if (m_displayFilter)
m_displayFilter->removeChangedCallback(this);
}
int32_t GuezIed2SituationMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool GuezIed2SituationMap::init(PluginProvider *pluginProvider)
{
if (!pluginProvider)
return false;
m_pluginProvider = pluginProvider;
m_guezIedDtc = pluginProvider->gimDtc();
if (!m_guezIedDtc)
return false;
m_guezIedGuiIfc = pluginProvider->gimIfc();
m_guezIedDtc->enableIed(true);
m_guezIedDtc->enableIedPosition(true);
m_guezIedDtc->waitForHistoricalDataIed(1000);
m_guezIedDtc->waitForHistoricalDataIedPosition(1000);
FilterClass::init(m_pluginProvider);
auto fltAesIfc = pluginProvider->fltAesIfc();
if (fltAesIfc)
{
m_displayFilter = fltAesIfc->aesFilterForOperator(pluginProvider->operatorId(), pluginProvider->workspaceId());
if (m_displayFilter)
m_displayFilter->addChangedCallback(this);
}
onAesDisplayFilterChanged(AreaEffectSimulation::AesType_def::AtMineAreaSingleMines);
connect(m_pluginProvider, &PluginProvider::partitionTimeChanged,
this, &GuezIed2SituationMap::partitionTimeChanged);
return true;
}
bool GuezIed2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_guezIedDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_guezIedDtc.get(), &GuezIedManagement::Interface::Dtc::iedChanged,
this, &GuezIed2SituationMap::onIedChanged);
connect(m_guezIedDtc.get(), &GuezIedManagement::Interface::Dtc::iedPositionChanged,
this, &GuezIed2SituationMap::onIedPositionChanged);
m_guezIedDtc->ieds([this](const GuezIedManagement::Ied & data)
{
onIedChanged(data, DataModification::eAdded);
});
m_guezIedDtc->iedPositions([this](const GuezIedManagement::IedPosition & data)
{
onIedPositionChanged(data, DataModification::eAdded);
});
onAesDisplayFilterChanged(AreaEffectSimulation::AesType_def::AtMineAreaSingleMines);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool GuezIed2SituationMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
if (!m_guezIedGuiIfc)
return false;
const QVector<int32_t> &simIds = uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
m_guezIedGuiIfc->showInfoWindow(simIds);
return true;
}
bool GuezIed2SituationMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_guezIedDtc)
return false;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
RefPointer<MAP_T> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_image = mapObj->previewImage();
const auto cb = [simIdOut, &umodOut](const GuezIedManagement::Ied & data) -> bool
{
if (data.id() == simIdOut)
{
umodOut.m_equipmentNumber = data.equipmentNumber();
umodOut.m_partyId = data.partyId();
umodOut.m_description1 = QString::fromStdString(data.name());
umodOut.m_description2 = QString::number(data.explosiveForce());
return true;
}
return false;
};
std::function<bool(const GuezIedManagement::Ied &data)> cb1 = cb;
return m_guezIedDtc->ieds(cb1);
}
void GuezIed2SituationMap::onIedChanged(const GuezIedManagement::Ied &data,
DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
DEBUG_LOG(m_logger) << "onIedChanged: " << data;
updateDdsDataContainer(data, modType);
handleChanged(data, modType);
}
void GuezIed2SituationMap::onIedPositionChanged(const GuezIedManagement::IedPosition &data, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
DEBUG_LOG(m_logger) << "onIedPositionChanged: " << data;
const int32_t simId = data.id();
const Core::GeoPosition &geoPos = data.position();
auto it = m_simId2UniqueMapId.constFind(simId);
if (it == m_simId2UniqueMapId.constEnd())
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " GUEZ Ied not found simId = " << simId;
return;
}
const UniqueMapId uniqueMapId = it.value();
RefPointer<Sim2SituationMap::MAP_T> mapObj = m_objFac.get<Sim2SituationMap::MAP_T>(uniqueMapId);
if (mapObj)
{
mapObj->setOrigin(Point3D(geoPos.lon(), geoPos.lat(), geoPos.z()));
if (!mapObj->updateView())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " GUEZ Ied updateView failed"
<< " simId = " << simId
<< " uniqueMapId = " << uniqueMapId ;
return;
}
}
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " GUEZ Ied not found in objFac"
<< " simId = " << simId
<< " uniqueMapId = " << uniqueMapId ;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return;
}
Injury guezIedStateToInjury(const GuezIedManagement::IedTacticalState &iedState)
{
switch (iedState.underlying())
{
case GuezIedManagement::IedTacticalState::Active:
return AdvancedSymbology::Injury::NoInjury;
break;
default:
return AdvancedSymbology::Injury::TotalKill;
}
}
void updateIedPyro(const GuezIedManagement::IedTacticalState &iedStateIn,
AdvancedSymbology::Injury &injuryInOut,
QString &symbolInOut)
{
if (injuryInOut != AdvancedSymbology::Injury::TotalKill)
return;
switch (iedStateIn.underlying())
{
case GuezIedManagement::IedTacticalState::Unknown:
case GuezIedManagement::IedTacticalState::NotActive:
case GuezIedManagement::IedTacticalState::Active:
break;
case GuezIedManagement::IedTacticalState::TriggeredBySwitch:
case GuezIedManagement::IedTacticalState::TriggeredByRemote:
case GuezIedManagement::IedTacticalState::TriggeredByLightBarrier:
case GuezIedManagement::IedTacticalState::TriggeredByTautWire:
case GuezIedManagement::IedTacticalState::TriggeredByControlDevice:
{
const QString &bsc = AdvancedSymbology::SidcBuilderBase::concreteSidcToBaseSymbolCode(symbolInOut);
if ((bsc.compare(QStringLiteral("AP6D|BASE|40110300")) == 0 ||
bsc.compare(QStringLiteral("M25D|BASE|40110300")) == 0)
)
{
symbolInOut = QStringLiteral("AP6D|CMPL|10014000001103010000");
injuryInOut = AdvancedSymbology::Injury::NoInjury;
}
}
break;
case GuezIedManagement::IedTacticalState::Defused:
return;
}
}
bool GuezIed2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " id=" << ddsData.id()
<< " name=" << ddsData.name();
SymbolData symData = mapObj->symbol();
symData.sidc = QString::fromStdString(ddsData.symbol());
mapObj->setTextModifier(Participant::TextModifier::T_UniqueDesignation, QString::fromStdString(ddsData.name()));
mapObj->setTextModifier(Participant::TextModifier::M_HigherFormation, QString::number(ddsData.explosiveForce()));
mapObj->setPartyId(ddsData.partyId());
AdvancedSymbology::Injury injury = guezIedStateToInjury(ddsData.tacticalState());
if ((ddsData.type() == GuezIedManagement::IedType_def::IedSmallPyro) ||
(ddsData.type() == GuezIedManagement::IedType_def::IedBigPyro))
{
updateIedPyro(ddsData.tacticalState(), injury, symData.sidc);
}
int32_t injuryPartyId = -1;
mapObj->setInjury(injury, injuryPartyId);
mapObj->setSymbol(symData);
if (m_symbolAppearanceSettings)
handleSymbolAppearanceSettings(mapObj, ddsData);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void GuezIed2SituationMap::onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType)
{
DEBUG_LOG(m_logger) << "GuezIed2SituationMap";
if (!m_displayFilter || aesType != AreaEffectSimulation::AesType_def::AtMineAreaSingleMines)
return;
m_effectStateStruct = m_displayFilter->effectStateFilter(AreaEffectSimulation::AesType_def::AtMineAreaSingleMines);
handleSymbolAppearanceSettings();
return;
}
void GuezIed2SituationMap::onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part part)
{
if ((part != FilterManagement::SymbolAppearanceSettings::Part::All) &&
(part != FilterManagement::SymbolAppearanceSettings::Part::Symbol))
return;
const bool relevant = symbolAppearanceSettingsChangesAreRelevant(m_symbolAppearanceSettings->settings());
m_currentSymbolSettings = m_symbolAppearanceSettings->settings();
if (!relevant)
return;
handleSymbolAppearanceSettings();
}
bool GuezIed2SituationMap::symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale) ||
(m_currentSymbolSettings.symbolSettings.symbolTransparency != newSas.symbolSettings.symbolTransparency) ||
(m_currentSymbolSettings.symbolSettings.symbolPartyAppearance != newSas.symbolSettings.symbolPartyAppearance);
}
void GuezIed2SituationMap::handleSymbolAppearanceSettings()
{
for (const GuezIedManagement::Ied &ied : qAsConst(m_ddsDataContainer))
{
const UniqueMapId uniqueMapId = m_simId2UniqueMapId.value(ied.id(), INVALID_MAP_ID);
if (uniqueMapId == INVALID_MAP_ID)
{
WARNING_LOG(m_logger) << LOGFUNCTION << "Found a ied which is in internal map but has no map object...: " << ied.id();
continue;
}
RefPointer<MAP_T> mapObj = m_objFac.get<MAP_T>(uniqueMapId);
if (!mapObj.valid())
continue;
handleSymbolAppearanceSettings(mapObj, ied);
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " updateView failed,"
<< " mapObj = " << mapObj->debugInfo();
}
}
void GuezIed2SituationMap::handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj, const Sim2SituationMap::DDS_T &ddsData)
{
const FilterManagement::SymbolAppearanceSettings::Settings &filterSettings = m_symbolAppearanceSettings->settings();
mapObj->setScale(filterSettings.symbolSettings.symbolScale);
mapObj->setUserSymbolOpacity(1.0f - filterSettings.symbolSettings.symbolTransparency);
const auto spa = filterSettings.symbolSettings.symbolPartyAppearance.value(ddsData.partyId());
mapObj->setTextModifierVisibility(Participant::TextModifier::T_UniqueDesignation, spa.showDesignator);
mapObj->setTextModifierVisibility(Participant::TextModifier::M_HigherFormation, spa.showTacticalIdentifier);
const bool isVisi = isVisible(ddsData);
mapObj->setVisibility(isVisi);
}
bool GuezIed2SituationMap::isVisible(const Sim2SituationMap::DDS_T &ddsData) const
{
bool isVisi = visibleBySymbolPartyAppearance(ddsData) &&
visibleByAesFilter(ddsData);
return isVisi;
}
bool GuezIed2SituationMap::visibleBySymbolPartyAppearance(const Sim2SituationMap::DDS_T &ddsData) const
{
const FilterManagement::SymbolAppearanceSettings::Settings &filterSettings = m_symbolAppearanceSettings->settings();
const auto spa = filterSettings.symbolSettings.symbolPartyAppearance.value(ddsData.partyId());
return spa.isVisible;
}
bool GuezIed2SituationMap::visibleByAesFilter(const Sim2SituationMap::DDS_T &ddsData) const
{
if (!m_displayFilter)
return true;
switch (ddsData.tacticalState().underlying())
{
case GuezIedManagement::IedTacticalState_def::NotActive:
return m_effectStateStruct.displayPrepared;
case GuezIedManagement::IedTacticalState_def::Active:
return m_effectStateStruct.displayActivated;
case GuezIedManagement::IedTacticalState_def::Unknown:
return false;
case GuezIedManagement::IedTacticalState_def::Defused:
case GuezIedManagement::IedTacticalState_def::TriggeredByControlDevice:
case GuezIedManagement::IedTacticalState_def::TriggeredByLightBarrier:
case GuezIedManagement::IedTacticalState_def::TriggeredByRemote:
case GuezIedManagement::IedTacticalState_def::TriggeredBySwitch:
case GuezIedManagement::IedTacticalState_def::TriggeredByTautWire:
auto timeTriggered = ddsData.sampleTime();
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtMineAreaSingleMines);
const auto afterGlow = m_effectStateStruct.expiredAfterglowDurationMSec;
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " partitionTime=" << m_pluginProvider->partitionTime()
<< " timeTriggered" << timeTriggered
<< " afterGlow" << afterGlow
<< " timeTriggered + afterGlow=" << timeTriggered + afterGlow;
return (m_pluginProvider->partitionTime() < timeTriggered + afterGlow);
}
return true;
}
void GuezIed2SituationMap::partitionTimeChanged()
{
handleSymbolAppearanceSettings();
}
}
@@ -0,0 +1,96 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <GuezIedManagement/gim_data_plugin_interface.h>
#include <GuezIedManagement/gim_info_gui_plugin_interface.h>
#include <FilterManagement/flt_data_plugin_aes_display_filter.h>
#include <AreaEffectSimulation/aes_enums.hpp>
#include <MapObjects/participant.h>
namespace Buildings
{
class ForeignInfoGuiInterface;
}
namespace SituationMap
{
class GuezIed2SituationMap final : public Sim2SituationMap<GuezIedManagement::Ied, SituationMap::Participant>
, protected FilterManagement::AesDisplayFilter::FilterChangedCallback
, protected DdsFilterHandling<SituationMap::Participant>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<GuezIedManagement::Ied, SituationMap::Participant>;
using FilterClass = DdsFilterHandling<SituationMap::Participant>;
public:
GuezIed2SituationMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName);
~GuezIed2SituationMap();
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override
{
if (m_guezIedDtc)
m_guezIedDtc->disconnect(this);
if (m_pluginProvider)
disconnect(m_pluginProvider, &PluginProvider::partitionTimeChanged,
this, &GuezIed2SituationMap::partitionTimeChanged);
}
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
protected Q_SLOTS:
void onIedChanged(const GuezIedManagement::Ied &data, DataModification modType = DataModification::eAdded);
void onIedPositionChanged(const GuezIedManagement::IedPosition &data, DataModification modType = DataModification::eAdded);
void onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType) override;
protected:
void partitionTimeChanged();
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
void onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part part) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override;
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override
{
if (!mapObj.valid())
return;
const int simId = m_uniqueMapId2SimId.value(mapObj->uniqueMapId());
handleSymbolAppearanceSettings(mapObj, m_ddsDataContainer.value(simId));
}
void handleSymbolAppearanceSettings();
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj, const Sim2SituationMap::DDS_T &ddsData);
bool isVisible(const Sim2SituationMap::DDS_T &ddsData) const;
bool visibleBySymbolPartyAppearance(const Sim2SituationMap::DDS_T &ddsData) const;
bool visibleByAesFilter(const Sim2SituationMap::DDS_T &ddsData) const;
private:
std::shared_ptr<GuezIedManagement::Interface::Dtc> m_guezIedDtc;
std::shared_ptr<GuezIedManagement::ForeignGuiInterface> m_guezIedGuiIfc;
PluginProvider *m_pluginProvider;
std::shared_ptr<FilterManagement::AesDisplayFilter> m_displayFilter;
FilterManagement::AesDisplayFilter::EffectStateStruct m_effectStateStruct;
};
}
@@ -0,0 +1,350 @@
#include "guez_nasat_9liner.h"
#include <Map/object_factory.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <MathUtils/simple_helper.h>
#include <Common/PluginInterfaces/gui_plugin_interface.h>
#include <QPolygonF>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QTimer>
namespace SituationMap
{
int32_t GuezNasat9Liner2SituationMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
GuezNasat9Liner2SituationMap::GuezNasat9Liner2SituationMap(ObjectFactory &objFac, const QString &layername, int drawOrder, const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
, m_pluginProvider(nullptr)
, m_notifyTimer(new QTimer(this))
{
m_notifyTimer->setInterval(500);
m_notifyTimer->setSingleShot(true);
connect(m_notifyTimer, &QTimer::timeout,
this, &GuezNasat9Liner2SituationMap::updateAllItems);
}
GuezNasat9Liner2SituationMap::~GuezNasat9Liner2SituationMap()
{
m_notifyTimer->stop();
}
bool GuezNasat9Liner2SituationMap::init(PluginProvider *pluginProvider)
{
if (!pluginProvider)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no pluginProvider";
return false;
}
m_pluginProvider = pluginProvider;
m_gnaDtc = pluginProvider->gnaDtc();
if (!m_gnaDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_gnaDtc";
return false;
}
m_gnaDtc->enableNasat9Liner();
m_ppmDtc = pluginProvider->ppmDtc();
if (!m_ppmDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_ppmDtc";
return false;
}
FilterClass::init(m_pluginProvider);
connect(m_pluginProvider, &PluginProvider::partitionTimeChanged,
this, &GuezNasat9Liner2SituationMap::onPartitionTimeChanged);
return true;
}
bool GuezNasat9Liner2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_gnaDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
{
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::participantChanged,
this, &GuezNasat9Liner2SituationMap::onParticipantChanged, Qt::UniqueConnection);
m_ppmDtc->participants([this](const ParticipantManagement::Participant &data)
{
onParticipantChanged(data, DataModification::eAdded);
});
}
{
connect(m_gnaDtc.get(), &GuezNasat::Interface::Dtc::nasat9LinerChanged,
this, &GuezNasat9Liner2SituationMap::handleChanged, Qt::UniqueConnection);
m_gnaDtc->nasat9Liners([this](const GuezNasat::Nasat9Liner & data)
{
handleChanged(data, DataModification::eAdded);
});
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool GuezNasat9Liner2SituationMap::isElapsed(const GuezNasat::Nasat9Liner &ddsData) const
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " check ddsData=" << ddsData;
if (BaseClass::isElapsed(ddsData))
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " check ddsData=" << ddsData << " HIDE";
return true;
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " check ddsData=" << ddsData << " SHOW";
return false;
}
bool GuezNasat9Liner2SituationMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
const QVector<int32_t> &simIds = uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
return true;
}
bool GuezNasat9Liner2SituationMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_gnaDtc)
return false;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
RefPointer<MAP_T> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_image = mapObj->previewImage();
umodOut.m_description1 = QString::fromStdString(m_gnaDtc->nasat9Liner(simIdOut).name());
return true;
}
void GuezNasat9Liner2SituationMap::onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " pId=" << data.id()
<< " parytIdOld=" << m_participantToPartyId.value(data.id(), -1)
<< " parytId=" << data.partyId()
<< ", m_participantToPartyId.size()=" << m_participantToPartyId.size();
const int simId = data.id();
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
m_participantToPartyId[simId] = data.partyId();
break;
case DataModification::eRemoved:
m_ddsDataContainer.remove(simId);
break;
}
m_notifyTimer->start();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_participantToPartyId.size()=" << m_participantToPartyId.size();
}
bool GuezNasat9Liner2SituationMap::handleChanged(const Sim2SituationMap::DDS_T &ddsData, DataModification modType)
{
m_notifyTimer->start();
updateDdsDataContainer(ddsData, modType);
return BaseClass::handleChanged(ddsData, modType);
}
bool GuezNasat9Liner2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " id=" << ddsData.id()
<< " name=" << ddsData.name()
<< " isCurrent=" << ddsData.isCurrent()
<< " initialPoint=" << ddsData.initialPoint()
<< " targetPosition=" << ddsData.targetPosition()
<< " participantId=" << ddsData.participantId()
<< " m_participantToPartyId.size()=" << m_participantToPartyId.size()
<< " partyId.size()=" << m_participantToPartyId.value(ddsData.participantId(), -1);
mapObj->setPickable(false);
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setPartyId(m_participantToPartyId.value(ddsData.participantId(), -1));
TextStyle ts = mapObj->textStyle();
ts.setHorizontalAlignment(HorizontalAlignment::Center);
mapObj->setTextStyle(ts);
MAP_T::NineLinerData data;
data.initialPoint = Point3D(ddsData.initialPoint().lon(), ddsData.initialPoint().lat(), .0);
data.targetPosition = Point3D(ddsData.targetPosition().lon(), ddsData.targetPosition().lat(), .0);
data.fah = ddsData.finalAttackHeading();
data.fahLow = ddsData.finalAttackHeadingLow();
data.fahHigh = ddsData.finalAttackHeadingHigh();
data.friendliesBearing = ddsData.friendliesBearing();
data.friendliesDistance = ddsData.friendliesDistance();
mapObj->setNineLinerData(data);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool GuezNasat9Liner2SituationMap::symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale) ||
(m_currentSymbolSettings.symbolSettings.nasatNineLinerDisplayLengthMSec != newSas.symbolSettings.nasatNineLinerDisplayLengthMSec);
}
void GuezNasat9Liner2SituationMap::handleSymbolAppearanceSettings()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " m_ddsDataContainer.size()=" << m_ddsDataContainer.size();
for (const GuezNasat::Nasat9Liner &nineLiner : qAsConst(m_ddsDataContainer))
{
RefPointer<MAP_T> mapObj = getMapObjectOfSimId(nineLiner.id());
if (!mapObj.valid())
continue;
handleSymbolAppearanceSettings(mapObj, nineLiner);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " m_ddsDataContainer.size()=" << m_ddsDataContainer.size();
}
void GuezNasat9Liner2SituationMap::handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj)
{
if (!mapObj.valid())
return;
const int simId = m_uniqueMapId2SimId.value(mapObj->uniqueMapId());
handleSymbolAppearanceSettings(mapObj, m_ddsDataContainer.value(simId));
}
void GuezNasat9Liner2SituationMap::handleSymbolAppearanceSettings(RefPointer<Sim2SituationMap::MAP_T> mapObj, const Sim2SituationMap::DDS_T &ddsData)
{
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
const bool isVisi = visibleByDisplayLength(m_pluginProvider->partitionTime(), ddsData.sampleTime());
if (mapObj->visibility() != isVisi)
{
mapObj->setVisibility(isVisi);
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " updateView failed,"
<< " mapObj = " << mapObj->debugInfo();
}
}
bool GuezNasat9Liner2SituationMap::visibleByDisplayLength(const qint64 newPartitionTime, const qint64 stateTime) const
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " newPartitionTime = " << newPartitionTime
<< " stateTime = " << stateTime
<< " age = " << (newPartitionTime - stateTime)
<< " nasatNineLinerDisplayLengthMSec = " << m_currentSymbolSettings.symbolSettings.nasatNineLinerDisplayLengthMSec;
if (m_currentSymbolSettings.symbolSettings.nasatNineLinerDisplayLengthMSec < 0)
return true;
return (newPartitionTime - stateTime) <= m_currentSymbolSettings.symbolSettings.nasatNineLinerDisplayLengthMSec;
}
void GuezNasat9Liner2SituationMap::onPartitionTimeChanged()
{
handleSymbolAppearanceSettings();
}
void GuezNasat9Liner2SituationMap::updateAllItems()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, m_ddsDataContainer.size()=" << m_ddsDataContainer.size();
for (const DDS_T &ddsData : qAsConst(m_ddsDataContainer))
{
RefPointer<MAP_T> mapObj = getMapObjectOfSimId(ddsData.id());
if (!mapObj.valid())
continue;
updateElementImpl(ddsData, mapObj);
handleSymbolAppearanceSettings(mapObj);
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " updateView failed for "<< mapObj->debugInfo();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_ddsDataContainer.size()=" << m_ddsDataContainer.size();
}
}
@@ -0,0 +1,86 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/GuezNasat/gna_data_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
#include <MapObjects/polyline.h>
#include <MapObjects/nine_liner.h>
class QTimer;
namespace Buildings
{
class ForeignInfoGuiInterface;
}
namespace SituationMap
{
class GuezNasat9Liner2SituationMap final : public Sim2SituationMap<GuezNasat::Nasat9Liner, SituationMap::NineLiner>
, protected DdsFilterHandling<SituationMap::NineLiner>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<GuezNasat::Nasat9Liner, SituationMap::NineLiner>;
using FilterClass = DdsFilterHandling<SituationMap::NineLiner>;
public:
explicit GuezNasat9Liner2SituationMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName);
~GuezNasat9Liner2SituationMap();
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override
{
if (m_gnaDtc)
m_gnaDtc->disconnect(this);
if (m_ppmDtc)
m_ppmDtc->disconnect(this);
}
bool isElapsed(const GuezNasat::Nasat9Liner &ddsData) const override;
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
protected Q_SLOTS:
void onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType);
void updateAllItems();
protected:
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool handleChanged(const DDS_T &ddsData, DataModification modType);
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override;
void handleSymbolAppearanceSettings();
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override;
void handleSymbolAppearanceSettings(RefPointer<MAP_T> mapObj, const Sim2SituationMap::DDS_T &ddsData);
bool visibleByDisplayLength(const qint64 newPartitionTime, const qint64 stateTime) const;
void onPartitionTimeChanged();
private:
PluginProvider *m_pluginProvider{nullptr};
std::shared_ptr<GuezNasat::Interface::Dtc> m_gnaDtc;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
QHash<int, int> m_participantToPartyId;
QTimer *m_notifyTimer{nullptr};
QMap<int, qint64> m_lastSampleTimePerParticipant;
};
}
@@ -0,0 +1,541 @@
#include "hitlineinfo_to_map.h"
#include "pdm_handler.h"
#include <Map/object_factory.h>
#include <Map/map.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <LtsUtilsCore/outdated_position.h>
#include <MathUtils/simple_helper.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
#include <QDateTime>
#include <QTimer>
namespace SituationMap
{
HitlineInfo2SituationMap::HitlineInfo2SituationMap(PdmHandler *pdmHandler,
Participant2SituationMap *participant2SituationMap,
ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
, m_pdmHandler(pdmHandler)
, m_participant2SituationMap(participant2SituationMap)
, m_pBuildingHitlineCleanupTimer(new QTimer(this))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_pBuildingHitlineCleanupTimer->setInterval(1000 * 60 * 5);
connect(m_pBuildingHitlineCleanupTimer, &QTimer::timeout, this, &HitlineInfo2SituationMap::onCleanupBuildingHitlines);
m_pBuildingHitlineCleanupTimer->start();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
HitlineInfo2SituationMap::~HitlineInfo2SituationMap()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
int32_t HitlineInfo2SituationMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool HitlineInfo2SituationMap::init(PluginProvider *pluginProvider)
{
if (!pluginProvider ||
!pluginProvider->ppmDtc())
return false;
m_pluginProvider = pluginProvider;
m_ppmDtc = pluginProvider->ppmDtc();
if (!m_ppmDtc)
return false;
auto bldDtc = m_pluginProvider->bldDtc();
if (bldDtc)
{
connect(bldDtc.get(), &Buildings::Interface::Dtc::buildingHitLineInfoChanged,
this, &HitlineInfo2SituationMap::onBuildingHitlineInfoChanged);
bldDtc->buildingHitLineInfos([this](const Buildings::BuildingHitLineInfo & data)
{
onBuildingHitlineInfoChanged(data, DataModification::eAdded);
});
}
FilterClass::init(m_pluginProvider);
connect(m_pluginProvider, &PluginProvider::partitionTimeChanged,
this, &HitlineInfo2SituationMap::onPartitionTimeChanged);
return true;
}
bool HitlineInfo2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_ppmDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::hitLineInfoChanged,
this, &HitlineInfo2SituationMap::onHitLineInfoChanged);
m_ppmDtc->hitLineInfos([this](const Sim2SituationMap::DDS_T & ddsData)
{
onHitLineInfoChanged(ddsData, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void HitlineInfo2SituationMap::stop()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (m_ppmDtc)
m_ppmDtc->disconnect(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool HitlineInfo2SituationMap::isElapsed(const ParticipantManagement::HitLineInfo &ddsData) const
{
const Core::GeoPosition &startGeoPos = ddsData.originatorPos();
const Core::GeoPosition &endGeoPos = ddsData.injuryPos();
{
Point3D dummy(startGeoPos.lon(), startGeoPos.lat(), startGeoPos.z());
if (dummy.isNull())
return true;
}
{
Point3D dummy(endGeoPos.lon(), endGeoPos.lat(), endGeoPos.z());
if (dummy.isNull())
return true;
}
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
{
if (startGeoPos.z() < 0)
return true;
if (endGeoPos.z() < 0)
return true;
}
return false;
}
bool HitlineInfo2SituationMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
auto ppmParticipantInfoIfc = m_pluginProvider->ppmParticipantInfoIfc();
if (!ppmParticipantInfoIfc)
return false;
const QVector<qint32> &simIds = uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
ppmParticipantInfoIfc->showHitLineInfoWindow(simIds);
return true;
}
QString HitlineInfo2SituationMap::chargeTypeIdentifier(const int32_t originatorChargeTypeId) const
{
if (!m_pdmHandler)
return QStringLiteral("ctId_%1").arg(originatorChargeTypeId);
QString chargeTypeString = m_pdmHandler->trChargeTypeShortName(originatorChargeTypeId);
if (chargeTypeString.isEmpty())
return QStringLiteral("ctId_%1").arg(originatorChargeTypeId);
return chargeTypeString;
}
bool HitlineInfo2SituationMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_ppmDtc)
return false;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
RefPointer<MAP_T> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_image = mapObj->previewImage();
const auto cb = [this, simIdOut, &umodOut](const Sim2SituationMap::DDS_T & ddsData) -> bool
{
if (ddsData.id() == simIdOut)
{
umodOut.m_partyId = ddsData.originatorPartyId();
const int32_t originatorChargeTypeId = ddsData.chargeTypeId();
umodOut.m_description1 = chargeTypeIdentifier(originatorChargeTypeId);
return true;
}
return false;
};
std::function<bool(const Sim2SituationMap::DDS_T &ddsData)> cb1 = cb;
return m_ppmDtc->hitLineInfos(cb1);
}
bool HitlineInfo2SituationMap::onHitLineInfoChanged(const Sim2SituationMap::DDS_T &ddsData,
DataModification modType)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< ", ddsData.id()=" << ddsData.id()
<< ", ddsData.injuryBuildingId()=" << ddsData.injuryBuildingId()
<< ", modType=" << modType
<< ", m_buildingHits.size()=" << m_buildingHits.size();
if (((modType==DataModification::eAdded) || (modType==DataModification::eModified)) &&
(!visibleByBldgHitlines(ddsData))
)
{
DEBUG_LOG(m_logger) << "Not showing participant hitline " << ddsData <<
" since there is already a hitline on the building";
return true;
}
updateDdsDataContainer(ddsData, modType);
return handleChanged(ddsData, modType);
}
void HitlineInfo2SituationMap::onBuildingHitlineInfoChanged(const Buildings::BuildingHitLineInfo &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", data.id()=" << data.id()
<< ", data.originatorParticipantId()=" << data.originatorParticipantId()
<< ", data.buildingId()=" << data.buildingId()
<< ", modType=" << modType
<< ", m_buildingHits.size()=" << m_buildingHits.size();
if (modType != DataModification::eAdded && modType != DataModification::eModified)
return;
BuildingHit bh;
bh.sampleTime = data.sampleTime();
bh.originatorParticipantId = data.originatorParticipantId();
bh.chargeTypeId = data.chargeTypeId();
m_buildingHits[data.buildingId()].push_back(bh);
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< ", data.id()=" << data.id()
<< ", data.originatorParticipantId()=" << data.originatorParticipantId()
<< ", data.buildingId()=" << data.buildingId()
<< ", modType=" << modType
<< ", m_buildingHits.size()=" << m_buildingHits.size();
}
void HitlineInfo2SituationMap::onCleanupBuildingHitlines()
{
const qint64 tNow = QDateTime::currentMSecsSinceEpoch();
const auto isOutdated = [tNow](const BuildingHit &bh)
{
return LtsUtils::isPositionTimeOutdated(tNow, bh.sampleTime);
};
for (auto &hitLines : m_buildingHits)
hitLines.erase(std::remove_if(hitLines.begin(), hitLines.end(), isOutdated), hitLines.end());
}
bool HitlineInfo2SituationMap::createElement(const DDS_T &ddsData)
{
const int32_t simId = getSimId(ddsData);
if (!m_simId2UniqueMapId.contains(simId))
{
INFO_LOG(m_logger) << LOGFUNCTION << " new Hitline !!!!" << " simId = " << simId;
const SpecialChargeType specialChargeTypeId = m_pdmHandler->isSpecialChargeType(ddsData.chargeTypeId());
if (PdmHandler::isChargeTypeLtdOrLrf(specialChargeTypeId))
m_participant2SituationMap->onParticipantFakeGearEventChanged(ddsData.originatorParticipantId(), ddsData.sampleTime(), specialChargeTypeId);
}
return BaseClass::createElement(ddsData);
}
bool HitlineInfo2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
const qint32 hitlineId = ddsData.id();
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " id=" << hitlineId;
mapObj->setVisibility(SituationMap::ObjectAppearance::Tactical, false);
mapObj->rLineStyle().setLineWidth(3);
LineStyle ls = mapObj->lineStyle();
const SpecialChargeType sct = m_pdmHandler->isSpecialChargeType(ddsData.chargeTypeId());
switch (sct)
{
case SpecialChargeType::LRF:
ls.setLinePattern(LinePattern::Dot);
break;
case SpecialChargeType::LTD:
ls.setLinePattern(LinePattern::Solid);
break;
case SpecialChargeType::NoneSpecial:
default:
ls.setLinePattern(LinePattern::Dash);
}
mapObj->setLineStyle(ls);
mapObj->setPartyId(ddsData.originatorPartyId());
const int32_t originatorChargeTypeId = ddsData.chargeTypeId();
mapObj->setIdentifier(chargeTypeIdentifier(originatorChargeTypeId));
const Core::GeoPosition &startGeoPos = ddsData.originatorPos();
const Core::GeoPosition &endGeoPos = ddsData.injuryPos();
mapObj->setStartAndEndPoint(Point3D(startGeoPos.lon(), startGeoPos.lat(), startGeoPos.z()),
Point3D(endGeoPos.lon(), endGeoPos.lat(), endGeoPos.z()));
handleSymbolAppearanceSettings(mapObj, ddsData);
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " id=" << hitlineId;
return true;
}
void HitlineInfo2SituationMap::onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part part)
{
if ((part != FilterManagement::SymbolAppearanceSettings::Part::All) &&
(part != FilterManagement::SymbolAppearanceSettings::Part::Symbol))
return;
const bool relevant = symbolAppearanceSettingsChangesAreRelevant(m_symbolAppearanceSettings->settings());
m_currentSymbolSettings = m_symbolAppearanceSettings->settings();
if (!relevant)
return;
handleSymbolAppearanceSettings();
}
bool HitlineInfo2SituationMap::symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const
{
return qFuzzyCompare(m_currentSymbolSettings.symbolSettings.symbolScale, newSas.symbolSettings.symbolScale) ||
(m_currentSymbolSettings.symbolSettings.symbolPartyAppearance != newSas.symbolSettings.symbolPartyAppearance) ||
(m_currentSymbolSettings.symbolSettings.hitLineDisplayLengthMSec != newSas.symbolSettings.hitLineDisplayLengthMSec||
(m_currentSymbolSettings.symbolSettings.lrfLineDisplayLengthMSec != newSas.symbolSettings.lrfLineDisplayLengthMSec)||
(m_currentSymbolSettings.symbolSettings.ltdLineDisplayLengthMSec != newSas.symbolSettings.ltdLineDisplayLengthMSec));
}
void HitlineInfo2SituationMap::handleSymbolAppearanceSettings()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " m_ddsDataContainer.size()=" << m_ddsDataContainer.size();
for (const ParticipantManagement::HitLineInfo &hitline : qAsConst(m_ddsDataContainer))
{
RefPointer<MAP_T> mapObj = getMapObjectOfSimId(hitline.id());
if (!mapObj.valid())
continue;
handleSymbolAppearanceSettings(mapObj, hitline);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " m_ddsDataContainer.size()=" << m_ddsDataContainer.size();
}
void HitlineInfo2SituationMap::handleSymbolAppearanceSettings(RefPointer<MAP_T> mapObj, const Sim2SituationMap::DDS_T &ddsData)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " ddsData.id()=" << ddsData.id()
<< ", mapObj = " << mapObj->debugInfo();
const FilterManagement::SymbolAppearanceSettings::Settings &filterSettings = m_symbolAppearanceSettings->settings();
mapObj->setScale(filterSettings.symbolSettings.symbolScale);
bool bUncertain = false;
const bool isVisi = isVisible(ddsData, &bUncertain);
if (bUncertain)
{
QTimer::singleShot(200, this, [this, ddsData]()
{
RefPointer<MAP_T> mapObj = getMapObjectOfSimId(ddsData.id());
if (!mapObj.valid())
return;
handleSymbolAppearanceSettings(mapObj, ddsData);
});
}
if (mapObj->visibility() != isVisi)
{
mapObj->setVisibility(isVisi);
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " updateView failed,"
<< " mapObj = " << mapObj->debugInfo();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " ddsData.id()=" << ddsData.id()
<< ", mapObj = " << mapObj->debugInfo();
}
bool HitlineInfo2SituationMap::isVisible(const Sim2SituationMap::DDS_T &ddsData, bool *bUncertain) const
{
return
visibleByBldgHitlines(ddsData) &&
visibleBySymbolPartyAppearance(ddsData) &&
visibleByHitLineDisplayLength(m_pluginProvider->partitionTime(), ddsData) &&
visibleByParticipants(ddsData, bUncertain);
}
bool HitlineInfo2SituationMap::visibleBySymbolPartyAppearance(const Sim2SituationMap::DDS_T &ddsData) const
{
const FilterManagement::SymbolAppearanceSettings::Settings &filterSettings = m_symbolAppearanceSettings->settings();
const auto spa = filterSettings.symbolSettings.symbolPartyAppearance.value(ddsData.originatorPartyId());
return spa.isVisible;
}
bool HitlineInfo2SituationMap::visibleByParticipants(const Sim2SituationMap::DDS_T &ddsData, bool *bUncertain) const
{
if (!m_participant2SituationMap)
return true;
bool bParticipant1Exists = true;
bool bParticipant2Exists = true;
bool visi =
m_participant2SituationMap->isParticipantVisible(ddsData.originatorParticipantId(), &bParticipant1Exists) &&
m_participant2SituationMap->isParticipantVisible(ddsData.injuryParticipantId(), &bParticipant2Exists);
if ((!bParticipant1Exists || !bParticipant2Exists) && bUncertain)
*bUncertain = true;
return visi;
}
bool HitlineInfo2SituationMap::visibleByBldgHitlines(const Sim2SituationMap::DDS_T &ddsData) const
{
auto itBuildingHit = m_buildingHits.constFind(ddsData.injuryBuildingId());
if (itBuildingHit != m_buildingHits.constEnd())
{
const QVector<BuildingHit> &bHits = itBuildingHit.value();
qint64 displayLength = m_currentSymbolSettings.symbolSettings.hitLineDisplayLengthMSec;
const SpecialChargeType sct = m_pdmHandler->isSpecialChargeType(ddsData.chargeTypeId());
switch (sct)
{
case SpecialChargeType::LRF:
displayLength = m_currentSymbolSettings.symbolSettings.lrfLineDisplayLengthMSec;
break;
case SpecialChargeType::LTD:
displayLength = m_currentSymbolSettings.symbolSettings.ltdLineDisplayLengthMSec;
break;
case SpecialChargeType::NoneSpecial:
default:
break;
}
for (const BuildingHit &bh : bHits)
{
if (bh.chargeTypeId == ddsData.chargeTypeId() &&
bh.originatorParticipantId == ddsData.originatorParticipantId() &&
ddsData.sampleTime() - displayLength < bh.sampleTime)
{
DEBUG_LOG(m_logger) << "Not showing participant hitline " << ddsData << " since there is already a hitline on the building";
return false;
}
}
}
return true;
}
bool HitlineInfo2SituationMap::visibleByHitLineDisplayLength(const qint64 newPartitionTime, const Sim2SituationMap::DDS_T &ddsData) const
{
const qint64 stateTime = ddsData.sampleTime();
qint64 displayLength = m_currentSymbolSettings.symbolSettings.hitLineDisplayLengthMSec;
const SpecialChargeType sct = m_pdmHandler->isSpecialChargeType(ddsData.chargeTypeId());
switch (sct)
{
case SpecialChargeType::LRF:
displayLength = m_currentSymbolSettings.symbolSettings.lrfLineDisplayLengthMSec;
break;
case SpecialChargeType::LTD:
displayLength = m_currentSymbolSettings.symbolSettings.ltdLineDisplayLengthMSec;
break;
case SpecialChargeType::NoneSpecial:
default:
break;
}
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " newPartitionTime = " << newPartitionTime
<< " stateTime = " << stateTime
<< " age = " << (newPartitionTime - stateTime)
<< " SpecialChargeType = " << sct
<< " displayLengthMSec = " << displayLength;
if (displayLength <= 0)
return false;
return (newPartitionTime - stateTime) <= displayLength;
}
void HitlineInfo2SituationMap::onPartitionTimeChanged()
{
handleSymbolAppearanceSettings();
}
}
@@ -0,0 +1,105 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include "participant_to_map.h"
#include <MapObjects/hit_line.h>
#include <Buildings/bld_dtc.h>
#include <FilterManagement/flt_dtc.h>
#include <ParticipantManagement/ppm_dtc.h>
#include <ParticipantManagement/ppm_participant_info_gui_plugin_interface.h>
#include <memory>
namespace SituationMap
{
class PdmHandler;
class HitlineInfo2SituationMap final : public Sim2SituationMap<ParticipantManagement::HitLineInfo, SituationMap::HitLine>
, protected DdsFilterHandling<SituationMap::HitLine>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<ParticipantManagement::HitLineInfo, SituationMap::HitLine>;
using FilterClass = DdsFilterHandling<SituationMap::HitLine>;
public:
HitlineInfo2SituationMap(PdmHandler *pdmHandler,
Participant2SituationMap *participant2SituationMap,
ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName);
~HitlineInfo2SituationMap();
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override;
bool isElapsed(const ParticipantManagement::HitLineInfo &ddsData) const override;
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
QString chargeTypeIdentifier(const int32_t originatorChargeTypeId) const;
protected Q_SLOTS:
bool onHitLineInfoChanged(const Sim2SituationMap::DDS_T &ddsData, DataModification modType = DataModification::eAdded);
void onBuildingHitlineInfoChanged(const Buildings::BuildingHitLineInfo &data, DataModification modType);
void onCleanupBuildingHitlines();
protected:
bool isVisible(const Sim2SituationMap::DDS_T &ddsData, bool *bUncertain) const;
bool visibleBySymbolPartyAppearance(const Sim2SituationMap::DDS_T &ddsData) const;
bool visibleByParticipants(const Sim2SituationMap::DDS_T &ddsData, bool *bUncertain) const;
bool visibleByBldgHitlines(const Sim2SituationMap::DDS_T &ddsData) const;
bool visibleByHitLineDisplayLength(const qint64 newPartitionTime, const DDS_T &ddsData) const;
void onPartitionTimeChanged();
bool createElement(const DDS_T &ddsData) override;
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
void onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part part) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override;
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override
{
if (!mapObj.valid())
return;
const int simId = m_uniqueMapId2SimId.value(mapObj->uniqueMapId());
handleSymbolAppearanceSettings(mapObj, m_ddsDataContainer.value(simId));
}
void handleSymbolAppearanceSettings();
void handleSymbolAppearanceSettings(RefPointer<MAP_T> mapObj, const Sim2SituationMap::DDS_T &ddsData);
private:
PluginProvider *m_pluginProvider = nullptr;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
PdmHandler *m_pdmHandler = nullptr;
QPointer<Participant2SituationMap> m_participant2SituationMap;
struct BuildingHit
{
int64_t sampleTime = 0;
int originatorParticipantId = 0;
int chargeTypeId = 0;
};
QHash<int, QVector<BuildingHit>> m_buildingHits;
QTimer *m_pBuildingHitlineCleanupTimer = nullptr;
};
}
@@ -0,0 +1,22 @@
#pragma once
namespace SituationMap
{
enum class MapObjectType {
MOT_Undefined,
MOT_Participant,
MOT_Aes,
MOT_Building,
MOT_Bridge,
MOT_MountingPoint,
MOT_GuezIed,
MOT_TrainingArea,
MOT_SpecialArea,
MOT_ShootbackArea
};
}
@@ -0,0 +1,440 @@
#include "mine_area_null_to_map.h"
#include <AreaEffectSimulation/Utils/polygons.h>
#include <AreaEffectSimulation/Utils/ddsdbconvert.h>
#include <ProjectDataManagement/pdm_dtc.h>
#include <LtsUtilsCore/dds_bitarray.h>
#include <SituationMap/Symbology/sidc_codec.h>
namespace SituationMap
{
DusMineStateProxy::DusMineStateProxy(QObject *parent)
: BaseClass(parent)
, m_lastDusMineState()
, m_lastItemView()
, m_logger(getLogger("DusMineStateProxy"))
{
}
bool DusMineStateProxy::init(PluginProvider *pluginProvider)
{
if (!pluginProvider)
return false;
m_aesDtc = pluginProvider->aesDtc();
return m_aesDtc != nullptr;
}
bool DusMineStateProxy::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::dusMineStateChanged,
this, static_cast<bool (DusMineStateProxy::*)(const AreaEffectSimulation::DusMineState&, DataModification)>(&DusMineStateProxy::handleChanged), Qt::UniqueConnection);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, static_cast<bool (DusMineStateProxy::*)(const AreaEffectSimulation::AesItemView&, DataModification)>(&DusMineStateProxy::handleChanged), Qt::UniqueConnection);
const std::function<bool(const AreaEffectSimulation::DusMineState &)> cbDusMineState = [this] (const AreaEffectSimulation::DusMineState &data) -> bool
{ return handleChanged(data, DataModification::eAdded); };
m_aesDtc->dusMineStates(cbDusMineState);
const std::function<bool(const AreaEffectSimulation::AesItemView &)> cbAesItemView = [this] (const AreaEffectSimulation::AesItemView &data) -> bool
{ return handleChanged(data, DataModification::eAdded); };
m_aesDtc->aesItemViews(cbAesItemView);
return true;
}
void DusMineStateProxy::stop()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
this->disconnect();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool DusMineStateProxy::dusMineStateAndPositionDatas(const std::function<void (const DusMineStateAndPositionData &)> &cb)
{
if (m_map.isEmpty())
return false;
for (auto it = m_map.constBegin(); it != m_map.constEnd(); ++it)
cb(it.value());
return true;
}
bool DusMineStateProxy::dusMineStateAndPositionDatas(const std::function<bool (const DusMineStateAndPositionData &)> &cb)
{
if (m_map.isEmpty())
return false;
for (auto it = m_map.constBegin(); it != m_map.constEnd(); ++it)
if (cb(it.value()))
return true;
return false;
}
bool DusMineStateProxy::handleChanged(const AreaEffectSimulation::DusMineState &ddsData, DataModification modType)
{
Q_UNUSED(modType);
if (ddsData.id() != 0)
return false;
TRACE_LOG(m_logger) << LOGFUNCTION << " START, ddsData.id()=" << ddsData.id()
<< " ddsData.mines().size() = " << ddsData.mines().size();
if (modType == DataModification::eRemoved)
m_lastDusMineState = AreaEffectSimulation::DusMineState();
else
m_lastDusMineState = ddsData;
return publishNewMap();
}
bool DusMineStateProxy::handleChanged(const AreaEffectSimulation::AesItemView &ddsData, DataModification modType)
{
Q_UNUSED(modType);
if (ddsData.id() != AreaEffectSimulation::AesType::AtMineAreaSingleMines)
return false;
TRACE_LOG(m_logger) << LOGFUNCTION << " START, ddsData.id()=" << ddsData.id()
<< " ddsData.form().size() = " << ddsData.form().size();
if (modType == DataModification::eRemoved)
m_lastItemView = AreaEffectSimulation::AesItemView();
else
m_lastItemView = ddsData;
return publishNewMap();
}
bool DusMineStateProxy::publishNewMap()
{
if (m_lastItemView.setId() != m_lastDusMineState.setId())
return false;
const QMap<int32_t, DusMineStateAndPositionData> &mapContVeryNew = getFromDds();
QMapIterator<int32_t, DusMineStateAndPositionData> mapItRetrieved(mapContVeryNew);
while (mapItRetrieved.hasNext())
{
mapItRetrieved.next();
if (m_map.contains(mapItRetrieved.key()))
emit dusMineStateChanged(mapItRetrieved.value(), DataModification::eModified);
else
emit dusMineStateChanged(mapItRetrieved.value(), DataModification::eAdded);
}
QMapIterator<int32_t, DusMineStateAndPositionData> mapItRemoved(m_map);
while (mapItRemoved.hasNext())
{
mapItRemoved.next();
if (! mapContVeryNew.contains(mapItRemoved.key()))
emit dusMineStateChanged(mapItRemoved.value(), DataModification::eRemoved);
}
m_map = mapContVeryNew;
DEBUG_LOG(m_logger) << "Publishing new dus-mine map to situationMap adapter";
return true;
}
const QMap<int32_t, DusMineStateAndPositionData> DusMineStateProxy::getFromDds()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, ddsData.id()=" << m_lastDusMineState.id()
<< " ddsData.mines().size() = " << m_lastDusMineState.mines().size();
QMap<int32_t, DusMineStateAndPositionData> mapCont;
const auto size = m_lastDusMineState.mines().size();
const auto &mines = m_lastDusMineState.mines();
if (m_logger.isDebugEnabled())
{
int idx = 0;
for (const AreaEffectSimulation::DusMine &mine : mines)
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " idx=" << idx++
<< ", eqId=" << mine.eqId()
<< ", chargeTypeId=" << mine.chargeTypeId();
}
}
if (size != m_lastItemView.form().size())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " ddsData.id()=" << m_lastDusMineState.id()
<< " size does not match"
<< " ddsData.mines().size() = " << mines.size()
<< " itemView.form().size() = " << m_lastItemView.form().size();
return mapCont;
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " ddsData.id()=" << m_lastDusMineState.id()
<< " size ::"
<< " ddsData.mines().size() = " << mines.size()
<< " itemView.form().size() = " << m_lastItemView.form().size();
for (size_t i = 0; i < size; ++i)
{
const AreaEffectSimulation::DusMine &dusMine = mines[i];
const Core::GeoPosition2D &pos = m_lastItemView.form().at(i);
DusMineStateAndPositionData dmsDdsData(dusMine.eqId(),
{dusMine.chargeTypeId(),0,0},
dusMine.triggered(),
pos
);
DEBUG_LOG(m_logger) << LOGFUNCTION << " i=" << i << ", id/eqId=" << dusMine.eqId() << ", pos=" << pos;
mapCont.insert(dusMine.eqId(), dmsDdsData);
}
return mapCont;
}
bool DusMineStateProxy::getItemView(AreaEffectSimulation::AesItemView &itemView)
{
int aesType = static_cast<int>(AreaEffectSimulation::AesType::inner_enum::AtMineAreaSingleMines);
const AreaEffectSimulation::AesItemView &localItemView = m_aesDtc->aesItemView(aesType);
if (localItemView.id() != aesType)
return false;
itemView = localItemView;
return true;
}
bool MineAreaNull2SituationMap::init(PluginProvider *pluginProvider)
{
if (!BaseClass::init(pluginProvider))
return false;
if (!m_dusMineStateProxy)
{
m_dusMineStateProxy = new DusMineStateProxy(this);
if (!m_dusMineStateProxy->init(pluginProvider))
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed for DusMineStateProxy";
}
return true;
}
bool MineAreaNull2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_dusMineStateProxy)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no DusMineStateProxy";
return false;
}
m_dusMineStateProxy->run();
connect(m_dusMineStateProxy, &DusMineStateProxy::dusMineStateChanged,
this, &MineAreaNull2SituationMap::handleChanged, Qt::UniqueConnection);
m_dusMineStateProxy->dusMineStateAndPositionDatas([this](const DusMineStateAndPositionData & data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void MineAreaNull2SituationMap::stop()
{
if (m_dusMineStateProxy)
m_dusMineStateProxy->stop();
}
bool MineAreaNull2SituationMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
auto sp = m_aesInfoIfc.lock();
if (!sp)
return false;
const QVector<int32_t> &simIds = this->uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
sp->showInfoWindow(simIds, AreaEffectSimulation::AesType_def::AtMineAreaSingleMines);
return true;
}
bool MineAreaNull2SituationMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_dusMineStateProxy)
return false;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
RefPointer<MAP_T> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_symDataToRender = mapObj->symbolDataToRender();
const auto cb = [simIdOut, &umodOut](const DusMineStateAndPositionData &data) -> bool
{
if (data.id() == simIdOut)
{
umodOut.m_description1 = QString::number(data.id());
umodOut.m_description2 = data.triggered() ? tr("disarmed") : tr("armed");
return true;
}
return false;
};
std::function<bool(const DusMineStateAndPositionData &data)> cb1 = cb;
return m_dusMineStateProxy->dusMineStateAndPositionDatas(cb1);
}
bool MineAreaNull2SituationMap::updateVisibility(const Aes2SituationMap::DDS_TYPE &ddsData, RefPointer<Aes2SituationMap::MAP_TYPE> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, simId=" << getSimId(ddsData);
if (!BaseClass::updateVisibility(ddsData, mapObj))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " BaseClass::updateVisibility failed, simId=" << getSimId(ddsData);
return false;
}
AreaEffectSimulation::AesItemView itemView;
bool bUpdateView = false;
if (m_displayFilter )
{
mapObj->setVisibility(m_displayFilter->showNotTriggeredCDMine()
&& this->isVisibleByFilter(ddsData));
bUpdateView = true;
}
if (bUpdateView && !mapObj->updateView())
ERROR_LOG(m_logger)<< LOGFUNCTION << " simId = " << getSimId(ddsData) << " XXXX updateView failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void MineAreaNull2SituationMap::onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType)
{
if (AreaEffectSimulation::AesType_def::AtMineArea != aesType.underlying())
return;
const auto cb = [this](const DDS_TYPE &data) -> bool
{
if (data.isDeleted())
return false;
this->updateVisibility(data);
return false;
};
iterateAesData(cb);
}
bool MineAreaNull2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
const int32_t simId_eqId = ddsData.id();
SymbolData symData;
symData.sidc = AdvancedSymbology::SidcCodec::encodeComplete( mapObj->symbologyType(), "10011500002101000000" );
symData.color = Qt::yellow;
symData.size = 1.0;
mapObj->setSymbol(symData);
SituationMap::Injury injury = SituationMap::Injury::NoInjury;
if (ddsData.triggered())
injury = SituationMap::Injury::TotalKill;
mapObj->setInjury(injury, QColor(Qt::black));
mapObj->setVisibility(true);
mapObj->setOrigin(Point3D(ddsData.position().lon(), ddsData.position().lat(), .0));
mapObj->setTextModifier(Participant::TextModifier::M_HigherFormation, QString::number(simId_eqId));
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool MineAreaNull2SituationMap::symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale) ||
(m_currentSymbolSettings.symbolSettings.symbolTransparency != newSas.symbolSettings.symbolTransparency)
;
}
void MineAreaNull2SituationMap::handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj)
{
mapObj->setUserSymbolOpacity(1.0f - m_currentSymbolSettings.symbolSettings.symbolTransparency);
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
}
}
@@ -0,0 +1,219 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/participant.h>
#include <QObject>
namespace SituationMap
{
class AesItemProxy
{
public:
class EffectStart final
{
public:
static bool is_set() { return false; }
static qint64 get() { return 0; }
};
class PartyId final
{
public:
static bool is_set() { return false; }
static qint64 get() { return -1; }
};
explicit AesItemProxy(int32_t id = 0,
const AreaEffectSimulation::ChargeStruct &chargeStruct = {-1,0,0},
const Core::GeoPosition2D &form = Core::GeoPosition2D())
: m_id_param(id),
m_chargeStruct(chargeStruct),
m_form_param(form)
{}
virtual ~AesItemProxy() = default;
int32_t id() const { return m_id_param; }
void setId(const int32_t &value) { m_id_param = value; }
static std::string name() { return std::string(); }
static bool isDeleted() { return false; }
static EffectStart effectStart() { return {}; }
static PartyId partyId() { return {}; }
static bool isCentral() { return false;}
static AreaEffectSimulation::AesEffectState effectStateId() { return AreaEffectSimulation::AesEffectState_def::EsCreated;}
AreaEffectSimulation::ChargeStruct chargeStruct() const { return m_chargeStruct; }
int chargeTypeId() const { return m_chargeStruct.chargeTypeId(); }
static qint64 effectDuration() { return -1; }
Core::GeoPosition2D position() const { return m_form_param; }
private:
int32_t m_id_param;
AreaEffectSimulation::ChargeStruct m_chargeStruct;
Core::GeoPosition2D m_form_param;
};
class DusMineStateAndPositionData : public AesItemProxy
{
public:
using BaseClass = AesItemProxy;
explicit DusMineStateAndPositionData(int32_t id = 0,
const AreaEffectSimulation::ChargeStruct &chargeStruct = {-1,0,0},
bool triggered = false,
const Core::GeoPosition2D &form = Core::GeoPosition2D()
)
: BaseClass(id, chargeStruct, form),
m_triggered(triggered)
{}
virtual ~DusMineStateAndPositionData() = default;
bool triggered() const { return m_triggered; }
void setTriggered(bool onOff) { m_triggered = onOff; }
private:
bool m_triggered;
};
class MineAreaNull2SituationMap;
class DusMineStateProxy final : public QObject
{
Q_OBJECT
public:
using BaseClass = QObject;
explicit DusMineStateProxy(QObject *parent = nullptr);
~DusMineStateProxy() = default;
bool init(PluginProvider *pluginProvider);
bool run();
void stop();
virtual bool dusMineStateAndPositionDatas(const std::function<void(const DusMineStateAndPositionData &data)> &cb);
virtual bool dusMineStateAndPositionDatas(const std::function<bool(const DusMineStateAndPositionData &data)> &cb);
Q_SIGNALS:
void dusMineStateChanged(const DusMineStateAndPositionData &dusMineStateAndPositionData, DataModification modType);
protected:
bool handleChanged(const AreaEffectSimulation::DusMineState &ddsData, DataModification modType);
bool handleChanged(const AreaEffectSimulation::AesItemView &ddsData, DataModification modType);
bool publishNewMap();
const QMap<int32_t, DusMineStateAndPositionData> getFromDds();
bool getItemView(AreaEffectSimulation::AesItemView &itemView);
std::shared_ptr<AreaEffectSimulation::Interface::Dtc> m_aesDtc;
AreaEffectSimulation::DusMineState m_lastDusMineState;
AreaEffectSimulation::AesItemView m_lastItemView;
QMap<int32_t, DusMineStateAndPositionData> m_map;
QSharedPointer<MineAreaNull2SituationMap> m_mineAreaNull2SituationMap;
LOGGER_T m_logger;
};
class MineAreaNull2SituationMap;
template <>
struct Aes2SituationMapTraits<MineAreaNull2SituationMap>
{
using DDS_TYPE = DusMineStateAndPositionData;
using MAP_TYPE = SituationMap::Participant;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtMineArea;
};
class MineAreaNull2SituationMap final : public Aes2SituationMap<MineAreaNull2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<MineAreaNull2SituationMap>;
using BaseClass::BaseClass;
bool init(PluginProvider *pluginProvider) override;
bool run() override;
void stop() override;
bool iterateAesData(const std::function<bool(const DDS_TYPE &data)> &cb) const
{
if (!m_dusMineStateProxy)
return false;
return m_dusMineStateProxy->dusMineStateAndPositionDatas(cb);
}
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
using BaseClass::updateVisibility;
bool updateVisibility(const DDS_TYPE &ddsData, RefPointer<MAP_TYPE> mapObj) override;
protected:
void onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType) override;
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool updateSingleMines(const int simId,
RefPointer<MAP_T> mapObj);
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override;
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override;
protected Q_SLOTS:
private:
DusMineStateProxy *m_dusMineStateProxy = nullptr;
};
}
@@ -0,0 +1,451 @@
#include "mine_area_to_map.h"
#include <AreaEffectSimulation/Utils/polygons.h>
#include <AreaEffectSimulation/Utils/ddsdbconvert.h>
#include <ProjectDataManagement/pdm_dtc.h>
#include <LtsUtilsCore/dds_bitarray.h>
namespace SituationMap
{
bool MineArea2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
m_triggeredImpacts.clear();
m_aesItemViewForImpacts.clear();
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::mineAreaChanged,
this, &MineArea2SituationMap::handleChanged, Qt::UniqueConnection);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::triggeredImpactsChanged,
this, &MineArea2SituationMap::onTriggeredImpactsChanged, Qt::UniqueConnection);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &MineArea2SituationMap::onAesItemViewChanged, Qt::UniqueConnection);
m_aesDtc->mineAreas([this](const AreaEffectSimulation::MineArea &data)
{
handleChanged(data, DataModification::eAdded);
});
m_aesDtc->triggeredImpactss([this](const AreaEffectSimulation::TriggeredImpacts &data)
{
onTriggeredImpactsChanged(data, DataModification::eAdded);
});
m_aesDtc->aesItemViews([this](const AreaEffectSimulation::AesItemView &data)
{
onAesItemViewChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool MineArea2SituationMap::updateVisibility(const DDS_TYPE &data, RefPointer<MAP_TYPE> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, simId=" << getSimId(data);
if (!BaseClass::updateVisibility(data, mapObj))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " BaseClass::updateVisibility failed, simId=" << getSimId(data);
return false;
}
bool bDisplayFilterShowDetails = true;
if (m_displayFilter)
bDisplayFilterShowDetails = m_displayFilter->showDetails(AreaEffectSimulation::AesType_def::AtMineArea);
const bool bShowDetails = mapObj->visibility() && bDisplayFilterShowDetails;
bool bUpdateView = false;
if (bShowDetails != mapObj->mineVisibility(MineField::MineState::Activated))
{
mapObj->setMineVisibility(MineField::MineState::Activated, bShowDetails);
bUpdateView = true;
}
if (bShowDetails != mapObj->mineVisibility(MineField::MineState::DeActivated))
{
mapObj->setMineVisibility(MineField::MineState::DeActivated, bShowDetails);
bUpdateView = true;
}
if (bUpdateView)
if (!mapObj->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " simId = " << getSimId(data) << " XXXX updateView failed";
return true;
}
bool MineArea2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
const int32_t simId = ddsData.id();
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
mapObj->setAesState(effectState2aesState(ddsData.effectStateId().underlying()));
{
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtMineArea, itemView))
{
this->updateGeometry(itemView, mapObj);
} else {
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtMineArea) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
const QVector<AreaEffectSimulation::Database::AesMineAreaSegment> segments(AreaEffectSimulation::DdsDbConvert::mineAreaSegments(ddsData));
const QVector<QPolygonF> singleSegments(AreaEffectSimulation::Polygons::mineAreaSingleSegments(segments, ddsData.width(), ddsData.isCenterLine()));
QList<int> keysInUse = mapObj->keysInUse();
int segmentIdx = -1;
PositionCont posCont;
for(const QPolygonF &singleSegment : singleSegments)
{
++segmentIdx;
posCont.clear();
posCont.reserve(singleSegment.size());
for (auto item : singleSegment)
posCont.append(Point3D(item.x(), item.y(), .0));
mapObj->setSegment(segmentIdx, posCont);
keysInUse.removeAll(segmentIdx);
}
for (auto item : qAsConst(keysInUse))
if (item >= 0)
mapObj->removeSegment(item);
}
auto itTi = m_triggeredImpacts.constFind(simId);
if (itTi != m_triggeredImpacts.cend())
onTriggeredImpactsChanged(itTi.value(), DataModification::eAdded);
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool MineArea2SituationMap::updateGeometry(const AreaEffectSimulation::AesItemView &data,
RefPointer<SituationMap::MineField> mapObj)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
const PositionCont &posCont = form2PosCont(data.form());
mapObj->setSegment(-1, posCont);
mapObj->setPositions(posCont);
DEBUG_LOG(m_logger) << LOGFUNCTION << " END, posCont.size() = " << posCont.size();
return true;
}
void MineArea2SituationMap::onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
const int32_t simId = data.aesItemId();
if (simId < 0)
return;
if (data.aesTypeId() != AreaEffectSimulation::AesType::AtMineAreaSingleMines)
return;
if (simId == 0)
return;
if (modType == DataModification::eRemoved)
{
m_triggeredImpacts.remove(simId);
return;
}
m_triggeredImpacts[simId] = data;
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << simId
<< " m_triggeredImpacts updated";
updateMines(simId);
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " simId = " << simId;
}
void MineArea2SituationMap::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " data.aesTypeId()=" << data.aesTypeId() << " modType=" << modType;
const int32_t simId = data.aesItemId();
if (simId < 0)
return;
{
if (data.aesTypeId() == AreaEffectSimulation::AesType::AtMineArea)
{
RefPointer<MAP_T> mapObj = this->getMapObjectOfSimId(simId);
if (!mapObj.valid())
{
INFO_LOG(m_logger) << LOGFUNCTION
<< " getMapObjectOfSimId failed"
<< ", simId = " << simId
<< ", modType=" << modType;
return;
}
updateGeometry(data, mapObj);
}
}
if (data.aesTypeId() != AreaEffectSimulation::AesType::AtMineAreaSingleMines)
return;
if (modType == DataModification::eRemoved)
{
m_aesItemViewForImpacts.remove(simId);
return;
}
m_aesItemViewForImpacts[simId] = data;
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << simId
<< " m_aesItemViewForImpacts updated";
updateMines(simId);
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " simId = " << simId;
}
bool MineArea2SituationMap::completeMissingData(int32_t simId,
AreaEffectSimulation::TriggeredImpacts &dataTriggeredImpacts,
AreaEffectSimulation::AesItemView &dataAesItemView) const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " simId = " << simId;
if (simId < 0)
return false;
auto itAIV = m_aesItemViewForImpacts.find(simId);
if (itAIV == m_aesItemViewForImpacts.constEnd())
{
INFO_LOG(m_logger) << LOGFUNCTION << " simId = " << simId
<< " no AesItemViewForImpacts found.";
return false;
}
dataAesItemView = itAIV.value();
auto itTI = m_triggeredImpacts.find(simId);
if (itTI == m_triggeredImpacts.constEnd())
{
INFO_LOG(m_logger) << LOGFUNCTION << " simId = " << simId
<< " no TriggeredImpacts found.";
return false;
}
dataTriggeredImpacts = itTI.value();
const int32_t impactCount = dataTriggeredImpacts.impactCount();
const int32_t formSize = dataAesItemView.form().size();
if (impactCount != formSize)
{
WARNING_LOG(m_logger) << LOGFUNCTION
<< " simId = " << simId
<< " size mismatch"
<< " impactCount=" << impactCount
<< " formSize.size()=" << formSize;
return false;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " simId = " << simId;
return true;
}
bool MineArea2SituationMap::updateMines(const int32_t simId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " simId = " << simId;
if (simId < 0)
return false;
RefPointer<MAP_T> mapObj = this->getMapObjectOfSimId(simId);
if (!mapObj.valid())
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " getMapObjectOfSimId failed"
<< " simId = " << simId << " (maybe expired)";
return false;
}
AreaEffectSimulation::TriggeredImpacts dataTriggeredImpacts;
AreaEffectSimulation::AesItemView dataAesItemView;
bool bothTopicsMatch = completeMissingData(simId, dataTriggeredImpacts, dataAesItemView);
const PositionCont &posCont = form2PosCont(dataAesItemView.form());
if (bothTopicsMatch)
{
PositionCont posContActivated;
PositionCont posContDeActivated;
posContActivated.reserve(posCont.size());
posContDeActivated.reserve(posCont.size());
const auto &bitField = dataTriggeredImpacts.bitfield();
for (int i = 0; i < posCont.size(); ++i)
{
const Point3D &point = posCont.at(i);
if (LtsUtils::BitArray::testBit(bitField, i))
posContActivated.append(point);
else
posContDeActivated.append(point);
}
mapObj->setPositionsMine(MineField::MineState::Activated, posContActivated);
mapObj->setPositionsMine(MineField::MineState::DeActivated, posContDeActivated);
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " size match -> posContActivated " << posContActivated.size();
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " size match -> posContDeActivated " << posContDeActivated.size();
}
else
{
INFO_LOG(m_logger) << LOGFUNCTION << " simId = " << simId
<< " bothTopicsMatch = " << bothTopicsMatch
<< " on initial, there is no TriggeredImpacts published. In that case interpret all positions as active..";
mapObj->setPositionsMine(MineField::MineState::Activated, posCont);
mapObj->setPositionsMine(MineField::MineState::DeActivated, PositionCont());
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " size mismatch -> all active";
}
if (!mapObj->updateView())
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " simId = " << simId
<< " updateView failed";
return false;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " simId = " << simId;
return true;
}
}
@@ -0,0 +1,62 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/mine_field.h>
#include <QObject>
namespace SituationMap
{
class MineArea2SituationMap;
template <>
struct Aes2SituationMapTraits<MineArea2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::MineArea;
using MAP_TYPE = SituationMap::MineField;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtMineArea;
};
class MineArea2SituationMap final : public Aes2SituationMap<MineArea2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<MineArea2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::MineArea &data)> &cb) const
{
return m_aesDtc->mineAreas(cb);
}
bool updateVisibility(const DDS_TYPE &data, RefPointer<MAP_TYPE> mapObj) override;
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool updateGeometry(const AreaEffectSimulation::AesItemView &data,
RefPointer<SituationMap::MineField> mapObj) override;
bool updateSingleMines(const int simId,
RefPointer<MAP_T> mapObj);
protected Q_SLOTS:
void onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType);
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
protected:
bool completeMissingData(int32_t simId,
AreaEffectSimulation::TriggeredImpacts &dataTriggeredImpacts,
AreaEffectSimulation::AesItemView &dataAesItemView) const;
bool updateMines(const int32_t simId);
private:
QMap<int32_t, AreaEffectSimulation::TriggeredImpacts> m_triggeredImpacts;
QMap<int32_t, AreaEffectSimulation::AesItemView> m_aesItemViewForImpacts;
};
}
@@ -0,0 +1,76 @@
#include "mine_corridor_to_map.h"
#include <AreaEffectSimulation/Utils/polygons.h>
#include <AreaEffectSimulation/Utils/ddsdbconvert.h>
#include <LtsUtilsCore/dds_bitarray.h>
namespace SituationMap
{
bool MineCorridor2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::mineCorridorChanged,
this, &MineCorridor2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->mineCorridors([this](const AreaEffectSimulation::MineCorridor &data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool MineCorridor2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
const int32_t simId = ddsData.id();
QColor color(Qt::gray);
color.setAlpha(175);
mapObj->rLineStyle().setLineColor(color);
mapObj->rFillStyle().setFillColor(color);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtMineCorridor, itemView))
{
this->updateGeometry(itemView, mapObj);
} else {
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtMineCorridor) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,42 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/polygon.h>
#include <QObject>
namespace SituationMap
{
class MineCorridor2SituationMap;
template <>
struct Aes2SituationMapTraits<MineCorridor2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::MineCorridor;
using MAP_TYPE = SituationMap::Polygon;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtMineCorridor;
};
class MineCorridor2SituationMap final : public Aes2SituationMap<MineCorridor2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<MineCorridor2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::MineCorridor &data)> &cb) const
{
return m_aesDtc->mineCorridors(cb);
}
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
};
}
@@ -0,0 +1,905 @@
#include "mounting_point_to_map.h"
#include <Map/map.h>
#include <Map/object_factory.h>
#include <Map/layer_factory.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <InfrastructureManagement/ism_translation.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonArray>
#include <QGuiApplication>
#include <sstream>
namespace SituationMap
{
QString toString(ResourceManagerMode rmm)
{
switch (rmm) {
case ResourceManagerMode::Undefined:
return QStringLiteral("RMM_Undefined");
break;
case ResourceManagerMode::RMM_PlanActivityView:
return QStringLiteral("RMM_PlanActivityView");
break;
case ResourceManagerMode::RMM_PlanDefinitionView:
return QStringLiteral("RMM_PlanDefinitionView");
break;
case ResourceManagerMode::RMM_ComponentMonitor:
return QStringLiteral("RMM_ComponentMonitor");
break;
}
return QStringLiteral("RMM_UNKNOWN");
}
bool MountingPointToMap::init(PluginProvider *pluginProvider, bool resourceMode)
{
if (!pluginProvider ||
!pluginProvider->ismDtc() ||
!pluginProvider->ismDataIfc())
return false;
m_resourceMode = resourceMode;
m_pluginProvider = pluginProvider;
INFO_LOG(m_logger) << LOGFUNCTION << " m_resourceMode=" << m_resourceMode
<< " exerciseId=" << m_pluginProvider->exerciseId();
FilterClass::init(m_pluginProvider);
m_ismDtc = m_pluginProvider->ismDtc();
m_ismDataIfc = m_pluginProvider->ismDataIfc();
m_ismGuiIfc = m_pluginProvider->ismGuiIfc();
m_cmoDtc = m_pluginProvider->cmoDtc();
InfrastructureManagement::MountingPoint::init();
m_handleAllMountingPointsTimer = new QTimer(this);
m_handleAllMountingPointsTimer->setInterval(1500);
m_handleAllMountingPointsTimer->setSingleShot(true);
connect(m_handleAllMountingPointsTimer, &QTimer::timeout,
this, &MountingPointToMap::onHandleAllMountingPoints);
#ifdef SUPPORT_SELECTION_APPROACH
m_selectionFilterTimer = new QTimer(this);
m_selectionFilterTimer->setInterval(2000);
connect(m_selectionFilterTimer, &QTimer::timeout,
this, &MountingPointToMap::onHandleSelectionFilterTimeout);
#endif
if (m_cmoDtc)
{
m_cmoDtc->enableComponentStatus(true);
m_cmoDtc->waitForHistoricalDataComponentStatus(1000);
}
INFO_LOG(m_logger) << LOGFUNCTION << " m_resourceMode=" << m_resourceMode
<< " exerciseId=" << m_pluginProvider->exerciseId()
<< " DONE";
return true;
}
bool MountingPointToMap::initRenderer()
{
INFO_LOG(m_logger) << LOGFUNCTION << " START"
<< ", to rmm = " << toString(m_resourceManagerMode)
<< ", m_uniqueValueRendererAssigned=" << m_uniqueValueRendererAssigned;
if (m_uniqueValueRendererAssigned)
return true;
QElapsedTimer elapsedTimer;
if (m_logger.isInfoEnabled())
elapsedTimer.start();
m_uniqueValueRendererAssigned = initRendererInternal();
if (m_logger.isInfoEnabled())
INFO_LOG(m_logger) << LOGFUNCTION << " END, initRendererXY to rmm = " << toString(m_resourceManagerMode) << " took " << elapsedTimer.elapsed() << " [ms]";
return m_uniqueValueRendererAssigned;
}
bool MountingPointToMap::initRendererInternal()
{
INFO_LOG(m_logger) << LOGFUNCTION << " START, rmm=" << toString(m_resourceManagerMode);
const QString &layername = m_layername;
QVector<SituationMap::LayerFactory::UniqueValueData> uvCont;
SituationMap::LayerFactory::UniqueValueData uvd;
QMap<InfrastructureManagement::MountingPointType_def::type, InfrastructureManagement::MountingPoint::MpNameImageData> &imageCont =
InfrastructureManagement::MountingPoint::getImageTable();
uvCont.reserve(imageCont.size() * 5);
for (const InfrastructureManagement::MountingPoint::MpNameImageData &mnid : qAsConst(imageCont) )
{
{
const InfrastructureManagement::MountingPoint::NameImagePair &nipRef = mnid.nipBlue;
uvd.label = nipRef.m_name;
uvd.img = nipRef.m_img.scaled(QSize(25,25), Qt::KeepAspectRatio, Qt::SmoothTransformation);
uvd.value = nipRef.m_name;
uvCont.append(uvd);
}
{
const InfrastructureManagement::MountingPoint::NameImagePair &nipRef = mnid.nipGray;
uvd.label = nipRef.m_name;
uvd.img = nipRef.m_img.scaled(QSize(25,25), Qt::KeepAspectRatio, Qt::SmoothTransformation);
uvd.value = nipRef.m_name;
uvCont.append(uvd);
}
{
const InfrastructureManagement::MountingPoint::NameImagePair &nipRef = mnid.nipGreen;
uvd.label = nipRef.m_name;
uvd.img = nipRef.m_img.scaled(QSize(25,25), Qt::KeepAspectRatio, Qt::SmoothTransformation);
uvd.value = nipRef.m_name;
uvCont.append(uvd);
}
{
const InfrastructureManagement::MountingPoint::NameImagePair &nipRef = mnid.nipRed;
uvd.label = nipRef.m_name;
uvd.img = nipRef.m_img.scaled(QSize(25,25), Qt::KeepAspectRatio, Qt::SmoothTransformation);
uvd.value = nipRef.m_name;
uvCont.append(uvd);
}
{
const InfrastructureManagement::MountingPoint::NameImagePair &nipRef = mnid.nipOrange;
uvd.label = nipRef.m_name;
uvd.img = nipRef.m_img.scaled(QSize(25,25), Qt::KeepAspectRatio, Qt::SmoothTransformation);
uvd.value = nipRef.m_name;
uvCont.append(uvd);
}
}
bool success = m_objFac.map()->layerFactory().assignUniqueValueRenderer(layername,
QStringLiteral("MountingPointFieldName"),
uvCont);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " assignUniqueValueRenderer ... on layer= " << layername << " failed";
INFO_LOG(m_logger) << LOGFUNCTION << " END, rmm=" << toString(m_resourceManagerMode);
return success;
}
ResourceManagerMode MountingPointToMap::resourceManagerMode() const
{
return m_resourceManagerMode;
}
bool MountingPointToMap::setResourceManagerMode(ResourceManagerMode rmm)
{
INFO_LOG(m_logger) << LOGFUNCTION << " START"
<< ", current rmm = " << toString(m_resourceManagerMode) << " - desired rmm = " << toString(rmm);
QElapsedTimer elapsedTimer;
if (m_logger.isInfoEnabled())
elapsedTimer.start();
if (rmm == ResourceManagerMode::Undefined)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " ERROR, ResourceManagerMode::Undefined required "
<< ", stay at current rmm = " << toString(m_resourceManagerMode);
return false;
}
bool change = m_resourceManagerMode != rmm;
m_resourceManagerMode = rmm;
if (change)
{
run();
}
if (change && m_logger.isInfoEnabled())
INFO_LOG(m_logger) << LOGFUNCTION << " END, switching to current rmm = " << toString(m_resourceManagerMode) << " took " << elapsedTimer.elapsed() << " [ms]";
INFO_LOG(m_logger) << LOGFUNCTION << " END" << ", desired rmm = " << toString(rmm);
return true;
}
bool MountingPointToMap::run()
{
DEBUG_LOG(m_logger) << " Starting to run";
this->stop();
if (!m_ismDataIfc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << "Could not run. ForeignDataInterface not set.";
return false;
}
connect(m_ismDataIfc.get(), &InfrastructureManagement::ForeignDataInterface::buildingsInCurrentExerciseChanged,
this, &MountingPointToMap::onBuildingsInCurrentExerciseChanged, Qt::UniqueConnection);
connect(m_ismDataIfc.get(), &InfrastructureManagement::ForeignDataInterface::mountingPointChanged,
this, &MountingPointToMap::onMountingPointChanged, Qt::UniqueConnection);
initRenderer();
onHandleAllMountingPoints();
#ifdef SUPPORT_SELECTION_APPROACH
setVisibility();
m_selectionFilterTimer->start();
#endif
if (m_cmoDtc)
{
connect(m_cmoDtc.get(), &ComponentMonitor::Interface::Dtc::componentStatusChanged,
this, &MountingPointToMap::onComponentStatusChanged, Qt::UniqueConnection);
}
return true;
}
void MountingPointToMap::onHandleAllMountingPoints()
{
INFO_LOG(m_logger) << LOGFUNCTION << " START"
<< ", m_pluginProvider->exerciseId() = " << m_pluginProvider->exerciseId()
<< ", m_resourceMode = " << m_resourceMode;
if (m_pluginProvider->exerciseId() != 0 || m_resourceMode)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " mountingPoints().size() = " << m_ismDataIfc->mountingPoints().size();
m_ismDataIfc->mountingPoints([this](const InfrastructureManagement::MountingPoint& data)
{
onMountingPointChanged(data, DataModification::eAdded);
});
}
INFO_LOG(m_logger) << LOGFUNCTION << " END";
}
void MountingPointToMap::stop()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << "Stopping...";
if (m_handleAllMountingPointsTimer)
m_handleAllMountingPointsTimer->stop();
#ifdef SUPPORT_SELECTION_APPROACH
if (m_selectionFilterTimer)
m_selectionFilterTimer->stop();
#endif
if (m_ismDtc)
m_ismDtc->disconnect(this);
if (m_ismDataIfc)
m_ismDataIfc->disconnect(this);
if (m_cmoDtc)
m_cmoDtc->disconnect(this);
m_mountingPoints.clear();
DEBUG_LOG(m_logger) << LOGFUNCTION << "Stopping...done";
}
bool MountingPointToMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
if (!m_ismGuiIfc)
return false;
const QVector<int32_t> &simIds = uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
if (m_ismGuiIfc->isInSelectionMode())
m_ismGuiIfc->addToSelection(simIds);
else
m_ismGuiIfc->showMountingPointInfoWindows(simIds);
return true;
}
bool MountingPointToMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_ismDataIfc)
return false;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
const auto cb = [this, simIdOut, &umodOut](const InfrastructureManagement::MountingPoint &data) -> bool
{
if (data.id() == simIdOut)
{
umodOut.m_description1 = data.name();
umodOut.m_participantData.m_typeName = InfrastructureManagement::toString(data.type());
QString attribValueUnused;
bool suc = false;
switch (m_resourceManagerMode) {
case ResourceManagerMode::RMM_PlanActivityView:
suc = InfrastructureManagement::MountingPoint::getImageAttributePlanActivity(data, umodOut.m_image, attribValueUnused);
if (!suc)
WARNING_LOG(m_logger) << LOGFUNCTION
<< "getImageAttributePlanActivity failed m_resourceMode=" << m_resourceMode
<< " m_resourceManagerMode=" << toString(m_resourceManagerMode);
break;
case ResourceManagerMode::RMM_PlanDefinitionView:
suc = InfrastructureManagement::MountingPoint::getImageAttributePlanDefinition(data, umodOut.m_image, attribValueUnused);
if (!suc)
WARNING_LOG(m_logger) << LOGFUNCTION
<< "getImageAttributePlanDefinition failed m_resourceMode=" << m_resourceMode
<< " m_resourceManagerMode=" << toString(m_resourceManagerMode);
break;
case ResourceManagerMode::RMM_ComponentMonitor:
{
InfrastructureManagement::MountingPoint::MpColor col = InfrastructureManagement::MountingPoint::MpColor::GRAY;
suc = InfrastructureManagement::MountingPoint::getImageAttribute(data, col, umodOut.m_image, attribValueUnused);
if (!suc)
{
WARNING_LOG(m_logger) << LOGFUNCTION
<< "getImageAttribute failed m_resourceMode=" << m_resourceMode
<< " m_resourceManagerMode=" << toString(m_resourceManagerMode);
}
}
break;
default:
break;
}
return true;
}
return false;
};
std::function<bool(const InfrastructureManagement::MountingPoint &data)> cb1 = cb;
return m_ismDataIfc->mountingPoints(cb1);
}
bool MountingPointToMap::onMountingPointChanged(const InfrastructureManagement::MountingPoint &data, DataModification modType)
{
DEBUG_LOG(m_logger) << " m_resourceMode=" << m_resourceMode
<< " onMountingPointChanged"
<< " id=" << data.id()
<< " name=" << data.name()
<< " buildingId=" << data.buildingId()
<< " associatedAssetId=" << data.associatedAssetId()
<< " hasAssociatedAsset=" << data.hasAssociatedAsset()
<< " MountingPointType=" << data.type()
<< " aimState=" << data.aimState()
<< " exerciseId=" << m_pluginProvider->exerciseId();
if (m_pluginProvider->exerciseId() == 0 && !m_resourceMode)
return true;
if (!isElapsed(data))
{
m_mountingPoints.insert(data.id(), data);
const std::string &hostname = mountingPointHostname(data);
if (!hostname.empty())
{
m_associatedAssetHostnameToMountingPointId[hostname] = data.id();
DEBUG_LOG(m_logger) << " m_resourceMode=" << m_resourceMode
<< " INSERT hostname '" << hostname << "'"
<< " id " << data.id();
}
}
return handleChanged(data, modType);
}
bool MountingPointToMap::isElapsed(const Sim2SituationMap::DDS_T &data) const
{
DEBUG_LOG(m_logger) << " isElapsed"
<< ", m_resourceManagerMode=" << (int)m_resourceManagerMode;
if (BaseClass::isElapsed(data))
return true;
const InfrastructureManagement::MountingPointType mpType = data.type();
if (mpType.underlying() == InfrastructureManagement::MountingPointType::BuildingNetworkSwitch)
return true;
if (m_resourceMode)
{
switch (m_resourceManagerMode) {
case ResourceManagerMode::RMM_PlanActivityView:
return ( (mpType.underlying() == InfrastructureManagement::MountingPointType_def::BuildingControlUnit) ||
(data.aimState().underlying() == InfrastructureManagement::MountingPointState_def::Idle)
);
break;
case ResourceManagerMode::RMM_PlanDefinitionView:
return (mpType.underlying() == InfrastructureManagement::MountingPointType_def::BuildingControlUnit);
break;
case ResourceManagerMode::RMM_ComponentMonitor:
return
! (data.hasAssociatedAsset() &&
(
(mpType.underlying() == InfrastructureManagement::MountingPointType_def::OutdoorIPS) ||
(mpType.underlying() == InfrastructureManagement::MountingPointType_def::IndoorIPS) ||
(mpType.underlying() == InfrastructureManagement::MountingPointType_def::OutdoorCamera) ||
(mpType.underlying() == InfrastructureManagement::MountingPointType_def::IndoorCamera) ||
(mpType.underlying() == InfrastructureManagement::MountingPointType_def::OutdoorCamera) ||
(mpType.underlying() == InfrastructureManagement::MountingPointType_def::EffectGenerationControlUnit) ||
(mpType.underlying() == InfrastructureManagement::MountingPointType_def::BuildingSensorModule)
)
);
break;
default:
break;
}
}
const int bldgId = data.buildingId();
if (!m_ismDataIfc->isBuildingsInCurrentExercise(bldgId))
{
DEBUG_LOG(m_logger) << "isElapsed: buildingId=" << bldgId;
return true;
}
if ((mpType.underlying() == InfrastructureManagement::MountingPointType::OutdoorCamera) ||
(mpType.underlying() == InfrastructureManagement::MountingPointType::AnnouncementUnit))
return data.hasAssociatedAsset() == false;
return true;
}
int32_t MountingPointToMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool MountingPointToMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData, RefPointer<Sim2SituationMap::MAP_T> mapObj)
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " m_resourceMode=" << m_resourceMode
<< " m_resourceManagerMode=" << (int)m_resourceManagerMode
<< " id " << ddsData.id()
<< " type " << ddsData.type()
<< " name = " << ddsData.name()
<< " has associatedAssetId = " << ddsData.associatedAssetId()
<< " aimState = " << ddsData.aimState()
<< ", goeCoord = " << ddsData.geoPosition();
const Core::GeoPosition &geoPos = ddsData.geoPosition();
mapObj->setOrigin(Point3D(geoPos.lon(), geoPos.lat(), geoPos.z()));
QString attribValue;
QImage imgUnused;
switch (m_resourceManagerMode) {
case ResourceManagerMode::RMM_PlanActivityView:
{
bool suc = InfrastructureManagement::MountingPoint::getImageAttributePlanActivity(ddsData, imgUnused, attribValue);
if (!suc)
{
WARNING_LOG(m_logger) << LOGFUNCTION
<< "getImageAttributePlanActivity failed m_resourceMode=" << m_resourceMode
<< " m_resourceManagerMode=" << (int)m_resourceManagerMode;
}
}
break;
case ResourceManagerMode::RMM_PlanDefinitionView:
{
bool suc = InfrastructureManagement::MountingPoint::getImageAttributePlanDefinition(ddsData, imgUnused, attribValue);
if (!suc)
{
WARNING_LOG(m_logger) << LOGFUNCTION
<< "getImageAttributePlanDefinition failed m_resourceMode=" << m_resourceMode
<< " m_resourceManagerMode=" << (int)m_resourceManagerMode;
}
}
break;
case ResourceManagerMode::RMM_ComponentMonitor:
{
InfrastructureManagement::MountingPoint::MpColor col = InfrastructureManagement::MountingPoint::MpColor::GRAY;
const InfrastructureManagement::MountingPointType mpType = ddsData.type();
if ( (mpType.underlying() == InfrastructureManagement::MountingPointType_def::OutdoorIPS) ||
(mpType.underlying() == InfrastructureManagement::MountingPointType_def::IndoorIPS) )
{
col = InfrastructureManagement::MountingPoint::MpColor::GRAY;
} else {
const std::string &hostname = mountingPointHostname(ddsData);
if (!hostname.empty())
{
ComponentMonitor::ComponentState stateOut;
if (componentStateOfHostname(hostname, stateOut))
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " componentStateOfHostname: '" << hostname << "' -> " << stateOut;
switch (stateOut.underlying()) {
case ComponentMonitor::ComponentState_def::Undefined:
if (QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
col = InfrastructureManagement::MountingPoint::MpColor::ORANGE;
else
col = InfrastructureManagement::MountingPoint::MpColor::RED;
break;
case ComponentMonitor::ComponentState_def::Reachable:
col = InfrastructureManagement::MountingPoint::MpColor::GREEN;
break;
case ComponentMonitor::ComponentState_def::Unreachable:
col = InfrastructureManagement::MountingPoint::MpColor::RED;
break;
default:
break;
}
} else {
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " componentStateOfHostname: host '" << hostname << "' not found. Maybe topic removed ";
}
}
}
bool suc = InfrastructureManagement::MountingPoint::getImageAttribute(ddsData, col, imgUnused, attribValue);
if (!suc)
{
WARNING_LOG(m_logger) << LOGFUNCTION
<< ", getImageAttribute failed m_resourceMode=" << m_resourceMode
<< ", m_resourceManagerMode=" << (int)m_resourceManagerMode;
}
}
break;
default:
break;
}
QVariantMap attribMap;
attribMap.insert(QStringLiteral("MountingPointFieldName"), attribValue);
INFO_LOG(m_logger) << LOGFUNCTION
<< " id " << ddsData.id()
<< " type " << ddsData.type()
<< " name = " << ddsData.name()
<< " attribValue = >>>" << attribValue << "<<<";
mapObj->setAttributes(attribMap);
return true;
}
#ifdef BLDCOMPONENT_FILTER_APPROACH
void MountingPointToMap::handleBuildingComponentSettings(RefPointer<Sim2SituationMap::MAP_T> &mapObj)
{
if (!mapObj.valid())
return;
const UniqueMapId uniqueMapId = mapObj->uniqueMapId();
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return;
const InfrastructureManagement::MountingPoint &ddsDataMP = m_mountingPoints[simIdOut];
Q_ASSERT(ddsDataMP.id() == simIdOut);
handleBuildingComponentSettingsMP(mapObj, ddsDataMP);
}
void MountingPointToMap::handleBuildingComponentSettingsMP(RefPointer<Sim2SituationMap::MAP_T> &mapObj,
const InfrastructureManagement::MountingPoint &mountingPoint)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_resourceMode=" << m_resourceMode
<< ", debugInfo='" << mapObj->debugInfo();
if (!mapObj.valid())
return;
const InfrastructureManagement::MountingPointType_def::type type = mountingPoint.type().underlying();
bool newVisi = showMountingPointType(type);
if (newVisi)
{
const QSet<int> hiddenFloorIdsRef = m_currentBuildingComponentSettings.buildingSettings.hiddenFloorIds;
newVisi = !hiddenFloorIdsRef.contains(mountingPoint.floor());
}
bool oldVisibility = mapObj->visibility();
if (oldVisibility != newVisi)
{
mapObj->setVisibility(newVisi);
if (!mapObj->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << mapObj->debugInfo() << "'" << " updateView failed";
}
}
bool MountingPointToMap::showMountingPointType(InfrastructureManagement::MountingPointType_def::type mpType) const
{
const FilterManagement::BuildingComponentSettings::BldCmpSettings::ComponentSettings &cs =
m_currentBuildingComponentSettings.componentSettings;
switch (mpType) {
case InfrastructureManagement::MountingPointType_def::AnnouncementUnit:
#ifdef GUEZ_MODE
return false;
#else
return cs.showAnnouncementUnit;
#endif
break;
case InfrastructureManagement::MountingPointType_def::BuildingControlUnit:
return cs.showBuildingControlUnit;
break;
case InfrastructureManagement::MountingPointType_def::BuildingNetworkSwitch:
#ifdef GUEZ_MODE
return false;
#else
return cs.showBuildingNetworkSwitch;
#endif
break;
case InfrastructureManagement::MountingPointType_def::BuildingSensorModule:
return cs.showBuildingSensorModule;
break;
case InfrastructureManagement::MountingPointType_def::EffectGenerationControlUnit:
return cs.showEffectGenerationControlUnit;
break;
case InfrastructureManagement::MountingPointType_def::IndoorCamera:
return cs.showIndoorCamera;
break;
case InfrastructureManagement::MountingPointType_def::IndoorIPS:
return cs.showIndoorIPS;
break;
case InfrastructureManagement::MountingPointType_def::MeteoDataUnit:
return cs.showMeteoDataUnit;
break;
case InfrastructureManagement::MountingPointType_def::OutdoorCamera:
return cs.showOutdoorCamera;
break;
case InfrastructureManagement::MountingPointType_def::OutdoorControlUnit:
#ifdef GUEZ_MODE
return false;
#else
return cs.showOutdoorControlUnit;
#endif
break;
case InfrastructureManagement::MountingPointType_def::OutdoorIPS:
return cs.showOutdoorIPS;
break;
case InfrastructureManagement::MountingPointType_def::VirtualIPS:
return cs.showVirtualIPS;
break;
case InfrastructureManagement::MountingPointType_def::Unknown:
WARNING_LOG(m_logger) << LOGFUNCTION << " visibility of MountingPointType_def::Unknown - unwanted, most likelky an error...";
#ifdef LTS_DEBUG
Q_ASSERT(false);
#endif
return true;
break;
default:
break;
}
return true;
}
#endif
#ifdef SUPPORT_SELECTION_APPROACH
void MountingPointToMap::onHandleSelectionFilterTimeout()
{
if (!m_ismGuiIfc)
return;
m_ismGuiIfc->getCurrentFilters(m_selectionFilter.m_floorIds, m_selectionFilter.m_mountingPointTypes);
setVisibility();
}
#endif
std::string MountingPointToMap::mountingPointHostname(const InfrastructureManagement::MountingPoint &mountingPoint)
{
if (!mountingPoint.hasAssociatedAsset())
return {};
const int assAssetId = mountingPoint.associatedAssetId();
const InfrastructureManagement::InstrumentationAsset &iAsset = m_ismDtc->instrumentationAsset(assAssetId);
if (iAsset.id() == assAssetId)
{
const std::string &hostname = iAsset.hostname();
if (!hostname.empty())
return hostname;
}
return {};
}
bool MountingPointToMap::componentStateOfHostname(const std::string &hostname, ComponentMonitor::ComponentState &stateOut)
{
stateOut = ComponentMonitor::ComponentState(ComponentMonitor::ComponentState_def::Undefined);
if (!m_cmoDtc)
return false;
const auto cb = [hostname, &stateOut](const ComponentMonitor::ComponentStatus &ddsData) -> bool
{
if (ddsData.hostname().compare(hostname) == 0)
{
stateOut = ddsData.state();
return true;
}
return false;
};
std::function<bool(const ComponentMonitor::ComponentStatus &data)> cb1 = cb;
return m_cmoDtc->componentStatuss(cb1);
}
void MountingPointToMap::onBuildingsInCurrentExerciseChanged()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", m_resourceManagerMode = " << toString(m_resourceManagerMode);
m_handleAllMountingPointsTimer->start();
}
bool MountingPointToMap::onComponentStatusChanged(const ComponentMonitor::ComponentStatus &data, DataModification modType)
{
if (m_resourceManagerMode != ResourceManagerMode::RMM_ComponentMonitor)
return false;
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", data =" << data
<< ", modType = " << modType
<< ", m_resourceManagerMode = " << toString(m_resourceManagerMode);
const std::string &hostname = data.hostname();
if (hostname.empty())
return false;
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< ", data =" << data
<< ", modType = " << modType
<< ", m_resourceManagerMode = " << toString(m_resourceManagerMode);
const auto it = m_associatedAssetHostnameToMountingPointId.find(hostname);
if (it == m_associatedAssetHostnameToMountingPointId.end())
return false;
const int mountingPointId = *it;
const InfrastructureManagement::MountingPoint &mountingPoint = m_mountingPoints[mountingPointId];
const UniqueMapId uniqueMapId = m_simId2UniqueMapId.value(mountingPointId, INVALID_MAP_ID);
if (!isUniqueMapIdValid(uniqueMapId))
{
WARNING_LOG(m_logger) << LOGFUNCTION << "Found a mountingPoint which is in internal map but has no map object...: " << mountingPointId;
return false;
}
RefPointer<MAP_T> mapObj = m_objFac.get<MAP_T>(uniqueMapId);
if (!mapObj.valid())
return false;
updateElementImpl(mountingPoint, mapObj);
if (!mapObj->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << mapObj->debugInfo() << "'" << " updateView failed";
return true;
}
}
@@ -0,0 +1,120 @@
#pragma once
#define BLDCOMPONENT_FILTER_APPROACH
#include "sim_to_situation_map_tmpl.h"
#include "resource_manager_mode.h"
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <Plugins/InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <Plugins/ComponentMonitor/cmo_data_plugin_interface.h>
#include <Plugins/InfrastructureManagement/Shared/ism_mounting_point.h>
#include <MapObjects/geo_image.h>
#include <MapObjects/map_object_attributes.h>
#include <QTimer>
namespace SituationMap
{
class MountingPointToMap final : public Sim2SituationMap<InfrastructureManagement::MountingPoint, SituationMap::MapObjectAttributes>
, protected DdsFilterHandling<SituationMap::MapObjectAttributes>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<InfrastructureManagement::MountingPoint, SituationMap::MapObjectAttributes>;
using FilterClass = DdsFilterHandling<SituationMap::MapObjectAttributes>;
public:
MountingPointToMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
{}
bool init(PluginProvider *pluginProvider, bool resourceMode);
bool initRenderer();
bool initRendererInternal();
ResourceManagerMode resourceManagerMode() const;
bool setResourceManagerMode(ResourceManagerMode rmm);
bool run() override;
void stop() override;
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
protected Q_SLOTS:
void onHandleAllMountingPoints();
#ifdef SUPPORT_SELECTION_APPROACH
void onHandleSelectionFilterTimeout();
#endif
bool onMountingPointChanged(const InfrastructureManagement::MountingPoint &data, DataModification modType);
void onBuildingsInCurrentExerciseChanged();
bool onComponentStatusChanged(const ComponentMonitor::ComponentStatus &data, DataModification modType);
protected:
bool isElapsed(const Sim2SituationMap::DDS_T &data) const override;
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const DDS_T &ddsData, RefPointer<MAP_T> mapObj) override;
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override
{
Q_UNUSED(mapObj);
}
#ifdef BLDCOMPONENT_FILTER_APPROACH
bool buildingComponentSettingsChangesAreRelevant(const FilterManagement::BuildingComponentSettings::BldCmpSettings&) const override
{
return true;
}
void handleBuildingComponentSettings(RefPointer<MAP_T> &mapObj) override;
void handleBuildingComponentSettingsMP(RefPointer<MAP_T> &mapObj,
const InfrastructureManagement::MountingPoint &mountingPoint);
bool showMountingPointType(InfrastructureManagement::MountingPointType_def::type mpType) const;
#endif
private:
std::string mountingPointHostname(const InfrastructureManagement::MountingPoint &mountingPoint);
bool componentStateOfHostname(const std::string &hostname, ComponentMonitor::ComponentState &stateOut);
private:
PluginProvider *m_pluginProvider{nullptr};
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> m_ismDataIfc;
std::shared_ptr<InfrastructureManagement::ForeignResourceManagementGuiInterface> m_ismGuiIfc;
std::shared_ptr<ComponentMonitor::Interface::Dtc> m_cmoDtc;
bool m_uniqueValueRendererAssigned{false};
bool m_resourceMode{false};
ResourceManagerMode m_resourceManagerMode{ResourceManagerMode::RMM_PlanActivityView};
QTimer *m_handleAllMountingPointsTimer{nullptr};
QMap<int, InfrastructureManagement::MountingPoint> m_mountingPoints;
QMap<std::string, int> m_associatedAssetHostnameToMountingPointId;
#ifdef SUPPORT_SELECTION_APPROACH
struct SelectionFilter
{
QVector<int> m_floorIds;
QVector<InfrastructureManagement::MountingPointType> m_mountingPointTypes;
} m_selectionFilter;
QTimer *m_selectionFilterTimer{nullptr};
#endif
};
}
@@ -0,0 +1,353 @@
#include "mse_bridge_to_map.h"
#include <Map/object_factory.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <MathUtils/simple_helper.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Plugins/Buildings/bld_info_gui_plugin_interface.h>
#include <InfrastructureManagement/ism_translation.h>
#include <SituationMap/Symbology/sidc_codec.h>
#include <Common/resource_path.h>
#include <QUrl>
#include <QDir>
namespace SituationMap
{
int32_t MSEBridgeToMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool MSEBridgeToMap::init(PluginProvider *pluginProvider)
{
if (!pluginProvider ||
!pluginProvider->ismDtc())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no pluginProvider";
return false;
}
m_pluginProvider = pluginProvider;
m_ismDtc = pluginProvider->ismDtc();
m_bldInfoIfc = pluginProvider->bldInfoIfc();
FilterClass::init(m_pluginProvider);
return true;
}
bool MSEBridgeToMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_ismDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
m_mseIdWithoutValidFootprint.clear();
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainFootprintChanged,
this, &MSEBridgeToMap::onMainFootprintChanged);
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
this, &MSEBridgeToMap::onMainStructureElementChanged);
m_ismDtc->mainStructureElements([this](const InfrastructureManagement::MainStructureElement & data)
{
onMainStructureElementChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool MSEBridgeToMap::isElapsed(const InfrastructureManagement::MainStructureElement &ddsData) const
{
if (BaseClass::isElapsed(ddsData))
return true;
if (ddsData.structureElementTypeId() != InfrastructureManagement::StructureElementType::Bridge)
return true;
const qint32 mseId = ddsData.id();
const InfrastructureManagement::MainFootprint &mainFootprint = m_ismDtc->mainFootprint(mseId);
if (mainFootprint.elements().size() < 4)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " mainFootprint with id=" << mseId << " is not sufficiant."
<< " mainFootprint.elements().size() = " << mainFootprint.elements().size();
if (!m_mseIdWithoutValidFootprint.contains(mseId))
{
INFO_LOG(m_logger) << LOGFUNCTION << " Save for future mainFootPrintChanged..."
<< " (m_mseIdWithoutValidFootprint.size()=" << m_mseIdWithoutValidFootprint.size();
m_mseIdWithoutValidFootprint.append(mseId);
}
return true;
}
return false;
}
bool MSEBridgeToMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
if (!m_bldInfoIfc)
return false;
const QVector<int32_t> &simIds = uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
m_bldInfoIfc->showBridgeInfoWindow(simIds);
return true;
}
bool MSEBridgeToMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_ismDtc)
return false;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
RefPointer<MAP_T> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_image = mapObj->previewImage();
const auto cb = [this, simIdOut, &umodOut](const InfrastructureManagement::MainStructureElement & data) -> bool
{
if (data.id() == simIdOut)
{
umodOut.m_description1 = m_ismDtc->getBuildingDisplayName(data);
umodOut.m_participantData.m_typeName = InfrastructureManagement::toString(data.structureElementTypeId());
return true;
}
return false;
};
std::function<bool(const InfrastructureManagement::MainStructureElement &data)> cb1 = cb;
return m_ismDtc->mainStructureElements(cb1);
}
void MSEBridgeToMap::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data,
DataModification modType)
{
handleChanged(data, modType);
}
void MSEBridgeToMap::onMainFootprintChanged(const InfrastructureManagement::MainFootprint &data, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
if (data.elements().size() < 4)
return;
const int32_t mseId = data.id();
if (m_mseIdWithoutValidFootprint.contains(mseId))
{
const InfrastructureManagement::MainStructureElement &mseData= m_ismDtc->mainStructureElement(mseId);
if (mseData.id() == mseId)
{
m_mseIdWithoutValidFootprint.removeAll(mseId);
onMainStructureElementChanged(mseData, DataModification::eAdded);
}
}
}
bool MSEBridgeToMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " id=" << ddsData.id()
<< " name=" << ddsData.name()
<< " geoPosition=" << ddsData.geoPosition()
<< " angle=" << ddsData.angle();
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setIdentifier(m_ismDtc->getBuildingDisplayName(ddsData));
const qint32 bridgeId = getSimId(ddsData);
QList<QPointF> relPositions2D;
{
const InfrastructureManagement::MainFootprint &mainFootprint = m_ismDtc->mainFootprint(bridgeId);
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " id=" << ddsData.id()
<< " name=" << ddsData.name()
<< " mainFootprint.elements().size()=" << mainFootprint.elements().size();
relPositions2D.reserve(mainFootprint.elements().size());
for (const InfrastructureManagement::FootprintElement &element : mainFootprint.elements())
{
const auto &relPos = element.relPosition();
relPositions2D += QPointF(relPos.offsetX(), relPos.offsetY());
}
}
DEBUG_LOG(m_logger) << "footprint = " << relPositions2D;
PositionCont absPositionsGeo;
const Core::GeoPosition &geoPosition = ddsData.geoPosition();
const double angleRad = ddsData.angle() * LtsCoordTrans::deg2rad();
const QPointF referencePointGeo(geoPosition.lon(), geoPosition.lat());
const LtsCoordTrans::UtmCoordinate referencePointUTM = LtsCoordTrans::UtmCoordinate::fromGeographic(referencePointGeo);
const QPointF center;
absPositionsGeo.reserve(relPositions2D.size());
for (const auto &relPosition : qAsConst(relPositions2D))
{
const QPointF relPositionRotate = MathUtils::rotate(relPosition, center, angleRad);
const QPointF pGeo = referencePointUTM.geographic(relPositionRotate);
absPositionsGeo.append(Point3D::fromQPointF(pGeo));
}
DEBUG_LOG(m_logger) << "absPositionsGeo = " << absPositionsGeo;
mapObj->setPositions(absPositionsGeo);
mapObj->setMarker(Point3D::fromQPointF(referencePointGeo));
static QString resourcePath = SituationMap::getResourcePath() + QDir::separator() + QStringLiteral("3Dmodels") + QDir::separator();
BuildingOutline::ModelSceneSymbolData mssd;
mssd.url = QUrl(resourcePath + QString(QStringLiteral("SPD/buildings/Bruecke_20m/Bruecke_20m.dae")));
mssd.scale = 1.0;
QColor color = Qt::darkGray;
LinePattern linePattern = LinePattern::Dash;
FillPattern fillPattern = FillPattern::Solid;
switch(m_ismDtc->getBridgeStatus(ddsData.id()).underlying())
{
case InfrastructureManagement::BridgeStatus::Broken:
{
QFileInfo fi(resourcePath + QString(QStringLiteral("SPD/buildings/Bruecke_20m/Bruecke_20m_defekt.dae")));
if (fi.exists())
mssd.url = QUrl(fi.absoluteFilePath());
else
mssd.scale = 0.25;
linePattern = LinePattern::Dot;
fillPattern = FillPattern::DiagonalCross;
}
break;
case InfrastructureManagement::BridgeStatus::Intact:
mssd.scale = 1.2;
color.setAlphaF(0.5);
break;
default:
color = Qt::yellow;
break;
}
TextStyle ts = mapObj->textStyle();
ts.setHorizontalAlignment(HorizontalAlignment::Center);
LineStyle ls = mapObj->lineStyle();
ls.setLinePattern(linePattern);
FillStyle fs = mapObj->fillStyle();
fs.setFillColor(color);
fs.setFillPattern(fillPattern);
mapObj->setTextStyle(ts);
mapObj->setLineStyle(ls);
mapObj->setFillStyle(fs);
mssd.heading = (ddsData.angle()*-1)+90;
mapObj->setModelSceneSymbolData(mssd);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool MSEBridgeToMap::symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale) ||
(m_currentSymbolSettings.symbolSettings.showBuildingIdentifier != newSas.symbolSettings.showBuildingIdentifier);
}
void MSEBridgeToMap::handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj)
{
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
mapObj->setIdentifierVisible(m_currentSymbolSettings.symbolSettings.showBuildingIdentifier);
}
}
@@ -0,0 +1,72 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <Buildings/bld_dtc.h>
#include <MapObjects/building_outline.h>
namespace Buildings
{
class ForeignInfoGuiInterface;
}
namespace SituationMap
{
class MSEBridgeToMap final : public Sim2SituationMap<InfrastructureManagement::MainStructureElement, SituationMap::BuildingOutline>
, protected DdsFilterHandling<SituationMap::BuildingOutline>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<InfrastructureManagement::MainStructureElement, SituationMap::BuildingOutline>;
using FilterClass = DdsFilterHandling<SituationMap::BuildingOutline>;
public:
explicit MSEBridgeToMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
{}
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override
{
if (m_ismDtc)
m_ismDtc->disconnect(this);
}
bool isElapsed(const InfrastructureManagement::MainStructureElement &ddsData) const override;
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
protected Q_SLOTS:
void onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data,
DataModification modType = DataModification::eAdded);
void onMainFootprintChanged(const InfrastructureManagement::MainFootprint &data,
DataModification modType = DataModification::eAdded);
protected:
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override;
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override;
private:
PluginProvider *m_pluginProvider = nullptr;
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
std::shared_ptr<Buildings::ForeignInfoGuiInterface> m_bldInfoIfc;
mutable QVector<int> m_mseIdWithoutValidFootprint;
};
}
@@ -0,0 +1,215 @@
#include "mse_point_to_map.h"
#include <Map/object_factory.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <InfrastructureManagement/ism_translation.h>
#include <Plugins/Buildings/bld_info_gui_plugin_interface.h>
#include <QPainter>
#include <sstream>
using namespace SituationMap;
QImage renderApproachingPoint(const QColor &color)
{
int size = 100;
QImage image(size, size, QImage::Format_ARGB32);
image.fill(Qt::transparent);
QPainter painter(&image);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.setPen(QPen(Qt::NoPen));
painter.setBrush(QBrush(color, Qt::Dense5Pattern));
painter.drawRect(image.rect());
QPen pen(color);
pen.setWidth(5);
painter.setPen(pen);
const int sizeHalf = size / 2.0;
QPointF center(sizeHalf, sizeHalf);
painter.setBrush(color);
painter.drawEllipse(center, sizeHalf * 0.1, sizeHalf * 0.1);
QLine newLine(sizeHalf, 0, sizeHalf, sizeHalf * 0.6);
painter.drawLine(newLine);
QTransform trans;
trans.translate(sizeHalf, sizeHalf);
trans.rotate(90);
trans.translate(-sizeHalf, -sizeHalf);
newLine = trans.map(newLine);
painter.drawLine(newLine);
newLine = trans.map(newLine);
painter.drawLine(newLine);
newLine = trans.map(newLine);
painter.drawLine(newLine);
painter.end();
return image;
}
bool MSEPointToMap::init(PluginProvider *pluginProvider)
{
if (!pluginProvider ||
!pluginProvider->ismDtc() ||
!pluginProvider->ismDataIfc())
return false;
m_pluginProvider = pluginProvider;
DEBUG_LOG(m_logger) << LOGFUNCTION << " exerciseId=" << m_pluginProvider->exerciseId();
m_ismDtc = m_pluginProvider->ismDtc();
m_bldInfoIfc = pluginProvider->bldInfoIfc();
FilterClass::init(m_pluginProvider);
return true;
}
bool MSEPointToMap::run()
{
DEBUG_LOG(m_logger) << "Starting to run";
this->stop();
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
this, &MSEPointToMap::handleChanged, Qt::UniqueConnection);
m_ismDtc->mainStructureElements([this](const InfrastructureManagement::MainStructureElement & data)
{
handleChanged(data, DataModification::eAdded);
});
return true;
}
void MSEPointToMap::stop()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " Stopping";
if (m_ismDtc)
m_ismDtc->disconnect(this);
}
bool MSEPointToMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_ismDtc)
return false;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
RefPointer<MAP_T> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_image = mapObj->previewImage();
const auto cb = [simIdOut, &umodOut](const InfrastructureManagement::MainStructureElement & data) -> bool
{
if (data.id() == simIdOut)
{
umodOut.m_description1 = QString::fromStdString(data.name());
umodOut.m_participantData.m_typeName = InfrastructureManagement::toString(data.structureElementTypeId());
return true;
}
return false;
};
std::function<bool(const InfrastructureManagement::MainStructureElement &data)> cb1 = cb;
return m_ismDtc->mainStructureElements(cb1);
}
bool MSEPointToMap::isElapsed(const Sim2SituationMap::DDS_T &data) const
{
DEBUG_LOG(m_logger) << " isElapsed";
if (BaseClass::isElapsed(data))
return true;
if (data.isDeleted())
return true;
if (data.structureElementTypeId() != InfrastructureManagement::StructureElementType::ApproachingPoint)
return true;
return false;
}
int32_t MSEPointToMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool MSEPointToMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData, RefPointer<Sim2SituationMap::MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION
<< ", id " << ddsData.id()
<< ", name = " << ddsData.name();
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
TextStyle textStyle;
textStyle.setSize(10);
if (ddsData.structureElementTypeId() == InfrastructureManagement::StructureElementType::ApproachingPoint)
{
textStyle.setTextColor(Qt::yellow);
mapObj->setProxyImage(renderApproachingPoint(Qt::yellow), QSize(50, 50));
}
mapObj->setTextStyle(textStyle);
const Core::GeoPosition &geoPos = ddsData.geoPosition();
mapObj->setOrigin(Point3D(geoPos.lon(), geoPos.lat(), geoPos.z()));
return true;
}
bool MSEPointToMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
if (!m_bldInfoIfc)
return false;
const QVector<int32_t> &simIds = uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
return true;
}
@@ -0,0 +1,63 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <MapObjects/geo_image.h>
namespace SituationMap
{
class MSEPointToMap final : public Sim2SituationMap<InfrastructureManagement::MainStructureElement, SituationMap::GeoImage>
, protected DdsFilterHandling<SituationMap::GeoImage>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<InfrastructureManagement::MainStructureElement, SituationMap::GeoImage>;
using FilterClass = DdsFilterHandling<SituationMap::GeoImage>;
public:
MSEPointToMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
, m_pluginProvider(nullptr)
{}
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override;
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
protected:
bool isElapsed(const Sim2SituationMap::DDS_T &data) const override;
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const DDS_T &ddsData, RefPointer<MAP_T> mapObj) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale);
}
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override
{
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
}
private:
private:
PluginProvider *m_pluginProvider;
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
std::shared_ptr<Buildings::ForeignInfoGuiInterface> m_bldInfoIfc;
};
}
@@ -0,0 +1,175 @@
#include "ncontamination_to_map.h"
#include <Map/map.h>
#include <Map/object_factory.h>
namespace SituationMap
{
bool NContamination2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
return false;
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::nContaminationChanged,
this, &NContamination2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->nContaminations([this](const AreaEffectSimulation::NContamination &data)
{
handleChanged(data, DataModification::eAdded);
});
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
connect(m_pluginProvider, &PluginProvider::partitionTimeChanged,
this, &NContamination2SituationMap::onPartitionTimeChanged, Qt::UniqueConnection);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
void NContamination2SituationMap::onPartitionTimeChanged(qint64 newPartitionTime)
{
updateAllSpheres3D(newPartitionTime);
}
void NContamination2SituationMap::updateAllSpheres3D(qint64 newPartitionTime)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", m_simId2UniqueMapId.size = " << m_simId2UniqueMapId.size();
QMapIterator<int32_t, UniqueMapId> it(m_simId2UniqueMapId);
while (it.hasNext())
{
it.next();
const UniqueMapId uniqueMapId = it.value();
RefPointer<MAP_T> mapObj = m_objFac.get<MAP_T>(uniqueMapId);
if (!mapObj.valid())
continue;
const int simId = it.key();
const AreaEffectSimulation::NContamination &nCont = m_aesDtc->nContamination(simId);
if (nCont.id() != simId)
continue;
if (updateSphere3D(mapObj, nCont, newPartitionTime))
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " updateView failed";
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
}
bool NContamination2SituationMap::updateSphere3D(RefPointer<Sim2SituationMap::MAP_T> mapObj, const AreaEffectSimulation::NContamination &data, qint64 newPartitionTime)
{
const int32_t simId = data.id();
if (!mapObj)
return false;
bool bUpdateRequired = false;
const bool bDesiredNewState = (data.effectStateId().underlying() == AreaEffectSimulation::AesEffectState_def::EsActivated) &&
((newPartitionTime - data.sampleTime() < 5000));
TRACE_LOG(m_logger) << LOGFUNCTION << ", START" << " simId = " << simId
<< ", sampleTime " << data.sampleTime()
<< ", bDesiredNewState " << bDesiredNewState;
if (mapObj->hasDetonation() && !bDesiredNewState)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << ", START REMOVE " << " simId = " << simId;
mapObj->resetDetonation();
bUpdateRequired = true;
}
else if (!mapObj->hasDetonation() && bDesiredNewState)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << ", START ADD " << " simId = " << simId;
const Core::GeoPosition2D &geoPos = data.impactPosition();
Point3D markerOrigin(geoPos.lon(), geoPos.lat(), 0);
mapObj->setDetonation(markerOrigin, data.impactRadius());
bUpdateRequired = true;
}
TRACE_LOG(m_logger) << LOGFUNCTION << ", END" << " simId = " << simId;
return bUpdateRequired;
}
bool NContamination2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
mapObj->setAesState(effectState2aesState(ddsData.effectStateId().underlying()));
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
updateSphere3D(mapObj, ddsData, m_pluginProvider->partitionTime());
const int32_t simId = ddsData.id();
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtNContamination, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtNContamination) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
const Core::GeoPosition2D& impactPos2D = ddsData.impactPosition();
mapObj->setImpactOrigin(Point3D(impactPos2D.lon(), impactPos2D.lat(), 0.0));
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,47 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/nuclear_agent.h>
#include <QObject>
namespace SituationMap
{
class NContamination2SituationMap;
template <>
struct Aes2SituationMapTraits<NContamination2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::NContamination;
using MAP_TYPE = SituationMap::NuclearAgent;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtNContamination;
};
class NContamination2SituationMap final : public Aes2SituationMap<NContamination2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<NContamination2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::NContamination &data)> &cb) const
{
return m_aesDtc->nContaminations(cb);
}
protected Q_SLOTS:
void onPartitionTimeChanged(qint64 newPartitionTime);
protected:
void updateAllSpheres3D(qint64 newPartitionTime);
bool updateSphere3D(RefPointer<MAP_T> mapObj, const AreaEffectSimulation::NContamination &data, qint64 newPartitionTime);
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
};
}
@@ -0,0 +1,371 @@
#include "off_route_to_map.h"
#include <Map/map.h>
#include <Map/object_factory.h>
#include <Map/layer_factory.h>
namespace SituationMap
{
static int s_offRouteMine2 = 254;
bool OffRoute2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
return false;
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::offRouteMineChanged,
this, &OffRoute2SituationMap::handleChanged, Qt::UniqueConnection);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &OffRoute2SituationMap::onAesItemViewChanged, Qt::UniqueConnection);
m_aesDtc->offRouteMines([this](const AreaEffectSimulation::OffRouteMine &data)
{
handleChanged(data, DataModification::eAdded);
});
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
connect(m_pluginProvider, &PluginProvider::partitionTimeChanged,
this, &OffRoute2SituationMap::onPartitionTimeChanged, Qt::UniqueConnection);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
void OffRoute2SituationMap::onPartitionTimeChanged(qint64 newPartitionTime)
{
updateAllDetonationSpheres(newPartitionTime);
}
void OffRoute2SituationMap::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, " << " data.aesTypeId()=" << data.aesTypeId() << " modType=" << modType;
if (data.aesTypeId() != AreaEffectSimulation::AesType::AtOffRouteMineSecondary)
return;
const int32_t simId = data.aesItemId();
if (simId < 0)
return;
updateSecondary(simId);
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " data.aesTypeId()=" << data.aesTypeId() << " modType=" << modType;
}
void OffRoute2SituationMap::updateAllDetonationSpheres(qint64 newPartitionTime)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< ", m_simId2UniqueMapId.size = " << m_simId2UniqueMapId.size();
QMapIterator<int32_t, UniqueMapId> it(m_simId2UniqueMapId);
while (it.hasNext())
{
it.next();
const UniqueMapId uniqueMapId = it.value();
RefPointer<MAP_T> mapObj = m_objFac.get<MAP_T>(uniqueMapId);
if (!mapObj.valid())
continue;
const int simId = it.key();
const AreaEffectSimulation::OffRouteMine &offRouteMine = m_aesDtc->offRouteMine(simId);
if (offRouteMine.id() != simId)
continue;
if (updateDetonationSphere3D(mapObj, offRouteMine, newPartitionTime))
if (!mapObj->updateView())
WARNING_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " updateView failed";
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
}
bool OffRoute2SituationMap::updateDetonationSphere3D(RefPointer<Sim2SituationMap::MAP_T> mapObj, const AreaEffectSimulation::OffRouteMine &trap, qint64 newPartitionTime)
{
const int32_t simId = trap.id();
if (!mapObj)
return false;
bool bUpdateRequired = false;
const bool bDesiredNewState = trap.triggered() && ((newPartitionTime - trap.sampleTime() < 5000));
TRACE_LOG(m_logger) << LOGFUNCTION << ", START" << " simId = " << simId
<< ", sampleTime " << trap.sampleTime()
<< ", bDesiredNewState " << bDesiredNewState;
#ifdef RENDERER_APPROACH
if (mapObj->has3DMarkerRenderer() && !bDesiredNewState)
{
INFO_LOG(m_logger) << LOGFUNCTION << ", START REMOVE " << " simId = " << simId;
mapObj->set3DMarkerRenderer(Point3D(), QVariantMap());
bUpdateRequired = true;
}
else if (!mapObj->has3DMarkerRenderer() && bDesiredNewState)
{
INFO_LOG(m_logger) << LOGFUNCTION << ", START ADD " << " simId = " << simId;
const Core::GeoPosition2D &geoPos = trap.area().cornerBottomLeft();
Point3D markerOrigin(geoPos.lon(), geoPos.lat(), 0);
QVariantMap attribMap;
QString attribValue;
const QColor &majorColor = mapObj->majorColor();
attribValue = QString(QStringLiteral("Impact_Color_%1")).arg(majorColor.name());
attribMap.insert(QStringLiteral("IMPACT_COLOR"), attribValue);
const double radius = 10;
attribValue = QString(QStringLiteral("Impact_Radius_%1")).arg(radius);
attribMap.insert(QStringLiteral("IMPACT_RADIUS"), attribValue);
LayerFactory::UniqueValueDataAesCentral::TYPE type{LayerFactory::UniqueValueDataAesCentral::TYPE::SPHERE};
attribValue = QString(QStringLiteral("Impact_Type_%1")).arg(LayerFactory::toString(type));
attribMap.insert(QStringLiteral("IMPACT_TYPE"), attribValue);
attribMap.insert(QStringLiteral("HEADING"), 0);
attribMap.insert(QStringLiteral("PITCH") , 0);
attribMap.insert(QStringLiteral("ROLL") , 90);
mapObj->set3DMarkerRenderer(markerOrigin, attribMap);
bUpdateRequired = true;
}
#else
if (mapObj->has3DMarkerSceneSymbol() && !bDesiredNewState)
{
FATAL_LOG(m_logger) << LOGFUNCTION << ", START REMOVE " << " simId = " << simId;
mapObj->set3DMarkerSceneSymbol(Point3D(), {});
bUpdateRequired = true;
}
else if (!mapObj->has3DMarkerSceneSymbol() && bDesiredNewState)
{
FATAL_LOG(m_logger) << LOGFUNCTION << ", START ADD " << " simId = " << simId;
const Core::GeoPosition2D &geoPos = trap.area().cornerBottomLeft();
Point3D markerOrigin(geoPos.lon(), geoPos.lat(), 0);
VirtualMine::SceneSymbolData ssData;
const QColor &majorColor = mapObj->majorColor();
ssData.color = majorColor;
ssData.radius = std::max( (trap.impactRadius().is_set() ? trap.impactRadius().get() : 1) , 1.0);
ssData.cone = false;
mapObj->set3DMarkerSceneSymbol(markerOrigin, ssData);
}
#endif
TRACE_LOG(m_logger) << LOGFUNCTION << ", END" << " simId = " << simId;
return bUpdateRequired;
}
bool OffRoute2SituationMap::updateSecondary(int32_t simId, bool bUpdateJust3DPart)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " simId = " << simId
<< ", bUpdateJust3DPart" << bUpdateJust3DPart;
if (simId < 0)
return false;
RefPointer<MAP_T> mapObj = this->getMapObjectOfSimId(simId);
if (!mapObj.valid())
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " getMapObjectOfSimId failed"
<< " simId = " << simId << " (maybe expired)";
return false;
}
const AreaEffectSimulation::OffRouteMine &trap = m_aesDtc->offRouteMine(simId);
if (trap.chargeStruct().chargeTypeId() == s_offRouteMine2)
{
AreaEffectSimulation::AesItemView dataAesItemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtOffRouteMineSecondary, dataAesItemView))
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " AesItemViewForSecondary found :-) ";
} else {
WARNING_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " no AesItemViewForSecondary found. :-( ";
}
if ((dataAesItemView.aesItemId() == simId) &&
(trap.id() == simId) &&
trap.triggered())
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " setSubsidiaryLine";
VirtualMine::OptionalData optData;
optData.closed = true;
mapObj->setSubsidiaryLine(0,
form2PosCont(dataAesItemView.form()), optData);
} else {
DEBUG_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " removeSubsidiaryLine";
mapObj->removeSubsidiaryLine(0);
}
if (!mapObj->updateView()){
ERROR_LOG(m_logger) << LOGFUNCTION << " simId = " << simId << " updateView failed";
return false;
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << ", END" << " simId = " << simId
<< " trap.triggered(" << trap.triggered();
return true;
}
bool OffRoute2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
mapObj->setAesState(effectState2aesState(ddsData.effectStateId().underlying()));
const int32_t simId = ddsData.id();
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtOffRouteMine, itemView))
{
this->updateGeometry(itemView, mapObj);
if (m_objFac.map() && (m_objFac.map()->mode() == Mode::Mode_3D))
updateDetonationSphere3D(mapObj, ddsData, m_pluginProvider->partitionTime());
}
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtOffRouteMine) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
updateSecondary(simId);
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool OffRoute2SituationMap::isVisibleByFilter(const Aes2SituationMap::DDS_TYPE &data) const
{
if (!m_displayFilter)
return true;
const auto es = data.effectStart().is_set() ? data.effectStart().get() : 0;
const auto partyId = data.partyId().is_set() ? data.partyId().get() : -1;
bool isVisibleByFilter = partyId > 0 ? FilterClass::m_currentSymbolSettings.symbolSettings.symbolPartyAppearance.value(partyId).isVisible : true;
if (isVisibleByFilter)
isVisibleByFilter = m_displayFilter->isVisible(AreaEffectSimulation::AesType_def::AtMineArea,
data.effectStateId(),
data.chargeStruct().chargeTypeId(),
partyId,
data.isCentral(),
es,
data.effectDuration(),
m_pluginProvider->partitionTime());
return isVisibleByFilter;
}
void OffRoute2SituationMap::onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType)
{
if ((AreaEffectSimulation::AesType_def::AtOffRouteMine != aesType.underlying()) &&
(AreaEffectSimulation::AesType_def::AtMineArea != aesType.underlying()))
return;
const auto cb = [this](const DDS_TYPE &data) -> bool
{
if (data.isDeleted())
return false;
this->updateVisibility(data);
return false;
};
iterateAesData(cb);
}
}
@@ -0,0 +1,67 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/virtual_mine.h>
#include <QObject>
#define OFFROUTEMINE_HAS_SECONDARY_VIEW
namespace SituationMap
{
class OffRoute2SituationMap;
template <>
struct Aes2SituationMapTraits<OffRoute2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::OffRouteMine;
using MAP_TYPE = SituationMap::VirtualMine;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtOffRouteMine;
};
class OffRoute2SituationMap final : public Aes2SituationMap<OffRoute2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<OffRoute2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::OffRouteMine &data)> &cb) const
{
return m_aesDtc->offRouteMines(cb);
}
protected Q_SLOTS:
void onPartitionTimeChanged(qint64 newPartitionTime);
protected:
void updateAllDetonationSpheres(qint64 newPartitionTime);
protected Q_SLOTS:
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
protected:
bool updateDetonationSphere3D(RefPointer<MAP_T> mapObj, const AreaEffectSimulation::OffRouteMine &trap, qint64 newPartitionTime);
bool updateSecondary(int32_t simId, bool bUpdateJust3DPart = false);
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool isVisibleByFilter(const DDS_TYPE &data) const override;
void onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType) override;
};
}
@@ -0,0 +1,228 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include "pdm_handler.h"
#include <Utils/movement_track_manager.h>
#include <Plugins/FilterManagement/flt_data_plugin_interface.h>
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_participant_info_gui_plugin_interface.h>
#include <Plugins/OcSituationClient/osc_participant_info_gui_plugin_interface.h>
#include <Plugins/GuezIedManagement/gim_data_plugin_interface.h>
#include <MapObjects/participant.h>
#include <QPointer>
namespace SituationMap
{
struct HitlineInfo
{
qint32 participantId = -1;
ParticipantManagement::ParticipantPosition participantPosition;
ParticipantManagement::StateInformation participantState;
ParticipantManagement::ParticipantPosition originatorPosition;
qint32 injuryPartyId = -1;
};
class LayerFactory;
class PdmHandler;
class Participant2SituationMap final : public Sim2SituationMap<ParticipantManagement::Participant, SituationMap::Participant>
, protected DdsFilterHandling<SituationMap::Participant>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<ParticipantManagement::Participant, SituationMap::Participant>;
using FilterClass = DdsFilterHandling<SituationMap::Participant>;
struct InternalPosition final : public ParticipantManagement::UnitPosition
{
Core::PositionReportingSource reportingSource;
bool isUnit = true;
bool bShowCenter = false;
bool bIsMountedOn = false;
bool bHasMountedParticipants = false;
inline const Core::GeoPosition &position() const OMG_NOEXCEPT
{
return (isUnit && bShowCenter) ? positionCenter() : positionLeader();
}
inline rti::core::int64 sampleTime() const OMG_NOEXCEPT
{
return (isUnit && bShowCenter) ? sampleTimeCenter() : sampleTimeLeader();
}
InternalPosition() = default;
explicit InternalPosition(const ParticipantManagement::UnitPosition &unitPos_param, bool bCenter)
: ParticipantManagement::UnitPosition(unitPos_param)
, bShowCenter(bCenter)
{}
};
public:
Participant2SituationMap(PdmHandler *pdmHandler,
ObjectFactory &objFac,
const QString &layername,
const char *loggerName);
~Participant2SituationMap();
bool init(LayerFactory *layerFactory,
PluginProvider *pluginProvider);
bool run() override;
void stop() override;
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
void setMovementTrackManager(const QPointer<MovementTrackManager> &mtMgr) { m_movementTrackManager = mtMgr; }
bool enableFireEventFlashing(bool enable);
bool isFireEventFlashingEnabled() const;
bool isParticipantVisible(const int32_t participantId, bool *bParticipantExists) const;
Q_SIGNALS:
void hitlineOccured(const HitlineInfo &hitlineInfo);
void participantPositionChanged(const int32_t participantId, const Point3D &newPos);
void participantOwnPositionChanged(const Point3D &newPos, int64_t sampleTime);
public Q_SLOTS:
void onParticipantFakeGearEventChanged(int participantId, qint64 sampleTime, SpecialChargeType specialChargeType);
protected Q_SLOTS:
void onPartitionTimeChanged(qint64 newPartitionTime);
void onFireEventFlashTimer();
void onTypesChanged(const ParticipantManagement::Type &data,
DataModification modType);
void onParticipantChanged(const ParticipantManagement::Participant &data,
DataModification modType);
void onPositionChanged(const ParticipantManagement::ParticipantPosition &data,
DataModification modType);
void onUnitPositionChanged(const ParticipantManagement::UnitPosition &data,
DataModification modType);
void updateParticipantPosition(int participantId, bool bHandleSymbolAppearanceSettingsParticipant = true);
void updateParticipantPosition(const InternalPosition &pos, bool bHandleSymbolAppearanceSettingsParticipant = true);
void onDynamicParticipantDataChanged(const ParticipantManagement::DynamicParticipantData &data,
DataModification modType);
void onBiteChanged(const ParticipantManagement::Bite &data,
DataModification modType);
void onParticipantGearEventChanged(const ParticipantManagement::ParticipantGearEvent &data, DataModification modType);
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
void onDusMineStateChanged(const AreaEffectSimulation::DusMineState &data, DataModification modType);
void onMovementTrackActivityChanged(int trackId, bool active);
void onMovementTrackRemoved(int trackId);
void addToUpdateNotify(const RefPointer<MAP_T> &mapObj);
void notifyMapAboutModifedObjects();
protected:
void updateHierarchyLevels();
int participantHierachyLevel(const ParticipantManagement::Participant &data) const;
QString layernameWithHierachy(qint32 hierachyLevel) const;
QString layernameWithHierachy(const Sim2SituationMap::DDS_T &ddsData) const override;
bool isElapsed(const ParticipantManagement::Participant &data) const override;
void checkForUnknownOriginatorsParticipant(int possibleOriginatorParticipantId);
void checkForUnknownOriginatorsAes(int possibleOriginatorEffectSimId);
bool updateDynamicParticipantData(RefPointer<Sim2SituationMap::MAP_T> mapObj, const ParticipantManagement::DynamicParticipantData &data);
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const ParticipantManagement::Participant &ddsData,
RefPointer<Participant> mapObj) override;
bool removeElement(const int32_t simId) override;
void updateGearEvents(bool doUpdateView = false);
void updateGearEventInternal(bool doUpdateView,
qint64 curPartitionTimeMSec,
qint64 fireEventFlashingDurationMSec,
const QSet<int> &particpantIdsWithGearEvents);
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings & ) const override
{
return true;
}
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override;
void onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part part) override;
bool hasBitError(const ParticipantManagement::DynamicParticipantData &dpd) const;
bool isOutOfDate(const InternalPosition &pos) const;
bool isSimulatedPosition(const InternalPosition &pos) const;
void handleSymbolAppearanceSettingsParticipant(int participantId);
void handleSymbolAppearanceSettingsParticipant(RefPointer<MAP_T> &mapObj,
const ParticipantManagement::Participant &participant);
void handleSymbolAppearanceSettingsParticipant(RefPointer<MAP_T> &mapObj,
const ParticipantManagement::Participant &participant,
const InternalPosition &pPos,
const ParticipantManagement::DynamicParticipantData &dpd);
private:
LayerFactory *m_layerFactory = nullptr;
PluginProvider *m_pluginProvider = nullptr;
QTimer *m_notifiyTimer = nullptr;
std::shared_ptr<AreaEffectSimulation::Interface::Dtc> m_aesDtc;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
std::shared_ptr<ParticipantManagement::ForeignParticipantInfoGuiInterface> m_ppmParticipantInfoIfc;
std::shared_ptr<OcSituationClient::ForeignParticipantInfoGuiInterface> m_ocParticipantInfoIfc;
QHash<qint32, ParticipantManagement::Type> m_types;
QHash<int, ParticipantManagement::Participant> m_participants;
QHash<int, InternalPosition> m_participantPositions;
QHash<int, ParticipantManagement::DynamicParticipantData> m_participantDynamicData;
QHash<int, qint64> m_participantGearEvents;
QHash<int, qint64> m_lrfParticipantFakeGearEvents;
QHash<int, qint64> m_ltdParticipantFakeGearEvents;
QHash<int, bool> m_participantsWithProperties;
QVector<QPair<int, int>> m_unknownOriginatorsParticipant;
QVector<QPair<int, int>> m_unknownOriginatorsAes;
QSet<int> m_participantWithMaybeMissingPartyId;
QHash<int, int> m_aesItemView2PartyId;
QVector<RefPointer<MAP_T>> m_objectsToUpdate;
QSet<int> m_hasBiteError;
PdmHandler *m_pdmHandler;
bool m_bShowCenterPositions = false;
QTimer *m_fireEventFlashTimer = nullptr;
int m_fireEventFlashTriState = 0;
bool m_fireEventFlashEnable = true;
QPointer<SituationMap::MovementTrackManager> m_movementTrackManager;
};
}
@@ -0,0 +1,200 @@
#include "pdm_handler.h"
#include <ProjectDataManagement/pdm_dtc.h>
#include <QJsonDocument>
#include <QJsonObject>
namespace SituationMap
{
QString toString(SpecialChargeType value)
{
switch (value)
{
case SpecialChargeType::NoneSpecial:
return QStringLiteral("SpecialChargeType:NoneSpecial");
case SpecialChargeType::LRF:
return QStringLiteral("SpecialChargeType:LRF");
case SpecialChargeType::LTD:
return QStringLiteral("SpecialChargeType:LTD");
}
Q_ASSERT(false);
return QStringLiteral("SpecialChargeTypeERROR");
}
PdmHandler::PdmHandler(const std::shared_ptr<ProjectDataManagement::Interface::Dtc> &dtcPdm)
: m_dtcPdm(dtcPdm)
, m_logger(getLogger("PdmHandler"))
{}
void PdmHandler::initializePdm()
{
if (m_dtcPdm == nullptr)
return;
if (m_bPdmInitialized)
return;
m_bPdmInitialized = true;
connect(m_dtcPdm.get(), &ProjectDataManagement::Interface::Dtc::chargeTypeChanged,
this, &PdmHandler::onChargeTypeChanged);
connect(m_dtcPdm.get(), &ProjectDataManagement::Interface::Dtc::gearTypeChargeTypeChanged,
this, &PdmHandler::onGearTypeChargeTypeChanged);
m_chargeTypes = m_dtcPdm->chargeTypes();
m_gearTypeChargeTypes = m_dtcPdm->gearTypeChargeTypes();
}
void PdmHandler::onChargeTypeChanged(const ProjectDataManagement::ChargeType &data, DataModification mod)
{
switch (mod)
{
case DataModification::eAdded:
case DataModification::eModified:
m_chargeTypes[data.id()] = data;
break;
case DataModification::eRemoved:
break;
}
}
void PdmHandler::onGearTypeChargeTypeChanged(const ProjectDataManagement::GearTypeChargeType &data, DataModification mod)
{
switch (mod)
{
case DataModification::eAdded:
case DataModification::eModified:
m_gearTypeChargeTypes[data.id()] = data;
break;
case DataModification::eRemoved:
break;
}
}
ProjectDataManagement::ChargeType PdmHandler::chargeTypeFromId(int chargeTypeId)
{
if (chargeTypeId <= 0)
return ProjectDataManagement::ChargeType();
initializePdm();
auto it = m_chargeTypes.constFind(chargeTypeId);
if (it == m_chargeTypes.cend())
{
WARNING_LOG(m_logger) << "Could not find charge type with id " << chargeTypeId;
return ProjectDataManagement::ChargeType();
}
return it.value();
}
int PdmHandler::maxRangeFromGearTypeIdAndChargeTypeId(int gearTypeId, int chargeTypeId)
{
if (gearTypeId < 0)
return -1;
if (chargeTypeId < 0)
return -1;
initializePdm();
for (const auto &entry : qAsConst(m_gearTypeChargeTypes))
if ((entry.gearTypeId() == gearTypeId) &&
(entry.chargeTypeId() == chargeTypeId))
return entry.maxRange();
for (const auto &entry : qAsConst(m_gearTypeChargeTypes))
if ((entry.gearTypeId() == 1000) &&
(entry.chargeTypeId() == chargeTypeId))
return entry.maxRange();
return -1;
}
double PdmHandler::impactRadius(const AreaEffectSimulation::ChargeStruct &chargeStruct, double defaultValue)
{
if (chargeStruct.chargeTypeId() < 0)
return defaultValue;
initializePdm();
if (!m_dtcPdm)
return defaultValue;
return m_dtcPdm->impactRadius(chargeStruct.chargeTypeId(), chargeStruct.igniterTypeId(), chargeStruct.igniterFunctionId());
}
bool PdmHandler::isSmart(const AreaEffectSimulation::ChargeStruct &chargeStruct)
{
if (chargeStruct.chargeTypeId() < 0)
return false;
initializePdm();
if (!m_dtcPdm)
return false;
return m_dtcPdm->isSmart(chargeStruct.chargeTypeId(), chargeStruct.igniterTypeId(), chargeStruct.igniterFunctionId());
}
QString PdmHandler::trChargeTypeShortName(int chargeTypeId)
{
if (!m_dtcPdm)
return QString();
return m_dtcPdm->trChargeTypeShortName(chargeTypeId);
}
bool PdmHandler::isLRFChargeType(int chargeTypeId)
{
return isSpecialChargeType(chargeTypeId) == SpecialChargeType::LRF;
}
bool PdmHandler::isLTDChargeType(int chargeTypeId)
{
return isSpecialChargeType(chargeTypeId) == SpecialChargeType::LTD;
}
bool PdmHandler::isChargeTypeLtdOrLrf(SpecialChargeType sct)
{
return ((sct == SpecialChargeType::LRF) || (sct == SpecialChargeType::LTD));
}
ProjectDataManagement::GearClass PdmHandler::gearClassFromChargeTypeId(int chargeTypeId)
{
if (!m_dtcPdm)
return ProjectDataManagement::GearClass_def::Unknown;
return m_dtcPdm->gearClassFromChargeTypeId(chargeTypeId);
}
QVector<ProjectDataManagement::CasEffect> PdmHandler::casEffects(const AreaEffectSimulation::ChargeStruct &chargeStruct)
{
if (!m_dtcPdm)
return {};
return m_dtcPdm->casEffects(chargeStruct.chargeTypeId(), chargeStruct.igniterTypeId(), chargeStruct.igniterFunctionId());
}
bool PdmHandler::isChargeTypeLtdOrLrf(int chargeTypeId)
{
const SpecialChargeType specialChargeTypeId = isSpecialChargeType(chargeTypeId);
return isChargeTypeLtdOrLrf(specialChargeTypeId);
}
SpecialChargeType PdmHandler::isSpecialChargeType(int chargeTypeId)
{
ProjectDataManagement::ChargeTypeProperty ret = m_dtcPdm->getChargeTypeSpecialProperty(chargeTypeId, 0,0);
if (ret == ProjectDataManagement::ChargeTypeProperty::LRF)
return SpecialChargeType::LRF;
if (ret == ProjectDataManagement::ChargeTypeProperty::LTD)
return SpecialChargeType::LTD;
return SpecialChargeType::NoneSpecial;
}
}
@@ -0,0 +1,82 @@
#pragma once
#include <Common/situation_map_logging.h>
#include <QMap>
#include <QObject>
#include <memory>
#include <LtsUtilsCore/data_modification_enum.h>
#include <ProjectDataManagement/pdm_dtc.h>
#include <AreaEffectSimulation/aes_dtc.h>
namespace SituationMap
{
enum class SpecialChargeType
{
NoneSpecial,
LRF,
LTD
};
QString toString(SpecialChargeType value);
static inline std::ostream &operator<< (std::ostream &stream,
const SpecialChargeType value)
{
stream << "SpecialChargeType " << toString(value);
return stream;
}
class PdmHandler : public QObject
{
Q_OBJECT
public:
explicit PdmHandler(const std::shared_ptr<ProjectDataManagement::Interface::Dtc> &dtcPdm);
ProjectDataManagement::ChargeType chargeTypeFromId(int chargeTypeId);
int maxRangeFromGearTypeIdAndChargeTypeId(int gearTypeId, int chargeTypeId);
double impactRadius(const AreaEffectSimulation::ChargeStruct &chargeStruct, double defaultValue = 10.0);
bool isSmart(const AreaEffectSimulation::ChargeStruct &chargeStruct);
QString trChargeTypeShortName(int chargeTypeId);
SpecialChargeType isSpecialChargeType(int chargeTypeId);
bool isLRFChargeType(int chargeTypeId);
bool isLTDChargeType(int chargeTypeId);
bool isChargeTypeLtdOrLrf(int chargeTypeId);
static bool isChargeTypeLtdOrLrf(SpecialChargeType sct);
ProjectDataManagement::GearClass gearClassFromChargeTypeId(int chargeTypeId);
QVector<ProjectDataManagement::CasEffect> casEffects(const AreaEffectSimulation::ChargeStruct &chargeStruct);
private:
void initializePdm();
void onChargeTypeChanged(const ProjectDataManagement::ChargeType &data, DataModification mod);
void onGearTypeChargeTypeChanged(const ProjectDataManagement::GearTypeChargeType &data, DataModification mod);
private:
std::shared_ptr<ProjectDataManagement::Interface::Dtc> m_dtcPdm;
QMap<int, ProjectDataManagement::ChargeType> m_chargeTypes;
QMap<int, ProjectDataManagement::GearTypeChargeType> m_gearTypeChargeTypes;
bool m_bPdmInitialized{false};
LOGGER_T m_logger;
};
}
@@ -0,0 +1,234 @@
#pragma once
#include <memory>
#include <QObject>
#include <SituationMap/sitmapdds_export.h>
namespace LtsAppDescriptor
{
enum class App;
}
namespace AlarmManagement
{
class ForeignInfoGuiInterface;
namespace Interface
{
class Dtc;
class Ftc;
}
}
namespace AssetManagement
{
namespace Interface
{
class Dtc;
class Ftc;
}
}
namespace AreaEffectSimulation
{
class ForeignInfoGuiInterface;
namespace Interface
{
class Dtc;
}
}
namespace Buildings
{
namespace Interface
{
class Dtc;
class Ftc;
}
class ForeignInfoGuiInterface;
}
namespace CentralEffectSimulation
{
namespace Interface
{
class Dtc;
}
}
namespace ExerciseManagement
{
namespace Interface
{
class Dtc;
class Ftc;
}
}
namespace FilterManagement
{
class ForeignFltParticipantGuiInterface;
class ForeignAesGuiInterface;
class ForeignFltBuildingComponentGuiInterface;
namespace Interface
{
class Dtc;
class Ftc;
}
}
namespace GuezIedManagement
{
class ForeignGuiInterface;
namespace Interface
{
class Dtc;
}
}
namespace GuezNasat
{
class ForeignGuiInterface;
namespace Interface
{
class Dtc;
}
}
namespace InfrastructureManagement
{
class ForeignDataInterface;
class ForeignResourceManagementGuiInterface;
namespace Interface
{
class Dtc;
}
}
namespace OperatorManagement
{
namespace Interface
{
class Dtc;
class Ftc;
}
}
namespace ParticipantManagement
{
class ForeignParticipantInfoGuiInterface;
namespace Interface
{
class Dtc;
class Ftc;
}
}
namespace SituationReplay
{
namespace Interface
{
class Dtc;
}
}
namespace ProjectDataManagement
{
namespace Interface
{
class Dtc;
}
}
namespace OcSituationClient
{
class ForeignParticipantInfoGuiInterface;
}
namespace ServiceMonitor
{
class ForeignGuiInterface;
}
namespace TargetManagement
{
namespace Interface
{
class Dtc;
}
}
namespace ComponentMonitor
{
namespace Interface
{
class Dtc;
}
}
namespace SituationMap
{
class SITMAPDDS_EXPORT PluginProvider : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
virtual QString toString() const = 0;
virtual int exerciseId() const = 0;
virtual bool isSessionValid() const = 0;
virtual qint64 partitionTime() const = 0;
virtual int partitionId() const = 0;
virtual int operatorId() const = 0;
virtual LtsAppDescriptor::App appId() const = 0;
virtual bool isVisibleParty(int partyId) const = 0;
virtual QString workspaceId() const = 0;
virtual bool isReplayPartition() const = 0;
virtual std::shared_ptr<AreaEffectSimulation::Interface::Dtc> aesDtc() const = 0;
virtual std::shared_ptr<AreaEffectSimulation::ForeignInfoGuiInterface> aesInfoIfc() const = 0;
virtual std::shared_ptr<AlarmManagement::Interface::Dtc> almDtc() const = 0;
virtual std::shared_ptr<AlarmManagement::Interface::Ftc> almFtc() const = 0;
virtual std::shared_ptr<AlarmManagement::ForeignInfoGuiInterface> almInfoIfc() const = 0;
virtual std::shared_ptr<AssetManagement::Interface::Dtc> asmDtc() const = 0;
virtual std::shared_ptr<AssetManagement::Interface::Ftc> asmFtc() const = 0;
virtual std::shared_ptr<Buildings::Interface::Dtc> bldDtc() const = 0;
virtual std::shared_ptr<Buildings::Interface::Ftc> bldFtc() const = 0;
virtual std::shared_ptr<Buildings::ForeignInfoGuiInterface> bldInfoIfc() const = 0;
virtual std::shared_ptr<CentralEffectSimulation::Interface::Dtc> cesDtc() const = 0;
virtual std::shared_ptr<ExerciseManagement::Interface::Dtc> exmDtc() const = 0;
virtual std::shared_ptr<ExerciseManagement::Interface::Ftc> exmFtc() const = 0;
virtual std::shared_ptr<FilterManagement::Interface::Dtc> fltDtc() const = 0;
virtual std::shared_ptr<FilterManagement::Interface::Ftc> fltFtc() const = 0;
virtual std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> fltParticipantIfc() const = 0;
virtual std::shared_ptr<FilterManagement::ForeignAesGuiInterface> fltAesIfc() const = 0;
virtual std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> fltBuildingComponentIfc() const = 0;
virtual std::shared_ptr<GuezIedManagement::Interface::Dtc> gimDtc() const = 0;
virtual std::shared_ptr<GuezIedManagement::ForeignGuiInterface> gimIfc() const = 0;
virtual std::shared_ptr<GuezNasat::Interface::Dtc> gnaDtc() const = 0;
virtual std::shared_ptr<GuezNasat::ForeignGuiInterface> gnaIfc() const = 0;
virtual std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc() const = 0;
virtual std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismDataIfc() const = 0;
virtual std::shared_ptr<InfrastructureManagement::ForeignResourceManagementGuiInterface> ismGuiIfc() const = 0;
virtual std::shared_ptr<OperatorManagement::Interface::Dtc> opmDtc() const = 0;
virtual std::shared_ptr<OperatorManagement::Interface::Ftc> opmFtc() const = 0;
virtual std::shared_ptr<ParticipantManagement::Interface::Dtc> ppmDtc() const = 0;
virtual std::shared_ptr<SituationReplay::Interface::Dtc> srpDtc() const = 0;
virtual std::shared_ptr<ParticipantManagement::Interface::Ftc> ppmFtc() const = 0;
virtual std::shared_ptr<ParticipantManagement::ForeignParticipantInfoGuiInterface> ppmParticipantInfoIfc() const = 0;
virtual std::shared_ptr<ProjectDataManagement::Interface::Dtc> pdmDtc() const = 0;
virtual std::shared_ptr<OcSituationClient::ForeignParticipantInfoGuiInterface> ocParticipantInfoIfc() const = 0;
virtual std::shared_ptr<ServiceMonitor::ForeignGuiInterface> smoServiceMonitorIfc() const = 0;
virtual std::shared_ptr<TargetManagement::Interface::Dtc> tgtDtc() const = 0;
virtual std::shared_ptr<ComponentMonitor::Interface::Dtc> cmoDtc() const = 0;
signals:
void partitionTimeChanged(qint64 partitionTime);
void workspaceIdChanged(const QString &newWorkspaceId);
};
}
@@ -0,0 +1,76 @@
#include "recon_area_to_map.h"
namespace SituationMap
{
bool ReconArea2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::reconAreaChanged,
this, &ReconArea2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->reconAreas([this](const AreaEffectSimulation::ReconArea &data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool ReconArea2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setVisibility(ObjectAppearance::Tactical, false);
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
if (ddsData.partyId().is_set())
mapObj->setPartyId(ddsData.partyId().get());
else
{
mapObj->rLineStyle().setLineColor(Qt::black);
mapObj->rFillStyle().setFillColor(Qt::black);
}
mapObj->setAesState(effectState2aesState(ddsData.effectStateId().underlying()));
const int32_t simId = ddsData.id();
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, Aes2SituationMapTraits<ReconArea2SituationMap>::aesType, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtReconArea) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,44 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/biological_agent.h>
#include <QObject>
#include <memory>
namespace SituationMap
{
class ReconArea2SituationMap;
template <>
struct Aes2SituationMapTraits<ReconArea2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::ReconArea;
using MAP_TYPE = SituationMap::BiologicalAgent;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtReconArea;
};
class ReconArea2SituationMap final : public Aes2SituationMap<ReconArea2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<ReconArea2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::ReconArea &data)> &cb) const
{
return m_aesDtc->reconAreas(cb);
}
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
};
}
@@ -0,0 +1,20 @@
#pragma once
#include <QString>
namespace SituationMap
{
enum class ResourceManagerMode
{
Undefined,
RMM_PlanActivityView,
RMM_PlanDefinitionView,
RMM_ComponentMonitor
};
}
@@ -0,0 +1,102 @@
#include "shootback_area_to_map.h"
#include <LtsUtilsCore/dds_bitarray.h>
#include <LtsCoordTrans/lts_coord_trans.h>
namespace SituationMap
{
bool ShootbackAreaToSituationMap::init(PluginProvider *pluginProvider)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!pluginProvider ||
!pluginProvider->asmDtc())
return false;
m_pluginProvider = pluginProvider;
DEBUG_LOG(m_logger) << LOGFUNCTION << " exerciseId=" << m_pluginProvider->exerciseId();
m_tgtDtc = m_pluginProvider->tgtDtc();
FilterClass::init(m_pluginProvider);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool ShootbackAreaToSituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_tgtDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
this->stop();
connect(m_tgtDtc.get(), &TargetManagement::Interface::Dtc::shootbackAreaChanged,
this, &ShootbackAreaToSituationMap::handleChanged, Qt::UniqueConnection);
m_tgtDtc->shootbackAreas([this](const TargetManagement::ShootbackArea & data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void ShootbackAreaToSituationMap::stop()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << "Stopping";
if (m_tgtDtc)
m_tgtDtc->disconnect(this);
}
int32_t ShootbackAreaToSituationMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool ShootbackAreaToSituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setLineStyle(LineStyle(Qt::black, 2, LinePattern::Solid));
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
const Core::GeoPosition2D &center = ddsData.position();
const LtsCoordTrans::UtmCoordinate referencePointUTM = LtsCoordTrans::UtmCoordinate::fromGeographic(center.lon(), center.lat());
const QPointF size(ddsData.width() / 2.0, ddsData.height() / 2.0);
PositionCont posCont;
posCont.reserve(4);
posCont.push_back(Point3D::fromQPointF(referencePointUTM.geographic(size.x() * -1, size.y() * -1)));
posCont.push_back(Point3D::fromQPointF(referencePointUTM.geographic(size.x() * -1, size.y() * +1)));
posCont.push_back(Point3D::fromQPointF(referencePointUTM.geographic(size.x() * +1, size.y() * +1)));
posCont.push_back(Point3D::fromQPointF(referencePointUTM.geographic(size.x() * +1, size.y() * -1)));
mapObj->setPositions(posCont);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,56 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/TargetManagement/tgt_data_plugin_interface.h>
#include <MapObjects/polygon.h>
#include <QObject>
namespace SituationMap
{
class ShootbackAreaToSituationMap final : public Sim2SituationMap<TargetManagement::ShootbackArea, SituationMap::Polygon>
, protected DdsFilterHandling<SituationMap::Polygon>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<TargetManagement::ShootbackArea, SituationMap::Polygon>;
using FilterClass = DdsFilterHandling<SituationMap::Polygon>;
public:
ShootbackAreaToSituationMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
, m_pluginProvider(nullptr)
{}
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override;
protected:
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale);
}
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override
{
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
}
private:
PluginProvider *m_pluginProvider;
std::shared_ptr<TargetManagement::Interface::Dtc> m_tgtDtc;
};
}
@@ -0,0 +1,680 @@
#pragma once
#include "unified_map_object_data.h"
#include "plugin_provider.h"
#include <Map/object_factory.h>
#include <Common/situation_map_logging.h>
#include <LtsUtilsCore/data_modification_enum.h>
#include <LtsAppDescriptor/lts_app_descriptor.h>
#include <FilterManagement/flt_data_plugin_interface.h>
#include <FilterManagement/flt_participant_plugin_interface.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <FilterManagement/flt_building_cmpnt_plugin_interface.h>
#include <FilterManagement/flt_building_cmpnt_settings.h>
#include <QObject>
#include <QMap>
#include <QVector>
const char SimIdProperty[] = "SimId";
namespace SituationMap
{
class Sim2SituationMapBase : public QObject
{
Q_OBJECT
using BaseClass = QObject;
public:
Sim2SituationMapBase(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass()
, m_objFac(objFac)
, m_assignDrawOrder(true)
, m_drawOrder(drawOrder)
, m_layername(layername)
, m_loggerName(QString::fromLatin1(loggerName))
, m_logger(getLogger(loggerName))
{}
virtual ~Sim2SituationMapBase() = default;
bool assignDrawOrder() const
{
return m_assignDrawOrder;
}
void setAssignDrawOrder(bool assignDrawOrder)
{
m_assignDrawOrder = assignDrawOrder;
}
virtual bool run() = 0;
virtual void stop() = 0;
virtual void clearObjects() = 0;
virtual bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
Q_UNUSED(uniqueMapIds);
return false;
}
virtual bool unifiedMapObjectData(UniqueMapId , UnifiedMapObjectData &) const
{
return false;
}
long mapObjectCount() const
{
return m_simId2UniqueMapId.size();
}
UniqueMapId simId2UniqueMapId(int32_t simId) const
{
const UniqueMapId uniqueMapId = m_simId2UniqueMapId.value(simId, SituationMap::INVALID_MAP_ID);
return uniqueMapId;
}
bool uniqueMapId2SimId(UniqueMapId uniqueMapId, int32_t &simId) const
{
if (!SituationMap::isUniqueMapIdValid(uniqueMapId))
return false;
simId = m_uniqueMapId2SimId.value(uniqueMapId, -1);
return (simId != -1);
}
const QVector<int32_t> uniqueMapIds2SimIds(const QVector<UniqueMapId> &uniqueMapIds) const
{
QVector<int32_t> simIds;
simIds.reserve(uniqueMapIds.size());
int32_t simId_entityId = -1;
for(const UniqueMapId uniqueMapId : qAsConst(uniqueMapIds))
{
if (this->uniqueMapId2SimId(uniqueMapId, simId_entityId))
simIds.append(simId_entityId);
}
return simIds;
}
virtual qint64 startTime(UniqueMapId uniqueMapId) const
{
Q_UNUSED(uniqueMapId);
return -1;
}
const QString &layername() const
{
return m_layername;
}
template <typename MAP_T>
void iterateObjects(const std::function<void( RefPointer<MAP_T> &mapObj)> &f)
{
for (const UniqueMapId &uniqueMapId : qAsConst(m_simId2UniqueMapId))
{
RefPointer<MAP_T> mapObj = m_objFac.get<MAP_T>(uniqueMapId);
if (!mapObj.valid())
continue;
f(mapObj);
}
}
virtual void reRenderObjects()
{
for (const UniqueMapId &uniqueMapId : qAsConst(m_simId2UniqueMapId))
{
RefPointer<AbstractMapObject> mapObj = m_objFac.get(uniqueMapId);
if (!mapObj.valid())
continue;
mapObj->reRenderSymbol();
mapObj->updateView();
if (!mapObj->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " updateElement failed, "
<< " uniqueMapId = " << uniqueMapId
<< " debugInfo='" << mapObj->debugInfo() << "'";
}
}
void emit_visibilityHasChangedSignal()
{
emit visibilityHasChangedSignal();
}
virtual void symbolAppearanceSettingsChangedPostOperation()
{
}
Q_SIGNALS:
void mapObjectChanged(UniqueMapId uniqueMapId);
void mapObjectRemoved(UniqueMapId uniqueMapId);
void visibilityHasChangedSignal();
protected:
ObjectFactory &m_objFac;
bool m_assignDrawOrder;
int m_drawOrder;
const QString m_layername;
QMap<int32_t, UniqueMapId> m_simId2UniqueMapId;
QMap<UniqueMapId, int32_t> m_uniqueMapId2SimId;
QString m_loggerName;
LOGGER_T m_logger;
};
template <typename DDS_TYPE, typename MAP_TYPE>
class Sim2SituationMap : public Sim2SituationMapBase
{
public:
using DDS_T = DDS_TYPE;
using MAP_T = MAP_TYPE;
Sim2SituationMap(ObjectFactory &objFac,
const QString &layername,
const char *loggerName)
: Sim2SituationMapBase(objFac, layername, 0, loggerName)
{}
Sim2SituationMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: Sim2SituationMapBase(objFac, layername, drawOrder, loggerName)
{}
~Sim2SituationMap()
{
}
virtual int32_t getSimId(const DDS_TYPE &ddsData) const = 0;
virtual bool isElapsed(const DDS_TYPE &ddsData) const
{
Q_UNUSED(ddsData)
return false;
}
RefPointer<MAP_T> getMapObjectOfUniqueMapId(const UniqueMapId uniqueMapId) const
{
if (!isUniqueMapIdValid(uniqueMapId))
return {};
return m_objFac.get<MAP_T>(uniqueMapId);
}
RefPointer<MAP_T> getMapObjectOfSimId(const int32_t simId) const
{
const UniqueMapId uniqueMapId = m_simId2UniqueMapId.value(simId, INVALID_MAP_ID);
return getMapObjectOfUniqueMapId(uniqueMapId);
}
protected:
void addProperties(RefPointer<MAP_T> mapObj, int32_t simId)
{
if (mapObj)
mapObj->setProperty(SimIdProperty, simId);
}
virtual QString layernameWithHierachy(const DDS_T &ddsData) const
{
Q_UNUSED(ddsData);
return m_layername;
}
virtual bool createElement(const DDS_T &ddsData)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " simId = " << getSimId(ddsData);
const int32_t simId = getSimId(ddsData);
if (m_simId2UniqueMapId.contains(simId))
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " mapObject already exists"
<< " simId = " << simId;
return true;
}
const QString &debugInfo = QStringLiteral("%1_%2").arg(m_loggerName).arg(simId);
const QString &layername = this->layernameWithHierachy(ddsData);
RefPointer<MAP_T> mapObj = m_objFac.create<MAP_T>(layername, debugInfo);
if (!mapObj)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " creation failed"
<< " simId = " << simId;
return false;
}
if (m_assignDrawOrder)
mapObj->setDrawOrder(m_drawOrder);
addProperties(mapObj, simId);
const UniqueMapId uniqueMapId = mapObj->uniqueMapId();
if (!isUniqueMapIdValid(uniqueMapId))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " uniqueMapId invalid"
<< " simId = " << simId;
return false;
}
m_simId2UniqueMapId[simId] = uniqueMapId;
m_uniqueMapId2SimId[uniqueMapId] = simId;
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
virtual bool updateElementImpl(const DDS_T &ddsData, RefPointer<MAP_T> mapObj) = 0;
bool updateElement(const DDS_T &ddsData)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< " simId = " << getSimId(ddsData);
const int32_t simId = getSimId(ddsData);
const UniqueMapId uniqueMapId = m_simId2UniqueMapId.value(simId, INVALID_MAP_ID);
if (!isUniqueMapIdValid(uniqueMapId))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " not found" << " simId = " << simId;
return false;
}
RefPointer<MAP_T> mapObj = m_objFac.get<MAP_T>(uniqueMapId);
if (!mapObj)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " not found in objFac"
<< " simId = " << simId
<< " uniqueMapId = " << uniqueMapId;
return false;
}
bool success = updateElementImpl(ddsData, mapObj);
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " updateElementImpl failed, "
<< " simId = " << getSimId(ddsData);
return false;
}
handleSymbolAppearanceSettings(mapObj);
handleBuildingComponentSettings(mapObj);
if (!mapObj->updateView())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " updateElement failed, "
<< " simId = " << getSimId(ddsData);
return false;
}
emit mapObjectChanged(uniqueMapId);
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool removeElement(const DDS_T &ddsData)
{
const int32_t simId = getSimId(ddsData);
DEBUG_LOG(m_logger) << LOGFUNCTION << " START" << " simId = " << simId;
return removeElement(simId);
}
virtual bool removeElement(const int32_t simId)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START" << " simId = " << simId;
const UniqueMapId uniqueMapId = m_simId2UniqueMapId.value(simId, INVALID_MAP_ID);
if (!isUniqueMapIdValid(uniqueMapId))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " not found"
<< ", simId = " << simId;
return false;
}
RefPointer<MAP_T> mapObj = m_objFac.get<MAP_T>(uniqueMapId);
if (mapObj)
{
mapObj->removeMySelf();
m_simId2UniqueMapId.remove(simId);
m_uniqueMapId2SimId.remove(uniqueMapId);
}
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " not found in objFac"
<< " simId = " << simId
<< " uniqueMapId = " << uniqueMapId;
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
emit mapObjectRemoved(uniqueMapId);
return true;
}
virtual void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) = 0;
virtual void handleBuildingComponentSettings(RefPointer<MAP_T> &)
{
}
public:
void clearObjects() override
{
const QList<int32_t> &simIds = m_simId2UniqueMapId.keys();
for(int32_t simId : simIds)
this->removeElement(simId);
}
protected:
bool handleChanged(const DDS_T &ddsData, DataModification modType)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< " modType = " << modType
<< " simId = " << getSimId(ddsData);
const bool bIsElapsed = isElapsed(ddsData);
if (bIsElapsed && (modType == DataModification::eAdded))
modType = DataModification::eRemoved;
if (bIsElapsed && modType == DataModification::eModified)
modType = DataModification::eRemoved;
bool success = false;
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
success = this->createElement(ddsData) && this->updateElement(ddsData);
break;
case DataModification::eRemoved:
success = this->removeElement(ddsData);
break;
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
return success;
}
QHash<int, DDS_T> m_ddsDataContainer;
void updateDdsDataContainer(const DDS_T &data, DataModification modType)
{
int simId = getSimId(data);
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
m_ddsDataContainer[simId] = data;
break;
case DataModification::eRemoved:
m_ddsDataContainer.remove(simId);
break;
}
}
};
template <typename MAP_T>
class DdsFilterHandling :
protected FilterManagement::SymbolAppearanceSettings::SettingsChangedCallback,
protected FilterManagement::BuildingComponentSettings::SettingsChangedCallback
{
public:
DdsFilterHandling(const char *loggerName, Sim2SituationMapBase *smBase)
: m_smBase(smBase)
, my_logger(getLogger(loggerName))
{}
virtual ~DdsFilterHandling()
{
removeSymbolAppearanceCallback();
removeBuildingComponentCallback();
}
protected:
void init(PluginProvider *pluginProvider)
{
m_pluginProvider = pluginProvider;
onWorkspaceIdChanged(m_pluginProvider->workspaceId());
QObject::connect(pluginProvider, &PluginProvider::workspaceIdChanged, m_smBase,
[this](const QString &newWorkspaceId) { onWorkspaceIdChanged(newWorkspaceId); });
}
virtual void onWorkspaceIdChanged(const QString &newWorkspaceId)
{
DEBUG_LOG(my_logger) << LOGFUNCTION << ": onWorkspaceIdChanged: " << newWorkspaceId
<< ", m_pluginProvider->toString: " << m_pluginProvider->toString();
removeSymbolAppearanceCallback();
removeBuildingComponentCallback();
const auto fltParticipantIfc = m_pluginProvider->fltParticipantIfc();
if (fltParticipantIfc)
{
m_symbolAppearanceSettings = fltParticipantIfc->symbolAppearanceForOperator(m_pluginProvider->operatorId(),
m_pluginProvider->workspaceId());
if (m_symbolAppearanceSettings)
m_symbolAppearanceSettings->addChangedCallback(this);
else
{
ERROR_LOG(my_logger) << LOGFUNCTION << " addChangedCallback SymAppearance failed";
#ifdef LTS_DEBUG
Q_ASSERT(false);
#endif
}
onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part::All);
}
else
ERROR_LOG(my_logger) << LOGFUNCTION << " no FilterManagement flm";
if (m_symbolAppearanceSettings && !m_symbolAppearanceSettings->isChangedCallbackRegistered(this))
for (int i=0; i<20;++i)
ERROR_LOG(my_logger) << LOGFUNCTION << " isChangedCallbackRegistered SymApp failure!!!";
const auto buildingComponentIfc = m_pluginProvider->fltBuildingComponentIfc();
if (buildingComponentIfc)
{
m_buildingComponentSettings = buildingComponentIfc->buildingComponentSettingsForOperator(m_pluginProvider->operatorId(),
m_pluginProvider->workspaceId());
if (m_buildingComponentSettings)
m_buildingComponentSettings->addChangedCallback(this);
else
{
ERROR_LOG(my_logger) << LOGFUNCTION << " addChangedCallback BldgCmpnt failed";
#ifdef LTS_DEBUG
Q_ASSERT(false);
#endif
}
onBuildingComponentSettingsChanged();
}
else if (m_pluginProvider->appId() == LtsAppDescriptor::App::ResourceManager)
ERROR_LOG(my_logger) << LOGFUNCTION << " no FilterManagement flm (fltBuildingComponentIfc)";
if (m_buildingComponentSettings && !m_buildingComponentSettings->isChangedCallbackRegistered(this))
for (int i=0; i<20;++i)
ERROR_LOG(my_logger) << LOGFUNCTION << " isChangedCallbackRegistered BldgCmpnt failure!!!";
}
private:
void removeSymbolAppearanceCallback()
{
if (m_symbolAppearanceSettings)
m_symbolAppearanceSettings->removeChangedCallback(this);
m_symbolAppearanceSettings = nullptr;
}
void removeBuildingComponentCallback()
{
if (m_buildingComponentSettings)
m_buildingComponentSettings->removeChangedCallback(this);
m_buildingComponentSettings = nullptr;
}
protected:
virtual bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings & ) const
{
return true;
}
virtual bool buildingComponentSettingsChangesAreRelevant(const FilterManagement::BuildingComponentSettings::BldCmpSettings& ) const
{
return false;
}
void onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part part) override
{
Q_UNUSED(part);
QElapsedTimer elapsedTimer;
if (my_logger.isInfoEnabled())
elapsedTimer.start();
const bool relevant = symbolAppearanceSettingsChangesAreRelevant(m_symbolAppearanceSettings->settings());
m_currentSymbolSettings = m_symbolAppearanceSettings->settings();
if (!relevant)
return;
auto cb = [this](RefPointer<MAP_T> &mapObj)
{
handleSymbolAppearanceSettings(mapObj);
if (!mapObj->updateView())
WARNING_LOG(my_logger) << LOGFUNCTION << " updateView failed,"
<< " mapObj = " << mapObj->debugInfo();
};
m_smBase->iterateObjects<MAP_T>(cb);
m_smBase->symbolAppearanceSettingsChangedPostOperation();
if (my_logger.isInfoEnabled())
{
std::string className;
if (m_smBase)
{
auto &tempRef = *m_smBase;
className = typeid(tempRef).name();
}
INFO_LOG(my_logger) << className << " with PostOperation took " << elapsedTimer.elapsed() << " [ms]"
<< ", mapObjectCount " << m_smBase->mapObjectCount();
}
}
void onBuildingComponentSettingsChanged() override
{
const bool relevant = buildingComponentSettingsChangesAreRelevant(m_buildingComponentSettings->bldCmpSettings());
m_currentBuildingComponentSettings = m_buildingComponentSettings->bldCmpSettings();
if (!relevant)
return;
auto cb = [this](RefPointer<MAP_T> &mapObj)
{
handleBuildingComponentSettings(mapObj);
if (!mapObj->updateView())
WARNING_LOG(my_logger) << LOGFUNCTION << " updateView failed,"
<< " mapObj = " << mapObj->debugInfo();
};
m_smBase->iterateObjects<MAP_T>(cb);
}
virtual void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) = 0;
virtual void handleBuildingComponentSettings(RefPointer<MAP_T> &)
{
}
protected:
std::shared_ptr<FilterManagement::SymbolAppearanceSettings> m_symbolAppearanceSettings;
FilterManagement::SymbolAppearanceSettings::Settings m_currentSymbolSettings;
std::shared_ptr<FilterManagement::BuildingComponentSettings> m_buildingComponentSettings;
FilterManagement::BuildingComponentSettings::BldCmpSettings m_currentBuildingComponentSettings;
private:
PluginProvider *m_pluginProvider{nullptr};
Sim2SituationMapBase *m_smBase{nullptr};
NGL::INGLLogger &my_logger;
};
}
@@ -0,0 +1,355 @@
#include "sound_area_to_map.h"
#include <Map/object_factory.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <InfrastructureManagement/ism_translation.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonArray>
#include <sstream>
using namespace SituationMap;
inline PositionCont form2PosCont2D(const std::vector<Core::GeoPosition2D> &form)
{
PositionCont ret;
ret.reserve(form.size());
for (const auto &pos : form)
ret.push_back({pos.lon(), pos.lat(), 0.0});
return ret;
}
bool SoundAreaToMap::init(PluginProvider *pluginProvider, bool resourceMode)
{
if (!pluginProvider ||
!pluginProvider->ismDtc() ||
!pluginProvider->ismDataIfc())
return false;
m_resourceMode = resourceMode;
m_pluginProvider = pluginProvider;
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_resourceMode=" << m_resourceMode
<< " exerciseId=" << m_pluginProvider->exerciseId();
m_ismDtc = m_pluginProvider->ismDtc();
m_ismDataIfc = m_pluginProvider->ismDataIfc();
m_ismGuiIfc = m_pluginProvider->ismGuiIfc();
InfrastructureManagement::MountingPoint::init();
return true;
}
bool SoundAreaToMap::run()
{
this->stop();
if (!m_ismDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << "Could not run. Dtc not set.";
return false;
}
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::effectAreaChanged,
this, &SoundAreaToMap::onEffectAreaChanged, Qt::UniqueConnection);
if (m_pluginProvider->exerciseId() != 0 || m_resourceMode)
{
m_ismDtc->effectAreas([this](const InfrastructureManagement::EffectArea& data)
{
onEffectAreaChanged(data, DataModification::eAdded);
});
}
return true;
}
void SoundAreaToMap::stop()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << "Stopping";
if (m_ismDtc)
m_ismDtc->disconnect(this);
m_bldgsInExcersise.clear();
m_mountingPoints.clear();
}
bool SoundAreaToMap::mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds)
{
return true;
if (!m_ismGuiIfc)
return false;
const QVector<int32_t> &simIds = uniqueMapIds2SimIds(uniqueMapIds);
if (simIds.isEmpty())
return true;
return true;
}
bool SoundAreaToMap::unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const
{
if (!m_ismDtc)
return false;
int32_t simIdOut = -1;
if (!this->uniqueMapId2SimId(uniqueMapId, simIdOut))
return false;
umodOut = UnifiedMapObjectData();
RefPointer<MAP_T> mapObj = this->getMapObjectOfUniqueMapId(uniqueMapId);
if (mapObj.valid())
umodOut.m_image = mapObj->previewImage();
const auto cb = [simIdOut, &umodOut](const InfrastructureManagement::EffectArea &data) -> bool
{
if (data.id() == simIdOut)
{
umodOut.m_description1 = QString::fromStdString(data.name());
umodOut.m_description2 = tr("Sound Area") + QString(QStringLiteral(" (%1)")).arg(data.id());
return true;
}
return false;
};
std::function<bool(const InfrastructureManagement::EffectArea &data)> cb1 = cb;
return m_ismDtc->effectAreas(cb1);
}
bool SoundAreaToMap::onEffectAreaChanged(const InfrastructureManagement::EffectArea &data, DataModification modType)
{
DEBUG_LOG(m_logger) << " onEffectAreaChanged"
<< " id=" << data.id()
<< " name='" << data.name() << "'"
<< " areaEgcuId=" << data.areaEgcuId()
<< " ata.geometry().size()=" << data.geometry().size()
<< " exerciseId=" << m_pluginProvider->exerciseId();
return handleChanged(data, modType);
}
bool SoundAreaToMap::isElapsed(const Sim2SituationMap::DDS_T &data) const
{
DEBUG_LOG(m_logger) << " isElapsed?";
if (BaseClass::isElapsed(data))
return true;
if (data.geometry().size() < 3)
return true;
return false;
}
int32_t SoundAreaToMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
SituationMap::PositionCont soundGeometryToPositions(const QJsonDocument &jdoc)
{
QJsonObject jObj = jdoc.object();
if (jObj.isEmpty())
return {};
const QJsonArray &jArray = jObj[QLatin1String("soundGeometry")].toArray();
if (jArray.isEmpty())
return {};
SituationMap::PositionCont posCont;
posCont.reserve(jArray.size());
for (const auto &val : qAsConst(jArray))
{
const QJsonObject &objTemp = val.toObject();
posCont.append(Point3D::fromQPointF({objTemp[QLatin1String("lon")].toDouble(),
objTemp[QLatin1String("lat")].toDouble()}
));
}
return posCont;
}
InfrastructureManagement::MountingPoint SoundAreaToMap::mountingPointWithAssociatedId(int associatedId)
{
if (!m_ismDataIfc)
return InfrastructureManagement::MountingPoint();
InfrastructureManagement::MountingPoint mp;
const auto cb = [&mp, associatedId](const InfrastructureManagement::MountingPoint &data) -> bool
{
if (data.associatedAssetId() == associatedId)
{
mp = data;
return true;
}
return false;
};
std::function<bool(const InfrastructureManagement::MountingPoint &data)> cb1 = cb;
m_ismDataIfc->mountingPoints(cb1);
return mp;
}
bool SoundAreaToMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData, RefPointer<Sim2SituationMap::MAP_T> mapObj)
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " id " << ddsData.id()
<< ", name = " << ddsData.name();
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
mapObj->setPickable(true);
QColor col(Qt::red);
mapObj->setLineStyle(LineStyle(col, 1, LinePattern::DashDotDot));
mapObj->setFillStyle(FillStyle(col, FillPattern::BackwardDiagonal));
const SituationMap::PositionCont &posCont = form2PosCont2D(ddsData.geometry());
mapObj->setPositions(posCont);
const InfrastructureManagement::MountingPoint &associatedMountingPoint = mountingPointWithAssociatedId(ddsData.areaEgcuId());
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " id " << ddsData.id()
<< ", name = " << ddsData.name()
<< " MP: buildingId" << associatedMountingPoint.buildingId()
<< " MP: geoPosition" << associatedMountingPoint.geoPosition();
if (associatedMountingPoint.id() > 0)
{
mapObj->setMarkerData(MarkerData(associatedMountingPoint.toImage(), QSize(25,25)));
const Core::GeoPosition &geoPos = associatedMountingPoint.geoPosition();
mapObj->setMarkerOrigin(Point3D(geoPos.lon(), geoPos.lat(), geoPos.z()));
} else {
mapObj->setMarkerData(MarkerData());
mapObj->setMarkerOrigin(Point3D());
}
return true;
}
bool SoundAreaToMap::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data,
DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << "SoundAreaToMap::onMainStructureElementChanged data.id=" << data.id();
DEBUG_LOG(m_logger) << LOGFUNCTION << " vorher " << m_bldgsInExcersise.values();
m_bldgsInExcersise.remove(data.id());
if (modType == DataModification::eAdded || modType == DataModification::eModified)
{
QJsonParseError parseError;
QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(data.properties()), &parseError);
if (parseError.error != QJsonParseError::NoError)
{
INFO_LOG(m_logger) << "Could not parse JSON props of building with ID "
<< data.id()
<< ". Reason: "
<< parseError.errorString()
<< "; JSON: "
<< doc.toJson(QJsonDocument::Compact);
return true;
}
const int32_t actualExerciseId = m_pluginProvider->exerciseId();
const QJsonArray &arr = doc.object().value(QLatin1String("available_in_exercise")).toArray();
for (const QJsonValue &value : qAsConst(arr))
{
if (!value.isDouble())
continue;
const int tmp = value.toInt();
DEBUG_LOG(m_logger) << "actualExerciseId=" << actualExerciseId
<< " available_in_exercise=" << tmp;
if (tmp == actualExerciseId)
{
DEBUG_LOG(m_logger) << "m_bldgsInExcersise.append:" << data.id();
m_bldgsInExcersise.insert(data.id());
}
}
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " nachher " << m_bldgsInExcersise.values();
return true;
}
@@ -0,0 +1,67 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <Plugins/InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <Plugins/InfrastructureManagement/Shared/ism_mounting_point.h>
#include <MapObjects/sound_area.h>
namespace SituationMap
{
class SoundAreaToMap final : public Sim2SituationMap<InfrastructureManagement::EffectArea, SituationMap::SoundArea>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<InfrastructureManagement::EffectArea, SituationMap::SoundArea>;
public:
SoundAreaToMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
{}
bool init(PluginProvider *pluginProvider, bool resourceMode);
bool run() override;
void stop() override;
bool mapObjectsClicked(const QVector<UniqueMapId> &uniqueMapIds) override;
bool unifiedMapObjectData(UniqueMapId uniqueMapId, UnifiedMapObjectData &umodOut) const override;
protected Q_SLOTS:
bool onEffectAreaChanged(const InfrastructureManagement::EffectArea &data, DataModification modType);
bool onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data,
DataModification modType = DataModification::eAdded);
protected:
bool isElapsed(const Sim2SituationMap::DDS_T &data) const override;
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const DDS_T &ddsData, RefPointer<MAP_T> mapObj) override;
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override
{
Q_UNUSED(mapObj);
}
private:
InfrastructureManagement::MountingPoint mountingPointWithAssociatedId(int associatedId);
private:
PluginProvider *m_pluginProvider{nullptr};
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> m_ismDataIfc;
std::shared_ptr<InfrastructureManagement::ForeignResourceManagementGuiInterface> m_ismGuiIfc;
bool m_resourceMode{false};
QSet<int> m_bldgsInExcersise;
QMap<int, InfrastructureManagement::MountingPoint> m_mountingPoints;
};
}
@@ -0,0 +1,108 @@
#include "special_areas_to_map.h"
#include <LtsUtilsCore/dds_bitarray.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
namespace SituationMap
{
bool SpecialAreaToSituationMap::init(PluginProvider *pluginProvider)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!pluginProvider ||
!pluginProvider->ismDtc())
return false;
m_pluginProvider = pluginProvider;
DEBUG_LOG(m_logger) << LOGFUNCTION << " exerciseId=" << m_pluginProvider->exerciseId();
m_ismDtc = m_pluginProvider->ismDtc();
FilterClass::init(m_pluginProvider);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool SpecialAreaToSituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_ismDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
this->stop();
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::specialAreaChanged,
this, &SpecialAreaToSituationMap::handleChanged, Qt::UniqueConnection);
m_ismDtc->specialAreas([this](const InfrastructureManagement::SpecialArea & data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void SpecialAreaToSituationMap::stop()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << "Stopping";
if (m_ismDtc)
m_ismDtc->disconnect(this);
}
bool SpecialAreaToSituationMap::isElapsed(const Sim2SituationMap::DDS_T &data) const
{
Q_UNUSED(data)
return false;
}
int32_t SpecialAreaToSituationMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool SpecialAreaToSituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setPickable(false);
mapObj->setLineStyle(LineStyle(Qt::green, 3, LinePattern::DashDot));
mapObj->setFillStyle(FillStyle(FillPattern::Null));
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
const std::vector<Core::GeoPosition2D> &polygon = ddsData.polygon();
PositionCont posCont;
posCont.reserve(polygon.size());
for (const auto &p : qAsConst(polygon))
posCont.push_back(Point3D(p.lon(), p.lat(), .0));
mapObj->setPositions(posCont);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,59 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <MapObjects/polygon.h>
#include <QObject>
namespace SituationMap
{
class SpecialAreaToSituationMap final : public Sim2SituationMap<InfrastructureManagement::SpecialArea, SituationMap::Polygon>
, protected DdsFilterHandling<SituationMap::Polygon>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<InfrastructureManagement::SpecialArea, SituationMap::Polygon>;
using FilterClass = DdsFilterHandling<SituationMap::Polygon>;
public:
SpecialAreaToSituationMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
, m_pluginProvider(nullptr)
{}
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override;
protected:
bool isElapsed(const Sim2SituationMap::DDS_T &data) const override;
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale) ||
(m_currentSymbolSettings.symbolSettings.showSpecialAreas != newSas.symbolSettings.showSpecialAreas);
}
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override
{
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
mapObj->setVisibility(m_currentSymbolSettings.symbolSettings.showSpecialAreas);
}
private:
PluginProvider *m_pluginProvider;
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
};
}
@@ -0,0 +1,76 @@
#include "technical_area_to_map.h"
#include <LtsUtilsCore/dds_bitarray.h>
namespace SituationMap
{
bool TechnicalArea2SituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_aesDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::technicalAreaChanged,
this, &TechnicalArea2SituationMap::handleChanged, Qt::UniqueConnection);
m_aesDtc->technicalAreas([this](const AreaEffectSimulation::TechnicalArea & data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::run();
}
bool TechnicalArea2SituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
const int32_t simId = ddsData.id();
mapObj->setPickable(false);
mapObj->setLineStyle(LineStyle(Qt::black, 2, LinePattern::DashDotDot));
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
AreaEffectSimulation::AesItemView itemView;
if (m_aesDtc->aesItemViewFromEntityId(simId, AreaEffectSimulation::AesType::AtTechnicalArea, itemView))
this->updateGeometry(itemView, mapObj);
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " no AesItemView (AtTechnicalArea) found"
<< ", simId = " << simId
<< ", provide fallBackGeometry";
mapObj->setPositions({{0.0, 0.0, .0},
{0.0, 0.1, .0},
{0.1, 0.1, .0},
{0.1, 0.0, .0}});
}
updateVisibility(ddsData, mapObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,42 @@
#pragma once
#include "aes_to_situation_map_tmpl.h"
#include <Plugins/AreaEffectSimulation/aes_data_plugin_interface.h>
#include <MapObjects/polygon.h>
#include <QObject>
namespace SituationMap
{
class TechnicalArea2SituationMap;
template <>
struct Aes2SituationMapTraits<TechnicalArea2SituationMap>
{
using DDS_TYPE = AreaEffectSimulation::TechnicalArea;
using MAP_TYPE = SituationMap::Polygon;
static const AreaEffectSimulation::AesType_def::type aesType = AreaEffectSimulation::AesType_def::AtTechnicalArea;
};
class TechnicalArea2SituationMap final : public Aes2SituationMap<TechnicalArea2SituationMap>
{
Q_OBJECT
public:
using BaseClass = SituationMap::Aes2SituationMap<TechnicalArea2SituationMap>;
using BaseClass::BaseClass;
bool run() override;
bool iterateAesData(const std::function<bool(const AreaEffectSimulation::TechnicalArea &data)> &cb) const
{
return m_aesDtc->technicalAreas(cb);
}
protected:
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
};
}
@@ -0,0 +1,121 @@
#include "training_area_to_map.h"
#include <LtsUtilsCore/dds_bitarray.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
namespace SituationMap
{
bool TrainingAreaToSituationMap::init(PluginProvider *pluginProvider)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!pluginProvider ||
!pluginProvider->asmDtc())
return false;
m_pluginProvider = pluginProvider;
DEBUG_LOG(m_logger) << LOGFUNCTION << " exerciseId=" << m_pluginProvider->exerciseId();
if (m_pluginProvider->exmDtc())
{
const int curExerciseId = m_pluginProvider->exerciseId();
m_trainingAreaIdOfCurrentExercise = m_pluginProvider->exmDtc()->exercise(curExerciseId).trainingAreaId();
}
m_asmDtc = m_pluginProvider->asmDtc();
FilterClass::init(m_pluginProvider);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool TrainingAreaToSituationMap::run()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_asmDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
this->stop();
connect(m_asmDtc.get(), &AssetManagement::Interface::Dtc::trainingAreaChanged,
this, &TrainingAreaToSituationMap::handleChanged, Qt::UniqueConnection);
m_asmDtc->trainingAreas([this](const AssetManagement::TrainingArea & data)
{
handleChanged(data, DataModification::eAdded);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void TrainingAreaToSituationMap::stop()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << "Stopping";
if (m_asmDtc)
m_asmDtc->disconnect(this);
}
bool TrainingAreaToSituationMap::isElapsed(const Sim2SituationMap::DDS_T &data) const
{
if (m_trainingAreaIdOfCurrentExercise <= 0)
return false;
return (m_trainingAreaIdOfCurrentExercise != data.id());
}
int32_t TrainingAreaToSituationMap::getSimId(const Sim2SituationMap::DDS_T &ddsData) const
{
return ddsData.id();
}
bool TrainingAreaToSituationMap::updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
mapObj->setPickable(false);
mapObj->setLineStyle(LineStyle(Qt::black, 2, LinePattern::Dot));
mapObj->setFillStyle(FillStyle(FillPattern::Null));
mapObj->setIdentifier(QString::fromStdString(ddsData.name()));
const Core::GeoPosition2D &bottomLeft = ddsData.bottomLeft();
const LtsCoordTrans::UtmCoordinate referencePointUTM = LtsCoordTrans::UtmCoordinate::fromGeographic(bottomLeft.lon(), bottomLeft.lat());
const QPointF size(ddsData.width(), ddsData.height());
PositionCont posCont;
posCont.reserve(4);
posCont.push_back(Point3D(bottomLeft.lon(), bottomLeft.lat(), .0));
posCont.push_back(Point3D::fromQPointF(referencePointUTM.geographic(0 , size.y())));
posCont.push_back(Point3D::fromQPointF(referencePointUTM.geographic(size.x(), size.y())));
posCont.push_back(Point3D::fromQPointF(referencePointUTM.geographic(size.x(), 0)));
mapObj->setPositions(posCont);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
}
@@ -0,0 +1,60 @@
#pragma once
#include "sim_to_situation_map_tmpl.h"
#include <Plugins/AssetManagement/asm_data_plugin_interface.h>
#include <MapObjects/polygon.h>
#include <QObject>
namespace SituationMap
{
class TrainingAreaToSituationMap final : public Sim2SituationMap<AssetManagement::TrainingArea, SituationMap::Polygon>
, protected DdsFilterHandling<SituationMap::Polygon>
{
Q_OBJECT
using BaseClass = SituationMap::Sim2SituationMap<AssetManagement::TrainingArea, SituationMap::Polygon>;
using FilterClass = DdsFilterHandling<SituationMap::Polygon>;
public:
TrainingAreaToSituationMap(ObjectFactory &objFac,
const QString &layername,
int drawOrder,
const char *loggerName)
: BaseClass(objFac, layername, drawOrder, loggerName)
, FilterClass(loggerName, this)
, m_pluginProvider(nullptr)
{}
bool init(PluginProvider *pluginProvider);
bool run() override;
void stop() override;
protected:
bool isElapsed(const Sim2SituationMap::DDS_T &data) const override;
int32_t getSimId(const Sim2SituationMap::DDS_T &ddsData) const override;
bool updateElementImpl(const Sim2SituationMap::DDS_T &ddsData,
RefPointer<MAP_T> mapObj) override;
bool symbolAppearanceSettingsChangesAreRelevant(const FilterManagement::SymbolAppearanceSettings::Settings &newSas) const override
{
return (m_currentSymbolSettings.symbolSettings.symbolScale != newSas.symbolSettings.symbolScale) ||
(m_currentSymbolSettings.symbolSettings.showTrainingAreaBorder != newSas.symbolSettings.showTrainingAreaBorder);
}
void handleSymbolAppearanceSettings(RefPointer<MAP_T> &mapObj) override
{
mapObj->setScale(m_currentSymbolSettings.symbolSettings.symbolScale);
mapObj->setVisibility(m_currentSymbolSettings.symbolSettings.showTrainingAreaBorder);
}
private:
PluginProvider *m_pluginProvider;
int m_trainingAreaIdOfCurrentExercise = -1;
std::shared_ptr<AssetManagement::Interface::Dtc> m_asmDtc;
};
}
@@ -0,0 +1,53 @@
#pragma once
#include <Map/situation_map_types.h>
#include <QString>
namespace SituationMap
{
struct UnifiedMapObjectData
{
int m_equipmentNumber{-1};
int m_partyId{-1};
struct participantData
{
int m_participantId{-1};
int m_typeId{-1};
int m_vulnerabilityState{-1};
QString m_vulnerabilityString;
QString m_typeName;
};
participantData m_participantData;
struct buildingData
{
int buildingId{-1};
};
buildingData m_buildingData;
QString m_description1;
QString m_description2;
SymbolDataToRender m_symDataToRender;
QImage m_image;
};
}
@@ -0,0 +1,249 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Mike Wille, SLSE, 2016-06-10
#
IF(BUILD_RPM)
IF(UNIX)
OPTION(BUILD_USE_MAP_CACHE "Use MapCache (GUEZ_ONLY) via _pname" ON)
ELSE()
OPTION(BUILD_USE_MAP_CACHE "Use MapCache (GUEZ_ONLY) via _pname" OFF)
ENDIF()
ELSE()
# !BUILD_RPM entspricht LTS_DEBUG
OPTION(BUILD_USE_MAP_CACHE "Use MapCache (GUEZ_ONLY) via LTS_debug)" ON)
ENDIF()
MESSAGE(STATUS "Enable MapCache: ${BUILD_USE_MAP_CACHE})")
IF (BUILD_USE_MAP_CACHE)
add_definitions(-DUSE_MAP_CACHE)
ENDIF()
SET(sitmap_dds_SRCS
situation_map_init.cpp
situation_map_init.h
situation_map_init_p.h
MapObjectSelection/map_object_model.cpp
MapObjectSelection/map_object_model.h
MapObjectSelection/map_object_selection_widget.cpp
MapObjectSelection/map_object_selection_widget.h
MapObjectSelection/map_object_custom_view.cpp
MapObjectSelection/map_object_custom_view.h
AdapterDds/adapter_dds.cpp
AdapterDds/adapter_dds.h
AdapterDds/map_object_type.h
AdapterDds/aes_to_situation_map_tmpl.h
AdapterDds/air_support_impact_to_map.cpp
AdapterDds/air_support_impact_to_map.h
AdapterDds/emergency_call_to_map.cpp
AdapterDds/emergency_call_to_map.h
AdapterDds/bccontamination_to_map.cpp
AdapterDds/bccontamination_to_map.h
AdapterDds/borderline_to_map.cpp
AdapterDds/borderline_to_map.h
AdapterDds/buildings_to_map.cpp
AdapterDds/buildings_to_map.h
AdapterDds/buildinghitlineinfo_to_map.cpp
AdapterDds/buildinghitlineinfo_to_map.h
AdapterDds/building_contamination.cpp
AdapterDds/building_contamination.h
AdapterDds/building_ownership.cpp
AdapterDds/building_ownership.h
AdapterDds/booby_traps_to_map.cpp
AdapterDds/booby_traps_to_map.h
AdapterDds/special_areas_to_map.cpp
AdapterDds/special_areas_to_map.h
AdapterDds/danger_area_to_map.cpp
AdapterDds/danger_area_to_map.h
AdapterDds/dus_single_mine_to_map.cpp
AdapterDds/dus_single_mine_to_map.h
AdapterDds/explosion_area_to_map.cpp
AdapterDds/explosion_area_to_map.h
AdapterDds/explosion_cluster_to_map.cpp
AdapterDds/explosion_cluster_to_map.h
AdapterDds/effect_cluster_to_map.cpp
AdapterDds/effect_cluster_to_map.h
AdapterDds/explosion_single_to_map.cpp
AdapterDds/explosion_single_to_map.h
# AdapterDds/explosion_single_central_to_map.cpp
# AdapterDds/explosion_single_central_to_map.h
AdapterDds/functional_area_to_map.cpp
AdapterDds/functional_area_to_map.h
AdapterDds/gas_pipe_to_map.cpp
AdapterDds/gas_pipe_to_map.h
AdapterDds/guez_ied_to_map.cpp
AdapterDds/guez_ied_to_map.h
AdapterDds/guez_nasat_9liner.cpp
AdapterDds/guez_nasat_9liner.h
AdapterDds/hitlineinfo_to_map.cpp
AdapterDds/hitlineinfo_to_map.h
AdapterDds/mine_area_null_to_map.cpp
AdapterDds/mine_area_null_to_map.h
AdapterDds/mine_area_to_map.cpp
AdapterDds/mine_area_to_map.h
AdapterDds/mine_corridor_to_map.cpp
AdapterDds/mine_corridor_to_map.h
AdapterDds/mounting_point_to_map.cpp
AdapterDds/mounting_point_to_map.h
AdapterDds/sound_area_to_map.cpp
AdapterDds/sound_area_to_map.h
AdapterDds/mse_point_to_map.cpp
AdapterDds/mse_point_to_map.h
AdapterDds/mse_bridge_to_map.cpp
AdapterDds/mse_bridge_to_map.h
AdapterDds/ncontamination_to_map.cpp
AdapterDds/ncontamination_to_map.h
AdapterDds/off_route_to_map.cpp
AdapterDds/off_route_to_map.h
AdapterDds/participant_to_map.cpp
AdapterDds/participant_to_map.h
AdapterDds/pdm_handler.cpp
AdapterDds/pdm_handler.h
AdapterDds/shootback_area_to_map.cpp
AdapterDds/shootback_area_to_map.h
AdapterDds/recon_area_to_map.cpp
AdapterDds/recon_area_to_map.h
AdapterDds/technical_area_to_map.cpp
AdapterDds/technical_area_to_map.h
AdapterDds/training_area_to_map.cpp
AdapterDds/training_area_to_map.h
AdapterDds/plugin_provider.h
AdapterDds/sim_to_situation_map_tmpl.h
AdapterDds/unified_map_object_data.h
AdapterDds/charge_effect_to_map.cpp
AdapterDds/charge_effect_to_map.h
)
NGL_WRAP_UI(sitmap_dds_SRCS
MapObjectSelection/map_object_selection_dialog.ui
MapObjectSelection/map_object_custom_view.ui
)
NGL_ADD_LIBRARY2(WS SitmapDds SHARED ${sitmap_dds_SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(SitmapDds
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(SitmapDds
PUBLIC
Qt5::Core
situationMap
LtsUtilsGuiDds # RequestHelper
PRIVATE
svcMapDummy
situationMapFunctionDialog # remove me here plz
LtsCoordTrans
LtsDataView
LtsSessionData
situationMapObjects
LtsUtilsSettings
#needed through AdapterDds sources
AlmDataPluginInterface
AsmDataPluginInterface
BldDataPluginInterface
ExmDataPluginInterface
FltDataPluginInterface
IsmDataPluginInterface
GnaDataPluginInterface
CmoDataPluginInterface
SmoCheckButtonHandler
TgtDataPluginInterface
IsmShared
svcAesClient
svcCesClient
svcGimClient
svcPpmClient
svcSrpClient
)
#
# SitmapGuiPlugin
#
SET(sitmap_edit_gui_SRCS
sitmap_gui_plugin.cpp
sitmap_gui_plugin.h
sitmap_register_app_handler.cpp
sitmap_register_app_handler.h
sitmap_widget_control.cpp
sitmap_widget_control.h
sitmap_layer_control.cpp
sitmap_layer_control.h
ConfigureUrl/sitmap_configure_url_model.cpp
ConfigureUrl/sitmap_configure_url_model.h
ConfigureUrl/sitmap_configure_url_widget.cpp
ConfigureUrl/sitmap_configure_url_widget.h
ConfigureUrl/sitmap_configure_urls.cpp
ConfigureUrl/sitmap_configure_urls.h
layers_model.cpp
layers_model.h
terrain_profile_handler.cpp
terrain_profile_handler.h
viewshed_dialog.h
plugin_provider_lts_session.h
plugin_provider_lts_session.cpp
TopicEditor/topic_editor.h
TopicEditor/topic_editor.cpp
)
NGL_WRAP_UI(sitmap_edit_gui_SRCS
ConfigureUrl/sitmap_configure_url_widget.ui
ConfigureUrl/sitmap_configure_single_url.ui
ConfigureUrl/sitmap_configure_urls.ui
sitmap_widget_control.ui
sitmap_layer_control.ui
TopicEditor/topic_editor.ui
)
NGL_ADD_LIBRARY2(WS SitmapGuiPlugin MODULE ${sitmap_edit_gui_SRCS})
NGL_TARGET_LINK_LIBRARIES(SitmapGuiPlugin
SitmapDds
svcMapDummy
situationMapCommon
situationMap
situationMapObjects
NGLLogger
LtsPrinting
LtsSession
SituationMapGuiPluginInterface
Qt5::Widgets
LtsWidgets
LtsCoordTrans
LtsAppDescriptor
LtsAppManager
LtsUtilsSettings
TopicEditorBase
FltFilterChange
LtsNotification
# only to create a menu entry - should be done by the bdv gui plugin...
BdvViewerGuiPluginInterface
AesDataPluginInterface
AlmDataPluginInterface
AsmDataPluginInterface
BldDataPluginInterface
CesDataPluginInterface
FltDataPluginInterface
GimDataPluginInterface
GnaDataPluginInterface
IsmDataPluginInterface
OpmDataPluginInterface
PpmDataPluginInterface
TgtDataPluginInterface
CmoDataPluginInterface
)
@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Configure_Single_Url</class>
<widget class="QWidget" name="Configure_Single_Url">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1099</width>
<height>134</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Layer Control</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Url:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="toolTip">
<string>Min. zoom in limit</string>
</property>
<property name="text">
<string>Min Scale:</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="le_minScale">
<property name="text">
<string notr="true">-1</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLabel" name="label_4">
<property name="toolTip">
<string>Max. zoom in limit</string>
</property>
<property name="text">
<string>Max Scale:</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QLineEdit" name="le_maxScale">
<property name="text">
<string notr="true">-1</string>
</property>
</widget>
</item>
<item row="3" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2" colspan="3">
<widget class="QLineEdit" name="le_name"/>
</item>
<item row="0" column="2" colspan="3">
<widget class="QLineEdit" name="le_url"/>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,100 @@
#include "sitmap_configure_url_model.h"
#include <AssetManagement/asm_data_plugin_interface.h>
namespace SituationMap
{
ConfigureMapUrlModel::ConfigureMapUrlModel(QObject *parent)
: BaseClass( {tr("Name"), tr("Url"), tr("Map Type"), tr("Min Scale"), tr("Max Scale")}, parent)
{
}
ConfigureMapUrlModel::~ConfigureMapUrlModel()
{
}
void ConfigureMapUrlModel::addData(const DATA_T &entry)
{
for (const auto &r : qAsConst(m_vecData))
{
if (r == entry)
return;
}
beginInsertRows(QModelIndex(), m_vecData.size(), m_vecData.size());
m_vecData += entry;
endInsertRows();
}
QModelIndex ConfigureMapUrlModel::moveRow(const QModelIndex &sourceIndex, int destinationRow)
{
if (destinationRow >= m_vecData.size() || destinationRow < 0)
return sourceIndex;
std::swap(m_vecData[destinationRow], m_vecData[sourceIndex.row()]);
QModelIndex idx = index(destinationRow, 0);
emit dataChanged(index(sourceIndex.row(), 0), index(sourceIndex.row(), columnCount(QModelIndex()) - 1));
emit dataChanged(idx, index(destinationRow, columnCount(QModelIndex()) - 1));
return idx;
}
QVector<ConfigureMapUrlModel::DATA_T> ConfigureMapUrlModel::allData() const
{
return m_vecData;
}
QVariant ConfigureMapUrlModel::data(const QModelIndex &index, int role) const
{
if ((role != Qt::DisplayRole &&
role != Qt::EditRole &&
role != Qt::UserRole) || !index.isValid() || index.row() >= m_vecData.size())
return QVariant();
const DATA_T &md = m_vecData.at(index.row());
switch (index.column())
{
case Columns::Url:
return QString::fromStdString(md.url());
case Columns::Name:
return QString::fromStdString(md.name());
case Columns::MapType:
{
switch (md.mapTypeId().underlying())
{
case AssetManagement::MapType_def::Aerial:
return tr("Aerial");
case AssetManagement::MapType_def::Topographic:
return tr("Topographic");
case AssetManagement::MapType_def::Unknown:
case AssetManagement::MapType_def::Feature:
case AssetManagement::MapType_def::Elevation:
case AssetManagement::MapType_def::SceneObjects:
break;
}
return tr("Unknown");
}
case Columns::MinScale:
return md.minScale();
case Columns::MaxScale:
return md.maxScale();
}
return QVariant();
}
}
@@ -0,0 +1,50 @@
#pragma once
#include <LtsWidgets/lts_abstract_table_model.h>
namespace AssetManagement
{
class MapDescription;
}
namespace SituationMap
{
class ConfigureMapUrlModel : public LtsWidgets::LtsAbstractTableModel<AssetManagement::MapDescription>
{
Q_OBJECT
using BaseClass = LtsWidgets::LtsAbstractTableModel<AssetManagement::MapDescription>;
using DATA_T = AssetManagement::MapDescription;
public:
enum Columns
{
Name,
Url,
MapType,
MinScale,
MaxScale,
};
explicit ConfigureMapUrlModel(QObject *parent = nullptr);
~ConfigureMapUrlModel();
QVariant data(const QModelIndex &index, int role) const override;
void addData(const DATA_T &entry);
QModelIndex moveRow(const QModelIndex &sourceIndex, int destinationRow);
QVector<ConfigureMapUrlModel::DATA_T> allData() const;
};
}
@@ -0,0 +1,226 @@
#include "sitmap_configure_url_widget.h"
#include "ui_sitmap_configure_url_widget.h"
#include "ui_sitmap_configure_single_url.h"
#include "sitmap_configure_url_model.h"
#include <AssetManagement/asm_data_plugin_interface.h>
constexpr int MIN_SCALE = -1;
constexpr int MAX_SCALE = 9999999;
namespace SituationMap
{
ConfigureSingleMapUrl::ConfigureSingleMapUrl(QWidget *parent)
: BaseClass(parent)
, m_ui(new Ui::Configure_Single_Url)
, m_buttonBox(new LtsWidgets::LtsDialogButtonBox(this))
{
setAttribute(Qt::WA_DeleteOnClose);
m_ui->setupUi(this);
layout()->addWidget(m_buttonBox);
connect(m_buttonBox->getButton(LtsWidgets::DialogButton::Ok), &QPushButton::clicked, this, &ConfigureSingleMapUrl::onOk);
connect(m_buttonBox->getButton(LtsWidgets::DialogButton::Close), &QPushButton::clicked, this, &ConfigureSingleMapUrl::onClose);
m_ui->le_url->setPlaceholderText(QStringLiteral("http://HOSTNAME/arcgis/rest/services/XXXX/MapServer"));
m_ui->le_name->setPlaceholderText(tr("Displayname"));
m_ui->le_minScale->setPlaceholderText(tr("limit zoom out, '-1' for invalid, '0' for infinite"));
m_ui->le_minScale->setValidator(new QIntValidator(MIN_SCALE, MAX_SCALE, this));
m_ui->le_minScale->setToolTip(m_ui->le_minScale->placeholderText());
m_ui->le_maxScale->setPlaceholderText(tr("limit zoom in, '-1' for invalid"));
m_ui->le_maxScale->setValidator(new QIntValidator(MIN_SCALE, MAX_SCALE, this));
m_ui->le_maxScale->setToolTip(m_ui->le_maxScale->placeholderText());
}
ConfigureSingleMapUrl::~ConfigureSingleMapUrl()
{
}
void ConfigureSingleMapUrl::setPlaceholderTextForFile()
{
m_ui->le_url->setPlaceholderText(QStringLiteral("file:filename.ext"));
}
void ConfigureSingleMapUrl::setData(const ConfigureSingleMapUrl::DATA_T &data)
{
m_ui->le_url->setText(QString::fromStdString(data.url()));
m_ui->le_name->setText(QString::fromStdString(data.name()));
m_ui->le_minScale->setText(QString::number(data.minScale()));
m_ui->le_maxScale->setText(QString::number(data.maxScale()));
}
ConfigureSingleMapUrl::DATA_T ConfigureSingleMapUrl::data()
{
ConfigureSingleMapUrl::DATA_T data;
data.url(m_ui->le_url->text().trimmed().toStdString());
data.name(m_ui->le_name->text().trimmed().toStdString());
data.minScale(m_ui->le_minScale->text().toDouble());
data.maxScale(m_ui->le_maxScale->text().toDouble());
return data;
}
void ConfigureSingleMapUrl::onOk()
{
emit signalApply();
this->close();
}
void ConfigureSingleMapUrl::onClose()
{
this->close();
}
ConfigureMapUrlsWidget::ConfigureMapUrlsWidget(QWidget *parent)
: QWidget(parent)
, m_ui(new Ui::Configure_Urls_Widget)
, m_logger(getLogger("ConfigureMapUrlsWidget"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_ui->setupUi(this);
connect(m_ui->pbUp, &QPushButton::clicked, this, &ConfigureMapUrlsWidget::onUpClicked);
connect(m_ui->pbDown, &QPushButton::clicked, this, &ConfigureMapUrlsWidget::onDownClicked);
connect(m_ui->pbAdd, &QPushButton::clicked, this, &ConfigureMapUrlsWidget::onAddClicked);
connect(m_ui->pbModify, &QPushButton::clicked, this, &ConfigureMapUrlsWidget::onModfiyClicked);
connect(m_ui->pbRemove, &QPushButton::clicked, this, &ConfigureMapUrlsWidget::onRemoveClicked);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
ConfigureMapUrlsWidget::~ConfigureMapUrlsWidget()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_ui;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void ConfigureMapUrlsWidget::setModel(ConfigureMapUrlModel *model)
{
if (!m_ui->tvLayer || !model)
return;
m_ui->tvLayer->setModel(model);
m_ui->tvLayer->hideColumn(ConfigureMapUrlModel::Columns::MapType);
m_configureMapUrlModel = model;
}
ConfigureMapUrlModel *ConfigureMapUrlsWidget::model() const
{
return m_configureMapUrlModel;
}
QTableView *ConfigureMapUrlsWidget::tableView()
{
return m_ui->tvLayer;
}
void ConfigureMapUrlsWidget::onUpClicked()
{
if (!m_configureMapUrlModel)
return;
int currentRow = m_ui->tvLayer->currentIndex().row();
if (currentRow - 1 < 0)
return;
QModelIndex idx = m_configureMapUrlModel->moveRow(m_ui->tvLayer->currentIndex(), currentRow - 1);
m_ui->tvLayer->setCurrentIndex(idx);
emit hasChanges();
}
void ConfigureMapUrlsWidget::onDownClicked()
{
if (!m_configureMapUrlModel)
return;
int currentRow = m_ui->tvLayer->currentIndex().row();
QModelIndex idx = m_configureMapUrlModel->moveRow(m_ui->tvLayer->currentIndex(), currentRow + 1);
m_ui->tvLayer->setCurrentIndex(idx);
emit hasChanges();
}
void ConfigureMapUrlsWidget::onAddClicked()
{
delete m_currentConfigureSingleUrl;
m_currentConfigureSingleUrl = new ConfigureSingleMapUrl(this);
m_currentConfigureSingleUrl->setWindowTitle(tr("Add Url"));
if (m_placeholderTextFile)
m_currentConfigureSingleUrl->setPlaceholderTextForFile();
connect(m_currentConfigureSingleUrl.data(), &ConfigureSingleMapUrl::signalApply,
this, &ConfigureMapUrlsWidget::addSingleUrl);
m_currentConfigureSingleUrl->show();
}
void ConfigureMapUrlsWidget::addSingleUrl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_configureMapUrlModel)
return;
const ConfigureSingleMapUrl::DATA_T &data = m_currentConfigureSingleUrl->data();
m_configureMapUrlModel->addData(data);
emit hasChanges();
}
void ConfigureMapUrlsWidget::onModfiyClicked()
{
delete m_currentConfigureSingleUrl;
m_currentConfigureSingleUrl = new ConfigureSingleMapUrl(this);
m_currentConfigureSingleUrl->setWindowTitle(tr("Modify Url"));
if (m_placeholderTextFile)
m_currentConfigureSingleUrl->setPlaceholderTextForFile();
connect(m_currentConfigureSingleUrl.data(), &ConfigureSingleMapUrl::signalApply,
this, &ConfigureMapUrlsWidget::modifySingleUrl);
int currentRow = m_ui->tvLayer->currentIndex().row();
m_currentConfigureSingleUrl->setData(m_configureMapUrlModel->getRowData(currentRow));
m_currentConfigureSingleUrl->show();
}
void ConfigureMapUrlsWidget::modifySingleUrl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_configureMapUrlModel)
return;
int currentRow = m_ui->tvLayer->currentIndex().row();
const ConfigureSingleMapUrl::DATA_T &data = m_currentConfigureSingleUrl->data();
m_configureMapUrlModel->setRowData(currentRow, data);
emit hasChanges();
}
void ConfigureMapUrlsWidget::onRemoveClicked()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
int currentRow = m_ui->tvLayer->currentIndex().row();
m_configureMapUrlModel->removeRow(currentRow);
emit hasChanges();
}
}
@@ -0,0 +1,111 @@
#pragma once
#include <Common/situation_map_logging.h>
#include <LtsWidgets/lts_dialog.h>
#include <QTableView>
class QToolButton;
namespace Ui
{
class Configure_Urls_Widget;
class Configure_Single_Url;
}
namespace AssetManagement
{
class MapDescription;
}
namespace SituationMap
{
class ConfigureMapUrlModel;
class ConfigureSingleMapUrl final : public LtsWidgets::LtsFramelessDialog
{
Q_OBJECT
public:
using BaseClass = LtsWidgets::LtsFramelessDialog;
using DATA_T = AssetManagement::MapDescription;
explicit ConfigureSingleMapUrl(QWidget *parent = nullptr);
~ConfigureSingleMapUrl();
void setPlaceholderTextForFile();
void setData(const DATA_T &data);
DATA_T data();
Q_SIGNALS:
void signalApply();
protected Q_SLOTS:
void onOk();
void onClose();
private:
Ui::Configure_Single_Url *m_ui;
LtsWidgets::LtsDialogButtonBox *m_buttonBox;
};
class ConfigureMapUrlsWidget : public QWidget
{
Q_OBJECT
public:
explicit ConfigureMapUrlsWidget(QWidget *parent = nullptr);
~ConfigureMapUrlsWidget();
void setPlaceholderTextForFile() { m_placeholderTextFile = true; }
void setModel(ConfigureMapUrlModel *model);
ConfigureMapUrlModel *model() const;
QTableView *tableView();
Q_SIGNALS:
void hasChanges();
protected Q_SLOTS:
void onUpClicked();
void onDownClicked();
void onAddClicked();
void onModfiyClicked();
void onRemoveClicked();
void addSingleUrl();
void modifySingleUrl();
private:
QPointer<ConfigureSingleMapUrl> m_currentConfigureSingleUrl;
Ui::Configure_Urls_Widget *m_ui;
ConfigureMapUrlModel *m_configureMapUrlModel = nullptr;
bool m_placeholderTextFile = false;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Configure_Urls_Widget</class>
<widget class="QWidget" name="Configure_Urls_Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>811</width>
<height>441</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Layer Control</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTableView" name="tvLayer">
<property name="minimumSize">
<size>
<width>500</width>
<height>200</height>
</size>
</property>
<property name="editTriggers">
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::CurrentChanged|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<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>
<widget class="QPushButton" name="pbUp">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Z/src/nglwidgets/nglresources.qrc">
<normaloff>:/icons/png/camera_arrow_up.png</normaloff>:/icons/png/camera_arrow_up.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbDown">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Z/src/nglwidgets/nglresources.qrc">
<normaloff>:/icons/png/camera_arrow_down.png</normaloff>:/icons/png/camera_arrow_down.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbAdd">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Z/src/nglwidgets/nglresources.qrc">
<normaloff>:/icons/png/add.png</normaloff>:/icons/png/add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbModify">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Z/src/nglwidgets/nglresources.qrc">
<normaloff>:/icons/png/edith_graphic_eass.png</normaloff>:/icons/png/edith_graphic_eass.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbRemove">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Z/src/nglwidgets/nglresources.qrc">
<normaloff>:/icons/png/remove.png</normaloff>:/icons/png/remove.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="../../../../../Z/src/nglwidgets/nglresources.qrc"/>
</resources>
<connections/>
</ui>
@@ -0,0 +1,377 @@
#include "sitmap_configure_urls.h"
#include "ui_sitmap_configure_urls.h"
#include "sitmap_configure_url_model.h"
#include "sitmap_configure_url_widget.h"
#include <Map/map_initializer.h>
#include "AdapterDds/plugin_provider.h"
#include <LtsUtils/LtsUtilsCore/dds_vector.h>
namespace SituationMap
{
ConfigureMapUrls::ConfigureMapUrls(QWidget *parent)
: LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_pluginProvider(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_ui(new Ui::Configure_Urls)
, m_logger(getLogger("ConfigureMapUrls"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_ui->setupUi(this);
ConfigureMapUrlsWidget *w;
m_ui->tabWidget->removeTab(0);
w = new ConfigureMapUrlsWidget();
w->setModel(new ConfigureMapUrlModel(this));
m_ui->tabWidget->addTab(w, tr("Map"));
connect(w, &ConfigureMapUrlsWidget::hasChanges, this, &ConfigureMapUrls::slotChangesMade);
w = new ConfigureMapUrlsWidget();
w->setModel(new ConfigureMapUrlModel(this));
m_ui->tabWidget->addTab(w, tr("Scene"));
connect(w, &ConfigureMapUrlsWidget::hasChanges, this, &ConfigureMapUrls::slotChangesMade);
w = new ConfigureMapUrlsWidget();
w->setModel(new ConfigureMapUrlModel(this));
w->setPlaceholderTextForFile();
m_ui->tabWidget->addTab(w, tr("Elevation"));
connect(w, &ConfigureMapUrlsWidget::hasChanges, this, &ConfigureMapUrls::slotChangesMade);
w = new ConfigureMapUrlsWidget();
w->setModel(new ConfigureMapUrlModel(this));
w->setPlaceholderTextForFile();
m_ui->tabWidget->addTab(w, tr("SceneObject"));
connect(w, &ConfigureMapUrlsWidget::hasChanges, this, &ConfigureMapUrls::slotChangesMade);
setOnlineHelpFilename(QStringLiteral("Configuration_of_Modells_SLPKs"));
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
ConfigureMapUrls::~ConfigureMapUrls()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_ui;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool ConfigureMapUrls::init(PluginProvider *pluginProvider)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_pluginProvider = pluginProvider;
if (!m_pluginProvider)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no pluginProvider";
return false;
}
bool bRet = true;
m_asmDtc = m_pluginProvider->asmDtc();
if (!m_asmDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Can not retrieve AssetManagement::DTC";
bRet = false;
}
m_asmFtc = m_pluginProvider->asmFtc();
if (!m_asmFtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Can not retrieve AssetManagement::FTC";
bRet = false;
}
connect(m_ui->cbTrainingArea, &LtsWidgets::LtsComboBox::currentTextChanged,
this, &ConfigureMapUrls::onSelectedTrainingAreaChanged);
m_ui->tabWidget->setCurrentIndex(0);
fillTrainingAreaCbx();
syncTaToGui();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return bRet;
}
void ConfigureMapUrls::fillTrainingAreaCbx()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_asmDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return;
}
{
QSignalBlocker blocker(m_ui->cbTrainingArea);
int curIdxTa = m_ui->cbTrainingArea->currentIndex();
m_ui->cbTrainingArea->clear();
auto cb = [this](const AssetManagement::TrainingArea & ta)
{
m_ui->cbTrainingArea->addItem(QString::fromStdString(ta.name()), QVariant(ta.id()));
};
m_asmDtc->trainingAreas(cb);
m_ui->cbTrainingArea->model()->sort(0);
if (curIdxTa >= 0)
m_ui->cbTrainingArea->setCurrentIndex(curIdxTa);
}
if (m_ui->cbTrainingArea->model()->rowCount() > 0)
{
const int newTrainingAreaId = m_ui->cbTrainingArea->currentData().toInt();
if (!retrieveTaOfService(newTrainingAreaId))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " retrieveTrainingAreaOfService failed";
return;
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void ConfigureMapUrls::onSelectedTrainingAreaChanged(const QString & )
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
const int newTrainingAreaId = m_ui->cbTrainingArea->currentData().toInt();
if (m_trainingArea.id() == newTrainingAreaId)
return;
if (hasUnsavedChanges())
{
switch (LtsWidgets::LtsMessageDialog::askApplyDiscardCancel(this))
{
case LtsWidgets::Button::Apply:
apply();
if (!retrieveTaOfService(newTrainingAreaId))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " retrieveTrainingAreaOfService failed";
return;
}
break;
case LtsWidgets::Button::Cancel:
INFO_LOG(m_logger) << LOGFUNCTION << " set back to m_trainingArea.id() = " << m_trainingArea.id();
m_ui->cbTrainingArea->setCurrentIndex(m_ui->cbTrainingArea->findData(QVariant(m_trainingArea.id()), Qt::UserRole));
break;
case LtsWidgets::Button::Discard:
if (!retrieveTaOfService(newTrainingAreaId))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " retrieveTrainingAreaOfService failed";
return;
}
break;
default:
ERROR_LOG(m_logger) << LOGFUNCTION << " got unexpected!!!";
break;
}
}
else
{
if (!retrieveTaOfService(newTrainingAreaId))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " retrieveTrainingAreaOfService failed";
return;
}
}
syncTaToGui();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool ConfigureMapUrls::retrieveTaOfService(int trainingAreaId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, trainingAreaId=" << trainingAreaId;
if (!m_asmDtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no dtc";
return false;
}
m_trainingArea = AssetManagement::TrainingArea();
syncTaToGui();
AssetManagement::TrainingArea ta = m_asmDtc->trainingArea(trainingAreaId);
if (ta.id() != trainingAreaId)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " switch to m_trainingArea failed (taId=" << trainingAreaId << ")";
return false;
}
m_trainingArea = ta;
INFO_LOG(m_logger) << LOGFUNCTION << " switch to m_trainingArea " << m_trainingArea.id()
<< ", ta" << ta;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
static inline std::vector<AssetManagement::MapDescription> vecToVec(const QVector<AssetManagement::MapDescription> &vec)
{
return LtsUtils::convert<std::vector<AssetManagement::MapDescription>>(vec);
}
static inline QVector<AssetManagement::MapDescription> vecToVec(const std::vector<AssetManagement::MapDescription> &vec)
{
return LtsUtils::convert<QVector<AssetManagement::MapDescription>>(vec);
}
void basicConfig(ConfigureMapUrlsWidget *tv, bool showTypeMinMax = true)
{
if (!tv)
return;
tv->tableView()->resizeColumnsToContents();
tv->tableView()->setColumnWidth(1, 100);
tv->tableView()->setColumnWidth(2, 100);
tv->tableView()->setColumnWidth(3, 100);
tv->tableView()->setColumnWidth(4, 100);
if (!showTypeMinMax)
{
tv->tableView()->hideColumn(ConfigureMapUrlModel::Columns::MapType);
tv->tableView()->hideColumn(ConfigureMapUrlModel::Columns::MinScale);
tv->tableView()->hideColumn(ConfigureMapUrlModel::Columns::MaxScale);
}
}
void ConfigureMapUrls::syncTaToGui()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
ConfigureMapUrlsWidget *w;
w = static_cast<ConfigureMapUrlsWidget *>(m_ui->tabWidget->widget(0));
if (w && w->model())
{
w->model()->setData(vecToVec(m_trainingArea.map2D()));
TRACE_LOG(m_logger) << LOGFUNCTION << " model->rowCount()" << w->model()->rowCount();
}
basicConfig(w);
if (w && w->model())
connect(w->model(), &ConfigureMapUrlModel::dataChanged, this, []()
{
qCritical() << " Changed!!!";
});
w = static_cast<ConfigureMapUrlsWidget *>(m_ui->tabWidget->widget(1));
if (w && w->model())
{
w->model()->setData(vecToVec(m_trainingArea.scene3D()));
TRACE_LOG(m_logger) << LOGFUNCTION << " model->rowCount()" << w->model()->rowCount();
}
basicConfig(w);
w = static_cast<ConfigureMapUrlsWidget *>(m_ui->tabWidget->widget(2));
if (w && w->model())
w->model()->setData(vecToVec(m_trainingArea.elevation()));
basicConfig(w, false);
w = static_cast<ConfigureMapUrlsWidget *>(m_ui->tabWidget->widget(3));
if (w && w->model())
w->model()->setData(vecToVec(m_trainingArea.sceneObjects()));
basicConfig(w, false);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void ConfigureMapUrls::syncGuiToTa()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
ConfigureMapUrlsWidget *w;
w = static_cast<ConfigureMapUrlsWidget *>(m_ui->tabWidget->widget(0));
if (w && w->model())
m_trainingArea.map2D(vecToVec(w->model()->allData()));
w = static_cast<ConfigureMapUrlsWidget *>(m_ui->tabWidget->widget(1));
if (w && w->model())
m_trainingArea.scene3D(vecToVec(w->model()->allData()));
w = static_cast<ConfigureMapUrlsWidget *>(m_ui->tabWidget->widget(2));
if (w && w->model())
m_trainingArea.elevation(vecToVec(w->model()->allData()));
w = static_cast<ConfigureMapUrlsWidget *>(m_ui->tabWidget->widget(3));
if (w && w->model())
m_trainingArea.sceneObjects(vecToVec(w->model()->allData()));
for (auto &item : m_trainingArea.map2D())
item.mapDescriptionTypeId(AssetManagement::MapDescriptionType_def::Map2D);
for (auto &item : m_trainingArea.scene3D())
item.mapDescriptionTypeId(AssetManagement::MapDescriptionType_def::Scene3D);
for (auto &item : m_trainingArea.elevation())
item.mapDescriptionTypeId(AssetManagement::MapDescriptionType_def::Elevation);
for (auto &item : m_trainingArea.sceneObjects())
item.mapDescriptionTypeId(AssetManagement::MapDescriptionType_def::SceneObj);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void ConfigureMapUrls::retranslate()
{
translate(m_ui, tr("Configure Map Urls"));
}
bool ConfigureMapUrls::apply()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_asmFtc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " Can not retrieve AssetManagement::FTC";
return false;
}
this->syncGuiToTa();
bool success = m_requestHelper->startSingleRequest([this]()
{
return m_asmFtc->trainingAreaModifyRequest(m_trainingArea, this);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END, scucess=" << success;
return success;
}
void ConfigureMapUrls::onTrainingAreaModifyReply(const Core::FunctionReplyObject &reply)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (reply.error())
{
ERROR_LOG(m_logger) << LOGFUNCTION << "Got onTrainingAreaModifyReply error: " << reply();
return;
}
INFO_LOG(m_logger) << LOGFUNCTION << " Got onTrainingAreaModifyReply with id " << reply.id();
m_requestHelper->requestReply(reply);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
}
@@ -0,0 +1,79 @@
#pragma once
#include <Common/situation_map_logging.h>
#include <AssetManagement/asm_data_plugin_interface.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
namespace Ui
{
class Configure_Urls;
}
namespace SituationMap
{
class PluginProvider;
class ConfigureMapUrls : public LtsWidgets::LtsDialog
, protected AssetManagement::Interface::Ftc::TrainingAreaModifyReplyHandler
{
Q_OBJECT
public:
explicit ConfigureMapUrls(QWidget *parent = nullptr);
~ConfigureMapUrls();
bool init(PluginProvider *pluginProvider);
protected:
void fillTrainingAreaCbx();
bool retrieveTaOfService(int trainingAreaId);
void syncTaToGui();
void syncGuiToTa();
void onTrainingAreaModifyReply(const Core::FunctionReplyObject &reply) override;
protected Q_SLOTS:
void onSelectedTrainingAreaChanged(const QString &dummy = QString());
private:
void retranslate() override;
bool apply() override final;
protected:
private:
SituationMap::PluginProvider *m_pluginProvider;
std::shared_ptr<AssetManagement::Interface::Dtc> m_asmDtc;
std::shared_ptr<AssetManagement::Interface::Ftc> m_asmFtc;
LtsUtils::RequestHelper *m_requestHelper;
AssetManagement::TrainingArea m_trainingArea;
Ui::Configure_Urls *m_ui;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Configure_Urls</class>
<widget class="QWidget" name="Configure_Urls">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>667</width>
<height>368</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="lblTrainingArea">
<property name="text">
<string>Training Area:</string>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsComboBox" name="cbTrainingArea">
<property name="const" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="map">
<attribute name="title">
<string>Map</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,67 @@
#include "map_object_custom_view.h"
#include "ui_map_object_custom_view.h"
#include "map_object_model.h"
#include <LtsSession/lts_session_data.h>
#include <QDataWidgetMapper>
namespace SituationMap
{
MapObjectCustomView::MapObjectCustomView(QWidget *parent)
: BaseClass(parent)
, m_ui(new Ui::MapObjectCustomView)
, m_mapper(new QDataWidgetMapper(this))
{
m_ui->setupUi(this);
if (LtsSessionData::LtsSessionData::getInstance()->isTablet())
{
constexpr auto scaleFactor = 1.4;
resize(size() * scaleFactor);
m_ui->lbIcon->setMinimumSize(m_ui->lbIcon->minimumSize() * scaleFactor);
m_ui->lbIcon->setMaximumSize(m_ui->lbIcon->maximumSize() * scaleFactor);
}
}
MapObjectCustomView::~MapObjectCustomView()
{
delete m_ui;
}
bool MapObjectCustomView::init(const QModelIndex &idx)
{
if (!idx.isValid())
return false;
if (idx.model() != m_mapper->model())
{
m_mapper->setModel(const_cast<QAbstractItemModel *>(idx.model()));
m_mapper->addMapping(m_ui->lbDescription, MapObjectModel::Columns::SINGLE_DESCRIPTION, "text");
m_mapper->addMapping(m_ui->lbIcon, MapObjectModel::Columns::PICTURE, "pixmap");
}
setRow(idx.row());
return true;
}
void MapObjectCustomView::setRow(int row)
{
m_mapper->setCurrentIndex(row);
QAbstractItemModel *modelPtr = m_mapper->model();
if (modelPtr)
m_uniqueMapId = modelPtr->data(modelPtr->index(row, MapObjectModel::Columns::UNIQUE_MAP_ID)).toInt();
else
m_uniqueMapId = -1;
}
}
@@ -0,0 +1,40 @@
#pragma once
#include <Map/situation_map_types.h>
#include <Viewer/LtsDataView/abstract_display_widget.h>
class QDataWidgetMapper;
namespace Ui
{
class MapObjectCustomView;
}
namespace SituationMap
{
class MapObjectCustomView final : public LtsDataView::AbstractDisplayWidget
{
Q_OBJECT
using BaseClass = AbstractDisplayWidget;
public:
explicit MapObjectCustomView(QWidget *parent = nullptr);
~MapObjectCustomView();
bool init(const QModelIndex &idx) override;
private:
void setRow(int row);
private:
Ui::MapObjectCustomView *m_ui;
QDataWidgetMapper *m_mapper = nullptr;
UniqueMapId m_uniqueMapId = INVALID_MAP_ID;
};
}
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MapObjectCustomView</class>
<widget class="QWidget" name="MapObjectCustomView">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>63</width>
<height>88</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>4</number>
</property>
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="lbIcon">
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbDescription">
<property name="text">
<string notr="true">&lt;Desc&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,539 @@
#include "map_object_model.h"
#include <Symbology/sidc_codec.h>
#include <SituationMap/Map/party_id_to_color_functor.h>
#include <LtsWidgets/lts_column_filter_proxy_model.h>
#include <QString>
#include <QBuffer>
#include <QPainter>
#include <QGuiApplication>
namespace SituationMap
{
static constexpr int ICON_RESOLUTION_CUSTOM = 128;
static constexpr int ICON_RESOLUTION_TABLE = 32;
void updateMapObjectDataToEnsureGoodQuality(MapObjectData *mod)
{
mod->m_symDataToRender.sizeL = ICON_RESOLUTION_CUSTOM;
}
MapObjectData::~MapObjectData()
{
delete m_symbolResultWatcher;
}
void MapObjectData::onResultReady()
{
if (!m_symbolResultWatcher)
return;
QSharedPointer<AdvancedSymbology::SymbolResult> symResult = m_symbolResultWatcher->symbolResult();
if (!symResult)
return;
setImage(symResult->symbolImage().image());
emit dataChanged(m_uniqueMapId);
m_symbolResultWatcher->deleteLater();
m_symbolResultWatcher = nullptr;
}
void MapObjectData::requestImage(AdvancedSymbology::SymbolDictionary *dict)
{
if (!m_symbolResultWatcher)
{
m_symbolResultWatcher = new AdvancedSymbology::SymbolResultWatcher;
connect(m_symbolResultWatcher, &AdvancedSymbology::SymbolResultWatcher::resultReady,
this, &MapObjectData::onResultReady);
}
updateMapObjectDataToEnsureGoodQuality(this);
m_symbolResultWatcher->setSymbolResult(dict->findImage(m_symDataToRender));
}
void MapObjectData::setImage(const QImage &img)
{
if (img.isNull())
{
m_pixIcon = QPixmap();
m_pixPicture = QPixmap();
return;
}
const auto dpr = qApp->devicePixelRatio();
m_pixIcon = QPixmap::fromImage(img.scaled(QSize(ICON_RESOLUTION_TABLE, ICON_RESOLUTION_TABLE) * dpr,
Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
m_pixPicture = QPixmap::fromImage(img.scaled(QSize(ICON_RESOLUTION_CUSTOM, ICON_RESOLUTION_CUSTOM) * dpr,
Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
m_pixIcon.setDevicePixelRatio(dpr);
m_pixPicture.setDevicePixelRatio(dpr);
}
MapObjectModel::MapObjectModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<QSharedPointer<MapObjectData>>(
{
tr("UniqueMapid"),
tr("Sidc"),
tr("Description"),
tr("Icon"),
tr("ParticipantId"),
tr("Equipment number"),
tr("Party"),
tr("TypeId"),
tr("Type"),
tr("VulnerabilityStateId"),
tr("VulnerabilityState"),
tr("Designator"),
tr("Tact. Identifier"),
tr("Picture")
},
parent)
, m_logger(getLogger("MapObjectModel"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
MapObjectModel::~MapObjectModel()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void MapObjectModel::initModel(Map *map)
{
m_map = map;
m_dictionary = &(m_map->symbolDictionary());
connect(m_dictionary, &AdvancedSymbology::SymbolDictionary::changedDelayed, this, &MapObjectModel::requestCivilIcons, Qt::UniqueConnection);
connect(this, &MapObjectModel::rowsInserted, this, &MapObjectModel::updateUsedPartyIds);
connect(this, &MapObjectModel::rowsRemoved, this, &MapObjectModel::updateUsedPartyIds);
connect(this, &MapObjectModel::modelReset, this, &MapObjectModel::updateUsedPartyIds);
}
bool MapObjectModel::contains(UniqueMapId uniqueMapId) const
{
return findRowForUniqueMapId(uniqueMapId) >= 0;
}
void MapObjectModel::remove(UniqueMapId uniqueMapId)
{
const int row = findRowForUniqueMapId(uniqueMapId);
removeRow(row);
}
void MapObjectModel::setMapObjectData(const QVector<QSharedPointer<MapObjectData>> &mapObjectDataVec)
{
setData(mapObjectDataVec);
for (const QSharedPointer<MapObjectData> &mapObjectData : mapObjectDataVec)
if (mapObjectData)
{
updateMapObjectDataToEnsureGoodQuality(mapObjectData.data());
connect(mapObjectData.data(), &MapObjectData::dataChanged,
this, &MapObjectModel::onDataChanged, Qt::UniqueConnection);
}
}
bool MapObjectModel::addMapObjectData(const QSharedPointer<MapObjectData> &mapObjectData)
{
const int row = findRowForUniqueMapId(mapObjectData->m_uniqueMapId);
if (row >= 0)
return false;
updateMapObjectDataToEnsureGoodQuality(mapObjectData.data());
if (!insertRow(mapObjectData))
return false;
connect(mapObjectData.data(), &MapObjectData::dataChanged,
this, &MapObjectModel::onDataChanged, Qt::UniqueConnection);
return true;
}
QImage markImage(const QPixmap &orgPixmap)
{
QImage newImage(orgPixmap.size(), QImage::Format_ARGB32);
static QColor fillColor = QColor(211, 211, 211, 120);
newImage.fill(fillColor);
QPainter painter(&newImage);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.drawPixmap(orgPixmap.rect(), orgPixmap);
painter.end();
return newImage;
}
bool MapObjectModel::updateMapObjectData(const QSharedPointer<MapObjectData> &mapObjectData)
{
const int row = findRowForUniqueMapId(mapObjectData->m_uniqueMapId);
if (row < 0)
return false;
if (!mapObjectData->m_symDataToRender.sidc.isEmpty())
{
updateMapObjectDataToEnsureGoodQuality(mapObjectData.data());
const auto &oldRowData = m_vecData.at(row);
if (oldRowData->m_symDataToRender == mapObjectData->m_symDataToRender)
return true;
mapObjectData->setImage(markImage(oldRowData->m_pixPicture));
requestIcon(mapObjectData);
}
connect(mapObjectData.data(), &MapObjectData::dataChanged,
this, &MapObjectModel::onDataChanged, Qt::UniqueConnection);
return setRowData(row, mapObjectData);
}
void MapObjectModel::requestCivilIcons()
{
for (const DATA_T &moData : qAsConst(m_vecData))
{
if (!moData)
continue;
const QString &sidc = moData->m_symDataToRender.sidc;
if (!AdvancedSymbology::SidcCodec::isEncoded(sidc))
continue;
if (!AdvancedSymbology::SidcCodec::isCivil(sidc))
continue;
requestIcon(moData);
}
}
QVariant MapObjectModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole &&
orientation == Qt::Horizontal)
{
if (section == PARTY)
{
LtsWidgets::ComboboxFilterContent cfc;
cfc.data.reserve(m_usedPartyIds.size());
LtsWidgets::ComboboxFilterData cfd;
for (const int partyId : m_usedPartyIds)
{
const PartyIdToColorFunctor::PartyData party = m_map->partyIdToColorFunctor().partyId(partyId);
cfd.data = partyId;
cfd.text = party.m_name;
cfd.icon = party.m_icon;
cfc.data.push_back(cfd);
}
cfc.sortItems = false;
return cfc.toVariant();
}
if (section == TYPE_NAME)
{
LtsWidgets::ComboboxFilterContent cfc;
cfc.data.reserve(m_usedTypeName.size());
LtsWidgets::ComboboxFilterData cfd;
for (const QString &typeName : m_usedTypeName)
{
cfd.data = typeName;
cfd.text = typeName;
cfc.data.push_back(cfd);
}
cfc.sortItems = true;
return cfc.toVariant();
}
if (section == VULNERABILITY_STATE)
{
LtsWidgets::ComboboxFilterContent cfc;
cfc.data.reserve(m_usedVulnerabilities.size());
LtsWidgets::ComboboxFilterData cfd;
for (auto it = m_usedVulnerabilities.begin(); it != m_usedVulnerabilities.end(); ++it)
{
cfd.data = it.key();
cfd.text = it.value();
cfc.data.push_back(cfd);
}
cfc.sortItems = false;
return cfc.toVariant();
}
}
return BaseClass::headerData(section, orientation, role);
}
QVariant MapObjectModel::data(const QModelIndex &index, int role) const
{
if (!indexIsValid(index))
return QVariant();
if (role != Qt::DisplayRole &&
role != Qt::ToolTipRole &&
role != Qt::EditRole &&
role != Qt::DecorationRole &&
role != LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
return QVariant();
const DATA_T &moData = m_vecData.at(index.row());
if (role == Qt::ToolTipRole)
{
switch (index.column())
{
case PARTY:
return QStringLiteral("%1 (%2)").arg(moData->m_partyName).arg(moData->m_partyId);
case UNIQUE_MAP_ID:
case ICON:
{
QString tooltip(QStringLiteral("<html>"));
const QPixmap &img = moData->m_pixPicture;
if (!img.isNull())
{
QByteArray data;
QBuffer buffer(&data);
img.save(&buffer, "PNG", 100);
tooltip.append(QStringLiteral("<center><img src='data:image/png;base64,%1'></center>").arg(QString::fromLatin1(data.toBase64())));
}
if (!moData->m_typeName.isEmpty())
{
const QString &hdr = this->headerData(MapObjectModel::Columns::TYPE_NAME , Qt::Horizontal, Qt::DisplayRole).toString();
tooltip.append(QStringLiteral("<p>%1: %2</p>").arg(hdr, moData->m_typeName));
}
if (!moData->m_typeName.isEmpty())
{
const QString &hdr = this->headerData(MapObjectModel::Columns::VULNERABILITY_STATE, Qt::Horizontal, Qt::DisplayRole).toString();
tooltip.append(QStringLiteral("<p>%1: %2</p>").arg(hdr, moData->m_vulnerabilityString));
}
if (!moData->m_description1.isEmpty())
{
const QString &hdr = this->headerData(MapObjectModel::Columns::DESCRIPTION1, Qt::Horizontal, Qt::DisplayRole).toString();
tooltip.append(QStringLiteral("<p>%1: %2</p>").arg(hdr, moData->m_description1));
}
if (!moData->m_description2.isEmpty())
{
const QString &hdr = this->headerData(MapObjectModel::Columns::DESCRIPTION2, Qt::Horizontal, Qt::DisplayRole).toString();
tooltip.append(QStringLiteral("<p>%1: %2</p>").arg(hdr, moData->m_description2));
}
#ifdef LTS_DEBUG
tooltip.append(QStringLiteral("<p>participantId: %2</p>").arg(moData->m_participantId));
tooltip.append(QStringLiteral("<p>row: %2</p>").arg(index.row()));
tooltip.append(QStringLiteral("<p>uniqueMapId: %2</p>").arg(moData->m_uniqueMapId));
tooltip.append(QStringLiteral("<p>typeId: %2</p>").arg(moData->m_typeId));
tooltip.append(QStringLiteral("<p>vulnerabilityStateId: %2</p>").arg(moData->m_vulnerabilityState));
#endif
tooltip.append(QStringLiteral("</html>"));
return tooltip;
}
}
}
if ((role == Qt::DisplayRole) || (role == Qt::EditRole) || (role != LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole))
{
const UniqueMapId &uniqueMapId = moData->m_uniqueMapId;
switch (index.column())
{
case UNIQUE_MAP_ID:
return uniqueMapId;
case SIDC:
return moData->m_symDataToRender.sidc;
case SINGLE_DESCRIPTION:
if (moData->m_equipmentNumber >= 0)
return moData->m_equipmentNumber;
else
return moData->m_description1;
case ICON:
{
if (moData->m_pixIcon.isNull())
{
moData->setImage(AdvancedSymbology::SymbolDictionary::temporaryImage());
requestIcon(moData);
}
if (moData->m_pixIcon.isNull())
return QVariant();
return moData->m_pixIcon;
}
case PARTICIPANT_ID:
return moData->m_participantId <= 0 ? QVariant() : QVariant(moData->m_participantId);
case EQUIPMENT_NUMBER:
return moData->m_equipmentNumber <= 0 ? QVariant() : QVariant(moData->m_equipmentNumber);
case PARTY:
return moData->m_partyName;
case TYPE_ID:
return moData->m_typeId <= 0 ? QVariant() : QVariant(moData->m_typeId);
case TYPE_NAME:
return moData->m_typeName;
case VULNERABILITY_STATE:
return moData->m_vulnerabilityString;
case VULNERABILITY_STATE_ID:
return moData->m_vulnerabilityState <= 0 ? QVariant() : QVariant(moData->m_vulnerabilityState);
case DESCRIPTION1:
return moData->m_description1;
case DESCRIPTION2:
return moData->m_description2;
case PICTURE:
{
if (moData->m_pixPicture.isNull())
{
moData->setImage(AdvancedSymbology::SymbolDictionary::temporaryImage());
requestIcon(moData);
}
if (moData->m_pixPicture.isNull())
return QVariant();
return moData->m_pixPicture;
}
}
}
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
{
if (index.column() == PARTY)
return moData->m_partyId;
if (index.column() == TYPE_NAME)
return moData->m_typeName;
if (index.column() == VULNERABILITY_STATE)
return moData->m_vulnerabilityState;
}
return QVariant();
}
UniqueMapId MapObjectModel::uniqueMapIdOfIndex(const QModelIndex &index) const
{
if (!indexIsValid(index))
return SituationMap::INVALID_MAP_ID;
const DATA_T &moData = m_vecData.at(index.row());
if (!moData)
return SituationMap::INVALID_MAP_ID;
return moData->m_uniqueMapId;
}
void MapObjectModel::onDataChanged(UniqueMapId uniqueMapId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, uniqueMapId=" << uniqueMapId;
int row = findRowForUniqueMapId(uniqueMapId);
emit dataChanged(index(row, 0), index(row, LtsAbstractTableModel::columnCount(QModelIndex()) - 1));
}
int MapObjectModel::findRowForUniqueMapId(UniqueMapId uniqueMapId) const
{
for (int i = 0; i < m_vecData.size(); ++i)
{
if (m_vecData.at(i)->m_uniqueMapId == uniqueMapId)
return i;
}
return -1;
}
void MapObjectModel::requestIcon(const MapObjectModel::DATA_T &data) const
{
data->requestImage(m_dictionary);
}
void MapObjectModel::updateUsedPartyIds()
{
m_usedPartyIds.clear();
m_usedTypeName.clear();
m_usedVulnerabilities.clear();
for (const QSharedPointer<MapObjectData> &item : qAsConst(m_vecData))
{
if (!item)
continue;
m_usedPartyIds[item->m_partyId] = item->m_partyId;
m_usedTypeName.insert(item->m_typeName);
m_usedVulnerabilities.insert(item->m_vulnerabilityState,
item->m_vulnerabilityState < 0 ? QStringLiteral("-") : item->m_vulnerabilityString);
}
}
void MapObjectProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<MapObjectModel*>(sourceModel);
BaseClass::setSourceModel(sourceModel);
}
bool MapObjectProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if (!m_sourceModel ||
source_left.column() != source_right.column() ||
source_left.row() < 0 || source_left.row() >= m_sourceModel->m_vecData.size() ||
source_right.row() < 0 || source_right.row() >= m_sourceModel->m_vecData.size()
)
return BaseClass::lessThan(source_left, source_right);
const QSharedPointer<MapObjectData> &left = m_sourceModel->m_vecData.at(source_left.row());
const QSharedPointer<MapObjectData>&right = m_sourceModel->m_vecData.at(source_right.row());
switch (source_left.column())
{
case MapObjectModel::Columns::UNIQUE_MAP_ID:
return left->m_uniqueMapId < right->m_uniqueMapId;
case MapObjectModel::Columns::SIDC:
return left->m_symDataToRender.sidc < right->m_symDataToRender.sidc;
case MapObjectModel::Columns::SINGLE_DESCRIPTION:
if (left->m_equipmentNumber && right->m_equipmentNumber)
return left->m_equipmentNumber < right->m_equipmentNumber;
if (left->m_equipmentNumber)
return true;
if (right->m_equipmentNumber)
return true;
return left->m_description1 < left->m_description1;
case MapObjectModel::Columns::PARTICIPANT_ID:
return left->m_participantId < right->m_participantId;
case MapObjectModel::Columns::EQUIPMENT_NUMBER:
return left->m_equipmentNumber < right->m_equipmentNumber;
case MapObjectModel::Columns::PARTY:
return left->m_partyId < right->m_partyId;
case MapObjectModel::Columns::TYPE_ID:
return left->m_typeId < right->m_typeId;
case MapObjectModel::Columns::TYPE_NAME:
return left->m_typeName < right->m_typeName;
case MapObjectModel::Columns::DESCRIPTION1:
return left->m_description1 < right->m_description1;
case MapObjectModel::Columns::DESCRIPTION2:
return left->m_description2 < right->m_description2;
}
return BaseClass::lessThan(source_left, source_right);
}
}
Loaded 100 of 11247 files, more files were not shown because too many files have changed in this diff. Show more