mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 01:40:04 +00:00 
			
		
		
		
	Add data level codes, refactor data value determination to product description block
This commit is contained in:
		
							parent
							
								
									b67f546774
								
							
						
					
					
						commit
						2f06076bb5
					
				
					 5 changed files with 407 additions and 51 deletions
				
			
		|  | @ -7,6 +7,8 @@ | ||||||
| #include <scwx/wsr88d/rpg/graphic_product_message.hpp> | #include <scwx/wsr88d/rpg/graphic_product_message.hpp> | ||||||
| #include <scwx/wsr88d/rpg/radial_data_packet.hpp> | #include <scwx/wsr88d/rpg/radial_data_packet.hpp> | ||||||
| 
 | 
 | ||||||
|  | #include <limits> | ||||||
|  | 
 | ||||||
| #include <boost/range/irange.hpp> | #include <boost/range/irange.hpp> | ||||||
| #include <boost/timer/timer.hpp> | #include <boost/timer/timer.hpp> | ||||||
| #include <fmt/format.h> | #include <fmt/format.h> | ||||||
|  | @ -240,15 +242,22 @@ void Level3ProductView::UpdateColorTable() | ||||||
|       return; |       return; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    int16_t  productCode = descriptionBlock->product_code(); |    std::int16_t productCode = descriptionBlock->product_code(); | ||||||
|    float        offset      = descriptionBlock->offset(); |    float        offset      = descriptionBlock->offset(); | ||||||
|    float        scale       = descriptionBlock->scale(); |    float        scale       = descriptionBlock->scale(); | ||||||
|    uint16_t threshold   = descriptionBlock->threshold(); |    std::uint8_t threshold   = static_cast<std::uint8_t>( | ||||||
|  |       std::clamp<std::uint16_t>(descriptionBlock->threshold(), | ||||||
|  |                                 std::numeric_limits<std::uint8_t>::min(), | ||||||
|  |                                 std::numeric_limits<std::uint8_t>::max())); | ||||||
| 
 | 
 | ||||||
|    // If the threshold is 2, the range min should be set to 1 for range folding
 |    // If the threshold is 2, the range min should be set to 1 for range
 | ||||||
|    uint16_t rangeMin       = std::min<uint16_t>(1, threshold); |    // folding
 | ||||||
|    uint16_t numberOfLevels = descriptionBlock->number_of_levels(); |    std::uint8_t  rangeMin       = std::min<std::uint8_t>(1, threshold); | ||||||
|    uint16_t rangeMax       = (numberOfLevels > 0) ? numberOfLevels - 1 : 0; |    std::uint16_t numberOfLevels = descriptionBlock->number_of_levels(); | ||||||
|  |    std::uint8_t  rangeMax       = static_cast<std::uint8_t>( | ||||||
|  |       std::clamp<std::uint16_t>((numberOfLevels > 0) ? numberOfLevels - 1 : 0, | ||||||
|  |                                 std::numeric_limits<std::uint8_t>::min(), | ||||||
|  |                                 std::numeric_limits<std::uint8_t>::max())); | ||||||
| 
 | 
 | ||||||
|    if (p->savedColorTable_ == p->colorTable_ && //
 |    if (p->savedColorTable_ == p->colorTable_ && //
 | ||||||
|        p->savedOffset_ == offset &&             //
 |        p->savedOffset_ == offset &&             //
 | ||||||
|  | @ -274,7 +283,8 @@ void Level3ProductView::UpdateColorTable() | ||||||
|       [&](uint16_t i) |       [&](uint16_t i) | ||||||
|       { |       { | ||||||
|          const size_t lutIndex = i - *dataRange.begin(); |          const size_t lutIndex = i - *dataRange.begin(); | ||||||
|          float        f; | 
 | ||||||
|  |          std::optional<float> f = descriptionBlock->data_value(i); | ||||||
| 
 | 
 | ||||||
|          // Different products use different scale/offset formulas
 |          // Different products use different scale/offset formulas
 | ||||||
|          if (numberOfLevels > 16 || productCode == 34) |          if (numberOfLevels > 16 || productCode == 34) | ||||||
|  | @ -285,28 +295,14 @@ void Level3ProductView::UpdateColorTable() | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                switch (descriptionBlock->product_code()) |                if (f.has_value()) | ||||||
|                { |                { | ||||||
|                case 159: |                   lut[lutIndex] = p->colorTable_->Color(f.value()); | ||||||
|                case 161: |                } | ||||||
|                case 163: |                else | ||||||
|                case 167: |                { | ||||||
|                case 168: |                   lut[lutIndex] = boost::gil::rgba8_pixel_t {0, 0, 0, 0}; | ||||||
|                case 170: |  | ||||||
|                case 172: |  | ||||||
|                case 173: |  | ||||||
|                case 174: |  | ||||||
|                case 175: |  | ||||||
|                case 176: |  | ||||||
|                   f = (i - offset) / scale; |  | ||||||
|                   break; |  | ||||||
| 
 |  | ||||||
|                default: |  | ||||||
|                   f = i * scale + offset; |  | ||||||
|                   break; |  | ||||||
|                } |                } | ||||||
| 
 |  | ||||||
|                lut[lutIndex] = p->colorTable_->Color(f); |  | ||||||
|             } |             } | ||||||
|          } |          } | ||||||
|          else |          else | ||||||
|  | @ -314,29 +310,15 @@ void Level3ProductView::UpdateColorTable() | ||||||
|             uint16_t th = descriptionBlock->data_level_threshold(i); |             uint16_t th = descriptionBlock->data_level_threshold(i); | ||||||
|             if ((th & 0x8000u) == 0) |             if ((th & 0x8000u) == 0) | ||||||
|             { |             { | ||||||
|                float scaleFactor = 1.0f; |  | ||||||
| 
 |  | ||||||
|                if (th & 0x4000u) |  | ||||||
|                { |  | ||||||
|                   scaleFactor *= 0.01f; |  | ||||||
|                } |  | ||||||
|                if (th & 0x2000u) |  | ||||||
|                { |  | ||||||
|                   scaleFactor *= 0.05f; |  | ||||||
|                } |  | ||||||
|                if (th & 0x1000u) |  | ||||||
|                { |  | ||||||
|                   scaleFactor *= 0.1f; |  | ||||||
|                } |  | ||||||
|                if (th & 0x0100u) |  | ||||||
|                { |  | ||||||
|                   scaleFactor *= -1.0f; |  | ||||||
|                } |  | ||||||
| 
 |  | ||||||
|                // If bit 0 is zero, then the LSB is numeric
 |                // If bit 0 is zero, then the LSB is numeric
 | ||||||
|                f = static_cast<float>(th & 0x00ffu) * scaleFactor; |                if (f.has_value()) | ||||||
| 
 |                { | ||||||
|                lut[lutIndex] = p->colorTable_->Color(f); |                   lut[lutIndex] = p->colorTable_->Color(f.value()); | ||||||
|  |                } | ||||||
|  |                else | ||||||
|  |                { | ||||||
|  |                   lut[lutIndex] = boost::gil::rgba8_pixel_t {0, 0, 0, 0}; | ||||||
|  |                } | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|  |  | ||||||
|  | @ -1,9 +1,11 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <scwx/awips/message.hpp> | #include <scwx/awips/message.hpp> | ||||||
|  | #include <scwx/wsr88d/rpg/rpg_types.hpp> | ||||||
| 
 | 
 | ||||||
| #include <cstdint> | #include <cstdint> | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include <optional> | ||||||
| 
 | 
 | ||||||
| #include <units/angle.h> | #include <units/angle.h> | ||||||
| 
 | 
 | ||||||
|  | @ -61,6 +63,9 @@ public: | ||||||
|    float    scale() const; |    float    scale() const; | ||||||
|    uint16_t number_of_levels() const; |    uint16_t number_of_levels() const; | ||||||
| 
 | 
 | ||||||
|  |    std::optional<DataLevelCode> data_level_code(std::uint8_t level) const; | ||||||
|  |    std::optional<float>         data_value(std::uint8_t level) const; | ||||||
|  | 
 | ||||||
|    float log_offset() const; |    float log_offset() const; | ||||||
|    float log_scale() const; |    float log_scale() const; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										58
									
								
								wxdata/include/scwx/wsr88d/rpg/rpg_types.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								wxdata/include/scwx/wsr88d/rpg/rpg_types.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace wsr88d | ||||||
|  | { | ||||||
|  | namespace rpg | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | enum class DataLevelCode | ||||||
|  | { | ||||||
|  |    BadData, | ||||||
|  |    BelowThreshold, | ||||||
|  |    Blank, | ||||||
|  |    ChaffDetection, | ||||||
|  |    EditRemove, | ||||||
|  |    FlaggedData, | ||||||
|  |    Missing, | ||||||
|  |    NoData, | ||||||
|  |    OutsideCoverageArea, | ||||||
|  |    NoAccumulation, | ||||||
|  |    RangeFolded, | ||||||
|  |    Reserved, | ||||||
|  | 
 | ||||||
|  |    // Hydrometeor Classification
 | ||||||
|  |    Biological, | ||||||
|  |    AnomalousPropagationGroundClutter, | ||||||
|  |    IceCrystals, | ||||||
|  |    DrySnow, | ||||||
|  |    WetSnow, | ||||||
|  |    LightAndOrModerateRain, | ||||||
|  |    HeavyRain, | ||||||
|  |    BigDrops, | ||||||
|  |    Graupel, | ||||||
|  |    SmallHail, | ||||||
|  |    LargeHail, | ||||||
|  |    GiantHail, | ||||||
|  |    UnknownClassification, | ||||||
|  | 
 | ||||||
|  |    // Rainfall Rate Classification
 | ||||||
|  |    NoPrecipitation, | ||||||
|  |    Unfilled, | ||||||
|  |    Convective, | ||||||
|  |    Tropical, | ||||||
|  |    SpecificAttenuation, | ||||||
|  |    KL, | ||||||
|  |    KH, | ||||||
|  |    Z1, | ||||||
|  |    Z6, | ||||||
|  |    Z8, | ||||||
|  |    SI, | ||||||
|  | 
 | ||||||
|  |    Unknown | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace rpg
 | ||||||
|  | } // namespace wsr88d
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -705,6 +705,316 @@ bool ProductDescriptionBlock::Parse(std::istream& is) | ||||||
|    return blockValid; |    return blockValid; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::optional<DataLevelCode> | ||||||
|  | ProductDescriptionBlock::data_level_code(std::uint8_t level) const | ||||||
|  | { | ||||||
|  |    switch (p->productCode_) | ||||||
|  |    { | ||||||
|  |    case 32: | ||||||
|  |    case 93: | ||||||
|  |    case 94: | ||||||
|  |    case 99: | ||||||
|  |    case 153: | ||||||
|  |    case 154: | ||||||
|  |    case 155: | ||||||
|  |    case 159: | ||||||
|  |    case 161: | ||||||
|  |    case 163: | ||||||
|  |    case 167: | ||||||
|  |    case 168: | ||||||
|  |    case 195: | ||||||
|  |       switch (level) | ||||||
|  |       { | ||||||
|  |       case 0: | ||||||
|  |          return DataLevelCode::BelowThreshold; | ||||||
|  |       case 1: | ||||||
|  |          return DataLevelCode::RangeFolded; | ||||||
|  |       default: | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case 81: | ||||||
|  |       switch (level) | ||||||
|  |       { | ||||||
|  |       case 0: | ||||||
|  |          return DataLevelCode::NoAccumulation; | ||||||
|  |       case 255: | ||||||
|  |          return DataLevelCode::OutsideCoverageArea; | ||||||
|  |       default: | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case 134: | ||||||
|  |       switch (level) | ||||||
|  |       { | ||||||
|  |       case 0: | ||||||
|  |          return DataLevelCode::BelowThreshold; | ||||||
|  |       case 1: | ||||||
|  |          return DataLevelCode::FlaggedData; | ||||||
|  |       case 255: | ||||||
|  |          return DataLevelCode::Reserved; | ||||||
|  |       default: | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case 135: | ||||||
|  |       switch (level) | ||||||
|  |       { | ||||||
|  |       case 0: | ||||||
|  |          return DataLevelCode::BelowThreshold; | ||||||
|  |       case 1: | ||||||
|  |          return DataLevelCode::BadData; | ||||||
|  |       default: | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case 138: | ||||||
|  |       switch (level) | ||||||
|  |       { | ||||||
|  |       case 0: | ||||||
|  |          return DataLevelCode::NoAccumulation; | ||||||
|  |       default: | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case 165: | ||||||
|  |    case 177: | ||||||
|  |       switch (level) | ||||||
|  |       { | ||||||
|  |       case 0: | ||||||
|  |          return DataLevelCode::BelowThreshold; | ||||||
|  |       case 10: | ||||||
|  |          return DataLevelCode::Biological; | ||||||
|  |       case 20: | ||||||
|  |          return DataLevelCode::AnomalousPropagationGroundClutter; | ||||||
|  |       case 30: | ||||||
|  |          return DataLevelCode::IceCrystals; | ||||||
|  |       case 40: | ||||||
|  |          return DataLevelCode::DrySnow; | ||||||
|  |       case 50: | ||||||
|  |          return DataLevelCode::WetSnow; | ||||||
|  |       case 60: | ||||||
|  |          return DataLevelCode::LightAndOrModerateRain; | ||||||
|  |       case 70: | ||||||
|  |          return DataLevelCode::HeavyRain; | ||||||
|  |       case 80: | ||||||
|  |          return DataLevelCode::BigDrops; | ||||||
|  |       case 90: | ||||||
|  |          return DataLevelCode::Graupel; | ||||||
|  |       case 100: | ||||||
|  |          return DataLevelCode::SmallHail; | ||||||
|  |       case 110: | ||||||
|  |          return DataLevelCode::LargeHail; | ||||||
|  |       case 120: | ||||||
|  |          return DataLevelCode::GiantHail; | ||||||
|  |       case 140: | ||||||
|  |          return DataLevelCode::UnknownClassification; | ||||||
|  |       case 150: | ||||||
|  |          return DataLevelCode::RangeFolded; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case 170: | ||||||
|  |    case 172: | ||||||
|  |    case 173: | ||||||
|  |    case 174: | ||||||
|  |    case 175: | ||||||
|  |       switch (level) | ||||||
|  |       { | ||||||
|  |       case 0: | ||||||
|  |          return DataLevelCode::NoData; | ||||||
|  |       default: | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case 193: | ||||||
|  |       switch (level) | ||||||
|  |       { | ||||||
|  |       case 0: | ||||||
|  |          return DataLevelCode::BelowThreshold; | ||||||
|  |       case 1: | ||||||
|  |          return DataLevelCode::RangeFolded; | ||||||
|  |       case 2: | ||||||
|  |          return DataLevelCode::EditRemove; | ||||||
|  |       case 254: | ||||||
|  |          return DataLevelCode::ChaffDetection; | ||||||
|  |       default: | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case 197: | ||||||
|  |       switch (level) | ||||||
|  |       { | ||||||
|  |       case 0: | ||||||
|  |          return DataLevelCode::NoPrecipitation; | ||||||
|  |       case 10: | ||||||
|  |          return DataLevelCode::Unfilled; | ||||||
|  |       case 20: | ||||||
|  |          return DataLevelCode::Convective; | ||||||
|  |       case 30: | ||||||
|  |          return DataLevelCode::Tropical; | ||||||
|  |       case 40: | ||||||
|  |          return DataLevelCode::SpecificAttenuation; | ||||||
|  |       case 50: | ||||||
|  |          return DataLevelCode::KL; | ||||||
|  |       case 60: | ||||||
|  |          return DataLevelCode::KH; | ||||||
|  |       case 70: | ||||||
|  |          return DataLevelCode::Z1; | ||||||
|  |       case 80: | ||||||
|  |          return DataLevelCode::Z6; | ||||||
|  |       case 90: | ||||||
|  |          return DataLevelCode::Z8; | ||||||
|  |       case 100: | ||||||
|  |          return DataLevelCode::SI; | ||||||
|  |       default: | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    default: | ||||||
|  |       break; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    // Different products use different scale/offset formulas
 | ||||||
|  |    if (number_of_levels() <= 16 && p->productCode_ != 34) | ||||||
|  |    { | ||||||
|  |       uint16_t th = data_level_threshold(level); | ||||||
|  |       if ((th & 0x8000u)) | ||||||
|  |       { | ||||||
|  |          // If bit 0 is one, then the LSB is coded
 | ||||||
|  |          uint16_t lsb = th & 0x00ffu; | ||||||
|  | 
 | ||||||
|  |          switch (lsb) | ||||||
|  |          { | ||||||
|  |          case 0: | ||||||
|  |             return DataLevelCode::Blank; | ||||||
|  |          case 1: | ||||||
|  |             return DataLevelCode::BelowThreshold; | ||||||
|  |          case 2: | ||||||
|  |             return DataLevelCode::NoData; | ||||||
|  |          case 3: | ||||||
|  |             return DataLevelCode::RangeFolded; | ||||||
|  |          case 4: | ||||||
|  |             return DataLevelCode::Biological; | ||||||
|  |          case 5: | ||||||
|  |             return DataLevelCode::AnomalousPropagationGroundClutter; | ||||||
|  |          case 6: | ||||||
|  |             return DataLevelCode::IceCrystals; | ||||||
|  |          case 7: | ||||||
|  |             return DataLevelCode::Graupel; | ||||||
|  |          case 8: | ||||||
|  |             return DataLevelCode::WetSnow; | ||||||
|  |          case 9: | ||||||
|  |             return DataLevelCode::DrySnow; | ||||||
|  |          case 10: | ||||||
|  |             return DataLevelCode::LightAndOrModerateRain; | ||||||
|  |          case 11: | ||||||
|  |             return DataLevelCode::HeavyRain; | ||||||
|  |          case 12: | ||||||
|  |             return DataLevelCode::BigDrops; | ||||||
|  |          case 13: | ||||||
|  |             return DataLevelCode::SmallHail; | ||||||
|  |          case 14: | ||||||
|  |             return DataLevelCode::UnknownClassification; | ||||||
|  |          case 15: | ||||||
|  |             return DataLevelCode::LargeHail; | ||||||
|  |          case 16: | ||||||
|  |             return DataLevelCode::GiantHail; | ||||||
|  |          default: | ||||||
|  |             break; | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return std::nullopt; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::optional<float> | ||||||
|  | ProductDescriptionBlock::data_value(std::uint8_t level) const | ||||||
|  | { | ||||||
|  |    float         dataOffset     = offset(); | ||||||
|  |    float         dataScale      = scale(); | ||||||
|  |    std::uint16_t dataThreshold  = threshold(); | ||||||
|  |    std::uint16_t numberOfLevels = number_of_levels(); | ||||||
|  | 
 | ||||||
|  |    if (level < dataThreshold) | ||||||
|  |    { | ||||||
|  |       return std::nullopt; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    float f; | ||||||
|  | 
 | ||||||
|  |    // Different products use different scale/offset formulas
 | ||||||
|  |    if (numberOfLevels > 16 || p->productCode_ == 34) | ||||||
|  |    { | ||||||
|  |       switch (p->productCode_) | ||||||
|  |       { | ||||||
|  |       case 159: | ||||||
|  |       case 161: | ||||||
|  |       case 163: | ||||||
|  |       case 167: | ||||||
|  |       case 168: | ||||||
|  |       case 170: | ||||||
|  |       case 172: | ||||||
|  |       case 173: | ||||||
|  |       case 174: | ||||||
|  |       case 175: | ||||||
|  |       case 176: | ||||||
|  |          f = (level - dataOffset) / dataScale; | ||||||
|  |          break; | ||||||
|  | 
 | ||||||
|  |       default: | ||||||
|  |          f = level * dataScale + dataOffset; | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |    else | ||||||
|  |    { | ||||||
|  |       std::uint16_t th = data_level_threshold(level); | ||||||
|  |       if ((th & 0x8000u) == 0) | ||||||
|  |       { | ||||||
|  |          float scaleFactor = 1.0f; | ||||||
|  | 
 | ||||||
|  |          if (th & 0x4000u) | ||||||
|  |          { | ||||||
|  |             scaleFactor *= 0.01f; | ||||||
|  |          } | ||||||
|  |          if (th & 0x2000u) | ||||||
|  |          { | ||||||
|  |             scaleFactor *= 0.05f; | ||||||
|  |          } | ||||||
|  |          if (th & 0x1000u) | ||||||
|  |          { | ||||||
|  |             scaleFactor *= 0.1f; | ||||||
|  |          } | ||||||
|  |          if (th & 0x0100u) | ||||||
|  |          { | ||||||
|  |             scaleFactor *= -1.0f; | ||||||
|  |          } | ||||||
|  | 
 | ||||||
|  |          // If bit 0 is zero, then the LSB is numeric
 | ||||||
|  |          f = static_cast<float>(th & 0x00ffu) * scaleFactor; | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |       { | ||||||
|  |          // If bit 0 is one, then the LSB is coded
 | ||||||
|  |          std::uint16_t lsb = th & 0x00ffu; | ||||||
|  | 
 | ||||||
|  |          f = static_cast<float>(lsb); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return f; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace rpg
 | } // namespace rpg
 | ||||||
| } // namespace wsr88d
 | } // namespace wsr88d
 | ||||||
| } // namespace scwx
 | } // namespace scwx
 | ||||||
|  |  | ||||||
|  | @ -146,6 +146,7 @@ set(HDR_WSR88D_RPG include/scwx/wsr88d/rpg/ccb_header.hpp | ||||||
|                    include/scwx/wsr88d/rpg/radar_coded_message.hpp |                    include/scwx/wsr88d/rpg/radar_coded_message.hpp | ||||||
|                    include/scwx/wsr88d/rpg/radial_data_packet.hpp |                    include/scwx/wsr88d/rpg/radial_data_packet.hpp | ||||||
|                    include/scwx/wsr88d/rpg/raster_data_packet.hpp |                    include/scwx/wsr88d/rpg/raster_data_packet.hpp | ||||||
|  |                    include/scwx/wsr88d/rpg/rpg_types.hpp | ||||||
|                    include/scwx/wsr88d/rpg/scit_forecast_data_packet.hpp |                    include/scwx/wsr88d/rpg/scit_forecast_data_packet.hpp | ||||||
|                    include/scwx/wsr88d/rpg/set_color_level_packet.hpp |                    include/scwx/wsr88d/rpg/set_color_level_packet.hpp | ||||||
|                    include/scwx/wsr88d/rpg/special_graphic_symbol_packet.hpp |                    include/scwx/wsr88d/rpg/special_graphic_symbol_packet.hpp | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat