Merge pull request #153 from dpaulat/feature/maplibre-native-qt

Update MapLibre Native Qt
This commit is contained in:
Dan Paulat 2024-03-08 17:48:48 -06:00 committed by GitHub
commit 69e92848d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
96 changed files with 1236 additions and 626 deletions

View file

@ -28,7 +28,7 @@ jobs:
compiler: msvc
msvc_arch: x64
msvc_version: 2022
qt_version: 6.6.1
qt_version: 6.6.2
qt_arch: win64_msvc2019_64
qt_modules: qtimageformats qtmultimedia qtpositioning
qt_tools: ''
@ -44,7 +44,7 @@ jobs:
env_cc: gcc-11
env_cxx: g++-11
compiler: gcc
qt_version: 6.6.1
qt_version: 6.6.2
qt_arch: gcc_64
qt_modules: qtimageformats qtmultimedia qtpositioning
qt_tools: ''
@ -136,8 +136,8 @@ jobs:
objcopy --strip-debug --strip-unneeded supercell-wx
cd ..
cd lib/
objcopy --only-keep-debug libQMapLibreGL.so libQMapLibreGL.so.debug
objcopy --strip-debug --strip-unneeded libQMapLibreGL.so
objcopy --only-keep-debug libQMapLibre.so libQMapLibre.so.debug
objcopy --strip-debug --strip-unneeded libQMapLibre.so
- name: Install Supercell Wx
shell: pwsh
@ -229,4 +229,11 @@ jobs:
env:
MAPBOX_API_KEY: ${{ secrets.MAPBOX_API_KEY }}
MAPTILER_API_KEY: ${{ secrets.MAPTILER_API_KEY }}
run: ctest -C ${{ matrix.build_type }} --exclude-regex mbgl-test-runner
run: ctest -C ${{ matrix.build_type }} --exclude-regex test_mln.*
- name: Upload Test Logs
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: supercell-wx-test-logs-${{ matrix.name }}
path: ${{ github.workspace }}/build/Testing/

9
.gitmodules vendored
View file

@ -1,6 +1,3 @@
[submodule "external/mapbox-gl-native"]
path = external/mapbox-gl-native
url = https://github.com/dpaulat/maplibre-gl-native.git
[submodule "external/cmake-conan"]
path = external/cmake-conan
url = https://github.com/conan-io/cmake-conan.git
@ -34,3 +31,9 @@
[submodule "external/textflowcpp"]
path = external/textflowcpp
url = https://github.com/catchorg/textflowcpp.git
[submodule "external/maplibre-native-qt"]
path = external/maplibre-native-qt
url = https://github.com/dpaulat/maplibre-native-qt.git
[submodule "external/maplibre-native"]
path = external/maplibre-native
url = https://github.com/dpaulat/maplibre-gl-native.git

View file

@ -67,6 +67,7 @@ Supercell Wx uses assets from the following sources:
| [Font Awesome Free](https://fontawesome.com/) | CC BY 4.0 License |
| [Inconsolata](https://fonts.google.com/specimen/Inconsolata) | SIL Open Font License |
| [NOAA's Weather and Climate Toolkit](https://www.ncdc.noaa.gov/wct/) | Public Domain | Default Color Tables |
| [Roboto Flex](https://fonts.google.com/specimen/Roboto+Flex) | SIL Open Font License |
| [Supercell thunderstorm with dramatic clouds](https://www.shutterstock.com/image-photo/supercell-thunderstorm-dramatic-clouds-1354353521) | Shutterstock Standard License | Photo by John Sirlin
Services

View file

@ -48,3 +48,5 @@ add_subdirectory(external)
add_subdirectory(wxdata)
add_subdirectory(scwx-qt)
add_subdirectory(test)
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER CMakePredefinedTargets)

View file

@ -8,7 +8,7 @@ set_property(DIRECTORY
date.cmake
hsluv-c.cmake
imgui.cmake
mapbox-gl-native.cmake
maplibre-native-qt.cmake
stb.cmake
textflowcpp.cmake
units.cmake)
@ -17,7 +17,7 @@ include(aws-sdk-cpp.cmake)
include(date.cmake)
include(hsluv-c.cmake)
include(imgui.cmake)
include(mapbox-gl-native.cmake)
include(maplibre-native-qt.cmake)
include(stb.cmake)
include(textflowcpp.cmake)
include(units.cmake)

@ -1 +0,0 @@
Subproject commit 3e85454fe5e571e7b235131912bb867ef9d75c3c

View file

@ -1,48 +0,0 @@
cmake_minimum_required(VERSION 3.20)
set(PROJECT_NAME scwx-mbgl)
set(gtest_disable_pthreads ON)
set(MLN_WITH_QT ON)
set(MLN_QT_WITH_INTERNAL_ICU ON)
add_subdirectory(mapbox-gl-native)
find_package(ZLIB)
target_include_directories(mbgl-core PRIVATE ${ZLIB_INCLUDE_DIRS})
target_link_libraries(mbgl-core INTERFACE ${ZLIB_LIBRARIES})
if (MSVC)
# Produce PDB file for debug
target_compile_options(mbgl-core PRIVATE "$<$<CONFIG:Release>:/Zi>")
target_compile_options(qmaplibregl PRIVATE "$<$<CONFIG:Release>:/Zi>")
target_link_options(qmaplibregl PRIVATE "$<$<CONFIG:Release>:/DEBUG>")
target_link_options(qmaplibregl PRIVATE "$<$<CONFIG:Release>:/OPT:REF>")
target_link_options(qmaplibregl PRIVATE "$<$<CONFIG:Release>:/OPT:ICF>")
else()
target_compile_options(mbgl-core PRIVATE "$<$<CONFIG:Release>:-g>")
target_compile_options(qmaplibregl PRIVATE "$<$<CONFIG:Release>:-g>")
endif()
set(MBGL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mapbox-gl-native/include
${CMAKE_CURRENT_SOURCE_DIR}/mapbox-gl-native/platform/qt/include PARENT_SCOPE)
set_target_properties(mbgl-qt PROPERTIES EXCLUDE_FROM_ALL True)
set_target_properties(mbgl-test-runner PROPERTIES EXCLUDE_FROM_ALL True)
set_target_properties(mbgl-benchmark PROPERTIES FOLDER mbgl/exclude)
set_target_properties(mbgl-render-test PROPERTIES FOLDER mbgl/exclude)
set_target_properties(mbgl-test PROPERTIES FOLDER mbgl/exclude)
set_target_properties(mbgl-vendor-benchmark PROPERTIES FOLDER mbgl/exclude)
set_target_properties(mbgl-vendor-googletest PROPERTIES FOLDER mbgl/exclude)
set_target_properties(mbgl-core-license PROPERTIES FOLDER mbgl/exclude)
set_target_properties(mbgl-qt PROPERTIES FOLDER mbgl/exclude)
set_target_properties(mbgl-test-runner PROPERTIES FOLDER mbgl/exclude)
if (TARGET mbgl-qt-docs)
set_target_properties(mbgl-qt-docs PROPERTIES FOLDER mbgl/exclude)
endif()
set_target_properties(mbgl-core PROPERTIES FOLDER mbgl)
set_target_properties(mbgl-vendor-csscolorparser PROPERTIES FOLDER mbgl)
set_target_properties(mbgl-vendor-nunicode PROPERTIES FOLDER mbgl)
set_target_properties(mbgl-vendor-parsedate PROPERTIES FOLDER mbgl)
set_target_properties(qmaplibregl PROPERTIES FOLDER mbgl)

1
external/maplibre-native vendored Submodule

@ -0,0 +1 @@
Subproject commit 6932d9b49cf01ac75b79aff9f9a9f0f9ce97a9ae

1
external/maplibre-native-qt vendored Submodule

@ -0,0 +1 @@
Subproject commit fe734916414ce761e053dafaeecafeb19d51509c

47
external/maplibre-native-qt.cmake vendored Normal file
View file

@ -0,0 +1,47 @@
cmake_minimum_required(VERSION 3.20)
set(PROJECT_NAME scwx-mln)
set(gtest_disable_pthreads ON)
set(MLN_WITH_QT ON)
set(MLN_QT_WITH_INTERNAL_ICU ON)
set(MLN_QT_WITH_LOCATION OFF)
set(MLN_CORE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native)
add_subdirectory(maplibre-native-qt)
find_package(ZLIB)
target_include_directories(mbgl-core PRIVATE ${ZLIB_INCLUDE_DIRS})
target_link_libraries(mbgl-core INTERFACE ${ZLIB_LIBRARIES})
if (MSVC)
# Produce PDB file for debug
target_compile_options(mbgl-core PRIVATE "$<$<CONFIG:Release>:/Zi>")
target_compile_options(Core PRIVATE "$<$<CONFIG:Release>:/Zi>")
target_link_options(Core PRIVATE "$<$<CONFIG:Release>:/DEBUG>")
target_link_options(Core PRIVATE "$<$<CONFIG:Release>:/OPT:REF>")
target_link_options(Core PRIVATE "$<$<CONFIG:Release>:/OPT:ICF>")
else()
target_compile_options(mbgl-core PRIVATE "$<$<CONFIG:Release>:-g>")
target_compile_options(Core PRIVATE "$<$<CONFIG:Release>:-g>")
endif()
set(MLN_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native/include
${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native-qt/src/core/include
${CMAKE_CURRENT_BINARY_DIR}/maplibre-native-qt/src/core/include PARENT_SCOPE)
set_target_properties(test_mln_core PROPERTIES EXCLUDE_FROM_ALL True)
set_target_properties(test_mln_widgets PROPERTIES EXCLUDE_FROM_ALL True)
set_target_properties(Widgets PROPERTIES EXCLUDE_FROM_ALL True)
set_target_properties(test_mln_core PROPERTIES FOLDER mln/exclude)
set_target_properties(test_mln_widgets PROPERTIES FOLDER mln/exclude)
set_target_properties(Widgets PROPERTIES FOLDER mln/exclude)
set_target_properties(Core PROPERTIES FOLDER mln)
set_target_properties(mbgl-core PROPERTIES FOLDER mln)
set_target_properties(mbgl-vendor-csscolorparser PROPERTIES FOLDER mln)
set_target_properties(mbgl-vendor-nunicode PROPERTIES FOLDER mln)
set_target_properties(mbgl-vendor-parsedate PROPERTIES FOLDER mln)
if (TARGET mbgl-vendor-sqlite)
set_target_properties(mbgl-vendor-sqlite PROPERTIES FOLDER mln)
endif()

View file

@ -25,6 +25,7 @@ out VertexData
vec3 texCoord;
vec4 color;
ivec2 timeRange;
bool displayed;
} vsOut;
smooth out vec3 texCoord;
@ -41,6 +42,9 @@ vec2 latLngToScreenCoordinate(in vec2 latLng)
void main()
{
// Always set displayed to true
vsOut.displayed = true;
// Pass the threshold and time range to the geometry shader
vsOut.threshold = aThreshold;
vsOut.timeRange = aTimeRange;

View file

@ -16,12 +16,16 @@ out VertexData
vec3 texCoord;
vec4 color;
ivec2 timeRange;
bool displayed;
} vsOut;
smooth out vec4 color;
void main()
{
// Always set displayed to true
vsOut.displayed = true;
// Pass the threshold and time range to the geometry shader
vsOut.threshold = aThreshold;
vsOut.timeRange = aTimeRange;

View file

@ -7,20 +7,42 @@ layout (location = 1) in vec2 aXYOffset;
layout (location = 2) in vec3 aTexCoord;
layout (location = 3) in vec4 aModulate;
layout (location = 4) in float aAngleDeg;
layout (location = 5) in int aDisplayed;
uniform mat4 uMVPMatrix;
out VertexData
{
int threshold;
vec3 texCoord;
vec4 color;
ivec2 timeRange;
bool displayed;
} vsOut;
smooth out vec3 texCoord;
smooth out vec4 color;
void main()
{
// Always set threshold and time range to zero
vsOut.threshold = 0;
vsOut.timeRange = ivec2(0, 0);
// Pass displayed to the geometry shader
vsOut.displayed = (aDisplayed != 0);
// Pass the texture coordinate and color modulate to the geometry and
// fragment shaders
vsOut.texCoord = aTexCoord;
vsOut.color = aModulate;
texCoord = aTexCoord;
color = aModulate;
// Rotate clockwise
float angle = aAngleDeg * DEG2RAD;
mat2 rotate = mat2(cos(angle), -sin(angle),
sin(angle), cos(angle));
gl_Position = uMVPMatrix * vec4(aVertex + rotate * aXYOffset, 0.0f, 1.0f);
texCoord = aTexCoord;
color = aModulate;
}

View file

@ -12,6 +12,7 @@ in VertexData
vec3 texCoord;
vec4 color;
ivec2 timeRange;
bool displayed;
} gsIn[];
smooth out vec3 texCoord;
@ -19,7 +20,8 @@ smooth out vec4 color;
void main()
{
if ((gsIn[0].threshold <= 0 || // If Threshold: 0 was specified, no threshold
if (gsIn[0].displayed &&
(gsIn[0].threshold <= 0 || // If Threshold: 0 was specified, no threshold
gsIn[0].threshold >= uMapDistance || // If Threshold is above current map distance
gsIn[0].threshold >= 999) && // If Threshold: 999 was specified (or greater), no threshold
(gsIn[0].timeRange[0] == 0 || // If there is no start time specified

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -28,6 +28,7 @@ find_package(QT NAMES Qt6
OpenGL
OpenGLWidgets
Positioning
Svg
Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR}
@ -38,6 +39,7 @@ find_package(Qt${QT_VERSION_MAJOR}
OpenGL
OpenGLWidgets
Positioning
Svg
Widgets
REQUIRED)
@ -470,7 +472,10 @@ set_target_properties(release_translations PROPERTIES FOLDER qt)
set_target_properties(scwx-qt_lrelease PROPERTIES FOLDER qt)
set_target_properties(scwx-qt_lupdate PROPERTIES FOLDER qt)
set_target_properties(scwx-qt_other_files PROPERTIES FOLDER qt)
set_target_properties(update_translations PROPERTIES FOLDER qt)
if (TARGET update_translations)
set_target_properties(update_translations PROPERTIES FOLDER qt)
endif()
set_target_properties(scwx-qt_generate_counties_db PROPERTIES FOLDER generate)
set_target_properties(scwx-qt_generate_versions PROPERTIES FOLDER generate)
@ -496,7 +501,7 @@ endif()
target_include_directories(scwx-qt PUBLIC ${scwx-qt_SOURCE_DIR}/source
${FTGL_INCLUDE_DIR}
${IMGUI_INCLUDE_DIRS}
${MBGL_INCLUDE_DIR}
${MLN_INCLUDE_DIRS}
${STB_INCLUDE_DIR}
${TEXTFLOWCPP_INCLUDE_DIR})
@ -552,9 +557,10 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::OpenGLWidgets
Qt${QT_VERSION_MAJOR}::Multimedia
Qt${QT_VERSION_MAJOR}::Positioning
Qt${QT_VERSION_MAJOR}::Svg
Boost::json
Boost::timer
qmaplibregl
QMapLibre::Core
$<$<CXX_COMPILER_ID:MSVC>:opengl32>
Fontconfig::Fontconfig
GeographicLib::GeographicLib
@ -570,11 +576,11 @@ target_link_libraries(supercell-wx PRIVATE scwx-qt
wxdata)
# Set DT_RUNPATH for Linux targets
set_target_properties(qmaplibregl PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib")
set_target_properties(Core PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") # QMapLibre::Core
set_target_properties(supercell-wx PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib")
install(TARGETS supercell-wx
qmaplibregl
Core # QMapLibre::Core
RUNTIME_DEPENDENCIES
PRE_EXCLUDE_REGEXES "api-ms-" "ext-ms-" "qt6"
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
@ -587,8 +593,8 @@ install(TARGETS supercell-wx
# NO_TRANSLATIONS is needed for Qt 6.5.0 (will be fixed in 6.5.1)
# https://bugreports.qt.io/browse/QTBUG-112204
qt_generate_deploy_app_script(TARGET qmaplibregl
OUTPUT_SCRIPT deploy_script_qmaplibregl
qt_generate_deploy_app_script(TARGET Core # QMapLibre::Core
OUTPUT_SCRIPT deploy_script_qmaplibre_core
NO_TRANSLATIONS
NO_UNSUPPORTED_PLATFORM_ERROR)
@ -597,7 +603,7 @@ qt_generate_deploy_app_script(TARGET supercell-wx
NO_TRANSLATIONS
NO_UNSUPPORTED_PLATFORM_ERROR)
install(SCRIPT ${deploy_script_qmaplibregl}
install(SCRIPT ${deploy_script_qmaplibre_core}
COMPONENT supercell-wx)
install(SCRIPT ${deploy_script_scwx}

View file

@ -18,6 +18,7 @@
<file>res/fonts/din1451alt.ttf</file>
<file>res/fonts/din1451alt_g.ttf</file>
<file>res/fonts/Inconsolata-Regular.ttf</file>
<file>res/fonts/RobotoFlex-Regular.ttf</file>
<file>res/icons/scwx-64.png</file>
<file>res/icons/scwx-256.ico</file>
<file>res/icons/scwx-256.png</file>
@ -69,5 +70,7 @@
<file>res/textures/lines/default-1x7.png</file>
<file>res/textures/lines/test-pattern.png</file>
<file>res/textures/images/crosshairs-24.png</file>
<file>res/textures/images/mapbox-logo.svg</file>
<file>res/textures/images/maptiler-logo.svg</file>
</qresource>
</RCC>

View file

@ -43,18 +43,18 @@ DrawItem::DrawItem(DrawItem&&) noexcept = default;
DrawItem& DrawItem::operator=(DrawItem&&) noexcept = default;
void DrawItem::Render(
const QMapLibreGL::CustomLayerRenderParameters& /* params */)
const QMapLibre::CustomLayerRenderParameters& /* params */)
{
}
void DrawItem::Render(const QMapLibreGL::CustomLayerRenderParameters& params,
void DrawItem::Render(const QMapLibre::CustomLayerRenderParameters& params,
bool /* textureAtlasChanged */)
{
Render(params);
}
bool DrawItem::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& /* params */,
const QMapLibre::CustomLayerRenderParameters& /* params */,
const QPointF& /* mouseLocalPos */,
const QPointF& /* mouseGlobalPos */,
const glm::vec2& /* mouseCoords */,
@ -66,8 +66,8 @@ bool DrawItem::RunMousePicking(
}
void DrawItem::UseDefaultProjection(
const QMapLibreGL::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation)
const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation)
{
glm::mat4 projection = glm::ortho(0.0f,
static_cast<float>(params.width),
@ -79,8 +79,8 @@ void DrawItem::UseDefaultProjection(
}
void DrawItem::UseRotationProjection(
const QMapLibreGL::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation)
const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation)
{
glm::mat4 projection = glm::ortho(0.0f,
static_cast<float>(params.width),
@ -96,9 +96,9 @@ void DrawItem::UseRotationProjection(
}
void DrawItem::UseMapProjection(
const QMapLibreGL::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation,
GLint uMapScreenCoordLocation)
const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation,
GLint uMapScreenCoordLocation)
{
OpenGLFunctions& gl = p->gl_;

View file

@ -6,8 +6,8 @@
#include <memory>
#include <QMapLibreGL/QMapLibreGL>
#include <glm/gtc/type_ptr.hpp>
#include <qmaplibre.hpp>
namespace scwx
{
@ -31,8 +31,8 @@ public:
DrawItem& operator=(DrawItem&&) noexcept;
virtual void Initialize() = 0;
virtual void Render(const QMapLibreGL::CustomLayerRenderParameters& params);
virtual void Render(const QMapLibreGL::CustomLayerRenderParameters& params,
virtual void Render(const QMapLibre::CustomLayerRenderParameters& params);
virtual void Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged);
virtual void Deinitialize() = 0;
@ -49,21 +49,21 @@ public:
* @return true if the draw item was picked, otherwise false
*/
virtual bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler);
RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler);
protected:
void
UseDefaultProjection(const QMapLibreGL::CustomLayerRenderParameters& params,
UseDefaultProjection(const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation);
void
UseRotationProjection(const QMapLibreGL::CustomLayerRenderParameters& params,
UseRotationProjection(const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation);
void UseMapProjection(const QMapLibreGL::CustomLayerRenderParameters& params,
void UseMapProjection(const QMapLibre::CustomLayerRenderParameters& params,
GLint uMVPMatrixLocation,
GLint uMapScreenCoordLocation);

View file

@ -243,7 +243,7 @@ void GeoIcons::Initialize()
p->dirty_ = true;
}
void GeoIcons::Render(const QMapLibreGL::CustomLayerRenderParameters& params,
void GeoIcons::Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged)
{
if (!p->visible_)
@ -732,7 +732,7 @@ void GeoIcons::Impl::Update(bool textureAtlasChanged)
}
bool GeoIcons::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,

View file

@ -33,16 +33,16 @@ public:
void set_thresholded(bool thresholded);
void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params,
void Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) override;
void Deinitialize() override;
bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override;
/**

View file

@ -218,7 +218,7 @@ void GeoLines::Initialize()
p->dirty_ = true;
}
void GeoLines::Render(const QMapLibreGL::CustomLayerRenderParameters& params)
void GeoLines::Render(const QMapLibre::CustomLayerRenderParameters& params)
{
if (!p->visible_)
{
@ -513,7 +513,7 @@ void GeoLines::Impl::Update()
}
bool GeoLines::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,

View file

@ -32,15 +32,15 @@ public:
void set_thresholded(bool thresholded);
void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override;
void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override;
bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override;
/**

View file

@ -1,5 +1,4 @@
#include <scwx/qt/gl/draw/icons.hpp>
#include <scwx/qt/types/icon_types.hpp>
#include <scwx/qt/util/maplibre.hpp>
#include <scwx/qt/util/texture_atlas.hpp>
#include <scwx/qt/util/tooltip.hpp>
@ -8,6 +7,7 @@
#include <execution>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/unordered_flat_set.hpp>
namespace scwx
{
@ -25,7 +25,7 @@ static constexpr std::size_t kNumRectangles = 1;
static constexpr std::size_t kNumTriangles = kNumRectangles * 2;
static constexpr std::size_t kVerticesPerTriangle = 3;
static constexpr std::size_t kVerticesPerRectangle = kVerticesPerTriangle * 2;
static constexpr std::size_t kPointsPerVertex = 9;
static constexpr std::size_t kPointsPerVertex = 10;
static constexpr std::size_t kPointsPerTexCoord = 3;
static constexpr std::size_t kIconBufferLength =
kNumTriangles * kVerticesPerTriangle * kPointsPerVertex;
@ -35,12 +35,15 @@ static constexpr std::size_t kTextureBufferLength =
struct IconDrawItem : types::EventHandler
{
boost::gil::rgba32f_pixel_t modulate_ {1.0f, 1.0f, 1.0f, 1.0f};
bool visible_ {true};
double x_ {};
double y_ {};
units::degrees<double> angle_ {};
std::string iconSheet_ {};
std::size_t iconIndex_ {};
std::string hoverText_ {};
std::shared_ptr<types::IconInfo> iconInfo_ {};
};
class Icons::Impl
@ -68,9 +71,14 @@ public:
~Impl() {}
void UpdateBuffers();
void UpdateTextureBuffer();
void Update(bool textureAtlasChanged);
void UpdateBuffers();
static void UpdateSingleBuffer(const std::shared_ptr<IconDrawItem>& di,
std::size_t iconIndex,
std::vector<float>& iconBuffer,
std::vector<IconHoverEntry>& hoverIcons);
void UpdateTextureBuffer();
void UpdateModifiedIconBuffers();
void Update(bool textureAtlasChanged);
std::shared_ptr<GlContext> context_;
@ -78,11 +86,14 @@ public:
bool dirty_ {false};
bool lastTextureAtlasChanged_ {false};
boost::unordered_flat_set<std::shared_ptr<IconDrawItem>> dirtyIcons_ {};
std::mutex iconMutex_;
boost::unordered_flat_map<std::string, types::IconInfo>
boost::unordered_flat_map<std::string, std::shared_ptr<types::IconInfo>>
currentIconSheets_ {};
boost::unordered_flat_map<std::string, types::IconInfo> newIconSheets_ {};
boost::unordered_flat_map<std::string, std::shared_ptr<types::IconInfo>>
newIconSheets_ {};
std::vector<std::shared_ptr<IconDrawItem>> currentIconList_ {};
std::vector<std::shared_ptr<IconDrawItem>> newIconList_ {};
@ -120,6 +131,7 @@ void Icons::Initialize()
p->shaderProgram_ = p->context_->GetShaderProgram(
{{GL_VERTEX_SHADER, ":/gl/texture2d_array.vert"},
{GL_GEOMETRY_SHADER, ":/gl/threshold.geom"},
{GL_FRAGMENT_SHADER, ":/gl/texture2d_array.frag"}});
p->uMVPMatrixLocation_ = p->shaderProgram_->GetUniformLocation("uMVPMatrix");
@ -167,6 +179,15 @@ void Icons::Initialize()
reinterpret_cast<void*>(8 * sizeof(float)));
gl.glEnableVertexAttribArray(4);
// aAngle
gl.glVertexAttribPointer(5,
1,
GL_FLOAT,
GL_FALSE,
kPointsPerVertex * sizeof(float),
reinterpret_cast<void*>(9 * sizeof(float)));
gl.glEnableVertexAttribArray(5);
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]);
gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW);
@ -182,7 +203,7 @@ void Icons::Initialize()
p->dirty_ = true;
}
void Icons::Render(const QMapLibreGL::CustomLayerRenderParameters& params,
void Icons::Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged)
{
if (!p->visible_)
@ -243,17 +264,19 @@ void Icons::StartIconSheets()
p->newIconSheets_.clear();
}
void Icons::AddIconSheet(const std::string& name,
std::size_t iconWidth,
std::size_t iconHeight,
std::int32_t hotX,
std::int32_t hotY)
std::shared_ptr<types::IconInfo> Icons::AddIconSheet(const std::string& name,
std::size_t iconWidth,
std::size_t iconHeight,
std::int32_t hotX,
std::int32_t hotY)
{
// Populate icon sheet map
p->newIconSheets_.emplace(std::piecewise_construct,
std::tuple {name},
std::forward_as_tuple(types::IconInfo {
name, iconWidth, iconHeight, hotX, hotY}));
return p->newIconSheets_
.emplace(std::piecewise_construct,
std::tuple {name},
std::forward_as_tuple(std::make_shared<types::IconInfo>(
name, iconWidth, iconHeight, hotX, hotY)))
.first->second;
}
void Icons::FinishIconSheets()
@ -261,7 +284,7 @@ void Icons::FinishIconSheets()
// Update icon sheets
for (auto& iconSheet : p->newIconSheets_)
{
iconSheet.second.UpdateTextureInfo();
iconSheet.second->UpdateTextureInfo();
}
std::unique_lock lock {p->iconMutex_};
@ -290,12 +313,20 @@ std::shared_ptr<IconDrawItem> Icons::AddIcon()
return p->newIconList_.emplace_back(std::make_shared<IconDrawItem>());
}
void Icons::SetIconVisible(const std::shared_ptr<IconDrawItem>& di,
bool visible)
{
di->visible_ = visible;
p->dirtyIcons_.insert(di);
}
void Icons::SetIconTexture(const std::shared_ptr<IconDrawItem>& di,
const std::string& iconSheet,
std::size_t iconIndex)
{
di->iconSheet_ = iconSheet;
di->iconIndex_ = iconIndex;
p->dirtyIcons_.insert(di);
}
void Icons::SetIconLocation(const std::shared_ptr<IconDrawItem>& di,
@ -304,12 +335,14 @@ void Icons::SetIconLocation(const std::shared_ptr<IconDrawItem>& di,
{
di->x_ = x;
di->y_ = y;
p->dirtyIcons_.insert(di);
}
void Icons::SetIconAngle(const std::shared_ptr<IconDrawItem>& di,
units::angle::degrees<double> angle)
{
di->angle_ = angle;
p->dirtyIcons_.insert(di);
}
void Icons::SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
@ -319,18 +352,21 @@ void Icons::SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
modulate[1] / 255.0f,
modulate[2] / 255.0f,
modulate[3] / 255.0f};
p->dirtyIcons_.insert(di);
}
void Icons::SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
boost::gil::rgba32f_pixel_t modulate)
{
di->modulate_ = modulate;
p->dirtyIcons_.insert(di);
}
void Icons::SetIconHoverText(const std::shared_ptr<IconDrawItem>& di,
const std::string& text)
{
di->hoverText_ = text;
p->dirtyIcons_.insert(di);
}
void Icons::FinishIcons()
@ -372,10 +408,11 @@ void Icons::Impl::UpdateBuffers()
continue;
}
auto& icon = it->second;
auto& icon = it->second;
di->iconInfo_ = icon;
// Validate icon
if (di->iconIndex_ >= icon.numIcons_)
if (di->iconIndex_ >= icon->numIcons_)
{
// No icon found
logger_->warn("Invalid icon index: {}", di->iconIndex_);
@ -385,61 +422,115 @@ void Icons::Impl::UpdateBuffers()
// Icon is valid, add to valid icon list
newValidIconList_.push_back(di);
// Base X/Y offsets in pixels
const float x = static_cast<float>(di->x_);
const float y = static_cast<float>(di->y_);
// Update icon buffer
UpdateSingleBuffer(
di, newValidIconList_.size() - 1, newIconBuffer_, newHoverIcons_);
}
// Icon size
const float iw = static_cast<float>(icon.iconWidth_);
const float ih = static_cast<float>(icon.iconHeight_);
// All icons have been updated
dirtyIcons_.clear();
}
// Hot X/Y (zero-based icon center)
const float hx = static_cast<float>(icon.hotX_);
const float hy = static_cast<float>(icon.hotY_);
void Icons::Impl::UpdateSingleBuffer(const std::shared_ptr<IconDrawItem>& di,
std::size_t iconIndex,
std::vector<float>& iconBuffer,
std::vector<IconHoverEntry>& hoverIcons)
{
auto& icon = di->iconInfo_;
// Final X/Y offsets in pixels
const float lx = std::roundf(-hx);
const float rx = std::roundf(lx + iw);
const float ty = std::roundf(+hy);
const float by = std::roundf(ty - ih);
// Base X/Y offsets in pixels
const float x = static_cast<float>(di->x_);
const float y = static_cast<float>(di->y_);
// Angle in degrees
units::angle::degrees<float> angle = di->angle_;
const float a = angle.value();
// Icon size
const float iw = static_cast<float>(icon->iconWidth_);
const float ih = static_cast<float>(icon->iconHeight_);
// Modulate color
const float mc0 = di->modulate_[0];
const float mc1 = di->modulate_[1];
const float mc2 = di->modulate_[2];
const float mc3 = di->modulate_[3];
// Hot X/Y (zero-based icon center)
const float hx = static_cast<float>(icon->hotX_);
const float hy = static_cast<float>(icon->hotY_);
newIconBuffer_.insert(newIconBuffer_.end(),
{
// Icon
x, y, lx, by, mc0, mc1, mc2, mc3, a, // BL
x, y, lx, ty, mc0, mc1, mc2, mc3, a, // TL
x, y, rx, by, mc0, mc1, mc2, mc3, a, // BR
x, y, rx, by, mc0, mc1, mc2, mc3, a, // BR
x, y, rx, ty, mc0, mc1, mc2, mc3, a, // TR
x, y, lx, ty, mc0, mc1, mc2, mc3, a // TL
});
// Final X/Y offsets in pixels
const float lx = std::roundf(-hx);
const float rx = std::roundf(lx + iw);
const float ty = std::roundf(+hy);
const float by = std::roundf(ty - ih);
if (!di->hoverText_.empty() || di->event_ != nullptr)
// Angle in degrees
units::angle::degrees<float> angle = di->angle_;
const float a = angle.value();
// Modulate color
const float mc0 = di->modulate_[0];
const float mc1 = di->modulate_[1];
const float mc2 = di->modulate_[2];
const float mc3 = di->modulate_[3];
// Visibility
const float v = static_cast<float>(di->visible_);
// Icon initializer list data
const auto iconData = {
// Icon
x, y, lx, by, mc0, mc1, mc2, mc3, a, v, // BL
x, y, lx, ty, mc0, mc1, mc2, mc3, a, v, // TL
x, y, rx, by, mc0, mc1, mc2, mc3, a, v, // BR
x, y, rx, by, mc0, mc1, mc2, mc3, a, v, // BR
x, y, rx, ty, mc0, mc1, mc2, mc3, a, v, // TR
x, y, lx, ty, mc0, mc1, mc2, mc3, a, v // TL
};
// Buffer position data
auto iconBufferPosition = iconBuffer.end();
auto iconBufferOffset = iconIndex * kIconBufferLength;
if (iconBufferOffset < iconBuffer.size())
{
iconBufferPosition = iconBuffer.begin() + iconBufferOffset;
}
if (iconBufferPosition == iconBuffer.cend())
{
iconBuffer.insert(iconBufferPosition, iconData);
}
else
{
std::copy(iconData.begin(), iconData.end(), iconBufferPosition);
}
auto hoverIt = std::find_if(hoverIcons.begin(),
hoverIcons.end(),
[&di](auto& entry) { return entry.di_ == di; });
if (di->visible_ && (!di->hoverText_.empty() || di->event_ != nullptr))
{
const units::angle::radians<double> radians = angle;
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};
const glm::vec2 otl = rotate * glm::vec2 {lx, ty};
const glm::vec2 otr = rotate * glm::vec2 {rx, ty};
const glm::vec2 obl = rotate * glm::vec2 {lx, by};
const glm::vec2 obr = rotate * glm::vec2 {rx, by};
if (hoverIt == hoverIcons.end())
{
const units::angle::radians<double> radians = angle;
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};
const glm::vec2 otl = rotate * glm::vec2 {lx, ty};
const glm::vec2 otr = rotate * glm::vec2 {rx, ty};
const glm::vec2 obl = rotate * glm::vec2 {lx, by};
const glm::vec2 obr = rotate * glm::vec2 {rx, by};
newHoverIcons_.emplace_back(IconHoverEntry {di, otl, otr, obl, obr});
hoverIcons.emplace_back(IconHoverEntry {di, otl, otr, obl, obr});
}
else
{
hoverIt->otl_ = otl;
hoverIt->otr_ = otr;
hoverIt->obl_ = obl;
hoverIt->obr_ = obr;
}
}
else if (hoverIt != hoverIcons.end())
{
hoverIcons.erase(hoverIt);
}
}
@ -477,7 +568,7 @@ void Icons::Impl::UpdateTextureBuffer()
auto& icon = it->second;
// Validate icon
if (di->iconIndex_ >= icon.numIcons_)
if (di->iconIndex_ >= icon->numIcons_)
{
// No icon found
logger_->error("Invalid icon index: {}", di->iconIndex_);
@ -503,17 +594,17 @@ void Icons::Impl::UpdateTextureBuffer()
}
// Texture coordinates
const std::size_t iconRow = (di->iconIndex_) / icon.columns_;
const std::size_t iconColumn = (di->iconIndex_) % icon.columns_;
const std::size_t iconRow = (di->iconIndex_) / icon->columns_;
const std::size_t iconColumn = (di->iconIndex_) % icon->columns_;
const float iconX = iconColumn * icon.scaledWidth_;
const float iconY = iconRow * icon.scaledHeight_;
const float iconX = iconColumn * icon->scaledWidth_;
const float iconY = iconRow * icon->scaledHeight_;
const float ls = icon.texture_.sLeft_ + iconX;
const float rs = ls + icon.scaledWidth_;
const float tt = icon.texture_.tTop_ + iconY;
const float bt = tt + icon.scaledHeight_;
const float r = static_cast<float>(icon.texture_.layerId_);
const float ls = icon->texture_.sLeft_ + iconX;
const float rs = ls + icon->scaledWidth_;
const float tt = icon->texture_.tTop_ + iconY;
const float bt = tt + icon->scaledHeight_;
const float r = static_cast<float>(icon->texture_.layerId_);
// clang-format off
textureBuffer_.insert(
@ -531,17 +622,47 @@ void Icons::Impl::UpdateTextureBuffer()
}
}
void Icons::Impl::UpdateModifiedIconBuffers()
{
// Update buffers for modified icons
for (auto& di : dirtyIcons_)
{
// Find modified icon in the current list
auto it =
std::find(currentIconList_.cbegin(), currentIconList_.cend(), di);
// Ignore invalid icons
if (it == currentIconList_.cend())
{
continue;
}
auto iconIndex = std::distance(currentIconList_.cbegin(), it);
UpdateSingleBuffer(di, iconIndex, currentIconBuffer_, currentHoverIcons_);
}
// Clear list of modified icons
if (!dirtyIcons_.empty())
{
dirtyIcons_.clear();
dirty_ = true;
}
}
void Icons::Impl::Update(bool textureAtlasChanged)
{
gl::OpenGLFunctions& gl = context_->gl();
UpdateModifiedIconBuffers();
// If the texture atlas has changed
if (dirty_ || textureAtlasChanged || lastTextureAtlasChanged_)
{
// Update texture coordinates
for (auto& iconSheet : currentIconSheets_)
{
iconSheet.second.UpdateTextureInfo();
iconSheet.second->UpdateTextureInfo();
}
// Update OpenGL texture buffer data
@ -575,9 +696,9 @@ void Icons::Impl::Update(bool textureAtlasChanged)
}
bool Icons::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& /* mouseCoords */,
const common::Coordinate& /* mouseGeoCoords */,
std::shared_ptr<types::EventHandler>& eventHandler)

View file

@ -2,6 +2,7 @@
#include <scwx/qt/gl/gl_context.hpp>
#include <scwx/qt/gl/draw/draw_item.hpp>
#include <scwx/qt/types/icon_types.hpp>
#include <boost/gil.hpp>
#include <units/angle.h>
@ -32,16 +33,16 @@ public:
Icons& operator=(Icons&&) noexcept;
void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params,
void Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) override;
void Deinitialize() override;
bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override;
/**
@ -69,12 +70,14 @@ public:
* Default is -1 to center the icon.
* @param [in] hotY The zero-based center of the each icon in the icon sheet.
* Default is -1 to center the icon.
*
* @return Icon info
*/
void AddIconSheet(const std::string& name,
std::size_t iconWidth = 0,
std::size_t iconHeight = 0,
std::int32_t hotX = -1,
std::int32_t hotY = -1);
std::shared_ptr<types::IconInfo> AddIconSheet(const std::string& name,
std::size_t iconWidth = 0,
std::size_t iconHeight = 0,
std::int32_t hotX = -1,
std::int32_t hotY = -1);
/**
* Resets and prepares the draw item for adding a new set of icon sheets.
@ -93,6 +96,12 @@ public:
*/
std::shared_ptr<IconDrawItem> AddIcon();
/**
* @param [in] di Icon draw item
* @param [in] visible Visibility of the icon
*/
void SetIconVisible(const std::shared_ptr<IconDrawItem>& di, bool visible);
/**
* Sets the texture of an icon.
*
@ -100,9 +109,9 @@ public:
* @param [in] iconSheet The name of the icon sheet in the texture atlas
* @param [in] iconIndex The zero-based index of the icon in the icon sheet
*/
static void SetIconTexture(const std::shared_ptr<IconDrawItem>& di,
const std::string& iconSheet,
std::size_t iconIndex);
void SetIconTexture(const std::shared_ptr<IconDrawItem>& di,
const std::string& iconSheet,
std::size_t iconIndex);
/**
* Sets the location of an icon.
@ -111,7 +120,7 @@ public:
* @param [in] x The x location of the icon in pixels.
* @param [in] y The y location of the icon in pixels.
*/
static void
void
SetIconLocation(const std::shared_ptr<IconDrawItem>& di, double x, double y);
/**
@ -120,8 +129,8 @@ public:
* @param [in] di Icon draw item
* @param [in] angle Angle in degrees
*/
static void SetIconAngle(const std::shared_ptr<IconDrawItem>& di,
units::angle::degrees<double> angle);
void SetIconAngle(const std::shared_ptr<IconDrawItem>& di,
units::angle::degrees<double> angle);
/**
* Sets the modulate color of an icon.
@ -129,8 +138,8 @@ public:
* @param [in] di Icon draw item
* @param [in] modulate Modulate color
*/
static void SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
boost::gil::rgba8_pixel_t modulate);
void SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
boost::gil::rgba8_pixel_t modulate);
/**
* Sets the modulate color of an icon.
@ -138,8 +147,8 @@ public:
* @param [in] di Icon draw item
* @param [in] modulate Modulate color
*/
static void SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
boost::gil::rgba32f_pixel_t modulate);
void SetIconModulate(const std::shared_ptr<IconDrawItem>& di,
boost::gil::rgba32f_pixel_t modulate);
/**
* Sets the hover text of an icon.
@ -147,8 +156,8 @@ public:
* @param [in] di Icon draw item
* @param [in] text Hover text
*/
static void SetIconHoverText(const std::shared_ptr<IconDrawItem>& di,
const std::string& text);
void SetIconHoverText(const std::shared_ptr<IconDrawItem>& di,
const std::string& text);
/**
* Finalizes the draw item after adding new icons.

View file

@ -103,8 +103,7 @@ void LinkedVectors::Initialize()
p->geoLines_->Initialize();
}
void LinkedVectors::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
void LinkedVectors::Render(const QMapLibre::CustomLayerRenderParameters& params)
{
if (!p->visible_)
{
@ -337,12 +336,12 @@ void LinkedVectors::FinishVectors()
}
bool LinkedVectors::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler)
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler)
{
return p->geoLines_->RunMousePicking(params,
mouseLocalPos,

View file

@ -43,15 +43,15 @@ public:
void set_thresholded(bool thresholded);
void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override;
void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override;
bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override;
/**

View file

@ -255,8 +255,8 @@ void PlacefileIcons::Initialize()
}
void PlacefileIcons::Render(
const QMapLibreGL::CustomLayerRenderParameters& params,
bool textureAtlasChanged)
const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged)
{
std::unique_lock lock {p->iconMutex_};
@ -685,7 +685,7 @@ void PlacefileIcons::Impl::Update(bool textureAtlasChanged)
}
bool PlacefileIcons::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,

View file

@ -31,16 +31,16 @@ public:
void set_thresholded(bool thresholded);
void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params,
void Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) override;
void Deinitialize() override;
bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override;
/**

View file

@ -224,8 +224,8 @@ void PlacefileImages::Initialize()
}
void PlacefileImages::Render(
const QMapLibreGL::CustomLayerRenderParameters& params,
bool textureAtlasChanged)
const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged)
{
std::unique_lock lock {p->imageMutex_};

View file

@ -29,7 +29,7 @@ public:
void set_thresholded(bool thresholded);
void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params,
void Render(const QMapLibre::CustomLayerRenderParameters& params,
bool textureAtlasChanged) override;
void Deinitialize() override;

View file

@ -213,7 +213,7 @@ void PlacefileLines::Initialize()
}
void PlacefileLines::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
const QMapLibre::CustomLayerRenderParameters& params)
{
std::unique_lock lock {p->lineMutex_};
@ -496,7 +496,7 @@ void PlacefileLines::Impl::Update()
}
bool PlacefileLines::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,

View file

@ -29,15 +29,15 @@ public:
void set_thresholded(bool thresholded);
void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override;
void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override;
bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override;
/**

View file

@ -221,7 +221,7 @@ void PlacefilePolygons::Initialize()
}
void PlacefilePolygons::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
const QMapLibre::CustomLayerRenderParameters& params)
{
if (!p->currentBuffer_.empty())
{

View file

@ -31,7 +31,7 @@ public:
void set_thresholded(bool thresholded);
void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override;
void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override;
/**

View file

@ -34,14 +34,14 @@ public:
~Impl() {}
void RenderTextDrawItem(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QMapLibre::CustomLayerRenderParameters& params,
const std::shared_ptr<const gr::Placefile::TextDrawItem>& di);
void RenderText(const QMapLibreGL::CustomLayerRenderParameters& params,
const std::string& text,
const std::string& hoverText,
boost::gil::rgba8_pixel_t color,
float x,
float y);
void RenderText(const QMapLibre::CustomLayerRenderParameters& params,
const std::string& text,
const std::string& hoverText,
boost::gil::rgba8_pixel_t color,
float x,
float y);
std::shared_ptr<GlContext> context_;
@ -98,8 +98,7 @@ void PlacefileText::set_thresholded(bool thresholded)
void PlacefileText::Initialize() {}
void PlacefileText::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
void PlacefileText::Render(const QMapLibre::CustomLayerRenderParameters& params)
{
std::unique_lock lock {p->listMutex_};
@ -128,7 +127,7 @@ void PlacefileText::Render(
}
void PlacefileText::Impl::RenderTextDrawItem(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QMapLibre::CustomLayerRenderParameters& params,
const std::shared_ptr<const gr::Placefile::TextDrawItem>& di)
{
// If no time has been selected, use the current time
@ -191,12 +190,12 @@ void PlacefileText::Impl::RenderTextDrawItem(
}
void PlacefileText::Impl::RenderText(
const QMapLibreGL::CustomLayerRenderParameters& params,
const std::string& text,
const std::string& hoverText,
boost::gil::rgba8_pixel_t color,
float x,
float y)
const QMapLibre::CustomLayerRenderParameters& params,
const std::string& text,
const std::string& hoverText,
boost::gil::rgba8_pixel_t color,
float x,
float y)
{
const std::string windowName {
fmt::format("PlacefileText-{}-{}", placefileName_, ++textId_)};
@ -238,7 +237,7 @@ void PlacefileText::Deinitialize()
}
bool PlacefileText::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& /* params */,
const QMapLibre::CustomLayerRenderParameters& /* params */,
const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos,
const glm::vec2& /* mouseCoords */,

View file

@ -34,15 +34,15 @@ public:
void set_thresholded(bool thresholded);
void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override;
void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override;
bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override;
/**

View file

@ -169,7 +169,7 @@ void PlacefileTriangles::Initialize()
}
void PlacefileTriangles::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
const QMapLibre::CustomLayerRenderParameters& params)
{
if (!p->currentBuffer_.empty())
{

View file

@ -29,7 +29,7 @@ public:
void set_thresholded(bool thresholded);
void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override;
void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override;
/**

View file

@ -122,7 +122,7 @@ void Rectangle::Initialize()
p->dirty_ = true;
}
void Rectangle::Render(const QMapLibreGL::CustomLayerRenderParameters& params)
void Rectangle::Render(const QMapLibre::CustomLayerRenderParameters& params)
{
if (p->visible_)
{

View file

@ -27,7 +27,7 @@ public:
Rectangle& operator=(Rectangle&&) noexcept;
void Initialize() override;
void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override;
void Render(const QMapLibre::CustomLayerRenderParameters& params) override;
void Deinitialize() override;
void SetBorder(float width, boost::gil::rgba8_pixel_t color);

View file

@ -120,8 +120,11 @@ public:
std::string mapProviderApiKey = map::GetMapProviderApiKey(mapProvider_);
settings_.resetToTemplate(mapProviderInfo.settingsTemplate_);
settings_.setApiKey(QString {mapProviderApiKey.c_str()});
if (mapProvider_ == map::MapProvider::Mapbox)
{
settings_.setProviderTemplate(mapProviderInfo.providerTemplate_);
settings_.setApiKey(QString {mapProviderApiKey.c_str()});
}
settings_.setCacheDatabasePath(QString {cacheDbPath.c_str()});
settings_.setCacheDatabaseMaximumSize(20 * 1024 * 1024);
@ -164,10 +167,10 @@ public:
boost::asio::thread_pool threadPool_ {1u};
MainWindow* mainWindow_;
QMapLibreGL::Settings settings_;
map::MapProvider mapProvider_;
map::MapWidget* activeMap_;
MainWindow* mainWindow_;
QMapLibre::Settings settings_;
map::MapProvider mapProvider_;
map::MapWidget* activeMap_;
ui::CollapsibleGroup* mapSettingsGroup_;
ui::CollapsibleGroup* level2ProductsGroup_;

View file

@ -26,7 +26,7 @@
#include <boost/range/irange.hpp>
#include <boost/timer/timer.hpp>
#include <fmt/chrono.h>
#include <QMapLibreGL/QMapLibreGL>
#include <qmaplibre.hpp>
#if defined(_MSC_VER)
# pragma warning(pop)
@ -423,8 +423,8 @@ void RadarProductManager::Initialize()
const GeographicLib::Geodesic& geodesic(
util::GeographicLib::DefaultGeodesic());
const QMapLibreGL::Coordinate radar(p->radarSite_->latitude(),
p->radarSite_->longitude());
const QMapLibre::Coordinate radar(p->radarSite_->latitude(),
p->radarSite_->longitude());
const float gateSize = gate_size();

View file

@ -28,7 +28,8 @@ static void LoadTextures();
static const std::vector<std::pair<types::Font, std::string>> fontNames_ {
{types::Font::din1451alt, ":/res/fonts/din1451alt.ttf"},
{types::Font::din1451alt_g, ":/res/fonts/din1451alt_g.ttf"},
{types::Font::Inconsolata_Regular, ":/res/fonts/Inconsolata-Regular.ttf"}};
{types::Font::Inconsolata_Regular, ":/res/fonts/Inconsolata-Regular.ttf"},
{types::Font::RobotoFlex_Regular, ":/res/fonts/RobotoFlex-Regular.ttf"}};
void Initialize()
{

View file

@ -24,22 +24,22 @@ static const std::string logPrefix_ = "scwx::qt::map::alert_layer";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
static std::vector<std::string>
AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map,
awips::Phenomenon phenomenon,
bool alertActive,
const QString& beforeLayer);
static QMapLibreGL::Feature
AddAlertLayer(std::shared_ptr<QMapLibre::Map> map,
awips::Phenomenon phenomenon,
bool alertActive,
const QString& beforeLayer);
static QMapLibre::Feature
CreateFeature(const awips::CodedLocation& codedLocation);
static QMapLibreGL::Coordinate
static QMapLibre::Coordinate
GetMapboxCoordinate(const common::Coordinate& coordinate);
static QMapLibreGL::Coordinates
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<QMapLibreGL::Feature> {})}};
{"data", QVariant::fromValue(std::list<QMapLibre::Feature> {})}};
static const std::vector<awips::Phenomenon> kAlertPhenomena_ {
awips::Phenomenon::Marine,
awips::Phenomenon::FlashFlood,
@ -87,8 +87,8 @@ class AlertLayerHandler : public QObject
static std::shared_ptr<AlertLayerHandler> Instance();
std::list<QMapLibreGL::Feature>* FeatureList(awips::Phenomenon phenomenon,
bool alertActive);
std::list<QMapLibre::Feature>* FeatureList(awips::Phenomenon phenomenon,
bool alertActive);
void HandleAlert(const types::TextEventKey& key, size_t messageIndex);
void UpdateAlerts();
@ -103,7 +103,7 @@ class AlertLayerHandler : public QObject
std::unordered_multimap<types::TextEventKey,
std::tuple<awips::Phenomenon,
bool,
std::list<QMapLibreGL::Feature>::iterator,
std::list<QMapLibre::Feature>::iterator,
std::chrono::system_clock::time_point>,
types::TextEventHash<types::TextEventKey>>
featureMap_;
@ -166,16 +166,16 @@ std::vector<std::string> AlertLayer::AddLayers(awips::Phenomenon phenomenon,
return layers;
}
std::list<QMapLibreGL::Feature>*
std::list<QMapLibre::Feature>*
AlertLayerHandler::FeatureList(awips::Phenomenon phenomenon, bool alertActive)
{
std::list<QMapLibreGL::Feature>* featureList = nullptr;
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<QMapLibreGL::Feature>*>(
featureList = reinterpret_cast<std::list<QMapLibre::Feature>*>(
it->second["data"].data());
}
@ -371,10 +371,10 @@ std::shared_ptr<AlertLayerHandler> AlertLayerHandler::Instance()
}
static std::vector<std::string>
AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map,
awips::Phenomenon phenomenon,
bool alertActive,
const QString& beforeLayer)
AddAlertLayer(std::shared_ptr<QMapLibre::Map> map,
awips::Phenomenon phenomenon,
bool alertActive,
const QString& beforeLayer)
{
settings::PaletteSettings& paletteSettings =
settings::PaletteSettings::Instance();
@ -401,16 +401,16 @@ AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map,
const float opacity = outlineColor[3] / 255.0f;
map->addLayer({{"id", bgLayerId}, {"type", "line"}, {"source", sourceId}},
beforeLayer);
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({{"id", fgLayerId}, {"type", "line"}, {"source", sourceId}},
beforeLayer);
map->addLayer(
fgLayerId, {{"type", "line"}, {"source", sourceId}}, beforeLayer);
map->setLayoutProperty(fgLayerId, "line-join", "round");
map->setLayoutProperty(fgLayerId, "line-cap", "round");
map->setPaintProperty(fgLayerId,
@ -426,33 +426,33 @@ AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map,
return {bgLayerId.toStdString(), fgLayerId.toStdString()};
}
static QMapLibreGL::Feature
static QMapLibre::Feature
CreateFeature(const awips::CodedLocation& codedLocation)
{
auto mapboxCoordinates = GetMapboxCoordinates(codedLocation);
return {QMapLibreGL::Feature::PolygonType,
std::initializer_list<QMapLibreGL::CoordinatesCollection> {
std::initializer_list<QMapLibreGL::Coordinates> {
{mapboxCoordinates}}}};
return QMapLibre::Feature {
QMapLibre::Feature::PolygonType,
std::initializer_list<QMapLibre::CoordinatesCollection> {
std::initializer_list<QMapLibre::Coordinates> {{mapboxCoordinates}}}};
}
static QMapLibreGL::Coordinate
static QMapLibre::Coordinate
GetMapboxCoordinate(const common::Coordinate& coordinate)
{
return {coordinate.latitude_, coordinate.longitude_};
}
static QMapLibreGL::Coordinates
static QMapLibre::Coordinates
GetMapboxCoordinates(const awips::CodedLocation& codedLocation)
{
auto scwxCoordinates = codedLocation.coordinates();
QMapLibreGL::Coordinates mapboxCoordinates(scwxCoordinates.size() + 1u);
auto scwxCoordinates = codedLocation.coordinates();
QMapLibre::Coordinates mapboxCoordinates(scwxCoordinates.size() + 1u);
std::transform(scwxCoordinates.cbegin(),
scwxCoordinates.cend(),
mapboxCoordinates.begin(),
[](auto& coordinate) -> QMapLibreGL::Coordinate
[](auto& coordinate) -> QMapLibre::Coordinate
{ return GetMapboxCoordinate(coordinate); });
mapboxCoordinates.back() = GetMapboxCoordinate(scwxCoordinates.front());

View file

@ -116,7 +116,7 @@ void ColorTableLayer::Initialize()
}
void ColorTableLayer::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
const QMapLibre::CustomLayerRenderParameters& params)
{
gl::OpenGLFunctions& gl = context()->gl();
auto radarProductView = context()->radar_product_view();
@ -181,6 +181,12 @@ void ColorTableLayer::Render(
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]);
gl.glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
gl.glDrawArrays(GL_TRIANGLES, 0, 6);
context()->set_color_table_margins(QMargins {0, 0, 0, 10});
}
else
{
context()->set_color_table_margins(QMargins {});
}
SCWX_GL_CHECK_ERROR();
@ -200,6 +206,8 @@ void ColorTableLayer::Deinitialize()
p->vao_ = GL_INVALID_INDEX;
p->vbo_ = {GL_INVALID_INDEX};
p->texture_ = GL_INVALID_INDEX;
context()->set_color_table_margins(QMargins {});
}
} // namespace map

View file

@ -18,7 +18,7 @@ public:
~ColorTableLayer();
void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final;
void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final;
private:

View file

@ -44,7 +44,7 @@ void DrawLayer::Initialize()
}
}
void DrawLayer::Render(const QMapLibreGL::CustomLayerRenderParameters& params)
void DrawLayer::Render(const QMapLibre::CustomLayerRenderParameters& params)
{
gl::OpenGLFunctions& gl = p->context_->gl();
p->textureAtlas_ = p->context_->GetTextureAtlas();
@ -77,12 +77,12 @@ void DrawLayer::Deinitialize()
}
bool DrawLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler)
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler)
{
bool itemPicked = false;

View file

@ -19,16 +19,15 @@ public:
virtual ~DrawLayer();
virtual void Initialize() override;
virtual void
Render(const QMapLibreGL::CustomLayerRenderParameters&) override;
virtual void Render(const QMapLibre::CustomLayerRenderParameters&) override;
virtual void Deinitialize() override;
virtual bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override;
protected:

View file

@ -27,7 +27,7 @@ GenericLayer::GenericLayer(std::shared_ptr<MapContext> context) :
GenericLayer::~GenericLayer() = default;
bool GenericLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& /* params */,
const QMapLibre::CustomLayerRenderParameters& /* params */,
const QPointF& /* mouseLocalPos */,
const QPointF& /* mouseGlobalPos */,
const glm::vec2& /* mousePos */,

View file

@ -7,8 +7,8 @@
#include <memory>
#include <QObject>
#include <QMapLibreGL/QMapLibreGL>
#include <glm/gtc/type_ptr.hpp>
#include <qmaplibre.hpp>
namespace scwx
{
@ -27,9 +27,9 @@ public:
explicit GenericLayer(std::shared_ptr<MapContext> context);
virtual ~GenericLayer();
virtual void Initialize() = 0;
virtual void Render(const QMapLibreGL::CustomLayerRenderParameters&) = 0;
virtual void Deinitialize() = 0;
virtual void Initialize() = 0;
virtual void Render(const QMapLibre::CustomLayerRenderParameters&) = 0;
virtual void Deinitialize() = 0;
/**
* @brief Run mouse picking on the layer.
@ -44,12 +44,12 @@ public:
* @return true if a draw item was picked, otherwise false
*/
virtual bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler);
RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler);
signals:
void NeedsRendering();

View file

@ -34,8 +34,7 @@ void LayerWrapper::initialize()
p->layer_->Initialize();
}
void LayerWrapper::render(
const QMapLibreGL::CustomLayerRenderParameters& params)
void LayerWrapper::render(const QMapLibre::CustomLayerRenderParameters& params)
{
p->layer_->Render(params);
}

View file

@ -11,7 +11,7 @@ namespace map
class LayerWrapperImpl;
class LayerWrapper : public QMapLibreGL::CustomLayerHostInterface
class LayerWrapper : public QMapLibre::CustomLayerHostInterface
{
public:
explicit LayerWrapper(std::shared_ptr<GenericLayer> layer);
@ -24,7 +24,7 @@ public:
LayerWrapper& operator=(LayerWrapper&&) noexcept;
void initialize() override final;
void render(const QMapLibreGL::CustomLayerRenderParameters&) override final;
void render(const QMapLibre::CustomLayerRenderParameters&) override final;
void deinitialize() override final;
private:

View file

@ -20,14 +20,19 @@ public:
~Impl() {}
std::weak_ptr<QMapLibreGL::Map> map_ {};
MapSettings settings_ {};
float pixelRatio_ {1.0f};
common::RadarProductGroup radarProductGroup_ {
std::weak_ptr<QMapLibre::Map> map_ {};
MapSettings settings_ {};
float pixelRatio_ {1.0f};
common::RadarProductGroup radarProductGroup_ {
common::RadarProductGroup::Unknown};
std::string radarProduct_ {"???"};
int16_t radarProductCode_ {0};
QMapLibreGL::CustomLayerRenderParameters renderParameters_ {};
std::string radarProduct_ {"???"};
int16_t radarProductCode_ {0};
QMapLibre::CustomLayerRenderParameters renderParameters_ {};
MapProvider mapProvider_ {MapProvider::Unknown};
std::string mapCopyrights_ {};
QMargins colorTableMargins_ {};
std::shared_ptr<view::OverlayProductView> overlayProductView_ {nullptr};
std::shared_ptr<view::RadarProductView> radarProductView_;
@ -43,16 +48,31 @@ MapContext::~MapContext() = default;
MapContext::MapContext(MapContext&&) noexcept = default;
MapContext& MapContext::operator=(MapContext&&) noexcept = default;
std::weak_ptr<QMapLibreGL::Map> MapContext::map() const
std::weak_ptr<QMapLibre::Map> MapContext::map() const
{
return p->map_;
}
std::string MapContext::map_copyrights() const
{
return p->mapCopyrights_;
}
MapProvider MapContext::map_provider() const
{
return p->mapProvider_;
}
MapSettings& MapContext::settings()
{
return p->settings_;
}
QMargins MapContext::color_table_margins() const
{
return p->colorTableMargins_;
}
float MapContext::pixel_ratio() const
{
return p->pixelRatio_;
@ -84,16 +104,31 @@ int16_t MapContext::radar_product_code() const
return p->radarProductCode_;
}
QMapLibreGL::CustomLayerRenderParameters MapContext::render_parameters() const
QMapLibre::CustomLayerRenderParameters MapContext::render_parameters() const
{
return p->renderParameters_;
}
void MapContext::set_map(const std::shared_ptr<QMapLibreGL::Map>& map)
void MapContext::set_map(const std::shared_ptr<QMapLibre::Map>& map)
{
p->map_ = map;
}
void MapContext::set_map_copyrights(const std::string& copyrights)
{
p->mapCopyrights_ = copyrights;
}
void MapContext::set_map_provider(MapProvider provider)
{
p->mapProvider_ = provider;
}
void MapContext::set_color_table_margins(const QMargins& margins)
{
p->colorTableMargins_ = margins;
}
void MapContext::set_overlay_product_view(
const std::shared_ptr<view::OverlayProductView>& overlayProductView)
{
@ -128,7 +163,7 @@ void MapContext::set_radar_product_code(int16_t radarProductCode)
}
void MapContext::set_render_parameters(
const QMapLibreGL::CustomLayerRenderParameters& params)
const QMapLibre::CustomLayerRenderParameters& params)
{
p->renderParameters_ = params;
}

View file

@ -1,9 +1,11 @@
#pragma once
#include <scwx/qt/gl/gl_context.hpp>
#include <scwx/qt/map/map_provider.hpp>
#include <scwx/common/products.hpp>
#include <QMapLibreGL/QMapLibreGL>
#include <qmaplibre.hpp>
#include <QMargins>
namespace scwx
{
@ -35,17 +37,23 @@ public:
MapContext(MapContext&&) noexcept;
MapContext& operator=(MapContext&&) noexcept;
std::weak_ptr<QMapLibreGL::Map> map() const;
std::weak_ptr<QMapLibre::Map> map() const;
std::string map_copyrights() const;
MapProvider map_provider() const;
MapSettings& settings();
QMargins color_table_margins() const;
float pixel_ratio() const;
std::shared_ptr<view::OverlayProductView> overlay_product_view() const;
std::shared_ptr<view::RadarProductView> radar_product_view() const;
common::RadarProductGroup radar_product_group() const;
std::string radar_product() const;
int16_t radar_product_code() const;
QMapLibreGL::CustomLayerRenderParameters render_parameters() const;
QMapLibre::CustomLayerRenderParameters render_parameters() const;
void set_map(const std::shared_ptr<QMapLibreGL::Map>& map);
void set_map(const std::shared_ptr<QMapLibre::Map>& map);
void set_map_copyrights(const std::string& copyrights);
void set_map_provider(MapProvider provider);
void set_color_table_margins(const QMargins& margins);
void set_overlay_product_view(
const std::shared_ptr<view::OverlayProductView>& overlayProductView);
void set_pixel_ratio(float pixelRatio);
@ -54,8 +62,8 @@ public:
void set_radar_product_group(common::RadarProductGroup radarProductGroup);
void set_radar_product(const std::string& radarProduct);
void set_radar_product_code(int16_t radarProductCode);
void set_render_parameters(
const QMapLibreGL::CustomLayerRenderParameters& params);
void
set_render_parameters(const QMapLibre::CustomLayerRenderParameters& params);
private:
class Impl;

View file

@ -26,77 +26,155 @@ static const std::unordered_map<MapProvider, MapProviderInfo> mapProviderInfo_ {
MapProviderInfo {
.mapProvider_ {MapProvider::Mapbox},
.cacheDbName_ {"mbgl-cache.db"},
.settingsTemplate_ {
QMapLibreGL::Settings::SettingsTemplate::MapboxSettings},
.mapStyles_ {{.name_ {"Streets"},
.url_ {"mapbox://styles/mapbox/streets-v11"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Outdoors"},
.url_ {"mapbox://styles/mapbox/outdoors-v11"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Light"},
.url_ {"mapbox://styles/mapbox/light-v10"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Dark"},
.url_ {"mapbox://styles/mapbox/dark-v10"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Satellite"},
.url_ {"mapbox://styles/mapbox/satellite-v9"},
.drawBelow_ {"com.mapbox.annotations.points"}},
{.name_ {"Satellite Streets"},
.url_ {"mapbox://styles/mapbox/satellite-streets-v11"},
.drawBelow_ {mapboxDrawBelow_}}}}},
.providerTemplate_ {
QMapLibre::Settings::ProviderTemplate::MapboxProvider},
.mapStyles_ {
{.name_ {"Streets"},
.url_ {"mapbox://styles/mapbox/streets-v11"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"American Memory"},
.url_ {
"mapbox://styles/mapbox-map-design/cl4orrp5e000p14ldwenm7xsf"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Basic"},
.url_ {
"mapbox://styles/mapbox-map-design/cl4whef7m000714pc44f3qaxs"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Basic Overcast"},
.url_ {
"mapbox://styles/mapbox-map-design/cl4whev1w002w16s9mgoliotw"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Blueprint"},
.url_ {
"mapbox://styles/mapbox-map-design/cks97e1e37nsd17nzg7p0308g"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Bubble"},
.url_ {
"mapbox://styles/mapbox-map-design/cl4wxue5j000c14r17uqrjpqb"},
.drawBelow_ {"com\\.mapbox\\.annotations\\.points"}},
{.name_ {"Cali Terrain"},
.url_ {"mapbox://styles/mapbox/cjerxnqt3cgvp2rmyuxbeqme7"},
.drawBelow_ {"major roads casing"}},
{.name_ {"Dark"},
.url_ {"mapbox://styles/mapbox/dark-v10"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Decimal"},
.url_ {
"mapbox://styles/mapbox-map-design/ck4014y110wt61ctt07egsel6"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Frank"},
.url_ {
"mapbox://styles/mapbox-map-design/ckshxkppe0gge18nz20i0nrwq"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Ice Cream"},
.url_ {"mapbox://styles/mapbox/cj7t3i5yj0unt2rmt3y4b5e32"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Le Shine"},
.url_ {"mapbox://styles/mapbox/cjcunv5ae262f2sm9tfwg8i0w"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Light"},
.url_ {"mapbox://styles/mapbox/light-v10"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Mineral"},
.url_ {"mapbox://styles/mapbox/cjtep62gq54l21frr1whf27ak"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Minimo"},
.url_ {
"mapbox://styles/mapbox-map-design/cksjc2nsq1bg117pnekb655h1"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Moonlight"},
.url_ {"mapbox://styles/mapbox/cj3kbeqzo00022smj7akz3o1e"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Navigation Guidance Day"},
.url_ {"mapbox://styles/mapbox/navigation-guidance-day-v4"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Navigation Guidance Night"},
.url_ {"mapbox://styles/mapbox/navigation-guidance-night-v4"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Neon glow"},
.url_ {
"mapbox://styles/mapbox-map-design/cl4gxqwi5001415l381n7qwak"},
.drawBelow_ {"settlement-minor-label"}},
{.name_ {"North Star"},
.url_ {"mapbox://styles/mapbox/cj44mfrt20f082snokim4ungi"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Outdoors"},
.url_ {"mapbox://styles/mapbox/outdoors-v11"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Pencil"},
.url_ {
"mapbox://styles/mapbox-map-design/cks9iema71es417mlrft4go2k"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Satellite"},
.url_ {"mapbox://styles/mapbox/satellite-v9"},
.drawBelow_ {"com.mapbox.annotations.points"}},
{.name_ {"Satellite Streets"},
.url_ {"mapbox://styles/mapbox/satellite-streets-v11"},
.drawBelow_ {mapboxDrawBelow_}},
{.name_ {"Standard Oil Company"},
.url_ {
"mapbox://styles/mapbox-map-design/ckr0svm3922ki18qntevm857n"},
.drawBelow_ {mapboxDrawBelow_}}}}},
{MapProvider::MapTiler,
MapProviderInfo {
.mapProvider_ {MapProvider::MapTiler},
.cacheDbName_ {"maptiler-cache.db"},
.settingsTemplate_ {
QMapLibreGL::Settings::SettingsTemplate::MapTilerSettings},
.providerTemplate_ {
QMapLibre::Settings::ProviderTemplate::MapTilerProvider},
.mapStyles_ {
{.name_ {"Satellite"},
.url_ {"maptiler://maps/hybrid"},
.url_ {"https://api.maptiler.com/maps/hybrid/style.json"},
.drawBelow_ {"tunnel"}},
{.name_ {"Streets"},
.url_ {"maptiler://maps/streets-v2"},
.url_ {"https://api.maptiler.com/maps/streets-v2/style.json"},
.drawBelow_ {"aeroway"}},
{.name_ {"Streets Dark"},
.url_ {"maptiler://maps/streets-v2-dark"},
.url_ {"https://api.maptiler.com/maps/streets-v2-dark/style.json"},
.drawBelow_ {"aeroway"}},
{.name_ {"Backdrop"},
.url_ {"https://api.maptiler.com/maps/backdrop/style.json"},
.drawBelow_ {"Aeroway"}},
{.name_ {"Basic"},
.url_ {"maptiler://maps/basic-v2"},
.url_ {"https://api.maptiler.com/maps/basic-v2/style.json"},
.drawBelow_ {"railway_transit_tunnel", "Transit tunnel"}},
{.name_ {"Bright"},
.url_ {"maptiler://maps/bright-v2"},
.url_ {"https://api.maptiler.com/maps/bright-v2/style.json"},
.drawBelow_ {"ferry"}},
{.name_ {"Dataviz"},
.url_ {"maptiler://maps/dataviz"},
.url_ {"https://api.maptiler.com/maps/dataviz/style.json"},
.drawBelow_ {"aeroway"}},
{.name_ {"Dataviz Dark"},
.url_ {"maptiler://maps/dataviz-dark"},
.url_ {"https://api.maptiler.com/maps/dataviz-dark/style.json"},
.drawBelow_ {"aeroway"}},
{.name_ {"Landscape"},
.url_ {"https://api.maptiler.com/maps/landscape/style.json"},
.drawBelow_ {"Runway"}},
{.name_ {"Outdoor"},
.url_ {"maptiler://maps/outdoor-v2"},
.url_ {"https://api.maptiler.com/maps/outdoor-v2/style.json"},
.drawBelow_ {"aeroway_runway", "Aeroway"}},
{.name_ {"Swisstopo"},
.url_ {"maptiler://maps/ch-swisstopo-lbm"},
.url_ {"https://api.maptiler.com/maps/ch-swisstopo-lbm/style.json"},
.drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}},
{.name_ {"Swisstopo Dark"},
.url_ {"maptiler://maps/ch-swisstopo-lbm-dark"},
.url_ {
"https://api.maptiler.com/maps/ch-swisstopo-lbm-dark/style.json"},
.drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}},
{.name_ {"Swisstopo Grey"},
.url_ {"maptiler://maps/ch-swisstopo-lbm-grey"},
.url_ {
"https://api.maptiler.com/maps/ch-swisstopo-lbm-grey/style.json"},
.drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}},
{.name_ {"Swisstopo Vivid"},
.url_ {"maptiler://maps/ch-swisstopo-lbm-vivid"},
.url_ {"https://api.maptiler.com/maps/ch-swisstopo-lbm-vivid/"
"style.json"},
.drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}},
{.name_ {"Topo"},
.url_ {"maptiler://maps/topo-v2"},
.url_ {"https://api.maptiler.com/maps/topo-v2/style.json"},
.drawBelow_ {"aeroway_runway", "Runway"}},
{.name_ {"Topo Dark"},
.url_ {"maptiler://maps/topo-v2-dark"},
.url_ {"https://api.maptiler.com/maps/topo-v2-dark/style.json"},
.drawBelow_ {"aeroway_runway", "Runway"}},
{.name_ {"Winter"},
.url_ {"maptiler://maps/winter-v2"},
.url_ {"https://api.maptiler.com/maps/winter-v2/style.json"},
.drawBelow_ {"aeroway_runway", "Aeroway"}}}}},
{MapProvider::Unknown, MapProviderInfo {}}};

View file

@ -4,7 +4,7 @@
#include <string>
#include <QMapLibreGL/settings.hpp>
#include <QMapLibre/Settings>
namespace scwx
{
@ -32,10 +32,10 @@ struct MapStyle
struct MapProviderInfo
{
MapProvider mapProvider_ {MapProvider::Unknown};
std::string cacheDbName_ {};
QMapLibreGL::Settings::SettingsTemplate settingsTemplate_ {};
std::vector<MapStyle> mapStyles_ {};
MapProvider mapProvider_ {MapProvider::Unknown};
std::string cacheDbName_ {};
QMapLibre::Settings::ProviderTemplate providerTemplate_ {};
std::vector<MapStyle> mapStyles_ {};
};
MapProvider GetMapProvider(const std::string& name);

View file

@ -30,6 +30,8 @@
#include <backends/imgui_impl_opengl3.h>
#include <backends/imgui_impl_qt.hpp>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/thread_pool.hpp>
#include <boost/uuid/random_generator.hpp>
@ -44,6 +46,7 @@
#include <QKeyEvent>
#include <QMouseEvent>
#include <QString>
#include <QTextDocument>
namespace scwx
{
@ -60,9 +63,9 @@ class MapWidgetImpl : public QObject
Q_OBJECT
public:
explicit MapWidgetImpl(MapWidget* widget,
std::size_t id,
const QMapLibreGL::Settings& settings) :
explicit MapWidgetImpl(MapWidget* widget,
std::size_t id,
const QMapLibre::Settings& settings) :
id_ {id},
uuid_ {boost::uuids::random_generator()()},
context_ {std::make_shared<MapContext>()},
@ -94,11 +97,13 @@ public:
overlayProductView->SetAutoRefresh(autoRefreshEnabled_);
overlayProductView->SetAutoUpdate(autoUpdateEnabled_);
// Initialize context
context_->set_overlay_product_view(overlayProductView);
auto& generalSettings = settings::GeneralSettings::Instance();
// Initialize context
context_->set_map_provider(
GetMapProvider(generalSettings.map_provider().GetValue()));
context_->set_overlay_product_view(overlayProductView);
SetRadarSite(generalSettings.default_radar_site().GetValue());
// Create ImGui Context
@ -110,9 +115,6 @@ public:
// Initialize ImGui Qt backend
ImGui_ImplQt_Init();
// Set Map Provider Details
mapProvider_ = GetMapProvider(generalSettings.map_provider().GetValue());
ConnectSignals();
}
@ -143,6 +145,7 @@ public:
void AddLayers();
void AddPlacefileLayer(const std::string& placefileName,
const std::string& before);
void ConnectMapSignals();
void ConnectSignals();
void ImGuiCheckFonts();
void InitializeNewRadarProductView(const std::string& colorPalette);
@ -169,11 +172,10 @@ public:
std::shared_ptr<MapContext> context_;
MapWidget* widget_;
MapProvider mapProvider_;
QMapLibreGL::Settings settings_;
std::shared_ptr<QMapLibreGL::Map> map_;
std::list<std::string> layerList_;
MapWidget* widget_;
QMapLibre::Settings settings_;
std::shared_ptr<QMapLibre::Map> map_;
std::list<std::string> layerList_;
std::vector<std::shared_ptr<GenericLayer>> genericLayers_ {};
@ -229,7 +231,7 @@ public slots:
void Update();
};
MapWidget::MapWidget(std::size_t id, const QMapLibreGL::Settings& settings) :
MapWidget::MapWidget(std::size_t id, const QMapLibre::Settings& settings) :
p(std::make_unique<MapWidgetImpl>(this, id, settings))
{
if (settings::GeneralSettings::Instance().anti_aliasing_enabled().GetValue())
@ -246,10 +248,34 @@ MapWidget::MapWidget(std::size_t id, const QMapLibreGL::Settings& settings) :
MapWidget::~MapWidget()
{
// Make sure we have a valid context so we can delete the QMapLibreGL.
// Make sure we have a valid context so we can delete the QMapLibre.
makeCurrent();
}
void MapWidgetImpl::ConnectMapSignals()
{
connect(map_.get(),
&QMapLibre::Map::needsRendering,
this,
&MapWidgetImpl::Update);
connect(map_.get(),
&QMapLibre::Map::copyrightsChanged,
this,
[this](const QString& copyrightsHtml)
{
QTextDocument document {};
document.setHtml(copyrightsHtml);
// HTML cannot currently be included in ImGui windows. Where links
// can't be included, remove "Improve this map".
std::string copyrights {document.toPlainText().toStdString()};
boost::erase_all(copyrights, "Improve this map");
boost::trim_right(copyrights);
context_->set_map_copyrights(copyrights);
});
}
void MapWidgetImpl::ConnectSignals()
{
connect(placefileManager_.get(),
@ -725,7 +751,8 @@ void MapWidget::SetInitialMapStyle(const std::string& styleName)
void MapWidget::SetMapStyle(const std::string& styleName)
{
const auto& mapProviderInfo = GetMapProviderInfo(p->mapProvider_);
const auto mapProvider = p->context_->map_provider();
const auto& mapProviderInfo = GetMapProviderInfo(mapProvider);
auto& styles = mapProviderInfo.mapStyles_;
for (size_t i = 0u; i < styles.size(); ++i)
@ -737,7 +764,7 @@ void MapWidget::SetMapStyle(const std::string& styleName)
logger_->debug("Updating style: {}", styles[i].name_);
p->map_->setStyleUrl(styles[i].url_.c_str());
util::maplibre::SetMapStyleUrl(p->context_, styles[i].url_);
if (++p->currentStyleIndex_ == styles.size())
{
@ -756,14 +783,16 @@ qreal MapWidget::pixelRatio()
void MapWidget::changeStyle()
{
const auto& mapProviderInfo = GetMapProviderInfo(p->mapProvider_);
const auto mapProvider = p->context_->map_provider();
const auto& mapProviderInfo = GetMapProviderInfo(mapProvider);
auto& styles = mapProviderInfo.mapStyles_;
p->currentStyle_ = &styles[p->currentStyleIndex_];
logger_->debug("Updating style: {}", styles[p->currentStyleIndex_].name_);
p->map_->setStyleUrl(styles[p->currentStyleIndex_].url_.c_str());
util::maplibre::SetMapStyleUrl(p->context_,
styles[p->currentStyleIndex_].url_);
if (++p->currentStyleIndex_ == styles.size())
{
@ -987,8 +1016,8 @@ void MapWidgetImpl::AddLayer(const std::string& id,
std::shared_ptr<GenericLayer> layer,
const std::string& before)
{
// QMapLibreGL::addCustomLayer will take ownership of the std::unique_ptr
std::unique_ptr<QMapLibreGL::CustomLayerHostInterface> pHost =
// QMapLibre::addCustomLayer will take ownership of the std::unique_ptr
std::unique_ptr<QMapLibre::CustomLayerHostInterface> pHost =
std::make_unique<LayerWrapper>(layer);
try
@ -1131,12 +1160,9 @@ void MapWidget::initializeGL()
p->imGuiRendererInitialized_ = true;
p->map_.reset(
new QMapLibreGL::Map(nullptr, p->settings_, size(), pixelRatio()));
new QMapLibre::Map(nullptr, p->settings_, size(), pixelRatio()));
p->context_->set_map(p->map_);
connect(p->map_.get(),
&QMapLibreGL::Map::needsRendering,
p.get(),
&MapWidgetImpl::Update);
p->ConnectMapSignals();
// Set default location to radar site
std::shared_ptr<config::RadarSite> radarSite =
@ -1160,10 +1186,8 @@ void MapWidget::initializeGL()
SetMapStyle(p->initialStyleName_);
}
connect(p->map_.get(),
&QMapLibreGL::Map::mapChanged,
this,
&MapWidget::mapChanged);
connect(
p->map_.get(), &QMapLibre::Map::mapChanged, this, &MapWidget::mapChanged);
}
void MapWidget::paintGL()
@ -1192,7 +1216,7 @@ void MapWidget::paintGL()
// Update pixel ratio
p->context_->set_pixel_ratio(pixelRatio());
// Render QMapLibreGL Map
// Render QMapLibre Map
p->map_->resize(size());
p->map_->setFramebufferObject(defaultFramebufferObject(),
size() * pixelRatio());
@ -1243,7 +1267,7 @@ void MapWidgetImpl::ImGuiCheckFonts()
void MapWidgetImpl::RunMousePicking()
{
const QMapLibreGL::CustomLayerRenderParameters params =
const QMapLibre::CustomLayerRenderParameters params =
context_->render_parameters();
auto coordinate = map_->coordinateForPixel(lastPos_);
@ -1318,11 +1342,11 @@ void MapWidgetImpl::RunMousePicking()
lastItemPicked_ = itemPicked;
}
void MapWidget::mapChanged(QMapLibreGL::Map::MapChange mapChange)
void MapWidget::mapChanged(QMapLibre::Map::MapChange mapChange)
{
switch (mapChange)
{
case QMapLibreGL::Map::MapChangeDidFinishLoadingStyle:
case QMapLibre::Map::MapChangeDidFinishLoadingStyle:
p->UpdateLoadedStyle();
p->AddLayers();
break;

View file

@ -9,7 +9,7 @@
#include <chrono>
#include <memory>
#include <QMapLibreGL/QMapLibreGL>
#include <qmaplibre.hpp>
#include <QOpenGLWidget>
#include <QPropertyAnimation>
@ -33,7 +33,7 @@ class MapWidget : public QOpenGLWidget
Q_OBJECT
public:
explicit MapWidget(std::size_t id, const QMapLibreGL::Settings&);
explicit MapWidget(std::size_t id, const QMapLibre::Settings&);
~MapWidget();
void DumpLayerList() const;
@ -139,7 +139,7 @@ private:
friend class MapWidgetImpl;
private slots:
void mapChanged(QMapLibreGL::Map::MapChange);
void mapChanged(QMapLibre::Map::MapChange);
signals:
void Level3ProductsChanged();

View file

@ -2,8 +2,10 @@
#include <scwx/qt/gl/draw/geo_icons.hpp>
#include <scwx/qt/gl/draw/icons.hpp>
#include <scwx/qt/gl/draw/rectangle.hpp>
#include <scwx/qt/manager/font_manager.hpp>
#include <scwx/qt/manager/position_manager.hpp>
#include <scwx/qt/map/map_settings.hpp>
#include <scwx/qt/settings/general_settings.hpp>
#include <scwx/qt/types/texture_types.hpp>
#include <scwx/qt/view/radar_product_view.hpp>
#include <scwx/util/logger.hpp>
@ -40,14 +42,38 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
class OverlayLayerImpl
{
public:
explicit OverlayLayerImpl(std::shared_ptr<MapContext> context) :
explicit OverlayLayerImpl(OverlayLayer* self,
std::shared_ptr<MapContext> context) :
self_ {self},
activeBoxOuter_ {std::make_shared<gl::draw::Rectangle>(context)},
activeBoxInner_ {std::make_shared<gl::draw::Rectangle>(context)},
geoIcons_ {std::make_shared<gl::draw::GeoIcons>(context)},
icons_ {std::make_shared<gl::draw::Icons>(context)}
{
auto& generalSettings = settings::GeneralSettings::Instance();
showMapAttributionCallbackUuid_ =
generalSettings.show_map_attribution().RegisterValueChangedCallback(
[this](const bool&) { Q_EMIT self_->NeedsRendering(); });
showMapLogoCallbackUuid_ =
generalSettings.show_map_logo().RegisterValueChangedCallback(
[this](const bool&) { Q_EMIT self_->NeedsRendering(); });
}
~OverlayLayerImpl() = default;
~OverlayLayerImpl()
{
auto& generalSettings = settings::GeneralSettings::Instance();
generalSettings.show_map_attribution().UnregisterValueChangedCallback(
showMapAttributionCallbackUuid_);
generalSettings.show_map_logo().UnregisterValueChangedCallback(
showMapLogoCallbackUuid_);
}
OverlayLayer* self_;
boost::uuids::uuid showMapAttributionCallbackUuid_;
boost::uuids::uuid showMapLogoCallbackUuid_;
std::shared_ptr<manager::PositionManager> positionManager_ {
manager::PositionManager::Instance()};
@ -66,13 +92,22 @@ public:
types::GetTextureName(types::ImageTexture::CardinalPoint24)};
const std::string& compassIconName_ {
types::GetTextureName(types::ImageTexture::Compass24)};
const std::string& mapboxLogoImageName_ {
types::GetTextureName(types::ImageTexture::MapboxLogo)};
const std::string& mapTilerLogoImageName_ {
types::GetTextureName(types::ImageTexture::MapTilerLogo)};
std::shared_ptr<gl::draw::IconDrawItem> compassIcon_ {};
bool compassIconDirty_ {false};
double lastBearing_ {0.0};
double lastWidth_ {0.0};
double lastHeight_ {0.0};
float lastFontSize_ {0.0f};
std::shared_ptr<gl::draw::IconDrawItem> mapLogoIcon_ {};
bool firstRender_ {true};
double lastWidth_ {0.0};
double lastHeight_ {0.0};
float lastFontSize_ {0.0f};
QMargins lastColorTableMargins_ {};
std::string sweepTimeString_ {};
bool sweepTimeNeedsUpdate_ {true};
@ -80,7 +115,7 @@ public:
};
OverlayLayer::OverlayLayer(std::shared_ptr<MapContext> context) :
DrawLayer(context), p(std::make_unique<OverlayLayerImpl>(context))
DrawLayer(context), p(std::make_unique<OverlayLayerImpl>(this, context))
{
AddDrawItem(p->activeBoxOuter_);
AddDrawItem(p->activeBoxInner_);
@ -130,12 +165,13 @@ void OverlayLayer::Initialize()
p->icons_->StartIconSheets();
p->icons_->AddIconSheet(p->cardinalPointIconName_);
p->icons_->AddIconSheet(p->compassIconName_);
p->icons_->AddIconSheet(p->mapboxLogoImageName_)->SetAnchor(0.0f, 1.0f);
p->icons_->AddIconSheet(p->mapTilerLogoImageName_)->SetAnchor(0.0f, 1.0f);
p->icons_->FinishIconSheets();
p->icons_->StartIcons();
p->compassIcon_ = p->icons_->AddIcon();
gl::draw::Icons::SetIconTexture(
p->compassIcon_, p->cardinalPointIconName_, 0);
p->icons_->SetIconTexture(p->compassIcon_, p->cardinalPointIconName_, 0);
gl::draw::Icons::RegisterEventHandler(
p->compassIcon_,
[this](QEvent* ev)
@ -144,18 +180,16 @@ void OverlayLayer::Initialize()
{
case QEvent::Type::Enter:
// Highlight icon on mouse enter
gl::draw::Icons::SetIconModulate(
p->icons_->SetIconModulate(
p->compassIcon_,
boost::gil::rgba32f_pixel_t {1.5f, 1.5f, 1.5f, 1.0f});
p->compassIconDirty_ = true;
break;
case QEvent::Type::Leave:
// Restore icon on mouse leave
gl::draw::Icons::SetIconModulate(
p->icons_->SetIconModulate(
p->compassIcon_,
boost::gil::rgba32f_pixel_t {1.0f, 1.0f, 1.0f, 1.0f});
p->compassIconDirty_ = true;
break;
case QEvent::Type::MouseButtonPress:
@ -179,6 +213,17 @@ void OverlayLayer::Initialize()
break;
}
});
p->mapLogoIcon_ = p->icons_->AddIcon();
if (context()->map_provider() == MapProvider::Mapbox)
{
p->icons_->SetIconTexture(p->mapLogoIcon_, p->mapboxLogoImageName_, 0);
}
else if (context()->map_provider() == MapProvider::MapTiler)
{
p->icons_->SetIconTexture(p->mapLogoIcon_, p->mapTilerLogoImageName_, 0);
}
p->icons_->FinishIcons();
connect(p->positionManager_.get(),
@ -204,8 +249,7 @@ void OverlayLayer::Initialize()
});
}
void OverlayLayer::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
void OverlayLayer::Render(const QMapLibre::CustomLayerRenderParameters& params)
{
gl::OpenGLFunctions& gl = context()->gl();
auto radarProductView = context()->radar_product_view();
@ -258,42 +302,29 @@ void OverlayLayer::Render(
ImGui::GetFontSize() != p->lastFontSize_)
{
// Set the compass icon in the upper right, below the sweep time window
gl::draw::Icons::SetIconLocation(p->compassIcon_,
params.width - 24,
params.height -
(ImGui::GetFontSize() + 32));
p->compassIconDirty_ = true;
p->icons_->SetIconLocation(p->compassIcon_,
params.width - 24,
params.height - (ImGui::GetFontSize() + 32));
}
if (params.bearing != p->lastBearing_)
{
if (params.bearing == 0.0)
{
// Use cardinal point icon when bearing is oriented north-up
gl::draw::Icons::SetIconTexture(
p->icons_->SetIconTexture(
p->compassIcon_, p->cardinalPointIconName_, 0);
gl::draw::Icons::SetIconAngle(p->compassIcon_,
units::angle::degrees<double> {0.0});
p->icons_->SetIconAngle(p->compassIcon_,
units::angle::degrees<double> {0.0});
}
else
{
// Use rotated compass icon when bearing is rotated away from north-up
gl::draw::Icons::SetIconTexture(
p->compassIcon_, p->compassIconName_, 0);
gl::draw::Icons::SetIconAngle(
p->icons_->SetIconTexture(p->compassIcon_, p->compassIconName_, 0);
p->icons_->SetIconAngle(
p->compassIcon_,
units::angle::degrees<double> {-45 - params.bearing});
}
// Mark icon for re-drawing
p->compassIconDirty_ = true;
}
if (p->compassIconDirty_)
{
// Update icon render buffers
p->icons_->FinishIcons();
}
DrawLayer::Render(params);
if (radarProductView != nullptr)
{
@ -356,10 +387,53 @@ void OverlayLayer::Render(
ImGui::End();
}
p->lastWidth_ = params.width;
p->lastHeight_ = params.height;
p->lastBearing_ = params.bearing;
p->lastFontSize_ = ImGui::GetFontSize();
auto& generalSettings = settings::GeneralSettings::Instance();
QMargins colorTableMargins = context()->color_table_margins();
if (colorTableMargins != p->lastColorTableMargins_ || p->firstRender_)
{
// Draw map logo with a 10x10 indent from the bottom left
p->icons_->SetIconLocation(p->mapLogoIcon_,
10 + colorTableMargins.left(),
10 + colorTableMargins.bottom());
p->icons_->FinishIcons();
}
p->icons_->SetIconVisible(p->mapLogoIcon_,
generalSettings.show_map_logo().GetValue());
DrawLayer::Render(params);
auto mapCopyrights = context()->map_copyrights();
if (mapCopyrights.length() > 0 &&
generalSettings.show_map_attribution().GetValue())
{
auto attributionFont = manager::FontManager::Instance().GetImGuiFont(
types::FontCategory::Attribution);
ImGui::SetNextWindowPos(ImVec2 {static_cast<float>(params.width),
static_cast<float>(params.height) -
colorTableMargins.bottom()},
ImGuiCond_Always,
ImVec2 {1.0f, 1.0f});
ImGui::SetNextWindowBgAlpha(0.5f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2 {3.0f, 2.0f});
ImGui::PushFont(attributionFont->font());
ImGui::Begin("Attribution",
nullptr,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_AlwaysAutoResize);
ImGui::TextUnformatted(mapCopyrights.c_str());
ImGui::End();
ImGui::PopFont();
ImGui::PopStyleVar();
}
p->firstRender_ = false;
p->lastWidth_ = params.width;
p->lastHeight_ = params.height;
p->lastBearing_ = params.bearing;
p->lastFontSize_ = ImGui::GetFontSize();
p->lastColorTableMargins_ = colorTableMargins;
SCWX_GL_CHECK_ERROR();
}
@ -393,12 +467,12 @@ void OverlayLayer::Deinitialize()
}
bool OverlayLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler)
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler)
{
// If sweep time was picked, don't process additional items
if (p->sweepTimePicked_)

View file

@ -13,20 +13,22 @@ class OverlayLayerImpl;
class OverlayLayer : public DrawLayer
{
Q_DISABLE_COPY_MOVE(OverlayLayer)
public:
explicit OverlayLayer(std::shared_ptr<MapContext> context);
~OverlayLayer();
void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final;
void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final;
bool RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override final;
public slots:

View file

@ -139,7 +139,7 @@ void OverlayProductLayer::Initialize()
}
void OverlayProductLayer::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
const QMapLibre::CustomLayerRenderParameters& params)
{
gl::OpenGLFunctions& gl = context()->gl();
@ -436,12 +436,12 @@ std::string OverlayProductLayer::Impl::BuildHoverText(
}
bool OverlayProductLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler)
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler)
{
return DrawLayer::RunMousePicking(params,
mouseLocalPos,

View file

@ -16,15 +16,15 @@ public:
~OverlayProductLayer();
void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final;
void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final;
bool RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override final;
private:

View file

@ -124,7 +124,7 @@ void PlacefileLayer::Initialize()
}
void PlacefileLayer::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
const QMapLibre::CustomLayerRenderParameters& params)
{
gl::OpenGLFunctions& gl = context()->gl();

View file

@ -25,7 +25,7 @@ public:
void set_placefile_name(const std::string& placefileName);
void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final;
void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final;
void ReloadData();

View file

@ -261,7 +261,7 @@ void RadarProductLayer::UpdateSweep()
}
void RadarProductLayer::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
const QMapLibre::CustomLayerRenderParameters& params)
{
gl::OpenGLFunctions& gl = context()->gl();
@ -329,7 +329,7 @@ void RadarProductLayer::Deinitialize()
}
bool RadarProductLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& /* params */,
const QMapLibre::CustomLayerRenderParameters& /* params */,
const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos,
const glm::vec2& /* mouseCoords */,

View file

@ -18,15 +18,15 @@ public:
~RadarProductLayer();
void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final;
void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final;
virtual bool
RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override;
private:

View file

@ -15,13 +15,13 @@ namespace map
static const std::string logPrefix_ = "scwx::qt::map::radar_range_layer";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
static std::shared_ptr<QMapLibreGL::Feature>
GetRangeCircle(float range, QMapLibreGL::Coordinate center);
static std::shared_ptr<QMapLibre::Feature>
GetRangeCircle(float range, QMapLibre::Coordinate center);
void RadarRangeLayer::Add(std::shared_ptr<QMapLibreGL::Map> map,
float range,
QMapLibreGL::Coordinate center,
const QString& before)
void RadarRangeLayer::Add(std::shared_ptr<QMapLibre::Map> map,
float range,
QMapLibre::Coordinate center,
const QString& before)
{
static const QString layerId = QString::fromStdString(types::GetLayerName(
types::LayerType::Data, types::DataLayer::RadarRange));
@ -37,31 +37,30 @@ void RadarRangeLayer::Add(std::shared_ptr<QMapLibreGL::Map> map,
map->removeSource("rangeCircleSource");
}
std::shared_ptr<QMapLibreGL::Feature> rangeCircle =
std::shared_ptr<QMapLibre::Feature> rangeCircle =
GetRangeCircle(range, center);
map->addSource(
"rangeCircleSource",
{{"type", "geojson"}, {"data", QVariant::fromValue(*rangeCircle)}});
map->addLayer(
{{"id", layerId}, {"type", "line"}, {"source", "rangeCircleSource"}},
before);
layerId, {{"type", "line"}, {"source", "rangeCircleSource"}}, before);
map->setPaintProperty(layerId, "line-color", "rgba(128, 128, 128, 128)");
}
void RadarRangeLayer::Update(std::shared_ptr<QMapLibreGL::Map> map,
float range,
QMapLibreGL::Coordinate center)
void RadarRangeLayer::Update(std::shared_ptr<QMapLibre::Map> map,
float range,
QMapLibre::Coordinate center)
{
std::shared_ptr<QMapLibreGL::Feature> rangeCircle =
std::shared_ptr<QMapLibre::Feature> rangeCircle =
GetRangeCircle(range, center);
map->updateSource("rangeCircleSource",
{{"data", QVariant::fromValue(*rangeCircle)}});
}
static std::shared_ptr<QMapLibreGL::Feature>
GetRangeCircle(float range, QMapLibreGL::Coordinate center)
static std::shared_ptr<QMapLibre::Feature>
GetRangeCircle(float range, QMapLibre::Coordinate center)
{
const GeographicLib::Geodesic& geodesic(
util::GeographicLib::DefaultGeodesic());
@ -71,7 +70,7 @@ GetRangeCircle(float range, QMapLibreGL::Coordinate center)
float angle = -angleDeltaH;
QMapLibreGL::Coordinates geometry;
QMapLibre::Coordinates geometry;
for (uint16_t azimuth = 0; azimuth <= 720; ++azimuth)
{
@ -90,11 +89,11 @@ GetRangeCircle(float range, QMapLibreGL::Coordinate center)
angle += angleDelta;
}
std::shared_ptr<QMapLibreGL::Feature> rangeCircle =
std::make_shared<QMapLibreGL::Feature>(
QMapLibreGL::Feature::LineStringType,
std::initializer_list<QMapLibreGL::CoordinatesCollection> {
std::initializer_list<QMapLibreGL::Coordinates> {geometry}});
std::shared_ptr<QMapLibre::Feature> rangeCircle =
std::make_shared<QMapLibre::Feature>(
QMapLibre::Feature::LineStringType,
std::initializer_list<QMapLibre::CoordinatesCollection> {
std::initializer_list<QMapLibre::Coordinates> {geometry}});
return rangeCircle;
}

View file

@ -1,6 +1,6 @@
#pragma once
#include <QMapLibreGL/QMapLibreGL>
#include <qmaplibre.hpp>
namespace scwx
{
@ -11,13 +11,13 @@ namespace map
namespace RadarRangeLayer
{
void Add(std::shared_ptr<QMapLibreGL::Map> map,
float range,
QMapLibreGL::Coordinate center,
const QString& before = QString());
void Update(std::shared_ptr<QMapLibreGL::Map> map,
float range,
QMapLibreGL::Coordinate center);
void Add(std::shared_ptr<QMapLibre::Map> map,
float range,
QMapLibre::Coordinate center,
const QString& before = QString());
void Update(std::shared_ptr<QMapLibre::Map> map,
float range,
QMapLibre::Coordinate center);
} // namespace RadarRangeLayer
} // namespace map

View file

@ -6,7 +6,6 @@
#include <scwx/common/geographic.hpp>
#include <scwx/util/logger.hpp>
// #include <GeographicLib/Geodesic.hpp>
#include <imgui.h>
#include <mbgl/util/constants.hpp>
@ -26,7 +25,7 @@ public:
explicit Impl(RadarSiteLayer* self) : self_ {self} {}
~Impl() = default;
void RenderRadarSite(const QMapLibreGL::CustomLayerRenderParameters& params,
void RenderRadarSite(const QMapLibre::CustomLayerRenderParameters& params,
std::shared_ptr<config::RadarSite>& radarSite);
RadarSiteLayer* self_;
@ -58,7 +57,7 @@ void RadarSiteLayer::Initialize()
}
void RadarSiteLayer::Render(
const QMapLibreGL::CustomLayerRenderParameters& params)
const QMapLibre::CustomLayerRenderParameters& params)
{
gl::OpenGLFunctions& gl = context()->gl();
@ -90,8 +89,8 @@ void RadarSiteLayer::Render(
}
void RadarSiteLayer::Impl::RenderRadarSite(
const QMapLibreGL::CustomLayerRenderParameters& params,
std::shared_ptr<config::RadarSite>& radarSite)
const QMapLibre::CustomLayerRenderParameters& params,
std::shared_ptr<config::RadarSite>& radarSite)
{
const std::string windowName = fmt::format("radar-site-{}", radarSite->id());
@ -158,7 +157,7 @@ void RadarSiteLayer::Deinitialize()
}
bool RadarSiteLayer::RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& /* params */,
const QMapLibre::CustomLayerRenderParameters& /* params */,
const QPointF& /* mouseLocalPos */,
const QPointF& mouseGlobalPos,
const glm::vec2& /* mouseCoords */,

View file

@ -19,15 +19,15 @@ public:
~RadarSiteLayer();
void Initialize() override final;
void Render(const QMapLibreGL::CustomLayerRenderParameters&) override final;
void Render(const QMapLibre::CustomLayerRenderParameters&) override final;
void Deinitialize() override final;
bool RunMousePicking(
const QMapLibreGL::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
const QMapLibre::CustomLayerRenderParameters& params,
const QPointF& mouseLocalPos,
const QPointF& mouseGlobalPos,
const glm::vec2& mouseCoords,
const common::Coordinate& mouseGeoCoords,
std::shared_ptr<types::EventHandler>& eventHandler) override final;
signals:

View file

@ -46,6 +46,8 @@ public:
mapProvider_.SetDefault(defaultMapProviderValue);
mapboxApiKey_.SetDefault("?");
maptilerApiKey_.SetDefault("?");
showMapAttribution_.SetDefault(true);
showMapLogo_.SetDefault(true);
theme_.SetDefault(defaultThemeValue);
trackLocation_.SetDefault(false);
updateNotificationsEnabled_.SetDefault(true);
@ -142,6 +144,8 @@ public:
SettingsVariable<std::string> mapProvider_ {"map_provider"};
SettingsVariable<std::string> mapboxApiKey_ {"mapbox_api_key"};
SettingsVariable<std::string> maptilerApiKey_ {"maptiler_api_key"};
SettingsVariable<bool> showMapAttribution_ {"show_map_attribution"};
SettingsVariable<bool> showMapLogo_ {"show_map_logo"};
SettingsVariable<std::string> theme_ {"theme"};
SettingsVariable<bool> trackLocation_ {"track_location"};
SettingsVariable<bool> updateNotificationsEnabled_ {"update_notifications"};
@ -163,6 +167,8 @@ GeneralSettings::GeneralSettings() :
&p->mapProvider_,
&p->mapboxApiKey_,
&p->maptilerApiKey_,
&p->showMapAttribution_,
&p->showMapLogo_,
&p->theme_,
&p->trackLocation_,
&p->updateNotificationsEnabled_});
@ -240,6 +246,16 @@ SettingsVariable<std::string>& GeneralSettings::maptiler_api_key() const
return p->maptilerApiKey_;
}
SettingsVariable<bool>& GeneralSettings::show_map_attribution() const
{
return p->showMapAttribution_;
}
SettingsVariable<bool>& GeneralSettings::show_map_logo() const
{
return p->showMapLogo_;
}
SettingsVariable<std::string>& GeneralSettings::theme() const
{
return p->theme_;
@ -289,6 +305,8 @@ bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs)
lhs.p->mapProvider_ == rhs.p->mapProvider_ &&
lhs.p->mapboxApiKey_ == rhs.p->mapboxApiKey_ &&
lhs.p->maptilerApiKey_ == rhs.p->maptilerApiKey_ &&
lhs.p->showMapAttribution_ == rhs.p->showMapAttribution_ &&
lhs.p->showMapLogo_ == rhs.p->showMapLogo_ &&
lhs.p->theme_ == rhs.p->theme_ &&
lhs.p->trackLocation_ == rhs.p->trackLocation_ &&
lhs.p->updateNotificationsEnabled_ ==

View file

@ -38,6 +38,8 @@ public:
SettingsVariable<std::string>& map_provider() const;
SettingsVariable<std::string>& mapbox_api_key() const;
SettingsVariable<std::string>& maptiler_api_key() const;
SettingsVariable<bool>& show_map_attribution() const;
SettingsVariable<bool>& show_map_logo() const;
SettingsVariable<std::string>& theme() const;
SettingsVariable<bool>& track_location() const;
SettingsVariable<bool>& update_notifications_enabled() const;

View file

@ -15,19 +15,23 @@ static const std::string logPrefix_ = "scwx::qt::settings::text_settings";
static const std::string kAlteDIN1451Mittelscrhift_ {
"Alte DIN 1451 Mittelschrift"};
static const std::string kInconsolata_ {"Inconsolata"};
static const std::string kRobotoFlex_ {"Roboto Flex"};
static const std::string kRegular_ {"Regular"};
static const std::unordered_map<types::FontCategory, std::string>
kDefaultFontFamily_ {
{types::FontCategory::Default, kAlteDIN1451Mittelscrhift_},
{types::FontCategory::Tooltip, kInconsolata_}};
{types::FontCategory::Tooltip, kInconsolata_},
{types::FontCategory::Attribution, kRobotoFlex_}};
static const std::unordered_map<types::FontCategory, std::string>
kDefaultFontStyle_ {{types::FontCategory::Default, kRegular_},
{types::FontCategory::Tooltip, kRegular_}};
{types::FontCategory::Tooltip, kRegular_},
{types::FontCategory::Attribution, kRegular_}};
static const std::unordered_map<types::FontCategory, double>
kDefaultFontPointSize_ {{types::FontCategory::Default, 12.0},
{types::FontCategory::Tooltip, 10.5}};
{types::FontCategory::Tooltip, 10.5},
{types::FontCategory::Attribution, 9.0}};
class TextSettings::Impl
{

View file

@ -37,7 +37,8 @@ enum class Font
{
din1451alt,
din1451alt_g,
Inconsolata_Regular
Inconsolata_Regular,
RobotoFlex_Regular
};
} // namespace types

View file

@ -7,6 +7,11 @@ namespace qt
namespace types
{
void IconInfo::SetAnchor(float anchorX, float anchorY)
{
anchor_ = {anchorX, anchorY};
}
void IconInfo::UpdateTextureInfo()
{
texture_ = util::TextureAtlas::Instance().GetTextureAttributes(iconSheet_);
@ -27,8 +32,24 @@ void IconInfo::UpdateTextureInfo()
if (hotX_ == -1 || hotY_ == -1)
{
hotX_ = static_cast<std::int32_t>(iconWidth_ / 2);
hotY_ = static_cast<std::int32_t>(iconHeight_ / 2);
if (anchor_.has_value())
{
hotX_ =
std::clamp<std::int32_t>(static_cast<std::int32_t>(std::lround(
iconWidth_ * anchor_.value().first)),
0,
static_cast<std::int32_t>(iconWidth_));
hotY_ =
std::clamp<std::int32_t>(static_cast<std::int32_t>(std::lround(
iconHeight_ * anchor_.value().second)),
0,
static_cast<std::int32_t>(iconHeight_));
}
else
{
hotX_ = static_cast<std::int32_t>(iconWidth_ / 2);
hotY_ = static_cast<std::int32_t>(iconHeight_ / 2);
}
}
numIcons_ = columns_ * rows_;

View file

@ -2,7 +2,9 @@
#include <scwx/qt/util/texture_atlas.hpp>
#include <optional>
#include <string>
#include <utility>
namespace scwx
{
@ -26,6 +28,7 @@ struct IconInfo
{
}
void SetAnchor(float anchorX, float anchorY);
void UpdateTextureInfo();
std::string iconSheet_;
@ -39,6 +42,8 @@ struct IconInfo
std::size_t numIcons_ {};
float scaledWidth_ {};
float scaledHeight_ {};
std::optional<std::pair<float, float>> anchor_ {};
};
} // namespace types

View file

@ -14,6 +14,7 @@ namespace types
static const std::unordered_map<FontCategory, std::string> fontCategoryName_ {
{FontCategory::Default, "Default"},
{FontCategory::Tooltip, "Tooltip"},
{FontCategory::Attribution, "Attribution"},
{FontCategory::Unknown, "?"}};
static const std::unordered_map<TooltipMethod, std::string> tooltipMethodName_ {

View file

@ -15,10 +15,11 @@ enum class FontCategory
{
Default,
Tooltip,
Attribution,
Unknown
};
typedef scwx::util::
Iterator<FontCategory, FontCategory::Default, FontCategory::Tooltip>
Iterator<FontCategory, FontCategory::Default, FontCategory::Attribution>
FontCategoryIterator;
enum class TooltipMethod

View file

@ -21,7 +21,11 @@ static const std::unordered_map<ImageTexture, TextureInfo> imageTextureInfo_ {
{ImageTexture::Compass24,
{"images/compass-24", ":/res/icons/flaticon/compass-24.png"}},
{ImageTexture::Crosshairs24,
{"images/crosshairs-24", ":/res/textures/images/crosshairs-24.png"}}};
{"images/crosshairs-24", ":/res/textures/images/crosshairs-24.png"}},
{ImageTexture::MapboxLogo,
{"images/mapbox-logo", ":/res/textures/images/mapbox-logo.svg"}},
{ImageTexture::MapTilerLogo,
{"images/maptiler-logo", ":/res/textures/images/maptiler-logo.svg"}}};
static const std::unordered_map<LineTexture, TextureInfo> lineTextureInfo_ {
{LineTexture::Default1x7,

View file

@ -15,11 +15,13 @@ enum class ImageTexture
{
CardinalPoint24,
Compass24,
Crosshairs24
Crosshairs24,
MapboxLogo,
MapTilerLogo
};
typedef scwx::util::Iterator<ImageTexture,
ImageTexture::CardinalPoint24,
ImageTexture::Crosshairs24>
ImageTexture::MapTilerLogo>
ImageTextureIterator;
enum class LineTexture

View file

@ -130,6 +130,8 @@ public:
&theme_,
&defaultAlertAction_,
&antiAliasingEnabled_,
&showMapAttribution_,
&showMapLogo_,
&updateNotificationsEnabled_,
&debugEnabled_,
&alertAudioSoundFile_,
@ -220,6 +222,8 @@ public:
settings::SettingsInterface<std::string> defaultAlertAction_ {};
settings::SettingsInterface<std::string> theme_ {};
settings::SettingsInterface<bool> antiAliasingEnabled_ {};
settings::SettingsInterface<bool> showMapAttribution_ {};
settings::SettingsInterface<bool> showMapLogo_ {};
settings::SettingsInterface<bool> updateNotificationsEnabled_ {};
settings::SettingsInterface<bool> debugEnabled_ {};
@ -617,6 +621,13 @@ void SettingsDialogImpl::SetupGeneralTab()
generalSettings.anti_aliasing_enabled());
antiAliasingEnabled_.SetEditWidget(self_->ui->antiAliasingEnabledCheckBox);
showMapAttribution_.SetSettingsVariable(
generalSettings.show_map_attribution());
showMapAttribution_.SetEditWidget(self_->ui->showMapAttributionCheckBox);
showMapLogo_.SetSettingsVariable(generalSettings.show_map_logo());
showMapLogo_.SetEditWidget(self_->ui->showMapLogoCheckBox);
updateNotificationsEnabled_.SetSettingsVariable(
generalSettings.update_notifications_enabled());
updateNotificationsEnabled_.SetEditWidget(

View file

@ -322,6 +322,20 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showMapAttributionCheckBox">
<property name="text">
<string>Show Map Attribution</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showMapLogoCheckBox">
<property name="text">
<string>Show Map Logo</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="enableUpdateNotificationsCheckBox">
<property name="text">
@ -373,8 +387,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>514</width>
<height>382</height>
<width>66</width>
<height>18</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">

View file

@ -1,6 +1,6 @@
#include <scwx/qt/util/maplibre.hpp>
#include <QMapLibreGL/utils.hpp>
#include <QMapLibre/Utils>
#include <mbgl/util/constants.hpp>
namespace scwx
@ -13,14 +13,14 @@ namespace maplibre
{
units::length::meters<double>
GetMapDistance(const QMapLibreGL::CustomLayerRenderParameters& params)
GetMapDistance(const QMapLibre::CustomLayerRenderParameters& params)
{
return units::length::meters<double>(
QMapLibreGL::metersPerPixelAtLatitude(params.latitude, params.zoom) *
QMapLibre::metersPerPixelAtLatitude(params.latitude, params.zoom) *
(params.width + params.height) / 2.0);
}
glm::mat4 GetMapMatrix(const QMapLibreGL::CustomLayerRenderParameters& params)
glm::mat4 GetMapMatrix(const QMapLibre::CustomLayerRenderParameters& params)
{
glm::vec2 scale = GetMapScale(params);
@ -33,7 +33,7 @@ glm::mat4 GetMapMatrix(const QMapLibreGL::CustomLayerRenderParameters& params)
return mapMatrix;
}
glm::vec2 GetMapScale(const QMapLibreGL::CustomLayerRenderParameters& params)
glm::vec2 GetMapScale(const QMapLibre::CustomLayerRenderParameters& params)
{
const float scale = std::pow(2.0, params.zoom) * 2.0f *
mbgl::util::tileSize_D / mbgl::util::DEGREES_MAX;
@ -73,7 +73,7 @@ bool IsPointInPolygon(const std::vector<glm::vec2>& vertices,
return inPolygon;
}
glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate)
glm::vec2 LatLongToScreenCoordinate(const QMapLibre::Coordinate& coordinate)
{
static constexpr double RAD2DEG_D = 180.0 / M_PI;
@ -88,6 +88,26 @@ glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate)
return screen;
}
void SetMapStyleUrl(const std::shared_ptr<map::MapContext>& mapContext,
const std::string& url)
{
const auto mapProvider = mapContext->map_provider();
QString qUrl = QString::fromStdString(url);
if (mapProvider == map::MapProvider::MapTiler)
{
qUrl.append("?key=");
qUrl.append(map::GetMapProviderApiKey(mapProvider));
}
auto map = mapContext->map().lock();
if (map != nullptr)
{
map->setStyleUrl(qUrl);
}
}
} // namespace maplibre
} // namespace util
} // namespace qt

View file

@ -1,6 +1,9 @@
#pragma once
#include <QMapLibreGL/types.hpp>
#include <scwx/qt/map/map_context.hpp>
#include <QMapLibre/Map>
#include <QMapLibre/Types>
#include <glm/gtc/type_ptr.hpp>
#include <units/length.h>
@ -14,9 +17,9 @@ namespace maplibre
{
units::length::meters<double>
GetMapDistance(const QMapLibreGL::CustomLayerRenderParameters& params);
glm::mat4 GetMapMatrix(const QMapLibreGL::CustomLayerRenderParameters& params);
glm::vec2 GetMapScale(const QMapLibreGL::CustomLayerRenderParameters& params);
GetMapDistance(const QMapLibre::CustomLayerRenderParameters& params);
glm::mat4 GetMapMatrix(const QMapLibre::CustomLayerRenderParameters& params);
glm::vec2 GetMapScale(const QMapLibre::CustomLayerRenderParameters& params);
/**
* @brief Determine whether a point lies within a polygon
@ -29,7 +32,10 @@ glm::vec2 GetMapScale(const QMapLibreGL::CustomLayerRenderParameters& params);
bool IsPointInPolygon(const std::vector<glm::vec2>& vertices,
const glm::vec2& point);
glm::vec2 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate);
glm::vec2 LatLongToScreenCoordinate(const QMapLibre::Coordinate& coordinate);
void SetMapStyleUrl(const std::shared_ptr<map::MapContext>& mapContext,
const std::string& url);
} // namespace maplibre
} // namespace util

View file

@ -20,6 +20,9 @@
#include <stb_image.h>
#include <stb_rect_pack.h>
#include <QFile>
#include <QFileInfo>
#include <QPainter>
#include <QSvgRenderer>
#include <QUrl>
#if defined(_MSC_VER)
@ -49,6 +52,11 @@ public:
static std::shared_ptr<boost::gil::rgba8_image_t>
LoadImage(const std::string& imagePath);
static std::shared_ptr<boost::gil::rgba8_image_t>
ReadPngFile(const QString& imagePath);
static std::shared_ptr<boost::gil::rgba8_image_t>
ReadSvgFile(const QString& imagePath);
std::vector<std::shared_ptr<boost::gil::rgba8_image_t>>
registeredTextures_ {};
std::shared_mutex registeredTextureMutex_ {};
@ -376,34 +384,23 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath)
{
logger_->debug("Loading image: {}", imagePath);
std::shared_ptr<boost::gil::rgba8_image_t> image =
std::make_shared<boost::gil::rgba8_image_t>();
std::shared_ptr<boost::gil::rgba8_image_t> image = nullptr;
QUrl url = QUrl::fromUserInput(QString::fromStdString(imagePath));
QString qImagePath = QString::fromStdString(imagePath);
QUrl url = QUrl::fromUserInput(qImagePath);
if (url.isLocalFile())
{
QFile imageFile(imagePath.c_str());
QString suffix = QFileInfo(qImagePath).suffix().toLower();
imageFile.open(QIODevice::ReadOnly);
if (!imageFile.isOpen())
if (suffix == "svg")
{
logger_->error("Could not open image: {}", imagePath);
return nullptr;
image = ReadSvgFile(qImagePath);
}
boost::iostreams::stream<util::IoDeviceSource> dataStream(imageFile);
try
else
{
boost::gil::read_and_convert_image(
dataStream, *image, boost::gil::png_tag());
}
catch (const std::exception& ex)
{
logger_->error("Error reading image: {}", ex.what());
return nullptr;
image = ReadPngFile(qImagePath);
}
}
else
@ -442,6 +439,7 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath)
width * desiredChannels);
// Copy the view to the destination image
image = std::make_shared<boost::gil::rgba8_image_t>();
*image = boost::gil::rgba8_image_t(stbView);
auto& view = boost::gil::view(*image);
@ -477,6 +475,69 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath)
return image;
}
std::shared_ptr<boost::gil::rgba8_image_t>
TextureAtlas::Impl::ReadPngFile(const QString& imagePath)
{
QFile imageFile(imagePath);
imageFile.open(QIODevice::ReadOnly);
if (!imageFile.isOpen())
{
logger_->error("Could not open image: {}", imagePath.toStdString());
return nullptr;
}
boost::iostreams::stream<util::IoDeviceSource> dataStream(imageFile);
std::shared_ptr<boost::gil::rgba8_image_t> image =
std::make_shared<boost::gil::rgba8_image_t>();
try
{
boost::gil::read_and_convert_image(
dataStream, *image, boost::gil::png_tag());
}
catch (const std::exception& ex)
{
logger_->error("Error reading image: {}", ex.what());
return nullptr;
}
return image;
}
std::shared_ptr<boost::gil::rgba8_image_t>
TextureAtlas::Impl::ReadSvgFile(const QString& imagePath)
{
QSvgRenderer renderer {imagePath};
QPixmap pixmap {renderer.defaultSize()};
pixmap.fill(Qt::GlobalColor::transparent);
QPainter painter {&pixmap};
renderer.render(&painter, pixmap.rect());
QImage qImage = pixmap.toImage();
std::shared_ptr<boost::gil::rgba8_image_t> image = nullptr;
if (qImage.width() > 0 && qImage.height() > 0)
{
// Convert to ARGB32 format if not already (equivalent to bgra8_pixel_t)
qImage.convertTo(QImage::Format_ARGB32);
// Create a view pointing to the underlying QImage pixel data
auto view = boost::gil::interleaved_view(
qImage.width(),
qImage.height(),
reinterpret_cast<const boost::gil::bgra8_pixel_t*>(qImage.constBits()),
qImage.width() * 4);
image = std::make_shared<boost::gil::rgba8_image_t>(view);
}
return image;
}
TextureAtlas& TextureAtlas::Instance()
{
static TextureAtlas instance_ {};

View file

@ -2,7 +2,7 @@ call tools\setup-common.bat
set build_dir=build-debug
set build_type=Debug
set qt_version=6.6.1
set qt_version=6.6.2
mkdir %build_dir%
cmake -B %build_dir% -S . ^

View file

@ -3,7 +3,7 @@
build_dir=${1:-build-debug}
build_type=Debug
qt_version=6.6.1
qt_version=6.6.2
script_dir="$(dirname "$(readlink -f "$0")")"
mkdir -p ${build_dir}

View file

@ -2,7 +2,7 @@ call tools\setup-common.bat
set build_dir=build-release
set build_type=Release
set qt_version=6.6.1
set qt_version=6.6.2
mkdir %build_dir%
cmake -B %build_dir% -S . ^

View file

@ -3,7 +3,7 @@
build_dir=${1:-build-release}
build_type=Release
qt_version=6.6.1
qt_version=6.6.2
script_dir="$(dirname "$(readlink -f "$0")")"
mkdir -p ${build_dir}

@ -1 +1 @@
Subproject commit 0446ff708b387728faf8d2dbb3862a757067c2ee
Subproject commit 9cef3730c84d22803ea433fba8111826327dd82f

View file

@ -25,7 +25,7 @@ TEST(AwsLevel2DataProvider, FindKeyFixed)
TEST(AwsLevel2DataProvider, FindKeyNow)
{
AwsLevel2DataProvider provider("KLSX");
AwsLevel2DataProvider provider("KILX");
provider.Refresh();
std::string key = provider.FindKey(std::chrono::system_clock::now());
@ -78,7 +78,7 @@ TEST(AwsLevel2DataProvider, Prune)
TEST(AwsLevel2DataProvider, Refresh)
{
AwsLevel2DataProvider provider("KLSX");
AwsLevel2DataProvider provider("KILX");
auto [newObjects, totalObjects] = provider.Refresh();

View file

@ -25,7 +25,7 @@ TEST(AwsLevel3DataProvider, FindKeyFixed)
TEST(AwsLevel3DataProvider, FindKeyNow)
{
AwsLevel3DataProvider provider("KLSX", "N0B");
AwsLevel3DataProvider provider("KILX", "N0B");
provider.Refresh();
std::string key = provider.FindKey(std::chrono::system_clock::now());
@ -46,7 +46,7 @@ TEST(AwsLevel3DataProvider, LoadObjectByKey)
TEST(AwsLevel3DataProvider, Refresh)
{
AwsLevel3DataProvider provider("KLSX", "N0B");
AwsLevel3DataProvider provider("KILX", "N0B");
auto [newObjects, totalObjects] = provider.Refresh();
@ -58,7 +58,7 @@ TEST(AwsLevel3DataProvider, Refresh)
TEST(AwsLevel3DataProvider, GetAvailableProducts)
{
AwsLevel3DataProvider provider("KLSX", "N0B");
AwsLevel3DataProvider provider("KILX", "N0B");
provider.RequestAvailableProducts();
auto products = provider.GetAvailableProducts();

View file

@ -1,12 +1,14 @@
#include <scwx/qt/map/map_provider.hpp>
#include <scwx/qt/settings/general_settings.hpp>
#include <scwx/qt/util/maplibre.hpp>
#include <scwx/util/environment.hpp>
#include <scwx/util/logger.hpp>
#include <QCoreApplication>
#include <QMapLibreGL/QMapLibreGL>
#include <QTimer>
#include <gtest/gtest.h>
#include <qmaplibre.hpp>
#include <re2/re2.h>
namespace scwx
@ -45,22 +47,34 @@ TEST_P(ByMapProviderTest, MapProviderLayers)
// Configure map provider
const MapProviderInfo& mapProviderInfo = GetMapProviderInfo(mapProvider);
// Configure QMapLibreGL
QMapLibreGL::Settings mapSettings {};
mapSettings.resetToTemplate(mapProviderInfo.settingsTemplate_);
mapSettings.setApiKey(QString::fromStdString(apiKey));
// Configure QMapLibre
QMapLibre::Settings mapSettings {};
if (mapProvider == map::MapProvider::Mapbox)
{
mapSettings.setProviderTemplate(mapProviderInfo.providerTemplate_);
mapSettings.setApiKey(QString::fromStdString(apiKey));
}
else if (mapProvider == map::MapProvider::MapTiler)
{
settings::GeneralSettings::Instance().maptiler_api_key().SetValue(apiKey);
}
QMapLibreGL::Map map(nullptr, mapSettings, QSize(1, 1));
std::shared_ptr<map::MapContext> mapContext =
std::make_shared<map::MapContext>();
std::shared_ptr<QMapLibre::Map> map =
std::make_shared<QMapLibre::Map>(nullptr, mapSettings, QSize(1, 1));
mapContext->set_map(map);
mapContext->set_map_provider(mapProvider);
application.processEvents();
// Connect style load completion signal
QObject::connect(
&map,
&QMapLibreGL::Map::mapChanged,
[&](QMapLibreGL::Map::MapChange mapChange)
map.get(),
&QMapLibre::Map::mapChanged,
[&](QMapLibre::Map::MapChange mapChange)
{
if (mapChange ==
QMapLibreGL::Map::MapChange::MapChangeDidFinishLoadingStyle)
QMapLibre::Map::MapChange::MapChangeDidFinishLoadingStyle)
{
application.exit();
}
@ -88,7 +102,7 @@ TEST_P(ByMapProviderTest, MapProviderLayers)
// Load style
timeout = false;
map.setStyleUrl(QString::fromStdString(mapStyle.url_));
util::maplibre::SetMapStyleUrl(mapContext, mapStyle.url_);
timeoutTimer.start(5000ms);
application.exec();
timeoutTimer.stop();
@ -97,12 +111,12 @@ TEST_P(ByMapProviderTest, MapProviderLayers)
if (!timeout)
{
// Print layer names for debug
std::string layerIdsString = map.layerIds().join(", ").toStdString();
std::string layerIdsString = map->layerIds().join(", ").toStdString();
logger_->debug("{} Layers: [{}]", mapStyle.name_, layerIdsString);
// Search layer list
bool foundMatch = false;
for (const QString& qlayer : map.layerIds())
for (const QString& qlayer : map->layerIds())
{
const std::string layer = qlayer.toStdString();