Merge pull request #27 from dpaulat/feature/alert-navigation

Alert Navigation on "Go"
This commit is contained in:
Dan Paulat 2023-02-22 06:49:56 -06:00 committed by GitHub
commit 0cec9c316f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 261 additions and 61 deletions

View file

@ -8,12 +8,26 @@ set(ENABLE_TESTING OFF)
set(ENABLE_UNITY_BUILD ON) set(ENABLE_UNITY_BUILD ON)
set(MINIMIZE_SIZE OFF) set(MINIMIZE_SIZE OFF)
if(NOT CMAKE_EXE_LINKER_FLAGS_DEBUGOPT) # Some variables also need set in the cache... set them all!
set(CMAKE_EXE_LINKER_FLAGS_DEBUGOPT "") set(BUILD_ONLY "s3" CACHE STRING "A semi-colon delimited list of the projects to build")
endif() set(BUILD_SHARED_LIBS OFF CACHE BOOL "If enabled, all aws sdk libraries will be build as shared objects; otherwise all Aws libraries will be built as static objects")
set(CPP_STANDARD "17" CACHE STRING "Flag to upgrade the C++ standard used. The default is 11. The minimum is 11.")
set(ENABLE_TESTING OFF CACHE BOOL "Flag to enable/disable building unit and integration tests")
set(ENABLE_UNITY_BUILD ON CACHE BOOL "If enabled, the SDK will be built using a single unified .cpp file for each service library. Reduces the size of static library binaries on Windows and Linux")
set(MINIMIZE_SIZE OFF CACHE BOOL "If enabled, the SDK will be built via a unity aggregation process that results in smaller static libraries; additionally, release binaries will favor size optimizations over speed")
# Save off ${CMAKE_CXX_FLAGS} before modifying compiler settings
set(CMAKE_CXX_FLAGS_PREV "${CMAKE_CXX_FLAGS}")
# Fix CMake errors for internal variables not set
include(aws-sdk-cpp/cmake/compiler_settings.cmake)
set_msvc_warnings()
add_subdirectory(aws-sdk-cpp) add_subdirectory(aws-sdk-cpp)
# Restore ${CMAKE_CXX_FLAGS} now that aws-sdk-cpp has been added
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_PREV}")
set_target_properties(uninstall PROPERTIES EXCLUDE_FROM_ALL True) set_target_properties(uninstall PROPERTIES EXCLUDE_FROM_ALL True)
set_target_properties(aws-c-auth PROPERTIES FOLDER aws-sdk-cpp) set_target_properties(aws-c-auth PROPERTIES FOLDER aws-sdk-cpp)

View file

@ -163,6 +163,7 @@ set(HDR_UTIL source/scwx/qt/util/color.hpp
source/scwx/qt/util/file.hpp source/scwx/qt/util/file.hpp
source/scwx/qt/util/font.hpp source/scwx/qt/util/font.hpp
source/scwx/qt/util/font_buffer.hpp source/scwx/qt/util/font_buffer.hpp
source/scwx/qt/util/geographic_lib.hpp
source/scwx/qt/util/json.hpp source/scwx/qt/util/json.hpp
source/scwx/qt/util/streams.hpp source/scwx/qt/util/streams.hpp
source/scwx/qt/util/texture_atlas.hpp source/scwx/qt/util/texture_atlas.hpp
@ -172,6 +173,7 @@ set(SRC_UTIL source/scwx/qt/util/color.cpp
source/scwx/qt/util/file.cpp source/scwx/qt/util/file.cpp
source/scwx/qt/util/font.cpp source/scwx/qt/util/font.cpp
source/scwx/qt/util/font_buffer.cpp source/scwx/qt/util/font_buffer.cpp
source/scwx/qt/util/geographic_lib.cpp
source/scwx/qt/util/json.cpp source/scwx/qt/util/json.cpp
source/scwx/qt/util/texture_atlas.cpp source/scwx/qt/util/texture_atlas.cpp
source/scwx/qt/util/q_file_buffer.cpp source/scwx/qt/util/q_file_buffer.cpp

View file

@ -1,4 +1,5 @@
#include <scwx/qt/config/radar_site.hpp> #include <scwx/qt/config/radar_site.hpp>
#include <scwx/qt/util/geographic_lib.hpp>
#include <scwx/qt/util/json.hpp> #include <scwx/qt/util/json.hpp>
#include <scwx/common/sites.hpp> #include <scwx/common/sites.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
@ -162,6 +163,44 @@ std::vector<std::shared_ptr<RadarSite>> RadarSite::GetAll()
return radarSites; return radarSites;
} }
std::shared_ptr<RadarSite> RadarSite::FindNearest(
double latitude, double longitude, std::optional<std::string> type)
{
std::shared_lock lock(siteMutex_);
double distanceInMeters;
std::shared_ptr<RadarSite> nearestRadarSite = nullptr;
double nearestDistance = 0.0;
for (const auto& site : radarSiteMap_)
{
auto& radarSite = site.second;
// If the type filter doesn't match, skip
if (type.has_value() && radarSite->type() != type)
{
continue;
}
// Calculate distance to radar site
util::GeographicLib::DefaultGeodesic().Inverse(latitude,
longitude,
radarSite->latitude(),
radarSite->longitude(),
distanceInMeters);
// If the radar site is the closer, record it as the closest
if (nearestRadarSite == nullptr || distanceInMeters < nearestDistance)
{
nearestRadarSite = radarSite;
nearestDistance = distanceInMeters;
}
}
return nearestRadarSite;
}
std::string GetRadarIdFromSiteId(const std::string& siteId) std::string GetRadarIdFromSiteId(const std::string& siteId)
{ {
std::shared_lock lock(siteMutex_); std::shared_lock lock(siteMutex_);

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <optional>
#include <string> #include <string>
#include <vector> #include <vector>
@ -38,6 +39,20 @@ public:
static std::shared_ptr<RadarSite> Get(const std::string& id); static std::shared_ptr<RadarSite> Get(const std::string& id);
static std::vector<std::shared_ptr<RadarSite>> GetAll(); static std::vector<std::shared_ptr<RadarSite>> GetAll();
/**
* Find the nearest radar site to the supplied location.
*
* @param latitude Latitude in degrees
* @param longitude Longitude in degrees
* @param type Restrict results to optional radar type
*
* @return Nearest radar site
*/
static std::shared_ptr<RadarSite>
FindNearest(double latitude,
double longitude,
std::optional<std::string> type = std::nullopt);
static void Initialize(); static void Initialize();
static size_t ReadConfig(const std::string& path); static size_t ReadConfig(const std::string& path);

View file

@ -1,4 +1,5 @@
#include <scwx/qt/gl/draw/geo_line.hpp> #include <scwx/qt/gl/draw/geo_line.hpp>
#include <scwx/qt/util/geographic_lib.hpp>
#include <scwx/qt/util/texture_atlas.hpp> #include <scwx/qt/util/texture_atlas.hpp>
#include <scwx/common/geographic.hpp> #include <scwx/common/geographic.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
@ -6,8 +7,6 @@
#include <numbers> #include <numbers>
#include <optional> #include <optional>
#include <GeographicLib/Geodesic.hpp>
namespace scwx namespace scwx
{ {
namespace qt namespace qt
@ -33,8 +32,7 @@ class GeoLine::Impl
public: public:
explicit Impl(std::shared_ptr<GlContext> context) : explicit Impl(std::shared_ptr<GlContext> context) :
context_ {context}, context_ {context},
geodesic_(GeographicLib::Constants::WGS84_a(), geodesic_ {util::GeographicLib::DefaultGeodesic()},
GeographicLib::Constants::WGS84_f()),
dirty_ {false}, dirty_ {false},
visible_ {true}, visible_ {true},
points_ {}, points_ {},
@ -55,7 +53,7 @@ public:
std::shared_ptr<GlContext> context_; std::shared_ptr<GlContext> context_;
GeographicLib::Geodesic geodesic_; const GeographicLib::Geodesic& geodesic_;
bool dirty_; bool dirty_;

View file

@ -530,7 +530,12 @@ void MainWindowImpl::ConnectOtherSignals()
&ui::AlertDockWidget::MoveMap, &ui::AlertDockWidget::MoveMap,
this, this,
[=](double latitude, double longitude) [=](double latitude, double longitude)
{ activeMap_->SetMapLocation(latitude, longitude); }, {
for (map::MapWidget* map : maps_)
{
map->SetMapLocation(latitude, longitude, true);
}
},
Qt::QueuedConnection); Qt::QueuedConnection);
connect(mainWindow_, connect(mainWindow_,
&MainWindow::ActiveMapMoved, &MainWindow::ActiveMapMoved,

View file

@ -1,5 +1,6 @@
#include <scwx/qt/manager/radar_product_manager.hpp> #include <scwx/qt/manager/radar_product_manager.hpp>
#include <scwx/qt/manager/radar_product_manager_notifier.hpp> #include <scwx/qt/manager/radar_product_manager_notifier.hpp>
#include <scwx/qt/util/geographic_lib.hpp>
#include <scwx/common/constants.hpp> #include <scwx/common/constants.hpp>
#include <scwx/provider/nexrad_data_provider_factory.hpp> #include <scwx/provider/nexrad_data_provider_factory.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
@ -18,7 +19,6 @@
#include <boost/range/irange.hpp> #include <boost/range/irange.hpp>
#include <boost/timer/timer.hpp> #include <boost/timer/timer.hpp>
#include <fmt/chrono.h> #include <fmt/chrono.h>
#include <GeographicLib/Geodesic.hpp>
#include <QMapLibreGL/QMapLibreGL> #include <QMapLibreGL/QMapLibreGL>
#pragma warning(pop) #pragma warning(pop)
@ -81,7 +81,7 @@ public:
group_ {group}, group_ {group},
product_ {product}, product_ {product},
refreshEnabled_ {false}, refreshEnabled_ {false},
refreshTimer_ {util::io_context()}, refreshTimer_ {scwx::util::io_context()},
refreshTimerMutex_ {}, refreshTimerMutex_ {},
provider_ {nullptr} provider_ {nullptr}
{ {
@ -303,8 +303,8 @@ void RadarProductManager::Initialize()
boost::timer::cpu_timer timer; boost::timer::cpu_timer timer;
GeographicLib::Geodesic geodesic(GeographicLib::Constants::WGS84_a(), const GeographicLib::Geodesic& geodesic(
GeographicLib::Constants::WGS84_f()); util::GeographicLib::DefaultGeodesic());
const QMapLibreGL::Coordinate radar(p->radarSite_->latitude(), const QMapLibreGL::Coordinate radar(p->radarSite_->latitude(),
p->radarSite_->longitude()); p->radarSite_->longitude());
@ -425,7 +425,7 @@ void RadarProductManager::EnableRefresh(common::RadarProductGroup group,
p->GetLevel3ProviderManager(product); p->GetLevel3ProviderManager(product);
// Only enable refresh on available products // Only enable refresh on available products
util::async( scwx::util::async(
[=]() [=]()
{ {
providerManager->provider_->RequestAvailableProducts(); providerManager->provider_->RequestAvailableProducts();
@ -467,7 +467,7 @@ void RadarProductManagerImpl::RefreshData(
providerManager->refreshTimer_.cancel(); providerManager->refreshTimer_.cancel();
} }
util::async( scwx::util::async(
[=]() [=]()
{ {
auto [newObjects, totalObjects] = auto [newObjects, totalObjects] =
@ -547,7 +547,7 @@ void RadarProductManagerImpl::LoadProviderData(
{ {
logger_->debug("LoadProviderData: {}, {}", logger_->debug("LoadProviderData: {}, {}",
providerManager->name(), providerManager->name(),
util::TimeString(time)); scwx::util::TimeString(time));
RadarProductManagerImpl::LoadNexradFile( RadarProductManagerImpl::LoadNexradFile(
[=, &recordMap, &recordMutex, &loadDataMutex]() [=, &recordMap, &recordMutex, &loadDataMutex]()
@ -589,7 +589,7 @@ void RadarProductManager::LoadLevel2Data(
std::chrono::system_clock::time_point time, std::chrono::system_clock::time_point time,
std::shared_ptr<request::NexradFileRequest> request) std::shared_ptr<request::NexradFileRequest> request)
{ {
logger_->debug("LoadLevel2Data: {}", util::TimeString(time)); logger_->debug("LoadLevel2Data: {}", scwx::util::TimeString(time));
p->LoadProviderData(time, p->LoadProviderData(time,
p->level2ProviderManager_, p->level2ProviderManager_,
@ -604,7 +604,7 @@ void RadarProductManager::LoadLevel3Data(
std::chrono::system_clock::time_point time, std::chrono::system_clock::time_point time,
std::shared_ptr<request::NexradFileRequest> request) std::shared_ptr<request::NexradFileRequest> request)
{ {
logger_->debug("LoadLevel3Data: {}", util::TimeString(time)); logger_->debug("LoadLevel3Data: {}", scwx::util::TimeString(time));
// Look up provider manager // Look up provider manager
std::shared_lock providerManagerLock(p->level3ProviderManagerMutex_); std::shared_lock providerManagerLock(p->level3ProviderManagerMutex_);
@ -742,7 +742,7 @@ RadarProductManagerImpl::GetLevel2ProductRecord(
else else
{ {
// TODO: Round to minutes // TODO: Round to minutes
record = util::GetBoundedElementValue(level2ProductRecords_, time); record = scwx::util::GetBoundedElementValue(level2ProductRecords_, time);
// Does the record contain the time we are looking for? // Does the record contain the time we are looking for?
if (record != nullptr && (time < record->level2_file()->start_time())) if (record != nullptr && (time < record->level2_file()->start_time()))
@ -774,7 +774,7 @@ RadarProductManagerImpl::GetLevel3ProductRecord(
} }
else else
{ {
record = util::GetBoundedElementValue(it->second, time); record = scwx::util::GetBoundedElementValue(it->second, time);
} }
} }
@ -904,7 +904,7 @@ void RadarProductManager::UpdateAvailableProducts()
logger_->debug("UpdateAvailableProducts()"); logger_->debug("UpdateAvailableProducts()");
util::async( scwx::util::async(
[=]() [=]()
{ {
auto level3ProviderManager = auto level3ProviderManager =

View file

@ -190,23 +190,18 @@ void TextEventManager::Impl::HandleMessage(
void TextEventManager::Impl::Refresh() void TextEventManager::Impl::Refresh()
{ {
using namespace std::chrono;
logger_->trace("Refresh"); logger_->trace("Refresh");
// Take a unique lock before refreshing // Take a unique lock before refreshing
std::unique_lock lock(refreshMutex_); std::unique_lock lock(refreshMutex_);
// Set threshold to last 30 hours
auto newerThan = std::chrono::system_clock::now() - 30h;
// Update the file listing from the warnings provider // Update the file listing from the warnings provider
auto [newFiles, totalFiles] = warningsProvider_.ListFiles(newerThan); auto [newFiles, totalFiles] = warningsProvider_.ListFiles();
if (newFiles > 0) if (newFiles > 0)
{ {
// Load new files // Load new files
auto updatedFiles = warningsProvider_.LoadUpdatedFiles(newerThan); auto updatedFiles = warningsProvider_.LoadUpdatedFiles();
// Handle messages // Handle messages
for (auto& file : updatedFiles) for (auto& file : updatedFiles)

View file

@ -424,21 +424,31 @@ void MapWidget::SelectRadarProduct(
SelectRadarProduct(group, product, productCode); SelectRadarProduct(group, product, productCode);
} }
void MapWidget::SelectRadarSite(const std::string& id) void MapWidget::SelectRadarSite(const std::string& id, bool updateCoordinates)
{ {
logger_->debug("Selecting radar site: {}", id); logger_->debug("Selecting radar site: {}", id);
std::shared_ptr<config::RadarSite> radarSite = config::RadarSite::Get(id); std::shared_ptr<config::RadarSite> radarSite = config::RadarSite::Get(id);
SelectRadarSite(radarSite, updateCoordinates);
}
void MapWidget::SelectRadarSite(std::shared_ptr<config::RadarSite> radarSite,
bool updateCoordinates)
{
// Verify radar site is valid and has changed // Verify radar site is valid and has changed
if (radarSite != nullptr && if (radarSite != nullptr &&
(p->radarProductManager_ == nullptr || (p->radarProductManager_ == nullptr ||
id != p->radarProductManager_->radar_site()->id())) radarSite->id() != p->radarProductManager_->radar_site()->id()))
{ {
auto radarProductView = p->context_->radar_product_view(); auto radarProductView = p->context_->radar_product_view();
p->map_->setCoordinate({radarSite->latitude(), radarSite->longitude()}); if (updateCoordinates)
p->SetRadarSite(id); {
p->map_->setCoordinate(
{radarSite->latitude(), radarSite->longitude()});
}
p->SetRadarSite(radarSite->id());
p->Update(); p->Update();
// Select products from new site // Select products from new site
@ -480,12 +490,29 @@ void MapWidget::SetAutoRefresh(bool enabled)
} }
} }
void MapWidget::SetMapLocation(double latitude, double longitude) void MapWidget::SetMapLocation(double latitude,
double longitude,
bool updateRadarSite)
{ {
if (p->map_ != nullptr && p->prevLatitude_ != latitude || if (p->map_ != nullptr && p->prevLatitude_ != latitude ||
p->prevLongitude_ != longitude) p->prevLongitude_ != longitude)
{ {
// Update the map location
p->map_->setCoordinate({latitude, longitude}); p->map_->setCoordinate({latitude, longitude});
// If the radar site should be updated based on the new location
if (updateRadarSite)
{
// Find the nearest WSR-88D radar
std::shared_ptr<config::RadarSite> nearestRadarSite =
config::RadarSite::FindNearest(latitude, longitude, "wsr88d");
// If found, select it
if (nearestRadarSite != nullptr)
{
SelectRadarSite(nearestRadarSite->id(), false);
}
}
} }
} }

View file

@ -48,10 +48,40 @@ public:
const std::string& product, const std::string& product,
int16_t productCode); int16_t productCode);
void SelectRadarProduct(std::shared_ptr<types::RadarProductRecord> record); void SelectRadarProduct(std::shared_ptr<types::RadarProductRecord> record);
void SelectRadarSite(const std::string& radarSite);
/**
* @brief Selects a radar site.
*
* @param [in] radarSite ID of the requested radar site
* @param [in] updateCoordinates Whether to update the map coordinates to the
* requested radar site location. Default is true.
*/
void SelectRadarSite(const std::string& id, bool updateCoordinates = true);
/**
* @brief Selects a radar site.
*
* @param [in] radarSite Shared pointer to the requested radar site
* @param [in] updateCoordinates Whether to update the map coordinates to the
* requested radar site location. Default is true.
*/
void SelectRadarSite(std::shared_ptr<config::RadarSite> radarSite,
bool updateCoordinates = true);
void SetActive(bool isActive); void SetActive(bool isActive);
void SetAutoRefresh(bool enabled); void SetAutoRefresh(bool enabled);
void SetMapLocation(double latitude, double longitude);
/**
* @brief Sets the current map location.
*
* @param [in] latitude Latitude in degrees
* @param [in] longitude Longitude in degrees
* @param [in] updateRadarSite Whether to update the selected radar site to
* the closest WSR-88D site. Default is false.
*/
void SetMapLocation(double latitude,
double longitude,
bool updateRadarSite = false);
void SetMapParameters(double latitude, void SetMapParameters(double latitude,
double longitude, double longitude,
double zoom, double zoom,

View file

@ -1,7 +1,7 @@
#include <scwx/qt/map/radar_range_layer.hpp> #include <scwx/qt/map/radar_range_layer.hpp>
#include <scwx/qt/util/geographic_lib.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
#include <GeographicLib/Geodesic.hpp>
#include <glm/glm.hpp> #include <glm/glm.hpp>
namespace scwx namespace scwx
@ -61,8 +61,8 @@ void RadarRangeLayer::Update(std::shared_ptr<QMapLibreGL::Map> map,
static std::shared_ptr<QMapLibreGL::Feature> static std::shared_ptr<QMapLibreGL::Feature>
GetRangeCircle(float range, QMapLibreGL::Coordinate center) GetRangeCircle(float range, QMapLibreGL::Coordinate center)
{ {
GeographicLib::Geodesic geodesic(GeographicLib::Constants::WGS84_a(), const GeographicLib::Geodesic& geodesic(
GeographicLib::Constants::WGS84_f()); util::GeographicLib::DefaultGeodesic());
constexpr float angleDelta = 0.5f; constexpr float angleDelta = 0.5f;
constexpr float angleDeltaH = angleDelta / 2.0f; constexpr float angleDeltaH = angleDelta / 2.0f;

View file

@ -2,6 +2,7 @@
#include <scwx/qt/config/county_database.hpp> #include <scwx/qt/config/county_database.hpp>
#include <scwx/qt/manager/text_event_manager.hpp> #include <scwx/qt/manager/text_event_manager.hpp>
#include <scwx/qt/types/qt_types.hpp> #include <scwx/qt/types/qt_types.hpp>
#include <scwx/qt/util/geographic_lib.hpp>
#include <scwx/common/geographic.hpp> #include <scwx/common/geographic.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
#include <scwx/util/strings.hpp> #include <scwx/util/strings.hpp>
@ -9,7 +10,6 @@
#include <format> #include <format>
#include <GeographicLib/Geodesic.hpp>
#include <QApplication> #include <QApplication>
#include <QFontMetrics> #include <QFontMetrics>
@ -47,7 +47,7 @@ public:
QList<types::TextEventKey> textEventKeys_; QList<types::TextEventKey> textEventKeys_;
GeographicLib::Geodesic geodesic_; const GeographicLib::Geodesic& geodesic_;
std::unordered_map<types::TextEventKey, std::unordered_map<types::TextEventKey,
common::Coordinate, common::Coordinate,
@ -357,8 +357,7 @@ void AlertModel::HandleMapUpdate(double latitude, double longitude)
AlertModelImpl::AlertModelImpl() : AlertModelImpl::AlertModelImpl() :
textEventManager_ {manager::TextEventManager::Instance()}, textEventManager_ {manager::TextEventManager::Instance()},
textEventKeys_ {}, textEventKeys_ {},
geodesic_(GeographicLib::Constants::WGS84_a(), geodesic_(util::GeographicLib::DefaultGeodesic()),
GeographicLib::Constants::WGS84_f()),
distanceMap_ {}, distanceMap_ {},
distanceDisplay_ {scwx::common::DistanceType::Miles}, distanceDisplay_ {scwx::common::DistanceType::Miles},
previousPosition_ {} previousPosition_ {}
@ -381,7 +380,7 @@ std::string AlertModelImpl::GetCounties(const types::TextEventKey& key)
} }
std::sort(counties.begin(), counties.end()); std::sort(counties.begin(), counties.end());
return util::ToString(counties); return scwx::util::ToString(counties);
} }
std::string AlertModelImpl::GetState(const types::TextEventKey& key) std::string AlertModelImpl::GetState(const types::TextEventKey& key)
@ -390,7 +389,7 @@ std::string AlertModelImpl::GetState(const types::TextEventKey& key)
auto& lastMessage = messageList.back(); auto& lastMessage = messageList.back();
size_t segmentCount = lastMessage->segment_count(); size_t segmentCount = lastMessage->segment_count();
auto lastSegment = lastMessage->segment(segmentCount - 1); auto lastSegment = lastMessage->segment(segmentCount - 1);
return util::ToString(lastSegment->header_->ugc_.states()); return scwx::util::ToString(lastSegment->header_->ugc_.states());
} }
std::chrono::system_clock::time_point std::chrono::system_clock::time_point
@ -404,7 +403,7 @@ AlertModelImpl::GetStartTime(const types::TextEventKey& key)
std::string AlertModelImpl::GetStartTimeString(const types::TextEventKey& key) std::string AlertModelImpl::GetStartTimeString(const types::TextEventKey& key)
{ {
return util::TimeString(GetStartTime(key)); return scwx::util::TimeString(GetStartTime(key));
} }
std::chrono::system_clock::time_point std::chrono::system_clock::time_point
@ -419,7 +418,7 @@ AlertModelImpl::GetEndTime(const types::TextEventKey& key)
std::string AlertModelImpl::GetEndTimeString(const types::TextEventKey& key) std::string AlertModelImpl::GetEndTimeString(const types::TextEventKey& key)
{ {
return util::TimeString(GetEndTime(key)); return scwx::util::TimeString(GetEndTime(key));
} }
} // namespace model } // namespace model

View file

@ -1,13 +1,12 @@
#include <scwx/qt/model/radar_site_model.hpp> #include <scwx/qt/model/radar_site_model.hpp>
#include <scwx/qt/config/radar_site.hpp> #include <scwx/qt/config/radar_site.hpp>
#include <scwx/qt/types/qt_types.hpp> #include <scwx/qt/types/qt_types.hpp>
#include <scwx/qt/util/geographic_lib.hpp>
#include <scwx/common/geographic.hpp> #include <scwx/common/geographic.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
#include <format> #include <format>
#include <GeographicLib/Geodesic.hpp>
namespace scwx namespace scwx
{ {
namespace qt namespace qt
@ -36,7 +35,7 @@ public:
QList<std::shared_ptr<config::RadarSite>> radarSites_; QList<std::shared_ptr<config::RadarSite>> radarSites_;
GeographicLib::Geodesic geodesic_; const GeographicLib::Geodesic& geodesic_;
std::unordered_map<std::string, double> distanceMap_; std::unordered_map<std::string, double> distanceMap_;
scwx::common::DistanceType distanceDisplay_; scwx::common::DistanceType distanceDisplay_;
@ -186,8 +185,7 @@ void RadarSiteModel::HandleMapUpdate(double latitude, double longitude)
RadarSiteModelImpl::RadarSiteModelImpl() : RadarSiteModelImpl::RadarSiteModelImpl() :
radarSites_ {}, radarSites_ {},
geodesic_(GeographicLib::Constants::WGS84_a(), geodesic_(util::GeographicLib::DefaultGeodesic()),
GeographicLib::Constants::WGS84_f()),
distanceMap_ {}, distanceMap_ {},
distanceDisplay_ {scwx::common::DistanceType::Miles}, distanceDisplay_ {scwx::common::DistanceType::Miles},
previousPosition_ {} previousPosition_ {}

View file

@ -0,0 +1,24 @@
#include <scwx/qt/util/geographic_lib.hpp>
namespace scwx
{
namespace qt
{
namespace util
{
namespace GeographicLib
{
const ::GeographicLib::Geodesic& DefaultGeodesic()
{
static const ::GeographicLib::Geodesic geodesic_ {
::GeographicLib::Constants::WGS84_a(),
::GeographicLib::Constants::WGS84_f()};
return geodesic_;
}
} // namespace GeographicLib
} // namespace util
} // namespace qt
} // namespace scwx

View file

@ -0,0 +1,24 @@
#pragma once
#include <GeographicLib/Geodesic.hpp>
namespace scwx
{
namespace qt
{
namespace util
{
namespace GeographicLib
{
/**
* Get the default geodesic for the WGS84 ellipsoid.
*
* return WGS84 ellipsoid geodesic
*/
const ::GeographicLib::Geodesic& DefaultGeodesic();
} // namespace GeographicLib
} // namespace util
} // namespace qt
} // namespace scwx

View file

@ -1,4 +1,5 @@
#include <scwx/qt/view/level3_raster_view.hpp> #include <scwx/qt/view/level3_raster_view.hpp>
#include <scwx/qt/util/geographic_lib.hpp>
#include <scwx/common/constants.hpp> #include <scwx/common/constants.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
#include <scwx/util/threads.hpp> #include <scwx/util/threads.hpp>
@ -7,7 +8,6 @@
#include <boost/range/irange.hpp> #include <boost/range/irange.hpp>
#include <boost/timer/timer.hpp> #include <boost/timer/timer.hpp>
#include <GeographicLib/Geodesic.hpp>
namespace scwx namespace scwx
{ {
@ -202,12 +202,12 @@ void Level3RasterView::ComputeSweep()
p->longitude_ = descriptionBlock->longitude_of_radar(); p->longitude_ = descriptionBlock->longitude_of_radar();
p->range_ = descriptionBlock->range(); p->range_ = descriptionBlock->range();
p->sweepTime_ = p->sweepTime_ =
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);
p->vcp_ = descriptionBlock->volume_coverage_pattern(); p->vcp_ = descriptionBlock->volume_coverage_pattern();
GeographicLib::Geodesic geodesic(GeographicLib::Constants::WGS84_a(), const GeographicLib::Geodesic& geodesic =
GeographicLib::Constants::WGS84_f()); util::GeographicLib::DefaultGeodesic();
const uint16_t xResolution = descriptionBlock->x_resolution_raw(); const uint16_t xResolution = descriptionBlock->x_resolution_raw();
const uint16_t yResolution = descriptionBlock->y_resolution_raw(); const uint16_t yResolution = descriptionBlock->y_resolution_raw();

View file

@ -12,12 +12,23 @@ namespace config
static const std::string DEFAULT_RADAR_SITE_FILE = static const std::string DEFAULT_RADAR_SITE_FILE =
":/res/config/radar_sites.json"; ":/res/config/radar_sites.json";
TEST(RadarSite, DefaultConfig) class RadarSiteTest : public testing::Test
{ {
size_t numSites = RadarSite::ReadConfig(DEFAULT_RADAR_SITE_FILE); protected:
static size_t numSites_;
ASSERT_GT(numSites, 0); static void SetUpTestSuite()
EXPECT_EQ(numSites, 204); {
numSites_ = RadarSite::ReadConfig(DEFAULT_RADAR_SITE_FILE);
}
};
size_t RadarSiteTest::numSites_ {0u};
TEST_F(RadarSiteTest, DefaultConfig)
{
ASSERT_GT(numSites_, 0);
EXPECT_EQ(numSites_, 204);
std::shared_ptr<RadarSite> radarSite = RadarSite::Get("KLSX"); std::shared_ptr<RadarSite> radarSite = RadarSite::Get("KLSX");
@ -31,6 +42,25 @@ TEST(RadarSite, DefaultConfig)
EXPECT_DOUBLE_EQ(radarSite->longitude(), -90.682877); EXPECT_DOUBLE_EQ(radarSite->longitude(), -90.682877);
} }
TEST_F(RadarSiteTest, FindNearest)
{
ASSERT_GT(numSites_, 0);
std::shared_ptr<RadarSite> nearest1 =
RadarSite::FindNearest(46.591111, -112.020278); // Helena, MT
std::shared_ptr<RadarSite> nearest2 =
RadarSite::FindNearest(28.54, -81.38); // Orlando, FL
std::shared_ptr<RadarSite> nearest3 =
RadarSite::FindNearest(38.627222, -90.197778, "wsr88d"); // St Louis, MO
std::shared_ptr<RadarSite> nearest4 =
RadarSite::FindNearest(38.627222, -90.197778, "tdwr"); // St Louis, MO
EXPECT_EQ(nearest1->id(), "KTFX");
EXPECT_EQ(nearest2->id(), "TMCO");
EXPECT_EQ(nearest3->id(), "KLSX");
EXPECT_EQ(nearest4->id(), "TSTL");
}
} // namespace config } // namespace config
} // namespace qt } // namespace qt
} // namespace scwx } // namespace scwx

View file

@ -2,6 +2,6 @@ pip install conan
pip install geopandas pip install geopandas
pip install GitPython pip install GitPython
pip install sphinx pip install sphinx
pip install sphinx_rtd_theme pip install sphinx-rtd-theme
pip install breathe pip install breathe
conan profile new default --detect conan profile new default --detect