mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-29 18:00:05 +00:00
Deriving level 2 product view
This commit is contained in:
parent
2f1f15938a
commit
9ee52e7a6b
12 changed files with 602 additions and 354 deletions
|
|
@ -62,29 +62,29 @@
|
|||
<element xmi:type="uml:Operation" href="scwx.uml#_Ra89oC9-EeyWgvKLGfX-VA"/>
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_RbGHkS9-EeyWgvKLGfX-VA"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_91ztkC9-EeyWgvKLGfX-VA" type="Operation_ClassOperationLabel">
|
||||
<element xmi:type="uml:Operation" href="scwx.uml#_91rKsC9-EeyWgvKLGfX-VA"/>
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_910UoC9-EeyWgvKLGfX-VA"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_-xocoC9-EeyWgvKLGfX-VA" type="Operation_ClassOperationLabel">
|
||||
<element xmi:type="uml:Operation" href="scwx.uml#_-xc2cC9-EeyWgvKLGfX-VA"/>
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_-xocoS9-EeyWgvKLGfX-VA"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_CcI_gC9_EeyWgvKLGfX-VA" type="Operation_ClassOperationLabel">
|
||||
<element xmi:type="uml:Operation" href="scwx.uml#_Cb_1kC9_EeyWgvKLGfX-VA"/>
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_CcI_gS9_EeyWgvKLGfX-VA"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_91ztkC9-EeyWgvKLGfX-VA" type="Operation_ClassOperationLabel">
|
||||
<element xmi:type="uml:Operation" href="scwx.uml#_91rKsC9-EeyWgvKLGfX-VA"/>
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_910UoC9-EeyWgvKLGfX-VA"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="__jMccC9-EeyWgvKLGfX-VA" type="Operation_ClassOperationLabel">
|
||||
<element xmi:type="uml:Operation" href="scwx.uml#__jCEYC9-EeyWgvKLGfX-VA"/>
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="__jMccS9-EeyWgvKLGfX-VA"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_c8L5wDqCEey_nYE4G1Fl-w" type="Operation_ClassOperationLabel">
|
||||
<element xmi:type="uml:Operation" href="scwx.uml#_c77bEDqCEey_nYE4G1Fl-w"/>
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_c8L5wTqCEey_nYE4G1Fl-w"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_BfOrUC9_EeyWgvKLGfX-VA" type="Operation_ClassOperationLabel">
|
||||
<element xmi:type="uml:Operation" href="scwx.uml#_BfETQC9_EeyWgvKLGfX-VA"/>
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_BfOrUS9_EeyWgvKLGfX-VA"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_CcI_gC9_EeyWgvKLGfX-VA" type="Operation_ClassOperationLabel">
|
||||
<element xmi:type="uml:Operation" href="scwx.uml#_Cb_1kC9_EeyWgvKLGfX-VA"/>
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_CcI_gS9_EeyWgvKLGfX-VA"/>
|
||||
<children xmi:type="notation:Shape" xmi:id="_c8L5wDqCEey_nYE4G1Fl-w" type="Operation_ClassOperationLabel">
|
||||
<element xmi:type="uml:Operation" href="scwx.uml#_c77bEDqCEey_nYE4G1Fl-w"/>
|
||||
<layoutConstraint xmi:type="notation:Location" xmi:id="_c8L5wTqCEey_nYE4G1Fl-w"/>
|
||||
</children>
|
||||
<children xmi:type="notation:Shape" xmi:id="_ZAK94DqHEey_nYE4G1Fl-w" type="Operation_ClassOperationLabel">
|
||||
<element xmi:type="uml:Operation" href="scwx.uml#_Y__XsDqHEey_nYE4G1Fl-w"/>
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@
|
|||
<ownedOperation xmi:type="uml:Operation" xmi:id="_BfETQC9_EeyWgvKLGfX-VA" name="LoadColorTable">
|
||||
<ownedParameter xmi:type="uml:Parameter" xmi:id="_ZiBNADQAEeyGO_jIbsSKUw" type="_8fCdAC-AEeyWgvKLGfX-VA"/>
|
||||
</ownedOperation>
|
||||
<ownedOperation xmi:type="uml:Operation" xmi:id="_Cb_1kC9_EeyWgvKLGfX-VA" name="SweepTime">
|
||||
<ownedOperation xmi:type="uml:Operation" xmi:id="_Cb_1kC9_EeyWgvKLGfX-VA" name="sweep_time">
|
||||
<ownedParameter xmi:type="uml:Parameter" xmi:id="_tZRrUDQAEeyGO_jIbsSKUw" direction="return">
|
||||
<type xmi:type="uml:Class" href="std.uml#_L1eGYC9_EeyWgvKLGfX-VA"/>
|
||||
</ownedParameter>
|
||||
|
|
@ -131,4 +131,9 @@
|
|||
<C_Cpp:Ptr xmi:id="_sVLIYC9-EeyWgvKLGfX-VA" base_parameter="_fn3IQC9-EeyWgvKLGfX-VA"/>
|
||||
<C_Cpp:Ptr xmi:id="_a-OFQDQAEeyGO_jIbsSKUw" base_parameter="_ZiBNADQAEeyGO_jIbsSKUw"/>
|
||||
<C_Cpp:Ptr xmi:id="_lr6qADqCEey_nYE4G1Fl-w" base_parameter="_kEgAQDqCEey_nYE4G1Fl-w"/>
|
||||
<C_Cpp:Virtual xmi:id="_GY4iwDrAEey_nYE4G1Fl-w" base_operation="_-xc2cC9-EeyWgvKLGfX-VA"/>
|
||||
<C_Cpp:Virtual xmi:id="_HndOsDrAEey_nYE4G1Fl-w" base_operation="_Cb_1kC9_EeyWgvKLGfX-VA"/>
|
||||
<C_Cpp:Virtual xmi:id="_Jlj6IDrAEey_nYE4G1Fl-w" base_operation="_91rKsC9-EeyWgvKLGfX-VA"/>
|
||||
<C_Cpp:Virtual xmi:id="_NpMHoDrAEey_nYE4G1Fl-w" base_operation="_BfETQC9_EeyWgvKLGfX-VA"/>
|
||||
<C_Cpp:Virtual xmi:id="_PYPqcDrAEey_nYE4G1Fl-w" base_operation="_c77bEDqCEey_nYE4G1Fl-w"/>
|
||||
</xmi:XMI>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#Sun Oct 31 15:18:03 CDT 2021
|
||||
#Sun Oct 31 22:03:12 CDT 2021
|
||||
_label_asdf=asdf2
|
||||
|
|
|
|||
|
|
@ -82,8 +82,12 @@ set(HDR_UTIL source/scwx/qt/util/font.hpp
|
|||
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/radar_product_view.hpp)
|
||||
set(SRC_VIEW source/scwx/qt/view/radar_product_view.cpp)
|
||||
set(HDR_VIEW source/scwx/qt/view/level2_product_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/radar_product_view.cpp
|
||||
source/scwx/qt/view/radar_product_view_factory.cpp)
|
||||
|
||||
set(RESOURCE_FILES scwx-qt.qrc)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
#include <scwx/qt/map/map_widget.hpp>
|
||||
#include <scwx/qt/gl/gl.hpp>
|
||||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||
#include <scwx/qt/map/overlay_layer.hpp>
|
||||
#include <scwx/qt/map/radar_product_layer.hpp>
|
||||
#include <scwx/qt/map/radar_range_layer.hpp>
|
||||
#include <scwx/qt/view/radar_product_view_factory.hpp>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QColor>
|
||||
|
|
@ -104,7 +106,7 @@ void MapWidget::changeStyle()
|
|||
void MapWidget::AddLayers()
|
||||
{
|
||||
std::shared_ptr<view::RadarProductView> radarProductView =
|
||||
std::make_shared<view::RadarProductView>(p->radarProductManager_);
|
||||
view::RadarProductViewFactory::Create("L2REF", p->radarProductManager_);
|
||||
|
||||
radarProductView->Initialize();
|
||||
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ void OverlayLayer::render(const QMapbox::CustomLayerRenderParameters& params)
|
|||
{
|
||||
using namespace std::chrono;
|
||||
auto sweepTime =
|
||||
time_point_cast<seconds>(p->radarProductView_->SweepTime());
|
||||
time_point_cast<seconds>(p->radarProductView_->sweep_time());
|
||||
|
||||
if (sweepTime.time_since_epoch().count() != 0)
|
||||
{
|
||||
|
|
|
|||
404
scwx-qt/source/scwx/qt/view/level2_product_view.cpp
Normal file
404
scwx-qt/source/scwx/qt/view/level2_product_view.cpp
Normal file
|
|
@ -0,0 +1,404 @@
|
|||
#include <scwx/qt/view/level2_product_view.hpp>
|
||||
#include <scwx/common/constants.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::level2_product_view] ";
|
||||
|
||||
static constexpr uint32_t VERTICES_PER_BIN = 6;
|
||||
static constexpr uint32_t VALUES_PER_VERTEX = 2;
|
||||
|
||||
static const std::unordered_map<std::string, wsr88d::rda::DataBlockType>
|
||||
blockTypes_ {{PRODUCT_L2_REF, wsr88d::rda::DataBlockType::MomentRef},
|
||||
{PRODUCT_L2_VEL, wsr88d::rda::DataBlockType::MomentVel},
|
||||
{PRODUCT_L2_SW, wsr88d::rda::DataBlockType::MomentSw},
|
||||
{PRODUCT_L2_ZDR, wsr88d::rda::DataBlockType::MomentZdr},
|
||||
{PRODUCT_L2_PHI, wsr88d::rda::DataBlockType::MomentPhi},
|
||||
{PRODUCT_L2_RHO, wsr88d::rda::DataBlockType::MomentRho},
|
||||
{PRODUCT_L2_CFP, wsr88d::rda::DataBlockType::MomentCfp}};
|
||||
|
||||
static std::chrono::system_clock::time_point
|
||||
TimePoint(uint16_t modifiedJulianDate, uint32_t milliseconds);
|
||||
|
||||
class Level2ProductViewImpl
|
||||
{
|
||||
public:
|
||||
explicit Level2ProductViewImpl(
|
||||
const std::string& productName,
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager) :
|
||||
radarProductManager_ {radarProductManager}, sweepTime_ {}, colorTable_ {}
|
||||
{
|
||||
auto it = blockTypes_.find(productName);
|
||||
|
||||
if (it != blockTypes_.end())
|
||||
{
|
||||
dataBlockType_ = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Unknown product: \"" << productName << "\"";
|
||||
dataBlockType_ = wsr88d::rda::DataBlockType::Unknown;
|
||||
}
|
||||
}
|
||||
~Level2ProductViewImpl() = default;
|
||||
|
||||
wsr88d::rda::DataBlockType dataBlockType_;
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager_;
|
||||
|
||||
std::vector<float> vertices_;
|
||||
std::vector<uint8_t> dataMoments8_;
|
||||
std::vector<uint16_t> dataMoments16_;
|
||||
|
||||
std::chrono::system_clock::time_point sweepTime_;
|
||||
|
||||
std::vector<boost::gil::rgba8_pixel_t> colorTable_;
|
||||
};
|
||||
|
||||
Level2ProductView::Level2ProductView(
|
||||
const std::string& productName,
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager) :
|
||||
p(std::make_unique<Level2ProductViewImpl>(productName, radarProductManager))
|
||||
{
|
||||
connect(radarProductManager.get(),
|
||||
&manager::RadarProductManager::Level2DataLoaded,
|
||||
this,
|
||||
&Level2ProductView::ComputeSweep);
|
||||
}
|
||||
Level2ProductView::~Level2ProductView() = default;
|
||||
|
||||
const std::vector<boost::gil::rgba8_pixel_t>&
|
||||
Level2ProductView::color_table() const
|
||||
{
|
||||
if (p->colorTable_.size() == 0)
|
||||
{
|
||||
return RadarProductView::color_table();
|
||||
}
|
||||
else
|
||||
{
|
||||
return p->colorTable_;
|
||||
}
|
||||
}
|
||||
|
||||
std::chrono::system_clock::time_point Level2ProductView::sweep_time() const
|
||||
{
|
||||
return p->sweepTime_;
|
||||
}
|
||||
|
||||
const std::vector<float>& Level2ProductView::vertices() const
|
||||
{
|
||||
return p->vertices_;
|
||||
}
|
||||
|
||||
std::tuple<const void*, size_t, size_t> Level2ProductView::GetMomentData() const
|
||||
{
|
||||
const void* data;
|
||||
size_t dataSize;
|
||||
size_t componentSize;
|
||||
|
||||
if (p->dataMoments8_.size() > 0)
|
||||
{
|
||||
data = p->dataMoments8_.data();
|
||||
dataSize = p->dataMoments8_.size() * sizeof(uint8_t);
|
||||
componentSize = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = p->dataMoments16_.data();
|
||||
dataSize = p->dataMoments16_.size() * sizeof(uint16_t);
|
||||
componentSize = 2;
|
||||
}
|
||||
|
||||
return std::tie(data, dataSize, componentSize);
|
||||
}
|
||||
|
||||
void Level2ProductView::LoadColorTable(
|
||||
std::shared_ptr<common::ColorTable> colorTable)
|
||||
{
|
||||
// TODO: Make size, offset and scale dynamic
|
||||
const float offset = 66.0f;
|
||||
const float scale = 2.0f;
|
||||
|
||||
std::vector<boost::gil::rgba8_pixel_t>& lut = p->colorTable_;
|
||||
lut.resize(254);
|
||||
|
||||
auto dataRange = boost::irange<uint16_t>(2, 255);
|
||||
|
||||
std::for_each(std::execution::par_unseq,
|
||||
dataRange.begin(),
|
||||
dataRange.end(),
|
||||
[&](uint16_t i) {
|
||||
float f = (i - offset) / scale;
|
||||
lut[i - *dataRange.begin()] = colorTable->Color(f);
|
||||
});
|
||||
|
||||
emit ColorTableLoaded();
|
||||
}
|
||||
|
||||
void Level2ProductView::ComputeSweep()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "ComputeSweep()";
|
||||
|
||||
boost::timer::cpu_timer timer;
|
||||
|
||||
if (p->dataBlockType_ == wsr88d::rda::DataBlockType::Unknown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<const wsr88d::Ar2vFile> level2Data =
|
||||
p->radarProductManager_->level2_data();
|
||||
if (level2Data == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Pick this based on radar data
|
||||
const std::vector<float>& coordinates =
|
||||
p->radarProductManager_->coordinates(common::RadialSize::_0_5Degree);
|
||||
|
||||
// TODO: Pick this based on view settings
|
||||
auto radarData = level2Data->radar_data()[0];
|
||||
|
||||
p->sweepTime_ = TimePoint(radarData[0]->modified_julian_date(),
|
||||
radarData[0]->collection_time());
|
||||
|
||||
// Calculate vertices
|
||||
timer.start();
|
||||
|
||||
auto momentData0 = radarData[0]->moment_data_block(p->dataBlockType_);
|
||||
|
||||
// Setup vertex vector
|
||||
std::vector<float>& vertices = p->vertices_;
|
||||
const size_t radials = radarData.size();
|
||||
const uint32_t gates = momentData0->number_of_data_moment_gates();
|
||||
size_t vIndex = 0;
|
||||
vertices.clear();
|
||||
vertices.resize(radials * gates * VERTICES_PER_BIN * VALUES_PER_VERTEX);
|
||||
|
||||
// Setup data moment vector
|
||||
std::vector<uint8_t>& dataMoments8 = p->dataMoments8_;
|
||||
std::vector<uint16_t>& dataMoments16 = p->dataMoments16_;
|
||||
size_t mIndex = 0;
|
||||
|
||||
if (momentData0->data_word_size() == 8)
|
||||
{
|
||||
dataMoments16.resize(0);
|
||||
dataMoments16.shrink_to_fit();
|
||||
|
||||
dataMoments8.resize(radials * gates * VERTICES_PER_BIN);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataMoments8.resize(0);
|
||||
dataMoments8.shrink_to_fit();
|
||||
|
||||
dataMoments16.resize(radials * gates * VERTICES_PER_BIN);
|
||||
}
|
||||
|
||||
// Compute threshold at which to display an individual bin
|
||||
const float scale = momentData0->scale();
|
||||
const float offset = momentData0->offset();
|
||||
const uint16_t snrThreshold =
|
||||
std::lroundf(momentData0->snr_threshold_raw() * scale / 10 + offset);
|
||||
|
||||
// Azimuth resolution spacing:
|
||||
// 1 = 0.5 degrees
|
||||
// 2 = 1.0 degrees
|
||||
const float radialMultiplier =
|
||||
2.0f /
|
||||
std::clamp<int8_t>(radarData[0]->azimuth_resolution_spacing(), 1, 2);
|
||||
|
||||
const float startAngle = radarData[0]->azimuth_angle();
|
||||
const uint16_t startRadial = std::lroundf(startAngle * radialMultiplier);
|
||||
|
||||
for (uint16_t radial = 0; radial < radials; ++radial)
|
||||
{
|
||||
auto radialData = radarData[radial];
|
||||
auto momentData = radarData[radial]->moment_data_block(p->dataBlockType_);
|
||||
|
||||
if (momentData0->data_word_size() != momentData->data_word_size())
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Radial " << radial << " has different word size";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute gate interval
|
||||
const uint16_t dataMomentRange = momentData->data_moment_range_raw();
|
||||
const uint16_t dataMomentInterval =
|
||||
momentData->data_moment_range_sample_interval_raw();
|
||||
const uint16_t dataMomentIntervalH = dataMomentInterval / 2;
|
||||
|
||||
// Compute gate size (number of base 250m gates per bin)
|
||||
const uint16_t gateSize = std::max<uint16_t>(1, dataMomentInterval / 250);
|
||||
|
||||
// Compute gate range [startGate, endGate)
|
||||
const uint16_t startGate = (dataMomentRange - dataMomentIntervalH) / 250;
|
||||
const uint16_t numberOfDataMomentGates =
|
||||
std::min<uint16_t>(momentData->number_of_data_moment_gates(),
|
||||
static_cast<uint16_t>(gates));
|
||||
const uint16_t endGate =
|
||||
std::min<uint16_t>(startGate + numberOfDataMomentGates * gateSize,
|
||||
common::MAX_DATA_MOMENT_GATES);
|
||||
|
||||
const uint8_t* dataMomentsArray8 = nullptr;
|
||||
const uint16_t* dataMomentsArray16 = nullptr;
|
||||
|
||||
if (momentData->data_word_size() == 8)
|
||||
{
|
||||
dataMomentsArray8 =
|
||||
reinterpret_cast<const uint8_t*>(momentData->data_moments());
|
||||
}
|
||||
else
|
||||
{
|
||||
dataMomentsArray16 =
|
||||
reinterpret_cast<const uint16_t*>(momentData->data_moments());
|
||||
}
|
||||
|
||||
for (uint16_t gate = startGate, i = 0; gate + gateSize <= endGate;
|
||||
gate += gateSize, ++i)
|
||||
{
|
||||
size_t vertexCount = (gate > 0) ? 6 : 3;
|
||||
|
||||
// Store data moment value
|
||||
if (dataMomentsArray8 != nullptr)
|
||||
{
|
||||
uint8_t dataValue = dataMomentsArray8[i];
|
||||
if (dataValue < snrThreshold)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t m = 0; m < vertexCount; m++)
|
||||
{
|
||||
dataMoments8[mIndex++] = dataMomentsArray8[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t dataValue = dataMomentsArray16[i];
|
||||
if (dataValue < snrThreshold)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t m = 0; m < vertexCount; m++)
|
||||
{
|
||||
dataMoments16[mIndex++] = dataMomentsArray16[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Store vertices
|
||||
if (gate > 0)
|
||||
{
|
||||
const uint16_t baseCoord = gate - 1;
|
||||
|
||||
size_t offset1 = ((startRadial + radial) % common::MAX_RADIALS *
|
||||
common::MAX_DATA_MOMENT_GATES +
|
||||
baseCoord) *
|
||||
2;
|
||||
size_t offset2 = offset1 + gateSize * 2;
|
||||
size_t offset3 =
|
||||
(((startRadial + radial + 1) % common::MAX_RADIALS) *
|
||||
common::MAX_DATA_MOMENT_GATES +
|
||||
baseCoord) *
|
||||
2;
|
||||
size_t offset4 = offset3 + gateSize * 2;
|
||||
|
||||
vertices[vIndex++] = coordinates[offset1];
|
||||
vertices[vIndex++] = coordinates[offset1 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset2];
|
||||
vertices[vIndex++] = coordinates[offset2 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset3];
|
||||
vertices[vIndex++] = coordinates[offset3 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset3];
|
||||
vertices[vIndex++] = coordinates[offset3 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset4];
|
||||
vertices[vIndex++] = coordinates[offset4 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset2];
|
||||
vertices[vIndex++] = coordinates[offset2 + 1];
|
||||
|
||||
vertexCount = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint16_t baseCoord = gate;
|
||||
|
||||
size_t offset1 = ((startRadial + radial) % common::MAX_RADIALS *
|
||||
common::MAX_DATA_MOMENT_GATES +
|
||||
baseCoord) *
|
||||
2;
|
||||
size_t offset2 =
|
||||
(((startRadial + radial + 1) % common::MAX_RADIALS) *
|
||||
common::MAX_DATA_MOMENT_GATES +
|
||||
baseCoord) *
|
||||
2;
|
||||
|
||||
// TODO: Radar location
|
||||
vertices[vIndex++] = 38.6986f;
|
||||
vertices[vIndex++] = -90.6828f;
|
||||
|
||||
vertices[vIndex++] = coordinates[offset1];
|
||||
vertices[vIndex++] = coordinates[offset1 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset2];
|
||||
vertices[vIndex++] = coordinates[offset2 + 1];
|
||||
|
||||
vertexCount = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
vertices.resize(vIndex);
|
||||
|
||||
if (momentData0->data_word_size() == 8)
|
||||
{
|
||||
dataMoments8.resize(mIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataMoments16.resize(mIndex);
|
||||
}
|
||||
|
||||
timer.stop();
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< logPrefix_ << "Vertices calculated in " << timer.format(6, "%ws");
|
||||
|
||||
emit SweepComputed();
|
||||
}
|
||||
|
||||
std::shared_ptr<Level2ProductView> Level2ProductView::Create(
|
||||
const std::string& productName,
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager)
|
||||
{
|
||||
return std::make_shared<Level2ProductView>(productName, radarProductManager);
|
||||
}
|
||||
|
||||
static std::chrono::system_clock::time_point
|
||||
TimePoint(uint16_t modifiedJulianDate, uint32_t milliseconds)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using sys_days = time_point<system_clock, days>;
|
||||
constexpr auto epoch = sys_days {1969y / December / 31d};
|
||||
|
||||
return epoch + (modifiedJulianDate * 24h) +
|
||||
std::chrono::milliseconds {milliseconds};
|
||||
}
|
||||
|
||||
} // namespace view
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
59
scwx-qt/source/scwx/qt/view/level2_product_view.hpp
Normal file
59
scwx-qt/source/scwx/qt/view/level2_product_view.hpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#pragma once
|
||||
|
||||
#include <scwx/common/color_table.hpp>
|
||||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||
#include <scwx/qt/view/radar_product_view.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
{
|
||||
namespace view
|
||||
{
|
||||
|
||||
const std::string PRODUCT_L2_REF = "L2REF";
|
||||
const std::string PRODUCT_L2_VEL = "L2VEL";
|
||||
const std::string PRODUCT_L2_SW = "L2SW";
|
||||
const std::string PRODUCT_L2_ZDR = "L2ZDR";
|
||||
const std::string PRODUCT_L2_PHI = "L2PHI";
|
||||
const std::string PRODUCT_L2_RHO = "L2RHO";
|
||||
const std::string PRODUCT_L2_CFP = "L2CFP";
|
||||
|
||||
class Level2ProductViewImpl;
|
||||
|
||||
class Level2ProductView : public RadarProductView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Level2ProductView(
|
||||
const std::string& productName,
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager);
|
||||
~Level2ProductView();
|
||||
|
||||
const std::vector<boost::gil::rgba8_pixel_t>& color_table() const;
|
||||
std::chrono::system_clock::time_point sweep_time() const;
|
||||
const std::vector<float>& vertices() const;
|
||||
|
||||
void LoadColorTable(std::shared_ptr<common::ColorTable> colorTable);
|
||||
|
||||
std::tuple<const void*, size_t, size_t> GetMomentData() const;
|
||||
|
||||
static std::shared_ptr<Level2ProductView>
|
||||
Create(const std::string& productName,
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager);
|
||||
|
||||
protected slots:
|
||||
void ComputeSweep();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Level2ProductViewImpl> p;
|
||||
};
|
||||
|
||||
} // namespace view
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
|
|
@ -14,57 +14,31 @@ namespace view
|
|||
|
||||
static const std::string logPrefix_ = "[scwx::qt::view::radar_product_view] ";
|
||||
|
||||
static constexpr uint32_t VERTICES_PER_BIN = 6;
|
||||
static constexpr uint32_t VALUES_PER_VERTEX = 2;
|
||||
|
||||
static std::chrono::system_clock::time_point
|
||||
TimePoint(uint16_t modifiedJulianDate, uint32_t milliseconds);
|
||||
static const std::vector<boost::gil::rgba8_pixel_t> DEFAULT_COLOR_TABLE = {
|
||||
boost::gil::rgba8_pixel_t(0, 128, 0, 255),
|
||||
boost::gil::rgba8_pixel_t(255, 192, 0, 255),
|
||||
boost::gil::rgba8_pixel_t(255, 0, 0, 255)};
|
||||
|
||||
class RadarProductViewImpl
|
||||
{
|
||||
public:
|
||||
explicit RadarProductViewImpl(
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager) :
|
||||
radarProductManager_(radarProductManager),
|
||||
sweepTime_(),
|
||||
colorTable_ {boost::gil::rgba8_pixel_t(0, 128, 0, 255),
|
||||
boost::gil::rgba8_pixel_t(255, 192, 0, 255),
|
||||
boost::gil::rgba8_pixel_t(255, 0, 0, 255)}
|
||||
{
|
||||
}
|
||||
explicit RadarProductViewImpl() = default;
|
||||
~RadarProductViewImpl() = default;
|
||||
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager_;
|
||||
|
||||
std::vector<float> vertices_;
|
||||
std::vector<uint8_t> dataMoments8_;
|
||||
std::vector<uint16_t> dataMoments16_;
|
||||
|
||||
std::chrono::system_clock::time_point sweepTime_;
|
||||
|
||||
std::vector<boost::gil::rgba8_pixel_t> colorTable_;
|
||||
};
|
||||
|
||||
RadarProductView::RadarProductView(
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager) :
|
||||
p(std::make_unique<RadarProductViewImpl>(radarProductManager))
|
||||
{
|
||||
connect(radarProductManager.get(),
|
||||
&manager::RadarProductManager::Level2DataLoaded,
|
||||
this,
|
||||
&RadarProductView::ComputeSweep);
|
||||
}
|
||||
RadarProductView::RadarProductView() :
|
||||
p(std::make_unique<RadarProductViewImpl>()) {};
|
||||
RadarProductView::~RadarProductView() = default;
|
||||
|
||||
const std::vector<float>& RadarProductView::vertices() const
|
||||
{
|
||||
return p->vertices_;
|
||||
}
|
||||
|
||||
const std::vector<boost::gil::rgba8_pixel_t>&
|
||||
RadarProductView::color_table() const
|
||||
{
|
||||
return p->colorTable_;
|
||||
return DEFAULT_COLOR_TABLE;
|
||||
}
|
||||
|
||||
std::chrono::system_clock::time_point RadarProductView::sweep_time() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void RadarProductView::Initialize()
|
||||
|
|
@ -72,300 +46,13 @@ void RadarProductView::Initialize()
|
|||
ComputeSweep();
|
||||
}
|
||||
|
||||
std::tuple<const void*, size_t, size_t> RadarProductView::GetMomentData()
|
||||
{
|
||||
const void* data;
|
||||
size_t dataSize;
|
||||
size_t componentSize;
|
||||
|
||||
if (p->dataMoments8_.size() > 0)
|
||||
{
|
||||
data = p->dataMoments8_.data();
|
||||
dataSize = p->dataMoments8_.size() * sizeof(uint8_t);
|
||||
componentSize = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = p->dataMoments16_.data();
|
||||
dataSize = p->dataMoments16_.size() * sizeof(uint16_t);
|
||||
componentSize = 2;
|
||||
}
|
||||
|
||||
return std::tie(data, dataSize, componentSize);
|
||||
}
|
||||
|
||||
void RadarProductView::LoadColorTable(
|
||||
std::shared_ptr<common::ColorTable> colorTable)
|
||||
{
|
||||
// TODO: Make size, offset and scale dynamic
|
||||
const float offset = 66.0f;
|
||||
const float scale = 2.0f;
|
||||
|
||||
std::vector<boost::gil::rgba8_pixel_t>& lut = p->colorTable_;
|
||||
lut.resize(254);
|
||||
|
||||
auto dataRange = boost::irange<uint16_t>(2, 255);
|
||||
|
||||
std::for_each(std::execution::par_unseq,
|
||||
dataRange.begin(),
|
||||
dataRange.end(),
|
||||
[&](uint16_t i) {
|
||||
float f = (i - offset) / scale;
|
||||
lut[i - *dataRange.begin()] = colorTable->Color(f);
|
||||
});
|
||||
|
||||
emit ColorTableLoaded();
|
||||
}
|
||||
|
||||
std::chrono::system_clock::time_point RadarProductView::SweepTime()
|
||||
{
|
||||
return p->sweepTime_;
|
||||
}
|
||||
|
||||
void RadarProductView::ComputeSweep()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "ComputeSweep()";
|
||||
|
||||
boost::timer::cpu_timer timer;
|
||||
|
||||
// TODO: Pick this based on radar data
|
||||
const std::vector<float>& coordinates =
|
||||
p->radarProductManager_->coordinates(common::RadialSize::_0_5Degree);
|
||||
|
||||
std::shared_ptr<const wsr88d::Ar2vFile> level2Data =
|
||||
p->radarProductManager_->level2_data();
|
||||
if (level2Data == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Pick these based on view settings
|
||||
auto radarData = level2Data->radar_data()[0];
|
||||
wsr88d::rda::DataBlockType blockType = wsr88d::rda::DataBlockType::MomentRef;
|
||||
|
||||
p->sweepTime_ = TimePoint(radarData[0]->modified_julian_date(),
|
||||
radarData[0]->collection_time());
|
||||
|
||||
// Calculate vertices
|
||||
timer.start();
|
||||
|
||||
auto momentData0 = radarData[0]->moment_data_block(blockType);
|
||||
|
||||
// Setup vertex vector
|
||||
std::vector<float>& vertices = p->vertices_;
|
||||
const size_t radials = radarData.size();
|
||||
const uint32_t gates = momentData0->number_of_data_moment_gates();
|
||||
size_t vIndex = 0;
|
||||
vertices.clear();
|
||||
vertices.resize(radials * gates * VERTICES_PER_BIN * VALUES_PER_VERTEX);
|
||||
|
||||
// Setup data moment vector
|
||||
std::vector<uint8_t>& dataMoments8 = p->dataMoments8_;
|
||||
std::vector<uint16_t>& dataMoments16 = p->dataMoments16_;
|
||||
size_t mIndex = 0;
|
||||
|
||||
if (momentData0->data_word_size() == 8)
|
||||
{
|
||||
dataMoments16.resize(0);
|
||||
dataMoments16.shrink_to_fit();
|
||||
|
||||
dataMoments8.resize(radials * gates * VERTICES_PER_BIN);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataMoments8.resize(0);
|
||||
dataMoments8.shrink_to_fit();
|
||||
|
||||
dataMoments16.resize(radials * gates * VERTICES_PER_BIN);
|
||||
}
|
||||
|
||||
// Compute threshold at which to display an individual bin
|
||||
const float scale = momentData0->scale();
|
||||
const float offset = momentData0->offset();
|
||||
const uint16_t snrThreshold =
|
||||
std::lroundf(momentData0->snr_threshold_raw() * scale / 10 + offset);
|
||||
|
||||
// Azimuth resolution spacing:
|
||||
// 1 = 0.5 degrees
|
||||
// 2 = 1.0 degrees
|
||||
const float radialMultiplier =
|
||||
2.0f /
|
||||
std::clamp<int8_t>(radarData[0]->azimuth_resolution_spacing(), 1, 2);
|
||||
|
||||
const float startAngle = radarData[0]->azimuth_angle();
|
||||
const uint16_t startRadial = std::lroundf(startAngle * radialMultiplier);
|
||||
|
||||
for (uint16_t radial = 0; radial < radials; ++radial)
|
||||
{
|
||||
auto radialData = radarData[radial];
|
||||
auto momentData = radarData[radial]->moment_data_block(blockType);
|
||||
|
||||
if (momentData0->data_word_size() != momentData->data_word_size())
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Radial " << radial << " has different word size";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute gate interval
|
||||
const uint16_t dataMomentRange = momentData->data_moment_range_raw();
|
||||
const uint16_t dataMomentInterval =
|
||||
momentData->data_moment_range_sample_interval_raw();
|
||||
const uint16_t dataMomentIntervalH = dataMomentInterval / 2;
|
||||
|
||||
// Compute gate size (number of base 250m gates per bin)
|
||||
const uint16_t gateSize = std::max<uint16_t>(1, dataMomentInterval / 250);
|
||||
|
||||
// Compute gate range [startGate, endGate)
|
||||
const uint16_t startGate = (dataMomentRange - dataMomentIntervalH) / 250;
|
||||
const uint16_t numberOfDataMomentGates =
|
||||
std::min<uint16_t>(momentData->number_of_data_moment_gates(),
|
||||
static_cast<uint16_t>(gates));
|
||||
const uint16_t endGate =
|
||||
std::min<uint16_t>(startGate + numberOfDataMomentGates * gateSize,
|
||||
common::MAX_DATA_MOMENT_GATES);
|
||||
|
||||
const uint8_t* dataMomentsArray8 = nullptr;
|
||||
const uint16_t* dataMomentsArray16 = nullptr;
|
||||
|
||||
if (momentData->data_word_size() == 8)
|
||||
{
|
||||
dataMomentsArray8 =
|
||||
reinterpret_cast<const uint8_t*>(momentData->data_moments());
|
||||
}
|
||||
else
|
||||
{
|
||||
dataMomentsArray16 =
|
||||
reinterpret_cast<const uint16_t*>(momentData->data_moments());
|
||||
}
|
||||
|
||||
for (uint16_t gate = startGate, i = 0; gate + gateSize <= endGate;
|
||||
gate += gateSize, ++i)
|
||||
{
|
||||
size_t vertexCount = (gate > 0) ? 6 : 3;
|
||||
|
||||
// Store data moment value
|
||||
if (dataMomentsArray8 != nullptr)
|
||||
{
|
||||
uint8_t dataValue = dataMomentsArray8[i];
|
||||
if (dataValue < snrThreshold)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t m = 0; m < vertexCount; m++)
|
||||
{
|
||||
dataMoments8[mIndex++] = dataMomentsArray8[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t dataValue = dataMomentsArray16[i];
|
||||
if (dataValue < snrThreshold)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t m = 0; m < vertexCount; m++)
|
||||
{
|
||||
dataMoments16[mIndex++] = dataMomentsArray16[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Store vertices
|
||||
if (gate > 0)
|
||||
{
|
||||
const uint16_t baseCoord = gate - 1;
|
||||
|
||||
size_t offset1 = ((startRadial + radial) % common::MAX_RADIALS *
|
||||
common::MAX_DATA_MOMENT_GATES +
|
||||
baseCoord) *
|
||||
2;
|
||||
size_t offset2 = offset1 + gateSize * 2;
|
||||
size_t offset3 =
|
||||
(((startRadial + radial + 1) % common::MAX_RADIALS) *
|
||||
common::MAX_DATA_MOMENT_GATES +
|
||||
baseCoord) *
|
||||
2;
|
||||
size_t offset4 = offset3 + gateSize * 2;
|
||||
|
||||
vertices[vIndex++] = coordinates[offset1];
|
||||
vertices[vIndex++] = coordinates[offset1 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset2];
|
||||
vertices[vIndex++] = coordinates[offset2 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset3];
|
||||
vertices[vIndex++] = coordinates[offset3 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset3];
|
||||
vertices[vIndex++] = coordinates[offset3 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset4];
|
||||
vertices[vIndex++] = coordinates[offset4 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset2];
|
||||
vertices[vIndex++] = coordinates[offset2 + 1];
|
||||
|
||||
vertexCount = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint16_t baseCoord = gate;
|
||||
|
||||
size_t offset1 = ((startRadial + radial) % common::MAX_RADIALS *
|
||||
common::MAX_DATA_MOMENT_GATES +
|
||||
baseCoord) *
|
||||
2;
|
||||
size_t offset2 =
|
||||
(((startRadial + radial + 1) % common::MAX_RADIALS) *
|
||||
common::MAX_DATA_MOMENT_GATES +
|
||||
baseCoord) *
|
||||
2;
|
||||
|
||||
// TODO: Radar location
|
||||
vertices[vIndex++] = 38.6986f;
|
||||
vertices[vIndex++] = -90.6828f;
|
||||
|
||||
vertices[vIndex++] = coordinates[offset1];
|
||||
vertices[vIndex++] = coordinates[offset1 + 1];
|
||||
|
||||
vertices[vIndex++] = coordinates[offset2];
|
||||
vertices[vIndex++] = coordinates[offset2 + 1];
|
||||
|
||||
vertexCount = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
vertices.resize(vIndex);
|
||||
|
||||
if (momentData0->data_word_size() == 8)
|
||||
{
|
||||
dataMoments8.resize(mIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataMoments16.resize(mIndex);
|
||||
}
|
||||
|
||||
timer.stop();
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< logPrefix_ << "Vertices calculated in " << timer.format(6, "%ws");
|
||||
|
||||
emit SweepComputed();
|
||||
}
|
||||
|
||||
static std::chrono::system_clock::time_point
|
||||
TimePoint(uint16_t modifiedJulianDate, uint32_t milliseconds)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using sys_days = time_point<system_clock, days>;
|
||||
constexpr auto epoch = sys_days {1969y / December / 31d};
|
||||
|
||||
return epoch + (modifiedJulianDate * 24h) +
|
||||
std::chrono::milliseconds {milliseconds};
|
||||
}
|
||||
|
||||
} // namespace view
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <scwx/common/color_table.hpp>
|
||||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
|
|
@ -21,22 +22,21 @@ class RadarProductView : public QObject
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RadarProductView(
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager);
|
||||
explicit RadarProductView();
|
||||
~RadarProductView();
|
||||
|
||||
const std::vector<float>& vertices() const;
|
||||
const std::vector<boost::gil::rgba8_pixel_t>& color_table() const;
|
||||
virtual const std::vector<boost::gil::rgba8_pixel_t>& color_table() const;
|
||||
virtual std::chrono::system_clock::time_point sweep_time() const;
|
||||
virtual const std::vector<float>& vertices() const = 0;
|
||||
|
||||
void Initialize();
|
||||
virtual void
|
||||
LoadColorTable(std::shared_ptr<common::ColorTable> colorTable) = 0;
|
||||
|
||||
std::tuple<const void*, size_t, size_t> GetMomentData();
|
||||
void LoadColorTable(std::shared_ptr<common::ColorTable> colorTable);
|
||||
|
||||
std::chrono::system_clock::time_point SweepTime();
|
||||
virtual std::tuple<const void*, size_t, size_t> GetMomentData() const = 0;
|
||||
|
||||
protected slots:
|
||||
void ComputeSweep();
|
||||
virtual void ComputeSweep();
|
||||
|
||||
signals:
|
||||
void ColorTableLoaded();
|
||||
|
|
|
|||
51
scwx-qt/source/scwx/qt/view/radar_product_view_factory.cpp
Normal file
51
scwx-qt/source/scwx/qt/view/radar_product_view_factory.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include <scwx/qt/view/radar_product_view_factory.hpp>
|
||||
#include <scwx/qt/view/level2_product_view.hpp>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
{
|
||||
namespace view
|
||||
{
|
||||
|
||||
static const std::string logPrefix_ =
|
||||
"[scwx::qt::view::radar_product_view_factory] ";
|
||||
|
||||
typedef std::function<std::shared_ptr<RadarProductView>(
|
||||
const std::string& productName,
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager)>
|
||||
CreateRadarProductFunction;
|
||||
|
||||
static const std::unordered_map<std::string, CreateRadarProductFunction>
|
||||
create_ {{PRODUCT_L2_REF, Level2ProductView::Create},
|
||||
{PRODUCT_L2_VEL, Level2ProductView::Create},
|
||||
{PRODUCT_L2_SW, Level2ProductView::Create},
|
||||
{PRODUCT_L2_ZDR, Level2ProductView::Create},
|
||||
{PRODUCT_L2_PHI, Level2ProductView::Create},
|
||||
{PRODUCT_L2_RHO, Level2ProductView::Create},
|
||||
{PRODUCT_L2_CFP, Level2ProductView::Create}};
|
||||
|
||||
std::shared_ptr<RadarProductView> RadarProductViewFactory::Create(
|
||||
const std::string& productName,
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager)
|
||||
{
|
||||
std::shared_ptr<RadarProductView> view = nullptr;
|
||||
|
||||
if (create_.find(productName) == create_.end())
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Unknown radar product: " << productName;
|
||||
}
|
||||
else
|
||||
{
|
||||
view = create_.at(productName)(productName, radarProductManager);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
} // namespace view
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
36
scwx-qt/source/scwx/qt/view/radar_product_view_factory.hpp
Normal file
36
scwx-qt/source/scwx/qt/view/radar_product_view_factory.hpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||
#include <scwx/qt/view/radar_product_view.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace qt
|
||||
{
|
||||
namespace view
|
||||
{
|
||||
|
||||
class RadarProductViewFactory
|
||||
{
|
||||
private:
|
||||
explicit RadarProductViewFactory() = delete;
|
||||
~RadarProductViewFactory() = delete;
|
||||
|
||||
RadarProductViewFactory(const RadarProductViewFactory&) = delete;
|
||||
RadarProductViewFactory& operator=(const RadarProductViewFactory&) = delete;
|
||||
|
||||
RadarProductViewFactory(RadarProductViewFactory&&) noexcept = delete;
|
||||
RadarProductViewFactory&
|
||||
operator=(RadarProductViewFactory&&) noexcept = delete;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<RadarProductView>
|
||||
Create(const std::string& productName,
|
||||
std::shared_ptr<manager::RadarProductManager> radarProductManager);
|
||||
};
|
||||
|
||||
} // namespace view
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
Loading…
Add table
Add a link
Reference in a new issue