diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index d213b4fd..089d6749 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -963,6 +963,13 @@ void MainWindowImpl::ConnectMapSignals() } }, Qt::QueuedConnection); + connect( + mapWidget, + &map::MapWidget::IncomingLevel2ElevationChanged, + this, + [this](float incomingElevation) + { level2SettingsWidget_->UpdateIncomingElevation(incomingElevation); }, + Qt::QueuedConnection); } } diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp index ec54b4cd..ed952ed7 100644 --- a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -271,6 +272,8 @@ public: common::Level3ProductCategoryMap availableCategoryMap_ {}; std::shared_mutex availableCategoryMutex_ {}; + float incomingLevel2Elevation_ {-90}; + std::unordered_map, boost::hash> @@ -450,6 +453,11 @@ float RadarProductManager::gate_size() const return (is_tdwr()) ? 150.0f : 250.0f; } +float RadarProductManager::incoming_level_2_elevation() const +{ + return p->incomingLevel2Elevation_; +} + std::string RadarProductManager::radar_id() const { return p->radarId_; @@ -1542,6 +1550,16 @@ RadarProductManager::GetLevel2Data(wsr88d::rda::DataBlockType dataBlockType, foundTime = std::chrono::floor( scwx::util::TimePoint(radarData0->modified_julian_date(), radarData0->collection_time())); + + const float incomingElevation = + std::dynamic_pointer_cast( + p->level2ChunksProviderManager_->provider_) + ->GetCurrentElevation(); + if (incomingElevation != p->incomingLevel2Elevation_) + { + p->incomingLevel2Elevation_ = incomingElevation; + Q_EMIT IncomingLevel2ElevationChanged(incomingElevation); + } } } else // It is not in the chunk provider, so get it from the archive @@ -1576,6 +1594,12 @@ RadarProductManager::GetLevel2Data(wsr88d::rda::DataBlockType dataBlockType, elevationCut = recordElevationCut; elevationCuts = std::move(recordElevationCuts); foundTime = collectionTime; + + if (p->incomingLevel2Elevation_ != -90) + { + p->incomingLevel2Elevation_ = -90; + Q_EMIT IncomingLevel2ElevationChanged(-90); + } } } } diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp index ee54f147..6efd125d 100644 --- a/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp @@ -43,10 +43,11 @@ public: [[nodiscard]] const std::vector& coordinates(common::RadialSize radialSize, bool smoothingEnabled) const; - [[nodiscard]] const scwx::util::time_zone* default_time_zone() const; - [[nodiscard]] bool is_tdwr() const; - [[nodiscard]] float gate_size() const; - [[nodiscard]] std::string radar_id() const; + [[nodiscard]] const scwx::util::time_zone* default_time_zone() const; + [[nodiscard]] float gate_size() const; + [[nodiscard]] float incoming_level_2_elevation() const; + [[nodiscard]] bool is_tdwr() const; + [[nodiscard]] std::string radar_id() const; [[nodiscard]] std::shared_ptr radar_site() const; void Initialize(); @@ -148,6 +149,7 @@ signals: void NewDataAvailable(common::RadarProductGroup group, const std::string& product, std::chrono::system_clock::time_point latestTime); + void IncomingLevel2ElevationChanged(float incomingElevation); private: std::unique_ptr p; diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp index dafa801c..edb4c3d2 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -656,6 +656,12 @@ std::vector MapWidget::GetElevationCuts() const } } +float MapWidget::GetIncomingLevel2Elevation() const +{ + return p->radarProductManager_->incoming_level_2_elevation(); +} + + common::Level2Product MapWidgetImpl::GetLevel2ProductOrDefault(const std::string& productName) const { @@ -1796,6 +1802,14 @@ void MapWidgetImpl::RadarProductManagerConnect() { if (radarProductManager_ != nullptr) { + connect(radarProductManager_.get(), + &manager::RadarProductManager::IncomingLevel2ElevationChanged, + this, + [this](float incomingElevation) + { + Q_EMIT widget_->IncomingLevel2ElevationChanged( + incomingElevation); + }); connect(radarProductManager_.get(), &manager::RadarProductManager::Level3ProductsChanged, this, @@ -1916,6 +1930,10 @@ void MapWidgetImpl::RadarProductManagerDisconnect() &manager::RadarProductManager::NewDataAvailable, this, nullptr); + disconnect(radarProductManager_.get(), + &manager::RadarProductManager::IncomingLevel2ElevationChanged, + this, + nullptr); } } diff --git a/scwx-qt/source/scwx/qt/map/map_widget.hpp b/scwx-qt/source/scwx/qt/map/map_widget.hpp index 845832e4..5cc2e0a1 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.hpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.hpp @@ -45,6 +45,7 @@ public: GetAvailableLevel3Categories(); [[nodiscard]] std::optional GetElevation() const; [[nodiscard]] std::vector GetElevationCuts() const; + [[nodiscard]] float GetIncomingLevel2Elevation() const; [[nodiscard]] std::vector GetLevel3Products(); [[nodiscard]] std::string GetMapStyle() const; [[nodiscard]] common::RadarProductGroup GetRadarProductGroup() const; @@ -184,6 +185,7 @@ signals: void RadarSweepUpdated(); void RadarSweepNotUpdated(types::NoUpdateReason reason); void WidgetPainted(); + void IncomingLevel2ElevationChanged(float incomingElevation); }; } // namespace map diff --git a/scwx-qt/source/scwx/qt/ui/level2_settings_widget.cpp b/scwx-qt/source/scwx/qt/ui/level2_settings_widget.cpp index 1b851e72..4a3d0967 100644 --- a/scwx-qt/source/scwx/qt/ui/level2_settings_widget.cpp +++ b/scwx-qt/source/scwx/qt/ui/level2_settings_widget.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -30,6 +31,7 @@ public: self_ {self}, layout_ {new QVBoxLayout(self)}, elevationGroupBox_ {}, + incomingElevationLabel_ {}, elevationButtons_ {}, elevationCuts_ {}, elevationButtonsChanged_ {false}, @@ -39,10 +41,14 @@ public: { layout_->setContentsMargins(0, 0, 0, 0); + incomingElevationLabel_ = new QLabel("", self); + layout_->addWidget(incomingElevationLabel_); + elevationGroupBox_ = new QGroupBox(tr("Elevation"), self); new ui::FlowLayout(elevationGroupBox_); layout_->addWidget(elevationGroupBox_); + settingsGroupBox_ = new QGroupBox(tr("Settings"), self); QLayout* settingsLayout = new QVBoxLayout(settingsGroupBox_); layout_->addWidget(settingsGroupBox_); @@ -67,6 +73,7 @@ public: QLayout* layout_; QGroupBox* elevationGroupBox_; + QLabel* incomingElevationLabel_; std::list elevationButtons_; std::vector elevationCuts_; bool elevationButtonsChanged_; @@ -240,12 +247,19 @@ void Level2SettingsWidget::UpdateElevationSelection(float elevation) p->currentElevationButton_ = newElevationButton; } +void Level2SettingsWidget::UpdateIncomingElevation(float incomingElevation) +{ + p->incomingElevationLabel_->setText("Incoming Elevation: " + + QString::number(incomingElevation, 'f', 1) + common::Characters::DEGREE); +} + void Level2SettingsWidget::UpdateSettings(map::MapWidget* activeMap) { std::optional currentElevationOption = activeMap->GetElevation(); const float currentElevation = currentElevationOption.has_value() ? *currentElevationOption : 0.0f; std::vector elevationCuts = activeMap->GetElevationCuts(); + float incomingElevation = activeMap->GetIncomingLevel2Elevation(); if (p->elevationCuts_ != elevationCuts) { @@ -279,6 +293,7 @@ void Level2SettingsWidget::UpdateSettings(map::MapWidget* activeMap) } UpdateElevationSelection(currentElevation); + UpdateIncomingElevation(incomingElevation); } } // namespace ui diff --git a/scwx-qt/source/scwx/qt/ui/level2_settings_widget.hpp b/scwx-qt/source/scwx/qt/ui/level2_settings_widget.hpp index ce2e443f..796b1ade 100644 --- a/scwx-qt/source/scwx/qt/ui/level2_settings_widget.hpp +++ b/scwx-qt/source/scwx/qt/ui/level2_settings_widget.hpp @@ -23,6 +23,7 @@ public: void showEvent(QShowEvent* event) override; void UpdateElevationSelection(float elevation); + void UpdateIncomingElevation(float incomingElevation); void UpdateSettings(map::MapWidget* activeMap); signals: diff --git a/wxdata/include/scwx/provider/aws_level2_chunks_data_provider.hpp b/wxdata/include/scwx/provider/aws_level2_chunks_data_provider.hpp index 106b6605..a82dffb2 100644 --- a/wxdata/include/scwx/provider/aws_level2_chunks_data_provider.hpp +++ b/wxdata/include/scwx/provider/aws_level2_chunks_data_provider.hpp @@ -57,6 +57,8 @@ public: void RequestAvailableProducts() override; std::vector GetAvailableProducts() override; + float GetCurrentElevation(); + private: class Impl; std::unique_ptr p; diff --git a/wxdata/source/scwx/provider/aws_level2_chunks_data_provider.cpp b/wxdata/source/scwx/provider/aws_level2_chunks_data_provider.cpp index 02fdbca8..0d97c7b8 100644 --- a/wxdata/source/scwx/provider/aws_level2_chunks_data_provider.cpp +++ b/wxdata/source/scwx/provider/aws_level2_chunks_data_provider.cpp @@ -1,3 +1,4 @@ +#include "scwx/wsr88d/rda/digital_radar_data.hpp" #include #include #include @@ -704,4 +705,42 @@ AwsLevel2ChunksDataProvider::AwsLevel2ChunksDataProvider( AwsLevel2ChunksDataProvider& AwsLevel2ChunksDataProvider::operator=( AwsLevel2ChunksDataProvider&&) noexcept = default; +float AwsLevel2ChunksDataProvider::GetCurrentElevation() +{ + if (!p->currentScan_.valid_ || p->currentScan_.nexradFile_ == nullptr) + { + // Does not have any scan elevation. -90 is beyond what is possible + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + return -90; + } + + auto vcpData = p->currentScan_.nexradFile_->vcp_data(); + auto radarData = p->currentScan_.nexradFile_->radar_data(); + if (radarData.size() == 0) + { + // Does not have any scan elevation. -90 is beyond what is possible + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + return -90; + } + + const auto& lastElevation = radarData.crbegin(); + std::shared_ptr digitalRadarData0 = + std::dynamic_pointer_cast( + lastElevation->second->cbegin()->second); + + if (vcpData != nullptr) + { + // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions) Float is plenty + return vcpData->elevation_angle(lastElevation->first); + } + else if (digitalRadarData0 != nullptr) + { + return digitalRadarData0->elevation_angle().value(); + } + + // Does not have any scan elevation. -90 is beyond what is possible + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + return -90; +} + } // namespace scwx::provider