mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 01:40:04 +00:00 
			
		
		
		
	Add Storm Tracking Information display to Overlay Product Layer
This commit is contained in:
		
							parent
							
								
									a0701df13f
								
							
						
					
					
						commit
						900267b16f
					
				
					 2 changed files with 264 additions and 2 deletions
				
			
		|  | @ -1,4 +1,12 @@ | ||||||
| #include <scwx/qt/map/overlay_product_layer.hpp> | #include <scwx/qt/map/overlay_product_layer.hpp> | ||||||
|  | #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/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx | ||||||
|  | @ -14,13 +22,54 @@ static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
| class OverlayProductLayer::Impl | class OverlayProductLayer::Impl | ||||||
| { | { | ||||||
| public: | public: | ||||||
|    explicit Impl(std::shared_ptr<MapContext> context) {} |    explicit Impl(OverlayProductLayer*               self, | ||||||
|  |                  const std::shared_ptr<MapContext>& context) : | ||||||
|  |        self_ {self}, | ||||||
|  |        linkedVectors_ {std::make_shared<gl::draw::LinkedVectors>(context)} | ||||||
|  |    { | ||||||
|  |    } | ||||||
|    ~Impl() = default; |    ~Impl() = default; | ||||||
|  | 
 | ||||||
|  |    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, | ||||||
|  |       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); | ||||||
|  | 
 | ||||||
|  |    OverlayProductLayer* self_; | ||||||
|  | 
 | ||||||
|  |    bool stiNeedsUpdate_ {false}; | ||||||
|  | 
 | ||||||
|  |    std::shared_ptr<gl::draw::LinkedVectors> linkedVectors_; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| OverlayProductLayer::OverlayProductLayer(std::shared_ptr<MapContext> context) : | OverlayProductLayer::OverlayProductLayer(std::shared_ptr<MapContext> context) : | ||||||
|     DrawLayer(context), p(std::make_unique<Impl>(context)) |     DrawLayer(context), p(std::make_unique<Impl>(this, context)) | ||||||
| { | { | ||||||
|  |    auto overlayProductView = context->overlay_product_view(); | ||||||
|  |    connect(overlayProductView.get(), | ||||||
|  |            &view::OverlayProductView::ProductUpdated, | ||||||
|  |            this, | ||||||
|  |            [this](std::string product) | ||||||
|  |            { | ||||||
|  |               if (product == "NST") | ||||||
|  |               { | ||||||
|  |                  p->stiNeedsUpdate_ = true; | ||||||
|  |               } | ||||||
|  |            }); | ||||||
|  | 
 | ||||||
|  |    AddDrawItem(p->linkedVectors_); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| OverlayProductLayer::~OverlayProductLayer() = default; | OverlayProductLayer::~OverlayProductLayer() = default; | ||||||
|  | @ -29,6 +78,8 @@ void OverlayProductLayer::Initialize() | ||||||
| { | { | ||||||
|    logger_->debug("Initialize()"); |    logger_->debug("Initialize()"); | ||||||
| 
 | 
 | ||||||
|  |    p->UpdateStormTrackingInformation(); | ||||||
|  | 
 | ||||||
|    DrawLayer::Initialize(); |    DrawLayer::Initialize(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -40,6 +91,11 @@ void OverlayProductLayer::Render( | ||||||
|    // Set OpenGL blend mode for transparency
 |    // Set OpenGL blend mode for transparency
 | ||||||
|    gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |    gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||||
| 
 | 
 | ||||||
|  |    if (p->stiNeedsUpdate_) | ||||||
|  |    { | ||||||
|  |       p->UpdateStormTrackingInformation(); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    DrawLayer::Render(params); |    DrawLayer::Render(params); | ||||||
| 
 | 
 | ||||||
|    SCWX_GL_CHECK_ERROR(); |    SCWX_GL_CHECK_ERROR(); | ||||||
|  | @ -52,6 +108,170 @@ void OverlayProductLayer::Deinitialize() | ||||||
|    DrawLayer::Deinitialize(); |    DrawLayer::Deinitialize(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void OverlayProductLayer::Impl::UpdateStormTrackingInformation() | ||||||
|  | { | ||||||
|  |    logger_->debug("Update Storm Tracking Information"); | ||||||
|  | 
 | ||||||
|  |    stiNeedsUpdate_ = false; | ||||||
|  | 
 | ||||||
|  |    auto overlayProductView  = self_->context()->overlay_product_view(); | ||||||
|  |    auto radarProductManager = overlayProductView->radar_product_manager(); | ||||||
|  |    auto record              = overlayProductView->radar_product_record("NST"); | ||||||
|  | 
 | ||||||
|  |    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; | ||||||
|  |    if (record != nullptr) | ||||||
|  |    { | ||||||
|  |       l3File = record->level3_file(); | ||||||
|  |    } | ||||||
|  |    if (l3File != nullptr) | ||||||
|  |    { | ||||||
|  |       gpm = std::dynamic_pointer_cast<wsr88d::rpg::GraphicProductMessage>( | ||||||
|  |          l3File->message()); | ||||||
|  |    } | ||||||
|  |    if (gpm != nullptr) | ||||||
|  |    { | ||||||
|  |       psb = gpm->symbology_block(); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    linkedVectors_->StartVectors(); | ||||||
|  | 
 | ||||||
|  |    if (psb != nullptr) | ||||||
|  |    { | ||||||
|  |       std::shared_ptr<config::RadarSite> radarSite = nullptr; | ||||||
|  |       if (radarProductManager != nullptr) | ||||||
|  |       { | ||||||
|  |          radarSite = radarProductManager->radar_site(); | ||||||
|  |       } | ||||||
|  |       if (radarSite != nullptr) | ||||||
|  |       { | ||||||
|  |          latitude  = radarSite->latitude(); | ||||||
|  |          longitude = radarSite->longitude(); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       std::string stormId = "?"; | ||||||
|  | 
 | ||||||
|  |       for (std::size_t i = 0; i < psb->number_of_layers(); ++i) | ||||||
|  |       { | ||||||
|  |          auto packetList = psb->packet_list(static_cast<std::uint16_t>(i)); | ||||||
|  |          for (auto& packet : packetList) | ||||||
|  |          { | ||||||
|  |             switch (packet->packet_code()) | ||||||
|  |             { | ||||||
|  |             case static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::StormId): | ||||||
|  |                HandleStormIdPacket(packet, stormId); | ||||||
|  |                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_); | ||||||
|  |                break; | ||||||
|  | 
 | ||||||
|  |             default: | ||||||
|  |                logger_->trace("Ignoring packet type: {}", | ||||||
|  |                               packet->packet_code()); | ||||||
|  |                break; | ||||||
|  |             } | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |    else | ||||||
|  |    { | ||||||
|  |       logger_->trace("No Storm Tracking Information found"); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    linkedVectors_->FinishVectors(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void OverlayProductLayer::Impl::HandleStormIdPacket( | ||||||
|  |    const std::shared_ptr<wsr88d::rpg::Packet>& packet, std::string& stormId) | ||||||
|  | { | ||||||
|  |    auto stormIdPacket = | ||||||
|  |       std::dynamic_pointer_cast<wsr88d::rpg::StormIdSymbolPacket>(packet); | ||||||
|  | 
 | ||||||
|  |    if (stormIdPacket != nullptr && stormIdPacket->RecordCount() > 0) | ||||||
|  |    { | ||||||
|  |       stormId = stormIdPacket->storm_id(0); | ||||||
|  |    } | ||||||
|  |    else | ||||||
|  |    { | ||||||
|  |       logger_->warn("Invalid Storm ID Packet"); | ||||||
|  | 
 | ||||||
|  |       stormId = "?"; | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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) | ||||||
|  | { | ||||||
|  |    auto scitDataPacket = | ||||||
|  |       std::dynamic_pointer_cast<wsr88d::rpg::ScitDataPacket>(packet); | ||||||
|  | 
 | ||||||
|  |    if (scitDataPacket != nullptr) | ||||||
|  |    { | ||||||
|  |       boost::gil::rgba32f_pixel_t color {1.0f, 1.0f, 1.0f, 1.0f}; | ||||||
|  |       if (scitDataPacket->packet_code() == | ||||||
|  |           static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::ScitPastData)) | ||||||
|  |       { | ||||||
|  |          color = {0.5f, 0.5f, 0.5f, 1.0f}; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       for (auto& subpacket : scitDataPacket->packet_list()) | ||||||
|  |       { | ||||||
|  |          switch (subpacket->packet_code()) | ||||||
|  |          { | ||||||
|  |          case static_cast<std::uint16_t>( | ||||||
|  |             wsr88d::rpg::PacketCode::LinkedVectorNoValue): | ||||||
|  |             HandleLinkedVectorPacket( | ||||||
|  |                subpacket, center, stormId, color, linkedVectors); | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |          default: | ||||||
|  |             logger_->trace("Ignoring SCIT subpacket type: {}", | ||||||
|  |                            subpacket->packet_code()); | ||||||
|  |             break; | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |    else | ||||||
|  |    { | ||||||
|  |       logger_->warn("Invalid SCIT Data Packet"); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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, | ||||||
|  |    std::shared_ptr<gl::draw::LinkedVectors>&   linkedVectors) | ||||||
|  | { | ||||||
|  |    auto linkedVectorPacket = | ||||||
|  |       std::dynamic_pointer_cast<wsr88d::rpg::LinkedVectorPacket>(packet); | ||||||
|  | 
 | ||||||
|  |    if (linkedVectorPacket != nullptr) | ||||||
|  |    { | ||||||
|  |       auto di = linkedVectors->AddVector(center, linkedVectorPacket); | ||||||
|  |       gl::draw::LinkedVectors::SetVectorWidth(di, 1.0f); | ||||||
|  |       gl::draw::LinkedVectors::SetVectorModulate(di, color); | ||||||
|  |       gl::draw::LinkedVectors::SetVectorHoverText(di, hoverText); | ||||||
|  |    } | ||||||
|  |    else | ||||||
|  |    { | ||||||
|  |       logger_->warn("Invalid Linked Vector Packet"); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool OverlayProductLayer::RunMousePicking( | bool OverlayProductLayer::RunMousePicking( | ||||||
|    const QMapLibreGL::CustomLayerRenderParameters& params, |    const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
|    const QPointF&                                  mouseLocalPos, |    const QPointF&                                  mouseLocalPos, | ||||||
|  |  | ||||||
|  | @ -7,6 +7,48 @@ namespace wsr88d | ||||||
| namespace rpg | namespace rpg | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  | enum class PacketCode : std::uint16_t | ||||||
|  | { | ||||||
|  |    TextNoValue                          = 1, | ||||||
|  |    SpecialSymbol                        = 2, | ||||||
|  |    MesocycloneSymbol3                   = 3, | ||||||
|  |    WindBarbData                         = 4, | ||||||
|  |    VectorArrowData                      = 5, | ||||||
|  |    LinkedVectorNoValue                  = 6, | ||||||
|  |    UnlinkedVectorNoValue                = 7, | ||||||
|  |    TextUniform                          = 8, | ||||||
|  |    LinkedVectorUniform                  = 9, | ||||||
|  |    UnlinkedVectorUniform                = 10, | ||||||
|  |    MesocycloneSymbol11                  = 11, | ||||||
|  |    TornadoVortexSignatureSymbol         = 12, | ||||||
|  |    HailPositiveSymbol                   = 13, | ||||||
|  |    HailProbableSymbol                   = 14, | ||||||
|  |    StormId                              = 15, | ||||||
|  |    DigitalRadialDataArray               = 16, | ||||||
|  |    DigitalPrecipitationDataArray        = 17, | ||||||
|  |    PrecipitationRateDataArray           = 18, | ||||||
|  |    HdaHailSymbol                        = 19, | ||||||
|  |    PointFeatureSymbol                   = 20, | ||||||
|  |    CellTrendData                        = 21, | ||||||
|  |    CellTrendVolumeScanTimes             = 22, | ||||||
|  |    ScitPastData                         = 23, | ||||||
|  |    ScitForecastData                     = 24, | ||||||
|  |    StiCircle                            = 25, | ||||||
|  |    ElevatedTornadoVortexSignatureSymbol = 26, | ||||||
|  |    GenericData28                        = 28, | ||||||
|  |    GenericData29                        = 29, | ||||||
|  |    SetColorLevel                        = 0x0802, | ||||||
|  |    LinkedContourVector                  = 0x0E03, | ||||||
|  |    UnlinkedContourVector                = 0x3501, | ||||||
|  |    MapMessage0E23                       = 0x0E23, | ||||||
|  |    MapMessage3521                       = 0x3521, | ||||||
|  |    MapMessage4E00                       = 0x4E00, | ||||||
|  |    MapMessage4E01                       = 0x4E01, | ||||||
|  |    RadialData                           = 0xAF1F, | ||||||
|  |    RasterDataBA07                       = 0xBA07, | ||||||
|  |    RasterDataBA0F                       = 0xBA0F | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| enum class SpecialSymbol | enum class SpecialSymbol | ||||||
| { | { | ||||||
|    PastStormCellPosition, |    PastStormCellPosition, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat