diff --git a/external/aws-sdk-cpp.cmake b/external/aws-sdk-cpp.cmake index 3bbb73ac..8e2138c4 100644 --- a/external/aws-sdk-cpp.cmake +++ b/external/aws-sdk-cpp.cmake @@ -8,12 +8,26 @@ set(ENABLE_TESTING OFF) set(ENABLE_UNITY_BUILD ON) set(MINIMIZE_SIZE OFF) -if(NOT CMAKE_EXE_LINKER_FLAGS_DEBUGOPT) - set(CMAKE_EXE_LINKER_FLAGS_DEBUGOPT "") -endif() +# Some variables also need set in the cache... set them all! +set(BUILD_ONLY "s3" CACHE STRING "A semi-colon delimited list of the projects to build") +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) +# 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(aws-c-auth PROPERTIES FOLDER aws-sdk-cpp) diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 3d936401..9609ddf0 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -163,6 +163,7 @@ set(HDR_UTIL source/scwx/qt/util/color.hpp source/scwx/qt/util/file.hpp source/scwx/qt/util/font.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/streams.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/font.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/texture_atlas.cpp source/scwx/qt/util/q_file_buffer.cpp diff --git a/scwx-qt/source/scwx/qt/config/radar_site.cpp b/scwx-qt/source/scwx/qt/config/radar_site.cpp index 74a44290..6feadde9 100644 --- a/scwx-qt/source/scwx/qt/config/radar_site.cpp +++ b/scwx-qt/source/scwx/qt/config/radar_site.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -162,6 +163,44 @@ std::vector> RadarSite::GetAll() return radarSites; } +std::shared_ptr RadarSite::FindNearest( + double latitude, double longitude, std::optional type) +{ + std::shared_lock lock(siteMutex_); + + double distanceInMeters; + + std::shared_ptr 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::shared_lock lock(siteMutex_); diff --git a/scwx-qt/source/scwx/qt/config/radar_site.hpp b/scwx-qt/source/scwx/qt/config/radar_site.hpp index 279e8c13..953659f5 100644 --- a/scwx-qt/source/scwx/qt/config/radar_site.hpp +++ b/scwx-qt/source/scwx/qt/config/radar_site.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -38,6 +39,20 @@ public: static std::shared_ptr Get(const std::string& id); static std::vector> 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 + FindNearest(double latitude, + double longitude, + std::optional type = std::nullopt); + static void Initialize(); static size_t ReadConfig(const std::string& path); diff --git a/scwx-qt/source/scwx/qt/gl/draw/geo_line.cpp b/scwx-qt/source/scwx/qt/gl/draw/geo_line.cpp index 04e57048..39567a2d 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_line.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_line.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -6,8 +7,6 @@ #include #include -#include - namespace scwx { namespace qt @@ -33,8 +32,7 @@ class GeoLine::Impl public: explicit Impl(std::shared_ptr context) : context_ {context}, - geodesic_(GeographicLib::Constants::WGS84_a(), - GeographicLib::Constants::WGS84_f()), + geodesic_ {util::GeographicLib::DefaultGeodesic()}, dirty_ {false}, visible_ {true}, points_ {}, @@ -55,7 +53,7 @@ public: std::shared_ptr context_; - GeographicLib::Geodesic geodesic_; + const GeographicLib::Geodesic& geodesic_; bool dirty_; diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index c1fcca6a..490a0826 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -530,7 +530,12 @@ void MainWindowImpl::ConnectOtherSignals() &ui::AlertDockWidget::MoveMap, this, [=](double latitude, double longitude) - { activeMap_->SetMapLocation(latitude, longitude); }, + { + for (map::MapWidget* map : maps_) + { + map->SetMapLocation(latitude, longitude, true); + } + }, Qt::QueuedConnection); connect(mainWindow_, &MainWindow::ActiveMapMoved, diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp index e7f1192f..80514e49 100644 --- a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -18,7 +19,6 @@ #include #include #include -#include #include #pragma warning(pop) @@ -81,7 +81,7 @@ public: group_ {group}, product_ {product}, refreshEnabled_ {false}, - refreshTimer_ {util::io_context()}, + refreshTimer_ {scwx::util::io_context()}, refreshTimerMutex_ {}, provider_ {nullptr} { @@ -303,8 +303,8 @@ void RadarProductManager::Initialize() boost::timer::cpu_timer timer; - GeographicLib::Geodesic geodesic(GeographicLib::Constants::WGS84_a(), - GeographicLib::Constants::WGS84_f()); + const GeographicLib::Geodesic& geodesic( + util::GeographicLib::DefaultGeodesic()); const QMapLibreGL::Coordinate radar(p->radarSite_->latitude(), p->radarSite_->longitude()); @@ -425,7 +425,7 @@ void RadarProductManager::EnableRefresh(common::RadarProductGroup group, p->GetLevel3ProviderManager(product); // Only enable refresh on available products - util::async( + scwx::util::async( [=]() { providerManager->provider_->RequestAvailableProducts(); @@ -467,7 +467,7 @@ void RadarProductManagerImpl::RefreshData( providerManager->refreshTimer_.cancel(); } - util::async( + scwx::util::async( [=]() { auto [newObjects, totalObjects] = @@ -547,7 +547,7 @@ void RadarProductManagerImpl::LoadProviderData( { logger_->debug("LoadProviderData: {}, {}", providerManager->name(), - util::TimeString(time)); + scwx::util::TimeString(time)); RadarProductManagerImpl::LoadNexradFile( [=, &recordMap, &recordMutex, &loadDataMutex]() @@ -589,7 +589,7 @@ void RadarProductManager::LoadLevel2Data( std::chrono::system_clock::time_point time, std::shared_ptr request) { - logger_->debug("LoadLevel2Data: {}", util::TimeString(time)); + logger_->debug("LoadLevel2Data: {}", scwx::util::TimeString(time)); p->LoadProviderData(time, p->level2ProviderManager_, @@ -604,7 +604,7 @@ void RadarProductManager::LoadLevel3Data( std::chrono::system_clock::time_point time, std::shared_ptr request) { - logger_->debug("LoadLevel3Data: {}", util::TimeString(time)); + logger_->debug("LoadLevel3Data: {}", scwx::util::TimeString(time)); // Look up provider manager std::shared_lock providerManagerLock(p->level3ProviderManagerMutex_); @@ -742,7 +742,7 @@ RadarProductManagerImpl::GetLevel2ProductRecord( else { // 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? if (record != nullptr && (time < record->level2_file()->start_time())) @@ -774,7 +774,7 @@ RadarProductManagerImpl::GetLevel3ProductRecord( } else { - record = util::GetBoundedElementValue(it->second, time); + record = scwx::util::GetBoundedElementValue(it->second, time); } } @@ -904,7 +904,7 @@ void RadarProductManager::UpdateAvailableProducts() logger_->debug("UpdateAvailableProducts()"); - util::async( + scwx::util::async( [=]() { auto level3ProviderManager = diff --git a/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp b/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp index 1aa7aac8..d84eee98 100644 --- a/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp @@ -190,23 +190,18 @@ void TextEventManager::Impl::HandleMessage( void TextEventManager::Impl::Refresh() { - using namespace std::chrono; - logger_->trace("Refresh"); // Take a unique lock before refreshing 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 - auto [newFiles, totalFiles] = warningsProvider_.ListFiles(newerThan); + auto [newFiles, totalFiles] = warningsProvider_.ListFiles(); if (newFiles > 0) { // Load new files - auto updatedFiles = warningsProvider_.LoadUpdatedFiles(newerThan); + auto updatedFiles = warningsProvider_.LoadUpdatedFiles(); // Handle messages for (auto& file : updatedFiles) diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp index b770ab66..40d45910 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -424,21 +424,31 @@ void MapWidget::SelectRadarProduct( 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); std::shared_ptr radarSite = config::RadarSite::Get(id); + SelectRadarSite(radarSite, updateCoordinates); +} + +void MapWidget::SelectRadarSite(std::shared_ptr radarSite, + bool updateCoordinates) +{ // Verify radar site is valid and has changed if (radarSite != nullptr && (p->radarProductManager_ == nullptr || - id != p->radarProductManager_->radar_site()->id())) + radarSite->id() != p->radarProductManager_->radar_site()->id())) { auto radarProductView = p->context_->radar_product_view(); - p->map_->setCoordinate({radarSite->latitude(), radarSite->longitude()}); - p->SetRadarSite(id); + if (updateCoordinates) + { + p->map_->setCoordinate( + {radarSite->latitude(), radarSite->longitude()}); + } + p->SetRadarSite(radarSite->id()); p->Update(); // 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 || p->prevLongitude_ != longitude) { + // Update the map location 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 nearestRadarSite = + config::RadarSite::FindNearest(latitude, longitude, "wsr88d"); + + // If found, select it + if (nearestRadarSite != nullptr) + { + SelectRadarSite(nearestRadarSite->id(), false); + } + } } } diff --git a/scwx-qt/source/scwx/qt/map/map_widget.hpp b/scwx-qt/source/scwx/qt/map/map_widget.hpp index 73e4aae2..63f51160 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.hpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.hpp @@ -48,10 +48,40 @@ public: const std::string& product, int16_t productCode); void SelectRadarProduct(std::shared_ptr 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 radarSite, + bool updateCoordinates = true); + void SetActive(bool isActive); 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, double longitude, double zoom, diff --git a/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp index 545d0880..ea4fa55b 100644 --- a/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp @@ -1,7 +1,7 @@ #include +#include #include -#include #include namespace scwx @@ -61,8 +61,8 @@ void RadarRangeLayer::Update(std::shared_ptr map, static std::shared_ptr GetRangeCircle(float range, QMapLibreGL::Coordinate center) { - GeographicLib::Geodesic geodesic(GeographicLib::Constants::WGS84_a(), - GeographicLib::Constants::WGS84_f()); + const GeographicLib::Geodesic& geodesic( + util::GeographicLib::DefaultGeodesic()); constexpr float angleDelta = 0.5f; constexpr float angleDeltaH = angleDelta / 2.0f; diff --git a/scwx-qt/source/scwx/qt/model/alert_model.cpp b/scwx-qt/source/scwx/qt/model/alert_model.cpp index a2213988..03d3119a 100644 --- a/scwx-qt/source/scwx/qt/model/alert_model.cpp +++ b/scwx-qt/source/scwx/qt/model/alert_model.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -9,7 +10,6 @@ #include -#include #include #include @@ -47,7 +47,7 @@ public: QList textEventKeys_; - GeographicLib::Geodesic geodesic_; + const GeographicLib::Geodesic& geodesic_; std::unordered_mapsegment_count(); 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 @@ -404,7 +403,7 @@ AlertModelImpl::GetStartTime(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 @@ -419,7 +418,7 @@ AlertModelImpl::GetEndTime(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 diff --git a/scwx-qt/source/scwx/qt/model/radar_site_model.cpp b/scwx-qt/source/scwx/qt/model/radar_site_model.cpp index 6e9b321c..bc059953 100644 --- a/scwx-qt/source/scwx/qt/model/radar_site_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_site_model.cpp @@ -1,13 +1,12 @@ #include #include #include +#include #include #include #include -#include - namespace scwx { namespace qt @@ -36,7 +35,7 @@ public: QList> radarSites_; - GeographicLib::Geodesic geodesic_; + const GeographicLib::Geodesic& geodesic_; std::unordered_map distanceMap_; scwx::common::DistanceType distanceDisplay_; @@ -186,8 +185,7 @@ void RadarSiteModel::HandleMapUpdate(double latitude, double longitude) RadarSiteModelImpl::RadarSiteModelImpl() : radarSites_ {}, - geodesic_(GeographicLib::Constants::WGS84_a(), - GeographicLib::Constants::WGS84_f()), + geodesic_(util::GeographicLib::DefaultGeodesic()), distanceMap_ {}, distanceDisplay_ {scwx::common::DistanceType::Miles}, previousPosition_ {} diff --git a/scwx-qt/source/scwx/qt/util/geographic_lib.cpp b/scwx-qt/source/scwx/qt/util/geographic_lib.cpp new file mode 100644 index 00000000..5c55b9e2 --- /dev/null +++ b/scwx-qt/source/scwx/qt/util/geographic_lib.cpp @@ -0,0 +1,24 @@ +#include + +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 diff --git a/scwx-qt/source/scwx/qt/util/geographic_lib.hpp b/scwx-qt/source/scwx/qt/util/geographic_lib.hpp new file mode 100644 index 00000000..3fe3c187 --- /dev/null +++ b/scwx-qt/source/scwx/qt/util/geographic_lib.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +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 diff --git a/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp b/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp index d606a581..84c896ae 100644 --- a/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp +++ b/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -7,7 +8,6 @@ #include #include -#include namespace scwx { @@ -202,12 +202,12 @@ void Level3RasterView::ComputeSweep() p->longitude_ = descriptionBlock->longitude_of_radar(); p->range_ = descriptionBlock->range(); p->sweepTime_ = - util::TimePoint(descriptionBlock->volume_scan_date(), - descriptionBlock->volume_scan_start_time() * 1000); + scwx::util::TimePoint(descriptionBlock->volume_scan_date(), + descriptionBlock->volume_scan_start_time() * 1000); p->vcp_ = descriptionBlock->volume_coverage_pattern(); - GeographicLib::Geodesic geodesic(GeographicLib::Constants::WGS84_a(), - GeographicLib::Constants::WGS84_f()); + const GeographicLib::Geodesic& geodesic = + util::GeographicLib::DefaultGeodesic(); const uint16_t xResolution = descriptionBlock->x_resolution_raw(); const uint16_t yResolution = descriptionBlock->y_resolution_raw(); diff --git a/test/source/scwx/qt/config/radar_site.test.cpp b/test/source/scwx/qt/config/radar_site.test.cpp index f69381d1..7c1dde91 100644 --- a/test/source/scwx/qt/config/radar_site.test.cpp +++ b/test/source/scwx/qt/config/radar_site.test.cpp @@ -12,12 +12,23 @@ namespace config static const std::string DEFAULT_RADAR_SITE_FILE = ":/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); - EXPECT_EQ(numSites, 204); + static void SetUpTestSuite() + { + 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::Get("KLSX"); @@ -31,6 +42,25 @@ TEST(RadarSite, DefaultConfig) EXPECT_DOUBLE_EQ(radarSite->longitude(), -90.682877); } +TEST_F(RadarSiteTest, FindNearest) +{ + ASSERT_GT(numSites_, 0); + + std::shared_ptr nearest1 = + RadarSite::FindNearest(46.591111, -112.020278); // Helena, MT + std::shared_ptr nearest2 = + RadarSite::FindNearest(28.54, -81.38); // Orlando, FL + std::shared_ptr nearest3 = + RadarSite::FindNearest(38.627222, -90.197778, "wsr88d"); // St Louis, MO + std::shared_ptr 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 qt } // namespace scwx diff --git a/tools/setup-common.bat b/tools/setup-common.bat index 09ad52ff..fb15e9a7 100644 --- a/tools/setup-common.bat +++ b/tools/setup-common.bat @@ -2,6 +2,6 @@ pip install conan pip install geopandas pip install GitPython pip install sphinx -pip install sphinx_rtd_theme +pip install sphinx-rtd-theme pip install breathe conan profile new default --detect