mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 18:40:05 +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,46 +334,87 @@ 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,
|
||||||
{
|
&map::MapWidget::MapParametersChanged,
|
||||||
connect(mapWidget,
|
this,
|
||||||
&map::MapWidget::MapParametersChanged,
|
&MainWindowImpl::UpdateMapParameters);
|
||||||
this,
|
connect(
|
||||||
&MainWindowImpl::UpdateMapParameters);
|
mapWidget,
|
||||||
|
&map::MapWidget::MapParametersChanged,
|
||||||
|
this,
|
||||||
|
[&](double latitude, double longitude)
|
||||||
|
{
|
||||||
|
if (mapWidget == activeMap_)
|
||||||
|
{
|
||||||
|
emit mainWindow_->ActiveMapMoved(latitude, longitude);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
|
||||||
connect(
|
connect(
|
||||||
mapWidget,
|
mapWidget,
|
||||||
&map::MapWidget::RadarSweepUpdated,
|
&map::MapWidget::RadarSweepUpdated,
|
||||||
this,
|
this,
|
||||||
[&]()
|
[&]()
|
||||||
{
|
{
|
||||||
if (mapWidget == activeMap_)
|
if (mapWidget == activeMap_)
|
||||||
{
|
{
|
||||||
UpdateRadarProductSelection(
|
UpdateRadarProductSelection(mapWidget->GetRadarProductGroup(),
|
||||||
mapWidget->GetRadarProductGroup(),
|
mapWidget->GetRadarProductName());
|
||||||
mapWidget->GetRadarProductName());
|
UpdateRadarProductSettings();
|
||||||
UpdateRadarProductSettings();
|
UpdateRadarSite();
|
||||||
UpdateRadarSite();
|
UpdateVcp();
|
||||||
UpdateVcp();
|
}
|
||||||
}
|
},
|
||||||
},
|
Qt::QueuedConnection);
|
||||||
Qt::QueuedConnection);
|
|
||||||
|
|
||||||
connect(
|
connect(
|
||||||
mapWidget,
|
mapWidget,
|
||||||
&map::MapWidget::Level3ProductsChanged,
|
&map::MapWidget::Level3ProductsChanged,
|
||||||
this,
|
this,
|
||||||
[&]()
|
[&]()
|
||||||
{
|
{
|
||||||
if (mapWidget == activeMap_)
|
if (mapWidget == activeMap_)
|
||||||
{
|
{
|
||||||
UpdateAvailableLevel3Products();
|
UpdateAvailableLevel3Products();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
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