mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 06:30:05 +00:00 
			
		
		
		
	Add alert layer lines
This commit is contained in:
		
							parent
							
								
									037e0922b0
								
							
						
					
					
						commit
						b2d648e960
					
				
					 1 changed files with 186 additions and 7 deletions
				
			
		|  | @ -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_ {}; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat