/** * Handler for player data * $Id$ * $HeadURL$ * $Author$ * Created by gr, SLSE, 2017-02-20 */ #include "handler_participant_borderline.h" #include #include #include namespace CentralEffectSimulationBasic { HandlerParticipantBorderline::HandlerParticipantBorderline(const std::shared_ptr &ddsHandler, const std::shared_ptr &participantHandler, QObject *parent) : QObject(parent) , m_ddsHandler(ddsHandler) , m_handlerParticipant(participantHandler) , m_logger(CentralEffectSimulation::getLogger("Plugin.Basic.HandlerParticipantBorderline")) { INFO_LOG(m_logger) << "HandlerParticipantBorderline::HandlerParticipantBorderline"; } // end of ctor() //----------------------------------------------------------------------------- HandlerParticipantBorderline::~HandlerParticipantBorderline() { } // end of dtor() //----------------------------------------------------------------------------- bool HandlerParticipantBorderline::init() { INFO_LOG(m_logger) << "HandlerParticipantBorderline::init"; auto dtcAes = m_ddsHandler->dtcAes(); dtcAes->waitForHistoricalDataBorderline(1000); connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::borderlineChanged, this, &HandlerParticipantBorderline::onBorderlineChanged); connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newIndoorPosition, this, &HandlerParticipantBorderline::onParticipantPositionChanged); connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newOutdoorPosition, this, &HandlerParticipantBorderline::onParticipantPositionChanged); // Get 'static' data for all Borderlines { auto cb = [this](const AreaEffectSimulation::Borderline & fa) { onBorderlineChanged(fa, DataModification::eAdded); }; if (!dtcAes->borderlines(cb)) return false; } INFO_LOG(m_logger) << "HandlerParticipantBorderline::init() finished. "; return true; } // end of init() //----------------------------------------------------------------------------- void HandlerParticipantBorderline::onBorderlineChanged(const AreaEffectSimulation::Borderline &data, DataModification modType) { switch (modType) { case DataModification::eRemoved: DEBUG_LOG(m_logger) << " remove Borderline- data.id()=" << data.id(); m_borderlines.remove(data.id()); break; case DataModification::eAdded: case DataModification::eModified: { const AreaEffectSimulation::AesEffectState &effectState = data.effectStateId(); switch (effectState.underlying()) { case AreaEffectSimulation::AesEffectState_def::EsReceived: case AreaEffectSimulation::AesEffectState_def::EsFired: case AreaEffectSimulation::AesEffectState_def::EsCreated: case AreaEffectSimulation::AesEffectState_def::EsPrepared: case AreaEffectSimulation::AesEffectState_def::EsActivated: { BorderlineUtm borderline(data); DEBUG_LOG(m_logger) << "m_borderlines.insert id=" << data.id(); m_borderlines.insert(data.id(), borderline); break; } case AreaEffectSimulation::AesEffectState_def::EsRemoved: case AreaEffectSimulation::AesEffectState_def::EsExpired: case AreaEffectSimulation::AesEffectState_def::EsPaused: m_borderlines.remove(data.id()); break; case AreaEffectSimulation::AesEffectState_def::EsUnknown: case AreaEffectSimulation::AesEffectState_def::EsError: break; } break; } } } bool HandlerParticipantBorderline::intersect(const QPolygonF &polygonf, const QLineF &linef) const { DEBUG_LOG(m_logger) << "line to check: " << CentralEffectSimulation::debug(linef.p1()) << " - " << CentralEffectSimulation::debug(linef.p2()); QPointF a = polygonf.first(); for (const QPointF &b : polygonf) { const QLineF segment(a, b); DEBUG_LOG(m_logger) << "segment:" << CentralEffectSimulation::debug(a) << " - " << CentralEffectSimulation::debug(b); if (QLineF::BoundedIntersection == linef.intersect(segment, nullptr)) return true; a = b; } return false; } void HandlerParticipantBorderline::onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos) { // Bounding Box von der Linie DEBUG_LOG(m_logger) << "ParicipantStep " << " participantId=" << partPos.participantId() << " participantTypeId=" << partPos.participantTypeId() << " Anzahl Borderlines=" << m_borderlines.size(); for (const BorderlineUtm &borderline : qAsConst(m_borderlines)) { DEBUG_LOG(m_logger) << "borderline id = " << borderline.id << ", Box bottomLeft = " << CentralEffectSimulation::debug(borderline.boundingBox.bottomLeft()) << ", topRight = " << CentralEffectSimulation::debug(borderline.boundingBox.topRight()); const QPolygonF utmStepPoly = m_handlerParticipant->getParticipantStep(partPos.participantId(), borderline.zone); if (utmStepPoly.size() < 2) continue; // Intersection von Polygon und Line: Polygon = Borderline, Line from last Participant pos to actual participant pos const QLineF utmStep(utmStepPoly[0], utmStepPoly[1]); const bool result = intersect(borderline.points, utmStep); DEBUG_LOG(m_logger) << "result intersection = " << result; if (result) { if (borderline.operatorId <= 0) sendParticipantEvent(borderline, partPos, ProjectDataManagement::EventType_def::CrossGlobalBorderline); else sendParticipantEvent(borderline, partPos, ProjectDataManagement::EventType_def::CrossLocalBorderline); } } } // end of onParticipantPositionChanged() //----------------------------------------------------------------------------- // /////////////////////////////////// // P D M (ProjectDataManagement) // /////////////////////////////////// // Search for corresponding aesItemView // Check for all participants wheter he is in the explosion area void HandlerParticipantBorderline::sendParticipantEvent(const BorderlineUtm &borderline, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition, const ProjectDataManagement::EventType eventType) { ParticipantManagement::TypeClass typeClass = m_handlerParticipant->typeClassFromTypeId(participantPosition.participantTypeId()); if (typeClass == ParticipantManagement::TypeClass_def::Unit || typeClass == ParticipantManagement::TypeClass_def::SupportUnit || typeClass == ParticipantManagement::TypeClass_def::SupportEntity || typeClass == ParticipantManagement::TypeClass_def::Unknown) return; int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantPosition.participantId()); if (equipmentNumber <= 0) return; CentralEffectSimulation::ParticipantEvent pe; DEBUG_LOG(m_logger) << "sendParticipantEvent participantId=" << participantPosition.participantId() << " lat= " << participantPosition.pos().lat() << " lon= " << participantPosition.pos().lon() << " equipmentNumber=" << equipmentNumber << " eventType=" << eventType; pe.id(m_ddsHandler->getParticipantEventId()); pe.eventTypeId(eventType); pe.participantId(participantPosition.participantId()); pe.eventTime(participantPosition.sampleTime()); pe.aesItemId(borderline.id); pe.partyId(participantPosition.partyId()); pe.aesName(borderline.name.toStdString()); pe.equipmentNumber(equipmentNumber); pe.position(participantPosition.pos()); m_ddsHandler->dtsCes()->publish(pe); qint64 id = pe.id(); QTimer::singleShot(1 * 60 * 1000, this, [id, this]() { m_ddsHandler->dtsCes()->removeParticipantEventByKey(id); }); } HandlerParticipantBorderline::BorderlineUtm::BorderlineUtm(const AreaEffectSimulation::Borderline &bl) : id(bl.id()) , operatorId(bl.operatorId()) , partyId(bl.partyId().is_set() ? bl.partyId().get() : -1) , name(QString::fromStdString(bl.name())) { points.reserve(bl.segments().size()); for (const Core::GeoPosition2D &pointGeo : bl.segments()) points.push_back(CentralEffectSimulation::geographic2Utm(pointGeo, &zone)); boundingBox = points.boundingRect(); // build Polygon: } } // namespace CentralEffectSimulationBasic