From 33f92bcda574fbb0a5646bcea333f6ec5e5393a1 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sat, 3 May 2025 10:16:20 -0400 Subject: [PATCH] Add radar line and radar distance/altitude tooltip --- .../scwx/qt/map/radar_product_layer.cpp | 80 +++++++++++++++++-- .../source/scwx/qt/map/radar_site_layer.cpp | 71 +++++++++++++++- 2 files changed, 141 insertions(+), 10 deletions(-) diff --git a/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp index 8d243973..f305f4f7 100644 --- a/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -353,11 +356,66 @@ bool RadarProductLayer::RunMousePicking( std::shared_ptr radarProductView = context()->radar_product_view(); - if (radarProductView == nullptr) + if (context()->radar_site() == nullptr) { return itemPicked; } + // Get distance and altitude of point + const double radarLatitude = context()->radar_site()->latitude(); + const double radarLongitude = context()->radar_site()->longitude(); + + const auto distanceMeters = util::GeographicLib::GetDistance( + mouseGeoCoords.latitude_, + mouseGeoCoords.longitude_, + radarLatitude, + radarLongitude); + + const std::string distanceUnitName = + settings::UnitSettings::Instance().distance_units().GetValue(); + const types::DistanceUnits distanceUnits = + types::GetDistanceUnitsFromName(distanceUnitName); + const double distanceScale = types::GetDistanceUnitsScale(distanceUnits); + const std::string distanceAbbrev = + types::GetDistanceUnitsAbbreviation(distanceUnits); + + const double distance = distanceMeters.value() * + scwx::common::kKilometersPerMeter * distanceScale; + std::string distanceHeightStr = + fmt::format("{:.2f} {}", distance, distanceAbbrev); + + if (radarProductView == nullptr) + { + util::tooltip::Show(distanceHeightStr, mouseGlobalPos); + itemPicked = true; + return itemPicked; + } + + std::optional elevation = radarProductView->elevation(); + if (elevation.has_value()) + { + const auto altitudeMeters = + util::GeographicLib::GetRadarBeamAltititude( + distanceMeters, + units::angle::degrees(*elevation), + context()->radar_site()->altitude()); + + const std::string heightUnitName = + settings::UnitSettings::Instance().echo_tops_units().GetValue(); + const types::EchoTopsUnits heightUnits = + types::GetEchoTopsUnitsFromName(heightUnitName); + const double heightScale = types::GetEchoTopsUnitsScale(heightUnits); + const std::string heightAbbrev = + types::GetEchoTopsUnitsAbbreviation(heightUnits); + + const double altitude = altitudeMeters.value() * + scwx::common::kKilometersPerMeter * + heightScale; + + distanceHeightStr = fmt::format( + "{}\n{:.2f} {}", distanceHeightStr, altitude, heightAbbrev); + } + std::optional binLevel = radarProductView->GetBinLevel(mouseGeoCoords); @@ -383,12 +441,13 @@ bool RadarProductLayer::RunMousePicking( if (codeName != codeShortName && !codeShortName.empty()) { // There is a unique long and short name for the code - hoverText = fmt::format("{}: {}", codeShortName, codeName); + hoverText = fmt::format( + "{}: {}\n{}", codeShortName, codeName, distanceHeightStr); } else { // Otherwise, only use the long name (always present) - hoverText = codeName; + hoverText = fmt::format("{}\n{}", codeName, distanceHeightStr); } // Show the tooltip @@ -439,17 +498,20 @@ bool RadarProductLayer::RunMousePicking( { // Don't display a units value that wasn't intended to be // displayed - hoverText = fmt::format("{}{}", f, suffix); + hoverText = + fmt::format("{}{}\n{}", f, suffix, distanceHeightStr); } else if (std::isalpha(static_cast(units.at(0)))) { // dBZ, Kts, etc. - hoverText = fmt::format("{} {}{}", f, units, suffix); + hoverText = fmt::format( + "{} {}{}\n{}", f, units, suffix, distanceHeightStr); } else { // %, etc. - hoverText = fmt::format("{}{}{}", f, units, suffix); + hoverText = fmt::format( + "{}{}{}\n{}", f, units, suffix, distanceHeightStr); } // Show the tooltip @@ -458,6 +520,12 @@ bool RadarProductLayer::RunMousePicking( itemPicked = true; } } + else + { + // Always show tooltip for distance and altitude + util::tooltip::Show(distanceHeightStr, mouseGlobalPos); + itemPicked = true; + } } return itemPicked; diff --git a/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp index 65b53f14..67c0ed0e 100644 --- a/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -10,6 +11,8 @@ #include #include +#include + namespace scwx { namespace qt @@ -23,11 +26,32 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class RadarSiteLayer::Impl { public: - explicit Impl(RadarSiteLayer* self) : self_ {self} {} + explicit Impl(RadarSiteLayer* self, std::shared_ptr& context) : + self_ {self}, + geoLines_ {std::make_shared(context)} + { + geoLines_->StartLines(); + radarSiteLines_[0] = geoLines_->AddLine(); + radarSiteLines_[1] = geoLines_->AddLine(); + geoLines_->FinishLines(); + + static const boost::gil::rgba32f_pixel_t color0 {0.0f, 0.0f, 0.0f, 1.0f}; + static const boost::gil::rgba32f_pixel_t color1 {1.0f, 1.0f, 1.0f, 1.0f}; + static const float width = 1; + geoLines_->SetLineModulate(radarSiteLines_[0], color0); + geoLines_->SetLineWidth(radarSiteLines_[0], width + 2); + + geoLines_->SetLineModulate(radarSiteLines_[1], color1); + geoLines_->SetLineWidth(radarSiteLines_[1], width); + + self_->AddDrawItem(geoLines_); + geoLines_->set_thresholded(false); + } ~Impl() = default; void RenderRadarSite(const QMapLibre::CustomLayerRenderParameters& params, std::shared_ptr& radarSite); + void RenderRadarLine(); RadarSiteLayer* self_; @@ -41,10 +65,13 @@ public: float halfHeight_ {}; std::string hoverText_ {}; + + std::shared_ptr geoLines_; + std::array, 2> radarSiteLines_; }; RadarSiteLayer::RadarSiteLayer(std::shared_ptr context) : - DrawLayer(context, "RadarSiteLayer"), p(std::make_unique(this)) + DrawLayer(context, "RadarSiteLayer"), p(std::make_unique(this, context)) { } @@ -56,7 +83,7 @@ void RadarSiteLayer::Initialize() p->radarSites_ = config::RadarSite::GetAll(); - ImGuiInitialize(); + DrawLayer::Initialize(); } void RadarSiteLayer::Render( @@ -96,8 +123,12 @@ void RadarSiteLayer::Render( } ImGui::PopStyleVar(); - ImGuiFrameEnd(); + p->RenderRadarLine(); + + DrawLayer::RenderWithoutImGui(params); + + ImGuiFrameEnd(); SCWX_GL_CHECK_ERROR(); } @@ -163,6 +194,38 @@ void RadarSiteLayer::Impl::RenderRadarSite( } } +void RadarSiteLayer::Impl::RenderRadarLine() +{ + // TODO check if state is updated. + if ((QGuiApplication::keyboardModifiers() & + Qt::KeyboardModifier::ShiftModifier) && + self_->context()->radar_site() != nullptr) + { + const auto& mouseCoord = self_->context()->mouse_coordinate(); + const double radarLatitude = self_->context()->radar_site()->latitude(); + const double radarLongitude = self_->context()->radar_site()->longitude(); + + geoLines_->SetLineLocation(radarSiteLines_[0], + static_cast(mouseCoord.latitude_), + static_cast(mouseCoord.longitude_), + static_cast(radarLatitude), + static_cast(radarLongitude)); + geoLines_->SetLineVisible(radarSiteLines_[0], true); + + geoLines_->SetLineLocation(radarSiteLines_[1], + static_cast(mouseCoord.latitude_), + static_cast(mouseCoord.longitude_), + static_cast(radarLatitude), + static_cast(radarLongitude)); + geoLines_->SetLineVisible(radarSiteLines_[1], true); + } + else + { + geoLines_->SetLineVisible(radarSiteLines_[0], false); + geoLines_->SetLineVisible(radarSiteLines_[1], false); + } +} + void RadarSiteLayer::Deinitialize() { logger_->debug("Deinitialize()");