Get bin values at coordinates from level 3 radial data, stubs for raster and level 2

This commit is contained in:
Dan Paulat 2024-01-02 00:42:42 -06:00
parent c67b4cf536
commit 6e04e1fab3
9 changed files with 153 additions and 19 deletions

View file

@ -774,6 +774,14 @@ void Level2ProductViewImpl::ComputeCoordinates(
logger_->debug("Coordinates calculated in {}", timer.format(6, "%ws"));
}
std::optional<std::uint16_t>
Level2ProductView::GetBinLevel(const common::Coordinate& coordinate) const
{
// TODO
Q_UNUSED(coordinate);
return std::nullopt;
}
std::shared_ptr<Level2ProductView> Level2ProductView::Create(
common::Level2Product product,
std::shared_ptr<manager::RadarProductManager> radarProductManager)

View file

@ -47,6 +47,8 @@ public:
GetMomentData() const override;
std::tuple<const void*, std::size_t, std::size_t>
GetCfpMomentData() const override;
std::optional<std::uint16_t>
GetBinLevel(const common::Coordinate& coordinate) const override;
static std::shared_ptr<Level2ProductView>
Create(common::Level2Product product,

View file

@ -27,10 +27,10 @@ static const auto logger_ = util::Logger::Create(logPrefix_);
static constexpr uint16_t RANGE_FOLDED = 1u;
class Level3ProductViewImpl
class Level3ProductView::Impl
{
public:
explicit Level3ProductViewImpl(const std::string& product) :
explicit Impl(const std::string& product) :
product_ {product},
graphicMessage_ {nullptr},
colorTable_ {},
@ -42,7 +42,7 @@ public:
savedOffset_ {0.0f}
{
}
~Level3ProductViewImpl() = default;
~Impl() = default;
std::string product_;
@ -61,8 +61,7 @@ public:
Level3ProductView::Level3ProductView(
const std::string& product,
std::shared_ptr<manager::RadarProductManager> radarProductManager) :
RadarProductView(radarProductManager),
p(std::make_unique<Level3ProductViewImpl>(product))
RadarProductView(radarProductManager), p(std::make_unique<Impl>(product))
{
ConnectRadarProductManager();
}

View file

@ -15,8 +15,6 @@ namespace qt
namespace view
{
class Level3ProductViewImpl;
class Level3ProductView : public RadarProductView
{
Q_OBJECT
@ -52,7 +50,8 @@ protected:
void UpdateColorTable() override;
private:
std::unique_ptr<Level3ProductViewImpl> p;
class Impl;
std::unique_ptr<Impl> p;
};
} // namespace view

View file

@ -28,10 +28,10 @@ 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 Level3RadialView::Impl
{
public:
explicit Level3RadialViewImpl(Level3RadialView* self) :
explicit Impl(Level3RadialView* self) :
self_ {self},
latitude_ {},
longitude_ {},
@ -41,10 +41,10 @@ public:
{
coordinates_.resize(kMaxCoordinates_);
}
~Level3RadialViewImpl() { threadPool_.join(); };
~Impl() { threadPool_.join(); };
void ComputeCoordinates(
std::shared_ptr<wsr88d::rpg::GenericRadialDataPacket> radialData);
const std::shared_ptr<wsr88d::rpg::GenericRadialDataPacket>& radialData);
Level3RadialView* self_;
@ -54,6 +54,8 @@ public:
std::vector<float> vertices_ {};
std::vector<std::uint8_t> dataMoments8_ {};
std::shared_ptr<wsr88d::rpg::GenericRadialDataPacket> lastRadialData_ {};
float latitude_;
float longitude_;
float range_;
@ -66,7 +68,7 @@ Level3RadialView::Level3RadialView(
const std::string& product,
std::shared_ptr<manager::RadarProductManager> radarProductManager) :
Level3ProductView(product, radarProductManager),
p(std::make_unique<Level3RadialViewImpl>(this))
p(std::make_unique<Impl>(this))
{
}
@ -235,6 +237,8 @@ void Level3RadialView::ComputeSweep()
return;
}
p->lastRadialData_ = radialData;
// Valid number of radials is 1-720
size_t radials = radialData->number_of_radials();
if (radials < 1 || radials > 720)
@ -424,8 +428,8 @@ void Level3RadialView::ComputeSweep()
Q_EMIT SweepComputed();
}
void Level3RadialViewImpl::ComputeCoordinates(
std::shared_ptr<wsr88d::rpg::GenericRadialDataPacket> radialData)
void Level3RadialView::Impl::ComputeCoordinates(
const std::shared_ptr<wsr88d::rpg::GenericRadialDataPacket>& radialData)
{
logger_->debug("ComputeCoordinates()");
@ -485,6 +489,113 @@ void Level3RadialViewImpl::ComputeCoordinates(
logger_->debug("Coordinates calculated in {}", timer.format(6, "%ws"));
}
std::optional<std::uint16_t>
Level3RadialView::GetBinLevel(const common::Coordinate& coordinate) const
{
auto gpm = graphic_product_message();
if (gpm == nullptr)
{
return std::nullopt;
}
std::shared_ptr<wsr88d::rpg::ProductDescriptionBlock> descriptionBlock =
gpm->description_block();
if (descriptionBlock == nullptr)
{
return std::nullopt;
}
std::shared_ptr<wsr88d::rpg::GenericRadialDataPacket> radialData =
p->lastRadialData_;
if (radialData == nullptr)
{
return std::nullopt;
}
// Determine distance and azimuth of coordinate relative to radar location
double s12; // Distance (meters)
double azi1; // Azimuth (degrees)
double azi2; // Unused
util::GeographicLib::DefaultGeodesic().Inverse(
descriptionBlock->latitude_of_radar(),
descriptionBlock->longitude_of_radar(),
coordinate.latitude_,
coordinate.longitude_,
s12,
azi1,
azi2);
if (std::isnan(azi1))
{
// If a problem occurred with the geodesic inverse calculation
return std::nullopt;
}
// Azimuth is returned as [-180, 180) from the geodesic inverse, we need a
// range of [0, 360)
while (azi1 < 0.0)
{
azi1 += 360.0;
}
// Compute gate interval
const std::uint16_t gates = radialData->number_of_range_bins();
const std::uint16_t dataMomentInterval =
descriptionBlock->x_resolution_raw();
std::uint16_t gate = s12 / dataMomentInterval;
if (gate >= gates)
{
// Coordinate is beyond radar range
return std::nullopt;
}
// Find Radial
const std::uint16_t numRadials = radialData->number_of_radials();
std::uint16_t radial = numRadials;
float nextAngle = radialData->start_angle(0);
for (std::uint16_t i = 0; i < numRadials; ++i)
{
float startAngle = nextAngle;
nextAngle = radialData->start_angle((i + 1) % numRadials);
if (startAngle < nextAngle)
{
if (startAngle <= azi1 && azi1 < nextAngle)
{
radial = i;
break;
}
}
else
{
// If the bin crosses 0/360 degrees, special handling is needed
if (startAngle <= azi1 || azi1 < nextAngle)
{
radial = i;
break;
}
}
}
if (radial == numRadials)
{
// No radial was found (not likely to happen without a gap in data)
return std::nullopt;
}
// Compute threshold at which to display an individual bin
const std::uint16_t snrThreshold = descriptionBlock->threshold();
const std::uint8_t level = radialData->level(radial).at(gate);
if (level < snrThreshold && level != RANGE_FOLDED)
{
return std::nullopt;
}
return level;
}
std::shared_ptr<Level3RadialView> Level3RadialView::Create(
const std::string& product,
std::shared_ptr<manager::RadarProductManager> radarProductManager)

View file

@ -13,8 +13,6 @@ namespace qt
namespace view
{
class Level3RadialViewImpl;
class Level3RadialView : public Level3ProductView
{
Q_OBJECT
@ -32,6 +30,8 @@ public:
std::tuple<const void*, std::size_t, std::size_t>
GetMomentData() const override;
std::optional<std::uint16_t>
GetBinLevel(const common::Coordinate& coordinate) const override;
static std::shared_ptr<Level3RadialView>
Create(const std::string& product,
@ -44,7 +44,8 @@ protected slots:
void ComputeSweep() override;
private:
std::unique_ptr<Level3RadialViewImpl> p;
class Impl;
std::unique_ptr<Impl> p;
};
} // namespace view

View file

@ -352,6 +352,14 @@ void Level3RasterView::ComputeSweep()
Q_EMIT SweepComputed();
}
std::optional<std::uint16_t>
Level3RasterView::GetBinLevel(const common::Coordinate& coordinate) const
{
// TODO
Q_UNUSED(coordinate);
return std::nullopt;
}
std::shared_ptr<Level3RasterView> Level3RasterView::Create(
const std::string& product,
std::shared_ptr<manager::RadarProductManager> radarProductManager)

View file

@ -32,6 +32,8 @@ public:
std::tuple<const void*, std::size_t, std::size_t>
GetMomentData() const override;
std::optional<std::uint16_t>
GetBinLevel(const common::Coordinate& coordinate) const override;
static std::shared_ptr<Level3RasterView>
Create(const std::string& product,

View file

@ -1,6 +1,7 @@
#pragma once
#include <scwx/common/color_table.hpp>
#include <scwx/common/geographic.hpp>
#include <scwx/common/products.hpp>
#include <scwx/qt/manager/radar_product_manager.hpp>
#include <scwx/qt/types/map_types.hpp>
@ -8,6 +9,7 @@
#include <chrono>
#include <memory>
#include <mutex>
#include <optional>
#include <vector>
#include <QObject>
@ -64,6 +66,8 @@ public:
GetMomentData() const = 0;
virtual std::tuple<const void*, std::size_t, std::size_t>
GetCfpMomentData() const;
virtual std::optional<std::uint16_t>
GetBinLevel(const common::Coordinate& coordinate) const = 0;
std::chrono::system_clock::time_point GetSelectedTime() const;
virtual std::vector<std::pair<std::string, std::string>>