Refactoring common level 3 product view functions to new parent class

This commit is contained in:
Dan Paulat 2022-04-09 09:22:27 -05:00
parent 41fda1e9cf
commit 1dbc68a7d9
5 changed files with 285 additions and 187 deletions

View file

@ -105,10 +105,12 @@ set(SRC_UTIL source/scwx/qt/util/font.cpp
source/scwx/qt/util/font_buffer.cpp
source/scwx/qt/util/json.cpp)
set(HDR_VIEW source/scwx/qt/view/level2_product_view.hpp
source/scwx/qt/view/level3_product_view.hpp
source/scwx/qt/view/level3_radial_view.hpp
source/scwx/qt/view/radar_product_view.hpp
source/scwx/qt/view/radar_product_view_factory.hpp)
set(SRC_VIEW source/scwx/qt/view/level2_product_view.cpp
source/scwx/qt/view/level3_product_view.cpp
source/scwx/qt/view/level3_radial_view.cpp
source/scwx/qt/view/radar_product_view.cpp
source/scwx/qt/view/radar_product_view_factory.cpp)

View file

@ -0,0 +1,225 @@
#include <scwx/qt/view/level3_product_view.hpp>
#include <scwx/common/constants.hpp>
#include <scwx/util/threads.hpp>
#include <scwx/util/time.hpp>
#include <scwx/wsr88d/rpg/digital_radial_data_array_packet.hpp>
#include <scwx/wsr88d/rpg/graphic_product_message.hpp>
#include <scwx/wsr88d/rpg/radial_data_packet.hpp>
#include <boost/log/trivial.hpp>
#include <boost/range/irange.hpp>
#include <boost/timer/timer.hpp>
namespace scwx
{
namespace qt
{
namespace view
{
static const std::string logPrefix_ = "[scwx::qt::view::level3_product_view] ";
static constexpr uint16_t RANGE_FOLDED = 1u;
class Level3ProductViewImpl
{
public:
explicit Level3ProductViewImpl(const std::string& product) :
product_ {product},
graphicMessage_ {nullptr},
colorTable_ {},
colorTableLut_ {},
colorTableMin_ {2},
colorTableMax_ {254},
savedColorTable_ {nullptr},
savedScale_ {0.0f},
savedOffset_ {0.0f}
{
}
~Level3ProductViewImpl() = default;
std::string product_;
std::shared_ptr<wsr88d::rpg::GraphicProductMessage> graphicMessage_;
std::shared_ptr<common::ColorTable> colorTable_;
std::vector<boost::gil::rgba8_pixel_t> colorTableLut_;
uint16_t colorTableMin_;
uint16_t colorTableMax_;
std::shared_ptr<common::ColorTable> savedColorTable_;
float savedScale_;
float savedOffset_;
};
Level3ProductView::Level3ProductView(const std::string& product) :
p(std::make_unique<Level3ProductViewImpl>(product))
{
}
Level3ProductView::~Level3ProductView() = default;
const std::vector<boost::gil::rgba8_pixel_t>&
Level3ProductView::color_table() const
{
if (p->colorTableLut_.size() == 0)
{
return RadarProductView::color_table();
}
else
{
return p->colorTableLut_;
}
}
uint16_t Level3ProductView::color_table_min() const
{
if (p->colorTableLut_.size() == 0)
{
return RadarProductView::color_table_min();
}
else
{
return p->colorTableMin_;
}
}
uint16_t Level3ProductView::color_table_max() const
{
if (p->colorTableLut_.size() == 0)
{
return RadarProductView::color_table_max();
}
else
{
return p->colorTableMax_;
}
}
std::shared_ptr<wsr88d::rpg::GraphicProductMessage>
Level3ProductView::graphic_product_message() const
{
return p->graphicMessage_;
}
void Level3ProductView::set_graphic_product_message(
std::shared_ptr<wsr88d::rpg::GraphicProductMessage> gpm)
{
p->graphicMessage_ = gpm;
}
common::RadarProductGroup Level3ProductView::GetRadarProductGroup() const
{
return common::RadarProductGroup::Level3;
}
std::string Level3ProductView::GetRadarProductName() const
{
return p->product_;
}
void Level3ProductView::LoadColorTable(
std::shared_ptr<common::ColorTable> colorTable)
{
p->colorTable_ = colorTable;
UpdateColorTable();
}
void Level3ProductView::Update()
{
util::async([=]() { ComputeSweep(); });
}
void Level3ProductView::UpdateColorTable()
{
if (p->graphicMessage_ == nullptr || //
p->colorTable_ == nullptr || //
!p->colorTable_->IsValid())
{
// Nothing to update
return;
}
std::shared_ptr<wsr88d::rpg::ProductDescriptionBlock> descriptionBlock =
p->graphicMessage_->description_block();
if (descriptionBlock == nullptr)
{
// No description block
return;
}
float offset = descriptionBlock->offset();
float scale = descriptionBlock->scale();
uint16_t threshold = descriptionBlock->threshold();
if (p->savedColorTable_ == p->colorTable_ && //
p->savedOffset_ == offset && //
p->savedScale_ == scale)
{
// The color table LUT does not need updated
return;
}
// If the threshold is 2, the range min should be set to 1 for range folding
uint16_t rangeMin = std::min<uint16_t>(1, threshold);
uint16_t rangeMax = descriptionBlock->number_of_levels();
boost::integer_range<uint16_t> dataRange =
boost::irange<uint16_t>(rangeMin, rangeMax + 1);
std::vector<boost::gil::rgba8_pixel_t>& lut = p->colorTableLut_;
lut.resize(rangeMax - rangeMin + 1);
lut.shrink_to_fit();
std::for_each(std::execution::par_unseq,
dataRange.begin(),
dataRange.end(),
[&](uint16_t i)
{
if (i == RANGE_FOLDED && threshold > RANGE_FOLDED)
{
lut[i - *dataRange.begin()] = p->colorTable_->rf_color();
}
else
{
float f;
// Different products use different scale/offset formulas
switch (descriptionBlock->product_code())
{
case 159:
case 161:
case 163:
case 167:
case 168:
case 170:
case 172:
case 173:
case 174:
case 175:
case 176:
f = (i - offset) / scale;
break;
default:
f = i * scale + offset;
break;
}
lut[i - *dataRange.begin()] = p->colorTable_->Color(f);
}
});
p->colorTableMin_ = rangeMin;
p->colorTableMax_ = rangeMax;
p->savedColorTable_ = p->colorTable_;
p->savedOffset_ = offset;
p->savedScale_ = scale;
emit ColorTableUpdated();
}
} // namespace view
} // namespace qt
} // namespace scwx

View file

@ -0,0 +1,52 @@
#pragma once
#include <scwx/common/color_table.hpp>
#include <scwx/common/products.hpp>
#include <scwx/qt/view/radar_product_view.hpp>
#include <scwx/wsr88d/rpg/graphic_product_message.hpp>
#include <memory>
#include <vector>
namespace scwx
{
namespace qt
{
namespace view
{
class Level3ProductViewImpl;
class Level3ProductView : public RadarProductView
{
Q_OBJECT
public:
explicit Level3ProductView(const std::string& product);
~Level3ProductView();
const std::vector<boost::gil::rgba8_pixel_t>& color_table() const override;
uint16_t color_table_min() const override;
uint16_t color_table_max() const override;
void LoadColorTable(std::shared_ptr<common::ColorTable> colorTable) override;
void Update() override;
common::RadarProductGroup GetRadarProductGroup() const override;
std::string GetRadarProductName() const override;
protected:
std::shared_ptr<wsr88d::rpg::GraphicProductMessage>
graphic_product_message() const;
void set_graphic_product_message(
std::shared_ptr<wsr88d::rpg::GraphicProductMessage> gpm);
void UpdateColorTable() override;
private:
std::unique_ptr<Level3ProductViewImpl> p;
};
} // namespace view
} // namespace qt
} // namespace scwx

View file

@ -3,7 +3,6 @@
#include <scwx/util/threads.hpp>
#include <scwx/util/time.hpp>
#include <scwx/wsr88d/rpg/digital_radial_data_array_packet.hpp>
#include <scwx/wsr88d/rpg/graphic_product_message.hpp>
#include <scwx/wsr88d/rpg/radial_data_packet.hpp>
#include <boost/log/trivial.hpp>
@ -32,19 +31,11 @@ public:
product_ {product},
radarProductManager_ {radarProductManager},
selectedTime_ {},
graphicMessage_ {nullptr},
latitude_ {},
longitude_ {},
range_ {},
vcp_ {},
sweepTime_ {},
colorTable_ {},
colorTableLut_ {},
colorTableMin_ {2},
colorTableMax_ {254},
savedColorTable_ {nullptr},
savedScale_ {0.0f},
savedOffset_ {0.0f}
sweepTime_ {}
{
}
~Level3RadialViewImpl() = default;
@ -54,8 +45,6 @@ public:
std::chrono::system_clock::time_point selectedTime_;
std::shared_ptr<wsr88d::rpg::GraphicProductMessage> graphicMessage_;
std::vector<float> vertices_;
std::vector<uint8_t> dataMoments8_;
@ -65,62 +54,17 @@ public:
uint16_t vcp_;
std::chrono::system_clock::time_point sweepTime_;
std::shared_ptr<common::ColorTable> colorTable_;
std::vector<boost::gil::rgba8_pixel_t> colorTableLut_;
uint16_t colorTableMin_;
uint16_t colorTableMax_;
std::shared_ptr<common::ColorTable> savedColorTable_;
float savedScale_;
float savedOffset_;
};
Level3RadialView::Level3RadialView(
const std::string& product,
std::shared_ptr<manager::RadarProductManager> radarProductManager) :
Level3ProductView(product),
p(std::make_unique<Level3RadialViewImpl>(product, radarProductManager))
{
}
Level3RadialView::~Level3RadialView() = default;
const std::vector<boost::gil::rgba8_pixel_t>&
Level3RadialView::color_table() const
{
if (p->colorTableLut_.size() == 0)
{
return RadarProductView::color_table();
}
else
{
return p->colorTableLut_;
}
}
uint16_t Level3RadialView::color_table_min() const
{
if (p->colorTableLut_.size() == 0)
{
return RadarProductView::color_table_min();
}
else
{
return p->colorTableMin_;
}
}
uint16_t Level3RadialView::color_table_max() const
{
if (p->colorTableLut_.size() == 0)
{
return RadarProductView::color_table_max();
}
else
{
return p->colorTableMax_;
}
}
float Level3RadialView::range() const
{
return p->range_;
@ -141,16 +85,6 @@ const std::vector<float>& Level3RadialView::vertices() const
return p->vertices_;
}
common::RadarProductGroup Level3RadialView::GetRadarProductGroup() const
{
return common::RadarProductGroup::Level3;
}
std::string Level3RadialView::GetRadarProductName() const
{
return p->product_;
}
std::tuple<const void*, size_t, size_t> Level3RadialView::GetMomentData() const
{
const void* data;
@ -164,114 +98,11 @@ std::tuple<const void*, size_t, size_t> Level3RadialView::GetMomentData() const
return std::tie(data, dataSize, componentSize);
}
void Level3RadialView::LoadColorTable(
std::shared_ptr<common::ColorTable> colorTable)
{
p->colorTable_ = colorTable;
UpdateColorTable();
}
void Level3RadialView::SelectTime(std::chrono::system_clock::time_point time)
{
p->selectedTime_ = time;
}
void Level3RadialView::Update()
{
util::async([=]() { ComputeSweep(); });
}
void Level3RadialView::UpdateColorTable()
{
if (p->graphicMessage_ == nullptr || //
p->colorTable_ == nullptr || //
!p->colorTable_->IsValid())
{
// Nothing to update
return;
}
std::shared_ptr<wsr88d::rpg::ProductDescriptionBlock> descriptionBlock =
p->graphicMessage_->description_block();
if (descriptionBlock == nullptr)
{
// No description block
return;
}
float offset = descriptionBlock->offset();
float scale = descriptionBlock->scale();
uint16_t threshold = descriptionBlock->threshold();
if (p->savedColorTable_ == p->colorTable_ && //
p->savedOffset_ == offset && //
p->savedScale_ == scale)
{
// The color table LUT does not need updated
return;
}
// If the threshold is 2, the range min should be set to 1 for range folding
uint16_t rangeMin = std::min<uint16_t>(1, threshold);
uint16_t rangeMax = descriptionBlock->number_of_levels();
boost::integer_range<uint16_t> dataRange =
boost::irange<uint16_t>(rangeMin, rangeMax + 1);
std::vector<boost::gil::rgba8_pixel_t>& lut = p->colorTableLut_;
lut.resize(rangeMax - rangeMin + 1);
lut.shrink_to_fit();
std::for_each(std::execution::par_unseq,
dataRange.begin(),
dataRange.end(),
[&](uint16_t i)
{
if (i == RANGE_FOLDED && threshold > RANGE_FOLDED)
{
lut[i - *dataRange.begin()] = p->colorTable_->rf_color();
}
else
{
float f;
// Different products use different scale/offset formulas
switch (descriptionBlock->product_code())
{
case 159:
case 161:
case 163:
case 167:
case 168:
case 170:
case 172:
case 173:
case 174:
case 175:
case 176:
f = (i - offset) / scale;
break;
default:
f = i * scale + offset;
break;
}
lut[i - *dataRange.begin()] = p->colorTable_->Color(f);
}
});
p->colorTableMin_ = rangeMin;
p->colorTableMax_ = rangeMax;
p->savedColorTable_ = p->colorTable_;
p->savedOffset_ = offset;
p->savedScale_ = scale;
emit ColorTableUpdated();
}
void Level3RadialView::ComputeSweep()
{
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "ComputeSweep()";
@ -293,12 +124,12 @@ void Level3RadialView::ComputeSweep()
<< logPrefix_ << "Graphic Product Message not found";
return;
}
else if (gpm == p->graphicMessage_)
else if (gpm == graphic_product_message())
{
// Skip if this is the message we previously processed
return;
}
p->graphicMessage_ = gpm;
set_graphic_product_message(gpm);
// A message with radial data should have a Product Description Block and
// Product Symbology Block

View file

@ -1,9 +1,7 @@
#pragma once
#include <scwx/common/color_table.hpp>
#include <scwx/common/products.hpp>
#include <scwx/qt/view/level3_product_view.hpp>
#include <scwx/qt/manager/radar_product_manager.hpp>
#include <scwx/qt/view/radar_product_view.hpp>
#include <chrono>
#include <memory>
@ -18,7 +16,7 @@ namespace view
class Level3RadialViewImpl;
class Level3RadialView : public RadarProductView
class Level3RadialView : public Level3ProductView
{
Q_OBJECT
@ -28,29 +26,19 @@ public:
std::shared_ptr<manager::RadarProductManager> radarProductManager);
~Level3RadialView();
const std::vector<boost::gil::rgba8_pixel_t>& color_table() const override;
uint16_t color_table_min() const override;
uint16_t color_table_max() const override;
float range() const override;
std::chrono::system_clock::time_point sweep_time() const override;
uint16_t vcp() const override;
const std::vector<float>& vertices() const override;
void LoadColorTable(std::shared_ptr<common::ColorTable> colorTable) override;
void SelectTime(std::chrono::system_clock::time_point time) override;
void Update() override;
common::RadarProductGroup GetRadarProductGroup() const override;
std::string GetRadarProductName() const override;
std::tuple<const void*, size_t, size_t> GetMomentData() const override;
static std::shared_ptr<Level3RadialView>
Create(const std::string& product,
std::shared_ptr<manager::RadarProductManager> radarProductManager);
protected:
void UpdateColorTable() override;
protected slots:
void ComputeSweep() override;