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

218 lines
7.7 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Calculate line of sight
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2024-11-03
*/
#include "line_of_sight.h"
#include <CentralEffectSimulation/logger.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <LtsElevation/lts_elevation_manager.h>
#include <QElapsedTimer>
namespace CesExplosions
{
CentralEffectSimulation::LOGGER_T getLocalLogger()
{
return CentralEffectSimulation::getLogger("Plugin.Explosions.LineOfSight");
}
bool lineOfSightBuilding(const LtsCoordTrans::LtsCoordinate &impactLtsCoord_absZ,
const LtsCoordTrans::LtsCoordinate &participantLtsCoord_absZ,
bool &bLosOut,
std::shared_ptr<CentralEffectSimulation::ProxyBuilding> proxyBuilding)
{
static CentralEffectSimulation::LOGGER_T logger = getLocalLogger();
TRACE_LOG(logger) << LOGFUNCTION << " START";
DEBUG_LOG(logger) << LOGFUNCTION << " impactCoord = " << impactLtsCoord_absZ.toString(true);
DEBUG_LOG(logger) << LOGFUNCTION << " participant = " << participantLtsCoord_absZ.toString(true);
if (!proxyBuilding || !proxyBuilding->isSet_handlerBuildingModel())
{
INFO_LOG(logger) << LOGFUNCTION << " proxyBuilding not working...";
return false;
}
// sp should be checked by isSet above:
std::shared_ptr<CesBuildings::HandlerBuildingModelInterface> sp = proxyBuilding->handlerBuildingModelInterface();
const CesBuildings::HandlerBuildingModelInterface::LineBuildingIntersectsResult &result =
sp->getLineBuildingIntersects({impactLtsCoord_absZ.geoPosition(), participantLtsCoord_absZ.geoPosition()});
bool success = false;
if (result.errorString.empty())
{
if (result.intersects)
DEBUG_LOG(logger) << "lineOfSightBuilding, res.intersect = " << "YES";
else
DEBUG_LOG(logger) << "lineOfSightBuilding, res.intersect = " << "NO";
bLosOut = !result.intersects;
success = true;
}
else
{
ERROR_LOG(logger) << LOGFUNCTION
<< " getLineBuildingIntersects failed"
<< ", impactCoord = " << impactLtsCoord_absZ.toString(true)
<< ", participantCoord = " << participantLtsCoord_absZ.toString(true)
<< ", res.errorString = '" << result.errorString << "'";
}
DEBUG_LOG(logger) << LOGFUNCTION
<< ", success = " << success
<< ", bLosOut = " << bLosOut;
TRACE_LOG(logger) << LOGFUNCTION << " END, success = " << success;
return success;
}
bool lineOfSightElevation(const LtsCoordTrans::LtsCoordinate &impactLtsCoord_absZ,
const LtsCoordTrans::LtsCoordinate &participantLtsCoord_absZ,
bool &bLosOut,
const int exerciseId)
{
static CentralEffectSimulation::LOGGER_T logger = getLocalLogger();
TRACE_LOG(logger) << LOGFUNCTION << " START";
DEBUG_LOG(logger) << LOGFUNCTION << " getExerciseId=" << exerciseId
<< ", impactCoord = " << impactLtsCoord_absZ.toString(true)
<< ", participantCoord = " << participantLtsCoord_absZ.toString(true);
//
// The very first instanciation should be done by the MainHandler:
//
static LtsElevation::LTS_ELEVATION_MANAGER_TYPE s_ltsElevationManager = nullptr;
if (!s_ltsElevationManager)
s_ltsElevationManager = LtsElevation::LtsElevationManager::getInstance(exerciseId);
if (!s_ltsElevationManager)
{
WARNING_LOG(logger) << LOGFUNCTION << " no LtsElevationManager could be create for exerciseId " << exerciseId;
return false;
}
if (s_ltsElevationManager->isValid())
DEBUG_LOG(logger) << LOGFUNCTION << " LtsElevationManager is valid for exerciseId = " << exerciseId;
else
{
WARNING_LOG(logger) << LOGFUNCTION << " LtsElevationManager is INVALID for exerciseId = " << exerciseId;
return false;
}
const LtsUtils::QPoint3D &start = impactLtsCoord_absZ.toGeoPoint3D();
const LtsUtils::QPoint3D &end = participantLtsCoord_absZ.toGeoPoint3D();
const LtsElevation::LineOfSight losEle = s_ltsElevationManager->lineOfSightCalculation(start, end);
bool success = false;
switch (losEle)
{
case LtsElevation::LineOfSight::LOS_UNDEFINED:
case LtsElevation::LineOfSight::LOS_ERROR:
case LtsElevation::LineOfSight::LOS_INVISIBLE:
success = true;
bLosOut = false;
break;
case LtsElevation::LineOfSight::LOS_VISIBLE:
success = true;
bLosOut = true;
break;
} // switch
DEBUG_LOG(logger) << LOGFUNCTION
<< ", success = " << success
<< ", losEle = " << losEle
<< ", bLosOut = " << bLosOut;
TRACE_LOG(logger) << LOGFUNCTION << " END, success = " << success << ", losEle = " << losEle;
return success;
}
bool lineOfSight_elevationAndBuilding(const int exerciseId,
const LtsCoordTrans::LtsCoordinate &impactLtsCoord_absZ,
const LtsCoordTrans::LtsCoordinate &participantLtsCoord_absZ,
Options lineOfSightOptions,
bool &bLosOut,
std::shared_ptr<CentralEffectSimulation::ProxyBuilding> proxyBuilding)
{
static CentralEffectSimulation::LOGGER_T logger = getLocalLogger();
// What shall happen, if exeBldgLos is SKIP or proxyBuilding is not availble?
bool success = true; // (BLDG_LOS_SKIP || no buildings) -> bLOS given :-)
bLosOut = true;
DEBUG_LOG(logger) << LOGFUNCTION << " impactCoord = " << impactLtsCoord_absZ.toString(true);
DEBUG_LOG(logger) << LOGFUNCTION << " participant = " << participantLtsCoord_absZ.toString(true);
//
// execute different LineOfSight operations:
// try to start with the cheapest. But which is cheap and which expensive?
// assume lineOfSightBuilding is expensive due to several buildings, rooms, walls...
//
DEBUG_LOG(logger) << LOGFUNCTION << " vor lineOfSightOptions.testFlag EXECUTE_ELEVATION_LOS_CALC"
<< " lineOfSightOptions.testFlag(Option::EXECUTE_ELEVATION_LOS_CALC)=" << lineOfSightOptions.testFlag(Option::EXECUTE_ELEVATION_LOS_CALC);
if (lineOfSightOptions.testFlag(Option::EXECUTE_ELEVATION_LOS_CALC) /*&& bLOS*/)
{
DEBUG_LOG(logger) << LOGFUNCTION << " lineOfSightOptions EXECUTE_ELEVATION_LOS_CALC";
QElapsedTimer timer;
DEBUG_LOG(logger) << LOGFUNCTION << " vor lineOfSightOptions start";
if (logger.isInfoEnabled())
timer.start();
if (lineOfSightElevation(impactLtsCoord_absZ,
participantLtsCoord_absZ,
bLosOut, exerciseId))
{
DEBUG_LOG(logger) << "---------------- lineOfSightElevation bLosOut=" << bLosOut;
if (!bLosOut)
{
DEBUG_LOG(logger) << "---------------- lineOfSightElevation return success";
return success;
}
DEBUG_LOG(logger) << "---------------- lineOfSightElevation continue with buildings";
}
else
return false;
INFO_LOG(logger) << " lineOfSightElevation took [ms] " << timer.elapsed();
}
else
DEBUG_LOG(logger) << "skip lineOfSightElevation due to option EXECUTE_ELEVATION_LOS_CALC";
DEBUG_LOG(logger) << LOGFUNCTION << " vor lineOfSightOptions.testFlag EXECUTE_BLDG_LOS_CALC";
if (lineOfSightOptions.testFlag(Option::EXECUTE_BLDG_LOS_CALC))
{
QElapsedTimer timer;
if (logger.isInfoEnabled())
timer.start();
if (lineOfSightBuilding(impactLtsCoord_absZ, participantLtsCoord_absZ,
bLosOut, proxyBuilding))
return success;
else
return false;
INFO_LOG(logger) << " lineOfSightBuilding took [ms] " << timer.elapsed();
}
else
DEBUG_LOG(logger) << "skip lineOfSightBuilding due to option EXECUTE_BLDG_LOS_CALC or previous non-LineOfSight";
return true;
}
} // namespace