Add alert layer lines

This commit is contained in:
Dan Paulat 2024-07-08 22:55:54 -05:00
parent 037e0922b0
commit b2d648e960

View file

@ -1,5 +1,8 @@
#include <scwx/qt/map/alert_layer.hpp> #include <scwx/qt/map/alert_layer.hpp>
#include <scwx/qt/gl/draw/geo_lines.hpp>
#include <scwx/qt/manager/text_event_manager.hpp> #include <scwx/qt/manager/text_event_manager.hpp>
#include <scwx/qt/settings/palette_settings.hpp>
#include <scwx/qt/util/color.hpp>
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
#include <chrono> #include <chrono>
@ -20,6 +23,8 @@ namespace map
static const std::string logPrefix_ = "scwx::qt::map::alert_layer"; static const std::string logPrefix_ = "scwx::qt::map::alert_layer";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
static const boost::gil::rgba32f_pixel_t kBlack_ {0.0f, 0.0f, 0.0f, 1.0f};
template<class Key> template<class Key>
struct AlertTypeHash; struct AlertTypeHash;
@ -29,7 +34,7 @@ struct AlertTypeHash<std::pair<awips::Phenomenon, bool>>
size_t operator()(const std::pair<awips::Phenomenon, bool>& x) const; size_t operator()(const std::pair<awips::Phenomenon, bool>& x) const;
}; };
class AlertLayerHandler : QObject class AlertLayerHandler : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -92,26 +97,83 @@ public:
std::mutex alertMutex_ {}; std::mutex alertMutex_ {};
signals: signals:
void AlertAdded(const std::shared_ptr<SegmentRecord>& segmentRecord,
awips::Phenomenon phenomenon);
void AlertUpdated(const std::shared_ptr<SegmentRecord>& segmentRecord);
void AlertsUpdated(awips::Phenomenon phenomenon, bool alertActive); void AlertsUpdated(awips::Phenomenon phenomenon, bool alertActive);
}; };
class AlertLayer::Impl class AlertLayer::Impl
{ {
public: public:
explicit Impl([[maybe_unused]] std::shared_ptr<MapContext> context, explicit Impl(std::shared_ptr<MapContext> context,
awips::Phenomenon phenomenon) : awips::Phenomenon phenomenon) :
phenomenon_ {phenomenon} phenomenon_ {phenomenon},
borders_ {{false, std::make_shared<gl::draw::GeoLines>(context)},
{true, std::make_shared<gl::draw::GeoLines>(context)}},
lines_ {{false, std::make_shared<gl::draw::GeoLines>(context)},
{true, std::make_shared<gl::draw::GeoLines>(context)}}
{ {
} auto& paletteSettings = settings::PaletteSettings::Instance();
~Impl() {};
awips::Phenomenon phenomenon_; for (auto alertActive : {false, true})
{
lineColor_.emplace(
alertActive,
util::color::ToRgba8PixelT(
paletteSettings.alert_color(phenomenon_, alertActive)
.GetValue()));
}
ConnectSignals();
}
~Impl() { receiver_ = nullptr; };
void AddAlert(
const std::shared_ptr<AlertLayerHandler::SegmentRecord>& segmentRecord);
void UpdateAlert(
const std::shared_ptr<AlertLayerHandler::SegmentRecord>& segmentRecord);
void ConnectSignals();
static void AddLine(std::shared_ptr<gl::draw::GeoLines>& lines,
std::shared_ptr<gl::draw::GeoLineDrawItem>& di,
const common::Coordinate& p1,
const common::Coordinate& p2,
boost::gil::rgba32f_pixel_t color,
float width,
std::chrono::system_clock::time_point startTime,
std::chrono::system_clock::time_point endTime);
static void
AddLines(std::shared_ptr<gl::draw::GeoLines>& lines,
const std::vector<common::Coordinate>& coordinates,
boost::gil::rgba32_pixel_t color,
float width,
std::chrono::system_clock::time_point startTime,
std::chrono::system_clock::time_point endTime,
std::vector<std::shared_ptr<gl::draw::GeoLineDrawItem>>& drawItems);
const awips::Phenomenon phenomenon_;
std::unique_ptr<QObject> receiver_ {std::make_unique<QObject>()};
std::unordered_map<bool, std::shared_ptr<gl::draw::GeoLines>> borders_;
std::unordered_map<bool, std::shared_ptr<gl::draw::GeoLines>> lines_;
std::unordered_map<bool, boost::gil::rgba8_pixel_t> lineColor_;
}; };
AlertLayer::AlertLayer(std::shared_ptr<MapContext> context, AlertLayer::AlertLayer(std::shared_ptr<MapContext> context,
awips::Phenomenon phenomenon) : awips::Phenomenon phenomenon) :
DrawLayer(context), p(std::make_unique<Impl>(context, phenomenon)) DrawLayer(context), p(std::make_unique<Impl>(context, phenomenon))
{ {
for (auto alertActive : {false, true})
{
auto& borders = p->borders_.at(alertActive);
auto& lines = p->lines_.at(alertActive);
AddDrawItem(borders);
AddDrawItem(lines);
}
} }
AlertLayer::~AlertLayer() = default; AlertLayer::~AlertLayer() = default;
@ -121,6 +183,18 @@ void AlertLayer::Initialize()
logger_->debug("Initialize: {}", awips::GetPhenomenonText(p->phenomenon_)); logger_->debug("Initialize: {}", awips::GetPhenomenonText(p->phenomenon_));
DrawLayer::Initialize(); DrawLayer::Initialize();
for (auto alertActive : {false, true})
{
auto& borders = p->borders_.at(alertActive);
auto& lines = p->lines_.at(alertActive);
borders->StartLines();
borders->FinishLines();
lines->StartLines();
lines->FinishLines();
}
} }
void AlertLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) void AlertLayer::Render(const QMapLibre::CustomLayerRenderParameters& params)
@ -183,6 +257,8 @@ void AlertLayerHandler::HandleAlert(const types::TextEventKey& key,
if (segmentRecord->segmentEnd_ > segmentBegin) if (segmentRecord->segmentEnd_ > segmentBegin)
{ {
segmentRecord->segmentEnd_ = segmentBegin; segmentRecord->segmentEnd_ = segmentBegin;
Q_EMIT AlertUpdated(segmentRecord);
} }
} }
@ -210,6 +286,8 @@ void AlertLayerHandler::HandleAlert(const types::TextEventKey& key,
segmentsForKey.push_back(segmentRecord); segmentsForKey.push_back(segmentRecord);
segmentsForType.push_back(segmentRecord); segmentsForType.push_back(segmentRecord);
Q_EMIT AlertAdded(segmentRecord, phenomenon);
alertsUpdated.emplace(phenomenon, alertActive); alertsUpdated.emplace(phenomenon, alertActive);
} }
@ -223,6 +301,107 @@ void AlertLayerHandler::HandleAlert(const types::TextEventKey& key,
} }
} }
void AlertLayer::Impl::ConnectSignals()
{
QObject::connect(
&AlertLayerHandler::Instance(),
&AlertLayerHandler::AlertAdded,
receiver_.get(),
[this](
const std::shared_ptr<AlertLayerHandler::SegmentRecord>& segmentRecord,
awips::Phenomenon phenomenon)
{
if (phenomenon == phenomenon_)
{
AddAlert(segmentRecord);
}
});
}
void AlertLayer::Impl::AddAlert(
const std::shared_ptr<AlertLayerHandler::SegmentRecord>& segmentRecord)
{
auto& segment = segmentRecord->segment_;
auto& vtec = segment->header_->vtecString_.front();
auto action = vtec.pVtec_.action();
bool alertActive = (action != awips::PVtec::Action::Canceled);
auto& startTime = segmentRecord->segmentBegin_;
auto& endTime = segmentRecord->segmentEnd_;
auto& lineColor = lineColor_.at(alertActive);
auto& lines = lines_.at(alertActive);
const auto& coordinates = segment->codedLocation_->coordinates();
std::vector<std::shared_ptr<gl::draw::GeoLineDrawItem>> drawItems {};
AddLines(lines, coordinates, kBlack_, 5.0f, startTime, endTime, drawItems);
AddLines(lines, coordinates, lineColor, 3.0f, startTime, endTime, drawItems);
lines->FinishLines();
}
void AlertLayer::Impl::UpdateAlert(
[[maybe_unused]] const std::shared_ptr<AlertLayerHandler::SegmentRecord>&
segmentRecord)
{
// TODO
}
void AlertLayer::Impl::AddLines(
std::shared_ptr<gl::draw::GeoLines>& lines,
const std::vector<common::Coordinate>& coordinates,
boost::gil::rgba32_pixel_t color,
float width,
std::chrono::system_clock::time_point startTime,
std::chrono::system_clock::time_point endTime,
std::vector<std::shared_ptr<gl::draw::GeoLineDrawItem>>& drawItems)
{
for (std::size_t i = 0, j = 1; i < coordinates.size(); ++i, ++j)
{
if (j >= coordinates.size())
{
j = 0;
// Ignore repeated coordinates at the end
if (coordinates[i] == coordinates[j])
{
break;
}
}
auto di = lines->AddLine();
AddLine(lines,
di,
coordinates[i],
coordinates[j],
color,
width,
startTime,
endTime);
drawItems.push_back(di);
}
}
void AlertLayer::Impl::AddLine(std::shared_ptr<gl::draw::GeoLines>& lines,
std::shared_ptr<gl::draw::GeoLineDrawItem>& di,
const common::Coordinate& p1,
const common::Coordinate& p2,
boost::gil::rgba32f_pixel_t color,
float width,
std::chrono::system_clock::time_point startTime,
std::chrono::system_clock::time_point endTime)
{
lines->SetLineLocation(
di, p1.latitude_, p1.longitude_, p2.latitude_, p2.longitude_);
lines->SetLineModulate(di, color);
lines->SetLineWidth(di, width);
lines->SetLineStartTime(di, startTime);
lines->SetLineEndTime(di, endTime);
}
AlertLayerHandler& AlertLayerHandler::Instance() AlertLayerHandler& AlertLayerHandler::Instance()
{ {
static AlertLayerHandler alertLayerHandler_ {}; static AlertLayerHandler alertLayerHandler_ {};