diff --git a/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp index cc85ae5a..b9244a77 100644 --- a/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp @@ -110,7 +110,7 @@ void RadarProductLayer::initialize() gl.glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); connect(p->radarProductView_.get(), - &view::RadarProductView::ColorTableLoaded, + &view::RadarProductView::ColorTableUpdated, this, &RadarProductLayer::UpdateColorTableNextFrame); connect(p->radarProductView_.get(), @@ -239,7 +239,7 @@ void RadarProductLayer::deinitialize() p->texture_ = GL_INVALID_INDEX; disconnect(p->radarProductView_.get(), - &view::RadarProductView::ColorTableLoaded, + &view::RadarProductView::ColorTableUpdated, this, &RadarProductLayer::UpdateColorTableNextFrame); disconnect(p->radarProductView_.get(), diff --git a/scwx-qt/source/scwx/qt/view/level2_product_view.cpp b/scwx-qt/source/scwx/qt/view/level2_product_view.cpp index 6047f943..13db55d3 100644 --- a/scwx-qt/source/scwx/qt/view/level2_product_view.cpp +++ b/scwx-qt/source/scwx/qt/view/level2_product_view.cpp @@ -45,8 +45,11 @@ public: std::shared_ptr radarProductManager) : product_ {product}, radarProductManager_ {radarProductManager}, + latitude_ {}, + longitude_ {}, sweepTime_ {}, - colorTable_ {} + colorTable_ {}, + colorTableLut_ {} { auto it = blockTypes_.find(product); @@ -67,13 +70,23 @@ public: wsr88d::rda::DataBlockType dataBlockType_; std::shared_ptr radarProductManager_; + std::shared_ptr momentDataBlock0_; + std::vector vertices_; std::vector dataMoments8_; std::vector dataMoments16_; + float latitude_; + float longitude_; + std::chrono::system_clock::time_point sweepTime_; - std::vector colorTable_; + std::shared_ptr colorTable_; + std::vector colorTableLut_; + + std::shared_ptr savedColorTable_; + float savedScale_; + float savedOffset_; }; Level2ProductView::Level2ProductView( @@ -91,13 +104,13 @@ Level2ProductView::~Level2ProductView() = default; const std::vector& Level2ProductView::color_table() const { - if (p->colorTable_.size() == 0) + if (p->colorTableLut_.size() == 0) { return RadarProductView::color_table(); } else { - return p->colorTable_; + return p->colorTableLut_; } } @@ -136,11 +149,31 @@ std::tuple Level2ProductView::GetMomentData() const void Level2ProductView::LoadColorTable( std::shared_ptr colorTable) { - // TODO: Make size, offset and scale dynamic - const float offset = 66.0f; - const float scale = 2.0f; + p->colorTable_ = colorTable; + UpdateColorTable(); +} - std::vector& lut = p->colorTable_; +void Level2ProductView::UpdateColorTable() +{ + if (p->momentDataBlock0_ == nullptr || // + p->colorTable_ == nullptr) + { + // Nothing to update + return; + } + + const float offset = p->momentDataBlock0_->offset(); + const float scale = p->momentDataBlock0_->scale(); + + if (p->savedColorTable_ == p->colorTable_ && // + p->savedOffset_ == offset && // + p->savedScale_ == scale) + { + // The color table LUT does not need updated + return; + } + + std::vector& lut = p->colorTableLut_; lut.resize(254); auto dataRange = boost::irange(2, 255); @@ -150,10 +183,14 @@ void Level2ProductView::LoadColorTable( dataRange.end(), [&](uint16_t i) { float f = (i - offset) / scale; - lut[i - *dataRange.begin()] = colorTable->Color(f); + lut[i - *dataRange.begin()] = p->colorTable_->Color(f); }); - emit ColorTableLoaded(); + p->savedColorTable_ = p->colorTable_; + p->savedOffset_ = offset; + p->savedScale_ = scale; + + emit ColorTableUpdated(); } void Level2ProductView::ComputeSweep() @@ -181,7 +218,8 @@ void Level2ProductView::ComputeSweep() // TODO: Pick this based on view settings auto radarData = level2Data->radar_data()[0]; - auto momentData0 = radarData[0]->moment_data_block(p->dataBlockType_); + auto momentData0 = radarData[0]->moment_data_block(p->dataBlockType_); + p->momentDataBlock0_ = momentData0; if (momentData0 == nullptr) { @@ -190,7 +228,10 @@ void Level2ProductView::ComputeSweep() return; } - p->sweepTime_ = TimePoint(radarData[0]->modified_julian_date(), + auto volumeData0 = radarData[0]->volume_data_block(); + p->latitude_ = volumeData0->latitude(); + p->longitude_ = volumeData0->longitude(); + p->sweepTime_ = TimePoint(radarData[0]->modified_julian_date(), radarData[0]->collection_time()); // Calculate vertices @@ -368,9 +409,8 @@ void Level2ProductView::ComputeSweep() baseCoord) * 2; - // TODO: Radar location - vertices[vIndex++] = 38.6986f; - vertices[vIndex++] = -90.6828f; + vertices[vIndex++] = p->latitude_; + vertices[vIndex++] = p->longitude_; vertices[vIndex++] = coordinates[offset1]; vertices[vIndex++] = coordinates[offset1 + 1]; @@ -398,6 +438,8 @@ void Level2ProductView::ComputeSweep() << logPrefix_ << "Vertices calculated in " << timer.format(6, "%ws"); emit SweepComputed(); + + UpdateColorTable(); } std::shared_ptr Level2ProductView::Create( diff --git a/scwx-qt/source/scwx/qt/view/level2_product_view.hpp b/scwx-qt/source/scwx/qt/view/level2_product_view.hpp index 2ba94ef4..cbff8fe5 100644 --- a/scwx-qt/source/scwx/qt/view/level2_product_view.hpp +++ b/scwx-qt/source/scwx/qt/view/level2_product_view.hpp @@ -28,20 +28,23 @@ public: std::shared_ptr radarProductManager); ~Level2ProductView(); - const std::vector& color_table() const; - std::chrono::system_clock::time_point sweep_time() const; - const std::vector& vertices() const; + const std::vector& color_table() const override; + std::chrono::system_clock::time_point sweep_time() const override; + const std::vector& vertices() const override; - void LoadColorTable(std::shared_ptr colorTable); + void LoadColorTable(std::shared_ptr colorTable) override; - std::tuple GetMomentData() const; + std::tuple GetMomentData() const override; static std::shared_ptr Create(common::Level2Product product, std::shared_ptr radarProductManager); +protected: + void UpdateColorTable() override; + protected slots: - void ComputeSweep(); + void ComputeSweep() override; private: std::unique_ptr p; diff --git a/scwx-qt/source/scwx/qt/view/radar_product_view.hpp b/scwx-qt/source/scwx/qt/view/radar_product_view.hpp index 1d2d3af2..f957cc63 100644 --- a/scwx-qt/source/scwx/qt/view/radar_product_view.hpp +++ b/scwx-qt/source/scwx/qt/view/radar_product_view.hpp @@ -35,11 +35,14 @@ public: virtual std::tuple GetMomentData() const = 0; +protected: + virtual void UpdateColorTable() = 0; + protected slots: virtual void ComputeSweep(); signals: - void ColorTableLoaded(); + void ColorTableUpdated(); void SweepComputed(); private: diff --git a/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp b/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp index 922d6925..a9840da6 100644 --- a/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp +++ b/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp @@ -146,6 +146,9 @@ public: VolumeDataBlock(VolumeDataBlock&&) noexcept; VolumeDataBlock& operator=(VolumeDataBlock&&) noexcept; + float latitude() const; + float longitude() const; + static std::shared_ptr Create(const std::string& dataBlockType, const std::string& dataName, @@ -185,6 +188,7 @@ public: uint8_t azimuth_indexing_mode() const; uint16_t data_block_count() const; + std::shared_ptr volume_data_block() const; std::shared_ptr moment_data_block(DataBlockType type) const; bool Parse(std::istream& is); diff --git a/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp b/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp index 5db471fc..117130a0 100644 --- a/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp +++ b/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp @@ -275,6 +275,16 @@ VolumeDataBlock::VolumeDataBlock(VolumeDataBlock&&) noexcept = default; VolumeDataBlock& VolumeDataBlock::operator=(VolumeDataBlock&&) noexcept = default; +float VolumeDataBlock::latitude() const +{ + return p->latitude_; +} + +float VolumeDataBlock::longitude() const +{ + return p->longitude_; +} + std::shared_ptr VolumeDataBlock::Create(const std::string& dataBlockType, const std::string& dataName, @@ -603,6 +613,10 @@ uint16_t DigitalRadarData::data_block_count() const { return p->dataBlockCount_; } +std::shared_ptr DigitalRadarData::volume_data_block() const +{ + return p->volumeDataBlock_; +} std::shared_ptr DigitalRadarData::moment_data_block(DataBlockType type) const