mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 04:30:05 +00:00 
			
		
		
		
	Radial data packet
This commit is contained in:
		
							parent
							
								
									c2ca9a3eca
								
							
						
					
					
						commit
						c9617f13b0
					
				
					 5 changed files with 284 additions and 1 deletions
				
			
		
							
								
								
									
										49
									
								
								wxdata/include/scwx/wsr88d/rpg/radial_data_packet.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								wxdata/include/scwx/wsr88d/rpg/radial_data_packet.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <scwx/wsr88d/rpg/packet.hpp> | ||||
| 
 | ||||
| #include <cstdint> | ||||
| #include <memory> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace wsr88d | ||||
| { | ||||
| namespace rpg | ||||
| { | ||||
| 
 | ||||
| class RadialDataPacketImpl; | ||||
| 
 | ||||
| class RadialDataPacket : public Packet | ||||
| { | ||||
| public: | ||||
|    explicit RadialDataPacket(); | ||||
|    ~RadialDataPacket(); | ||||
| 
 | ||||
|    RadialDataPacket(const RadialDataPacket&) = delete; | ||||
|    RadialDataPacket& operator=(const RadialDataPacket&) = delete; | ||||
| 
 | ||||
|    RadialDataPacket(RadialDataPacket&&) noexcept; | ||||
|    RadialDataPacket& operator=(RadialDataPacket&&) noexcept; | ||||
| 
 | ||||
|    uint16_t packet_code() const; | ||||
|    uint16_t index_of_first_range_bin() const; | ||||
|    uint16_t number_of_range_bins() const; | ||||
|    int16_t  i_center_of_sweep() const; | ||||
|    int16_t  j_center_of_sweep() const; | ||||
|    float    scale_factor() const; | ||||
|    uint16_t number_of_radials() const; | ||||
| 
 | ||||
|    size_t data_size() const override; | ||||
| 
 | ||||
|    bool Parse(std::istream& is) override; | ||||
| 
 | ||||
|    static std::shared_ptr<RadialDataPacket> Create(std::istream& is); | ||||
| 
 | ||||
| private: | ||||
|    std::unique_ptr<RadialDataPacketImpl> p; | ||||
| }; | ||||
| 
 | ||||
| } // namespace rpg
 | ||||
| } // namespace wsr88d
 | ||||
| } // namespace scwx
 | ||||
|  | @ -2,6 +2,7 @@ | |||
| 
 | ||||
| #include <scwx/wsr88d/rpg/linked_contour_vector_packet.hpp> | ||||
| #include <scwx/wsr88d/rpg/linked_vector_packet.hpp> | ||||
| #include <scwx/wsr88d/rpg/radial_data_packet.hpp> | ||||
| #include <scwx/wsr88d/rpg/set_color_level_packet.hpp> | ||||
| #include <scwx/wsr88d/rpg/text_and_special_symbol_packet.hpp> | ||||
| #include <scwx/wsr88d/rpg/unlinked_contour_vector_packet.hpp> | ||||
|  | @ -33,7 +34,8 @@ static const std::unordered_map<uint16_t, CreateMessageFunction> create_ { | |||
|    {10, UnlinkedVectorPacket::Create}, | ||||
|    {0x0802, SetColorLevelPacket::Create}, | ||||
|    {0x0E03, LinkedContourVectorPacket::Create}, | ||||
|    {0x3501, UnlinkedContourVectorPacket::Create}}; | ||||
|    {0x3501, UnlinkedContourVectorPacket::Create}, | ||||
|    {0xAF1F, RadialDataPacket::Create}}; | ||||
| 
 | ||||
| std::shared_ptr<Packet> PacketFactory::Create(std::istream& is) | ||||
| { | ||||
|  | @ -62,6 +64,9 @@ std::shared_ptr<Packet> PacketFactory::Create(std::istream& is) | |||
| 
 | ||||
|    if (packetValid) | ||||
|    { | ||||
|       BOOST_LOG_TRIVIAL(trace) | ||||
|          << logPrefix_ << "Found packet code: " << packetCode << " (0x" | ||||
|          << std::hex << packetCode << std::dec << ")"; | ||||
|       packet = create_.at(packetCode)(is); | ||||
|    } | ||||
| 
 | ||||
|  |  | |||
|  | @ -109,6 +109,8 @@ bool ProductSymbologyBlock::Parse(std::istream& is) | |||
| 
 | ||||
|       for (uint16_t i = 0; i < p->numberOfLayers_; i++) | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(trace) << logPrefix_ << "Layer " << i; | ||||
| 
 | ||||
|          std::vector<std::shared_ptr<Packet>> packetList; | ||||
| 
 | ||||
|          is.read(reinterpret_cast<char*>(&layerDivider), 2); | ||||
|  |  | |||
							
								
								
									
										225
									
								
								wxdata/source/scwx/wsr88d/rpg/radial_data_packet.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								wxdata/source/scwx/wsr88d/rpg/radial_data_packet.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,225 @@ | |||
| #include <scwx/wsr88d/rpg/radial_data_packet.hpp> | ||||
| 
 | ||||
| #include <istream> | ||||
| #include <string> | ||||
| 
 | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace wsr88d | ||||
| { | ||||
| namespace rpg | ||||
| { | ||||
| 
 | ||||
| static const std::string logPrefix_ = | ||||
|    "[scwx::wsr88d::rpg::radial_data_packet] "; | ||||
| 
 | ||||
| struct Radial | ||||
| { | ||||
|    uint16_t             numberOfRleHalfwords_; | ||||
|    uint16_t             startAngle_; | ||||
|    uint16_t             angleDelta_; | ||||
|    std::vector<uint8_t> data_; | ||||
| 
 | ||||
|    Radial() : | ||||
|        numberOfRleHalfwords_ {0}, startAngle_ {0}, angleDelta_ {0}, data_ {} | ||||
|    { | ||||
|    } | ||||
| }; | ||||
| 
 | ||||
| class RadialDataPacketImpl | ||||
| { | ||||
| public: | ||||
|    explicit RadialDataPacketImpl() : | ||||
|        packetCode_ {}, | ||||
|        indexOfFirstRangeBin_ {}, | ||||
|        numberOfRangeBins_ {}, | ||||
|        iCenterOfSweep_ {}, | ||||
|        jCenterOfSweep_ {}, | ||||
|        scaleFactor_ {}, | ||||
|        dataSize_ {} {}; | ||||
|    ~RadialDataPacketImpl() = default; | ||||
| 
 | ||||
|    uint16_t packetCode_; | ||||
|    uint16_t indexOfFirstRangeBin_; | ||||
|    uint16_t numberOfRangeBins_; | ||||
|    int16_t  iCenterOfSweep_; | ||||
|    int16_t  jCenterOfSweep_; | ||||
|    uint16_t scaleFactor_; | ||||
|    uint16_t numberOfRadials_; | ||||
| 
 | ||||
|    // Repeat for each radial
 | ||||
|    std::vector<Radial> radial_; | ||||
| 
 | ||||
|    size_t dataSize_; | ||||
| }; | ||||
| 
 | ||||
| RadialDataPacket::RadialDataPacket() : | ||||
|     p(std::make_unique<RadialDataPacketImpl>()) | ||||
| { | ||||
| } | ||||
| RadialDataPacket::~RadialDataPacket() = default; | ||||
| 
 | ||||
| RadialDataPacket::RadialDataPacket(RadialDataPacket&&) noexcept = default; | ||||
| RadialDataPacket& | ||||
| RadialDataPacket::operator=(RadialDataPacket&&) noexcept = default; | ||||
| 
 | ||||
| uint16_t RadialDataPacket::packet_code() const | ||||
| { | ||||
|    return p->packetCode_; | ||||
| } | ||||
| 
 | ||||
| uint16_t RadialDataPacket::index_of_first_range_bin() const | ||||
| { | ||||
|    return p->indexOfFirstRangeBin_; | ||||
| } | ||||
| 
 | ||||
| uint16_t RadialDataPacket::number_of_range_bins() const | ||||
| { | ||||
|    return p->numberOfRangeBins_; | ||||
| } | ||||
| 
 | ||||
| int16_t RadialDataPacket::i_center_of_sweep() const | ||||
| { | ||||
|    return p->iCenterOfSweep_; | ||||
| } | ||||
| 
 | ||||
| int16_t RadialDataPacket::j_center_of_sweep() const | ||||
| { | ||||
|    return p->jCenterOfSweep_; | ||||
| } | ||||
| 
 | ||||
| float RadialDataPacket::scale_factor() const | ||||
| { | ||||
|    return p->scaleFactor_ * 0.001f; | ||||
| } | ||||
| 
 | ||||
| uint16_t RadialDataPacket::number_of_radials() const | ||||
| { | ||||
|    return p->numberOfRadials_; | ||||
| } | ||||
| 
 | ||||
| size_t RadialDataPacket::data_size() const | ||||
| { | ||||
|    return p->dataSize_; | ||||
| } | ||||
| 
 | ||||
| bool RadialDataPacket::Parse(std::istream& is) | ||||
| { | ||||
|    bool   blockValid = true; | ||||
|    size_t bytesRead  = 0; | ||||
| 
 | ||||
|    is.read(reinterpret_cast<char*>(&p->packetCode_), 2); | ||||
|    is.read(reinterpret_cast<char*>(&p->indexOfFirstRangeBin_), 2); | ||||
|    is.read(reinterpret_cast<char*>(&p->numberOfRangeBins_), 2); | ||||
|    is.read(reinterpret_cast<char*>(&p->iCenterOfSweep_), 2); | ||||
|    is.read(reinterpret_cast<char*>(&p->jCenterOfSweep_), 2); | ||||
|    is.read(reinterpret_cast<char*>(&p->scaleFactor_), 2); | ||||
|    is.read(reinterpret_cast<char*>(&p->numberOfRadials_), 2); | ||||
|    bytesRead += 14; | ||||
| 
 | ||||
|    p->packetCode_           = ntohs(p->packetCode_); | ||||
|    p->indexOfFirstRangeBin_ = ntohs(p->indexOfFirstRangeBin_); | ||||
|    p->numberOfRangeBins_    = ntohs(p->numberOfRangeBins_); | ||||
|    p->iCenterOfSweep_       = ntohs(p->iCenterOfSweep_); | ||||
|    p->jCenterOfSweep_       = ntohs(p->jCenterOfSweep_); | ||||
|    p->scaleFactor_          = ntohs(p->scaleFactor_); | ||||
|    p->numberOfRadials_      = ntohs(p->numberOfRadials_); | ||||
| 
 | ||||
|    if (is.eof()) | ||||
|    { | ||||
|       BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Reached end of file"; | ||||
|       blockValid = false; | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       if (p->packetCode_ != 0xAF1F) | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(warning) | ||||
|             << logPrefix_ << "Invalid packet code: " << p->packetCode_; | ||||
|          blockValid = false; | ||||
|       } | ||||
|       if (p->numberOfRangeBins_ < 1 || p->numberOfRangeBins_ > 460) | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(warning) | ||||
|             << logPrefix_ | ||||
|             << "Invalid number of range bins: " << p->numberOfRangeBins_; | ||||
|          blockValid = false; | ||||
|       } | ||||
|       if (p->numberOfRadials_ < 1 || p->numberOfRadials_ > 400) | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(warning) | ||||
|             << logPrefix_ | ||||
|             << "Invalid number of radials: " << p->numberOfRadials_; | ||||
|          blockValid = false; | ||||
|       } | ||||
|    } | ||||
| 
 | ||||
|    if (blockValid) | ||||
|    { | ||||
|       p->radial_.resize(p->numberOfRadials_); | ||||
| 
 | ||||
|       for (uint16_t r = 0; r < p->numberOfRadials_; r++) | ||||
|       { | ||||
|          Radial& radial = p->radial_[r]; | ||||
| 
 | ||||
|          is.read(reinterpret_cast<char*>(&radial.numberOfRleHalfwords_), 2); | ||||
|          is.read(reinterpret_cast<char*>(&radial.startAngle_), 2); | ||||
|          is.read(reinterpret_cast<char*>(&radial.angleDelta_), 2); | ||||
|          bytesRead += 6; | ||||
| 
 | ||||
|          radial.numberOfRleHalfwords_ = ntohs(radial.numberOfRleHalfwords_); | ||||
|          radial.startAngle_           = ntohs(radial.startAngle_); | ||||
|          radial.angleDelta_           = ntohs(radial.angleDelta_); | ||||
| 
 | ||||
|          if (radial.numberOfRleHalfwords_ < 1 || | ||||
|              radial.numberOfRleHalfwords_ > 230) | ||||
|          { | ||||
|             BOOST_LOG_TRIVIAL(warning) | ||||
|                << logPrefix_ << "Invalid number of RLE halfwords: " | ||||
|                << radial.numberOfRleHalfwords_ << " (Radial " << r << ")"; | ||||
|             blockValid = false; | ||||
|             break; | ||||
|          } | ||||
| 
 | ||||
|          // Read RLE halfwords
 | ||||
|          size_t dataSize = radial.numberOfRleHalfwords_ * 2; | ||||
|          radial.data_.resize(dataSize); | ||||
|          is.read(reinterpret_cast<char*>(radial.data_.data()), dataSize); | ||||
|          bytesRead += dataSize; | ||||
| 
 | ||||
|          // If the final byte is 0, truncate it
 | ||||
|          if (radial.data_.back() == 0) | ||||
|          { | ||||
|             radial.data_.pop_back(); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| 
 | ||||
|    p->dataSize_ = bytesRead; | ||||
| 
 | ||||
|    if (!ValidateMessage(is, bytesRead)) | ||||
|    { | ||||
|       blockValid = false; | ||||
|    } | ||||
| 
 | ||||
|    return blockValid; | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<RadialDataPacket> RadialDataPacket::Create(std::istream& is) | ||||
| { | ||||
|    std::shared_ptr<RadialDataPacket> packet = | ||||
|       std::make_shared<RadialDataPacket>(); | ||||
| 
 | ||||
|    if (!packet->Parse(is)) | ||||
|    { | ||||
|       packet.reset(); | ||||
|    } | ||||
| 
 | ||||
|    return packet; | ||||
| } | ||||
| 
 | ||||
| } // namespace rpg
 | ||||
| } // namespace wsr88d
 | ||||
| } // namespace scwx
 | ||||
|  | @ -53,6 +53,7 @@ set(HDR_WSR88D_RPG include/scwx/wsr88d/rpg/level3_message_header.hpp | |||
|                    include/scwx/wsr88d/rpg/packet_factory.hpp | ||||
|                    include/scwx/wsr88d/rpg/product_description_block.hpp | ||||
|                    include/scwx/wsr88d/rpg/product_symbology_block.hpp | ||||
|                    include/scwx/wsr88d/rpg/radial_data_packet.hpp | ||||
|                    include/scwx/wsr88d/rpg/set_color_level_packet.hpp | ||||
|                    include/scwx/wsr88d/rpg/text_and_special_symbol_packet.hpp | ||||
|                    include/scwx/wsr88d/rpg/unlinked_contour_vector_packet.hpp | ||||
|  | @ -65,6 +66,7 @@ set(SRC_WSR88D_RPG source/scwx/wsr88d/rpg/level3_message_header.cpp | |||
|                    source/scwx/wsr88d/rpg/packet_factory.cpp | ||||
|                    source/scwx/wsr88d/rpg/product_description_block.cpp | ||||
|                    source/scwx/wsr88d/rpg/product_symbology_block.cpp | ||||
|                    source/scwx/wsr88d/rpg/radial_data_packet.cpp | ||||
|                    source/scwx/wsr88d/rpg/set_color_level_packet.cpp | ||||
|                    source/scwx/wsr88d/rpg/text_and_special_symbol_packet.cpp | ||||
|                    source/scwx/wsr88d/rpg/unlinked_contour_vector_packet.cpp | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat