mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 17:40:05 +00:00 
			
		
		
		
	Removing old alert layer
This commit is contained in:
		
							parent
							
								
									74dbe1f915
								
							
						
					
					
						commit
						e8a0cf5fa9
					
				
					 3 changed files with 0 additions and 534 deletions
				
			
		|  | @ -120,7 +120,6 @@ set(SRC_MANAGER source/scwx/qt/manager/alert_manager.cpp | ||||||
|                 source/scwx/qt/manager/timeline_manager.cpp |                 source/scwx/qt/manager/timeline_manager.cpp | ||||||
|                 source/scwx/qt/manager/update_manager.cpp) |                 source/scwx/qt/manager/update_manager.cpp) | ||||||
| set(HDR_MAP source/scwx/qt/map/alert_layer.hpp | set(HDR_MAP source/scwx/qt/map/alert_layer.hpp | ||||||
|             source/scwx/qt/map/alert_layer_old.hpp |  | ||||||
|             source/scwx/qt/map/color_table_layer.hpp |             source/scwx/qt/map/color_table_layer.hpp | ||||||
|             source/scwx/qt/map/draw_layer.hpp |             source/scwx/qt/map/draw_layer.hpp | ||||||
|             source/scwx/qt/map/generic_layer.hpp |             source/scwx/qt/map/generic_layer.hpp | ||||||
|  | @ -136,7 +135,6 @@ set(HDR_MAP source/scwx/qt/map/alert_layer.hpp | ||||||
|             source/scwx/qt/map/radar_range_layer.hpp |             source/scwx/qt/map/radar_range_layer.hpp | ||||||
|             source/scwx/qt/map/radar_site_layer.hpp) |             source/scwx/qt/map/radar_site_layer.hpp) | ||||||
| set(SRC_MAP source/scwx/qt/map/alert_layer.cpp | set(SRC_MAP source/scwx/qt/map/alert_layer.cpp | ||||||
|             source/scwx/qt/map/alert_layer_old.cpp |  | ||||||
|             source/scwx/qt/map/color_table_layer.cpp |             source/scwx/qt/map/color_table_layer.cpp | ||||||
|             source/scwx/qt/map/draw_layer.cpp |             source/scwx/qt/map/draw_layer.cpp | ||||||
|             source/scwx/qt/map/generic_layer.cpp |             source/scwx/qt/map/generic_layer.cpp | ||||||
|  |  | ||||||
|  | @ -1,498 +0,0 @@ | ||||||
| #include <scwx/qt/map/alert_layer_old.hpp> |  | ||||||
| #include <scwx/qt/manager/text_event_manager.hpp> |  | ||||||
| #include <scwx/qt/settings/palette_settings.hpp> |  | ||||||
| #include <scwx/qt/types/layer_types.hpp> |  | ||||||
| #include <scwx/qt/util/color.hpp> |  | ||||||
| #include <scwx/util/logger.hpp> |  | ||||||
| #include <scwx/util/threads.hpp> |  | ||||||
| 
 |  | ||||||
| #include <chrono> |  | ||||||
| #include <shared_mutex> |  | ||||||
| #include <unordered_set> |  | ||||||
| 
 |  | ||||||
| #include <boost/asio/steady_timer.hpp> |  | ||||||
| #include <boost/container_hash/hash.hpp> |  | ||||||
| 
 |  | ||||||
| namespace scwx |  | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace map |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| static const std::string logPrefix_ = "scwx::qt::map::alert_layer_old"; |  | ||||||
| static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); |  | ||||||
| 
 |  | ||||||
| static std::vector<std::string> |  | ||||||
| AddAlertLayer(std::shared_ptr<QMapLibre::Map> map, |  | ||||||
|               awips::Phenomenon               phenomenon, |  | ||||||
|               bool                            alertActive, |  | ||||||
|               const QString&                  beforeLayer); |  | ||||||
| static QMapLibre::Feature |  | ||||||
| CreateFeature(const awips::CodedLocation& codedLocation); |  | ||||||
| static QMapLibre::Coordinate |  | ||||||
| GetMapboxCoordinate(const common::Coordinate& coordinate); |  | ||||||
| static QMapLibre::Coordinates |  | ||||||
|                GetMapboxCoordinates(const awips::CodedLocation& codedLocation); |  | ||||||
| static QString GetSourceId(awips::Phenomenon phenomenon, bool alertActive); |  | ||||||
| static QString GetSuffix(awips::Phenomenon phenomenon, bool alertActive); |  | ||||||
| 
 |  | ||||||
| static const QVariantMap kEmptyFeatureCollection_ { |  | ||||||
|    {"type", "geojson"}, |  | ||||||
|    {"data", QVariant::fromValue(std::list<QMapLibre::Feature> {})}}; |  | ||||||
| static const std::vector<awips::Phenomenon> kAlertPhenomena_ { |  | ||||||
|    awips::Phenomenon::Marine, |  | ||||||
|    awips::Phenomenon::FlashFlood, |  | ||||||
|    awips::Phenomenon::SevereThunderstorm, |  | ||||||
|    awips::Phenomenon::SnowSquall, |  | ||||||
|    awips::Phenomenon::Tornado}; |  | ||||||
| 
 |  | ||||||
| template<class Key> |  | ||||||
| struct AlertTypeOldHash; |  | ||||||
| 
 |  | ||||||
| template<> |  | ||||||
| struct AlertTypeOldHash<std::pair<awips::Phenomenon, bool>> |  | ||||||
| { |  | ||||||
|    size_t operator()(const std::pair<awips::Phenomenon, bool>& x) const; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class AlertLayerOldHandler : public QObject |  | ||||||
| { |  | ||||||
|    Q_OBJECT |  | ||||||
| public: |  | ||||||
|    explicit AlertLayerOldHandler() : |  | ||||||
|        textEventManager_ {manager::TextEventManager::Instance()}, |  | ||||||
|        alertUpdateTimer_ {scwx::util::io_context()}, |  | ||||||
|        alertSourceMap_ {}, |  | ||||||
|        featureMap_ {} |  | ||||||
|    { |  | ||||||
|       for (auto& phenomenon : kAlertPhenomena_) |  | ||||||
|       { |  | ||||||
|          for (bool alertActive : {false, true}) |  | ||||||
|          { |  | ||||||
|             alertSourceMap_.emplace(std::make_pair(phenomenon, alertActive), |  | ||||||
|                                     kEmptyFeatureCollection_); |  | ||||||
|          } |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       connect(textEventManager_.get(), |  | ||||||
|               &manager::TextEventManager::AlertUpdated, |  | ||||||
|               this, |  | ||||||
|               &AlertLayerOldHandler::HandleAlert); |  | ||||||
|    } |  | ||||||
|    ~AlertLayerOldHandler() |  | ||||||
|    { |  | ||||||
|       std::unique_lock lock(alertMutex_); |  | ||||||
|       alertUpdateTimer_.cancel(); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    static std::shared_ptr<AlertLayerOldHandler> Instance(); |  | ||||||
| 
 |  | ||||||
|    std::list<QMapLibre::Feature>* FeatureList(awips::Phenomenon phenomenon, |  | ||||||
|                                               bool              alertActive); |  | ||||||
| 
 |  | ||||||
|    void HandleAlert(const types::TextEventKey& key, size_t messageIndex); |  | ||||||
|    void UpdateAlerts(); |  | ||||||
| 
 |  | ||||||
|    std::shared_ptr<manager::TextEventManager> textEventManager_; |  | ||||||
| 
 |  | ||||||
|    boost::asio::steady_timer alertUpdateTimer_; |  | ||||||
|    std::unordered_map<std::pair<awips::Phenomenon, bool>, |  | ||||||
|                       QVariantMap, |  | ||||||
|                       AlertTypeOldHash<std::pair<awips::Phenomenon, bool>>> |  | ||||||
|       alertSourceMap_; |  | ||||||
|    std::unordered_multimap<types::TextEventKey, |  | ||||||
|                            std::tuple<awips::Phenomenon, |  | ||||||
|                                       bool, |  | ||||||
|                                       std::list<QMapLibre::Feature>::iterator, |  | ||||||
|                                       std::chrono::system_clock::time_point>, |  | ||||||
|                            types::TextEventHash<types::TextEventKey>> |  | ||||||
|                      featureMap_; |  | ||||||
|    std::shared_mutex alertMutex_; |  | ||||||
| 
 |  | ||||||
| signals: |  | ||||||
|    void AlertsUpdated(awips::Phenomenon phenomenon, bool alertActive); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class AlertLayerOldImpl : public QObject |  | ||||||
| { |  | ||||||
|    Q_OBJECT |  | ||||||
| public: |  | ||||||
|    explicit AlertLayerOldImpl(std::shared_ptr<MapContext> context) : |  | ||||||
|        context_ {context}, |  | ||||||
|        alertLayerOldHandler_ {AlertLayerOldHandler::Instance()} |  | ||||||
|    { |  | ||||||
|       connect(alertLayerOldHandler_.get(), |  | ||||||
|               &AlertLayerOldHandler::AlertsUpdated, |  | ||||||
|               this, |  | ||||||
|               &AlertLayerOldImpl::UpdateSource); |  | ||||||
|    } |  | ||||||
|    ~AlertLayerOldImpl() {}; |  | ||||||
| 
 |  | ||||||
|    void UpdateSource(awips::Phenomenon phenomenon, bool alertActive); |  | ||||||
| 
 |  | ||||||
|    std::shared_ptr<MapContext>           context_; |  | ||||||
|    std::shared_ptr<AlertLayerOldHandler> alertLayerOldHandler_; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| AlertLayerOld::AlertLayerOld(std::shared_ptr<MapContext> context) : |  | ||||||
|     p(std::make_unique<AlertLayerOldImpl>(context)) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| AlertLayerOld::~AlertLayerOld() = default; |  | ||||||
| 
 |  | ||||||
| std::vector<std::string> AlertLayerOld::AddLayers(awips::Phenomenon  phenomenon, |  | ||||||
|                                                   const std::string& before) |  | ||||||
| { |  | ||||||
|    logger_->debug("AddLayers(): {}", awips::GetPhenomenonCode(phenomenon)); |  | ||||||
| 
 |  | ||||||
|    std::vector<std::string> layers {}; |  | ||||||
| 
 |  | ||||||
|    auto map = p->context_->map().lock(); |  | ||||||
|    if (map == nullptr) |  | ||||||
|    { |  | ||||||
|       return layers; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    const QString beforeLayer {QString::fromStdString(before)}; |  | ||||||
| 
 |  | ||||||
|    // Add/update GeoJSON sources and create layers
 |  | ||||||
|    for (bool alertActive : {false, true}) |  | ||||||
|    { |  | ||||||
|       p->UpdateSource(phenomenon, alertActive); |  | ||||||
|       auto newLayers = AddAlertLayer(map, phenomenon, alertActive, beforeLayer); |  | ||||||
|       layers.insert(layers.end(), newLayers.cbegin(), newLayers.cend()); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    return layers; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::list<QMapLibre::Feature>* |  | ||||||
| AlertLayerOldHandler::FeatureList(awips::Phenomenon phenomenon, |  | ||||||
|                                   bool              alertActive) |  | ||||||
| { |  | ||||||
|    std::list<QMapLibre::Feature>* featureList = nullptr; |  | ||||||
| 
 |  | ||||||
|    auto key = std::make_pair(phenomenon, alertActive); |  | ||||||
|    auto it  = alertSourceMap_.find(key); |  | ||||||
|    if (it != alertSourceMap_.cend()) |  | ||||||
|    { |  | ||||||
|       featureList = reinterpret_cast<std::list<QMapLibre::Feature>*>( |  | ||||||
|          it->second["data"].data()); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    return featureList; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void AlertLayerOldHandler::HandleAlert(const types::TextEventKey& key, |  | ||||||
|                                        size_t                     messageIndex) |  | ||||||
| { |  | ||||||
|    // Skip alert if there are more messages to be processed
 |  | ||||||
|    if (messageIndex + 1 < textEventManager_->message_count(key)) |  | ||||||
|    { |  | ||||||
|       return; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    auto message = textEventManager_->message_list(key).at(messageIndex); |  | ||||||
|    std::unordered_set<std::pair<awips::Phenomenon, bool>, |  | ||||||
|                       AlertTypeOldHash<std::pair<awips::Phenomenon, bool>>> |  | ||||||
|       alertsUpdated {}; |  | ||||||
| 
 |  | ||||||
|    // Take a unique lock before modifying feature lists
 |  | ||||||
|    std::unique_lock lock(alertMutex_); |  | ||||||
| 
 |  | ||||||
|    // Remove existing features for key
 |  | ||||||
|    auto existingFeatures = featureMap_.equal_range(key); |  | ||||||
|    for (auto it = existingFeatures.first; it != existingFeatures.second; ++it) |  | ||||||
|    { |  | ||||||
|       auto& [phenomenon, alertActive, featureIt, eventEnd] = it->second; |  | ||||||
|       auto featureList = FeatureList(phenomenon, alertActive); |  | ||||||
|       if (featureList != nullptr) |  | ||||||
|       { |  | ||||||
|          // Remove existing feature for key
 |  | ||||||
|          featureList->erase(featureIt); |  | ||||||
| 
 |  | ||||||
|          // Mark alert type as updated
 |  | ||||||
|          alertsUpdated.emplace(phenomenon, alertActive); |  | ||||||
|       } |  | ||||||
|    } |  | ||||||
|    featureMap_.erase(existingFeatures.first, existingFeatures.second); |  | ||||||
| 
 |  | ||||||
|    for (auto segment : message->segments()) |  | ||||||
|    { |  | ||||||
|       if (!segment->codedLocation_.has_value()) |  | ||||||
|       { |  | ||||||
|          continue; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       auto&             vtec       = segment->header_->vtecString_.front(); |  | ||||||
|       auto              action     = vtec.pVtec_.action(); |  | ||||||
|       awips::Phenomenon phenomenon = vtec.pVtec_.phenomenon(); |  | ||||||
|       auto              eventEnd   = vtec.pVtec_.event_end(); |  | ||||||
|       bool alertActive             = (action != awips::PVtec::Action::Canceled); |  | ||||||
| 
 |  | ||||||
|       // If the event has ended, skip it
 |  | ||||||
|       if (eventEnd < std::chrono::system_clock::now()) |  | ||||||
|       { |  | ||||||
|          continue; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       auto featureList = FeatureList(phenomenon, alertActive); |  | ||||||
|       if (featureList != nullptr) |  | ||||||
|       { |  | ||||||
|          // Add alert location to polygon list
 |  | ||||||
|          auto featureIt = featureList->emplace( |  | ||||||
|             featureList->cend(), |  | ||||||
|             CreateFeature(segment->codedLocation_.value())); |  | ||||||
| 
 |  | ||||||
|          // Store iterator for created feature in feature map
 |  | ||||||
|          featureMap_.emplace(std::piecewise_construct, |  | ||||||
|                              std::forward_as_tuple(key), |  | ||||||
|                              std::forward_as_tuple( |  | ||||||
|                                 phenomenon, alertActive, featureIt, eventEnd)); |  | ||||||
| 
 |  | ||||||
|          // Mark alert type as updated
 |  | ||||||
|          alertsUpdated.emplace(phenomenon, alertActive); |  | ||||||
|       } |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    // Release the lock after completing feature list updates
 |  | ||||||
|    lock.unlock(); |  | ||||||
| 
 |  | ||||||
|    for (auto& alert : alertsUpdated) |  | ||||||
|    { |  | ||||||
|       // Emit signal for each updated alert type
 |  | ||||||
|       Q_EMIT AlertsUpdated(alert.first, alert.second); |  | ||||||
|    } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void AlertLayerOldHandler::UpdateAlerts() |  | ||||||
| { |  | ||||||
|    logger_->trace("UpdateAlerts"); |  | ||||||
| 
 |  | ||||||
|    // Take a unique lock before modifying feature lists
 |  | ||||||
|    std::unique_lock lock(alertMutex_); |  | ||||||
| 
 |  | ||||||
|    std::unordered_set<std::pair<awips::Phenomenon, bool>, |  | ||||||
|                       AlertTypeOldHash<std::pair<awips::Phenomenon, bool>>> |  | ||||||
|       alertsUpdated {}; |  | ||||||
| 
 |  | ||||||
|    // Evaluate each rendered feature for expiration
 |  | ||||||
|    for (auto it = featureMap_.begin(); it != featureMap_.end();) |  | ||||||
|    { |  | ||||||
|       auto& [phenomenon, alertActive, featureIt, eventEnd] = it->second; |  | ||||||
| 
 |  | ||||||
|       // If the event has ended, remove it from the feature list
 |  | ||||||
|       if (eventEnd < std::chrono::system_clock::now()) |  | ||||||
|       { |  | ||||||
|          logger_->debug("Alert expired: {}", it->first.ToString()); |  | ||||||
| 
 |  | ||||||
|          auto featureList = FeatureList(phenomenon, alertActive); |  | ||||||
|          if (featureList != nullptr) |  | ||||||
|          { |  | ||||||
|             // Remove existing feature for key
 |  | ||||||
|             featureList->erase(featureIt); |  | ||||||
| 
 |  | ||||||
|             // Mark alert type as updated
 |  | ||||||
|             alertsUpdated.emplace(phenomenon, alertActive); |  | ||||||
|          } |  | ||||||
| 
 |  | ||||||
|          // Erase current item and increment iterator
 |  | ||||||
|          it = featureMap_.erase(it); |  | ||||||
|       } |  | ||||||
|       else |  | ||||||
|       { |  | ||||||
|          // Current item is not expired, continue
 |  | ||||||
|          ++it; |  | ||||||
|       } |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    for (auto& alert : alertsUpdated) |  | ||||||
|    { |  | ||||||
|       // Emit signal for each updated alert type
 |  | ||||||
|       Q_EMIT AlertsUpdated(alert.first, alert.second); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    using namespace std::chrono; |  | ||||||
|    alertUpdateTimer_.expires_after(15s); |  | ||||||
|    alertUpdateTimer_.async_wait( |  | ||||||
|       [this](const boost::system::error_code& e) |  | ||||||
|       { |  | ||||||
|          if (e == boost::asio::error::operation_aborted) |  | ||||||
|          { |  | ||||||
|             logger_->debug("Alert update timer cancelled"); |  | ||||||
|          } |  | ||||||
|          else if (e != boost::system::errc::success) |  | ||||||
|          { |  | ||||||
|             logger_->warn("Alert update timer error: {}", e.message()); |  | ||||||
|          } |  | ||||||
|          else |  | ||||||
|          { |  | ||||||
|             try |  | ||||||
|             { |  | ||||||
|                UpdateAlerts(); |  | ||||||
|             } |  | ||||||
|             catch (const std::exception& ex) |  | ||||||
|             { |  | ||||||
|                logger_->error(ex.what()); |  | ||||||
|             } |  | ||||||
|          } |  | ||||||
|       }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void AlertLayerOldImpl::UpdateSource(awips::Phenomenon phenomenon, |  | ||||||
|                                      bool              alertActive) |  | ||||||
| { |  | ||||||
|    auto map = context_->map().lock(); |  | ||||||
|    if (map == nullptr) |  | ||||||
|    { |  | ||||||
|       return; |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    // Take a shared lock before using feature lists
 |  | ||||||
|    std::shared_lock lock(alertLayerOldHandler_->alertMutex_); |  | ||||||
| 
 |  | ||||||
|    // Update source, relies on alert source being defined
 |  | ||||||
|    map->updateSource(GetSourceId(phenomenon, alertActive), |  | ||||||
|                      alertLayerOldHandler_->alertSourceMap_.at( |  | ||||||
|                         std::make_pair(phenomenon, alertActive))); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::shared_ptr<AlertLayerOldHandler> AlertLayerOldHandler::Instance() |  | ||||||
| { |  | ||||||
|    static std::weak_ptr<AlertLayerOldHandler> alertLayerOldHandlerReference {}; |  | ||||||
|    static std::mutex                          instanceMutex {}; |  | ||||||
| 
 |  | ||||||
|    std::unique_lock lock(instanceMutex); |  | ||||||
| 
 |  | ||||||
|    std::shared_ptr<AlertLayerOldHandler> alertLayerOldHandler = |  | ||||||
|       alertLayerOldHandlerReference.lock(); |  | ||||||
| 
 |  | ||||||
|    if (alertLayerOldHandler == nullptr) |  | ||||||
|    { |  | ||||||
|       alertLayerOldHandler          = std::make_shared<AlertLayerOldHandler>(); |  | ||||||
|       alertLayerOldHandlerReference = alertLayerOldHandler; |  | ||||||
| 
 |  | ||||||
|       alertLayerOldHandler->UpdateAlerts(); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    return alertLayerOldHandler; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static std::vector<std::string> |  | ||||||
| AddAlertLayer(std::shared_ptr<QMapLibre::Map> map, |  | ||||||
|               awips::Phenomenon               phenomenon, |  | ||||||
|               bool                            alertActive, |  | ||||||
|               const QString&                  beforeLayer) |  | ||||||
| { |  | ||||||
|    settings::PaletteSettings& paletteSettings = |  | ||||||
|       settings::PaletteSettings::Instance(); |  | ||||||
| 
 |  | ||||||
|    QString layerPrefix = QString::fromStdString( |  | ||||||
|       types::GetLayerName(types::LayerType::Alert, phenomenon)); |  | ||||||
| 
 |  | ||||||
|    QString sourceId     = GetSourceId(phenomenon, alertActive); |  | ||||||
|    QString idSuffix     = GetSuffix(phenomenon, alertActive); |  | ||||||
|    auto    outlineColor = util::color::ToRgba8PixelT( |  | ||||||
|       paletteSettings.alert_color(phenomenon, alertActive).GetValue()); |  | ||||||
| 
 |  | ||||||
|    QString bgLayerId = QString("%1::bg-%2").arg(layerPrefix).arg(idSuffix); |  | ||||||
|    QString fgLayerId = QString("%1::fg-%2").arg(layerPrefix).arg(idSuffix); |  | ||||||
| 
 |  | ||||||
|    if (map->layerExists(bgLayerId)) |  | ||||||
|    { |  | ||||||
|       map->removeLayer(bgLayerId); |  | ||||||
|    } |  | ||||||
|    if (map->layerExists(fgLayerId)) |  | ||||||
|    { |  | ||||||
|       map->removeLayer(fgLayerId); |  | ||||||
|    } |  | ||||||
| 
 |  | ||||||
|    const float opacity = outlineColor[3] / 255.0f; |  | ||||||
| 
 |  | ||||||
|    map->addLayer( |  | ||||||
|       bgLayerId, {{"type", "line"}, {"source", sourceId}}, beforeLayer); |  | ||||||
|    map->setLayoutProperty(bgLayerId, "line-join", "round"); |  | ||||||
|    map->setLayoutProperty(bgLayerId, "line-cap", "round"); |  | ||||||
|    map->setPaintProperty(bgLayerId, "line-color", "rgba(0, 0, 0, 255)"); |  | ||||||
|    map->setPaintProperty(bgLayerId, "line-opacity", QString("%1").arg(opacity)); |  | ||||||
|    map->setPaintProperty(bgLayerId, "line-width", "5"); |  | ||||||
| 
 |  | ||||||
|    map->addLayer( |  | ||||||
|       fgLayerId, {{"type", "line"}, {"source", sourceId}}, beforeLayer); |  | ||||||
|    map->setLayoutProperty(fgLayerId, "line-join", "round"); |  | ||||||
|    map->setLayoutProperty(fgLayerId, "line-cap", "round"); |  | ||||||
|    map->setPaintProperty(fgLayerId, |  | ||||||
|                          "line-color", |  | ||||||
|                          QString("rgba(%1, %2, %3, %4)") |  | ||||||
|                             .arg(outlineColor[0]) |  | ||||||
|                             .arg(outlineColor[1]) |  | ||||||
|                             .arg(outlineColor[2]) |  | ||||||
|                             .arg(outlineColor[3])); |  | ||||||
|    map->setPaintProperty(fgLayerId, "line-opacity", QString("%1").arg(opacity)); |  | ||||||
|    map->setPaintProperty(fgLayerId, "line-width", "3"); |  | ||||||
| 
 |  | ||||||
|    return {bgLayerId.toStdString(), fgLayerId.toStdString()}; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static QMapLibre::Feature |  | ||||||
| CreateFeature(const awips::CodedLocation& codedLocation) |  | ||||||
| { |  | ||||||
|    auto mapboxCoordinates = GetMapboxCoordinates(codedLocation); |  | ||||||
| 
 |  | ||||||
|    return QMapLibre::Feature { |  | ||||||
|       QMapLibre::Feature::PolygonType, |  | ||||||
|       std::initializer_list<QMapLibre::CoordinatesCollection> { |  | ||||||
|          std::initializer_list<QMapLibre::Coordinates> {{mapboxCoordinates}}}}; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static QMapLibre::Coordinate |  | ||||||
| GetMapboxCoordinate(const common::Coordinate& coordinate) |  | ||||||
| { |  | ||||||
|    return {coordinate.latitude_, coordinate.longitude_}; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static QMapLibre::Coordinates |  | ||||||
| GetMapboxCoordinates(const awips::CodedLocation& codedLocation) |  | ||||||
| { |  | ||||||
|    auto                   scwxCoordinates = codedLocation.coordinates(); |  | ||||||
|    QMapLibre::Coordinates mapboxCoordinates(scwxCoordinates.size() + 1u); |  | ||||||
| 
 |  | ||||||
|    std::transform(scwxCoordinates.cbegin(), |  | ||||||
|                   scwxCoordinates.cend(), |  | ||||||
|                   mapboxCoordinates.begin(), |  | ||||||
|                   [](auto& coordinate) -> QMapLibre::Coordinate |  | ||||||
|                   { return GetMapboxCoordinate(coordinate); }); |  | ||||||
| 
 |  | ||||||
|    mapboxCoordinates.back() = GetMapboxCoordinate(scwxCoordinates.front()); |  | ||||||
| 
 |  | ||||||
|    return mapboxCoordinates; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static QString GetSourceId(awips::Phenomenon phenomenon, bool alertActive) |  | ||||||
| { |  | ||||||
|    return QString("alertPolygon-%1").arg(GetSuffix(phenomenon, alertActive)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static QString GetSuffix(awips::Phenomenon phenomenon, bool alertActive) |  | ||||||
| { |  | ||||||
|    return QString("-%1.%2") |  | ||||||
|       .arg(QString::fromStdString(awips::GetPhenomenonCode(phenomenon))) |  | ||||||
|       .arg(alertActive); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| size_t AlertTypeOldHash<std::pair<awips::Phenomenon, bool>>::operator()( |  | ||||||
|    const std::pair<awips::Phenomenon, bool>& x) const |  | ||||||
| { |  | ||||||
|    size_t seed = 0; |  | ||||||
|    boost::hash_combine(seed, x.first); |  | ||||||
|    boost::hash_combine(seed, x.second); |  | ||||||
|    return seed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } // namespace map
 |  | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
| 
 |  | ||||||
| #include "alert_layer_old.moc" |  | ||||||
|  | @ -1,34 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <scwx/awips/phenomenon.hpp> |  | ||||||
| #include <scwx/qt/map/map_context.hpp> |  | ||||||
| 
 |  | ||||||
| #include <memory> |  | ||||||
| #include <string> |  | ||||||
| #include <vector> |  | ||||||
| 
 |  | ||||||
| namespace scwx |  | ||||||
| { |  | ||||||
| namespace qt |  | ||||||
| { |  | ||||||
| namespace map |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| class AlertLayerOldImpl; |  | ||||||
| 
 |  | ||||||
| class AlertLayerOld |  | ||||||
| { |  | ||||||
| public: |  | ||||||
|    explicit AlertLayerOld(std::shared_ptr<MapContext> context); |  | ||||||
|    ~AlertLayerOld(); |  | ||||||
| 
 |  | ||||||
|    std::vector<std::string> AddLayers(awips::Phenomenon  phenomenon, |  | ||||||
|                                       const std::string& before = {}); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|    std::unique_ptr<AlertLayerOldImpl> p; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| } // namespace map
 |  | ||||||
| } // namespace qt
 |  | ||||||
| } // namespace scwx
 |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat