mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 14:00:06 +00:00
parent
869dee8288
commit
9c442574ae
3 changed files with 138 additions and 31 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
#include <scwx/qt/view/level3_radial_view.hpp>
|
#include <scwx/qt/view/level3_radial_view.hpp>
|
||||||
|
#include <scwx/qt/util/geographic_lib.hpp>
|
||||||
#include <scwx/common/constants.hpp>
|
#include <scwx/common/constants.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
#include <scwx/util/threads.hpp>
|
#include <scwx/util/threads.hpp>
|
||||||
|
|
@ -19,21 +20,37 @@ namespace view
|
||||||
static const std::string logPrefix_ = "scwx::qt::view::level3_radial_view";
|
static const std::string logPrefix_ = "scwx::qt::view::level3_radial_view";
|
||||||
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||||
|
|
||||||
static constexpr uint16_t RANGE_FOLDED = 1u;
|
static constexpr std::uint32_t kMaxRadialGates_ =
|
||||||
static constexpr uint32_t VERTICES_PER_BIN = 6u;
|
common::MAX_0_5_DEGREE_RADIALS * common::MAX_DATA_MOMENT_GATES;
|
||||||
static constexpr uint32_t VALUES_PER_VERTEX = 2u;
|
static constexpr std::uint32_t kMaxCoordinates_ = kMaxRadialGates_ * 2u;
|
||||||
|
|
||||||
|
static constexpr std::uint16_t RANGE_FOLDED = 1u;
|
||||||
|
static constexpr std::uint32_t VERTICES_PER_BIN = 6u;
|
||||||
|
static constexpr std::uint32_t VALUES_PER_VERTEX = 2u;
|
||||||
|
|
||||||
class Level3RadialViewImpl
|
class Level3RadialViewImpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Level3RadialViewImpl() :
|
explicit Level3RadialViewImpl(Level3RadialView* self) :
|
||||||
latitude_ {}, longitude_ {}, range_ {}, vcp_ {}, sweepTime_ {}
|
self_ {self},
|
||||||
|
latitude_ {},
|
||||||
|
longitude_ {},
|
||||||
|
range_ {},
|
||||||
|
vcp_ {},
|
||||||
|
sweepTime_ {}
|
||||||
{
|
{
|
||||||
|
coordinates_.resize(kMaxCoordinates_);
|
||||||
}
|
}
|
||||||
~Level3RadialViewImpl() = default;
|
~Level3RadialViewImpl() = default;
|
||||||
|
|
||||||
std::vector<float> vertices_;
|
void ComputeCoordinates(
|
||||||
std::vector<std::uint8_t> dataMoments8_;
|
std::shared_ptr<wsr88d::rpg::GenericRadialDataPacket> radialData);
|
||||||
|
|
||||||
|
Level3RadialView* self_;
|
||||||
|
|
||||||
|
std::vector<float> coordinates_ {};
|
||||||
|
std::vector<float> vertices_ {};
|
||||||
|
std::vector<std::uint8_t> dataMoments8_ {};
|
||||||
|
|
||||||
float latitude_;
|
float latitude_;
|
||||||
float longitude_;
|
float longitude_;
|
||||||
|
|
@ -47,7 +64,7 @@ Level3RadialView::Level3RadialView(
|
||||||
const std::string& product,
|
const std::string& product,
|
||||||
std::shared_ptr<manager::RadarProductManager> radarProductManager) :
|
std::shared_ptr<manager::RadarProductManager> radarProductManager) :
|
||||||
Level3ProductView(product, radarProductManager),
|
Level3ProductView(product, radarProductManager),
|
||||||
p(std::make_unique<Level3RadialViewImpl>())
|
p(std::make_unique<Level3RadialViewImpl>(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,7 +172,7 @@ void Level3RadialView::ComputeSweep()
|
||||||
}
|
}
|
||||||
|
|
||||||
// A message with radial data should either have a Digital Radial Data
|
// A message with radial data should either have a Digital Radial Data
|
||||||
// Array Packet, or a Radial Data Array Packet (TODO)
|
// Array Packet, or a Radial Data Array Packet
|
||||||
std::shared_ptr<wsr88d::rpg::DigitalRadialDataArrayPacket>
|
std::shared_ptr<wsr88d::rpg::DigitalRadialDataArrayPacket>
|
||||||
digitalDataPacket = nullptr;
|
digitalDataPacket = nullptr;
|
||||||
std::shared_ptr<wsr88d::rpg::RadialDataPacket> radialDataPacket = nullptr;
|
std::shared_ptr<wsr88d::rpg::RadialDataPacket> radialDataPacket = nullptr;
|
||||||
|
|
@ -205,20 +222,32 @@ void Level3RadialView::ComputeSweep()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume the number of radials should be 360 or 720
|
// Valid number of radials is 1-720
|
||||||
const size_t radials = radialData->number_of_radials();
|
size_t radials = radialData->number_of_radials();
|
||||||
if (radials != 360 && radials != 720)
|
if (radials < 1 || radials > 720)
|
||||||
{
|
{
|
||||||
logger_->warn("Unsupported number of radials: {}", radials);
|
logger_->warn("Unsupported number of radials: {}", radials);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const common::RadialSize radialSize =
|
common::RadialSize radialSize;
|
||||||
(radials == common::MAX_0_5_DEGREE_RADIALS) ?
|
if (radials == common::MAX_0_5_DEGREE_RADIALS)
|
||||||
common::RadialSize::_0_5Degree :
|
{
|
||||||
common::RadialSize::_1Degree;
|
radialSize = common::RadialSize::_0_5Degree;
|
||||||
|
}
|
||||||
|
else if (radials == common::MAX_1_DEGREE_RADIALS)
|
||||||
|
{
|
||||||
|
radialSize = common::RadialSize::_1Degree;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
radialSize = common::RadialSize::NonStandard;
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<float>& coordinates =
|
const std::vector<float>& coordinates =
|
||||||
radarProductManager->coordinates(radialSize);
|
(radialSize == common::RadialSize::NonStandard) ?
|
||||||
|
p->coordinates_ :
|
||||||
|
radarProductManager->coordinates(radialSize);
|
||||||
|
|
||||||
// There should be a positive number of range bins in radial data
|
// There should be a positive number of range bins in radial data
|
||||||
const uint16_t gates = radialData->number_of_range_bins();
|
const uint16_t gates = radialData->number_of_range_bins();
|
||||||
|
|
@ -232,8 +261,8 @@ void Level3RadialView::ComputeSweep()
|
||||||
p->longitude_ = descriptionBlock->longitude_of_radar();
|
p->longitude_ = descriptionBlock->longitude_of_radar();
|
||||||
p->range_ = descriptionBlock->range();
|
p->range_ = descriptionBlock->range();
|
||||||
p->sweepTime_ =
|
p->sweepTime_ =
|
||||||
util::TimePoint(descriptionBlock->volume_scan_date(),
|
scwx::util::TimePoint(descriptionBlock->volume_scan_date(),
|
||||||
descriptionBlock->volume_scan_start_time() * 1000);
|
descriptionBlock->volume_scan_start_time() * 1000);
|
||||||
p->vcp_ = descriptionBlock->volume_coverage_pattern();
|
p->vcp_ = descriptionBlock->volume_coverage_pattern();
|
||||||
|
|
||||||
// Calculate vertices
|
// Calculate vertices
|
||||||
|
|
@ -255,9 +284,18 @@ void Level3RadialView::ComputeSweep()
|
||||||
const uint16_t snrThreshold = descriptionBlock->threshold();
|
const uint16_t snrThreshold = descriptionBlock->threshold();
|
||||||
|
|
||||||
// Determine which radial to start at
|
// Determine which radial to start at
|
||||||
const float radialMultiplier = radials / 360.0f;
|
std::uint16_t startRadial;
|
||||||
const float startAngle = radialData->start_angle(0);
|
if (radialSize == common::RadialSize::NonStandard)
|
||||||
const uint16_t startRadial = std::lroundf(startAngle * radialMultiplier);
|
{
|
||||||
|
p->ComputeCoordinates(radialData);
|
||||||
|
startRadial = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const float radialMultiplier = radials / 360.0f;
|
||||||
|
const float startAngle = radialData->start_angle(0);
|
||||||
|
startRadial = std::lroundf(startAngle * radialMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
for (uint16_t radial = 0; radial < radialData->number_of_radials(); radial++)
|
for (uint16_t radial = 0; radial < radialData->number_of_radials(); radial++)
|
||||||
{
|
{
|
||||||
|
|
@ -371,6 +409,73 @@ void Level3RadialView::ComputeSweep()
|
||||||
emit SweepComputed();
|
emit SweepComputed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Level3RadialViewImpl::ComputeCoordinates(
|
||||||
|
std::shared_ptr<wsr88d::rpg::GenericRadialDataPacket> radialData)
|
||||||
|
{
|
||||||
|
logger_->debug("ComputeCoordinates()");
|
||||||
|
|
||||||
|
boost::timer::cpu_timer timer;
|
||||||
|
|
||||||
|
const GeographicLib::Geodesic& geodesic(
|
||||||
|
util::GeographicLib::DefaultGeodesic());
|
||||||
|
|
||||||
|
auto radarProductManager = self_->radar_product_manager();
|
||||||
|
auto radarSite = radarProductManager->radar_site();
|
||||||
|
const float gateSize = radarProductManager->gate_size();
|
||||||
|
const double radarLatitude = radarSite->latitude();
|
||||||
|
const double radarLongitude = radarSite->longitude();
|
||||||
|
|
||||||
|
// Calculate azimuth coordinates
|
||||||
|
timer.start();
|
||||||
|
|
||||||
|
const std::uint16_t numRadials = radialData->number_of_radials();
|
||||||
|
const std::uint16_t numRangeBins = radialData->number_of_range_bins();
|
||||||
|
const std::uint32_t numRadialGates = numRadials * numRangeBins;
|
||||||
|
const std::uint32_t maxRadialGates =
|
||||||
|
numRadials * common::MAX_DATA_MOMENT_GATES;
|
||||||
|
|
||||||
|
auto radialGates = boost::irange<uint32_t>(0, maxRadialGates);
|
||||||
|
|
||||||
|
std::for_each(
|
||||||
|
std::execution::par_unseq,
|
||||||
|
radialGates.begin(),
|
||||||
|
radialGates.end(),
|
||||||
|
[&](std::uint32_t radialGate)
|
||||||
|
{
|
||||||
|
const std::uint16_t gate = static_cast<std::uint16_t>(
|
||||||
|
radialGate % common::MAX_DATA_MOMENT_GATES);
|
||||||
|
|
||||||
|
if (gate >= numRadialGates)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::uint16_t radial = static_cast<std::uint16_t>(
|
||||||
|
radialGate / common::MAX_DATA_MOMENT_GATES);
|
||||||
|
|
||||||
|
const float deltaAngle =
|
||||||
|
(radial == 0) ? radialData->start_angle(0) -
|
||||||
|
radialData->start_angle(numRadials - 1) :
|
||||||
|
radialData->delta_angle(radial);
|
||||||
|
|
||||||
|
const float angle =
|
||||||
|
radialData->start_angle(radial) - (deltaAngle * 0.5f);
|
||||||
|
const float range = (gate + 1) * gateSize;
|
||||||
|
const std::size_t offset = radialGate * 2;
|
||||||
|
|
||||||
|
double latitude;
|
||||||
|
double longitude;
|
||||||
|
|
||||||
|
geodesic.Direct(
|
||||||
|
radarLatitude, radarLongitude, angle, range, latitude, longitude);
|
||||||
|
|
||||||
|
coordinates_[offset] = latitude;
|
||||||
|
coordinates_[offset + 1] = longitude;
|
||||||
|
});
|
||||||
|
timer.stop();
|
||||||
|
logger_->debug("Coordinates calculated in {}", timer.format(6, "%ws"));
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Level3RadialView> Level3RadialView::Create(
|
std::shared_ptr<Level3RadialView> Level3RadialView::Create(
|
||||||
const std::string& product,
|
const std::string& product,
|
||||||
std::shared_ptr<manager::RadarProductManager> radarProductManager)
|
std::shared_ptr<manager::RadarProductManager> radarProductManager)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ namespace common
|
||||||
enum class RadialSize
|
enum class RadialSize
|
||||||
{
|
{
|
||||||
_0_5Degree,
|
_0_5Degree,
|
||||||
_1Degree
|
_1Degree,
|
||||||
|
NonStandard
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace common
|
} // namespace common
|
||||||
|
|
|
||||||
|
|
@ -20,19 +20,20 @@ public:
|
||||||
explicit GenericRadialDataPacket();
|
explicit GenericRadialDataPacket();
|
||||||
~GenericRadialDataPacket();
|
~GenericRadialDataPacket();
|
||||||
|
|
||||||
GenericRadialDataPacket(const GenericRadialDataPacket&) = delete;
|
GenericRadialDataPacket(const GenericRadialDataPacket&) = delete;
|
||||||
GenericRadialDataPacket& operator=(const GenericRadialDataPacket&) = delete;
|
GenericRadialDataPacket& operator=(const GenericRadialDataPacket&) = delete;
|
||||||
|
|
||||||
GenericRadialDataPacket(GenericRadialDataPacket&&) noexcept;
|
GenericRadialDataPacket(GenericRadialDataPacket&&) noexcept;
|
||||||
GenericRadialDataPacket& operator=(GenericRadialDataPacket&&) noexcept;
|
GenericRadialDataPacket& operator=(GenericRadialDataPacket&&) noexcept;
|
||||||
|
virtual std::uint16_t index_of_first_range_bin() const = 0;
|
||||||
|
virtual std::int16_t i_center_of_sweep() const = 0;
|
||||||
|
virtual std::int16_t j_center_of_sweep() const = 0;
|
||||||
|
virtual std::uint16_t number_of_radials() const = 0;
|
||||||
|
virtual std::uint16_t number_of_range_bins() const = 0;
|
||||||
|
virtual float start_angle(std::uint16_t r) const = 0;
|
||||||
|
virtual float delta_angle(std::uint16_t r) const = 0;
|
||||||
|
|
||||||
virtual int16_t i_center_of_sweep() const = 0;
|
virtual const std::vector<std::uint8_t>& level(std::uint16_t r) const = 0;
|
||||||
virtual int16_t j_center_of_sweep() const = 0;
|
|
||||||
virtual uint16_t number_of_radials() const = 0;
|
|
||||||
virtual uint16_t number_of_range_bins() const = 0;
|
|
||||||
virtual float start_angle(uint16_t r) const = 0;
|
|
||||||
|
|
||||||
virtual const std::vector<uint8_t>& level(uint16_t r) const = 0;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<GenericRadialDataPacketImpl> p;
|
std::unique_ptr<GenericRadialDataPacketImpl> p;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue