#include #include #include #include #include #include #include #include #include #include namespace scwx { namespace qt { namespace map { static const std::string logPrefix_ = "scwx::qt::map::radar_site_layer"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class RadarSiteLayer::Impl { public: explicit Impl(RadarSiteLayer* self) : self_ {self} {} ~Impl() = default; void RenderRadarSite(const QMapLibre::CustomLayerRenderParameters& params, std::shared_ptr& radarSite); RadarSiteLayer* self_; std::vector> radarSites_ {}; glm::vec2 mapScreenCoordLocation_ {}; float mapScale_ {1.0f}; float mapBearingCos_ {1.0f}; float mapBearingSin_ {0.0f}; float halfWidth_ {}; float halfHeight_ {}; std::string hoverText_ {}; }; RadarSiteLayer::RadarSiteLayer(std::shared_ptr context) : DrawLayer(context, "RadarSiteLayer"), p(std::make_unique(this)) { } RadarSiteLayer::~RadarSiteLayer() = default; void RadarSiteLayer::Initialize() { logger_->debug("Initialize()"); p->radarSites_ = config::RadarSite::GetAll(); ImGuiInitialize(); } void RadarSiteLayer::Render( const QMapLibre::CustomLayerRenderParameters& params) { p->hoverText_.clear(); auto mapDistance = util::maplibre::GetMapDistance(params); auto threshold = units::length::kilometers( settings::GeneralSettings::Instance().radar_site_threshold().GetValue()); if (!(threshold.value() == 0.0 || mapDistance <= threshold || (threshold.value() < 0 && mapDistance >= -threshold))) { return; } gl::OpenGLFunctions& gl = context()->gl(); // Update map screen coordinate and scale information p->mapScreenCoordLocation_ = util::maplibre::LatLongToScreenCoordinate( {params.latitude, params.longitude}); p->mapScale_ = std::pow(2.0, params.zoom) * mbgl::util::tileSize_D / mbgl::util::DEGREES_MAX; p->mapBearingCos_ = cosf(params.bearing * common::kDegreesToRadians); p->mapBearingSin_ = sinf(params.bearing * common::kDegreesToRadians); p->halfWidth_ = params.width * 0.5f; p->halfHeight_ = params.height * 0.5f; ImGuiFrameStart(); // Radar site ImGui windows shouldn't have padding ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2 {0.0f, 0.0f}); for (auto& radarSite : p->radarSites_) { p->RenderRadarSite(params, radarSite); } ImGui::PopStyleVar(); ImGuiFrameEnd(); SCWX_GL_CHECK_ERROR(); } void RadarSiteLayer::Impl::RenderRadarSite( const QMapLibre::CustomLayerRenderParameters& params, std::shared_ptr& radarSite) { const std::string windowName = fmt::format("radar-site-{}", radarSite->id()); const auto screenCoordinates = (util::maplibre::LatLongToScreenCoordinate( {radarSite->latitude(), radarSite->longitude()}) - mapScreenCoordLocation_) * mapScale_; // Rotate text according to map rotation float rotatedX = screenCoordinates.x; float rotatedY = screenCoordinates.y; if (params.bearing != 0.0) { rotatedX = screenCoordinates.x * mapBearingCos_ - screenCoordinates.y * mapBearingSin_; rotatedY = screenCoordinates.x * mapBearingSin_ + screenCoordinates.y * mapBearingCos_; } // Convert screen to ImGui coordinates float x = rotatedX + halfWidth_; float y = params.height - (rotatedY + halfHeight_); // Setup window to hold text ImGui::SetNextWindowPos( ImVec2 {x, y}, ImGuiCond_Always, ImVec2 {0.5f, 0.5f}); if (ImGui::Begin(windowName.c_str(), nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) { // Render text if (ImGui::Button(radarSite->id().c_str())) { Q_EMIT self_->RadarSiteSelected(radarSite->id()); self_->ImGuiSelectContext(); } // Store hover text for mouse picking pass if (settings::TextSettings::Instance() .radar_site_hover_text_enabled() .GetValue() && ImGui::IsItemHovered()) { hoverText_ = fmt::format("{} ({})\n{}\n{}, {}", radarSite->id(), radarSite->type_name(), radarSite->location_name(), common::GetLatitudeString(radarSite->latitude()), common::GetLongitudeString(radarSite->longitude())); } // End window ImGui::End(); } } void RadarSiteLayer::Deinitialize() { logger_->debug("Deinitialize()"); p->radarSites_.clear(); } bool RadarSiteLayer::RunMousePicking( const QMapLibre::CustomLayerRenderParameters& /* params */, const QPointF& /* mouseLocalPos */, const QPointF& mouseGlobalPos, const glm::vec2& /* mouseCoords */, const common::Coordinate& /* mouseGeoCoords */, std::shared_ptr& /* eventHandler */) { if (!p->hoverText_.empty()) { util::tooltip::Show(p->hoverText_, mouseGlobalPos); return true; } return false; } } // namespace map } // namespace qt } // namespace scwx