mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 06:30:05 +00:00 
			
		
		
		
	Placefile line hover in-work
This commit is contained in:
		
							parent
							
								
									37d751774d
								
							
						
					
					
						commit
						8dfb9f1105
					
				
					 14 changed files with 243 additions and 36 deletions
				
			
		|  | @ -54,7 +54,8 @@ void DrawItem::Render(const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool DrawItem::RunMousePicking( | bool DrawItem::RunMousePicking( | ||||||
|    const QMapLibreGL::CustomLayerRenderParameters& /* params */) |    const QMapLibreGL::CustomLayerRenderParameters& /* params */, | ||||||
|  |    const glm::vec2& /* mousePos */) | ||||||
| { | { | ||||||
|    // By default, the draw item is not picked
 |    // By default, the draw item is not picked
 | ||||||
|    return false; |    return false; | ||||||
|  | @ -97,17 +98,7 @@ void DrawItem::UseMapProjection( | ||||||
| { | { | ||||||
|    OpenGLFunctions& gl = p->gl_; |    OpenGLFunctions& gl = p->gl_; | ||||||
| 
 | 
 | ||||||
|    // TODO: Refactor to utility class
 |    const glm::mat4 uMVPMatrix = util::maplibre::GetMapMatrix(params); | ||||||
|    const float scale = std::pow(2.0, params.zoom) * 2.0f * |  | ||||||
|                        mbgl::util::tileSize_D / mbgl::util::DEGREES_MAX; |  | ||||||
|    const float xScale = scale / params.width; |  | ||||||
|    const float yScale = scale / params.height; |  | ||||||
| 
 |  | ||||||
|    glm::mat4 uMVPMatrix(1.0f); |  | ||||||
|    uMVPMatrix = glm::scale(uMVPMatrix, glm::vec3(xScale, yScale, 1.0f)); |  | ||||||
|    uMVPMatrix = glm::rotate(uMVPMatrix, |  | ||||||
|                             glm::radians<float>(params.bearing), |  | ||||||
|                             glm::vec3(0.0f, 0.0f, 1.0f)); |  | ||||||
| 
 | 
 | ||||||
|    gl.glUniform2fv(uMapScreenCoordLocation, |    gl.glUniform2fv(uMapScreenCoordLocation, | ||||||
|                    1, |                    1, | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include <memory> | #include <memory> | ||||||
| 
 | 
 | ||||||
| #include <QMapLibreGL/QMapLibreGL> | #include <QMapLibreGL/QMapLibreGL> | ||||||
|  | #include <glm/gtc/type_ptr.hpp> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx | ||||||
| { | { | ||||||
|  | @ -37,11 +38,13 @@ public: | ||||||
|     * @brief Run mouse picking on the draw item. |     * @brief Run mouse picking on the draw item. | ||||||
|     * |     * | ||||||
|     * @param [in] params Custom layer render parameters |     * @param [in] params Custom layer render parameters | ||||||
|  |     * @param [in] mousePos Mouse cursor location in map screen coordinates | ||||||
|     * |     * | ||||||
|     * @return true if the draw item was picked, otherwise false |     * @return true if the draw item was picked, otherwise false | ||||||
|     */ |     */ | ||||||
|    virtual bool |    virtual bool | ||||||
|    RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params); |    RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
|  |                    const glm::vec2&                                mousePos); | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|    void |    void | ||||||
|  |  | ||||||
|  | @ -1,8 +1,12 @@ | ||||||
| #include <scwx/qt/gl/draw/placefile_lines.hpp> | #include <scwx/qt/gl/draw/placefile_lines.hpp> | ||||||
|  | #include <scwx/qt/manager/resource_manager.hpp> | ||||||
|  | #include <scwx/qt/manager/settings_manager.hpp> | ||||||
| #include <scwx/qt/util/geographic_lib.hpp> | #include <scwx/qt/util/geographic_lib.hpp> | ||||||
| #include <scwx/qt/util/maplibre.hpp> | #include <scwx/qt/util/maplibre.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
| 
 | 
 | ||||||
|  | #include <imgui.h> | ||||||
|  | 
 | ||||||
| namespace scwx | namespace scwx | ||||||
| { | { | ||||||
| namespace qt | namespace qt | ||||||
|  | @ -28,6 +32,15 @@ static const boost::gil::rgba8_pixel_t kBlack_ {0, 0, 0, 255}; | ||||||
| class PlacefileLines::Impl | class PlacefileLines::Impl | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  |    struct LineHoverEntry | ||||||
|  |    { | ||||||
|  |       std::string hoverText_; | ||||||
|  |       glm::vec2   p1_; | ||||||
|  |       glm::vec2   p2_; | ||||||
|  |       glm::mat2   rotate_; | ||||||
|  |       float       width_; | ||||||
|  |    }; | ||||||
|  | 
 | ||||||
|    explicit Impl(const std::shared_ptr<GlContext>& context) : |    explicit Impl(const std::shared_ptr<GlContext>& context) : | ||||||
|        context_ {context}, |        context_ {context}, | ||||||
|        shaderProgram_ {nullptr}, |        shaderProgram_ {nullptr}, | ||||||
|  | @ -46,9 +59,10 @@ public: | ||||||
|    void BufferLine(const gr::Placefile::LineDrawItem::Element& e1, |    void BufferLine(const gr::Placefile::LineDrawItem::Element& e1, | ||||||
|                    const gr::Placefile::LineDrawItem::Element& e2, |                    const gr::Placefile::LineDrawItem::Element& e2, | ||||||
|                    const float                                 width, |                    const float                                 width, | ||||||
|                    const float                                 angle, |                    const units::angle::degrees<double>         angle, | ||||||
|                    const boost::gil::rgba8_pixel_t             color, |                    const boost::gil::rgba8_pixel_t             color, | ||||||
|                    const GLint                                 threshold); |                    const GLint                                 threshold, | ||||||
|  |                    const std::string&                          hoverText = {}); | ||||||
|    void |    void | ||||||
|    UpdateBuffers(const std::shared_ptr<const gr::Placefile::LineDrawItem>& di); |    UpdateBuffers(const std::shared_ptr<const gr::Placefile::LineDrawItem>& di); | ||||||
|    void Update(); |    void Update(); | ||||||
|  | @ -68,6 +82,9 @@ public: | ||||||
|    std::vector<float> newLinesBuffer_ {}; |    std::vector<float> newLinesBuffer_ {}; | ||||||
|    std::vector<GLint> newThresholdBuffer_ {}; |    std::vector<GLint> newThresholdBuffer_ {}; | ||||||
| 
 | 
 | ||||||
|  |    std::vector<LineHoverEntry> currentHoverLines_ {}; | ||||||
|  |    std::vector<LineHoverEntry> newHoverLines_ {}; | ||||||
|  | 
 | ||||||
|    std::shared_ptr<ShaderProgram> shaderProgram_; |    std::shared_ptr<ShaderProgram> shaderProgram_; | ||||||
|    GLint                          uMVPMatrixLocation_; |    GLint                          uMVPMatrixLocation_; | ||||||
|    GLint                          uMapMatrixLocation_; |    GLint                          uMapMatrixLocation_; | ||||||
|  | @ -213,6 +230,125 @@ void PlacefileLines::Deinitialize() | ||||||
| 
 | 
 | ||||||
|    p->currentLinesBuffer_.clear(); |    p->currentLinesBuffer_.clear(); | ||||||
|    p->currentThresholdBuffer_.clear(); |    p->currentThresholdBuffer_.clear(); | ||||||
|  |    p->currentHoverLines_.clear(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DrawTooltip(const std::string& hoverText) | ||||||
|  | { | ||||||
|  |    // Get monospace font pointer
 | ||||||
|  |    std::size_t fontSize = 16; | ||||||
|  |    auto        fontSizes = | ||||||
|  |       manager::SettingsManager::general_settings().font_sizes().GetValue(); | ||||||
|  |    if (fontSizes.size() > 1) | ||||||
|  |    { | ||||||
|  |       fontSize = fontSizes[1]; | ||||||
|  |    } | ||||||
|  |    else if (fontSizes.size() > 0) | ||||||
|  |    { | ||||||
|  |       fontSize = fontSizes[0]; | ||||||
|  |    } | ||||||
|  |    auto monospace = | ||||||
|  |       manager::ResourceManager::Font(types::Font::Inconsolata_Regular); | ||||||
|  |    auto monospaceFont = monospace->ImGuiFont(fontSize); | ||||||
|  | 
 | ||||||
|  |    ImGui::BeginTooltip(); | ||||||
|  |    ImGui::PushFont(monospaceFont); | ||||||
|  |    ImGui::TextUnformatted(hoverText.c_str()); | ||||||
|  |    ImGui::PopFont(); | ||||||
|  |    ImGui::EndTooltip(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IsPointInPolygon(const std::vector<glm::vec2> vertices, | ||||||
|  |                       const glm::vec2&             point) | ||||||
|  | { | ||||||
|  |    bool inPolygon = true; | ||||||
|  | 
 | ||||||
|  |    // For each vertex, assume counterclockwise order
 | ||||||
|  |    for (std::size_t i = 0; i < vertices.size(); ++i) | ||||||
|  |    { | ||||||
|  |       const auto& p1 = vertices[i]; | ||||||
|  |       const auto& p2 = | ||||||
|  |          (i == vertices.size() - 1) ? vertices[0] : vertices[i + 1]; | ||||||
|  | 
 | ||||||
|  |       // Test which side of edge point lies on
 | ||||||
|  |       const float a = -(p2.y - p1.y); | ||||||
|  |       const float b = p2.x - p1.x; | ||||||
|  |       const float c = -(a * p1.x + b * p1.y); | ||||||
|  |       const float d = a * point.x + b * point.y + c; | ||||||
|  | 
 | ||||||
|  |       // If d < 0, the point is on the right-hand side, and outside of the
 | ||||||
|  |       // polygon
 | ||||||
|  |       if (d < 0) | ||||||
|  |       { | ||||||
|  |          inPolygon = false; | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return inPolygon; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool PlacefileLines::RunMousePicking( | ||||||
|  |    const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
|  |    const glm::vec2&                                mousePos) | ||||||
|  | { | ||||||
|  |    std::unique_lock lock {p->lineMutex_}; | ||||||
|  | 
 | ||||||
|  |    bool itemPicked = false; | ||||||
|  | 
 | ||||||
|  |    // Calculate map scale, remove width and height from original calculation
 | ||||||
|  |    glm::vec2 scale = util::maplibre::GetMapScale(params); | ||||||
|  |    scale = 1.0f / glm::vec2 {scale.x * params.width, scale.y * params.height}; | ||||||
|  | 
 | ||||||
|  |    // Scale and rotate the identity matrix to create the map matrix
 | ||||||
|  |    glm::mat4 mapMatrix {1.0f}; | ||||||
|  |    mapMatrix = glm::scale(mapMatrix, glm::vec3 {scale, 1.0f}); | ||||||
|  |    mapMatrix = glm::rotate(mapMatrix, | ||||||
|  |                            glm::radians<float>(params.bearing), | ||||||
|  |                            glm::vec3(0.0f, 0.0f, 1.0f)); | ||||||
|  | 
 | ||||||
|  |    // For each pickable line
 | ||||||
|  |    for (auto& line : p->currentHoverLines_) | ||||||
|  |    { | ||||||
|  |       // Initialize vertices
 | ||||||
|  |       glm::vec2 bl = line.p1_; | ||||||
|  |       glm::vec2 br = bl; | ||||||
|  |       glm::vec2 tl = line.p2_; | ||||||
|  |       glm::vec2 tr = tl; | ||||||
|  | 
 | ||||||
|  |       // Calculate offsets
 | ||||||
|  |       // - Offset is half the line width (pixels) in each direction
 | ||||||
|  |       // - Rotate the offset at each vertex
 | ||||||
|  |       // - Multiply the offset by the map matrix
 | ||||||
|  |       const float     hw = line.width_ * 0.5f; | ||||||
|  |       const glm::vec2 otl = | ||||||
|  |          mapMatrix * | ||||||
|  |          glm::vec4 {line.rotate_ * glm::vec2 {-hw, -hw}, 0.0f, 1.0f}; | ||||||
|  |       const glm::vec2 obl = | ||||||
|  |          mapMatrix * glm::vec4 {line.rotate_ * glm::vec2 {-hw, hw}, 0.0f, 1.0f}; | ||||||
|  |       const glm::vec2 obr = | ||||||
|  |          mapMatrix * glm::vec4 {line.rotate_ * glm::vec2 {hw, hw}, 0.0f, 1.0f}; | ||||||
|  |       const glm::vec2 otr = | ||||||
|  |          mapMatrix * glm::vec4 {line.rotate_ * glm::vec2 {hw, -hw}, 0.0f, 1.0f}; | ||||||
|  | 
 | ||||||
|  |       // Offset vertices
 | ||||||
|  |       tl += otl; | ||||||
|  |       bl += obl; | ||||||
|  |       br += obr; | ||||||
|  |       tr += otr; | ||||||
|  | 
 | ||||||
|  |       // TODO: X/Y offsets
 | ||||||
|  | 
 | ||||||
|  |       // Test point against polygon bounds
 | ||||||
|  |       if (IsPointInPolygon({tl, bl, br, tr}, mousePos)) | ||||||
|  |       { | ||||||
|  |          itemPicked = true; | ||||||
|  |          DrawTooltip(line.hoverText_); | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return itemPicked; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlacefileLines::StartLines() | void PlacefileLines::StartLines() | ||||||
|  | @ -220,6 +356,7 @@ void PlacefileLines::StartLines() | ||||||
|    // Clear the new buffers
 |    // Clear the new buffers
 | ||||||
|    p->newLinesBuffer_.clear(); |    p->newLinesBuffer_.clear(); | ||||||
|    p->newThresholdBuffer_.clear(); |    p->newThresholdBuffer_.clear(); | ||||||
|  |    p->newHoverLines_.clear(); | ||||||
| 
 | 
 | ||||||
|    p->newNumLines_ = 0u; |    p->newNumLines_ = 0u; | ||||||
| } | } | ||||||
|  | @ -241,10 +378,12 @@ void PlacefileLines::FinishLines() | ||||||
|    // Swap buffers
 |    // Swap buffers
 | ||||||
|    p->currentLinesBuffer_.swap(p->newLinesBuffer_); |    p->currentLinesBuffer_.swap(p->newLinesBuffer_); | ||||||
|    p->currentThresholdBuffer_.swap(p->newThresholdBuffer_); |    p->currentThresholdBuffer_.swap(p->newThresholdBuffer_); | ||||||
|  |    p->currentHoverLines_.swap(p->newHoverLines_); | ||||||
| 
 | 
 | ||||||
|    // Clear the new buffers
 |    // Clear the new buffers
 | ||||||
|    p->newLinesBuffer_.clear(); |    p->newLinesBuffer_.clear(); | ||||||
|    p->newThresholdBuffer_.clear(); |    p->newThresholdBuffer_.clear(); | ||||||
|  |    p->newHoverLines_.clear(); | ||||||
| 
 | 
 | ||||||
|    // Update the number of lines
 |    // Update the number of lines
 | ||||||
|    p->currentNumLines_ = p->newNumLines_; |    p->currentNumLines_ = p->newNumLines_; | ||||||
|  | @ -262,7 +401,7 @@ void PlacefileLines::Impl::UpdateBuffers( | ||||||
|    units::length::nautical_miles<double> threshold = di->threshold_; |    units::length::nautical_miles<double> threshold = di->threshold_; | ||||||
|    GLint thresholdValue = static_cast<GLint>(std::round(threshold.value())); |    GLint thresholdValue = static_cast<GLint>(std::round(threshold.value())); | ||||||
| 
 | 
 | ||||||
|    std::vector<float> angles {}; |    std::vector<units::angle::degrees<double>> angles {}; | ||||||
|    angles.reserve(di->elements_.size() - 1); |    angles.reserve(di->elements_.size() - 1); | ||||||
| 
 | 
 | ||||||
|    // For each element pair inside a Line statement, render a black line
 |    // For each element pair inside a Line statement, render a black line
 | ||||||
|  | @ -277,26 +416,27 @@ void PlacefileLines::Impl::UpdateBuffers( | ||||||
|       // Calculate angle
 |       // Calculate angle
 | ||||||
|       const units::angle::degrees<double> angle = |       const units::angle::degrees<double> angle = | ||||||
|          util::GeographicLib::GetAngle(lat1, lon1, lat2, lon2); |          util::GeographicLib::GetAngle(lat1, lon1, lat2, lon2); | ||||||
|       float angleValue = angle.value(); |       angles.push_back(angle); | ||||||
|       angles.push_back(angleValue); |  | ||||||
| 
 | 
 | ||||||
|  |       // Buffer line with hover text
 | ||||||
|       BufferLine(di->elements_[i], |       BufferLine(di->elements_[i], | ||||||
|                  di->elements_[i + 1], |                  di->elements_[i + 1], | ||||||
|                  di->width_ + 2, |                  di->width_ + 2, | ||||||
|                  static_cast<float>(angleValue), |                  angle, | ||||||
|                  kBlack_, |                  kBlack_, | ||||||
|                  thresholdValue); |                  thresholdValue, | ||||||
|  |                  di->hoverText_); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    // For each element pair inside a Line statement, render a colored line
 |    // For each element pair inside a Line statement, render a colored line
 | ||||||
|    for (std::size_t i = 0; i < di->elements_.size() - 1; ++i) |    for (std::size_t i = 0; i < di->elements_.size() - 1; ++i) | ||||||
|    { |    { | ||||||
|       float angleValue = angles[i]; |       auto angle = angles[i]; | ||||||
| 
 | 
 | ||||||
|       BufferLine(di->elements_[i], |       BufferLine(di->elements_[i], | ||||||
|                  di->elements_[i + 1], |                  di->elements_[i + 1], | ||||||
|                  di->width_, |                  di->width_, | ||||||
|                  static_cast<float>(angleValue), |                  angle, | ||||||
|                  di->color_, |                  di->color_, | ||||||
|                  thresholdValue); |                  thresholdValue); | ||||||
|    } |    } | ||||||
|  | @ -306,9 +446,10 @@ void PlacefileLines::Impl::BufferLine( | ||||||
|    const gr::Placefile::LineDrawItem::Element& e1, |    const gr::Placefile::LineDrawItem::Element& e1, | ||||||
|    const gr::Placefile::LineDrawItem::Element& e2, |    const gr::Placefile::LineDrawItem::Element& e2, | ||||||
|    const float                                 width, |    const float                                 width, | ||||||
|    const float                                 angle, |    const units::angle::degrees<double>         angle, | ||||||
|    const boost::gil::rgba8_pixel_t             color, |    const boost::gil::rgba8_pixel_t             color, | ||||||
|    const GLint                                 threshold) |    const GLint                                 threshold, | ||||||
|  |    const std::string&                          hoverText) | ||||||
| { | { | ||||||
|    // Latitude and longitude coordinates in degrees
 |    // Latitude and longitude coordinates in degrees
 | ||||||
|    const float lat1 = static_cast<float>(e1.latitude_); |    const float lat1 = static_cast<float>(e1.latitude_); | ||||||
|  | @ -323,7 +464,7 @@ void PlacefileLines::Impl::BufferLine( | ||||||
|    // const float y2 = static_cast<float>(e2.y_);
 |    // const float y2 = static_cast<float>(e2.y_);
 | ||||||
| 
 | 
 | ||||||
|    // Angle
 |    // Angle
 | ||||||
|    const float a = angle; |    const float a = static_cast<float>(angle.value()); | ||||||
| 
 | 
 | ||||||
|    // Final X/Y offsets in pixels
 |    // Final X/Y offsets in pixels
 | ||||||
|    const float hw = width * 0.5f; |    const float hw = width * 0.5f; | ||||||
|  | @ -352,6 +493,22 @@ void PlacefileLines::Impl::BufferLine( | ||||||
|    newThresholdBuffer_.insert( |    newThresholdBuffer_.insert( | ||||||
|       newThresholdBuffer_.end(), |       newThresholdBuffer_.end(), | ||||||
|       {threshold, threshold, threshold, threshold, threshold, threshold}); |       {threshold, threshold, threshold, threshold, threshold, threshold}); | ||||||
|  | 
 | ||||||
|  |    if (!hoverText.empty()) | ||||||
|  |    { | ||||||
|  |       const units::angle::radians<double> radians = angle; | ||||||
|  | 
 | ||||||
|  |       const auto sc1 = util::maplibre::LatLongToScreenCoordinate({lat1, lon1}); | ||||||
|  |       const auto sc2 = util::maplibre::LatLongToScreenCoordinate({lat2, lon2}); | ||||||
|  | 
 | ||||||
|  |       const float cosAngle = cosf(static_cast<float>(radians.value())); | ||||||
|  |       const float sinAngle = sinf(static_cast<float>(radians.value())); | ||||||
|  | 
 | ||||||
|  |       const glm::mat2 rotate {cosAngle, -sinAngle, sinAngle, cosAngle}; | ||||||
|  | 
 | ||||||
|  |       newHoverLines_.emplace_back( | ||||||
|  |          LineHoverEntry {hoverText, sc1, sc2, rotate, width}); | ||||||
|  |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlacefileLines::Impl::Update() | void PlacefileLines::Impl::Update() | ||||||
|  |  | ||||||
|  | @ -31,6 +31,9 @@ public: | ||||||
|    void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; |    void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; | ||||||
|    void Deinitialize() override; |    void Deinitialize() override; | ||||||
| 
 | 
 | ||||||
|  |    bool RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
|  |                         const glm::vec2& mousePos) override; | ||||||
|  | 
 | ||||||
|    /**
 |    /**
 | ||||||
|     * Resets and prepares the draw item for adding a new set of lines. |     * Resets and prepares the draw item for adding a new set of lines. | ||||||
|     */ |     */ | ||||||
|  |  | ||||||
|  | @ -210,7 +210,8 @@ void PlacefileText::Deinitialize() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool PlacefileText::RunMousePicking( | bool PlacefileText::RunMousePicking( | ||||||
|    const QMapLibreGL::CustomLayerRenderParameters& /* params */) |    const QMapLibreGL::CustomLayerRenderParameters& /* params */, | ||||||
|  |    const glm::vec2& /* mousePos */) | ||||||
| { | { | ||||||
|    bool itemPicked = false; |    bool itemPicked = false; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,8 +33,8 @@ public: | ||||||
|    void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; |    void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; | ||||||
|    void Deinitialize() override; |    void Deinitialize() override; | ||||||
| 
 | 
 | ||||||
|    bool RunMousePicking( |    bool RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
|       const QMapLibreGL::CustomLayerRenderParameters& params) override; |                         const glm::vec2& mousePos) override; | ||||||
| 
 | 
 | ||||||
|    /**
 |    /**
 | ||||||
|     * Resets and prepares the draw item for adding a new set of text. |     * Resets and prepares the draw item for adding a new set of text. | ||||||
|  |  | ||||||
|  | @ -77,7 +77,8 @@ void DrawLayer::Deinitialize() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool DrawLayer::RunMousePicking( | bool DrawLayer::RunMousePicking( | ||||||
|    const QMapLibreGL::CustomLayerRenderParameters& params) |    const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
|  |    const glm::vec2&                                mousePos) | ||||||
| { | { | ||||||
|    bool itemPicked = false; |    bool itemPicked = false; | ||||||
| 
 | 
 | ||||||
|  | @ -85,7 +86,7 @@ bool DrawLayer::RunMousePicking( | ||||||
|    for (auto it = p->drawList_.rbegin(); it != p->drawList_.rend(); ++it) |    for (auto it = p->drawList_.rbegin(); it != p->drawList_.rend(); ++it) | ||||||
|    { |    { | ||||||
|       // Run mouse picking on each draw item
 |       // Run mouse picking on each draw item
 | ||||||
|       if ((*it)->RunMousePicking(params)) |       if ((*it)->RunMousePicking(params, mousePos)) | ||||||
|       { |       { | ||||||
|          // If a draw item was picked, don't process additional items
 |          // If a draw item was picked, don't process additional items
 | ||||||
|          itemPicked = true; |          itemPicked = true; | ||||||
|  |  | ||||||
|  | @ -23,8 +23,9 @@ public: | ||||||
|    Render(const QMapLibreGL::CustomLayerRenderParameters&) override; |    Render(const QMapLibreGL::CustomLayerRenderParameters&) override; | ||||||
|    virtual void Deinitialize() override; |    virtual void Deinitialize() override; | ||||||
| 
 | 
 | ||||||
|    virtual bool RunMousePicking( |    virtual bool | ||||||
|       const QMapLibreGL::CustomLayerRenderParameters& params) override; |    RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
|  |                    const glm::vec2& mousePos) override; | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|    void AddDrawItem(const std::shared_ptr<gl::draw::DrawItem>& drawItem); |    void AddDrawItem(const std::shared_ptr<gl::draw::DrawItem>& drawItem); | ||||||
|  |  | ||||||
|  | @ -27,7 +27,8 @@ GenericLayer::GenericLayer(std::shared_ptr<MapContext> context) : | ||||||
| GenericLayer::~GenericLayer() = default; | GenericLayer::~GenericLayer() = default; | ||||||
| 
 | 
 | ||||||
| bool GenericLayer::RunMousePicking( | bool GenericLayer::RunMousePicking( | ||||||
|    const QMapLibreGL::CustomLayerRenderParameters& /* params */) |    const QMapLibreGL::CustomLayerRenderParameters& /* params */, | ||||||
|  |    const glm::vec2& /* mousePos */) | ||||||
| { | { | ||||||
|    // By default, the layer has nothing to pick
 |    // By default, the layer has nothing to pick
 | ||||||
|    return false; |    return false; | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <QObject> | #include <QObject> | ||||||
| #include <QMapLibreGL/QMapLibreGL> | #include <QMapLibreGL/QMapLibreGL> | ||||||
|  | #include <glm/gtc/type_ptr.hpp> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx | ||||||
| { | { | ||||||
|  | @ -32,11 +33,13 @@ public: | ||||||
|     * @brief Run mouse picking on the layer. |     * @brief Run mouse picking on the layer. | ||||||
|     * |     * | ||||||
|     * @param [in] params Custom layer render parameters |     * @param [in] params Custom layer render parameters | ||||||
|  |     * @param [in] mousePos Mouse cursor location in map screen coordinates | ||||||
|     * |     * | ||||||
|     * @return true if a draw item was picked, otherwise false |     * @return true if a draw item was picked, otherwise false | ||||||
|     */ |     */ | ||||||
|    virtual bool |    virtual bool | ||||||
|    RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params); |    RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
|  |                    const glm::vec2&                                mousePos); | ||||||
| 
 | 
 | ||||||
| protected: | protected: | ||||||
|    std::shared_ptr<MapContext> context() const; |    std::shared_ptr<MapContext> context() const; | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ | ||||||
| #include <scwx/qt/map/radar_range_layer.hpp> | #include <scwx/qt/map/radar_range_layer.hpp> | ||||||
| #include <scwx/qt/model/imgui_context_model.hpp> | #include <scwx/qt/model/imgui_context_model.hpp> | ||||||
| #include <scwx/qt/util/file.hpp> | #include <scwx/qt/util/file.hpp> | ||||||
|  | #include <scwx/qt/util/maplibre.hpp> | ||||||
| #include <scwx/qt/view/radar_product_view_factory.hpp> | #include <scwx/qt/view/radar_product_view_factory.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
| #include <scwx/util/time.hpp> | #include <scwx/util/time.hpp> | ||||||
|  | @ -172,6 +173,7 @@ public: | ||||||
| 
 | 
 | ||||||
|    common::Level2Product selectedLevel2Product_; |    common::Level2Product selectedLevel2Product_; | ||||||
| 
 | 
 | ||||||
|  |    bool            hasMouse_ {false}; | ||||||
|    QPointF         lastPos_; |    QPointF         lastPos_; | ||||||
|    std::size_t     currentStyleIndex_; |    std::size_t     currentStyleIndex_; | ||||||
|    const MapStyle* currentStyle_; |    const MapStyle* currentStyle_; | ||||||
|  | @ -862,6 +864,16 @@ void MapWidgetImpl::AddLayer(const std::string&            id, | ||||||
|    layerList_.push_back(id); |    layerList_.push_back(id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void MapWidget::enterEvent(QEnterEvent* /* ev */) | ||||||
|  | { | ||||||
|  |    p->hasMouse_ = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MapWidget::leaveEvent(QEvent* /* ev */) | ||||||
|  | { | ||||||
|  |    p->hasMouse_ = false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void MapWidget::keyPressEvent(QKeyEvent* ev) | void MapWidget::keyPressEvent(QKeyEvent* ev) | ||||||
| { | { | ||||||
|    switch (ev->key()) |    switch (ev->key()) | ||||||
|  | @ -1024,7 +1036,10 @@ void MapWidget::paintGL() | ||||||
|    p->map_->render(); |    p->map_->render(); | ||||||
| 
 | 
 | ||||||
|    // Perform mouse picking
 |    // Perform mouse picking
 | ||||||
|  |    if (p->hasMouse_) | ||||||
|  |    { | ||||||
|       p->RunMousePicking(); |       p->RunMousePicking(); | ||||||
|  |    } | ||||||
| 
 | 
 | ||||||
|    // Render ImGui Frame
 |    // Render ImGui Frame
 | ||||||
|    ImGui::Render(); |    ImGui::Render(); | ||||||
|  | @ -1039,13 +1054,17 @@ void MapWidgetImpl::RunMousePicking() | ||||||
|    const QMapLibreGL::CustomLayerRenderParameters params = |    const QMapLibreGL::CustomLayerRenderParameters params = | ||||||
|       context_->render_parameters(); |       context_->render_parameters(); | ||||||
| 
 | 
 | ||||||
|  |    auto coordinate = map_->coordinateForPixel(lastPos_); | ||||||
|  |    auto mouseScreenCoordinate = | ||||||
|  |       util::maplibre::LatLongToScreenCoordinate(coordinate); | ||||||
|  | 
 | ||||||
|    // For each layer in reverse
 |    // For each layer in reverse
 | ||||||
|    // TODO: All Generic Layers, not just Placefile Layers
 |    // TODO: All Generic Layers, not just Placefile Layers
 | ||||||
|    for (auto it = placefileLayers_.rbegin(); it != placefileLayers_.rend(); |    for (auto it = placefileLayers_.rbegin(); it != placefileLayers_.rend(); | ||||||
|         ++it) |         ++it) | ||||||
|    { |    { | ||||||
|       // Run mouse picking for each layer
 |       // Run mouse picking for each layer
 | ||||||
|       if ((*it)->RunMousePicking(params)) |       if ((*it)->RunMousePicking(params, mouseScreenCoordinate)) | ||||||
|       { |       { | ||||||
|          // If a draw item was picked, don't process additional layers
 |          // If a draw item was picked, don't process additional layers
 | ||||||
|          break; |          break; | ||||||
|  |  | ||||||
|  | @ -119,7 +119,9 @@ private: | ||||||
|    qreal pixelRatio(); |    qreal pixelRatio(); | ||||||
| 
 | 
 | ||||||
|    // QWidget implementation.
 |    // QWidget implementation.
 | ||||||
|  |    void enterEvent(QEnterEvent* ev) override final; | ||||||
|    void keyPressEvent(QKeyEvent* ev) override final; |    void keyPressEvent(QKeyEvent* ev) override final; | ||||||
|  |    void leaveEvent(QEvent* ev) override final; | ||||||
|    void mousePressEvent(QMouseEvent* ev) override final; |    void mousePressEvent(QMouseEvent* ev) override final; | ||||||
|    void mouseMoveEvent(QMouseEvent* ev) override final; |    void mouseMoveEvent(QMouseEvent* ev) override final; | ||||||
|    void wheelEvent(QWheelEvent* ev) override final; |    void wheelEvent(QWheelEvent* ev) override final; | ||||||
|  |  | ||||||
|  | @ -20,6 +20,29 @@ GetMapDistance(const QMapLibreGL::CustomLayerRenderParameters& params) | ||||||
|       (params.width + params.height) / 2.0); |       (params.width + params.height) / 2.0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | glm::mat4 GetMapMatrix(const QMapLibreGL::CustomLayerRenderParameters& params) | ||||||
|  | { | ||||||
|  |    glm::vec2 scale = GetMapScale(params); | ||||||
|  | 
 | ||||||
|  |    glm::mat4 mapMatrix(1.0f); | ||||||
|  |    mapMatrix = glm::scale(mapMatrix, glm::vec3(scale, 1.0f)); | ||||||
|  |    mapMatrix = glm::rotate(mapMatrix, | ||||||
|  |                            glm::radians<float>(params.bearing), | ||||||
|  |                            glm::vec3(0.0f, 0.0f, 1.0f)); | ||||||
|  | 
 | ||||||
|  |    return mapMatrix; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | glm::vec2 GetMapScale(const QMapLibreGL::CustomLayerRenderParameters& params) | ||||||
|  | { | ||||||
|  |    const float scale = std::pow(2.0, params.zoom) * 2.0f * | ||||||
|  |                        mbgl::util::tileSize_D / mbgl::util::DEGREES_MAX; | ||||||
|  |    const float xScale = scale / params.width; | ||||||
|  |    const float yScale = scale / params.height; | ||||||
|  | 
 | ||||||
|  |    return glm::vec2 {xScale, yScale}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate) | glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate) | ||||||
| { | { | ||||||
|    static constexpr double RAD2DEG_D = 180.0 / M_PI; |    static constexpr double RAD2DEG_D = 180.0 / M_PI; | ||||||
|  |  | ||||||
|  | @ -15,6 +15,8 @@ namespace maplibre | ||||||
| 
 | 
 | ||||||
| units::length::meters<double> | units::length::meters<double> | ||||||
| GetMapDistance(const QMapLibreGL::CustomLayerRenderParameters& params); | GetMapDistance(const QMapLibreGL::CustomLayerRenderParameters& params); | ||||||
|  | glm::mat4 GetMapMatrix(const QMapLibreGL::CustomLayerRenderParameters& params); | ||||||
|  | glm::vec2 GetMapScale(const QMapLibreGL::CustomLayerRenderParameters& params); | ||||||
| glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate); | glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate); | ||||||
| 
 | 
 | ||||||
| } // namespace maplibre
 | } // namespace maplibre
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat