mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 02:10: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
				
			
		|  | @ -21,8 +21,9 @@ static const boost::gil::rgba32f_pixel_t kBlack {0.0f, 0.0f, 0.0f, 1.0f}; | |||
| struct LinkedVectorDrawItem | ||||
| { | ||||
|    LinkedVectorDrawItem( | ||||
|       const common::Coordinate&                               center, | ||||
|       const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket) | ||||
|       const common::Coordinate& center, | ||||
|       const std::shared_ptr<const wsr88d::rpg::LinkedVectorPacket>& | ||||
|          vectorPacket) | ||||
|    { | ||||
|       coordinates_.push_back(util::GeographicLib::GetCoordinate( | ||||
|          center, vectorPacket->start_i_km(), vectorPacket->start_j_km())); | ||||
|  | @ -136,8 +137,8 @@ void LinkedVectors::StartVectors() | |||
| } | ||||
| 
 | ||||
| std::shared_ptr<LinkedVectorDrawItem> LinkedVectors::AddVector( | ||||
|    const common::Coordinate&                               center, | ||||
|    const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket) | ||||
|    const common::Coordinate&                                     center, | ||||
|    const std::shared_ptr<const wsr88d::rpg::LinkedVectorPacket>& vectorPacket) | ||||
| { | ||||
|    return p->vectorList_.emplace_back( | ||||
|       std::make_shared<LinkedVectorDrawItem>(center, vectorPacket)); | ||||
|  |  | |||
|  | @ -82,9 +82,10 @@ public: | |||
|     * | ||||
|     * @return Linked vector draw item | ||||
|     */ | ||||
|    std::shared_ptr<LinkedVectorDrawItem> AddVector( | ||||
|       const common::Coordinate&                               center, | ||||
|       const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket); | ||||
|    std::shared_ptr<LinkedVectorDrawItem> | ||||
|    AddVector(const common::Coordinate& center, | ||||
|              const std::shared_ptr<const wsr88d::rpg::LinkedVectorPacket>& | ||||
|                 vectorPacket); | ||||
| 
 | ||||
|    /**
 | ||||
|     * Sets the modulate color of a linked vector. | ||||
|  |  | |||
|  | @ -2,12 +2,13 @@ | |||
| #include <scwx/qt/gl/draw/linked_vectors.hpp> | ||||
| #include <scwx/qt/manager/radar_product_manager.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/rpg_types.hpp> | ||||
| #include <scwx/wsr88d/rpg/scit_data_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/time.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
|  | @ -33,20 +34,33 @@ public: | |||
|    void UpdateStormTrackingInformation(); | ||||
| 
 | ||||
|    static void HandleLinkedVectorPacket( | ||||
|       const std::shared_ptr<wsr88d::rpg::Packet>& packet, | ||||
|       const common::Coordinate&                   center, | ||||
|       const std::string&                          hoverText, | ||||
|       boost::gil::rgba32f_pixel_t                 color, | ||||
|       bool                                        tickRadiusIncrement, | ||||
|       std::shared_ptr<gl::draw::LinkedVectors>&   linkedVectors); | ||||
|       const std::shared_ptr<const wsr88d::rpg::Packet>& packet, | ||||
|       const common::Coordinate&                         center, | ||||
|       const std::string&                                hoverText, | ||||
|       boost::gil::rgba32f_pixel_t                       color, | ||||
|       units::length::nautical_miles<float>              tickRadius, | ||||
|       units::length::nautical_miles<float>              tickRadiusIncrement, | ||||
|       std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors); | ||||
|    static void HandleScitDataPacket( | ||||
|       const std::shared_ptr<wsr88d::rpg::Packet>& packet, | ||||
|       const common::Coordinate&                   center, | ||||
|       const std::string&                          stormId, | ||||
|       std::shared_ptr<gl::draw::LinkedVectors>&   linkedVectors); | ||||
|    static void | ||||
|    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, | ||||
|       const common::Coordinate&                         center, | ||||
|       const std::string&                                stormId, | ||||
|       const std::string&                                hoverText, | ||||
|       std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors); | ||||
| 
 | ||||
|    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); | ||||
| 
 | ||||
|    OverlayProductLayer* self_; | ||||
| 
 | ||||
|  | @ -122,21 +136,21 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation() | |||
|    float latitude  = 0.0f; | ||||
|    float longitude = 0.0f; | ||||
| 
 | ||||
|    std::shared_ptr<wsr88d::Level3File>                 l3File = nullptr; | ||||
|    std::shared_ptr<wsr88d::rpg::GraphicProductMessage> gpm    = nullptr; | ||||
|    std::shared_ptr<wsr88d::rpg::ProductSymbologyBlock> psb    = nullptr; | ||||
|    std::shared_ptr<wsr88d::Level3File> l3File                        = nullptr; | ||||
|    std::shared_ptr<wsr88d::rpg::StormTrackingInformationMessage> sti = nullptr; | ||||
|    std::shared_ptr<wsr88d::rpg::ProductSymbologyBlock>           psb = nullptr; | ||||
|    if (record != nullptr) | ||||
|    { | ||||
|       l3File = record->level3_file(); | ||||
|    } | ||||
|    if (l3File != nullptr) | ||||
|    { | ||||
|       gpm = std::dynamic_pointer_cast<wsr88d::rpg::GraphicProductMessage>( | ||||
|          l3File->message()); | ||||
|       sti = std::dynamic_pointer_cast< | ||||
|          wsr88d::rpg::StormTrackingInformationMessage>(l3File->message()); | ||||
|    } | ||||
|    if (gpm != nullptr) | ||||
|    if (sti != nullptr) | ||||
|    { | ||||
|       psb = gpm->symbology_block(); | ||||
|       psb = sti->symbology_block(); | ||||
|    } | ||||
| 
 | ||||
|    linkedVectors_->StartVectors(); | ||||
|  | @ -155,6 +169,7 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation() | |||
|       } | ||||
| 
 | ||||
|       std::string stormId = "?"; | ||||
|       std::string hoverText {}; | ||||
| 
 | ||||
|       for (std::size_t i = 0; i < psb->number_of_layers(); ++i) | ||||
|       { | ||||
|  | @ -164,15 +179,19 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation() | |||
|             switch (packet->packet_code()) | ||||
|             { | ||||
|             case static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::StormId): | ||||
|                HandleStormIdPacket(packet, stormId); | ||||
|                HandleStormIdPacket(sti, packet, stormId, hoverText); | ||||
|                break; | ||||
| 
 | ||||
|             case static_cast<std::uint16_t>( | ||||
|                wsr88d::rpg::PacketCode::ScitPastData): | ||||
|             case static_cast<std::uint16_t>( | ||||
|                wsr88d::rpg::PacketCode::ScitForecastData): | ||||
|                HandleScitDataPacket( | ||||
|                   packet, {latitude, longitude}, stormId, linkedVectors_); | ||||
|                HandleScitDataPacket(sti, | ||||
|                                     packet, | ||||
|                                     {latitude, longitude}, | ||||
|                                     stormId, | ||||
|                                     hoverText, | ||||
|                                     linkedVectors_); | ||||
|                break; | ||||
| 
 | ||||
|             default: | ||||
|  | @ -192,41 +211,63 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation() | |||
| } | ||||
| 
 | ||||
| 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 = | ||||
|       std::dynamic_pointer_cast<wsr88d::rpg::StormIdSymbolPacket>(packet); | ||||
|       std::dynamic_pointer_cast<const wsr88d::rpg::StormIdSymbolPacket>(packet); | ||||
| 
 | ||||
|    if (stormIdPacket != nullptr && stormIdPacket->RecordCount() > 0) | ||||
|    { | ||||
|       stormId = stormIdPacket->storm_id(0); | ||||
|       stormId   = stormIdPacket->storm_id(0); | ||||
|       hoverText = BuildHoverText(sti, stormId); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       logger_->warn("Invalid Storm ID Packet"); | ||||
| 
 | ||||
|       stormId = "?"; | ||||
|       hoverText.clear(); | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| void OverlayProductLayer::Impl::HandleScitDataPacket( | ||||
|    const std::shared_ptr<wsr88d::rpg::Packet>& packet, | ||||
|    const common::Coordinate&                   center, | ||||
|    const std::string&                          stormId, | ||||
|    std::shared_ptr<gl::draw::LinkedVectors>&   linkedVectors) | ||||
|    const std::shared_ptr<const wsr88d::rpg::StormTrackingInformationMessage>& | ||||
|                                                      sti, | ||||
|    const std::shared_ptr<const wsr88d::rpg::Packet>& packet, | ||||
|    const common::Coordinate&                         center, | ||||
|    const std::string&                                stormId, | ||||
|    const std::string&                                hoverText, | ||||
|    std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors) | ||||
| { | ||||
|    auto scitDataPacket = | ||||
|       std::dynamic_pointer_cast<wsr88d::rpg::ScitDataPacket>(packet); | ||||
|       std::dynamic_pointer_cast<const wsr88d::rpg::ScitDataPacket>(packet); | ||||
| 
 | ||||
|    if (scitDataPacket != nullptr) | ||||
|    { | ||||
|       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() == | ||||
|           static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::ScitPastData)) | ||||
|       { | ||||
|          color               = {0.5f, 0.5f, 0.5f, 1.0f}; | ||||
|          tickRadiusIncrement = false; | ||||
|          // If this is past data, the default tick radius and increment with a
 | ||||
|          // darker color
 | ||||
|          color = {0.5f, 0.5f, 0.5f, 1.0f}; | ||||
|       } | ||||
|       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()) | ||||
|  | @ -237,8 +278,9 @@ void OverlayProductLayer::Impl::HandleScitDataPacket( | |||
|             wsr88d::rpg::PacketCode::LinkedVectorNoValue): | ||||
|             HandleLinkedVectorPacket(subpacket, | ||||
|                                      center, | ||||
|                                      stormId, | ||||
|                                      hoverText, | ||||
|                                      color, | ||||
|                                      tickRadius, | ||||
|                                      tickRadiusIncrement, | ||||
|                                      linkedVectors); | ||||
|             break; | ||||
|  | @ -257,15 +299,16 @@ void OverlayProductLayer::Impl::HandleScitDataPacket( | |||
| } | ||||
| 
 | ||||
| void OverlayProductLayer::Impl::HandleLinkedVectorPacket( | ||||
|    const std::shared_ptr<wsr88d::rpg::Packet>& packet, | ||||
|    const common::Coordinate&                   center, | ||||
|    const std::string&                          hoverText, | ||||
|    boost::gil::rgba32f_pixel_t                 color, | ||||
|    bool                                        tickRadiusIncrement, | ||||
|    std::shared_ptr<gl::draw::LinkedVectors>&   linkedVectors) | ||||
|    const std::shared_ptr<const wsr88d::rpg::Packet>& packet, | ||||
|    const common::Coordinate&                         center, | ||||
|    const std::string&                                hoverText, | ||||
|    boost::gil::rgba32f_pixel_t                       color, | ||||
|    units::length::nautical_miles<float>              tickRadius, | ||||
|    units::length::nautical_miles<float>              tickRadiusIncrement, | ||||
|    std::shared_ptr<gl::draw::LinkedVectors>&         linkedVectors) | ||||
| { | ||||
|    auto linkedVectorPacket = | ||||
|       std::dynamic_pointer_cast<wsr88d::rpg::LinkedVectorPacket>(packet); | ||||
|       std::dynamic_pointer_cast<const wsr88d::rpg::LinkedVectorPacket>(packet); | ||||
| 
 | ||||
|    if (linkedVectorPacket != nullptr) | ||||
|    { | ||||
|  | @ -274,19 +317,9 @@ void OverlayProductLayer::Impl::HandleLinkedVectorPacket( | |||
|       gl::draw::LinkedVectors::SetVectorModulate(di, color); | ||||
|       gl::draw::LinkedVectors::SetVectorHoverText(di, hoverText); | ||||
|       gl::draw::LinkedVectors::SetVectorTicksEnabled(di, true); | ||||
|       gl::draw::LinkedVectors::SetVectorTickRadius( | ||||
|          di, units::length::nautical_miles<double> {1.0}); | ||||
| 
 | ||||
|       if (tickRadiusIncrement) | ||||
|       { | ||||
|          gl::draw::LinkedVectors::SetVectorTickRadiusIncrement( | ||||
|             di, units::length::nautical_miles<double> {1.0}); | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|          gl::draw::LinkedVectors::SetVectorTickRadiusIncrement( | ||||
|             di, units::length::nautical_miles<double> {0.0}); | ||||
|       } | ||||
|       gl::draw::LinkedVectors::SetVectorTickRadius(di, tickRadius); | ||||
|       gl::draw::LinkedVectors::SetVectorTickRadiusIncrement( | ||||
|          di, tickRadiusIncrement); | ||||
|    } | ||||
|    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( | ||||
|    const QMapLibreGL::CustomLayerRenderParameters& params, | ||||
|    const QPointF&                                  mouseLocalPos, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat