diff --git a/scwx-qt/source/scwx/qt/view/level3_product_view.cpp b/scwx-qt/source/scwx/qt/view/level3_product_view.cpp index d0bb0d47..642e0981 100644 --- a/scwx-qt/source/scwx/qt/view/level3_product_view.cpp +++ b/scwx-qt/source/scwx/qt/view/level3_product_view.cpp @@ -485,6 +485,50 @@ void Level3ProductView::UpdateColorTableLut() Q_EMIT ColorTableLutUpdated(); } +std::uint8_t Level3ProductView::ComputeEdgeValue() const +{ + std::uint8_t edgeValue = 0; + + std::shared_ptr descriptionBlock = + p->graphicMessage_->description_block(); + + const float offset = descriptionBlock->offset(); + const float scale = descriptionBlock->scale(); + + switch (p->category_) + { + case common::Level3ProductCategory::Velocity: + edgeValue = (scale > 0.0f) ? (-offset / scale) : -offset; + break; + + case common::Level3ProductCategory::DifferentialReflectivity: + edgeValue = -offset; + break; + + case common::Level3ProductCategory::SpectrumWidth: + case common::Level3ProductCategory::SpecificDifferentialPhase: + edgeValue = 2; + break; + + case common::Level3ProductCategory::CorrelationCoefficient: + edgeValue = static_cast( + std::max(255, descriptionBlock->number_of_levels())); + break; + + case common::Level3ProductCategory::Reflectivity: + case common::Level3ProductCategory::StormRelativeVelocity: + case common::Level3ProductCategory::VerticallyIntegratedLiquid: + case common::Level3ProductCategory::EchoTops: + case common::Level3ProductCategory::HydrometeorClassification: + case common::Level3ProductCategory::PrecipitationAccumulation: + default: + edgeValue = 0; + break; + } + + return edgeValue; +} + std::optional Level3ProductView::GetDataLevelCode(std::uint16_t level) const { diff --git a/scwx-qt/source/scwx/qt/view/level3_product_view.hpp b/scwx-qt/source/scwx/qt/view/level3_product_view.hpp index e836c6e0..e5de1873 100644 --- a/scwx-qt/source/scwx/qt/view/level3_product_view.hpp +++ b/scwx-qt/source/scwx/qt/view/level3_product_view.hpp @@ -58,6 +58,8 @@ protected: void DisconnectRadarProductManager() override; void UpdateColorTableLut() override; + std::uint8_t ComputeEdgeValue() const; + private: class Impl; std::unique_ptr p; diff --git a/scwx-qt/source/scwx/qt/view/level3_radial_view.cpp b/scwx-qt/source/scwx/qt/view/level3_radial_view.cpp index efb732d3..8d561935 100644 --- a/scwx-qt/source/scwx/qt/view/level3_radial_view.cpp +++ b/scwx-qt/source/scwx/qt/view/level3_radial_view.cpp @@ -47,6 +47,8 @@ public: const std::shared_ptr& radialData, bool smoothingEnabled); + inline std::uint8_t RemapDataMoment(std::uint8_t dataMoment) const; + Level3RadialView* self_; boost::asio::thread_pool threadPool_ {1u}; @@ -54,6 +56,7 @@ public: std::vector coordinates_ {}; std::vector vertices_ {}; std::vector dataMoments8_ {}; + std::uint8_t edgeValue_ {}; std::shared_ptr lastRadialData_ {}; bool lastSmoothingEnabled_ {false}; @@ -347,6 +350,10 @@ void Level3RadialView::ComputeSweep() // are skipping the radar site origin. The end gate is unaffected, as // we need to draw one less data point. ++startGate; + + // For most products other than reflectivity, the edge should not go to + // the bottom of the color table + p->edgeValue_ = ComputeEdgeValue(); } for (std::uint16_t radial = 0; radial < radialData->number_of_radials(); @@ -401,12 +408,12 @@ void Level3RadialView::ComputeSweep() } // The order must match the store vertices section below - dataMoments8[mIndex++] = dm1; - dataMoments8[mIndex++] = dm2; - dataMoments8[mIndex++] = dm4; - dataMoments8[mIndex++] = dm1; - dataMoments8[mIndex++] = dm3; - dataMoments8[mIndex++] = dm4; + dataMoments8[mIndex++] = p->RemapDataMoment(dm1); + dataMoments8[mIndex++] = p->RemapDataMoment(dm2); + dataMoments8[mIndex++] = p->RemapDataMoment(dm4); + dataMoments8[mIndex++] = p->RemapDataMoment(dm1); + dataMoments8[mIndex++] = p->RemapDataMoment(dm3); + dataMoments8[mIndex++] = p->RemapDataMoment(dm4); } else { @@ -492,6 +499,19 @@ void Level3RadialView::ComputeSweep() Q_EMIT SweepComputed(); } +std::uint8_t +Level3RadialView::Impl::RemapDataMoment(std::uint8_t dataMoment) const +{ + if (dataMoment != 0) + { + return dataMoment; + } + else + { + return edgeValue_; + } +} + void Level3RadialView::Impl::ComputeCoordinates( const std::shared_ptr& radialData, bool smoothingEnabled) diff --git a/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp b/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp index 75902b2a..433b51be 100644 --- a/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp +++ b/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp @@ -33,10 +33,13 @@ public: } ~Level3RasterViewImpl() { threadPool_.join(); }; + inline std::uint8_t RemapDataMoment(std::uint8_t dataMoment) const; + boost::asio::thread_pool threadPool_ {1u}; - std::vector vertices_; - std::vector dataMoments8_; + std::vector vertices_ {}; + std::vector dataMoments8_ {}; + std::uint8_t edgeValue_ {}; std::shared_ptr lastRasterData_ {}; bool lastSmoothingEnabled_ {false}; @@ -310,6 +313,13 @@ void Level3RasterView::ComputeSweep() rasterData->number_of_rows() - 1 : rasterData->number_of_rows(); + if (smoothingEnabled) + { + // For most products other than reflectivity, the edge should not go to + // the bottom of the color table + p->edgeValue_ = ComputeEdgeValue(); + } + for (std::size_t row = 0; row < rowCount; ++row) { const std::size_t nextRow = @@ -364,12 +374,12 @@ void Level3RasterView::ComputeSweep() } // The order must match the store vertices section below - dataMoments8[mIndex++] = dm1; - dataMoments8[mIndex++] = dm2; - dataMoments8[mIndex++] = dm4; - dataMoments8[mIndex++] = dm1; - dataMoments8[mIndex++] = dm3; - dataMoments8[mIndex++] = dm4; + dataMoments8[mIndex++] = p->RemapDataMoment(dm1); + dataMoments8[mIndex++] = p->RemapDataMoment(dm2); + dataMoments8[mIndex++] = p->RemapDataMoment(dm4); + dataMoments8[mIndex++] = p->RemapDataMoment(dm1); + dataMoments8[mIndex++] = p->RemapDataMoment(dm3); + dataMoments8[mIndex++] = p->RemapDataMoment(dm4); } // Store vertices @@ -411,6 +421,19 @@ void Level3RasterView::ComputeSweep() Q_EMIT SweepComputed(); } +std::uint8_t +Level3RasterViewImpl::RemapDataMoment(std::uint8_t dataMoment) const +{ + if (dataMoment != 0) + { + return dataMoment; + } + else + { + return edgeValue_; + } +} + std::optional Level3RasterView::GetBinLevel(const common::Coordinate& coordinate) const {