mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 06:20:06 +00:00 
			
		
		
		
	Merge pull request #418 from AdenKoperczak/modify_tilt_selection
This commit is contained in:
		
						commit
						44c37a8435
					
				
					 15 changed files with 380 additions and 220 deletions
				
			
		|  | @ -139,6 +139,8 @@ public: | ||||||
|    } |    } | ||||||
|    ~MainWindowImpl() |    ~MainWindowImpl() | ||||||
|    { |    { | ||||||
|  |       homeRadarConnection_.disconnect(); | ||||||
|  | 
 | ||||||
|       auto& generalSettings = settings::GeneralSettings::Instance(); |       auto& generalSettings = settings::GeneralSettings::Instance(); | ||||||
| 
 | 
 | ||||||
|       auto& customStyleUrl       = generalSettings.custom_style_url(); |       auto& customStyleUrl       = generalSettings.custom_style_url(); | ||||||
|  | @ -239,6 +241,8 @@ public: | ||||||
|         layerActions_ {}; |         layerActions_ {}; | ||||||
|    bool layerActionsInitialized_ {false}; |    bool layerActionsInitialized_ {false}; | ||||||
| 
 | 
 | ||||||
|  |    boost::signals2::scoped_connection homeRadarConnection_ {}; | ||||||
|  | 
 | ||||||
|    std::vector<map::MapWidget*> maps_; |    std::vector<map::MapWidget*> maps_; | ||||||
| 
 | 
 | ||||||
|    std::chrono::system_clock::time_point selectedTime_ {}; |    std::chrono::system_clock::time_point selectedTime_ {}; | ||||||
|  | @ -267,6 +271,7 @@ MainWindow::MainWindow(QWidget* parent) : | ||||||
|    ui->vcpLabel->setVisible(false); |    ui->vcpLabel->setVisible(false); | ||||||
|    ui->vcpValueLabel->setVisible(false); |    ui->vcpValueLabel->setVisible(false); | ||||||
|    ui->vcpDescriptionLabel->setVisible(false); |    ui->vcpDescriptionLabel->setVisible(false); | ||||||
|  |    ui->saveRadarProductsButton->setVisible(true); | ||||||
| 
 | 
 | ||||||
|    p->radarSitePresetsMenu_ = new QMenu(this); |    p->radarSitePresetsMenu_ = new QMenu(this); | ||||||
|    ui->radarSitePresetsButton->setMenu(p->radarSitePresetsMenu_); |    ui->radarSitePresetsButton->setMenu(p->radarSitePresetsMenu_); | ||||||
|  | @ -326,6 +331,8 @@ MainWindow::MainWindow(QWidget* parent) : | ||||||
|       ui->smoothRadarDataCheckBox); |       ui->smoothRadarDataCheckBox); | ||||||
|    p->mapSettingsGroup_->GetContentsLayout()->addWidget( |    p->mapSettingsGroup_->GetContentsLayout()->addWidget( | ||||||
|       ui->trackLocationCheckBox); |       ui->trackLocationCheckBox); | ||||||
|  |    p->mapSettingsGroup_->GetContentsLayout()->addWidget( | ||||||
|  |       ui->saveRadarProductsButton); | ||||||
|    ui->radarToolboxScrollAreaContents->layout()->replaceWidget( |    ui->radarToolboxScrollAreaContents->layout()->replaceWidget( | ||||||
|       ui->mapSettingsGroupBox, p->mapSettingsGroup_); |       ui->mapSettingsGroupBox, p->mapSettingsGroup_); | ||||||
|    ui->mapSettingsGroupBox->setVisible(false); |    ui->mapSettingsGroupBox->setVisible(false); | ||||||
|  | @ -1124,6 +1131,21 @@ void MainWindowImpl::ConnectOtherSignals() | ||||||
|               // Turn on location tracking
 |               // Turn on location tracking
 | ||||||
|               positionManager_->TrackLocation(trackingEnabled); |               positionManager_->TrackLocation(trackingEnabled); | ||||||
|            }); |            }); | ||||||
|  |    connect( | ||||||
|  |       mainWindow_->ui->saveRadarProductsButton, | ||||||
|  |       &QAbstractButton::clicked, | ||||||
|  |       mainWindow_, | ||||||
|  |       [this]() | ||||||
|  |       { | ||||||
|  |          auto& mapSettings = settings::MapSettings::Instance(); | ||||||
|  |          for (std::size_t i = 0; i < maps_.size(); i++) | ||||||
|  |          { | ||||||
|  |             const auto& map = maps_.at(i); | ||||||
|  |             mapSettings.radar_product_group(i).StageValue( | ||||||
|  |                common::GetRadarProductGroupName(map->GetRadarProductGroup())); | ||||||
|  |             mapSettings.radar_product(i).StageValue(map->GetRadarProductName()); | ||||||
|  |          } | ||||||
|  |       }); | ||||||
|    connect(level2ProductsWidget_, |    connect(level2ProductsWidget_, | ||||||
|            &ui::Level2ProductsWidget::RadarProductSelected, |            &ui::Level2ProductsWidget::RadarProductSelected, | ||||||
|            mainWindow_, |            mainWindow_, | ||||||
|  | @ -1255,6 +1277,28 @@ void MainWindowImpl::ConnectOtherSignals() | ||||||
|               timeLabel_->setVisible(true); |               timeLabel_->setVisible(true); | ||||||
|            }); |            }); | ||||||
|    clockTimer_.start(1000); |    clockTimer_.start(1000); | ||||||
|  | 
 | ||||||
|  |    auto& generalSettings = settings::GeneralSettings::Instance(); | ||||||
|  |    homeRadarConnection_ = | ||||||
|  |       generalSettings.default_radar_site().changed_signal().connect( | ||||||
|  |          [this]() | ||||||
|  |          { | ||||||
|  |             const std::shared_ptr<config::RadarSite> radarSite = | ||||||
|  |                activeMap_->GetRadarSite(); | ||||||
|  |             const std::string homeRadarSite = | ||||||
|  |                settings::GeneralSettings::Instance() | ||||||
|  |                   .default_radar_site() | ||||||
|  |                   .GetValue(); | ||||||
|  |             if (radarSite == nullptr) | ||||||
|  |             { | ||||||
|  |                mainWindow_->ui->saveRadarProductsButton->setVisible(false); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                mainWindow_->ui->saveRadarProductsButton->setVisible( | ||||||
|  |                   radarSite->id() == homeRadarSite); | ||||||
|  |             } | ||||||
|  |          }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindowImpl::InitializeLayerDisplayActions() | void MainWindowImpl::InitializeLayerDisplayActions() | ||||||
|  | @ -1509,6 +1553,8 @@ void MainWindowImpl::UpdateRadarProductSettings() | ||||||
| void MainWindowImpl::UpdateRadarSite() | void MainWindowImpl::UpdateRadarSite() | ||||||
| { | { | ||||||
|    std::shared_ptr<config::RadarSite> radarSite = activeMap_->GetRadarSite(); |    std::shared_ptr<config::RadarSite> radarSite = activeMap_->GetRadarSite(); | ||||||
|  |    const std::string                  homeRadarSite = | ||||||
|  |       settings::GeneralSettings::Instance().default_radar_site().GetValue(); | ||||||
| 
 | 
 | ||||||
|    if (radarSite != nullptr) |    if (radarSite != nullptr) | ||||||
|    { |    { | ||||||
|  | @ -1523,6 +1569,9 @@ void MainWindowImpl::UpdateRadarSite() | ||||||
|          radarSite->location_name().c_str()); |          radarSite->location_name().c_str()); | ||||||
| 
 | 
 | ||||||
|       timelineManager_->SetRadarSite(radarSite->id()); |       timelineManager_->SetRadarSite(radarSite->id()); | ||||||
|  | 
 | ||||||
|  |       mainWindow_->ui->saveRadarProductsButton->setVisible(radarSite->id() == | ||||||
|  |                                                            homeRadarSite); | ||||||
|    } |    } | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|  | @ -1530,6 +1579,7 @@ void MainWindowImpl::UpdateRadarSite() | ||||||
| 
 | 
 | ||||||
|       mainWindow_->ui->radarSiteValueLabel->setVisible(false); |       mainWindow_->ui->radarSiteValueLabel->setVisible(false); | ||||||
|       mainWindow_->ui->radarLocationLabel->setVisible(false); |       mainWindow_->ui->radarLocationLabel->setVisible(false); | ||||||
|  |       mainWindow_->ui->saveRadarProductsButton->setVisible(false); | ||||||
| 
 | 
 | ||||||
|       timelineManager_->SetRadarSite("?"); |       timelineManager_->SetRadarSite("?"); | ||||||
|    } |    } | ||||||
|  |  | ||||||
|  | @ -155,8 +155,8 @@ | ||||||
|          <rect> |          <rect> | ||||||
|           <x>0</x> |           <x>0</x> | ||||||
|           <y>0</y> |           <y>0</y> | ||||||
|           <width>190</width> |           <width>205</width> | ||||||
|           <height>680</height> |           <height>701</height> | ||||||
|          </rect> |          </rect> | ||||||
|         </property> |         </property> | ||||||
|         <layout class="QVBoxLayout" name="verticalLayout_6"> |         <layout class="QVBoxLayout" name="verticalLayout_6"> | ||||||
|  | @ -181,32 +181,24 @@ | ||||||
|             <enum>QFrame::Shadow::Raised</enum> |             <enum>QFrame::Shadow::Raised</enum> | ||||||
|            </property> |            </property> | ||||||
|            <layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0,0,0"> |            <layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0,0,0"> | ||||||
|             <item row="0" column="2"> |             <item row="3" column="2" colspan="3"> | ||||||
|              <widget class="QLabel" name="radarSiteValueLabel"> |              <widget class="QLabel" name="vcpValueLabel"> | ||||||
|               <property name="sizePolicy"> |  | ||||||
|                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> |  | ||||||
|                 <horstretch>0</horstretch> |  | ||||||
|                 <verstretch>0</verstretch> |  | ||||||
|                </sizepolicy> |  | ||||||
|               </property> |  | ||||||
|               <property name="text"> |               <property name="text"> | ||||||
|                <string notr="true">KLSX</string> |                <string notr="true">35</string> | ||||||
|               </property> |               </property> | ||||||
|              </widget> |              </widget> | ||||||
|             </item> |             </item> | ||||||
|             <item row="3" column="0" colspan="2"> |             <item row="4" column="2" colspan="3"> | ||||||
|              <widget class="QLabel" name="vcpLabel"> |              <widget class="QLabel" name="vcpDescriptionLabel"> | ||||||
|               <property name="sizePolicy"> |  | ||||||
|                <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> |  | ||||||
|                 <horstretch>0</horstretch> |  | ||||||
|                 <verstretch>0</verstretch> |  | ||||||
|                </sizepolicy> |  | ||||||
|               </property> |  | ||||||
|               <property name="toolTip"> |  | ||||||
|                <string>Volume Coverage Pattern</string> |  | ||||||
|               </property> |  | ||||||
|               <property name="text"> |               <property name="text"> | ||||||
|                <string>VCP</string> |                <string>Clear Air Mode</string> | ||||||
|  |               </property> | ||||||
|  |              </widget> | ||||||
|  |             </item> | ||||||
|  |             <item row="1" column="2" colspan="3"> | ||||||
|  |              <widget class="QLabel" name="radarLocationLabel"> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string notr="true">St. Louis, MO</string> | ||||||
|               </property> |               </property> | ||||||
|              </widget> |              </widget> | ||||||
|             </item> |             </item> | ||||||
|  | @ -271,34 +263,6 @@ | ||||||
|               </layout> |               </layout> | ||||||
|              </widget> |              </widget> | ||||||
|             </item> |             </item> | ||||||
|             <item row="0" column="0" colspan="2"> |  | ||||||
|              <widget class="QLabel" name="radarSiteLabel"> |  | ||||||
|               <property name="text"> |  | ||||||
|                <string>Radar Site</string> |  | ||||||
|               </property> |  | ||||||
|              </widget> |  | ||||||
|             </item> |  | ||||||
|             <item row="1" column="2" colspan="3"> |  | ||||||
|              <widget class="QLabel" name="radarLocationLabel"> |  | ||||||
|               <property name="text"> |  | ||||||
|                <string notr="true">St. Louis, MO</string> |  | ||||||
|               </property> |  | ||||||
|              </widget> |  | ||||||
|             </item> |  | ||||||
|             <item row="3" column="2" colspan="3"> |  | ||||||
|              <widget class="QLabel" name="vcpValueLabel"> |  | ||||||
|               <property name="text"> |  | ||||||
|                <string notr="true">35</string> |  | ||||||
|               </property> |  | ||||||
|              </widget> |  | ||||||
|             </item> |  | ||||||
|             <item row="4" column="2" colspan="3"> |  | ||||||
|              <widget class="QLabel" name="vcpDescriptionLabel"> |  | ||||||
|               <property name="text"> |  | ||||||
|                <string>Clear Air Mode</string> |  | ||||||
|               </property> |  | ||||||
|              </widget> |  | ||||||
|             </item> |  | ||||||
|             <item row="0" column="3"> |             <item row="0" column="3"> | ||||||
|              <widget class="QToolButton" name="radarSiteSelectButton"> |              <widget class="QToolButton" name="radarSiteSelectButton"> | ||||||
|               <property name="maximumSize"> |               <property name="maximumSize"> | ||||||
|  | @ -312,6 +276,42 @@ | ||||||
|               </property> |               </property> | ||||||
|              </widget> |              </widget> | ||||||
|             </item> |             </item> | ||||||
|  |             <item row="3" column="0" colspan="2"> | ||||||
|  |              <widget class="QLabel" name="vcpLabel"> | ||||||
|  |               <property name="sizePolicy"> | ||||||
|  |                <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> | ||||||
|  |                 <horstretch>0</horstretch> | ||||||
|  |                 <verstretch>0</verstretch> | ||||||
|  |                </sizepolicy> | ||||||
|  |               </property> | ||||||
|  |               <property name="toolTip"> | ||||||
|  |                <string>Volume Coverage Pattern</string> | ||||||
|  |               </property> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string>VCP</string> | ||||||
|  |               </property> | ||||||
|  |              </widget> | ||||||
|  |             </item> | ||||||
|  |             <item row="0" column="0" colspan="2"> | ||||||
|  |              <widget class="QLabel" name="radarSiteLabel"> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string>Radar Site</string> | ||||||
|  |               </property> | ||||||
|  |              </widget> | ||||||
|  |             </item> | ||||||
|  |             <item row="0" column="2"> | ||||||
|  |              <widget class="QLabel" name="radarSiteValueLabel"> | ||||||
|  |               <property name="sizePolicy"> | ||||||
|  |                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> | ||||||
|  |                 <horstretch>0</horstretch> | ||||||
|  |                 <verstretch>0</verstretch> | ||||||
|  |                </sizepolicy> | ||||||
|  |               </property> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string notr="true">KLSX</string> | ||||||
|  |               </property> | ||||||
|  |              </widget> | ||||||
|  |             </item> | ||||||
|            </layout> |            </layout> | ||||||
|           </widget> |           </widget> | ||||||
|          </item> |          </item> | ||||||
|  | @ -345,6 +345,13 @@ | ||||||
|               </property> |               </property> | ||||||
|              </widget> |              </widget> | ||||||
|             </item> |             </item> | ||||||
|  |             <item> | ||||||
|  |              <widget class="QPushButton" name="saveRadarProductsButton"> | ||||||
|  |               <property name="text"> | ||||||
|  |                <string>Set As Default Products</string> | ||||||
|  |               </property> | ||||||
|  |              </widget> | ||||||
|  |             </item> | ||||||
|            </layout> |            </layout> | ||||||
|           </widget> |           </widget> | ||||||
|          </item> |          </item> | ||||||
|  |  | ||||||
|  | @ -98,7 +98,8 @@ public: | ||||||
|        prevLongitude_ {0.0}, |        prevLongitude_ {0.0}, | ||||||
|        prevZoom_ {0.0}, |        prevZoom_ {0.0}, | ||||||
|        prevBearing_ {0.0}, |        prevBearing_ {0.0}, | ||||||
|        prevPitch_ {0.0} |        prevPitch_ {0.0}, | ||||||
|  |        tiltsToIndices_ {} | ||||||
|    { |    { | ||||||
|       // Create views
 |       // Create views
 | ||||||
|       auto overlayProductView = std::make_shared<view::OverlayProductView>(); |       auto overlayProductView = std::make_shared<view::OverlayProductView>(); | ||||||
|  | @ -273,6 +274,9 @@ public: | ||||||
|    bool productAvailabilityUpdated_ {false}; |    bool productAvailabilityUpdated_ {false}; | ||||||
|    bool productAvailabilityProductSelected_ {false}; |    bool productAvailabilityProductSelected_ {false}; | ||||||
| 
 | 
 | ||||||
|  |    std::unordered_map<std::string, size_t> tiltsToIndices_; | ||||||
|  |    size_t                                  currentTiltIndex_ {0}; | ||||||
|  | 
 | ||||||
| public slots: | public slots: | ||||||
|    void Update(); |    void Update(); | ||||||
| }; | }; | ||||||
|  | @ -611,7 +615,7 @@ common::Level3ProductCategoryMap MapWidget::GetAvailableLevel3Categories() | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| float MapWidget::GetElevation() const | std::optional<float> MapWidget::GetElevation() const | ||||||
| { | { | ||||||
|    auto radarProductView = p->context_->radar_product_view(); |    auto radarProductView = p->context_->radar_product_view(); | ||||||
| 
 | 
 | ||||||
|  | @ -621,7 +625,7 @@ float MapWidget::GetElevation() const | ||||||
|    } |    } | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|       return 0.0f; |       return {}; | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -829,6 +833,17 @@ void MapWidget::SelectRadarProduct(common::RadarProductGroup group, | ||||||
|       productCode = common::GetLevel3ProductCodeByAwipsId(productName); |       productCode = common::GetLevel3ProductCodeByAwipsId(productName); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  |    if (group == common::RadarProductGroup::Level3) | ||||||
|  |    { | ||||||
|  |       const auto& tiltIndex = p->tiltsToIndices_.find(productName); | ||||||
|  |       p->currentTiltIndex_ = | ||||||
|  |          tiltIndex != p->tiltsToIndices_.cend() ? tiltIndex->second : 0; | ||||||
|  |    } | ||||||
|  |    else | ||||||
|  |    { | ||||||
|  |       p->currentTiltIndex_ = 0; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    if (radarProductView == nullptr || |    if (radarProductView == nullptr || | ||||||
|        radarProductView->GetRadarProductGroup() != group || |        radarProductView->GetRadarProductGroup() != group || | ||||||
|        (radarProductView->GetRadarProductGroup() == |        (radarProductView->GetRadarProductGroup() == | ||||||
|  | @ -933,11 +948,6 @@ void MapWidget::SelectRadarSite(std::shared_ptr<config::RadarSite> radarSite, | ||||||
|       if (radarProductView != nullptr) |       if (radarProductView != nullptr) | ||||||
|       { |       { | ||||||
|          radarProductView->set_radar_product_manager(p->radarProductManager_); |          radarProductView->set_radar_product_manager(p->radarProductManager_); | ||||||
|          SelectRadarProduct(radarProductView->GetRadarProductGroup(), |  | ||||||
|                             radarProductView->GetRadarProductName(), |  | ||||||
|                             0, |  | ||||||
|                             radarProductView->selected_time(), |  | ||||||
|                             false); |  | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       p->AddLayers(); |       p->AddLayers(); | ||||||
|  | @ -1756,6 +1766,24 @@ void MapWidgetImpl::RadarProductManagerConnect() | ||||||
|               this, |               this, | ||||||
|               [this]() |               [this]() | ||||||
|               { |               { | ||||||
|  |                  const common::Level3ProductCategoryMap& categoryMap = | ||||||
|  |                     widget_->GetAvailableLevel3Categories(); | ||||||
|  | 
 | ||||||
|  |                  tiltsToIndices_.clear(); | ||||||
|  |                  for (const auto& category : categoryMap) | ||||||
|  |                  { | ||||||
|  |                     for (const auto& product : category.second) | ||||||
|  |                     { | ||||||
|  |                        for (size_t tiltIndex = 0; | ||||||
|  |                             tiltIndex < product.second.size(); | ||||||
|  |                             tiltIndex++) | ||||||
|  |                        { | ||||||
|  |                           tiltsToIndices_.emplace(product.second[tiltIndex], | ||||||
|  |                                                   tiltIndex); | ||||||
|  |                        } | ||||||
|  |                     } | ||||||
|  |                  } | ||||||
|  | 
 | ||||||
|                  productAvailabilityUpdated_ = true; |                  productAvailabilityUpdated_ = true; | ||||||
|                  CheckLevel3Availability(); |                  CheckLevel3Availability(); | ||||||
|                  Q_EMIT widget_->Level3ProductsChanged(); |                  Q_EMIT widget_->Level3ProductsChanged(); | ||||||
|  | @ -2058,7 +2086,7 @@ void MapWidgetImpl::CheckLevel3Availability() | ||||||
|     * has been updated |     * has been updated | ||||||
|     * |     * | ||||||
|     * productAvailabilityProductSelected_ Only update once the radar site is |     * productAvailabilityProductSelected_ Only update once the radar site is | ||||||
|     * fully selected, including the current product |     * fully selected | ||||||
|     */ |     */ | ||||||
|    if (!(productAvailabilityCheckNeeded_ && productAvailabilityUpdated_ && |    if (!(productAvailabilityCheckNeeded_ && productAvailabilityUpdated_ && | ||||||
|          productAvailabilityProductSelected_)) |          productAvailabilityProductSelected_)) | ||||||
|  | @ -2067,9 +2095,21 @@ void MapWidgetImpl::CheckLevel3Availability() | ||||||
|    } |    } | ||||||
|    productAvailabilityCheckNeeded_ = false; |    productAvailabilityCheckNeeded_ = false; | ||||||
| 
 | 
 | ||||||
|  |    // Get radar product view for fallback and level2 selection
 | ||||||
|  |    auto radarProductView = context_->radar_product_view(); | ||||||
|  |    if (radarProductView == nullptr) | ||||||
|  |    { | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    // Only do this for level3 products
 |    // Only do this for level3 products
 | ||||||
|    if (widget_->GetRadarProductGroup() != common::RadarProductGroup::Level3) |    if (widget_->GetRadarProductGroup() != common::RadarProductGroup::Level3) | ||||||
|    { |    { | ||||||
|  |       widget_->SelectRadarProduct(radarProductView->GetRadarProductGroup(), | ||||||
|  |                                   radarProductView->GetRadarProductName(), | ||||||
|  |                                   0, | ||||||
|  |                                   radarProductView->selected_time(), | ||||||
|  |                                   false); | ||||||
|       return; |       return; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  | @ -2083,6 +2123,12 @@ void MapWidgetImpl::CheckLevel3Availability() | ||||||
|       common::GetLevel3CategoryByProduct(productName); |       common::GetLevel3CategoryByProduct(productName); | ||||||
|    if (productCategory == common::Level3ProductCategory::Unknown) |    if (productCategory == common::Level3ProductCategory::Unknown) | ||||||
|    { |    { | ||||||
|  |       // Default to the same as already selected
 | ||||||
|  |       widget_->SelectRadarProduct(radarProductView->GetRadarProductGroup(), | ||||||
|  |                                   radarProductView->GetRadarProductName(), | ||||||
|  |                                   0, | ||||||
|  |                                   radarProductView->selected_time(), | ||||||
|  |                                   false); | ||||||
|       return; |       return; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  | @ -2090,38 +2136,53 @@ void MapWidgetImpl::CheckLevel3Availability() | ||||||
|    // Has no products in this category, do not change categories
 |    // Has no products in this category, do not change categories
 | ||||||
|    if (availableProductsIt == categoryMap.cend()) |    if (availableProductsIt == categoryMap.cend()) | ||||||
|    { |    { | ||||||
|  |       // Default to the same as already selected
 | ||||||
|  |       widget_->SelectRadarProduct(radarProductView->GetRadarProductGroup(), | ||||||
|  |                                   radarProductView->GetRadarProductName(), | ||||||
|  |                                   0, | ||||||
|  |                                   radarProductView->selected_time(), | ||||||
|  |                                   false); | ||||||
|       return; |       return; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    const auto& availableProducts = availableProductsIt->second; |    const auto& availableProducts = availableProductsIt->second; | ||||||
|    const auto& availableTiltsIt  = availableProducts.find(productName); |    const auto& availableTiltsIt  = availableProducts.find(productName); | ||||||
|    // Does not have the same product, but has others in the same category.
 |  | ||||||
|    // Switch to the default product and tilt in this category.
 |  | ||||||
|    if (availableTiltsIt == availableProducts.cend()) |  | ||||||
|    { |  | ||||||
|       widget_->SelectRadarProduct( |  | ||||||
|          common::RadarProductGroup::Level3, |  | ||||||
|          common::GetLevel3CategoryDefaultProduct(productCategory, categoryMap), |  | ||||||
|          0, |  | ||||||
|          widget_->GetSelectedTime()); |  | ||||||
|       return; |  | ||||||
|    } |  | ||||||
| 
 | 
 | ||||||
|    const auto& availableTilts = availableTiltsIt->second; |    const auto& availableTilts = | ||||||
|    const auto& tilt           = std::ranges::find_if( |       availableTiltsIt == availableProducts.cend() ? | ||||||
|       availableTilts, |          // Does not have the same product, but has others in the same category.
 | ||||||
|       [productTilt](const std::string& tilt) { return productTilt == tilt; }); |          // Switch to the default product and tilt in this category.
 | ||||||
|    // Tilt is not available, set it to first tilt
 |          availableProducts.at(common::GetLevel3ProductByAwipsId( | ||||||
|    if (tilt == availableTilts.cend() && availableTilts.size() > 0) |             common::GetLevel3CategoryDefaultProduct(productCategory, | ||||||
|  |                                                     categoryMap))) : | ||||||
|  |          // Has the same product
 | ||||||
|  |          availableTiltsIt->second; | ||||||
|  | 
 | ||||||
|  |    // Try to match the tilt to the last tilt.
 | ||||||
|  |    if (currentTiltIndex_ < availableTilts.size()) | ||||||
|    { |    { | ||||||
|       widget_->SelectRadarProduct(common::RadarProductGroup::Level3, |       widget_->SelectRadarProduct(common::RadarProductGroup::Level3, | ||||||
|                                   availableTilts[0], |                                   availableTilts[currentTiltIndex_], | ||||||
|                                   0, |                                   0, | ||||||
|                                   widget_->GetSelectedTime()); |                                   widget_->GetSelectedTime()); | ||||||
|       return; |  | ||||||
|    } |    } | ||||||
| 
 |    else if (availableTilts.size() > 0) | ||||||
|    // Tilt is available, no change needed
 |    { | ||||||
|  |       widget_->SelectRadarProduct(common::RadarProductGroup::Level3, | ||||||
|  |                                   availableTilts[availableTilts.size() - 1], | ||||||
|  |                                   0, | ||||||
|  |                                   widget_->GetSelectedTime()); | ||||||
|  |    } | ||||||
|  |    else | ||||||
|  |    { | ||||||
|  |       // No tilts available in this case, default to the same as already
 | ||||||
|  |       // selected
 | ||||||
|  |       widget_->SelectRadarProduct(radarProductView->GetRadarProductGroup(), | ||||||
|  |                                   radarProductView->GetRadarProductName(), | ||||||
|  |                                   0, | ||||||
|  |                                   radarProductView->selected_time(), | ||||||
|  |                                   false); | ||||||
|  |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace map
 | } // namespace map
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <chrono> | #include <chrono> | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include <optional> | ||||||
| 
 | 
 | ||||||
| #include <qmaplibre.hpp> | #include <qmaplibre.hpp> | ||||||
| 
 | 
 | ||||||
|  | @ -41,7 +42,7 @@ public: | ||||||
| 
 | 
 | ||||||
|    [[nodiscard]] common::Level3ProductCategoryMap |    [[nodiscard]] common::Level3ProductCategoryMap | ||||||
|                                            GetAvailableLevel3Categories(); |                                            GetAvailableLevel3Categories(); | ||||||
|    [[nodiscard]] float                     GetElevation() const; |    [[nodiscard]] std::optional<float>      GetElevation() const; | ||||||
|    [[nodiscard]] std::vector<float>        GetElevationCuts() const; |    [[nodiscard]] std::vector<float>        GetElevationCuts() const; | ||||||
|    [[nodiscard]] std::vector<std::string>  GetLevel3Products(); |    [[nodiscard]] std::vector<std::string>  GetLevel3Products(); | ||||||
|    [[nodiscard]] std::string               GetMapStyle() const; |    [[nodiscard]] std::string               GetMapStyle() const; | ||||||
|  |  | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | #include <scwx/common/characters.hpp> | ||||||
| #include <scwx/qt/gl/draw/geo_icons.hpp> | #include <scwx/qt/gl/draw/geo_icons.hpp> | ||||||
| #include <scwx/qt/gl/draw/icons.hpp> | #include <scwx/qt/gl/draw/icons.hpp> | ||||||
| #include <scwx/qt/gl/draw/rectangle.hpp> | #include <scwx/qt/gl/draw/rectangle.hpp> | ||||||
|  | @ -426,7 +427,9 @@ void OverlayLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) | ||||||
|    if (radarProductView != nullptr) |    if (radarProductView != nullptr) | ||||||
|    { |    { | ||||||
|       // Render product name
 |       // Render product name
 | ||||||
|       std::string productName = radarProductView->GetRadarProductName(); |       const std::string productName = radarProductView->GetRadarProductName(); | ||||||
|  |       const std::optional<float> elevation = radarProductView->elevation(); | ||||||
|  | 
 | ||||||
|       if (productName.length() > 0 && !productName.starts_with('?')) |       if (productName.length() > 0 && !productName.starts_with('?')) | ||||||
|       { |       { | ||||||
|          ImGui::SetNextWindowPos(ImVec2 {0.0f, 0.0f}); |          ImGui::SetNextWindowPos(ImVec2 {0.0f, 0.0f}); | ||||||
|  | @ -434,7 +437,21 @@ void OverlayLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) | ||||||
|                       nullptr, |                       nullptr, | ||||||
|                       ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | |                       ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | | ||||||
|                          ImGuiWindowFlags_AlwaysAutoResize); |                          ImGuiWindowFlags_AlwaysAutoResize); | ||||||
|          ImGui::TextUnformatted(productName.c_str()); | 
 | ||||||
|  |          if (elevation.has_value()) | ||||||
|  |          { | ||||||
|  |             const std::string elevationString = | ||||||
|  |                (QString::number(*elevation, 'f', 1) + | ||||||
|  |                 common::Characters::DEGREE) | ||||||
|  |                   .toStdString(); | ||||||
|  |             ImGui::TextUnformatted( | ||||||
|  |                fmt::format("{} ({})", productName, elevationString).c_str()); | ||||||
|  |          } | ||||||
|  |          else | ||||||
|  |          { | ||||||
|  |             ImGui::TextUnformatted(productName.c_str()); | ||||||
|  |          } | ||||||
|  | 
 | ||||||
|          ImGui::End(); |          ImGui::End(); | ||||||
|       } |       } | ||||||
|    } |    } | ||||||
|  |  | ||||||
|  | @ -76,7 +76,7 @@ public: | ||||||
|             { |             { | ||||||
|                common::RadarProductGroup radarProductGroup = |                common::RadarProductGroup radarProductGroup = | ||||||
|                   common::GetRadarProductGroup( |                   common::GetRadarProductGroup( | ||||||
|                      map_.at(i).radarProductGroup_.GetValue()); |                      map_.at(i).radarProductGroup_.GetStagedOrValue()); | ||||||
| 
 | 
 | ||||||
|                if (radarProductGroup == common::RadarProductGroup::Level2) |                if (radarProductGroup == common::RadarProductGroup::Level2) | ||||||
|                { |                { | ||||||
|  | @ -193,6 +193,8 @@ bool MapSettings::Shutdown() | ||||||
| 
 | 
 | ||||||
|       dataChanged |= mapRecordSettings.mapStyle_.Commit(); |       dataChanged |= mapRecordSettings.mapStyle_.Commit(); | ||||||
|       dataChanged |= mapRecordSettings.smoothingEnabled_.Commit(); |       dataChanged |= mapRecordSettings.smoothingEnabled_.Commit(); | ||||||
|  |       dataChanged |= mapRecordSettings.radarProductGroup_.Commit(); | ||||||
|  |       dataChanged |= mapRecordSettings.radarProduct_.Commit(); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    return dataChanged; |    return dataChanged; | ||||||
|  |  | ||||||
|  | @ -242,7 +242,9 @@ void Level2SettingsWidget::UpdateElevationSelection(float elevation) | ||||||
| 
 | 
 | ||||||
| void Level2SettingsWidget::UpdateSettings(map::MapWidget* activeMap) | void Level2SettingsWidget::UpdateSettings(map::MapWidget* activeMap) | ||||||
| { | { | ||||||
|    float              currentElevation = activeMap->GetElevation(); |    std::optional<float> currentElevationOption = activeMap->GetElevation(); | ||||||
|  |    const float          currentElevation = | ||||||
|  |       currentElevationOption.has_value() ? *currentElevationOption : 0.0f; | ||||||
|    std::vector<float> elevationCuts    = activeMap->GetElevationCuts(); |    std::vector<float> elevationCuts    = activeMap->GetElevationCuts(); | ||||||
| 
 | 
 | ||||||
|    if (p->elevationCuts_ != elevationCuts) |    if (p->elevationCuts_ != elevationCuts) | ||||||
|  |  | ||||||
|  | @ -271,7 +271,7 @@ uint16_t Level2ProductView::color_table_max() const | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| float Level2ProductView::elevation() const | std::optional<float> Level2ProductView::elevation() const | ||||||
| { | { | ||||||
|    return p->elevationCut_; |    return p->elevationCut_; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,11 +8,7 @@ | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx::qt::view | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace view |  | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| class Level2ProductView : public RadarProductView | class Level2ProductView : public RadarProductView | ||||||
|  | @ -23,38 +19,47 @@ public: | ||||||
|    explicit Level2ProductView( |    explicit Level2ProductView( | ||||||
|       common::Level2Product                         product, |       common::Level2Product                         product, | ||||||
|       std::shared_ptr<manager::RadarProductManager> radarProductManager); |       std::shared_ptr<manager::RadarProductManager> radarProductManager); | ||||||
|    ~Level2ProductView(); |    ~Level2ProductView() override; | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<common::ColorTable> color_table() const override; |    Level2ProductView(const Level2ProductView&)            = delete; | ||||||
|    const std::vector<boost::gil::rgba8_pixel_t>& |    Level2ProductView(Level2ProductView&&)                 = delete; | ||||||
|                                          color_table_lut() const override; |    Level2ProductView& operator=(const Level2ProductView&) = delete; | ||||||
|    std::uint16_t                         color_table_min() const override; |    Level2ProductView& operator=(Level2ProductView&&)      = delete; | ||||||
|    std::uint16_t                         color_table_max() const override; | 
 | ||||||
|    float                                 elevation() const override; |    [[nodiscard]] std::shared_ptr<common::ColorTable> | ||||||
|    float                                 range() const override; |    color_table() const override; | ||||||
|    std::chrono::system_clock::time_point sweep_time() const override; |    [[nodiscard]] const std::vector<boost::gil::rgba8_pixel_t>& | ||||||
|    float                                 unit_scale() const override; |                                       color_table_lut() const override; | ||||||
|    std::string                           units() const override; |    [[nodiscard]] std::uint16_t        color_table_min() const override; | ||||||
|    std::uint16_t                         vcp() const override; |    [[nodiscard]] std::uint16_t        color_table_max() const override; | ||||||
|    const std::vector<float>&             vertices() const override; |    [[nodiscard]] std::optional<float> elevation() const override; | ||||||
|  |    [[nodiscard]] float                range() const override; | ||||||
|  |    [[nodiscard]] std::chrono::system_clock::time_point | ||||||
|  |                                            sweep_time() const override; | ||||||
|  |    [[nodiscard]] float                     unit_scale() const override; | ||||||
|  |    [[nodiscard]] std::string               units() const override; | ||||||
|  |    [[nodiscard]] std::uint16_t             vcp() const override; | ||||||
|  |    [[nodiscard]] const std::vector<float>& vertices() const override; | ||||||
| 
 | 
 | ||||||
|    void LoadColorTable(std::shared_ptr<common::ColorTable> colorTable) override; |    void LoadColorTable(std::shared_ptr<common::ColorTable> colorTable) override; | ||||||
|    void SelectElevation(float elevation) override; |    void SelectElevation(float elevation) override; | ||||||
|    void SelectProduct(const std::string& productName) override; |    void SelectProduct(const std::string& productName) override; | ||||||
| 
 | 
 | ||||||
|    common::RadarProductGroup GetRadarProductGroup() const override; |    [[nodiscard]] common::RadarProductGroup | ||||||
|    std::string               GetRadarProductName() const override; |                                     GetRadarProductGroup() const override; | ||||||
|    std::vector<float>        GetElevationCuts() const override; |    [[nodiscard]] std::string        GetRadarProductName() const override; | ||||||
|    std::tuple<const void*, std::size_t, std::size_t> |    [[nodiscard]] std::vector<float> GetElevationCuts() const override; | ||||||
|  |    [[nodiscard]] std::tuple<const void*, std::size_t, std::size_t> | ||||||
|    GetMomentData() const override; |    GetMomentData() const override; | ||||||
|    std::tuple<const void*, std::size_t, std::size_t> |    [[nodiscard]] std::tuple<const void*, std::size_t, std::size_t> | ||||||
|    GetCfpMomentData() const override; |    GetCfpMomentData() const override; | ||||||
| 
 | 
 | ||||||
|    std::optional<std::uint16_t> |    [[nodiscard]] std::optional<std::uint16_t> | ||||||
|    GetBinLevel(const common::Coordinate& coordinate) const override; |    GetBinLevel(const common::Coordinate& coordinate) const override; | ||||||
|    std::optional<wsr88d::DataLevelCode> |    [[nodiscard]] std::optional<wsr88d::DataLevelCode> | ||||||
|                         GetDataLevelCode(std::uint16_t level) const override; |    GetDataLevelCode(std::uint16_t level) const override; | ||||||
|    std::optional<float> GetDataValue(std::uint16_t level) const override; |    [[nodiscard]] std::optional<float> | ||||||
|  |    GetDataValue(std::uint16_t level) const override; | ||||||
| 
 | 
 | ||||||
|    static std::shared_ptr<Level2ProductView> |    static std::shared_ptr<Level2ProductView> | ||||||
|    Create(common::Level2Product                         product, |    Create(common::Level2Product                         product, | ||||||
|  | @ -75,6 +80,4 @@ private: | ||||||
|    std::unique_ptr<Impl> p; |    std::unique_ptr<Impl> p; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace view
 | } // namespace scwx::qt::view
 | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -67,6 +67,7 @@ public: | ||||||
| 
 | 
 | ||||||
|    float         latitude_; |    float         latitude_; | ||||||
|    float         longitude_; |    float         longitude_; | ||||||
|  |    std::optional<float> elevation_ {}; | ||||||
|    float         range_; |    float         range_; | ||||||
|    std::uint16_t vcp_; |    std::uint16_t vcp_; | ||||||
| 
 | 
 | ||||||
|  | @ -91,6 +92,11 @@ boost::asio::thread_pool& Level3RadialView::thread_pool() | ||||||
|    return p->threadPool_; |    return p->threadPool_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::optional<float> Level3RadialView::elevation() const | ||||||
|  | { | ||||||
|  |    return p->elevation_; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| float Level3RadialView::range() const | float Level3RadialView::range() const | ||||||
| { | { | ||||||
|    return p->range_; |    return p->range_; | ||||||
|  | @ -306,6 +312,10 @@ void Level3RadialView::ComputeSweep() | ||||||
|    p->latitude_  = descriptionBlock->latitude_of_radar(); |    p->latitude_  = descriptionBlock->latitude_of_radar(); | ||||||
|    p->longitude_ = descriptionBlock->longitude_of_radar(); |    p->longitude_ = descriptionBlock->longitude_of_radar(); | ||||||
|    p->range_     = descriptionBlock->range(); |    p->range_     = descriptionBlock->range(); | ||||||
|  |    p->elevation_ = | ||||||
|  |       descriptionBlock->has_elevation() ? | ||||||
|  |          static_cast<float>(descriptionBlock->elevation().value()) : | ||||||
|  |          std::optional<float> {}; | ||||||
|    p->sweepTime_ = |    p->sweepTime_ = | ||||||
|       scwx::util::TimePoint(descriptionBlock->volume_scan_date(), |       scwx::util::TimePoint(descriptionBlock->volume_scan_date(), | ||||||
|                             descriptionBlock->volume_scan_start_time() * 1000); |                             descriptionBlock->volume_scan_start_time() * 1000); | ||||||
|  |  | ||||||
|  | @ -6,11 +6,7 @@ | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx::qt::view | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace view |  | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| class Level3RadialView : public Level3ProductView | class Level3RadialView : public Level3ProductView | ||||||
|  | @ -21,17 +17,24 @@ public: | ||||||
|    explicit Level3RadialView( |    explicit Level3RadialView( | ||||||
|       const std::string&                            product, |       const std::string&                            product, | ||||||
|       std::shared_ptr<manager::RadarProductManager> radarProductManager); |       std::shared_ptr<manager::RadarProductManager> radarProductManager); | ||||||
|    ~Level3RadialView(); |    ~Level3RadialView() override; | ||||||
| 
 | 
 | ||||||
|    float                                 range() const override; |    Level3RadialView(const Level3RadialView&)            = delete; | ||||||
|    std::chrono::system_clock::time_point sweep_time() const override; |    Level3RadialView(Level3RadialView&&)                 = delete; | ||||||
|    std::uint16_t                         vcp() const override; |    Level3RadialView& operator=(const Level3RadialView&) = delete; | ||||||
|    const std::vector<float>&             vertices() const override; |    Level3RadialView& operator=(Level3RadialView&&)      = delete; | ||||||
| 
 | 
 | ||||||
|    std::tuple<const void*, std::size_t, std::size_t> |    [[nodiscard]] std::optional<float> elevation() const override; | ||||||
|  |    [[nodiscard]] float                range() const override; | ||||||
|  |    [[nodiscard]] std::chrono::system_clock::time_point | ||||||
|  |                                            sweep_time() const override; | ||||||
|  |    [[nodiscard]] std::uint16_t             vcp() const override; | ||||||
|  |    [[nodiscard]] const std::vector<float>& vertices() const override; | ||||||
|  | 
 | ||||||
|  |    [[nodiscard]] std::tuple<const void*, std::size_t, std::size_t> | ||||||
|    GetMomentData() const override; |    GetMomentData() const override; | ||||||
| 
 | 
 | ||||||
|    std::optional<std::uint16_t> |    [[nodiscard]] std::optional<std::uint16_t> | ||||||
|    GetBinLevel(const common::Coordinate& coordinate) const override; |    GetBinLevel(const common::Coordinate& coordinate) const override; | ||||||
| 
 | 
 | ||||||
|    static std::shared_ptr<Level3RadialView> |    static std::shared_ptr<Level3RadialView> | ||||||
|  | @ -49,6 +52,4 @@ private: | ||||||
|    std::unique_ptr<Impl> p; |    std::unique_ptr<Impl> p; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace view
 | } // namespace scwx::qt::view
 | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -85,9 +85,9 @@ std::uint16_t RadarProductView::color_table_max() const | ||||||
|    return kDefaultColorTableMax_; |    return kDefaultColorTableMax_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| float RadarProductView::elevation() const | std::optional<float> RadarProductView::elevation() const | ||||||
| { | { | ||||||
|    return 0.0f; |    return {}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::shared_ptr<manager::RadarProductManager> | std::shared_ptr<manager::RadarProductManager> | ||||||
|  |  | ||||||
|  | @ -16,11 +16,7 @@ | ||||||
| #include <QObject> | #include <QObject> | ||||||
| #include <boost/asio/thread_pool.hpp> | #include <boost/asio/thread_pool.hpp> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx::qt::view | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace view |  | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| class RadarProductViewImpl; | class RadarProductViewImpl; | ||||||
|  | @ -32,20 +28,27 @@ class RadarProductView : public QObject | ||||||
| public: | public: | ||||||
|    explicit RadarProductView( |    explicit RadarProductView( | ||||||
|       std::shared_ptr<manager::RadarProductManager> radarProductManager); |       std::shared_ptr<manager::RadarProductManager> radarProductManager); | ||||||
|    virtual ~RadarProductView(); |    ~RadarProductView() override; | ||||||
| 
 | 
 | ||||||
|    virtual std::shared_ptr<common::ColorTable> color_table() const = 0; |    RadarProductView(const RadarProductView&)            = delete; | ||||||
|    virtual const std::vector<boost::gil::rgba8_pixel_t>& |    RadarProductView(RadarProductView&&)                 = delete; | ||||||
|                                                  color_table_lut() const; |    RadarProductView& operator=(const RadarProductView&) = delete; | ||||||
|    virtual std::uint16_t                         color_table_min() const; |    RadarProductView& operator=(RadarProductView&&)      = delete; | ||||||
|    virtual std::uint16_t                         color_table_max() const; | 
 | ||||||
|    virtual float                                 elevation() const; |    [[nodiscard]] virtual std::shared_ptr<common::ColorTable> | ||||||
|    virtual float                                 range() const; |    color_table() const = 0; | ||||||
|    virtual std::chrono::system_clock::time_point sweep_time() const; |    [[nodiscard]] virtual const std::vector<boost::gil::rgba8_pixel_t>& | ||||||
|    virtual float                                 unit_scale() const = 0; |                                               color_table_lut() const; | ||||||
|    virtual std::string                           units() const      = 0; |    [[nodiscard]] virtual std::uint16_t        color_table_min() const; | ||||||
|    virtual std::uint16_t                         vcp() const        = 0; |    [[nodiscard]] virtual std::uint16_t        color_table_max() const; | ||||||
|    virtual const std::vector<float>&             vertices() const   = 0; |    [[nodiscard]] virtual std::optional<float> elevation() const; | ||||||
|  |    [[nodiscard]] virtual float                range() const; | ||||||
|  |    [[nodiscard]] virtual std::chrono::system_clock::time_point | ||||||
|  |                                                    sweep_time() const; | ||||||
|  |    [[nodiscard]] virtual float                     unit_scale() const = 0; | ||||||
|  |    [[nodiscard]] virtual std::string               units() const      = 0; | ||||||
|  |    [[nodiscard]] virtual std::uint16_t             vcp() const        = 0; | ||||||
|  |    [[nodiscard]] virtual const std::vector<float>& vertices() const   = 0; | ||||||
| 
 | 
 | ||||||
|    [[nodiscard]] std::shared_ptr<manager::RadarProductManager> |    [[nodiscard]] std::shared_ptr<manager::RadarProductManager> | ||||||
|    radar_product_manager() const; |    radar_product_manager() const; | ||||||
|  | @ -66,24 +69,26 @@ public: | ||||||
|    void         SelectTime(std::chrono::system_clock::time_point time); |    void         SelectTime(std::chrono::system_clock::time_point time); | ||||||
|    void         Update(); |    void         Update(); | ||||||
| 
 | 
 | ||||||
|    bool IsInitialized() const; |    [[nodiscard]] bool IsInitialized() const; | ||||||
| 
 | 
 | ||||||
|    virtual common::RadarProductGroup GetRadarProductGroup() const = 0; |    [[nodiscard]] virtual common::RadarProductGroup | ||||||
|    virtual std::string               GetRadarProductName() const  = 0; |                                             GetRadarProductGroup() const = 0; | ||||||
|    virtual std::vector<float>        GetElevationCuts() const; |    [[nodiscard]] virtual std::string        GetRadarProductName() const  = 0; | ||||||
|    virtual std::tuple<const void*, std::size_t, std::size_t> |    [[nodiscard]] virtual std::vector<float> GetElevationCuts() const; | ||||||
|  |    [[nodiscard]] virtual std::tuple<const void*, std::size_t, std::size_t> | ||||||
|    GetMomentData() const = 0; |    GetMomentData() const = 0; | ||||||
|    virtual std::tuple<const void*, std::size_t, std::size_t> |    [[nodiscard]] virtual std::tuple<const void*, std::size_t, std::size_t> | ||||||
|    GetCfpMomentData() const; |    GetCfpMomentData() const; | ||||||
| 
 | 
 | ||||||
|    virtual std::optional<std::uint16_t> |    [[nodiscard]] virtual std::optional<std::uint16_t> | ||||||
|    GetBinLevel(const common::Coordinate& coordinate) const = 0; |    GetBinLevel(const common::Coordinate& coordinate) const = 0; | ||||||
|    virtual std::optional<wsr88d::DataLevelCode> |    [[nodiscard]] virtual std::optional<wsr88d::DataLevelCode> | ||||||
|                                 GetDataLevelCode(std::uint16_t level) const = 0; |    GetDataLevelCode(std::uint16_t level) const = 0; | ||||||
|    virtual std::optional<float> GetDataValue(std::uint16_t level) const     = 0; |    [[nodiscard]] virtual std::optional<float> | ||||||
|    virtual bool                 IgnoreUnits() const; |                               GetDataValue(std::uint16_t level) const = 0; | ||||||
|  |    [[nodiscard]] virtual bool IgnoreUnits() const; | ||||||
| 
 | 
 | ||||||
|    virtual std::vector<std::pair<std::string, std::string>> |    [[nodiscard]] virtual std::vector<std::pair<std::string, std::string>> | ||||||
|    GetDescriptionFields() const; |    GetDescriptionFields() const; | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|  | @ -105,6 +110,4 @@ private: | ||||||
|    std::unique_ptr<RadarProductViewImpl> p; |    std::unique_ptr<RadarProductViewImpl> p; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace view
 | } // namespace scwx::qt::view
 | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -9,11 +9,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <units/angle.h> | #include <units/angle.h> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx::wsr88d::rpg | ||||||
| { |  | ||||||
| namespace wsr88d |  | ||||||
| { |  | ||||||
| namespace rpg |  | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| class ProductDescriptionBlockImpl; | class ProductDescriptionBlockImpl; | ||||||
|  | @ -22,7 +18,7 @@ class ProductDescriptionBlock : public awips::Message | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    explicit ProductDescriptionBlock(); |    explicit ProductDescriptionBlock(); | ||||||
|    ~ProductDescriptionBlock(); |    ~ProductDescriptionBlock() override; | ||||||
| 
 | 
 | ||||||
|    ProductDescriptionBlock(const ProductDescriptionBlock&)            = delete; |    ProductDescriptionBlock(const ProductDescriptionBlock&)            = delete; | ||||||
|    ProductDescriptionBlock& operator=(const ProductDescriptionBlock&) = delete; |    ProductDescriptionBlock& operator=(const ProductDescriptionBlock&) = delete; | ||||||
|  | @ -30,57 +26,59 @@ public: | ||||||
|    ProductDescriptionBlock(ProductDescriptionBlock&&) noexcept; |    ProductDescriptionBlock(ProductDescriptionBlock&&) noexcept; | ||||||
|    ProductDescriptionBlock& operator=(ProductDescriptionBlock&&) noexcept; |    ProductDescriptionBlock& operator=(ProductDescriptionBlock&&) noexcept; | ||||||
| 
 | 
 | ||||||
|    int16_t  block_divider() const; |    [[nodiscard]] int16_t  block_divider() const; | ||||||
|    float    latitude_of_radar() const; |    [[nodiscard]] float    latitude_of_radar() const; | ||||||
|    float    longitude_of_radar() const; |    [[nodiscard]] float    longitude_of_radar() const; | ||||||
|    int16_t  height_of_radar() const; |    [[nodiscard]] int16_t  height_of_radar() const; | ||||||
|    int16_t  product_code() const; |    [[nodiscard]] int16_t  product_code() const; | ||||||
|    uint16_t operational_mode() const; |    [[nodiscard]] uint16_t operational_mode() const; | ||||||
|    uint16_t volume_coverage_pattern() const; |    [[nodiscard]] uint16_t volume_coverage_pattern() const; | ||||||
|    int16_t  sequence_number() const; |    [[nodiscard]] int16_t  sequence_number() const; | ||||||
|    uint16_t volume_scan_number() const; |    [[nodiscard]] uint16_t volume_scan_number() const; | ||||||
|    uint16_t volume_scan_date() const; |    [[nodiscard]] uint16_t volume_scan_date() const; | ||||||
|    uint32_t volume_scan_start_time() const; |    [[nodiscard]] uint32_t volume_scan_start_time() const; | ||||||
|    uint16_t generation_date_of_product() const; |    [[nodiscard]] uint16_t generation_date_of_product() const; | ||||||
|    uint32_t generation_time_of_product() const; |    [[nodiscard]] uint32_t generation_time_of_product() const; | ||||||
|    uint16_t elevation_number() const; |    [[nodiscard]] uint16_t elevation_number() const; | ||||||
|    uint16_t data_level_threshold(size_t i) const; |    [[nodiscard]] uint16_t data_level_threshold(size_t i) const; | ||||||
|    uint8_t  version() const; |    [[nodiscard]] uint8_t  version() const; | ||||||
|    uint8_t  spot_blank() const; |    [[nodiscard]] uint8_t  spot_blank() const; | ||||||
|    uint32_t offset_to_symbology() const; |    [[nodiscard]] uint32_t offset_to_symbology() const; | ||||||
|    uint32_t offset_to_graphic() const; |    [[nodiscard]] uint32_t offset_to_graphic() const; | ||||||
|    uint32_t offset_to_tabular() const; |    [[nodiscard]] uint32_t offset_to_tabular() const; | ||||||
| 
 | 
 | ||||||
|    float    range() const; |    [[nodiscard]] float    range() const; | ||||||
|    uint16_t range_raw() const; |    [[nodiscard]] uint16_t range_raw() const; | ||||||
|    float    x_resolution() const; |    [[nodiscard]] float    x_resolution() const; | ||||||
|    uint16_t x_resolution_raw() const; |    [[nodiscard]] uint16_t x_resolution_raw() const; | ||||||
|    float    y_resolution() const; |    [[nodiscard]] float    y_resolution() const; | ||||||
|    uint16_t y_resolution_raw() const; |    [[nodiscard]] uint16_t y_resolution_raw() const; | ||||||
| 
 | 
 | ||||||
|    uint16_t threshold() const; |    [[nodiscard]] uint16_t threshold() const; | ||||||
|    float    offset() const; |    [[nodiscard]] float    offset() const; | ||||||
|    float    scale() const; |    [[nodiscard]] float    scale() const; | ||||||
|    uint16_t number_of_levels() const; |    [[nodiscard]] uint16_t number_of_levels() const; | ||||||
| 
 | 
 | ||||||
|    std::optional<DataLevelCode> data_level_code(std::uint8_t level) const; |    [[nodiscard]] std::optional<DataLevelCode> | ||||||
|    std::optional<float>         data_value(std::uint8_t level) const; |                                       data_level_code(std::uint8_t level) const; | ||||||
|  |    [[nodiscard]] std::optional<float> data_value(std::uint8_t level) const; | ||||||
| 
 | 
 | ||||||
|    std::uint16_t log_start() const; |    [[nodiscard]] std::uint16_t log_start() const; | ||||||
|    float         log_offset() const; |    [[nodiscard]] float         log_offset() const; | ||||||
|    float         log_scale() const; |    [[nodiscard]] float         log_scale() const; | ||||||
| 
 | 
 | ||||||
|    float gr_scale() const; |    [[nodiscard]] float gr_scale() const; | ||||||
| 
 | 
 | ||||||
|    std::uint8_t data_mask() const; |    [[nodiscard]] std::uint8_t data_mask() const; | ||||||
|    std::uint8_t topped_mask() const; |    [[nodiscard]] std::uint8_t topped_mask() const; | ||||||
| 
 | 
 | ||||||
|    units::angle::degrees<double> elevation() const; |    [[nodiscard]] units::angle::degrees<double> elevation() const; | ||||||
|  |    [[nodiscard]] bool                          has_elevation() const; | ||||||
| 
 | 
 | ||||||
|    bool IsCompressionEnabled() const; |    [[nodiscard]] bool IsCompressionEnabled() const; | ||||||
|    bool IsDataLevelCoded() const; |    [[nodiscard]] bool IsDataLevelCoded() const; | ||||||
| 
 | 
 | ||||||
|    size_t data_size() const override; |    [[nodiscard]] size_t data_size() const override; | ||||||
| 
 | 
 | ||||||
|    bool Parse(std::istream& is) override; |    bool Parse(std::istream& is) override; | ||||||
| 
 | 
 | ||||||
|  | @ -90,6 +88,4 @@ private: | ||||||
|    std::unique_ptr<ProductDescriptionBlockImpl> p; |    std::unique_ptr<ProductDescriptionBlockImpl> p; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace rpg
 | } // namespace scwx::wsr88d::rpg
 | ||||||
| } // namespace wsr88d
 |  | ||||||
| } // namespace scwx
 |  | ||||||
|  |  | ||||||
|  | @ -724,14 +724,21 @@ units::angle::degrees<double> ProductDescriptionBlock::elevation() const | ||||||
| { | { | ||||||
|    double elevation = 0.0; |    double elevation = 0.0; | ||||||
| 
 | 
 | ||||||
|    if (p->elevationNumber_ > 0) |    if (has_elevation()) | ||||||
|    { |    { | ||||||
|       elevation = p->parameters_[2] * 0.1; |       // Elevation is given in tenths of a degree
 | ||||||
|  |       // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
 | ||||||
|  |       elevation = static_cast<int16_t>(p->parameters_[2]) * 0.1; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    return units::angle::degrees<double> {elevation}; |    return units::angle::degrees<double> {elevation}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool ProductDescriptionBlock::has_elevation() const | ||||||
|  | { | ||||||
|  |    return p->elevationNumber_ > 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool ProductDescriptionBlock::IsCompressionEnabled() const | bool ProductDescriptionBlock::IsCompressionEnabled() const | ||||||
| { | { | ||||||
|    bool isCompressed = false; |    bool isCompressed = false; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat