mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 06:10:04 +00:00 
			
		
		
		
	Calculate distance to each radar site from current location
This commit is contained in:
		
							parent
							
								
									6e7a13494a
								
							
						
					
					
						commit
						3a4819aeff
					
				
					 7 changed files with 192 additions and 70 deletions
				
			
		|  | @ -77,6 +77,7 @@ public: | ||||||
| 
 | 
 | ||||||
|    void ConfigureMapLayout(); |    void ConfigureMapLayout(); | ||||||
|    void ConnectMapSignals(); |    void ConnectMapSignals(); | ||||||
|  |    void ConnectOtherSignals(); | ||||||
|    void HandleFocusChange(QWidget* focused); |    void HandleFocusChange(QWidget* focused); | ||||||
|    void SelectElevation(map::MapWidget* mapWidget, float elevation); |    void SelectElevation(map::MapWidget* mapWidget, float elevation); | ||||||
|    void SelectRadarProduct(map::MapWidget*           mapWidget, |    void SelectRadarProduct(map::MapWidget*           mapWidget, | ||||||
|  | @ -180,35 +181,7 @@ MainWindow::MainWindow(QWidget* parent) : | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    p->ConnectMapSignals(); |    p->ConnectMapSignals(); | ||||||
| 
 |    p->ConnectOtherSignals(); | ||||||
|    connect(qApp, |  | ||||||
|            &QApplication::focusChanged, |  | ||||||
|            this, |  | ||||||
|            [=](QWidget* /*old*/, QWidget* now) { p->HandleFocusChange(now); }); |  | ||||||
|    connect(p->level2ProductsWidget_, |  | ||||||
|            &ui::Level2ProductsWidget::RadarProductSelected, |  | ||||||
|            this, |  | ||||||
|            [&](common::RadarProductGroup group, |  | ||||||
|                const std::string&        productName, |  | ||||||
|                int16_t                   productCode) { |  | ||||||
|               p->SelectRadarProduct( |  | ||||||
|                  p->activeMap_, group, productName, productCode); |  | ||||||
|            }); |  | ||||||
|    connect(p->level3ProductsWidget_, |  | ||||||
|            &ui::Level3ProductsWidget::RadarProductSelected, |  | ||||||
|            this, |  | ||||||
|            [&](common::RadarProductGroup group, |  | ||||||
|                const std::string&        productName, |  | ||||||
|                int16_t                   productCode) { |  | ||||||
|               p->SelectRadarProduct( |  | ||||||
|                  p->activeMap_, group, productName, productCode); |  | ||||||
|            }); |  | ||||||
|    connect(p->level2SettingsWidget_, |  | ||||||
|            &ui::Level2SettingsWidget::ElevationSelected, |  | ||||||
|            this, |  | ||||||
|            [&](float elevation) |  | ||||||
|            { p->SelectElevation(p->activeMap_, elevation); }); |  | ||||||
| 
 |  | ||||||
|    p->HandleFocusChange(p->activeMap_); |    p->HandleFocusChange(p->activeMap_); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -361,14 +334,24 @@ void MainWindowImpl::ConfigureMapLayout() | ||||||
| 
 | 
 | ||||||
| void MainWindowImpl::ConnectMapSignals() | void MainWindowImpl::ConnectMapSignals() | ||||||
| { | { | ||||||
|    std::for_each(maps_.cbegin(), |    for (const auto& mapWidget : maps_) | ||||||
|                  maps_.cend(), |  | ||||||
|                  [&](auto& mapWidget) |  | ||||||
|    { |    { | ||||||
|       connect(mapWidget, |       connect(mapWidget, | ||||||
|               &map::MapWidget::MapParametersChanged, |               &map::MapWidget::MapParametersChanged, | ||||||
|               this, |               this, | ||||||
|               &MainWindowImpl::UpdateMapParameters); |               &MainWindowImpl::UpdateMapParameters); | ||||||
|  |       connect( | ||||||
|  |          mapWidget, | ||||||
|  |          &map::MapWidget::MapParametersChanged, | ||||||
|  |          this, | ||||||
|  |          [&](double latitude, double longitude) | ||||||
|  |          { | ||||||
|  |             if (mapWidget == activeMap_) | ||||||
|  |             { | ||||||
|  |                emit mainWindow_->ActiveMapMoved(latitude, longitude); | ||||||
|  |             } | ||||||
|  |          }, | ||||||
|  |          Qt::QueuedConnection); | ||||||
| 
 | 
 | ||||||
|       connect( |       connect( | ||||||
|          mapWidget, |          mapWidget, | ||||||
|  | @ -378,8 +361,7 @@ void MainWindowImpl::ConnectMapSignals() | ||||||
|          { |          { | ||||||
|             if (mapWidget == activeMap_) |             if (mapWidget == activeMap_) | ||||||
|             { |             { | ||||||
|                              UpdateRadarProductSelection( |                UpdateRadarProductSelection(mapWidget->GetRadarProductGroup(), | ||||||
|                                 mapWidget->GetRadarProductGroup(), |  | ||||||
|                                            mapWidget->GetRadarProductName()); |                                            mapWidget->GetRadarProductName()); | ||||||
|                UpdateRadarProductSettings(); |                UpdateRadarProductSettings(); | ||||||
|                UpdateRadarSite(); |                UpdateRadarSite(); | ||||||
|  | @ -400,7 +382,39 @@ void MainWindowImpl::ConnectMapSignals() | ||||||
|             } |             } | ||||||
|          }, |          }, | ||||||
|          Qt::QueuedConnection); |          Qt::QueuedConnection); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MainWindowImpl::ConnectOtherSignals() | ||||||
|  | { | ||||||
|  |    connect(qApp, | ||||||
|  |            &QApplication::focusChanged, | ||||||
|  |            mainWindow_, | ||||||
|  |            [=](QWidget* /*old*/, QWidget* now) { HandleFocusChange(now); }); | ||||||
|  |    connect(level2ProductsWidget_, | ||||||
|  |            &ui::Level2ProductsWidget::RadarProductSelected, | ||||||
|  |            mainWindow_, | ||||||
|  |            [&](common::RadarProductGroup group, | ||||||
|  |                const std::string&        productName, | ||||||
|  |                int16_t                   productCode) { | ||||||
|  |               SelectRadarProduct(activeMap_, group, productName, productCode); | ||||||
|            }); |            }); | ||||||
|  |    connect(level3ProductsWidget_, | ||||||
|  |            &ui::Level3ProductsWidget::RadarProductSelected, | ||||||
|  |            mainWindow_, | ||||||
|  |            [&](common::RadarProductGroup group, | ||||||
|  |                const std::string&        productName, | ||||||
|  |                int16_t                   productCode) { | ||||||
|  |               SelectRadarProduct(activeMap_, group, productName, productCode); | ||||||
|  |            }); | ||||||
|  |    connect(level2SettingsWidget_, | ||||||
|  |            &ui::Level2SettingsWidget::ElevationSelected, | ||||||
|  |            mainWindow_, | ||||||
|  |            [&](float elevation) { SelectElevation(activeMap_, elevation); }); | ||||||
|  |    connect(mainWindow_, | ||||||
|  |            &MainWindow::ActiveMapMoved, | ||||||
|  |            radarSiteDialog_, | ||||||
|  |            &ui::RadarSiteDialog::HandleMapUpdate); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MainWindowImpl::HandleFocusChange(QWidget* focused) | void MainWindowImpl::HandleFocusChange(QWidget* focused) | ||||||
|  |  | ||||||
|  | @ -28,6 +28,9 @@ public: | ||||||
| 
 | 
 | ||||||
|    void showEvent(QShowEvent* event) override; |    void showEvent(QShowEvent* event) override; | ||||||
| 
 | 
 | ||||||
|  | signals: | ||||||
|  |    void ActiveMapMoved(double latitude, double longitude); | ||||||
|  | 
 | ||||||
| private slots: | private slots: | ||||||
|    void on_actionOpen_triggered(); |    void on_actionOpen_triggered(); | ||||||
|    void on_actionExit_triggered(); |    void on_actionExit_triggered(); | ||||||
|  |  | ||||||
|  | @ -4,6 +4,10 @@ | ||||||
| #include <scwx/common/geographic.hpp> | #include <scwx/common/geographic.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
| 
 | 
 | ||||||
|  | #include <format> | ||||||
|  | 
 | ||||||
|  | #include <GeographicLib/Geodesic.hpp> | ||||||
|  | 
 | ||||||
| namespace scwx | namespace scwx | ||||||
| { | { | ||||||
| namespace qt | namespace qt | ||||||
|  | @ -14,7 +18,7 @@ namespace model | ||||||
| static const std::string logPrefix_ = "scwx::qt::model::radar_site_model"; | static const std::string logPrefix_ = "scwx::qt::model::radar_site_model"; | ||||||
| static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
| 
 | 
 | ||||||
| static constexpr size_t kNumColumns = 7u; | static constexpr size_t kNumColumns = 8u; | ||||||
| 
 | 
 | ||||||
| class RadarSiteModelImpl | class RadarSiteModelImpl | ||||||
| { | { | ||||||
|  | @ -23,6 +27,12 @@ public: | ||||||
|    ~RadarSiteModelImpl() = default; |    ~RadarSiteModelImpl() = default; | ||||||
| 
 | 
 | ||||||
|    QList<std::shared_ptr<config::RadarSite>> radarSites_; |    QList<std::shared_ptr<config::RadarSite>> radarSites_; | ||||||
|  | 
 | ||||||
|  |    GeographicLib::Geodesic geodesic_; | ||||||
|  | 
 | ||||||
|  |    std::unordered_map<std::string, double> distanceMap_; | ||||||
|  |    scwx::common::DistanceType              distanceDisplay_; | ||||||
|  |    scwx::common::Coordinate                previousPosition_; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| RadarSiteModel::RadarSiteModel(QObject* parent) : | RadarSiteModel::RadarSiteModel(QObject* parent) : | ||||||
|  | @ -81,6 +91,26 @@ QVariant RadarSiteModel::data(const QModelIndex& index, int role) const | ||||||
|          } |          } | ||||||
|       case 6: |       case 6: | ||||||
|          return QString::fromStdString(site->type_name()); |          return QString::fromStdString(site->type_name()); | ||||||
|  |       case 7: | ||||||
|  |          if (role == Qt::DisplayRole) | ||||||
|  |          { | ||||||
|  |             if (p->distanceDisplay_ == scwx::common::DistanceType::Miles) | ||||||
|  |             { | ||||||
|  |                return QString("%1 mi").arg( | ||||||
|  |                   static_cast<uint32_t>(p->distanceMap_.at(site->id()) * | ||||||
|  |                                         scwx::common::kMilesPerMeter)); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                return QString("%1 km").arg( | ||||||
|  |                   static_cast<uint32_t>(p->distanceMap_.at(site->id()) * | ||||||
|  |                                         scwx::common::kKilometersPerMeter)); | ||||||
|  |             } | ||||||
|  |          } | ||||||
|  |          else | ||||||
|  |          { | ||||||
|  |             return p->distanceMap_.at(site->id()); | ||||||
|  |          } | ||||||
|       default: |       default: | ||||||
|          break; |          break; | ||||||
|       } |       } | ||||||
|  | @ -113,6 +143,8 @@ QVariant RadarSiteModel::headerData(int             section, | ||||||
|             return tr("Longitude"); |             return tr("Longitude"); | ||||||
|          case 6: |          case 6: | ||||||
|             return tr("Type"); |             return tr("Type"); | ||||||
|  |          case 7: | ||||||
|  |             return tr("Distance"); | ||||||
|          default: |          default: | ||||||
|             break; |             break; | ||||||
|          } |          } | ||||||
|  | @ -122,7 +154,30 @@ QVariant RadarSiteModel::headerData(int             section, | ||||||
|    return QVariant(); |    return QVariant(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| RadarSiteModelImpl::RadarSiteModelImpl() : radarSites_ {} | void RadarSiteModel::HandleMapUpdate(double latitude, double longitude) | ||||||
|  | { | ||||||
|  |    logger_->trace("Handle map update: {}, {}", latitude, longitude); | ||||||
|  | 
 | ||||||
|  |    double distanceInMeters; | ||||||
|  | 
 | ||||||
|  |    for (const auto& site : p->radarSites_) | ||||||
|  |    { | ||||||
|  |       p->geodesic_.Inverse(latitude, | ||||||
|  |                            longitude, | ||||||
|  |                            site->latitude(), | ||||||
|  |                            site->longitude(), | ||||||
|  |                            distanceInMeters); | ||||||
|  |       p->distanceMap_[site->id()] = distanceInMeters; | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | RadarSiteModelImpl::RadarSiteModelImpl() : | ||||||
|  |     radarSites_ {}, | ||||||
|  |     geodesic_(GeographicLib::Constants::WGS84_a(), | ||||||
|  |               GeographicLib::Constants::WGS84_f()), | ||||||
|  |     distanceMap_ {}, | ||||||
|  |     distanceDisplay_ {scwx::common::DistanceType::Miles}, | ||||||
|  |     previousPosition_ {} | ||||||
| { | { | ||||||
|    // Get all loaded radar sites
 |    // Get all loaded radar sites
 | ||||||
|    std::vector<std::shared_ptr<config::RadarSite>> radarSites = |    std::vector<std::shared_ptr<config::RadarSite>> radarSites = | ||||||
|  | @ -131,6 +186,7 @@ RadarSiteModelImpl::RadarSiteModelImpl() : radarSites_ {} | ||||||
|    // Setup radar site list
 |    // Setup radar site list
 | ||||||
|    for (auto& site : radarSites) |    for (auto& site : radarSites) | ||||||
|    { |    { | ||||||
|  |       distanceMap_[site->id()] = 0.0; | ||||||
|       radarSites_.emplace_back(std::move(site)); |       radarSites_.emplace_back(std::move(site)); | ||||||
|    } |    } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -28,6 +28,8 @@ public: | ||||||
|                        Qt::Orientation orientation, |                        Qt::Orientation orientation, | ||||||
|                        int             role = Qt::DisplayRole) const override; |                        int             role = Qt::DisplayRole) const override; | ||||||
| 
 | 
 | ||||||
|  |    void HandleMapUpdate(double latitude, double longitude); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|    std::unique_ptr<RadarSiteModelImpl> p; |    std::unique_ptr<RadarSiteModelImpl> p; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <scwx/qt/common/types.hpp> | #include <scwx/qt/common/types.hpp> | ||||||
| #include <scwx/qt/model/radar_site_model.hpp> | #include <scwx/qt/model/radar_site_model.hpp> | ||||||
|  | #include <scwx/common/geographic.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
| 
 | 
 | ||||||
| #include <QSortFilterProxyModel> | #include <QSortFilterProxyModel> | ||||||
|  | @ -23,7 +24,9 @@ public: | ||||||
|    explicit RadarSiteDialogImpl(RadarSiteDialog* self) : |    explicit RadarSiteDialogImpl(RadarSiteDialog* self) : | ||||||
|        self_ {self}, |        self_ {self}, | ||||||
|        radarSiteModel_ {new model::RadarSiteModel(self_)}, |        radarSiteModel_ {new model::RadarSiteModel(self_)}, | ||||||
|        proxyModel_ {new QSortFilterProxyModel(self_)} |        proxyModel_ {new QSortFilterProxyModel(self_)}, | ||||||
|  |        mapPosition_ {}, | ||||||
|  |        mapUpdateDeferred_ {false} | ||||||
|    { |    { | ||||||
|       proxyModel_->setSourceModel(radarSiteModel_); |       proxyModel_->setSourceModel(radarSiteModel_); | ||||||
|       proxyModel_->setSortRole(common::SortRole); |       proxyModel_->setSortRole(common::SortRole); | ||||||
|  | @ -35,6 +38,9 @@ public: | ||||||
|    RadarSiteDialog*       self_; |    RadarSiteDialog*       self_; | ||||||
|    model::RadarSiteModel* radarSiteModel_; |    model::RadarSiteModel* radarSiteModel_; | ||||||
|    QSortFilterProxyModel* proxyModel_; |    QSortFilterProxyModel* proxyModel_; | ||||||
|  | 
 | ||||||
|  |    scwx::common::Coordinate mapPosition_; | ||||||
|  |    bool                     mapUpdateDeferred_; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| RadarSiteDialog::RadarSiteDialog(QWidget* parent) : | RadarSiteDialog::RadarSiteDialog(QWidget* parent) : | ||||||
|  | @ -63,6 +69,32 @@ RadarSiteDialog::~RadarSiteDialog() | ||||||
|    delete ui; |    delete ui; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void RadarSiteDialog::showEvent(QShowEvent* event) | ||||||
|  | { | ||||||
|  |    if (p->mapUpdateDeferred_) | ||||||
|  |    { | ||||||
|  |       p->radarSiteModel_->HandleMapUpdate(p->mapPosition_.latitude_, | ||||||
|  |                                           p->mapPosition_.longitude_); | ||||||
|  |       p->mapUpdateDeferred_ = false; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    QDialog::showEvent(event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void RadarSiteDialog::HandleMapUpdate(double latitude, double longitude) | ||||||
|  | { | ||||||
|  |    p->mapPosition_ = {latitude, longitude}; | ||||||
|  | 
 | ||||||
|  |    if (isVisible()) | ||||||
|  |    { | ||||||
|  |       p->radarSiteModel_->HandleMapUpdate(latitude, longitude); | ||||||
|  |    } | ||||||
|  |    else | ||||||
|  |    { | ||||||
|  |       p->mapUpdateDeferred_ = true; | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace ui
 | } // namespace ui
 | ||||||
| } // namespace qt
 | } // namespace qt
 | ||||||
| } // namespace scwx
 | } // namespace scwx
 | ||||||
|  |  | ||||||
|  | @ -24,6 +24,12 @@ public: | ||||||
|    explicit RadarSiteDialog(QWidget* parent = nullptr); |    explicit RadarSiteDialog(QWidget* parent = nullptr); | ||||||
|    ~RadarSiteDialog(); |    ~RadarSiteDialog(); | ||||||
| 
 | 
 | ||||||
|  | protected: | ||||||
|  |    void showEvent(QShowEvent*) override; | ||||||
|  | 
 | ||||||
|  | public slots: | ||||||
|  |    void HandleMapUpdate(double latitude, double longitude); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|    std::unique_ptr<RadarSiteDialogImpl> p; |    std::unique_ptr<RadarSiteDialogImpl> p; | ||||||
|    Ui::RadarSiteDialog*                 ui; |    Ui::RadarSiteDialog*                 ui; | ||||||
|  |  | ||||||
|  | @ -7,6 +7,9 @@ namespace scwx | ||||||
| namespace common | namespace common | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  | constexpr double kMilesPerMeter      = 0.00062137119; | ||||||
|  | constexpr double kKilometersPerMeter = 0.001; | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Coordinate type to hold latitude and longitude of a location. |  * @brief Coordinate type to hold latitude and longitude of a location. | ||||||
|  */ |  */ | ||||||
|  | @ -34,6 +37,12 @@ enum class DegreeStringType | ||||||
|    DegreesMinutesSeconds |    DegreesMinutesSeconds | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | enum class DistanceType | ||||||
|  | { | ||||||
|  |    Kilometers, | ||||||
|  |    Miles | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| std::string | std::string | ||||||
| GetLatitudeString(double           latitude, | GetLatitudeString(double           latitude, | ||||||
|                   DegreeStringType type = DegreeStringType::Decimal); |                   DegreeStringType type = DegreeStringType::Decimal); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat