#include "lts_elevation_manager.h" #ifdef BUILD_RTI #include #include #include #include #include #include #include #include static_assert((int)SituationMap::ElevationMapManager::LineOfSight::LOS_UNDEFINED == (int)LtsElevation::LineOfSight::LOS_UNDEFINED, "LineOfSight mismatch"); static_assert((int)SituationMap::ElevationMapManager::LineOfSight::LOS_ERROR == (int)LtsElevation::LineOfSight::LOS_ERROR, "LineOfSight mismatch"); static_assert((int)SituationMap::ElevationMapManager::LineOfSight::LOS_VISIBLE == (int)LtsElevation::LineOfSight::LOS_VISIBLE, "LineOfSight mismatch"); static_assert((int)SituationMap::ElevationMapManager::LineOfSight::LOS_INVISIBLE == (int)LtsElevation::LineOfSight::LOS_INVISIBLE, "LineOfSight mismatch"); #endif namespace LtsElevation { class LtsElevationManager; using LtsElevatioMgrMapTrainingAreaId = QMap; static LtsElevatioMgrMapTrainingAreaId& ltsElevatioMgrMapTrainingAreaId() { static LtsElevatioMgrMapTrainingAreaId s_ltsElevatioMgrMapTrainingAreaId; return s_ltsElevatioMgrMapTrainingAreaId; } static void cleanupLtsElevatioMgrMapTrainingAreaId() { qDeleteAll(ltsElevatioMgrMapTrainingAreaId()); ltsElevatioMgrMapTrainingAreaId().clear(); } LtsElevatioMgrMapTrainingAreaId& getLtsElevationMgrMapTrainingAreaId() { if (ltsElevatioMgrMapTrainingAreaId().isEmpty()) qAddPostRoutine(cleanupLtsElevatioMgrMapTrainingAreaId); return ltsElevatioMgrMapTrainingAreaId(); } static long s_counter{0}; class LtsElevationManager::Private { public: Private() = default; ~Private() { #ifdef BUILD_RTI delete m_elevationManager; #endif } std::shared_ptr m_exmDtc; #ifdef BUILD_RTI std::shared_ptr m_asmDtc; SituationMap::ElevationMapManager* m_elevationManager{nullptr}; #endif QStringList m_filePaths_rough_to_fine; }; LtsElevationManager::LtsElevationManager() : QObject(nullptr) , d(new Private) , m_logger(getLogger("LtsElevationManager")) { ++s_counter; TRACE_LOG(m_logger) << Q_FUNC_INFO << " START, s_counter=" << s_counter << " this=" << this; TRACE_LOG(m_logger) << Q_FUNC_INFO << " END, s_counter=" << s_counter << " this=" << this; } LtsElevationManager::~LtsElevationManager() { --s_counter; TRACE_LOG(m_logger) << Q_FUNC_INFO << " START, s_counter=" << s_counter << " this=" << this; delete d; TRACE_LOG(m_logger) << Q_FUNC_INFO << " END, s_counter=" << s_counter << " this=" << this; } LTS_ELEVATION_MANAGER_TYPE LtsElevationManager::createInstance(int exerciseId, const std::shared_ptr& exmDtc, #ifdef BUILD_RTI const std::shared_ptr& asmDtc #else const std::shared_ptr& asmDtc #endif ) { LOGGER_T logger = getLogger("LtsElevationManager"); TRACE_LOG(logger) << Q_FUNC_INFO << " START, exerciseId=" << exerciseId; if (exerciseId < 0) { ERROR_LOG(logger) << Q_FUNC_INFO << " exerciseId invalid, exerciseId=" << exerciseId; return nullptr; } // Qt5 logic restored (the qt6 port had dropped the exerciseId->trainingAreaId // caching and always returned nullptr here). #ifdef BUILD_RTI int trainingAreaId = -1; // remember for future calls // (so createInstance should work WITHOUT dtcs) // Idea: MainHandler: createInstance with exerciseId and valid dtcs // Plugin or simular: createInstance with exerciseId and no dtcs static QHash s_exIdToTaIdStore; const auto exTaIt = s_exIdToTaIdStore.find(exerciseId); if (exTaIt != s_exIdToTaIdStore.end()) { // CASE 1: // already created: trainingAreaId = *exTaIt; } else { // CASE 2: // ... or create on demand: if (!exmDtc || !asmDtc) { ERROR_LOG(logger) << Q_FUNC_INFO << " no dtcs for exerciseId=" << exerciseId << ", asmDtc=" << asmDtc << ", exmDtc=" << exmDtc; return nullptr; } // exId to taId trainingAreaId = exerciseIdToTrainingAreaId(exerciseId, exmDtc); if (trainingAreaId <= 0) { ERROR_LOG(logger) << Q_FUNC_INFO << " Error getting trainingAreaId" << ", exerciseId=" << exerciseId << ", trainingAreaId=" << trainingAreaId; return nullptr; } // store and remember: s_exIdToTaIdStore[exerciseId] = trainingAreaId; } // CASE 1: Following should work even with invalid asmDtc: LTS_ELEVATION_MANAGER_TYPE temp = createInstanceForTrainingAreaId(trainingAreaId, asmDtc); if (!temp) { ERROR_LOG(logger) << Q_FUNC_INFO << " Error on createInstanceForTrainingAreaId" << ", exerciseId=" << exerciseId << ", trainingAreaId=" << trainingAreaId; return nullptr; } // add exmDtc temp->initDDS(exmDtc, asmDtc); TRACE_LOG(logger) << Q_FUNC_INFO << " END, exerciseId=" << exerciseId; return temp; #else Q_UNUSED(exmDtc); Q_UNUSED(asmDtc); ERROR_LOG(logger) << Q_FUNC_INFO << " BUILD_RTI=OFF, cannot create instance"; return nullptr; #endif } LTS_ELEVATION_MANAGER_TYPE LtsElevationManager::getInstance(int exerciseId) { return LtsElevationManager::createInstance(exerciseId); } #ifdef BUILD_RTI LTS_ELEVATION_MANAGER_TYPE LtsElevationManager::createInstanceForTrainingAreaId(int trainingAreaId, const std::shared_ptr& asmDtc) { LOGGER_T logger = getLogger("LtsElevationManager"); TRACE_LOG(logger) << Q_FUNC_INFO << " START, trainingAreaId=" << trainingAreaId; if (trainingAreaId < 0) { ERROR_LOG(logger) << Q_FUNC_INFO << " trainingAreaId invalid, trainingAreaId=" << trainingAreaId; return nullptr; } LtsElevatioMgrMapTrainingAreaId& map = getLtsElevationMgrMapTrainingAreaId(); QMap::iterator it = map.find(trainingAreaId); if (it != map.end()) { DEBUG_LOG(logger) << " LtsElevationMgrMap contains instances: " << map.size(); return it.value(); } if (!asmDtc) { ERROR_LOG(logger) << Q_FUNC_INFO << " no dtcs for trainingAreaId=" << trainingAreaId << ", asmDtc=" << asmDtc; return nullptr; } LTS_ELEVATION_MANAGER_TYPE temp = new LtsElevationManager(); temp->initDDS(nullptr, asmDtc); const QStringList& filenames = temp->getFilenamesForTrainingArea(trainingAreaId); if (filenames.isEmpty()) { ERROR_LOG(logger) << Q_FUNC_INFO << " no filenames for trainingAreaId=" << trainingAreaId; delete temp; return nullptr; } bool bInitFilenames = temp->init(filenames); if (!bInitFilenames) { ERROR_LOG(logger) << Q_FUNC_INFO << " bInitFilenames failed for trainingAreaId=" << trainingAreaId; delete temp; return nullptr; } map.insert(trainingAreaId, temp); DEBUG_LOG(logger) << " LtsElevationMgrMap contains instances now: " << map.size(); TRACE_LOG(logger) << Q_FUNC_INFO << " END, trainingAreaId=" << trainingAreaId; return map[trainingAreaId]; } #endif LTS_ELEVATION_MANAGER_TYPE LtsElevationManager::createInstanceUnitTest(int id, const QStringList& filePaths_rough_to_fine) { LOGGER_T logger = getLogger("LtsElevationManager"); LtsElevatioMgrMapTrainingAreaId& map = getLtsElevationMgrMapTrainingAreaId(); QMap::iterator it = map.find(id); if (it != map.end()) { DEBUG_LOG(logger) << " LtsElevationMgrMap contains instances: " << map.size(); return it.value(); } LTS_ELEVATION_MANAGER_TYPE temp = new LtsElevationManager(); bool bInitFilenames = temp->init(filePaths_rough_to_fine); if (!bInitFilenames) { ERROR_LOG(logger) << Q_FUNC_INFO << " bInitFilenames failed for id=" << id; delete temp; return nullptr; } map.insert(id, temp); DEBUG_LOG(logger) << " LtsElevationMgrMap contains instances now: " << map.size(); TRACE_LOG(logger) << Q_FUNC_INFO << " END, trainingAreaId=" << id; return map[id]; } void LtsElevationManager::cleanupAll() { LOGGER_T logger = getLogger("LtsElevationManager"); TRACE_LOG(logger) << Q_FUNC_INFO << " START"; cleanupLtsElevatioMgrMapTrainingAreaId(); TRACE_LOG(logger) << Q_FUNC_INFO << " END"; } #ifdef BUILD_RTI void LtsElevationManager::initDDS(const std::shared_ptr& exmDtc, const std::shared_ptr& asmDtc) { TRACE_LOG(m_logger) << Q_FUNC_INFO << " START"; d->m_exmDtc = exmDtc; if (d->m_exmDtc) d->m_exmDtc->waitForHistoricalDataExercise(1000); d->m_asmDtc = asmDtc; if (d->m_asmDtc) d->m_asmDtc->waitForHistoricalDataTrainingArea(1000); TRACE_LOG(m_logger) << Q_FUNC_INFO << " END"; } #else void LtsElevationManager::initDDS(const std::shared_ptr& exmDtc, const std::shared_ptr& asmDtc) { Q_UNUSED(exmDtc); Q_UNUSED(asmDtc); TRACE_LOG(m_logger) << Q_FUNC_INFO << " START (BUILD_RTI=OFF, no DDS init)"; // BUILD_RTI=OFF: No DDS initialization TRACE_LOG(m_logger) << Q_FUNC_INFO << " END"; } #endif #ifdef BUILD_RTI QStringList LtsElevationManager::getFilenamesForExercise(int exerciseId) { TRACE_LOG(m_logger) << Q_FUNC_INFO << " START"; if (!d->m_exmDtc || !d->m_asmDtc) { ERROR_LOG(m_logger) << Q_FUNC_INFO << " no dtcs" << ", exerciseId=" << exerciseId; return {}; } int trainingAreaId = exerciseIdToTrainingAreaId(exerciseId, d->m_exmDtc); if (trainingAreaId <= 0) { ERROR_LOG(m_logger) << Q_FUNC_INFO << " Error getting trainingAreaId" << ", exerciseId=" << exerciseId << ", trainingAreaId=" << trainingAreaId; return {}; } QStringList filePaths_rough_to_fine = getFilenamesForTrainingArea(trainingAreaId); TRACE_LOG(m_logger) << Q_FUNC_INFO << " END, filePaths_rough_to_fine=" << filePaths_rough_to_fine.join(QStringLiteral(";")); return filePaths_rough_to_fine; } QStringList LtsElevationManager::getFilenamesForTrainingArea(int trainingAreaId) { TRACE_LOG(m_logger) << Q_FUNC_INFO << " START"; if (!d->m_asmDtc) { ERROR_LOG(m_logger) << Q_FUNC_INFO << " no dtcs" << ", trainingAreaId=" << trainingAreaId; return {}; } QStringList filePaths_rough_to_fine; { d->m_asmDtc->waitForHistoricalDataTrainingArea(1000); const AssetManagement::TrainingArea& ta = d->m_asmDtc->trainingArea(trainingAreaId); if (ta.id != trainingAreaId) { ERROR_LOG(m_logger) << Q_FUNC_INFO << " Error on s_asmDtc->trainingArea" << ", trainingAreaId=" << trainingAreaId; return {}; } const std::vector& mdVec = ta.elevation; filePaths_rough_to_fine.reserve(mdVec.size()); for (const AssetManagement::MapDescription& md : std::as_const(mdVec)) { QUrl url(QString::fromStdString(md.url)); QString filePathAbs = url.toLocalFile(); if (QDir::isRelativePath(filePathAbs)) filePathAbs = SituationMap::getResourcePath() + QStringLiteral("/elevation/") + filePathAbs; filePaths_rough_to_fine.append(filePathAbs); } } TRACE_LOG(m_logger) << Q_FUNC_INFO << " END, filePaths_rough_to_fine=" << filePaths_rough_to_fine.join(QStringLiteral(";")); return filePaths_rough_to_fine; } #else QStringList LtsElevationManager::getFilenamesForExercise(int /*exerciseId*/) { ERROR_LOG(m_logger) << Q_FUNC_INFO << " BUILD_RTI=OFF, getFilenamesForExercise not available"; return {}; } QStringList LtsElevationManager::getFilenamesForTrainingArea(int /*trainingAreaId*/) { ERROR_LOG(m_logger) << Q_FUNC_INFO << " BUILD_RTI=OFF, getFilenamesForTrainingArea not available"; return {}; } #endif bool LtsElevationManager::init(const QStringList& filePaths_rough_to_fine) { #ifdef BUILD_RTI delete d->m_elevationManager; d->m_elevationManager = new SituationMap::ElevationMapManager(); int cnt = d->m_elevationManager->init(filePaths_rough_to_fine); if (cnt != filePaths_rough_to_fine.size()) { FATAL_LOG(m_logger) << Q_FUNC_INFO << " ERROR, not all files could be loaded !!!"; FATAL_LOG(m_logger) << Q_FUNC_INFO << " ERROR, not all files could be loaded !!!"; FATAL_LOG(m_logger) << Q_FUNC_INFO << " ERROR, not all files could be loaded !!!"; FATAL_LOG(m_logger) << Q_FUNC_INFO << " ERROR, not all files could be loaded !!!"; FATAL_LOG(m_logger) << Q_FUNC_INFO << " ERROR, not all files could be loaded !!!"; return false; } return true; #else Q_UNUSED(filePaths_rough_to_fine); ERROR_LOG(m_logger) << Q_FUNC_INFO << " BUILD_RTI=OFF, init not available"; return false; #endif } #ifdef BUILD_RTI int LtsElevationManager::exerciseIdToTrainingAreaId(int exerciseId, const std::shared_ptr& exmDtc) { LOGGER_T logger = getLogger("LtsElevationManager"); if (!exmDtc) { ERROR_LOG(logger) << Q_FUNC_INFO << " no dtcs" << ", exerciseId=" << exerciseId; return -1; } int trainingAreaId = -1; { exmDtc->waitForHistoricalDataExercise(1000); const ExerciseManagement::Exercise& exm = exmDtc->exercise(exerciseId); if (exm.id != exerciseId) { ERROR_LOG(logger) << Q_FUNC_INFO << " Error on m_exmDtc->exercise" << ", exerciseId=" << exerciseId; return -1; } trainingAreaId = exm.trainingAreaId; if (trainingAreaId <= 0) { ERROR_LOG(logger) << Q_FUNC_INFO << " Error getting trainingAreaId" << ", exerciseId=" << exerciseId << ", trainingAreaId=" << trainingAreaId; return -1; } } return trainingAreaId; } #else int LtsElevationManager::exerciseIdToTrainingAreaId(int exerciseId, const std::shared_ptr& exmDtc) { Q_UNUSED(exerciseId); Q_UNUSED(exmDtc); LOGGER_T logger = getLogger("LtsElevationManager"); ERROR_LOG(logger) << Q_FUNC_INFO << " BUILD_RTI=OFF, cannot convert exerciseId to trainingAreaId"; return -1; } #endif bool LtsElevationManager::waitForInitialization() { #ifdef BUILD_RTI if (!d->m_elevationManager) return false; return d->m_elevationManager->waitForInitialization(); #else ERROR_LOG(m_logger) << Q_FUNC_INFO << " BUILD_RTI=OFF, waitForInitialization not available"; return false; #endif } bool LtsElevationManager::isValid() const { #ifdef BUILD_RTI if (!d->m_elevationManager) return false; return d->m_elevationManager->isValid(); #else ERROR_LOG(m_logger) << Q_FUNC_INFO << " BUILD_RTI=OFF, isValid not available"; return false; #endif } double LtsElevationManager::elevation(double lon_rad, double lat_rad, double defaultValue, bool* bIsCovered) const { #ifdef BUILD_RTI if (!d->m_elevationManager) return defaultValue; return d->m_elevationManager->elevation(lon_rad, lat_rad, defaultValue, bIsCovered); #else Q_UNUSED(lon_rad); Q_UNUSED(lat_rad); Q_UNUSED(bIsCovered); ERROR_LOG(m_logger) << Q_FUNC_INFO << " BUILD_RTI=OFF, elevation not available"; return defaultValue; #endif } LineOfSight LtsElevationManager::lineOfSightCalculation(const LtsUtils::QPoint3D& startPointGeo_absZ, const LtsUtils::QPoint3D& endPointGeo_absZ) { #ifdef BUILD_RTI TRACE_LOG(m_logger) << Q_FUNC_INFO << " START" << ", startPointGeo_absZ = " << startPointGeo_absZ << ", endPointGeo_absZ = " << endPointGeo_absZ; if (!isValid()) { ERROR_LOG(m_logger) << Q_FUNC_INFO << " Error, LtsElevationManager not valid"; return LineOfSight::LOS_ERROR; } SituationMap::ElevationMapManager::LineOfSight eleMapMgrResult = d->m_elevationManager->lineOfSightCalculation(startPointGeo_absZ, endPointGeo_absZ); LtsElevation::LineOfSight result = static_cast(eleMapMgrResult); TRACE_LOG(m_logger) << Q_FUNC_INFO << " END" << ", startPointGeo = " << startPointGeo_absZ << ", endPointGeo = " << endPointGeo_absZ << " -> LineOfSight " << result; return result; #else Q_UNUSED(startPointGeo_absZ); Q_UNUSED(endPointGeo_absZ); ERROR_LOG(m_logger) << Q_FUNC_INFO << " BUILD_RTI=OFF, lineOfSightCalculation not available"; return LineOfSight::LOS_ERROR; #endif } LineOfSight LtsElevationManager::lineOfSightCalculation(const QPointF& startPointGeo, double startHat, const QPointF& endPointGeo, double endHat) { #ifdef BUILD_RTI TRACE_LOG(m_logger) << Q_FUNC_INFO << " START" << ", startPointGeo = " << startPointGeo << ", startHat = " << startHat << ", endPointGeo = " << endPointGeo << ", endHat = " << endHat; SituationMap::ElevationMapManager::LineOfSight eleMapMgrResult = d->m_elevationManager->lineOfSightCalculation(startPointGeo, startHat, endPointGeo, endHat); LtsElevation::LineOfSight result = static_cast(eleMapMgrResult); TRACE_LOG(m_logger) << Q_FUNC_INFO << " END" << ", startPointGeo = " << startPointGeo << ", startHat = " << startHat << ", endPointGeo = " << endPointGeo << ", endHat = " << endHat << " -> LineOfSight " << static_cast(eleMapMgrResult); return result; #else Q_UNUSED(startPointGeo); Q_UNUSED(startHat); Q_UNUSED(endPointGeo); Q_UNUSED(endHat); ERROR_LOG(m_logger) << Q_FUNC_INFO << " BUILD_RTI=OFF, lineOfSightCalculation not available"; return LineOfSight::LOS_ERROR; #endif } const QString toString(const LineOfSight& value) { switch (value) { case LineOfSight::LOS_UNDEFINED: return QStringLiteral("LOS_UNDEFINED"); case LineOfSight::LOS_ERROR: return QStringLiteral("LOS_ERROR"); case LineOfSight::LOS_VISIBLE: return QStringLiteral("LOS_VISIBLE"); case LineOfSight::LOS_INVISIBLE: return QStringLiteral("LOS_INVISIBLE"); } Q_ASSERT(false); return QStringLiteral("LineOfSightERROR"); } std::ostream& operator<<(std::ostream& stream, const LineOfSight value) { stream << toString(value).toStdString(); return stream; } } // namespace LtsElevation