mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 22:30:06 +00:00
Calculate level 2 coordinates every rendering frame
- More accurate bin rendering position - Eliminates "rocking" when animating - 40-45ms negative impact on rendering per frame (specific to my setup) Fixes #53
This commit is contained in:
parent
9536a1fdcb
commit
1c84b061dc
1 changed files with 111 additions and 26 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
#include <scwx/qt/view/level2_product_view.hpp>
|
#include <scwx/qt/view/level2_product_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>
|
||||||
|
|
@ -17,6 +18,10 @@ namespace view
|
||||||
static const std::string logPrefix_ = "scwx::qt::view::level2_product_view";
|
static const std::string logPrefix_ = "scwx::qt::view::level2_product_view";
|
||||||
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||||
|
|
||||||
|
static constexpr std::uint32_t kMaxRadialGates_ =
|
||||||
|
common::MAX_0_5_DEGREE_RADIALS * common::MAX_DATA_MOMENT_GATES;
|
||||||
|
static constexpr std::uint32_t kMaxCoordinates_ = kMaxRadialGates_ * 2u;
|
||||||
|
|
||||||
static constexpr uint16_t RANGE_FOLDED = 1u;
|
static constexpr uint16_t RANGE_FOLDED = 1u;
|
||||||
static constexpr uint32_t VERTICES_PER_BIN = 6u;
|
static constexpr uint32_t VERTICES_PER_BIN = 6u;
|
||||||
static constexpr uint32_t VALUES_PER_VERTEX = 2u;
|
static constexpr uint32_t VALUES_PER_VERTEX = 2u;
|
||||||
|
|
@ -41,7 +46,9 @@ static const std::unordered_map<common::Level2Product,
|
||||||
class Level2ProductViewImpl
|
class Level2ProductViewImpl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Level2ProductViewImpl(common::Level2Product product) :
|
explicit Level2ProductViewImpl(Level2ProductView* self,
|
||||||
|
common::Level2Product product) :
|
||||||
|
self_ {self},
|
||||||
product_ {product},
|
product_ {product},
|
||||||
selectedElevation_ {0.0f},
|
selectedElevation_ {0.0f},
|
||||||
elevationScan_ {nullptr},
|
elevationScan_ {nullptr},
|
||||||
|
|
@ -61,13 +68,20 @@ public:
|
||||||
savedScale_ {0.0f},
|
savedScale_ {0.0f},
|
||||||
savedOffset_ {0.0f}
|
savedOffset_ {0.0f}
|
||||||
{
|
{
|
||||||
|
coordinates_.resize(kMaxCoordinates_);
|
||||||
|
|
||||||
SetProduct(product);
|
SetProduct(product);
|
||||||
}
|
}
|
||||||
~Level2ProductViewImpl() = default;
|
~Level2ProductViewImpl() = default;
|
||||||
|
|
||||||
|
void
|
||||||
|
ComputeCoordinates(std::shared_ptr<wsr88d::rda::ElevationScan> radarData);
|
||||||
|
|
||||||
void SetProduct(const std::string& productName);
|
void SetProduct(const std::string& productName);
|
||||||
void SetProduct(common::Level2Product product);
|
void SetProduct(common::Level2Product product);
|
||||||
|
|
||||||
|
Level2ProductView* self_;
|
||||||
|
|
||||||
common::Level2Product product_;
|
common::Level2Product product_;
|
||||||
wsr88d::rda::DataBlockType dataBlockType_;
|
wsr88d::rda::DataBlockType dataBlockType_;
|
||||||
|
|
||||||
|
|
@ -76,10 +90,11 @@ public:
|
||||||
std::shared_ptr<wsr88d::rda::ElevationScan> elevationScan_;
|
std::shared_ptr<wsr88d::rda::ElevationScan> elevationScan_;
|
||||||
std::shared_ptr<wsr88d::rda::MomentDataBlock> momentDataBlock0_;
|
std::shared_ptr<wsr88d::rda::MomentDataBlock> momentDataBlock0_;
|
||||||
|
|
||||||
std::vector<float> vertices_;
|
std::vector<float> coordinates_ {};
|
||||||
std::vector<uint8_t> dataMoments8_;
|
std::vector<float> vertices_ {};
|
||||||
std::vector<uint16_t> dataMoments16_;
|
std::vector<uint8_t> dataMoments8_ {};
|
||||||
std::vector<uint8_t> cfpMoments_;
|
std::vector<uint16_t> dataMoments16_ {};
|
||||||
|
std::vector<uint8_t> cfpMoments_ {};
|
||||||
|
|
||||||
float latitude_;
|
float latitude_;
|
||||||
float longitude_;
|
float longitude_;
|
||||||
|
|
@ -104,7 +119,7 @@ Level2ProductView::Level2ProductView(
|
||||||
common::Level2Product product,
|
common::Level2Product product,
|
||||||
std::shared_ptr<manager::RadarProductManager> radarProductManager) :
|
std::shared_ptr<manager::RadarProductManager> radarProductManager) :
|
||||||
RadarProductView(radarProductManager),
|
RadarProductView(radarProductManager),
|
||||||
p(std::make_unique<Level2ProductViewImpl>(product))
|
p(std::make_unique<Level2ProductViewImpl>(this, product))
|
||||||
{
|
{
|
||||||
ConnectRadarProductManager();
|
ConnectRadarProductManager();
|
||||||
}
|
}
|
||||||
|
|
@ -413,16 +428,14 @@ void Level2ProductView::ComputeSweep()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t radials = radarData->size();
|
const size_t radials = radarData->size();
|
||||||
const common::RadialSize radialSize =
|
|
||||||
(radials == common::MAX_0_5_DEGREE_RADIALS) ?
|
|
||||||
common::RadialSize::_0_5Degree :
|
|
||||||
common::RadialSize::_1Degree;
|
|
||||||
const std::vector<float>& coordinates =
|
|
||||||
radarProductManager->coordinates(radialSize);
|
|
||||||
|
|
||||||
auto radarData0 = (*radarData)[0];
|
p->ComputeCoordinates(radarData);
|
||||||
auto momentData0 = radarData0->moment_data_block(p->dataBlockType_);
|
|
||||||
|
const std::vector<float>& coordinates = p->coordinates_;
|
||||||
|
|
||||||
|
auto& radarData0 = (*radarData)[0];
|
||||||
|
auto momentData0 = radarData0->moment_data_block(p->dataBlockType_);
|
||||||
p->elevationScan_ = radarData;
|
p->elevationScan_ = radarData;
|
||||||
p->momentDataBlock0_ = momentData0;
|
p->momentDataBlock0_ = momentData0;
|
||||||
|
|
||||||
|
|
@ -442,8 +455,8 @@ void Level2ProductView::ComputeSweep()
|
||||||
p->range_ =
|
p->range_ =
|
||||||
momentData0->data_moment_range() +
|
momentData0->data_moment_range() +
|
||||||
momentData0->data_moment_range_sample_interval() * (gates - 0.5f);
|
momentData0->data_moment_range_sample_interval() * (gates - 0.5f);
|
||||||
p->sweepTime_ = util::TimePoint(radarData0->modified_julian_date(),
|
p->sweepTime_ = scwx::util::TimePoint(radarData0->modified_julian_date(),
|
||||||
radarData0->collection_time());
|
radarData0->collection_time());
|
||||||
p->vcp_ = volumeData0->volume_coverage_pattern_number();
|
p->vcp_ = volumeData0->volume_coverage_pattern_number();
|
||||||
|
|
||||||
// Calculate vertices
|
// Calculate vertices
|
||||||
|
|
@ -492,16 +505,10 @@ void Level2ProductView::ComputeSweep()
|
||||||
const uint16_t snrThreshold =
|
const uint16_t snrThreshold =
|
||||||
std::max<int16_t>(2, momentData0->snr_threshold_raw());
|
std::max<int16_t>(2, momentData0->snr_threshold_raw());
|
||||||
|
|
||||||
// Azimuth resolution spacing:
|
// Start radial is always 0, as coordinates are calculated for each sweep
|
||||||
// 1 = 0.5 degrees
|
constexpr std::uint16_t startRadial = 0u;
|
||||||
// 2 = 1.0 degrees
|
|
||||||
const float radialMultiplier =
|
|
||||||
2.0f / std::clamp<int8_t>(radarData0->azimuth_resolution_spacing(), 1, 2);
|
|
||||||
|
|
||||||
const float startAngle = radarData0->azimuth_angle();
|
for (auto& radialPair : *radarData)
|
||||||
const uint16_t startRadial = std::lroundf(startAngle * radialMultiplier);
|
|
||||||
|
|
||||||
for (auto radialPair : *radarData)
|
|
||||||
{
|
{
|
||||||
uint16_t radial = radialPair.first;
|
uint16_t radial = radialPair.first;
|
||||||
auto radialData = radialPair.second;
|
auto radialData = radialPair.second;
|
||||||
|
|
@ -685,6 +692,84 @@ void Level2ProductView::ComputeSweep()
|
||||||
emit SweepComputed();
|
emit SweepComputed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Level2ProductViewImpl::ComputeCoordinates(
|
||||||
|
std::shared_ptr<wsr88d::rda::ElevationScan> radarData)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
|
auto& radarData0 = (*radarData)[0];
|
||||||
|
auto momentData0 = radarData0->moment_data_block(dataBlockType_);
|
||||||
|
|
||||||
|
const std::uint16_t numRadials =
|
||||||
|
static_cast<std::uint16_t>(radarData->size());
|
||||||
|
const std::uint16_t numRangeBins =
|
||||||
|
momentData0->number_of_data_moment_gates();
|
||||||
|
|
||||||
|
auto radials = boost::irange<std::uint32_t>(0u, numRadials);
|
||||||
|
auto gates = boost::irange<std::uint32_t>(0u, numRangeBins);
|
||||||
|
|
||||||
|
std::for_each(
|
||||||
|
std::execution::par_unseq,
|
||||||
|
radials.begin(),
|
||||||
|
radials.end(),
|
||||||
|
[&](std::uint32_t radial)
|
||||||
|
{
|
||||||
|
// Angles are ordered clockwise, delta should be positive
|
||||||
|
float deltaAngle =
|
||||||
|
(radial == 0) ? (*radarData)[0]->azimuth_angle() -
|
||||||
|
(*radarData)[numRadials - 1]->azimuth_angle() :
|
||||||
|
(*radarData)[radial]->azimuth_angle() -
|
||||||
|
(*radarData)[radial - 1]->azimuth_angle();
|
||||||
|
while (deltaAngle < 0.0f)
|
||||||
|
{
|
||||||
|
deltaAngle += 360.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float angle =
|
||||||
|
(*radarData)[radial]->azimuth_angle() - (deltaAngle * 0.5f);
|
||||||
|
|
||||||
|
std::for_each(std::execution::par_unseq,
|
||||||
|
gates.begin(),
|
||||||
|
gates.end(),
|
||||||
|
[&](std::uint32_t gate)
|
||||||
|
{
|
||||||
|
const std::uint32_t radialGate =
|
||||||
|
radial * common::MAX_DATA_MOMENT_GATES + gate;
|
||||||
|
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<Level2ProductView> Level2ProductView::Create(
|
std::shared_ptr<Level2ProductView> Level2ProductView::Create(
|
||||||
common::Level2Product product,
|
common::Level2Product product,
|
||||||
std::shared_ptr<manager::RadarProductManager> radarProductManager)
|
std::shared_ptr<manager::RadarProductManager> radarProductManager)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue