diff --git a/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp b/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp index e7adf94d..31bb1813 100644 --- a/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp +++ b/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp @@ -9,15 +9,158 @@ namespace wsr88d namespace rda { +enum class DataBlockType +{ + Volume, + Elevation, + Radial, + MomentRef, + MomentVel, + MomentSw, + MomentZdr, + MomentPhi, + MomentRho, + MomentCfp, + Unknown +}; + +class DataBlockImpl; +class ElevationDataBlockImpl; +class MomentDataBlockImpl; +class RadialDataBlockImpl; +class VolumeDataBlockImpl; + class DigitalRadarDataImpl; +class DataBlock +{ +protected: + explicit DataBlock(const std::string& dataBlockType, + const std::string& dataName); + ~DataBlock(); + + DataBlock(const DataBlock&) = delete; + DataBlock& operator=(const DataBlock&) = delete; + + DataBlock(DataBlock&&) noexcept; + DataBlock& operator=(DataBlock&&) noexcept; + +private: + std::unique_ptr p; +}; + +class ElevationDataBlock : public DataBlock +{ +public: + explicit ElevationDataBlock(const std::string& dataBlockType, + const std::string& dataName); + ~ElevationDataBlock(); + + ElevationDataBlock(const ElevationDataBlock&) = delete; + ElevationDataBlock& operator=(const ElevationDataBlock&) = delete; + + ElevationDataBlock(ElevationDataBlock&&) noexcept; + ElevationDataBlock& operator=(ElevationDataBlock&&) noexcept; + + static std::shared_ptr + Create(const std::string& dataBlockType, + const std::string& dataName, + std::istream& is); + +private: + std::unique_ptr p; + + bool Parse(std::istream& is); +}; + +class MomentDataBlock : public DataBlock +{ +public: + explicit MomentDataBlock(const std::string& dataBlockType, + const std::string& dataName); + ~MomentDataBlock(); + + MomentDataBlock(const MomentDataBlock&) = delete; + MomentDataBlock& operator=(const MomentDataBlock&) = delete; + + MomentDataBlock(MomentDataBlock&&) noexcept; + MomentDataBlock& operator=(MomentDataBlock&&) noexcept; + + uint16_t number_of_data_moment_gates() const; + float data_moment_range() const; + float data_moment_range_sample_interval() const; + float snr_threshold() const; + uint8_t data_word_size() const; + float scale() const; + float offset() const; + const void* data_moments() const; + + static std::shared_ptr + Create(const std::string& dataBlockType, + const std::string& dataName, + std::istream& is); + +private: + std::unique_ptr p; + + bool Parse(std::istream& is); +}; + +class RadialDataBlock : public DataBlock +{ +public: + explicit RadialDataBlock(const std::string& dataBlockType, + const std::string& dataName); + ~RadialDataBlock(); + + RadialDataBlock(const RadialDataBlock&) = delete; + RadialDataBlock& operator=(const RadialDataBlock&) = delete; + + RadialDataBlock(RadialDataBlock&&) noexcept; + RadialDataBlock& operator=(RadialDataBlock&&) noexcept; + + static std::shared_ptr + Create(const std::string& dataBlockType, + const std::string& dataName, + std::istream& is); + +private: + std::unique_ptr p; + + bool Parse(std::istream& is); +}; + +class VolumeDataBlock : public DataBlock +{ +public: + explicit VolumeDataBlock(const std::string& dataBlockType, + const std::string& dataName); + ~VolumeDataBlock(); + + VolumeDataBlock(const VolumeDataBlock&) = delete; + VolumeDataBlock& operator=(const VolumeDataBlock&) = delete; + + VolumeDataBlock(VolumeDataBlock&&) noexcept; + VolumeDataBlock& operator=(VolumeDataBlock&&) noexcept; + + static std::shared_ptr + Create(const std::string& dataBlockType, + const std::string& dataName, + std::istream& is); + +private: + std::unique_ptr p; + + bool Parse(std::istream& is); +}; + class DigitalRadarData : public Message { public: explicit DigitalRadarData(); ~DigitalRadarData(); - DigitalRadarData(const Message&) = delete; + DigitalRadarData(const DigitalRadarData&) = delete; DigitalRadarData& operator=(const DigitalRadarData&) = delete; DigitalRadarData(DigitalRadarData&&) noexcept; @@ -39,6 +182,8 @@ public: uint8_t azimuth_indexing_mode() const; uint16_t data_block_count() const; + std::shared_ptr moment_data_block(DataBlockType type) const; + bool Parse(std::istream& is); static std::shared_ptr Create(MessageHeader&& header, diff --git a/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp b/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp index 049eba22..5d2442e7 100644 --- a/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp +++ b/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp @@ -12,21 +12,6 @@ namespace rda static const std::string logPrefix_ = "[scwx::wsr88d::rda::digital_radar_data] "; -enum class DataBlockType -{ - Volume, - Elevation, - Radial, - MomentRef, - MomentVel, - MomentSw, - MomentZdr, - MomentPhi, - MomentRho, - MomentCfp, - Unknown -}; - static const std::unordered_map strToDataBlock_ { {"VOL", DataBlockType::Volume}, {"ELV", DataBlockType::Elevation}, @@ -39,10 +24,11 @@ static const std::unordered_map strToDataBlock_ { {"RHO", DataBlockType::MomentRho}, {"CFP", DataBlockType::MomentCfp}}; -struct DataBlock +class DataBlockImpl { - explicit DataBlock(const std::string& dataBlockType, - const std::string& dataName) : +public: + explicit DataBlockImpl(const std::string& dataBlockType, + const std::string& dataName) : dataBlockType_ {dataBlockType}, dataName_ {dataName} { } @@ -51,11 +37,20 @@ struct DataBlock std::string dataName_; }; -struct MomentDataBlock : DataBlock +DataBlock::DataBlock(const std::string& dataBlockType, + const std::string& dataName) : + p(std::make_unique(dataBlockType, dataName)) { - explicit MomentDataBlock(const std::string& dataBlockType, - const std::string& dataName) : - DataBlock(dataBlockType, dataName), +} +DataBlock::~DataBlock() = default; + +DataBlock::DataBlock(DataBlock&&) noexcept = default; +DataBlock& DataBlock::operator=(DataBlock&&) noexcept = default; + +class MomentDataBlockImpl +{ +public: + explicit MomentDataBlockImpl() : numberOfDataMomentGates_ {0}, dataMomentRange_ {0}, dataMomentRangeSampleInterval_ {0}, @@ -78,75 +73,148 @@ struct MomentDataBlock : DataBlock float scale_; float offset_; - std::vector momentGates8_; + std::vector momentGates8_; std::vector momentGates16_; +}; - static std::unique_ptr - Create(const std::string& dataBlockType, - const std::string& dataName, - std::istream& is) +MomentDataBlock::MomentDataBlock(const std::string& dataBlockType, + const std::string& dataName) : + DataBlock(dataBlockType, dataName), + p(std::make_unique()) +{ +} +MomentDataBlock::~MomentDataBlock() = default; + +MomentDataBlock::MomentDataBlock(MomentDataBlock&&) noexcept = default; +MomentDataBlock& +MomentDataBlock::operator=(MomentDataBlock&&) noexcept = default; + +uint16_t MomentDataBlock::number_of_data_moment_gates() const +{ + return p->numberOfDataMomentGates_; +} + +float MomentDataBlock::data_moment_range() const +{ + return p->dataMomentRange_ / 0.001f; +} + +float MomentDataBlock::data_moment_range_sample_interval() const +{ + return p->dataMomentRangeSampleInterval_ / 0.001f; +} + +float MomentDataBlock::snr_threshold() const +{ + return p->snrThreshold_ / 0.1f; +} + +uint8_t MomentDataBlock::data_word_size() const +{ + return p->dataWordSize_; +} + +float MomentDataBlock::scale() const +{ + return p->scale_; +} + +float MomentDataBlock::offset() const +{ + return p->offset_; +} + +const void* MomentDataBlock::data_moments() const +{ + const void* dataMoments; + + switch (p->dataWordSize_) { - std::unique_ptr p = - std::make_unique(dataBlockType, dataName); + case 8: dataMoments = p->momentGates8_.data(); break; + case 16: dataMoments = p->momentGates8_.data(); break; + default: dataMoments = nullptr; break; + } - is.seekg(4, std::ios_base::cur); // 4-7 - is.read(reinterpret_cast(&p->numberOfDataMomentGates_), 2); // 8-9 - is.read(reinterpret_cast(&p->dataMomentRange_), 2); // 10-11 - is.read(reinterpret_cast(&p->dataMomentRangeSampleInterval_), - 2); // 12-13 - is.read(reinterpret_cast(&p->tover_), 2); // 14-15 - is.read(reinterpret_cast(&p->snrThreshold_), 2); // 16-17 - is.read(reinterpret_cast(&p->controlFlags_), 1); // 18 - is.read(reinterpret_cast(&p->dataWordSize_), 1); // 19 - is.read(reinterpret_cast(&p->scale_), 4); // 20-23 - is.read(reinterpret_cast(&p->offset_), 4); // 24-27 + return dataMoments; +} - p->numberOfDataMomentGates_ = ntohs(p->numberOfDataMomentGates_); - p->dataMomentRange_ = ntohs(p->dataMomentRange_); - p->dataMomentRangeSampleInterval_ = - ntohs(p->dataMomentRangeSampleInterval_); - p->tover_ = ntohs(p->tover_); - p->snrThreshold_ = ntohs(p->snrThreshold_); - p->scale_ = Message::SwapFloat(p->scale_); - p->offset_ = Message::SwapFloat(p->offset_); +std::shared_ptr +MomentDataBlock::Create(const std::string& dataBlockType, + const std::string& dataName, + std::istream& is) +{ + std::shared_ptr p = + std::make_shared(dataBlockType, dataName); - if (p->numberOfDataMomentGates_ >= 0 && - p->numberOfDataMomentGates_ <= 1840) + if (!p->Parse(is)) + { + p.reset(); + } + + return p; +} + +bool MomentDataBlock::Parse(std::istream& is) +{ + bool dataBlockValid = true; + + is.seekg(4, std::ios_base::cur); // 4-7 + is.read(reinterpret_cast(&p->numberOfDataMomentGates_), 2); // 8-9 + is.read(reinterpret_cast(&p->dataMomentRange_), 2); // 10-11 + is.read(reinterpret_cast(&p->dataMomentRangeSampleInterval_), + 2); // 12-13 + is.read(reinterpret_cast(&p->tover_), 2); // 14-15 + is.read(reinterpret_cast(&p->snrThreshold_), 2); // 16-17 + is.read(reinterpret_cast(&p->controlFlags_), 1); // 18 + is.read(reinterpret_cast(&p->dataWordSize_), 1); // 19 + is.read(reinterpret_cast(&p->scale_), 4); // 20-23 + is.read(reinterpret_cast(&p->offset_), 4); // 24-27 + + p->numberOfDataMomentGates_ = ntohs(p->numberOfDataMomentGates_); + p->dataMomentRange_ = ntohs(p->dataMomentRange_); + p->dataMomentRangeSampleInterval_ = ntohs(p->dataMomentRangeSampleInterval_); + p->tover_ = ntohs(p->tover_); + p->snrThreshold_ = ntohs(p->snrThreshold_); + p->scale_ = Message::SwapFloat(p->scale_); + p->offset_ = Message::SwapFloat(p->offset_); + + if (p->numberOfDataMomentGates_ >= 0 && p->numberOfDataMomentGates_ <= 1840) + { + if (p->dataWordSize_ == 8) { - if (p->dataWordSize_ == 8) - { - p->momentGates8_.resize(p->numberOfDataMomentGates_); - is.read(p->momentGates8_.data(), p->numberOfDataMomentGates_); - } - else if (p->dataWordSize_ == 16) - { - p->momentGates16_.resize(p->numberOfDataMomentGates_); - is.read(reinterpret_cast(p->momentGates16_.data()), - p->numberOfDataMomentGates_ * 2); - Message::SwapVector(p->momentGates16_); - } - else - { - BOOST_LOG_TRIVIAL(warning) - << logPrefix_ << "Invalid data word size: " << p->dataWordSize_; - } + p->momentGates8_.resize(p->numberOfDataMomentGates_); + is.read(reinterpret_cast(p->momentGates8_.data()), + p->numberOfDataMomentGates_); + } + else if (p->dataWordSize_ == 16) + { + p->momentGates16_.resize(p->numberOfDataMomentGates_); + is.read(reinterpret_cast(p->momentGates16_.data()), + p->numberOfDataMomentGates_ * 2); + Message::SwapVector(p->momentGates16_); } else { BOOST_LOG_TRIVIAL(warning) - << logPrefix_ << "Invalid number of data moment gates: " - << p->numberOfDataMomentGates_; + << logPrefix_ << "Invalid data word size: " << p->dataWordSize_; + dataBlockValid = false; } - - return p; } -}; + else + { + BOOST_LOG_TRIVIAL(warning) + << logPrefix_ << "Invalid number of data moment gates: " + << p->numberOfDataMomentGates_; + dataBlockValid = false; + } -struct VolumeDataBlock : DataBlock + return dataBlockValid; +} + +class VolumeDataBlockImpl { - explicit VolumeDataBlock(const std::string& dataBlockType, - const std::string& dataName) : - DataBlock(dataBlockType, dataName), +public: + explicit VolumeDataBlockImpl() : lrtup_ {0}, versionNumberMajor_ {0}, versionNumberMinor_ {0}, @@ -178,92 +246,136 @@ struct VolumeDataBlock : DataBlock float initialSystemDifferentialPhase_; uint16_t volumeCoveragePatternNumber_; uint16_t processingStatus_; - - static std::unique_ptr - Create(const std::string& dataBlockType, - const std::string& dataName, - std::istream& is) - { - std::unique_ptr p = - std::make_unique(dataBlockType, dataName); - - is.read(reinterpret_cast(&p->lrtup_), 2); // 4-5 - is.read(reinterpret_cast(&p->versionNumberMajor_), 1); // 6 - is.read(reinterpret_cast(&p->versionNumberMinor_), 1); // 7 - is.read(reinterpret_cast(&p->latitude_), 4); // 8-11 - is.read(reinterpret_cast(&p->longitude_), 4); // 12-15 - is.read(reinterpret_cast(&p->siteHeight_), 2); // 16-17 - is.read(reinterpret_cast(&p->feedhornHeight_), 2); // 18-19 - is.read(reinterpret_cast(&p->calibrationConstant_), 4); // 20-23 - is.read(reinterpret_cast(&p->horizontaShvTxPower_), 4); // 24-27 - is.read(reinterpret_cast(&p->verticalShvTxPower_), 4); // 28-31 - is.read(reinterpret_cast(&p->systemDifferentialReflectivity_), - 4); // 32-35 - is.read(reinterpret_cast(&p->initialSystemDifferentialPhase_), - 4); // 36-39 - is.read(reinterpret_cast(&p->volumeCoveragePatternNumber_), - 2); // 40-41 - is.read(reinterpret_cast(&p->processingStatus_), 2); // 42-43 - - p->lrtup_ = ntohs(p->lrtup_); - p->latitude_ = Message::SwapFloat(p->latitude_); - p->longitude_ = Message::SwapFloat(p->longitude_); - p->siteHeight_ = ntohs(p->siteHeight_); - p->feedhornHeight_ = ntohs(p->feedhornHeight_); - p->calibrationConstant_ = Message::SwapFloat(p->calibrationConstant_); - p->horizontaShvTxPower_ = Message::SwapFloat(p->horizontaShvTxPower_); - p->verticalShvTxPower_ = Message::SwapFloat(p->verticalShvTxPower_); - p->systemDifferentialReflectivity_ = - Message::SwapFloat(p->systemDifferentialReflectivity_); - p->initialSystemDifferentialPhase_ = - Message::SwapFloat(p->initialSystemDifferentialPhase_); - p->volumeCoveragePatternNumber_ = ntohs(p->volumeCoveragePatternNumber_); - p->processingStatus_ = ntohs(p->processingStatus_); - - return p; - } }; -struct ElevationDataBlock : DataBlock +VolumeDataBlock::VolumeDataBlock(const std::string& dataBlockType, + const std::string& dataName) : + DataBlock(dataBlockType, dataName), + p(std::make_unique()) { - explicit ElevationDataBlock(const std::string& dataBlockType, - const std::string& dataName) : - DataBlock(dataBlockType, dataName), - lrtup_ {0}, - atmos_ {0}, - calibrationConstant_ {0.0f} +} +VolumeDataBlock::~VolumeDataBlock() = default; + +VolumeDataBlock::VolumeDataBlock(VolumeDataBlock&&) noexcept = default; +VolumeDataBlock& +VolumeDataBlock::operator=(VolumeDataBlock&&) noexcept = default; + +std::shared_ptr +VolumeDataBlock::Create(const std::string& dataBlockType, + const std::string& dataName, + std::istream& is) +{ + std::shared_ptr p = + std::make_shared(dataBlockType, dataName); + + if (!p->Parse(is)) + { + p.reset(); + } + + return p; +} + +bool VolumeDataBlock::Parse(std::istream& is) +{ + bool dataBlockValid = true; + + is.read(reinterpret_cast(&p->lrtup_), 2); // 4-5 + is.read(reinterpret_cast(&p->versionNumberMajor_), 1); // 6 + is.read(reinterpret_cast(&p->versionNumberMinor_), 1); // 7 + is.read(reinterpret_cast(&p->latitude_), 4); // 8-11 + is.read(reinterpret_cast(&p->longitude_), 4); // 12-15 + is.read(reinterpret_cast(&p->siteHeight_), 2); // 16-17 + is.read(reinterpret_cast(&p->feedhornHeight_), 2); // 18-19 + is.read(reinterpret_cast(&p->calibrationConstant_), 4); // 20-23 + is.read(reinterpret_cast(&p->horizontaShvTxPower_), 4); // 24-27 + is.read(reinterpret_cast(&p->verticalShvTxPower_), 4); // 28-31 + is.read(reinterpret_cast(&p->systemDifferentialReflectivity_), + 4); // 32-35 + is.read(reinterpret_cast(&p->initialSystemDifferentialPhase_), + 4); // 36-39 + is.read(reinterpret_cast(&p->volumeCoveragePatternNumber_), + 2); // 40-41 + is.read(reinterpret_cast(&p->processingStatus_), 2); // 42-43 + + p->lrtup_ = ntohs(p->lrtup_); + p->latitude_ = Message::SwapFloat(p->latitude_); + p->longitude_ = Message::SwapFloat(p->longitude_); + p->siteHeight_ = ntohs(p->siteHeight_); + p->feedhornHeight_ = ntohs(p->feedhornHeight_); + p->calibrationConstant_ = Message::SwapFloat(p->calibrationConstant_); + p->horizontaShvTxPower_ = Message::SwapFloat(p->horizontaShvTxPower_); + p->verticalShvTxPower_ = Message::SwapFloat(p->verticalShvTxPower_); + p->systemDifferentialReflectivity_ = + Message::SwapFloat(p->systemDifferentialReflectivity_); + p->initialSystemDifferentialPhase_ = + Message::SwapFloat(p->initialSystemDifferentialPhase_); + p->volumeCoveragePatternNumber_ = ntohs(p->volumeCoveragePatternNumber_); + p->processingStatus_ = ntohs(p->processingStatus_); + + return dataBlockValid; +} + +class ElevationDataBlockImpl +{ +public: + explicit ElevationDataBlockImpl() : + lrtup_ {0}, atmos_ {0}, calibrationConstant_ {0.0f} { } uint16_t lrtup_; int16_t atmos_; float calibrationConstant_; - - static std::unique_ptr - Create(const std::string& dataBlockType, - const std::string& dataName, - std::istream& is) - { - std::unique_ptr p = - std::make_unique(dataBlockType, dataName); - - is.read(reinterpret_cast(&p->lrtup_), 2); // 4-5 - is.read(reinterpret_cast(&p->atmos_), 2); // 6-7 - is.read(reinterpret_cast(&p->calibrationConstant_), 4); // 8-11 - - p->lrtup_ = ntohs(p->lrtup_); - p->atmos_ = ntohs(p->atmos_); - p->calibrationConstant_ = Message::SwapFloat(p->calibrationConstant_); - - return p; - } }; -struct RadialDataBlock : DataBlock +ElevationDataBlock::ElevationDataBlock(const std::string& dataBlockType, + const std::string& dataName) : + DataBlock(dataBlockType, dataName), + p(std::make_unique()) { - explicit RadialDataBlock(const std::string& dataBlockType, - const std::string& dataName) : - DataBlock(dataBlockType, dataName), +} +ElevationDataBlock::~ElevationDataBlock() = default; + +ElevationDataBlock::ElevationDataBlock(ElevationDataBlock&&) noexcept = default; +ElevationDataBlock& +ElevationDataBlock::operator=(ElevationDataBlock&&) noexcept = default; + +std::shared_ptr +ElevationDataBlock::Create(const std::string& dataBlockType, + const std::string& dataName, + std::istream& is) +{ + std::shared_ptr p = + std::make_shared(dataBlockType, dataName); + + if (!p->Parse(is)) + { + p.reset(); + } + + return p; +} + +bool ElevationDataBlock::Parse(std::istream& is) +{ + bool dataBlockValid = true; + + is.read(reinterpret_cast(&p->lrtup_), 2); // 4-5 + is.read(reinterpret_cast(&p->atmos_), 2); // 6-7 + is.read(reinterpret_cast(&p->calibrationConstant_), 4); // 8-11 + + p->lrtup_ = ntohs(p->lrtup_); + p->atmos_ = ntohs(p->atmos_); + p->calibrationConstant_ = Message::SwapFloat(p->calibrationConstant_); + + return dataBlockValid; +} + +class RadialDataBlockImpl +{ +public: + explicit RadialDataBlockImpl() : lrtup_ {0}, unambigiousRange_ {0}, noiseLevelHorizontal_ {0.0f}, @@ -283,41 +395,65 @@ struct RadialDataBlock : DataBlock uint16_t radialFlags_; float calibrationConstantHorizontal_; float calibrationConstantVertical_; - - static std::unique_ptr - Create(const std::string& dataBlockType, - const std::string& dataName, - std::istream& is) - { - std::unique_ptr p = - std::make_unique(dataBlockType, dataName); - - is.read(reinterpret_cast(&p->lrtup_), 2); // 4-5 - is.read(reinterpret_cast(&p->unambigiousRange_), 2); // 6-7 - is.read(reinterpret_cast(&p->noiseLevelHorizontal_), 4); // 8-11 - is.read(reinterpret_cast(&p->noiseLevelVertical_), 4); // 12-15 - is.read(reinterpret_cast(&p->nyquistVelocity_), 2); // 16-17 - is.read(reinterpret_cast(&p->radialFlags_), 2); // 18-19 - is.read(reinterpret_cast(&p->calibrationConstantHorizontal_), - 4); // 20-23 - is.read(reinterpret_cast(&p->calibrationConstantVertical_), - 4); // 24-27 - - p->lrtup_ = ntohs(p->lrtup_); - p->unambigiousRange_ = ntohs(p->unambigiousRange_); - p->noiseLevelHorizontal_ = Message::SwapFloat(p->noiseLevelHorizontal_); - p->noiseLevelVertical_ = Message::SwapFloat(p->noiseLevelVertical_); - p->nyquistVelocity_ = ntohs(p->nyquistVelocity_); - p->radialFlags_ = ntohs(p->radialFlags_); - p->calibrationConstantHorizontal_ = - Message::SwapFloat(p->calibrationConstantHorizontal_); - p->calibrationConstantVertical_ = - Message::SwapFloat(p->calibrationConstantVertical_); - - return p; - } }; +RadialDataBlock::RadialDataBlock(const std::string& dataBlockType, + const std::string& dataName) : + DataBlock(dataBlockType, dataName), + p(std::make_unique()) +{ +} +RadialDataBlock::~RadialDataBlock() = default; + +RadialDataBlock::RadialDataBlock(RadialDataBlock&&) noexcept = default; +RadialDataBlock& +RadialDataBlock::operator=(RadialDataBlock&&) noexcept = default; + +std::shared_ptr +RadialDataBlock::Create(const std::string& dataBlockType, + const std::string& dataName, + std::istream& is) +{ + std::shared_ptr p = + std::make_shared(dataBlockType, dataName); + + if (!p->Parse(is)) + { + p.reset(); + } + + return p; +} + +bool RadialDataBlock::Parse(std::istream& is) +{ + bool dataBlockValid = true; + + is.read(reinterpret_cast(&p->lrtup_), 2); // 4-5 + is.read(reinterpret_cast(&p->unambigiousRange_), 2); // 6-7 + is.read(reinterpret_cast(&p->noiseLevelHorizontal_), 4); // 8-11 + is.read(reinterpret_cast(&p->noiseLevelVertical_), 4); // 12-15 + is.read(reinterpret_cast(&p->nyquistVelocity_), 2); // 16-17 + is.read(reinterpret_cast(&p->radialFlags_), 2); // 18-19 + is.read(reinterpret_cast(&p->calibrationConstantHorizontal_), + 4); // 20-23 + is.read(reinterpret_cast(&p->calibrationConstantVertical_), + 4); // 24-27 + + p->lrtup_ = ntohs(p->lrtup_); + p->unambigiousRange_ = ntohs(p->unambigiousRange_); + p->noiseLevelHorizontal_ = Message::SwapFloat(p->noiseLevelHorizontal_); + p->noiseLevelVertical_ = Message::SwapFloat(p->noiseLevelVertical_); + p->nyquistVelocity_ = ntohs(p->nyquistVelocity_); + p->radialFlags_ = ntohs(p->radialFlags_); + p->calibrationConstantHorizontal_ = + Message::SwapFloat(p->calibrationConstantHorizontal_); + p->calibrationConstantVertical_ = + Message::SwapFloat(p->calibrationConstantVertical_); + + return dataBlockValid; +} + class DigitalRadarDataImpl { public: @@ -341,13 +477,7 @@ public: volumeDataBlock_ {nullptr}, elevationDataBlock_ {nullptr}, radialDataBlock_ {nullptr}, - momentRefDataBlock_ {nullptr}, - momentVelDataBlock_ {nullptr}, - momentSwDataBlock_ {nullptr}, - momentZdrDataBlock_ {nullptr}, - momentPhiDataBlock_ {nullptr}, - momentRhoDataBlock_ {nullptr}, - momentCfpDataBlock_ {nullptr} {}; + momentDataBlock_ {} {}; ~DigitalRadarDataImpl() = default; std::string radarIdentifier_; @@ -367,16 +497,11 @@ public: uint16_t dataBlockCount_; std::array dataBlockPointer_; - std::unique_ptr volumeDataBlock_; - std::unique_ptr elevationDataBlock_; - std::unique_ptr radialDataBlock_; - std::unique_ptr momentRefDataBlock_; - std::unique_ptr momentVelDataBlock_; - std::unique_ptr momentSwDataBlock_; - std::unique_ptr momentZdrDataBlock_; - std::unique_ptr momentPhiDataBlock_; - std::unique_ptr momentRhoDataBlock_; - std::unique_ptr momentCfpDataBlock_; + std::shared_ptr volumeDataBlock_; + std::shared_ptr elevationDataBlock_; + std::shared_ptr radialDataBlock_; + std::unordered_map> + momentDataBlock_; }; DigitalRadarData::DigitalRadarData() : @@ -464,6 +589,20 @@ uint16_t DigitalRadarData::data_block_count() const return p->dataBlockCount_; } +std::shared_ptr +DigitalRadarData::moment_data_block(DataBlockType type) const +{ + std::shared_ptr momentDataBlock = nullptr; + + auto it = p->momentDataBlock_.find(type); + if (it != p->momentDataBlock_.end()) + { + momentDataBlock = it->second; + } + + return momentDataBlock; +} + bool DigitalRadarData::Parse(std::istream& is) { BOOST_LOG_TRIVIAL(debug) @@ -571,31 +710,13 @@ bool DigitalRadarData::Parse(std::istream& is) std::move(RadialDataBlock::Create(dataBlockType, dataName, is)); break; case DataBlockType::MomentRef: - p->momentRefDataBlock_ = - std::move(MomentDataBlock::Create(dataBlockType, dataName, is)); - break; case DataBlockType::MomentVel: - p->momentVelDataBlock_ = - std::move(MomentDataBlock::Create(dataBlockType, dataName, is)); - break; case DataBlockType::MomentSw: - p->momentSwDataBlock_ = - std::move(MomentDataBlock::Create(dataBlockType, dataName, is)); - break; case DataBlockType::MomentZdr: - p->momentZdrDataBlock_ = - std::move(MomentDataBlock::Create(dataBlockType, dataName, is)); - break; case DataBlockType::MomentPhi: - p->momentPhiDataBlock_ = - std::move(MomentDataBlock::Create(dataBlockType, dataName, is)); - break; case DataBlockType::MomentRho: - p->momentRhoDataBlock_ = - std::move(MomentDataBlock::Create(dataBlockType, dataName, is)); - break; case DataBlockType::MomentCfp: - p->momentCfpDataBlock_ = + p->momentDataBlock_[dataBlock] = std::move(MomentDataBlock::Create(dataBlockType, dataName, is)); break; default: