mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 13:00:05 +00:00 
			
		
		
		
	Generate hover text for storm tracking information
This commit is contained in:
		
							parent
							
								
									b4b1706587
								
							
						
					
					
						commit
						29e87fc11e
					
				
					 3 changed files with 158 additions and 63 deletions
				
			
		|  | @ -22,7 +22,8 @@ struct LinkedVectorDrawItem | ||||||
| { | { | ||||||
|    LinkedVectorDrawItem( |    LinkedVectorDrawItem( | ||||||
|       const common::Coordinate& center, |       const common::Coordinate& center, | ||||||
|       const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket) |       const std::shared_ptr<const wsr88d::rpg::LinkedVectorPacket>& | ||||||
|  |          vectorPacket) | ||||||
|    { |    { | ||||||
|       coordinates_.push_back(util::GeographicLib::GetCoordinate( |       coordinates_.push_back(util::GeographicLib::GetCoordinate( | ||||||
|          center, vectorPacket->start_i_km(), vectorPacket->start_j_km())); |          center, vectorPacket->start_i_km(), vectorPacket->start_j_km())); | ||||||
|  | @ -137,7 +138,7 @@ void LinkedVectors::StartVectors() | ||||||
| 
 | 
 | ||||||
| std::shared_ptr<LinkedVectorDrawItem> LinkedVectors::AddVector( | std::shared_ptr<LinkedVectorDrawItem> LinkedVectors::AddVector( | ||||||
|    const common::Coordinate&                                     center, |    const common::Coordinate&                                     center, | ||||||
|    const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket) |    const std::shared_ptr<const wsr88d::rpg::LinkedVectorPacket>& vectorPacket) | ||||||
| { | { | ||||||
|    return p->vectorList_.emplace_back( |    return p->vectorList_.emplace_back( | ||||||
|       std::make_shared<LinkedVectorDrawItem>(center, vectorPacket)); |       std::make_shared<LinkedVectorDrawItem>(center, vectorPacket)); | ||||||
|  |  | ||||||
|  | @ -82,9 +82,10 @@ public: | ||||||
|     * |     * | ||||||
|     * @return Linked vector draw item |     * @return Linked vector draw item | ||||||
|     */ |     */ | ||||||
|    std::shared_ptr<LinkedVectorDrawItem> AddVector( |    std::shared_ptr<LinkedVectorDrawItem> | ||||||
|       const common::Coordinate&                               center, |    AddVector(const common::Coordinate& center, | ||||||
|       const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket); |              const std::shared_ptr<const wsr88d::rpg::LinkedVectorPacket>& | ||||||
|  |                 vectorPacket); | ||||||
| 
 | 
 | ||||||
|    /**
 |    /**
 | ||||||
|     * Sets the modulate color of a linked vector. |     * Sets the modulate color of a linked vector. | ||||||
|  |  | ||||||
|  | @ -2,12 +2,13 @@ | ||||||
| #include <scwx/qt/gl/draw/linked_vectors.hpp> | #include <scwx/qt/gl/draw/linked_vectors.hpp> | ||||||
| #include <scwx/qt/manager/radar_product_manager.hpp> | #include <scwx/qt/manager/radar_product_manager.hpp> | ||||||
| #include <scwx/qt/view/overlay_product_view.hpp> | #include <scwx/qt/view/overlay_product_view.hpp> | ||||||
| #include <scwx/wsr88d/rpg/graphic_product_message.hpp> |  | ||||||
| #include <scwx/wsr88d/rpg/linked_vector_packet.hpp> | #include <scwx/wsr88d/rpg/linked_vector_packet.hpp> | ||||||
| #include <scwx/wsr88d/rpg/rpg_types.hpp> | #include <scwx/wsr88d/rpg/rpg_types.hpp> | ||||||
| #include <scwx/wsr88d/rpg/scit_data_packet.hpp> | #include <scwx/wsr88d/rpg/scit_data_packet.hpp> | ||||||
| #include <scwx/wsr88d/rpg/storm_id_symbol_packet.hpp> | #include <scwx/wsr88d/rpg/storm_id_symbol_packet.hpp> | ||||||
|  | #include <scwx/wsr88d/rpg/storm_tracking_information_message.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | #include <scwx/util/time.hpp> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx | ||||||
| { | { | ||||||
|  | @ -33,19 +34,32 @@ public: | ||||||
|    void UpdateStormTrackingInformation(); |    void UpdateStormTrackingInformation(); | ||||||
| 
 | 
 | ||||||
|    static void HandleLinkedVectorPacket( |    static void HandleLinkedVectorPacket( | ||||||
|       const std::shared_ptr<wsr88d::rpg::Packet>& packet, |       const std::shared_ptr<const wsr88d::rpg::Packet>& packet, | ||||||
|       const common::Coordinate&                         center, |       const common::Coordinate&                         center, | ||||||
|       const std::string&                                hoverText, |       const std::string&                                hoverText, | ||||||
|       boost::gil::rgba32f_pixel_t                       color, |       boost::gil::rgba32f_pixel_t                       color, | ||||||
|       bool                                        tickRadiusIncrement, |       units::length::nautical_miles<float>              tickRadius, | ||||||
|  |       units::length::nautical_miles<float>              tickRadiusIncrement, | ||||||
|       std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors); |       std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors); | ||||||
|    static void HandleScitDataPacket( |    static void HandleScitDataPacket( | ||||||
|       const std::shared_ptr<wsr88d::rpg::Packet>& packet, |       const std::shared_ptr<const wsr88d::rpg::StormTrackingInformationMessage>& | ||||||
|  |                                                         sti, | ||||||
|  |       const std::shared_ptr<const wsr88d::rpg::Packet>& packet, | ||||||
|       const common::Coordinate&                         center, |       const common::Coordinate&                         center, | ||||||
|       const std::string&                                stormId, |       const std::string&                                stormId, | ||||||
|  |       const std::string&                                hoverText, | ||||||
|       std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors); |       std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors); | ||||||
|    static void | 
 | ||||||
|    HandleStormIdPacket(const std::shared_ptr<wsr88d::rpg::Packet>& packet, |    static void HandleStormIdPacket( | ||||||
|  |       const std::shared_ptr<const wsr88d::rpg::StormTrackingInformationMessage>& | ||||||
|  |                                                         sti, | ||||||
|  |       const std::shared_ptr<const wsr88d::rpg::Packet>& packet, | ||||||
|  |       std::string&                                      stormId, | ||||||
|  |       std::string&                                      hoverText); | ||||||
|  | 
 | ||||||
|  |    static std::string BuildHoverText( | ||||||
|  |       const std::shared_ptr< | ||||||
|  |          const scwx::wsr88d::rpg::StormTrackingInformationMessage>& sti, | ||||||
|       std::string&                                                  stormId); |       std::string&                                                  stormId); | ||||||
| 
 | 
 | ||||||
|    OverlayProductLayer* self_; |    OverlayProductLayer* self_; | ||||||
|  | @ -123,7 +137,7 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation() | ||||||
|    float longitude = 0.0f; |    float longitude = 0.0f; | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<wsr88d::Level3File> l3File                        = nullptr; |    std::shared_ptr<wsr88d::Level3File> l3File                        = nullptr; | ||||||
|    std::shared_ptr<wsr88d::rpg::GraphicProductMessage> gpm    = nullptr; |    std::shared_ptr<wsr88d::rpg::StormTrackingInformationMessage> sti = nullptr; | ||||||
|    std::shared_ptr<wsr88d::rpg::ProductSymbologyBlock>           psb = nullptr; |    std::shared_ptr<wsr88d::rpg::ProductSymbologyBlock>           psb = nullptr; | ||||||
|    if (record != nullptr) |    if (record != nullptr) | ||||||
|    { |    { | ||||||
|  | @ -131,12 +145,12 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation() | ||||||
|    } |    } | ||||||
|    if (l3File != nullptr) |    if (l3File != nullptr) | ||||||
|    { |    { | ||||||
|       gpm = std::dynamic_pointer_cast<wsr88d::rpg::GraphicProductMessage>( |       sti = std::dynamic_pointer_cast< | ||||||
|          l3File->message()); |          wsr88d::rpg::StormTrackingInformationMessage>(l3File->message()); | ||||||
|    } |    } | ||||||
|    if (gpm != nullptr) |    if (sti != nullptr) | ||||||
|    { |    { | ||||||
|       psb = gpm->symbology_block(); |       psb = sti->symbology_block(); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    linkedVectors_->StartVectors(); |    linkedVectors_->StartVectors(); | ||||||
|  | @ -155,6 +169,7 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation() | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       std::string stormId = "?"; |       std::string stormId = "?"; | ||||||
|  |       std::string hoverText {}; | ||||||
| 
 | 
 | ||||||
|       for (std::size_t i = 0; i < psb->number_of_layers(); ++i) |       for (std::size_t i = 0; i < psb->number_of_layers(); ++i) | ||||||
|       { |       { | ||||||
|  | @ -164,15 +179,19 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation() | ||||||
|             switch (packet->packet_code()) |             switch (packet->packet_code()) | ||||||
|             { |             { | ||||||
|             case static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::StormId): |             case static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::StormId): | ||||||
|                HandleStormIdPacket(packet, stormId); |                HandleStormIdPacket(sti, packet, stormId, hoverText); | ||||||
|                break; |                break; | ||||||
| 
 | 
 | ||||||
|             case static_cast<std::uint16_t>( |             case static_cast<std::uint16_t>( | ||||||
|                wsr88d::rpg::PacketCode::ScitPastData): |                wsr88d::rpg::PacketCode::ScitPastData): | ||||||
|             case static_cast<std::uint16_t>( |             case static_cast<std::uint16_t>( | ||||||
|                wsr88d::rpg::PacketCode::ScitForecastData): |                wsr88d::rpg::PacketCode::ScitForecastData): | ||||||
|                HandleScitDataPacket( |                HandleScitDataPacket(sti, | ||||||
|                   packet, {latitude, longitude}, stormId, linkedVectors_); |                                     packet, | ||||||
|  |                                     {latitude, longitude}, | ||||||
|  |                                     stormId, | ||||||
|  |                                     hoverText, | ||||||
|  |                                     linkedVectors_); | ||||||
|                break; |                break; | ||||||
| 
 | 
 | ||||||
|             default: |             default: | ||||||
|  | @ -192,41 +211,63 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void OverlayProductLayer::Impl::HandleStormIdPacket( | void OverlayProductLayer::Impl::HandleStormIdPacket( | ||||||
|    const std::shared_ptr<wsr88d::rpg::Packet>& packet, std::string& stormId) |    const std::shared_ptr<const wsr88d::rpg::StormTrackingInformationMessage>& | ||||||
|  |                                                      sti, | ||||||
|  |    const std::shared_ptr<const wsr88d::rpg::Packet>& packet, | ||||||
|  |    std::string&                                      stormId, | ||||||
|  |    std::string&                                      hoverText) | ||||||
| { | { | ||||||
|    auto stormIdPacket = |    auto stormIdPacket = | ||||||
|       std::dynamic_pointer_cast<wsr88d::rpg::StormIdSymbolPacket>(packet); |       std::dynamic_pointer_cast<const wsr88d::rpg::StormIdSymbolPacket>(packet); | ||||||
| 
 | 
 | ||||||
|    if (stormIdPacket != nullptr && stormIdPacket->RecordCount() > 0) |    if (stormIdPacket != nullptr && stormIdPacket->RecordCount() > 0) | ||||||
|    { |    { | ||||||
|       stormId   = stormIdPacket->storm_id(0); |       stormId   = stormIdPacket->storm_id(0); | ||||||
|  |       hoverText = BuildHoverText(sti, stormId); | ||||||
|    } |    } | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|       logger_->warn("Invalid Storm ID Packet"); |       logger_->warn("Invalid Storm ID Packet"); | ||||||
| 
 | 
 | ||||||
|       stormId = "?"; |       stormId = "?"; | ||||||
|  |       hoverText.clear(); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void OverlayProductLayer::Impl::HandleScitDataPacket( | void OverlayProductLayer::Impl::HandleScitDataPacket( | ||||||
|    const std::shared_ptr<wsr88d::rpg::Packet>& packet, |    const std::shared_ptr<const wsr88d::rpg::StormTrackingInformationMessage>& | ||||||
|  |                                                      sti, | ||||||
|  |    const std::shared_ptr<const wsr88d::rpg::Packet>& packet, | ||||||
|    const common::Coordinate&                         center, |    const common::Coordinate&                         center, | ||||||
|    const std::string&                                stormId, |    const std::string&                                stormId, | ||||||
|  |    const std::string&                                hoverText, | ||||||
|    std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors) |    std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors) | ||||||
| { | { | ||||||
|    auto scitDataPacket = |    auto scitDataPacket = | ||||||
|       std::dynamic_pointer_cast<wsr88d::rpg::ScitDataPacket>(packet); |       std::dynamic_pointer_cast<const wsr88d::rpg::ScitDataPacket>(packet); | ||||||
| 
 | 
 | ||||||
|    if (scitDataPacket != nullptr) |    if (scitDataPacket != nullptr) | ||||||
|    { |    { | ||||||
|       boost::gil::rgba32f_pixel_t color {1.0f, 1.0f, 1.0f, 1.0f}; |       boost::gil::rgba32f_pixel_t color {1.0f, 1.0f, 1.0f, 1.0f}; | ||||||
|       bool                        tickRadiusIncrement = true; | 
 | ||||||
|  |       units::length::nautical_miles<float> tickRadius {0.5f}; | ||||||
|  |       units::length::nautical_miles<float> tickRadiusIncrement {0.0f}; | ||||||
|  | 
 | ||||||
|  |       auto stiRecord = sti->sti_record(stormId); | ||||||
|  | 
 | ||||||
|       if (scitDataPacket->packet_code() == |       if (scitDataPacket->packet_code() == | ||||||
|           static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::ScitPastData)) |           static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::ScitPastData)) | ||||||
|       { |       { | ||||||
|  |          // If this is past data, the default tick radius and increment with a
 | ||||||
|  |          // darker color
 | ||||||
|          color = {0.5f, 0.5f, 0.5f, 1.0f}; |          color = {0.5f, 0.5f, 0.5f, 1.0f}; | ||||||
|          tickRadiusIncrement = false; |       } | ||||||
|  |       else if (stiRecord != nullptr && stiRecord->meanError_.has_value()) | ||||||
|  |       { | ||||||
|  |          // If this is forecast data, use the mean error as the radius (minimum
 | ||||||
|  |          // of the default value), incrementing by the mean error
 | ||||||
|  |          tickRadiusIncrement = stiRecord->meanError_.value(); | ||||||
|  |          tickRadius          = std::max(tickRadius, tickRadiusIncrement); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       for (auto& subpacket : scitDataPacket->packet_list()) |       for (auto& subpacket : scitDataPacket->packet_list()) | ||||||
|  | @ -237,8 +278,9 @@ void OverlayProductLayer::Impl::HandleScitDataPacket( | ||||||
|             wsr88d::rpg::PacketCode::LinkedVectorNoValue): |             wsr88d::rpg::PacketCode::LinkedVectorNoValue): | ||||||
|             HandleLinkedVectorPacket(subpacket, |             HandleLinkedVectorPacket(subpacket, | ||||||
|                                      center, |                                      center, | ||||||
|                                      stormId, |                                      hoverText, | ||||||
|                                      color, |                                      color, | ||||||
|  |                                      tickRadius, | ||||||
|                                      tickRadiusIncrement, |                                      tickRadiusIncrement, | ||||||
|                                      linkedVectors); |                                      linkedVectors); | ||||||
|             break; |             break; | ||||||
|  | @ -257,15 +299,16 @@ void OverlayProductLayer::Impl::HandleScitDataPacket( | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void OverlayProductLayer::Impl::HandleLinkedVectorPacket( | void OverlayProductLayer::Impl::HandleLinkedVectorPacket( | ||||||
|    const std::shared_ptr<wsr88d::rpg::Packet>& packet, |    const std::shared_ptr<const wsr88d::rpg::Packet>& packet, | ||||||
|    const common::Coordinate&                         center, |    const common::Coordinate&                         center, | ||||||
|    const std::string&                                hoverText, |    const std::string&                                hoverText, | ||||||
|    boost::gil::rgba32f_pixel_t                       color, |    boost::gil::rgba32f_pixel_t                       color, | ||||||
|    bool                                        tickRadiusIncrement, |    units::length::nautical_miles<float>              tickRadius, | ||||||
|  |    units::length::nautical_miles<float>              tickRadiusIncrement, | ||||||
|    std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors) |    std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors) | ||||||
| { | { | ||||||
|    auto linkedVectorPacket = |    auto linkedVectorPacket = | ||||||
|       std::dynamic_pointer_cast<wsr88d::rpg::LinkedVectorPacket>(packet); |       std::dynamic_pointer_cast<const wsr88d::rpg::LinkedVectorPacket>(packet); | ||||||
| 
 | 
 | ||||||
|    if (linkedVectorPacket != nullptr) |    if (linkedVectorPacket != nullptr) | ||||||
|    { |    { | ||||||
|  | @ -274,19 +317,9 @@ void OverlayProductLayer::Impl::HandleLinkedVectorPacket( | ||||||
|       gl::draw::LinkedVectors::SetVectorModulate(di, color); |       gl::draw::LinkedVectors::SetVectorModulate(di, color); | ||||||
|       gl::draw::LinkedVectors::SetVectorHoverText(di, hoverText); |       gl::draw::LinkedVectors::SetVectorHoverText(di, hoverText); | ||||||
|       gl::draw::LinkedVectors::SetVectorTicksEnabled(di, true); |       gl::draw::LinkedVectors::SetVectorTicksEnabled(di, true); | ||||||
|       gl::draw::LinkedVectors::SetVectorTickRadius( |       gl::draw::LinkedVectors::SetVectorTickRadius(di, tickRadius); | ||||||
|          di, units::length::nautical_miles<double> {1.0}); |  | ||||||
| 
 |  | ||||||
|       if (tickRadiusIncrement) |  | ||||||
|       { |  | ||||||
|       gl::draw::LinkedVectors::SetVectorTickRadiusIncrement( |       gl::draw::LinkedVectors::SetVectorTickRadiusIncrement( | ||||||
|             di, units::length::nautical_miles<double> {1.0}); |          di, tickRadiusIncrement); | ||||||
|       } |  | ||||||
|       else |  | ||||||
|       { |  | ||||||
|          gl::draw::LinkedVectors::SetVectorTickRadiusIncrement( |  | ||||||
|             di, units::length::nautical_miles<double> {0.0}); |  | ||||||
|       } |  | ||||||
|    } |    } | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|  | @ -294,6 +327,66 @@ void OverlayProductLayer::Impl::HandleLinkedVectorPacket( | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::string OverlayProductLayer::Impl::BuildHoverText( | ||||||
|  |    const std::shared_ptr< | ||||||
|  |       const scwx::wsr88d::rpg::StormTrackingInformationMessage>& sti, | ||||||
|  |    std::string&                                                  stormId) | ||||||
|  | { | ||||||
|  |    std::string hoverText = fmt::format("Storm ID: {}", stormId); | ||||||
|  | 
 | ||||||
|  |    auto stiRecord = sti->sti_record(stormId); | ||||||
|  | 
 | ||||||
|  |    if (stiRecord != nullptr) | ||||||
|  |    { | ||||||
|  |       if (stiRecord->direction_.has_value() && stiRecord->speed_.has_value()) | ||||||
|  |       { | ||||||
|  |          hoverText += | ||||||
|  |             fmt::format("\nMovement: {} @ {}", | ||||||
|  |                         units::to_string(stiRecord->direction_.value()), | ||||||
|  |                         units::to_string(stiRecord->speed_.value())); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (stiRecord->maxDbz_.has_value() && | ||||||
|  |           stiRecord->maxDbzHeight_.has_value()) | ||||||
|  |       { | ||||||
|  |          hoverText += | ||||||
|  |             fmt::format("\nMax dBZ: {} ({} kft)", | ||||||
|  |                         stiRecord->maxDbz_.value(), | ||||||
|  |                         stiRecord->maxDbzHeight_.value().value() / 1000.0f); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (stiRecord->forecastError_.has_value()) | ||||||
|  |       { | ||||||
|  |          hoverText += | ||||||
|  |             fmt::format("\nForecast Error: {}", | ||||||
|  |                         units::to_string(stiRecord->forecastError_.value())); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (stiRecord->meanError_.has_value()) | ||||||
|  |       { | ||||||
|  |          hoverText += | ||||||
|  |             fmt::format("\nMean Error: {}", | ||||||
|  |                         units::to_string(stiRecord->meanError_.value())); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    auto dateTime = sti->date_time(); | ||||||
|  |    if (dateTime.has_value()) | ||||||
|  |    { | ||||||
|  |       hoverText += | ||||||
|  |          fmt::format("\nDate/Time: {}", util::TimeString(dateTime.value())); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    auto forecastInterval = sti->forecast_interval(); | ||||||
|  |    if (forecastInterval.has_value()) | ||||||
|  |    { | ||||||
|  |       hoverText += fmt::format("\nForecast Interval: {} min", | ||||||
|  |                                forecastInterval.value().count()); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return hoverText; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool OverlayProductLayer::RunMousePicking( | bool OverlayProductLayer::RunMousePicking( | ||||||
|    const QMapLibreGL::CustomLayerRenderParameters& params, |    const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
|    const QPointF&                                  mouseLocalPos, |    const QPointF&                                  mouseLocalPos, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat