Files
qt5-legatus-legacy/Lts/Services/CentralEffectSimulation/Plugins/MineAreas/handler_mine_areas.cpp
T
2026-08-13 18:33:10 +02:00

1167 lines
49 KiB
C++
Executable File

/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2017-02-20
*/
#include "handler_mine_areas.h"
#include "CentralEffectSimulation/handler_participant.h"
#include "settings.h"
#include <LtsUtilsCore/dds_bitarray.h>
#include <LtsUtilsCore/qpoint3d.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <ProjectDataManagement/pdm_enums.hpp>
#include <QTimer>
#include <QDateTime>
namespace dds
{
namespace core
{
inline uint qHash(ProjectDataManagement::EventType et)
{
return ::qHash(et.underlying());
}
}
}
namespace CesMineAreas
{
inline uint qHash(EffectType et)
{
return ::qHash(int(et));
}
QString toString(EffectType et)
{
switch (et)
{
case EffectType::Unknown: return QStringLiteral("Unknown");
case EffectType::EffectiveMineRangeEnter: return QStringLiteral("EffectiveMineRangeEnter");
case EffectType::EffectiveMineRangeLeave: return QStringLiteral("EffectiveMineRangeLeave");
case EffectType::NContaminationLeave: return QStringLiteral("NContaminationLeave");
case EffectType::NContaminationEnterArea1: return QStringLiteral("NContaminationEnterArea1");
case EffectType::NContaminationEnterArea2: return QStringLiteral("NContaminationEnterArea2");
case EffectType::NContaminationDetonation: return QStringLiteral("NContaminationDetonation");
case EffectType::FunctionalAreaLeave: return QStringLiteral("FunctionalAreaLeave");
case EffectType::FunctionalAreaEnter: return QStringLiteral("FunctionalAreaEnter");
case EffectType::ExplosionArea: return QStringLiteral("ExplosionArea");
case EffectType::ExplosionSingle: return QStringLiteral("ExplosionSingle");
case EffectType::BCContaminationLeave: return QStringLiteral("BCContaminationLeave");
case EffectType::BCContaminationEnterFloating: return QStringLiteral("BCContaminationEnterFloating");
case EffectType::BCContaminationEnterResident: return QStringLiteral("BCContaminationEnterResident");
case EffectType::BCContaminationEnterFloatingArea: return QStringLiteral("BCContaminationEnterFloatingArea");
case EffectType::BeStillWarning: return QStringLiteral("BeStillWarning");
}
return QStringLiteral("Unknown (%1)").arg(int(et));
}
HandlerMineAreas::HandlerMineAreas(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
QObject *parent)
: QObject(parent)
, m_ddsHandler(ddsHandler)
, m_handlerParticipant(participantHandler)
, m_logger(CentralEffectSimulation::getLogger("Plugin.MineAreas.HandlerMineAreas"))
{
DEBUG_LOG(m_logger) << "HandlerMineAreas::HandlerMineAreas";
m_aesItemViews.clear();
} // end of ctor()
//-----------------------------------------------------------------------------
HandlerMineAreas::~HandlerMineAreas()
{
m_aesItemViews.clear();
m_sendCesHitRequestQueue.clear();
m_eventStates.clear();
m_effectTypeStates.clear();
m_effectTypeBitFieldIndexes.clear();
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerMineAreas::init()
{
auto dtcAes = m_ddsHandler->dtcAes();
dtcAes->waitForHistoricalDataMineArea(2000);
dtcAes->waitForHistoricalDataMineCorridor(2000);
DEBUG_LOG(m_logger) << "HandlerMineAreas::init";
dtcAes->enableTriggeredImpacts();
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::triggeredImpactsChanged,
this, &HandlerMineAreas::onTriggeredImpactsChanged);
dtcAes->enableMineArea();
//////////////////////////////////////////////////////////////////
dtcAes->waitForHistoricalDataAesItemView(1000);
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &HandlerMineAreas::onAesItemViewChanged);
DEBUG_LOG(m_logger) << " m_aesItemViews.size=" << m_aesItemViews.size();
// Get 'static' data for all onAesItemView
{
auto cb = [this](const AreaEffectSimulation::AesItemView & aiv)
{
onAesItemViewChanged(aiv, DataModification::eAdded);
};
if (!dtcAes->aesItemViews(cb))
return false;
}
DEBUG_LOG(m_logger) << " m_aesItemViews.size=" << m_aesItemViews.size();
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newOutdoorPosition,
this, &HandlerMineAreas::onNewOutdoorPosition);
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newParticipantState,
this, &HandlerMineAreas::onNewParticipantState);
INFO_LOG(m_logger) << "HandlerParticipantArea::init() finished.";
return true;
} // end of init()
//-----------------------------------------------------------------------------
void HandlerMineAreas::onSendCesHitReply(const Core::FunctionReplyObject &replyObject)
{
DEBUG_LOG(m_logger) << "onSendCesHitReply for id " << replyObject.id() << " success= " << replyObject.error();
if (replyObject.error())
WARNING_LOG(m_logger) << "Can not send enter/leave FunctionsArea to participant in training area: " << replyObject();
// Send next Request, if available
if (!m_sendCesHitRequestQueue.isEmpty())
{
DEBUG_LOG(m_logger) << "m_sendCesAreaActionRequestQueue.size()=" << m_sendCesHitRequestQueue.size();
m_sendCesHitRequestQueue.dequeue();
// Send next Message
if (!m_sendCesHitRequestQueue.isEmpty())
{
const auto &hr = m_sendCesHitRequestQueue.head();
DEBUG_LOG(m_logger) << "sendCesHitRequest: " << hr;
m_ddsHandler->ftcTab()->sendCesHitRequest(hr, this);
}
}
}
void HandlerMineAreas::onMineTriggeredReply(const Core::FunctionReplyObject &replyObject)
{
if (replyObject.error())
ERROR_LOG(m_logger) << "Can not send MineTriggerReply: " << replyObject();
else
DEBUG_LOG(m_logger) << "MineTriggerReply for id " << replyObject.id() << " success";
}
// ///////////////////////////////////
// A E S (AreaEffectSimulation)
// ///////////////////////////////////
void HandlerMineAreas::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
{
if (data.aesTypeId() != AreaEffectSimulation::AesType_def::AtMineAreaSingleMines
&& data.aesTypeId() != AreaEffectSimulation::AesType_def::AtMineArea
&& data.aesTypeId() != AreaEffectSimulation::AesType_def::AtMineCorridor)
{
DEBUG_LOG(m_logger) << "AesItemView return";
return;
}
const AreaEffectSimulation::MineArea &ma = m_ddsHandler->dtcAes()->mineArea(data.aesItemId());
DEBUG_LOG(m_logger) << "aesItemId=" << data.aesItemId()
<< " chargeTypeId=" << data.chargeStruct().chargeTypeId()
<< " isCentral=" << ma.isCentral();
// 240 = Verlegemine muss immer berechnet werden.
if (!ma.isCentral() && (data.chargeStruct().chargeTypeId() != 240))
return;
if (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsExpired)
{
DEBUG_LOG(m_logger) << "AesItemView expired return id=" << data.aesItemId();
aesItemViewRemoved(data.aesItemId());
return;
}
if (m_ddsHandler->isDus(data.chargeStruct()))
{
DEBUG_LOG(m_logger) << "isDus aesItemId=" << data.aesItemId()
<< " chargeTypeId=" << data.chargeStruct().chargeTypeId() << " do not consider";
return;
}
const int aesItemId = data.aesItemId();
DEBUG_LOG(m_logger) << "Got AesItemView id: " << aesItemId
<< ", type: " << data.aesTypeId()
<< ", effectState: " << data.effectStateId()
<< ", modType: " << modType;
DEBUG_LOG(m_logger) << " m_aesItemViews.size=" << m_aesItemViews.size();
if (modType == DataModification::eRemoved)
{
DEBUG_LOG(m_logger) << " aesItemViewRemoved aesItemId=" << aesItemId;
aesItemViewRemoved(aesItemId);
return;
}
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtMineAreaSingleMines)
{
if (!m_aesItemViews.contains(aesItemId))
{
DEBUG_LOG(m_logger) << " !m_aesItemViews.contains aesItemId=" << aesItemId;
return;
}
// build Polygon Mines:
DEBUG_LOG(m_logger) << " m_aesItemViews.size=" << m_aesItemViews.size();
auto &formMines = m_aesItemViews[data.aesItemId()].formMines;
DEBUG_LOG(m_logger) << " m_aesItemViews.size=" << m_aesItemViews.size();
int &zone = m_aesItemViews[data.aesItemId()].zone;
DEBUG_LOG(m_logger) << " m_aesItemViews.size=" << m_aesItemViews.size();
formMines.clear();
formMines.reserve(data.form().size());
for (const Core::GeoPosition2D &pointGeo : data.form())
formMines.push_back(CentralEffectSimulation::geographic2Utm(pointGeo, &zone));
return;
}
const AreaEffectSimulation::AesEffectState &effectState = data.effectStateId();
const double impactRadius = m_ddsHandler->chargeTypeRadius(data.chargeStruct());
DEBUG_LOG(m_logger) << "impactRadius=" << impactRadius;
switch (effectState.underlying())
{
case AreaEffectSimulation::AesEffectState_def::EsPrepared:
{
break;
}
case AreaEffectSimulation::AesEffectState_def::EsActivated:
{
const auto aesItemViewUtm(CentralEffectSimulation::AesItemViewUtm::create(data, m_aesItemViews[data.aesItemId()], impactRadius));
DEBUG_LOG(m_logger) << "EsActivated m_aesItemViews.insert data.aesItemId()= " << data.aesItemId()
<< " m_aesItemViews.size=" << m_aesItemViews.size();
m_aesItemViews.insert(data.aesItemId(), aesItemViewUtm);
DEBUG_LOG(m_logger) << " m_aesItemViews.size=" << m_aesItemViews.size();
printAesItemViews();
break;
} // case EsActivated
case AreaEffectSimulation::AesEffectState_def::EsRemoved:
case AreaEffectSimulation::AesEffectState_def::EsExpired:
{
aesItemViewRemoved(aesItemId);
break;
}
default:
// do nothing
break;
} // switch effectStateId
DEBUG_LOG(m_logger) << " m_aesItemViews.size=" << m_aesItemViews.size();
printAesItemViews();
} // onAesItemViewChanged
void HandlerMineAreas::onNewOutdoorPosition(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition)
{
if (m_handlerParticipant->isOutdated(participantPosition))
return;
if (m_handlerParticipant->getEquipmentNumber(participantPosition.participantId()) == 0)
{
DEBUG_LOG(m_logger) << "Not handle position: participant has no equipment number";
return;
}
ParticipantManagement::TypeClass typeClass = m_handlerParticipant->typeClassFromTypeId(participantPosition.participantTypeId());
// can happen since the positions are collected for all participants (no check if it is a SupportEntity or similar)
if (typeClass == ParticipantManagement::TypeClass_def::Unit ||
typeClass == ParticipantManagement::TypeClass_def::SupportUnit ||
typeClass == ParticipantManagement::TypeClass_def::SupportEntity ||
typeClass == ParticipantManagement::TypeClass_def::Aircraft ||
typeClass == ParticipantManagement::TypeClass_def::Vessel ||
typeClass == ParticipantManagement::TypeClass_def::Unknown)
{
DEBUG_LOG(m_logger) << "return New Position Participant with id " << participantPosition.participantId()
<< " has invalid typeClass: " << typeClass;
return;
}
int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantPosition.participantId());
if (equipmentNumber <= 0)
{
TRACE_LOG(m_logger) << "return New Position - participant has no equipment number"
<< " participantId=" << participantPosition.participantId()
<< " typeClass=" << typeClass;
return;
}
if (participantPosition.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CatastrophicKill)
{
DEBUG_LOG(m_logger) << "New Position CatastrophicKill return";
return;
}
if (m_mineLists.contains(participantPosition.participantId()))
{
DEBUG_LOG(m_logger) << "Naechste Mine schicken ohne Bounding-Box-Check... return"
<< " Anzahl Minen in Liste:" << m_mineLists[participantPosition.participantId()].size()
<< " cesMaxPeriodForCashedMines=" << Settings::cesPeriodStoredMinesOutdated();
//DEBUG_LOG(m_logger) << "Settings::cesMaxPeriodForCashedMines() =" << Settings::cesMaxPeriodForCashedMines();
if ((m_mineLists[participantPosition.participantId()].size() > 0)
&& (QDateTime::currentMSecsSinceEpoch() - m_mineLists[participantPosition.participantId()][0].time < Settings::cesPeriodStoredMinesOutdated()))
{
DEBUG_LOG(m_logger) << "Send Stored mines";
// Search mine with the next no distance
int distance = m_mineLists[participantPosition.participantId()][0].distance;
int index = 0;
for (int i = 0; i < m_mineLists[participantPosition.participantId()].size(); i++)
{
if (m_mineLists[participantPosition.participantId()][i].distance < distance)
{
distance = m_mineLists[participantPosition.participantId()][i].distance;
index = i;
}
}
//m_mineLists[participantPos.participantId()].value()
int mineIndex = m_mineLists[participantPosition.participantId()][index].mineIndex;
int aesItemId = m_mineLists[participantPosition.participantId()][index].aesItemId;
if (!m_aesItemViews.contains(aesItemId))
return;
sendFtcMineTrigger(aesItemId, mineIndex - 1);
sendEffectTypeEvent(m_aesItemViews[aesItemId], participantPosition, EffectType::EffectiveMineRangeEnter, mineIndex - 1, -1);
CentralEffectSimulation::HandlerParticipant::CesParticipantData minePosition = participantPosition;
// TODO convert minePos to geographic and set minePosGeo
// DEBUG_LOG(m_logger) << "minePosGeo lat=" << minePosGeo.lat()
// << " lon=" << minePosGeo.lon()
// << " z=" << minePosGeo.z();
sendParticipantEvent(m_aesItemViews[aesItemId], minePosition, ProjectDataManagement::EventType_def::HitMine);
m_mineLists[participantPosition.participantId()].remove(index);
if (m_mineLists[participantPosition.participantId()].size() == 0)
{
m_mineLists[participantPosition.participantId()].clear();
m_mineLists.remove(participantPosition.participantId());
}
return;
}
else
{
DEBUG_LOG(m_logger) << "Stored mines are outdated!"
<< " actTime=" << QDateTime::currentMSecsSinceEpoch()
<< " Settings::cesPeriodStoredMinesOutdated()=" << Settings::cesPeriodStoredMinesOutdated();
m_mineLists[participantPosition.participantId()].clear();
m_mineLists.remove(participantPosition.participantId());
}// end if time-check
}
DEBUG_LOG(m_logger) << "HandlerParticipantArea::calculateAesParticipant paricipantId: " << participantPosition.participantId()
<< " m_aesItemViews.size=" << m_aesItemViews.size();
// const QVector<QPointF> utmStepPoly = m_handlerParticipant->getParticipantStep(participantPos.participantId(), m_zone);
for (const CentralEffectSimulation::AesItemViewUtm &itemView : qAsConst(m_aesItemViews))
{
int remaining = m_ddsHandler->remainingTasCode(itemView.chargeStruct);
DEBUG_LOG(m_logger) << " itemView: " << itemView.aesItemId << ", " << itemView.aesTypeId
<< " remainingTasCode=" << remaining;
if (itemView.effectStateId != AreaEffectSimulation::AesEffectState_def::EsActivated)
continue;
if (typeClass == ParticipantManagement::TypeClass_def::Human && remaining > 50)
{
DEBUG_LOG(m_logger) << "ParticipantManagement::TypeClass_def::Human && remaining > 50 continue";
continue;
}
if (typeClass == ParticipantManagement::TypeClass_def::Human && m_ddsHandler->isAtMine(itemView.chargeStruct))
continue;
if (itemView.aesTypeId.underlying() == AreaEffectSimulation::AesType_def::AtMineArea)
{
// checks whether the participant has been positioned in the minefield or across it.
bool inBoundingBox = inBoundingBoxCheck(itemView, participantPosition);
if (!inBoundingBox)
{
bool intersectsBoundingBox = intersectsBoundingBoxCheck(itemView, participantPosition.participantId());
if (!intersectsBoundingBox)
{
DEBUG_LOG(m_logger) << "Continue nach Bounding BoxCheck itemView: " << itemView.aesItemId << ", "
<< " paricipantId=" << participantPosition.participantId();
continue;
}
}
DEBUG_LOG(m_logger) << "Weiter nach Bounding BoxCheck itemView: " << itemView.aesItemId << ", "
<< " paricipantId=" << participantPosition.participantId();
bool inFormCheckResult = inFormCheck(itemView, participantPosition);
if (!inFormCheckResult)
{
DEBUG_LOG(m_logger) << "!inForm";
if (!intersectFormCheck(itemView, participantPosition.participantId()))
{
DEBUG_LOG(m_logger) << "!intersectForm continue";
continue;
}
}
DEBUG_LOG(m_logger) << "Weiter nach inFormCheck und intersectFormCheck";
sendParticipantEventEnterLeave(itemView, participantPosition, inFormCheckResult);
DEBUG_LOG(m_logger) << "intersectMineRadiusCheck ";
if (intersectMineRadiusCheck(itemView, participantPosition))
{
DEBUG_LOG(m_logger) << "intersectMineRadiusCheck=true return";
return;
}
} // if AtMineArea
} // for m_aesItemViews
} // calculateAesParticipant
void HandlerMineAreas::onNewParticipantState(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos)
{
DEBUG_LOG(m_logger) << "onNewParticipantState ";
if (participantPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CombatReady)
{
DEBUG_LOG(m_logger) << "m_mineLists.contains(participantPos.participantId():" << m_mineLists.contains(participantPos.participantId());
if (m_mineLists.contains(participantPos.participantId()))
{
DEBUG_LOG(m_logger) << "onNewParticipantState CombatReady, loesche Minenliste Eintrag";
m_mineLists[participantPos.participantId()].clear();
m_mineLists.remove(participantPos.participantId());
}
DEBUG_LOG(m_logger) << "onNewParticipantState CombatReady, loesche Minenliste";
}
}
// return true, if participant crossed the dangerous area of a mine
bool HandlerMineAreas::intersectMineRadiusCheck(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition)
{
qreal distance = -1.0;
qreal lastDistance = -1.0;
QPointF minePos = QPointF();
int mineIndex = -1;
int mineListIndex = -1;
int mineListItemIndex = -1;
int32_t bitFieldIdx = 0;
const double impactRadius = m_ddsHandler->chargeTypeRadius(itemView.chargeStruct);
const QPolygonF utmStep = m_handlerParticipant->getParticipantStep(participantPosition.participantId(), itemView.zone);
for (const auto &itPos : itemView.formMines)
{
DEBUG_LOG(m_logger) << " itemId=" << itemView.aesItemId
<< " chargeTypeId=" << itemView.chargeStruct.chargeTypeId()
<< ", MinePosUtm: " << CentralEffectSimulation::debug(itPos)
<< " utmStep:" << utmStep[0].x() << utmStep[0].y()
<< ", " << utmStep[1].x() << utmStep[1].y();
// Check, if mine is active
// already triggered (bit is already 0)
if (m_triggeredImpacts.contains(itemView.aesItemId))
{
const AreaEffectSimulation::TriggeredImpacts &triggeredImpact = m_triggeredImpacts[itemView.aesItemId];
if (!LtsUtils::BitArray::testBit(triggeredImpact.bitfield(), bitFieldIdx))
{
++bitFieldIdx;
DEBUG_LOG(m_logger) << "Mine is active continue bitFieldIdx=" << bitFieldIdx;
continue;
}
}
const int mineIdx = (itemView.aesTypeId == AreaEffectSimulation::AesType_def::AtDusSingleMine)
? itemView.dusMineId : bitFieldIdx + 1; // mineIdx in minefield starts at 1
// Check, if participant is inside danger-radius of the mine
distance = crossCircle(itPos, impactRadius, participantPosition.participantId(), itemView.zone);
DEBUG_LOG(m_logger) << "distance=" << distance;
if (distance < 0.0)
{
DEBUG_LOG(m_logger) << "distance < 0.0 continue";
++bitFieldIdx;
continue;
}
if (lastDistance < 0.0)
lastDistance = distance + 1.0;
MineListItem mineListItem;
mineListItem.aesItemId = itemView.aesItemId;
mineListItem.distance = distance;
mineListItem.mineIndex = mineIdx;
mineListItem.minePos = minePos;
mineListItem.time = QDateTime::currentMSecsSinceEpoch();
m_mineLists[participantPosition.participantId()].append(mineListItem);
mineListIndex++;
DEBUG_LOG(m_logger) << " m_mineLists[" << participantPosition.participantId()
<< "].length=" << m_mineLists[participantPosition.participantId()].length();
if (distance < lastDistance)
{
DEBUG_LOG(m_logger) << " distance < lastDistance crossCircle for aesItemId: " << itemView.aesItemId
<< ", mineIdx: " << mineIdx
<< ", impactRadius:" << impactRadius
<< ", participantId: " << participantPosition.participantId()
<< ", lastDistance:" << lastDistance
<< ", distance:" << distance;
minePos = itPos;
mineIndex = mineIdx;
lastDistance = distance;
mineListItemIndex = mineListIndex;
}
bitFieldIdx++;
} // for each mine
DEBUG_LOG(m_logger) << "End of for-loop participantId=" << participantPosition.participantId()
<< " mineIndex=" << mineIndex
<< " lastDistance=" << lastDistance;
if (lastDistance > 0)
{
DEBUG_LOG(m_logger) << "sendEffectTypeEvent participantId=" << participantPosition.participantId()
<< " mineIndex=" << mineIndex;
// TODO Minenposition fuer den Event nehmen und nicht die Participant-Position
sendFtcMineTrigger(itemView.aesItemId, mineIndex - 1);
sendEffectTypeEvent(itemView, participantPosition, EffectType::EffectiveMineRangeEnter, mineIndex - 1, -1);
CentralEffectSimulation::HandlerParticipant::CesParticipantData minePosition = participantPosition;
// TODO convert minePos to geographic and set minePosGeo
// DEBUG_LOG(m_logger) << "minePosGeo lat=" << minePosGeo.lat()
// << " lon=" << minePosGeo.lon()
// << " z=" << minePosGeo.z();
sendParticipantEvent(itemView, minePosition, ProjectDataManagement::EventType_def::HitMine);
// aktuell verarbeitete Mine aus der Liste entfernen.
m_mineLists[participantPosition.participantId()].remove(mineListItemIndex);
}
return false;
}
// return true, if participant is inside of the bounding Box
bool HandlerMineAreas::intersectsBoundingBoxCheck(const CentralEffectSimulation::AesItemViewUtm &itemView,
const int participantId)
{
bool result = false;
DEBUG_LOG(m_logger) << "intersectsBoundingBoxCheck participantId=" << participantId
<< " itemViewId=" << itemView.aesItemId
<< " zone=" << itemView.zone;
const QPolygonF stepPoly = m_handlerParticipant->getParticipantStep(participantId, itemView.zone);
if (stepPoly.size() < 2)
return false;
DEBUG_LOG(m_logger) << "utmStep von=" << stepPoly.at(0).x() << "/" << stepPoly.at(0).y()
<< " bis=" << stepPoly.at(1).x() << "/" << stepPoly.at(1).y()
<< " zone=" << itemView.zone;
DEBUG_LOG(m_logger) << "ItemView Bounding Box BottomLeft=" << itemView.boundingBoxBottomLeft.x() << "/" << itemView.boundingBoxBottomLeft.y()
<< " boundingBoxTopRight=" << itemView.boundingBoxTopRight.x() << "/" << itemView.boundingBoxTopRight.y();
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
result = itemView.boundingBox.intersected(stepPoly).size() > 0;
#else
result = itemView.boundingBox.intersects(stepPoly);
#endif
DEBUG_LOG(m_logger) << "HandlerMineAreas::intersectsBoundingBoxCheck result =" << result;
return result;
}
// return true, if participant is inside of the bounding Box
bool HandlerMineAreas::inBoundingBoxCheck(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition)
{
const double impactRadius = m_ddsHandler->chargeTypeRadius(itemView.chargeStruct);
qreal boundingBoxBottomLeftX = itemView.boundingBoxBottomLeft.x() - impactRadius;
qreal boundingBoxBottomLeftY = itemView.boundingBoxBottomLeft.y() + impactRadius;
qreal boundingBoxTopRightX = itemView.boundingBoxTopRight.x() + impactRadius;
qreal boundingBoxTopRightY = itemView.boundingBoxTopRight.y() - impactRadius;
QPointF boundingBoxBottomLeft = QPointF(boundingBoxBottomLeftX, boundingBoxBottomLeftY);
QPointF boundingBoxTopRight = QPointF(boundingBoxTopRightX, boundingBoxTopRightY);
DEBUG_LOG(m_logger) << " impactRadius=" << impactRadius
<< " itemView.boundingBoxBottomLeft" << itemView.boundingBoxBottomLeft.x() << "/" << itemView.boundingBoxBottomLeft.y()
<< " itemView.boundingBoxTopRight" << itemView.boundingBoxTopRight.x() << "/" << itemView.boundingBoxTopRight.y()
<< " boundingBoxBottomLeft=" << boundingBoxBottomLeft.x() << "/" << boundingBoxBottomLeft.y()
<< " boundingBoxTopRight=" << boundingBoxTopRight.x() << "/" << boundingBoxTopRight.y();
const QRectF boundingBoxImpact(boundingBoxBottomLeft,
boundingBoxTopRight);
const QPointF participantPosUtmPoint = CentralEffectSimulation::geographic2Utm(participantPosition.pos(), itemView.zone);
if (boundingBoxImpact.contains(participantPosUtmPoint))
{
DEBUG_LOG(m_logger) << "inBoundingBoxCheck Paricipant " << participantPosition.participantId()
<< " inside AesItemView:" << itemView.aesItemId << " return true";
return true;
}
DEBUG_LOG(m_logger) << "inBoundingBoxCheck Paricipant " << participantPosition.participantId()
<< " outside AesItemView:" << itemView.aesItemId << " return false";
return false;
}
// return true, if participant is inside of the form of AesItemView
bool HandlerMineAreas::inFormCheck(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition)
{
const QPointF participantPosUtmPoint = CentralEffectSimulation::geographic2Utm(participantPosition.pos(), itemView.zone);
DEBUG_LOG(m_logger) << "inFormCheck start, paricipantId: " << participantPosition.participantId()
<< ", aesItemId: " << itemView.aesItemId
<< ", aesTypeId: " << itemView.aesTypeId
<< ", form.size: " << itemView.form.size();
if (itemView.form.containsPoint(participantPosUtmPoint, Qt::FillRule::OddEvenFill))
{
DEBUG_LOG(m_logger) << "inside AES form, paricipantId: " << participantPosition.participantId()
<< ", aesItemId: " << itemView.aesItemId;
return true;
} // if inside
return inExtededFormCheck(itemView, participantPosition);
}
// return true, if participant is inside of the form of AesItemView
bool HandlerMineAreas::intersectFormCheck(const CentralEffectSimulation::AesItemViewUtm &itemView,
const int participantId)
{
const QPolygonF utmStep = m_handlerParticipant->getParticipantStep(participantId, itemView.zone);
DEBUG_LOG(m_logger) << "intersectFormCheck start, paricipantId: " << participantId
<< ", aesItemId: " << itemView.aesItemId
<< ", aesTypeId: " << itemView.aesTypeId
<< ", form.size: " << itemView.form.size();
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
if (itemView.form.intersected(utmStep).size() > 0)
#else
if (itemView.form.intersects(utmStep))
#endif
{
DEBUG_LOG(m_logger) << "intersect AES form, paricipantId: " << participantId
<< ", aesItemId: " << itemView.aesItemId;
return true;
} // if inside
return false;
}
void HandlerMineAreas::onTriggeredImpactsChanged(const AreaEffectSimulation::TriggeredImpacts &data, DataModification modType)
{
if (modType != DataModification::eAdded &&
modType != DataModification::eModified)
return;
DEBUG_LOG(m_logger) << "Got TriggeredImpacts: ";
switch (data.aesTypeId().underlying())
{
case AreaEffectSimulation::AesType_def::AtExplosionArea:
case AreaEffectSimulation::AesType_def::AtExplosionSingle:
//case AreaEffectSimulation::AesType_def::AtExplosionAreaSingleExplosions: Plugin Artillery
// explosion at the position of participant
calculateImpacts(data);
break;
case AreaEffectSimulation::AesType_def::AtMineAreaSingleMines:
case AreaEffectSimulation::AesType_def::AtMineArea:
// participant run on mine
// => store Mine-State and take into account when a participant runs to one of this mines
m_triggeredImpacts.insert(data.aesItemId(), data);
break;
default:
//nothigng
break;
}
} // onTriggeredImpactsChanged
// Check for all participants wheter he is in the explosion area
void HandlerMineAreas::calculateImpacts(const AreaEffectSimulation::TriggeredImpacts &data)
{
if ((data.aesTypeId() == AreaEffectSimulation::AesType_def::AtExplosionAreaSingleExplosions)
|| (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtExplosionClusterSingleExplosions))
return;
auto it = m_aesItemViews.find(data.aesItemId());
if (it == m_aesItemViews.end())
{
WARNING_LOG(m_logger) << "Could not find item view for aes with id " << data.aesItemId();
return;
}
CentralEffectSimulation::AesItemViewUtm &aesItemView = *it;
// older then 10sec? ignore
if (data.sampleTime() < m_ddsHandler->currentPartitionTime() - 10 * 1000)
{
if (aesItemView.sampleTimeHandledImpacts < data.sampleTime())
{
aesItemView.sampleTimeHandledImpacts = data.sampleTime();
aesItemView.handledImpacts = data.bitfield();
}
return;
}
QVector<int> bitsToCheck;
aesItemView.handledImpacts.resize(data.bitfield().size(), 0xFF);
for (int bitFieldIdx = 0; bitFieldIdx < data.impactCount(); ++bitFieldIdx)
{
// not yet triggered (bit is still 1)
if (LtsUtils::BitArray::testBit(data.bitfield(), bitFieldIdx))
continue;
// already checked (bit is already 0)
if (!LtsUtils::BitArray::testBit(aesItemView.handledImpacts, bitFieldIdx))
continue;
DEBUG_LOG(m_logger) << "New impact at idx " << bitFieldIdx;
bitsToCheck += bitFieldIdx;
}
// remember handled impacts
aesItemView.sampleTimeHandledImpacts = data.sampleTime();
aesItemView.handledImpacts = data.bitfield();
const auto participantPositions = m_handlerParticipant->positions();
for (const CentralEffectSimulation::HandlerParticipant::CesParticipantData &pPos : participantPositions)
{
DEBUG_LOG(m_logger) << "pos participantId=" << pPos.participantId()
<< " buildingId=" << pPos.buildingId()
<< " insideBuilding=" << pPos.insideBuilding()
<< " positionValid=" << pPos.positionValid;
if (pPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CatastrophicKill)
continue;
if (pPos.insideBuilding())
continue;
if (!inBoundingBoxCheck(aesItemView, pPos))
continue;
calculateImpacts(aesItemView, bitsToCheck, pPos);
}
} // calculateImpacts
// calculate all impacts of the field for a participant
void HandlerMineAreas::calculateImpacts(const CentralEffectSimulation::AesItemViewUtm &itemView,
const QVector<int> &impactsToCheck,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition)
{
// get radius of munition
const double impactRadius = m_ddsHandler->chargeTypeRadius(itemView.chargeStruct);
const QPointF participantPosUtmPoint = CentralEffectSimulation::geographic2Utm(participantPosition.pos(), itemView.zone);
for (int bitFieldIdx : impactsToCheck)
{
if (itemView.form.size() <= bitFieldIdx)
continue;
// get position of impact to corresponding bit
const QPointF &impactPos = itemView.form.value(bitFieldIdx);
if (inCircle(impactPos, impactRadius, participantPosUtmPoint))
sendEffectTypeEvent(itemView, participantPosition, EffectType::ExplosionArea, bitFieldIdx, QDateTime::currentMSecsSinceEpoch());
} // foreach Impact
} // calculateImpacts
// Send via TAB-Proxy to battlefield
void HandlerMineAreas::sendCesHitRequest(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
qint64 effectTime,
int mineFieldBitIndex)
{
int remaining = m_ddsHandler->remainingTasCode(itemView.chargeStruct);
DEBUG_LOG(m_logger) << "sendCesHitRequest "
<< " insideWlsArea=" << std::boolalpha << participantPosition.insideWlsArea()
<< " participantId=" << participantPosition.participantId();
const int equipNo = m_ddsHandler->participantId2EquipNo(participantPosition.participantId());
DEBUG_LOG(m_logger) << " ftc sendCESHit to Participant participantId = " << participantPosition.participantId()
<< " equipNo = " << equipNo
<< " aesItemId =" << itemView.aesItemId;
// participantPosition.participantPosition == 0 -> send to all
if (participantPosition.participantId() != 0 && equipNo <= 0)
{
DEBUG_LOG(m_logger) << "participantPosition.participantId != 0 && equipNo <= 0" ;
return;
}
if (participantPosition.participantId() != 0 &&
participantPosition.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CatastrophicKill)
{
DEBUG_LOG(m_logger) << "participantPosition.participantId != 0 CatastrophicKill)";
return;
}
int32_t originatorParticipantId = m_aesItemId2partIdMap.value(itemView.aesItemId, 0);
const TrainingAreaBase::TabPosition pos(participantPosition.pos(),
Core::PositionReportingSource_def::Gps, // irrelevant
participantPosition.buildingId(),
participantPosition.roomId());
const int originatorEquipNo = m_ddsHandler->participantId2EquipNo(originatorParticipantId);
const ProjectDataManagement::EventType eventType = ProjectDataManagement::EventType_def::Unknown;
TrainingAreaBase::SendCesHitRequest requestTab(
equipNo, // equipmentNumber
participantPosition.participantId(), // participantId
itemView.chargeStruct.chargeTypeId(), // chargeTypeId
itemView.aesItemId, // aesId
originatorEquipNo, // originatorEquipmentNumber
remaining, // remainEffectPercent ( no protection outside Building )
pos,
effectTime, // effectTime
eventType,
itemView.partyId, // originPartyId
mineFieldBitIndex
);
DEBUG_LOG(m_logger) << " participantId=" << participantPosition.participantId()
<< " chargeTypeId=" << itemView.chargeStruct.chargeTypeId();
m_sendCesHitRequestQueue.enqueue(requestTab);
if (m_sendCesHitRequestQueue.size() == 1)
{
DEBUG_LOG(m_logger) << "SendCesHitRequest: " << requestTab;
m_ddsHandler->ftcTab()->sendCesHitRequest(requestTab, this);
}
}
void HandlerMineAreas::sendCesHitRequest(const AreaEffectSimulation::AesItemView &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
qint64 effectTime,
int mineFieldBitIndex)
{
int remaining = m_ddsHandler->remainingTasCode(itemView.chargeStruct());
int32_t legacyChargeTypeId = 0;
legacyChargeTypeId = m_ddsHandler->getLegacyIdFromChargeTypeId(itemView.chargeStruct());
DEBUG_LOG(m_logger) << "sendCesHitRequest"
<< " insideWlsArea=" << std::boolalpha << participantPosition.insideWlsArea()
<< " participantId=" << participantPosition.participantId();
const int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantPosition.participantId());
DEBUG_LOG(m_logger) << " ftc sendCESHit to Participant participantId = " << participantPosition.participantId()
<< " equipNo = " << equipmentNumber << " aesItemId =" << itemView.aesItemId();
// participantPosition.participantPosition == 0 -> send to all
if (participantPosition.participantId() != 0 && equipmentNumber <= 0)
{
DEBUG_LOG(m_logger) << "participantPosition.participantId != 0 && equipNo <= 0" ;
return;
} // if
if (participantPosition.participantId() != 0 &&
participantPosition.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CatastrophicKill)
{
DEBUG_LOG(m_logger) << "participantPosition.participantId != 0 CatastrophicKill)";
return;
} // if
int32_t originatorParticipantId = m_aesItemId2partIdMap.value(itemView.aesItemId(), 0);
const int originatorEquipmentNumber = m_ddsHandler->participantId2EquipNo(originatorParticipantId);
const TrainingAreaBase::TabPosition pos(
participantPosition.pos(), Core::PositionReportingSource_def::Gps, participantPosition.buildingId(),
participantPosition.roomId()
);
const ProjectDataManagement::EventType eventType = ProjectDataManagement::EventType_def::Unknown;
TrainingAreaBase::SendCesHitRequest requestTab(
equipmentNumber, participantPosition.participantId(), legacyChargeTypeId, itemView.aesItemId(), originatorEquipmentNumber,
remaining, pos, effectTime, eventType, itemView.partyId().get(), mineFieldBitIndex
);
DEBUG_LOG(m_logger) << " participantId=" << participantPosition.participantId() << " chargeTypeId=" << itemView.chargeStruct().chargeTypeId()
<< " legacyChargeTypeId=" << legacyChargeTypeId;
m_sendCesHitRequestQueue.enqueue(requestTab);
if (m_sendCesHitRequestQueue.size() == 1)
{
DEBUG_LOG(m_logger) << "SendCesHitRequest: " << requestTab;
m_ddsHandler->ftcTab()->sendCesHitRequest(requestTab, this);
} // if
}
void HandlerMineAreas::sendParticipantEventEnterLeave(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const bool inFormCheckResult)
{
const ProjectDataManagement::EventType &lastEvent = m_eventStates[itemView.aesItemId][participantPosition.participantId()];
ProjectDataManagement::EventType eventType = ProjectDataManagement::EventType_def::EnterMineArea;
if (inFormCheckResult)
{
if (lastEvent == ProjectDataManagement::EventType_def::EnterMineArea)
return;
else
{
eventType = ProjectDataManagement::EventType_def::EnterMineArea;
m_eventStates[itemView.aesItemId][participantPosition.participantId()] = ProjectDataManagement::EventType_def::EnterMineArea;
}
}
else
{
if (lastEvent == ProjectDataManagement::EventType_def::LeaveMineArea)
return;
else
{
eventType = ProjectDataManagement::EventType_def::LeaveMineArea;
m_eventStates[itemView.aesItemId][participantPosition.participantId()] = ProjectDataManagement::EventType_def::LeaveMineArea;
}
}
sendParticipantEvent(itemView, participantPosition, eventType);
}
void HandlerMineAreas::sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const ProjectDataManagement::EventType eventType)
{
DEBUG_LOG(m_logger) << "sendParticipantEvent " << itemView.aesItemId
<< " participantId=" << participantPosition.participantId()
<< " eventType=" << eventType
<< " pos=" << participantPosition.pos().lat()
<< "/" << participantPosition.pos().lon()
<< "/" << participantPosition.pos().z();
int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantPosition.participantId());
const AreaEffectSimulation::MineArea &ma = m_ddsHandler->dtcAes()->mineArea(itemView.aesItemId);
CentralEffectSimulation::ParticipantEvent pe;
pe.id(m_ddsHandler->getParticipantEventId());
pe.eventTypeId(eventType.underlying());
pe.participantId(participantPosition.participantId());
pe.eventTime(participantPosition.sampleTime());
pe.aesItemId(itemView.aesItemId);
pe.partyId(participantPosition.partyId());
pe.aesName(ma.name());
pe.equipmentNumber(equipmentNumber);
pe.vulnerability(participantPosition.vulnerabilityState.underlying());
pe.position(participantPosition.pos());
m_ddsHandler->dtsCes()->publish(pe);
const auto id = pe.id();
QTimer::singleShot(1 * 60 * 1000, this, [id, this]() { m_ddsHandler->dtsCes()->removeParticipantEventByKey(id); });
}
void HandlerMineAreas::sendFtcMineTrigger(int aesItemId, int mineIndex)
{
const AreaEffectSimulation::MineArea &ma = m_ddsHandler->dtcAes()->mineArea(aesItemId);
auto ftcAes = m_ddsHandler->ftcAes();
AreaEffectSimulation::MineTriggeredRequest tr;
tr.mineAreaId(aesItemId);
tr.mineId(mineIndex);
tr.chargeTypeId(ma.chargeStruct().chargeTypeId());
DEBUG_LOG(m_logger) << "send sendFtcMineTrigger: aesItemId=" << tr.mineAreaId()
<< " MineIndex=" << tr.mineId();
ftcAes->mineTriggeredRequest(tr, this);
}
void HandlerMineAreas::sendEffectTypeEvent(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
EffectType effectType,
int mineFieldBitIndex,
qint64 effectTime)
{
DEBUG_LOG(m_logger) << "sendEffectTypeEvent aesItemId=" << itemView.aesItemId
<< " participantId=" << participantPosition.participantId()
<< " effectType=" << effectTime
<< " mineFieldBitIndex=" << mineFieldBitIndex;
Q_UNUSED(effectTime);
// Trefferereignis Sekundaerwirkung
QByteArray mfb;
if (mineFieldBitIndex >= 0)
mfb = ", mineFieldBitIndex: " + QByteArray::number(mineFieldBitIndex);
const int ctasEffectType = static_cast<int>(effectType) & 0xffff;
DEBUG_LOG(m_logger) << "Sending EffectType event " << toString(effectType)
<< ", participant: " << participantPosition.participantId()
<< ", aesItemId: " << itemView.aesItemId
<< mfb
<< ", ctasEffectType: " << ctasEffectType;
sendCesHitRequest(itemView,
participantPosition,
//effectTime >= 0 ? effectTime : participantPosition.sampleTime(),
QDateTime::currentMSecsSinceEpoch(),
mineFieldBitIndex);
}
// Anmerkung: Im SFM werden Quadrate und keine Kreise genommen. ( Wird hier nach Absprache mit Manfred nicht gemacht)
qreal HandlerMineAreas::crossCircle(const QPointF &centerUtm, const double radius, const int participantId, int zone)
{
qreal result = -1.0;
QPointF p1 = QPointF(centerUtm.x() + radius, centerUtm.y() + radius);
QPointF p2 = QPointF(centerUtm.x() + radius, centerUtm.y() - radius);
QPointF p3 = QPointF(centerUtm.x() - radius, centerUtm.y() - radius);
QPointF p4 = QPointF(centerUtm.x() - radius, centerUtm.y() + radius);
QPolygonF boundingBoxPolyMine;
boundingBoxPolyMine << p1 << p2 << p3 << p4 << p1;
const QPolygonF stepPoly = m_handlerParticipant->getParticipantStep(participantId, zone);
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
if (boundingBoxPolyMine.intersected(stepPoly).size() > 0)
#else
if (boundingBoxPolyMine.intersects(stepPoly))
#endif
{
QLineF line;
line.setP1(stepPoly[0]);
line.setP2(centerUtm);
DEBUG_LOG(m_logger) << "crossCircle distance =" << line.length();
return line.length();
}
return result;
} // inCircle
// Anmerkung: Im SFM werden Quadrate und keine Kreise genommen. ( Wird hier nach Absprache mit Manfred nicht gemacht)
bool HandlerMineAreas::inCircle(const QPointF &centerUtm, const double radius, const QPointF &pointUtm)
{
double squareDist = CentralEffectSimulation::getSquareDistance(centerUtm, pointUtm);
double squareRadius = radius * radius;
DEBUG_LOG(m_logger) << "squareDist: " << squareDist << ", squareRadius: " << squareRadius;
return (squareDist < squareRadius);
} // inCircle
void HandlerMineAreas::aesItemViewRemoved(int aesItemId)
{
DEBUG_LOG(m_logger) << "HandlerMineAreas::aesItemViewRemoved aesItemId=" << aesItemId;
m_effectTypeStates.remove(aesItemId);
m_effectTypeBitFieldIndexes.remove(aesItemId);
m_aesItemViews.remove(aesItemId);
m_eventStates.remove(aesItemId);
}
void HandlerMineAreas::printAesItemViews()
{
QHashIterator<int, CentralEffectSimulation::AesItemViewUtm> i(m_aesItemViews);
while (i.hasNext())
{
i.next();
DEBUG_LOG(m_logger) << "printAesItemViews key=" << i.key() << ": "
<< " aesItemId=" << i.value().aesItemId
<< " aesTypeId=" << i.value().aesTypeId;
}
}
bool HandlerMineAreas::inExtededFormCheck(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition) const
{
const double distance = m_ddsHandler->chargeTypeRadius(itemView.chargeStruct);
const QPointF participantPosUtmPoint = CentralEffectSimulation::geographic2Utm(participantPosition.pos(), itemView.zone);
///////////////////////////////////////////////////////////
// Check whether the position is within an expanded form //
///////////////////////////////////////////////////////////
DEBUG_LOG(m_logger) << "itemView.form.size=" << itemView.form.size();
for (int i = 0; i < itemView.form.size() ; i++)
{
int nextPoint = i + 1;
if (i == itemView.form.size() - 1)
nextPoint = 0;
const QPointF l1(itemView.form[i].x(), itemView.form[i].y());
const QPointF l2(itemView.form[nextPoint].x(), itemView.form[nextPoint].y());
double distancePointLineValue = distancePointLine(participantPosUtmPoint, l1, l2);
DEBUG_LOG(m_logger) << "distancePointLineValue=" << distancePointLineValue
<< " ParticipantPos =" << participantPosUtmPoint.x() << "/" << participantPosUtmPoint.y()
<< " Line=" << l1.x() << "/" << l1.y()
<< " " << l2.x() << "/" << l2.y();
if (distancePointLineValue < distance)
{
DEBUG_LOG(m_logger) << "posInExtendedForm return true";
return true;
}
}
DEBUG_LOG(m_logger) << "posInExtendedForm return false";
return false;
}
double HandlerMineAreas::distancePointLine(const QPointF &p, const QPointF &l1,
const QPointF &l2) const
{
const double u = (((p.x() - l1.x()) * (l2.x() - l1.x())) +
((p.y() - l1.y()) * (l2.y() - l1.y()))) / squareLen(l2, l1);
if ((u < 0.0f) || (u > 1.0f))
{
QLineF pToP1(p, l1);
QLineF pToP2(p, l2);
qreal length1 = pToP1.length();
qreal length2 = pToP2.length();
if (length1 < length2)
{
DEBUG_LOG(m_logger) << "a distancePointLine p=" << p.x() << "/" << p.y()
<< " line: p1=" << l1.x() << "/" << l1.y()
<< " p2=" << l2.x() << "/" << l2.y()
<< " distance=" << length1
<< ", return=" << length1;
return length1;
}
else
{
DEBUG_LOG(m_logger) << "b distancePointLine p=" << p.x() << "/" << p.y()
<< " line: p1=" << l1.x() << "/" << l1.y()
<< " p2=" << l2.x() << "/" << l2.y()
<< " distance=" << length2
<< ", return=" << length2;
return length2;
}
}
QPointF intersectPnt(l1.x() + u * (l2.x() - l1.x()),
l1.y() + u * (l2.y() - l1.y()));
/* double distance = sqrt(squareLen(p, intersectPnt));
DEBUG_LOG(m_logger) << "c distancePointLine p=" << p.x() << "/" << p.y()
<< " line: p1=" << l1.x() << "/" << l1.y()
<< " p2=" << l2.x() << "/" << l2.y()
<< " distance=" << distance;
return distance;*/
return 0;
}
double HandlerMineAreas::squareLen(const QPointF &p1, const QPointF &p2) const
{
double vx = p2.x() - p1.x();
double vy = p2.y() - p1.y();
return vx * vx + vy * vy;
}
} // namespace CesMineAreas