mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-11-01 17:00:05 +00:00
Generate hover text for storm tracking information
This commit is contained in:
parent
b4b1706587
commit
29e87fc11e
3 changed files with 158 additions and 63 deletions
|
|
@ -22,7 +22,8 @@ struct LinkedVectorDrawItem
|
||||||
{
|
{
|
||||||
LinkedVectorDrawItem(
|
LinkedVectorDrawItem(
|
||||||
const common::Coordinate& center,
|
const common::Coordinate& center,
|
||||||
const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket)
|
const std::shared_ptr<const wsr88d::rpg::LinkedVectorPacket>&
|
||||||
|
vectorPacket)
|
||||||
{
|
{
|
||||||
coordinates_.push_back(util::GeographicLib::GetCoordinate(
|
coordinates_.push_back(util::GeographicLib::GetCoordinate(
|
||||||
center, vectorPacket->start_i_km(), vectorPacket->start_j_km()));
|
center, vectorPacket->start_i_km(), vectorPacket->start_j_km()));
|
||||||
|
|
@ -137,7 +138,7 @@ void LinkedVectors::StartVectors()
|
||||||
|
|
||||||
std::shared_ptr<LinkedVectorDrawItem> LinkedVectors::AddVector(
|
std::shared_ptr<LinkedVectorDrawItem> LinkedVectors::AddVector(
|
||||||
const common::Coordinate& center,
|
const common::Coordinate& center,
|
||||||
const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket)
|
const std::shared_ptr<const wsr88d::rpg::LinkedVectorPacket>& vectorPacket)
|
||||||
{
|
{
|
||||||
return p->vectorList_.emplace_back(
|
return p->vectorList_.emplace_back(
|
||||||
std::make_shared<LinkedVectorDrawItem>(center, vectorPacket));
|
std::make_shared<LinkedVectorDrawItem>(center, vectorPacket));
|
||||||
|
|
|
||||||
|
|
@ -82,9 +82,10 @@ public:
|
||||||
*
|
*
|
||||||
* @return Linked vector draw item
|
* @return Linked vector draw item
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<LinkedVectorDrawItem> AddVector(
|
std::shared_ptr<LinkedVectorDrawItem>
|
||||||
const common::Coordinate& center,
|
AddVector(const common::Coordinate& center,
|
||||||
const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket);
|
const std::shared_ptr<const wsr88d::rpg::LinkedVectorPacket>&
|
||||||
|
vectorPacket);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the modulate color of a linked vector.
|
* Sets the modulate color of a linked vector.
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,13 @@
|
||||||
#include <scwx/qt/gl/draw/linked_vectors.hpp>
|
#include <scwx/qt/gl/draw/linked_vectors.hpp>
|
||||||
#include <scwx/qt/manager/radar_product_manager.hpp>
|
#include <scwx/qt/manager/radar_product_manager.hpp>
|
||||||
#include <scwx/qt/view/overlay_product_view.hpp>
|
#include <scwx/qt/view/overlay_product_view.hpp>
|
||||||
#include <scwx/wsr88d/rpg/graphic_product_message.hpp>
|
|
||||||
#include <scwx/wsr88d/rpg/linked_vector_packet.hpp>
|
#include <scwx/wsr88d/rpg/linked_vector_packet.hpp>
|
||||||
#include <scwx/wsr88d/rpg/rpg_types.hpp>
|
#include <scwx/wsr88d/rpg/rpg_types.hpp>
|
||||||
#include <scwx/wsr88d/rpg/scit_data_packet.hpp>
|
#include <scwx/wsr88d/rpg/scit_data_packet.hpp>
|
||||||
#include <scwx/wsr88d/rpg/storm_id_symbol_packet.hpp>
|
#include <scwx/wsr88d/rpg/storm_id_symbol_packet.hpp>
|
||||||
|
#include <scwx/wsr88d/rpg/storm_tracking_information_message.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
|
#include <scwx/util/time.hpp>
|
||||||
|
|
||||||
namespace scwx
|
namespace scwx
|
||||||
{
|
{
|
||||||
|
|
@ -33,19 +34,32 @@ public:
|
||||||
void UpdateStormTrackingInformation();
|
void UpdateStormTrackingInformation();
|
||||||
|
|
||||||
static void HandleLinkedVectorPacket(
|
static void HandleLinkedVectorPacket(
|
||||||
const std::shared_ptr<wsr88d::rpg::Packet>& packet,
|
const std::shared_ptr<const wsr88d::rpg::Packet>& packet,
|
||||||
const common::Coordinate& center,
|
const common::Coordinate& center,
|
||||||
const std::string& hoverText,
|
const std::string& hoverText,
|
||||||
boost::gil::rgba32f_pixel_t color,
|
boost::gil::rgba32f_pixel_t color,
|
||||||
bool tickRadiusIncrement,
|
units::length::nautical_miles<float> tickRadius,
|
||||||
|
units::length::nautical_miles<float> tickRadiusIncrement,
|
||||||
std::shared_ptr<gl::draw::LinkedVectors>& linkedVectors);
|
std::shared_ptr<gl::draw::LinkedVectors>& linkedVectors);
|
||||||
static void HandleScitDataPacket(
|
static void HandleScitDataPacket(
|
||||||
const std::shared_ptr<wsr88d::rpg::Packet>& packet,
|
const std::shared_ptr<const wsr88d::rpg::StormTrackingInformationMessage>&
|
||||||
|
sti,
|
||||||
|
const std::shared_ptr<const wsr88d::rpg::Packet>& packet,
|
||||||
const common::Coordinate& center,
|
const common::Coordinate& center,
|
||||||
const std::string& stormId,
|
const std::string& stormId,
|
||||||
|
const std::string& hoverText,
|
||||||
std::shared_ptr<gl::draw::LinkedVectors>& linkedVectors);
|
std::shared_ptr<gl::draw::LinkedVectors>& linkedVectors);
|
||||||
static void
|
|
||||||
HandleStormIdPacket(const std::shared_ptr<wsr88d::rpg::Packet>& packet,
|
static void HandleStormIdPacket(
|
||||||
|
const std::shared_ptr<const wsr88d::rpg::StormTrackingInformationMessage>&
|
||||||
|
sti,
|
||||||
|
const std::shared_ptr<const wsr88d::rpg::Packet>& packet,
|
||||||
|
std::string& stormId,
|
||||||
|
std::string& hoverText);
|
||||||
|
|
||||||
|
static std::string BuildHoverText(
|
||||||
|
const std::shared_ptr<
|
||||||
|
const scwx::wsr88d::rpg::StormTrackingInformationMessage>& sti,
|
||||||
std::string& stormId);
|
std::string& stormId);
|
||||||
|
|
||||||
OverlayProductLayer* self_;
|
OverlayProductLayer* self_;
|
||||||
|
|
@ -123,7 +137,7 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation()
|
||||||
float longitude = 0.0f;
|
float longitude = 0.0f;
|
||||||
|
|
||||||
std::shared_ptr<wsr88d::Level3File> l3File = nullptr;
|
std::shared_ptr<wsr88d::Level3File> l3File = nullptr;
|
||||||
std::shared_ptr<wsr88d::rpg::GraphicProductMessage> gpm = nullptr;
|
std::shared_ptr<wsr88d::rpg::StormTrackingInformationMessage> sti = nullptr;
|
||||||
std::shared_ptr<wsr88d::rpg::ProductSymbologyBlock> psb = nullptr;
|
std::shared_ptr<wsr88d::rpg::ProductSymbologyBlock> psb = nullptr;
|
||||||
if (record != nullptr)
|
if (record != nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -131,12 +145,12 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation()
|
||||||
}
|
}
|
||||||
if (l3File != nullptr)
|
if (l3File != nullptr)
|
||||||
{
|
{
|
||||||
gpm = std::dynamic_pointer_cast<wsr88d::rpg::GraphicProductMessage>(
|
sti = std::dynamic_pointer_cast<
|
||||||
l3File->message());
|
wsr88d::rpg::StormTrackingInformationMessage>(l3File->message());
|
||||||
}
|
}
|
||||||
if (gpm != nullptr)
|
if (sti != nullptr)
|
||||||
{
|
{
|
||||||
psb = gpm->symbology_block();
|
psb = sti->symbology_block();
|
||||||
}
|
}
|
||||||
|
|
||||||
linkedVectors_->StartVectors();
|
linkedVectors_->StartVectors();
|
||||||
|
|
@ -155,6 +169,7 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string stormId = "?";
|
std::string stormId = "?";
|
||||||
|
std::string hoverText {};
|
||||||
|
|
||||||
for (std::size_t i = 0; i < psb->number_of_layers(); ++i)
|
for (std::size_t i = 0; i < psb->number_of_layers(); ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -164,15 +179,19 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation()
|
||||||
switch (packet->packet_code())
|
switch (packet->packet_code())
|
||||||
{
|
{
|
||||||
case static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::StormId):
|
case static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::StormId):
|
||||||
HandleStormIdPacket(packet, stormId);
|
HandleStormIdPacket(sti, packet, stormId, hoverText);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case static_cast<std::uint16_t>(
|
case static_cast<std::uint16_t>(
|
||||||
wsr88d::rpg::PacketCode::ScitPastData):
|
wsr88d::rpg::PacketCode::ScitPastData):
|
||||||
case static_cast<std::uint16_t>(
|
case static_cast<std::uint16_t>(
|
||||||
wsr88d::rpg::PacketCode::ScitForecastData):
|
wsr88d::rpg::PacketCode::ScitForecastData):
|
||||||
HandleScitDataPacket(
|
HandleScitDataPacket(sti,
|
||||||
packet, {latitude, longitude}, stormId, linkedVectors_);
|
packet,
|
||||||
|
{latitude, longitude},
|
||||||
|
stormId,
|
||||||
|
hoverText,
|
||||||
|
linkedVectors_);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -192,41 +211,63 @@ void OverlayProductLayer::Impl::UpdateStormTrackingInformation()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayProductLayer::Impl::HandleStormIdPacket(
|
void OverlayProductLayer::Impl::HandleStormIdPacket(
|
||||||
const std::shared_ptr<wsr88d::rpg::Packet>& packet, std::string& stormId)
|
const std::shared_ptr<const wsr88d::rpg::StormTrackingInformationMessage>&
|
||||||
|
sti,
|
||||||
|
const std::shared_ptr<const wsr88d::rpg::Packet>& packet,
|
||||||
|
std::string& stormId,
|
||||||
|
std::string& hoverText)
|
||||||
{
|
{
|
||||||
auto stormIdPacket =
|
auto stormIdPacket =
|
||||||
std::dynamic_pointer_cast<wsr88d::rpg::StormIdSymbolPacket>(packet);
|
std::dynamic_pointer_cast<const wsr88d::rpg::StormIdSymbolPacket>(packet);
|
||||||
|
|
||||||
if (stormIdPacket != nullptr && stormIdPacket->RecordCount() > 0)
|
if (stormIdPacket != nullptr && stormIdPacket->RecordCount() > 0)
|
||||||
{
|
{
|
||||||
stormId = stormIdPacket->storm_id(0);
|
stormId = stormIdPacket->storm_id(0);
|
||||||
|
hoverText = BuildHoverText(sti, stormId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger_->warn("Invalid Storm ID Packet");
|
logger_->warn("Invalid Storm ID Packet");
|
||||||
|
|
||||||
stormId = "?";
|
stormId = "?";
|
||||||
|
hoverText.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayProductLayer::Impl::HandleScitDataPacket(
|
void OverlayProductLayer::Impl::HandleScitDataPacket(
|
||||||
const std::shared_ptr<wsr88d::rpg::Packet>& packet,
|
const std::shared_ptr<const wsr88d::rpg::StormTrackingInformationMessage>&
|
||||||
|
sti,
|
||||||
|
const std::shared_ptr<const wsr88d::rpg::Packet>& packet,
|
||||||
const common::Coordinate& center,
|
const common::Coordinate& center,
|
||||||
const std::string& stormId,
|
const std::string& stormId,
|
||||||
|
const std::string& hoverText,
|
||||||
std::shared_ptr<gl::draw::LinkedVectors>& linkedVectors)
|
std::shared_ptr<gl::draw::LinkedVectors>& linkedVectors)
|
||||||
{
|
{
|
||||||
auto scitDataPacket =
|
auto scitDataPacket =
|
||||||
std::dynamic_pointer_cast<wsr88d::rpg::ScitDataPacket>(packet);
|
std::dynamic_pointer_cast<const wsr88d::rpg::ScitDataPacket>(packet);
|
||||||
|
|
||||||
if (scitDataPacket != nullptr)
|
if (scitDataPacket != nullptr)
|
||||||
{
|
{
|
||||||
boost::gil::rgba32f_pixel_t color {1.0f, 1.0f, 1.0f, 1.0f};
|
boost::gil::rgba32f_pixel_t color {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
bool tickRadiusIncrement = true;
|
|
||||||
|
units::length::nautical_miles<float> tickRadius {0.5f};
|
||||||
|
units::length::nautical_miles<float> tickRadiusIncrement {0.0f};
|
||||||
|
|
||||||
|
auto stiRecord = sti->sti_record(stormId);
|
||||||
|
|
||||||
if (scitDataPacket->packet_code() ==
|
if (scitDataPacket->packet_code() ==
|
||||||
static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::ScitPastData))
|
static_cast<std::uint16_t>(wsr88d::rpg::PacketCode::ScitPastData))
|
||||||
{
|
{
|
||||||
|
// If this is past data, the default tick radius and increment with a
|
||||||
|
// darker color
|
||||||
color = {0.5f, 0.5f, 0.5f, 1.0f};
|
color = {0.5f, 0.5f, 0.5f, 1.0f};
|
||||||
tickRadiusIncrement = false;
|
}
|
||||||
|
else if (stiRecord != nullptr && stiRecord->meanError_.has_value())
|
||||||
|
{
|
||||||
|
// If this is forecast data, use the mean error as the radius (minimum
|
||||||
|
// of the default value), incrementing by the mean error
|
||||||
|
tickRadiusIncrement = stiRecord->meanError_.value();
|
||||||
|
tickRadius = std::max(tickRadius, tickRadiusIncrement);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& subpacket : scitDataPacket->packet_list())
|
for (auto& subpacket : scitDataPacket->packet_list())
|
||||||
|
|
@ -237,8 +278,9 @@ void OverlayProductLayer::Impl::HandleScitDataPacket(
|
||||||
wsr88d::rpg::PacketCode::LinkedVectorNoValue):
|
wsr88d::rpg::PacketCode::LinkedVectorNoValue):
|
||||||
HandleLinkedVectorPacket(subpacket,
|
HandleLinkedVectorPacket(subpacket,
|
||||||
center,
|
center,
|
||||||
stormId,
|
hoverText,
|
||||||
color,
|
color,
|
||||||
|
tickRadius,
|
||||||
tickRadiusIncrement,
|
tickRadiusIncrement,
|
||||||
linkedVectors);
|
linkedVectors);
|
||||||
break;
|
break;
|
||||||
|
|
@ -257,15 +299,16 @@ void OverlayProductLayer::Impl::HandleScitDataPacket(
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayProductLayer::Impl::HandleLinkedVectorPacket(
|
void OverlayProductLayer::Impl::HandleLinkedVectorPacket(
|
||||||
const std::shared_ptr<wsr88d::rpg::Packet>& packet,
|
const std::shared_ptr<const wsr88d::rpg::Packet>& packet,
|
||||||
const common::Coordinate& center,
|
const common::Coordinate& center,
|
||||||
const std::string& hoverText,
|
const std::string& hoverText,
|
||||||
boost::gil::rgba32f_pixel_t color,
|
boost::gil::rgba32f_pixel_t color,
|
||||||
bool tickRadiusIncrement,
|
units::length::nautical_miles<float> tickRadius,
|
||||||
|
units::length::nautical_miles<float> tickRadiusIncrement,
|
||||||
std::shared_ptr<gl::draw::LinkedVectors>& linkedVectors)
|
std::shared_ptr<gl::draw::LinkedVectors>& linkedVectors)
|
||||||
{
|
{
|
||||||
auto linkedVectorPacket =
|
auto linkedVectorPacket =
|
||||||
std::dynamic_pointer_cast<wsr88d::rpg::LinkedVectorPacket>(packet);
|
std::dynamic_pointer_cast<const wsr88d::rpg::LinkedVectorPacket>(packet);
|
||||||
|
|
||||||
if (linkedVectorPacket != nullptr)
|
if (linkedVectorPacket != nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -274,19 +317,9 @@ void OverlayProductLayer::Impl::HandleLinkedVectorPacket(
|
||||||
gl::draw::LinkedVectors::SetVectorModulate(di, color);
|
gl::draw::LinkedVectors::SetVectorModulate(di, color);
|
||||||
gl::draw::LinkedVectors::SetVectorHoverText(di, hoverText);
|
gl::draw::LinkedVectors::SetVectorHoverText(di, hoverText);
|
||||||
gl::draw::LinkedVectors::SetVectorTicksEnabled(di, true);
|
gl::draw::LinkedVectors::SetVectorTicksEnabled(di, true);
|
||||||
gl::draw::LinkedVectors::SetVectorTickRadius(
|
gl::draw::LinkedVectors::SetVectorTickRadius(di, tickRadius);
|
||||||
di, units::length::nautical_miles<double> {1.0});
|
|
||||||
|
|
||||||
if (tickRadiusIncrement)
|
|
||||||
{
|
|
||||||
gl::draw::LinkedVectors::SetVectorTickRadiusIncrement(
|
gl::draw::LinkedVectors::SetVectorTickRadiusIncrement(
|
||||||
di, units::length::nautical_miles<double> {1.0});
|
di, tickRadiusIncrement);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gl::draw::LinkedVectors::SetVectorTickRadiusIncrement(
|
|
||||||
di, units::length::nautical_miles<double> {0.0});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -294,6 +327,66 @@ void OverlayProductLayer::Impl::HandleLinkedVectorPacket(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string OverlayProductLayer::Impl::BuildHoverText(
|
||||||
|
const std::shared_ptr<
|
||||||
|
const scwx::wsr88d::rpg::StormTrackingInformationMessage>& sti,
|
||||||
|
std::string& stormId)
|
||||||
|
{
|
||||||
|
std::string hoverText = fmt::format("Storm ID: {}", stormId);
|
||||||
|
|
||||||
|
auto stiRecord = sti->sti_record(stormId);
|
||||||
|
|
||||||
|
if (stiRecord != nullptr)
|
||||||
|
{
|
||||||
|
if (stiRecord->direction_.has_value() && stiRecord->speed_.has_value())
|
||||||
|
{
|
||||||
|
hoverText +=
|
||||||
|
fmt::format("\nMovement: {} @ {}",
|
||||||
|
units::to_string(stiRecord->direction_.value()),
|
||||||
|
units::to_string(stiRecord->speed_.value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stiRecord->maxDbz_.has_value() &&
|
||||||
|
stiRecord->maxDbzHeight_.has_value())
|
||||||
|
{
|
||||||
|
hoverText +=
|
||||||
|
fmt::format("\nMax dBZ: {} ({} kft)",
|
||||||
|
stiRecord->maxDbz_.value(),
|
||||||
|
stiRecord->maxDbzHeight_.value().value() / 1000.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stiRecord->forecastError_.has_value())
|
||||||
|
{
|
||||||
|
hoverText +=
|
||||||
|
fmt::format("\nForecast Error: {}",
|
||||||
|
units::to_string(stiRecord->forecastError_.value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stiRecord->meanError_.has_value())
|
||||||
|
{
|
||||||
|
hoverText +=
|
||||||
|
fmt::format("\nMean Error: {}",
|
||||||
|
units::to_string(stiRecord->meanError_.value()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dateTime = sti->date_time();
|
||||||
|
if (dateTime.has_value())
|
||||||
|
{
|
||||||
|
hoverText +=
|
||||||
|
fmt::format("\nDate/Time: {}", util::TimeString(dateTime.value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto forecastInterval = sti->forecast_interval();
|
||||||
|
if (forecastInterval.has_value())
|
||||||
|
{
|
||||||
|
hoverText += fmt::format("\nForecast Interval: {} min",
|
||||||
|
forecastInterval.value().count());
|
||||||
|
}
|
||||||
|
|
||||||
|
return hoverText;
|
||||||
|
}
|
||||||
|
|
||||||
bool OverlayProductLayer::RunMousePicking(
|
bool OverlayProductLayer::RunMousePicking(
|
||||||
const QMapLibreGL::CustomLayerRenderParameters& params,
|
const QMapLibreGL::CustomLayerRenderParameters& params,
|
||||||
const QPointF& mouseLocalPos,
|
const QPointF& mouseLocalPos,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue