Merge branch 'master' into macvcpkg

This commit is contained in:
Matthias Kuhn 2024-10-29 21:25:38 +01:00 committed by GitHub
commit d277e8420f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
212 changed files with 5541 additions and 2839 deletions

View File

@ -76,8 +76,6 @@ jobs:
-D FLEX_EXECUTABLE="${SOURCE_DIR}/win_flex.exe" \
-D BISON_EXECUTABLE="${SOURCE_DIR}/win_bison.exe" \
-D SIP_BUILD_EXECUTABLE="${BUILD_DIR}\vcpkg_installed\x64-windows-release\tools\python3\Scripts\sip-build.exe" \
-D PYUIC_PROGRAM="${BUILD_DIR}\vcpkg_installed\x64-windows-release\tools\python3\pyuic5.bat" \
-D PYRCC_PROGRAM="${BUILD_DIR}\vcpkg_installed\x64-windows-release\tools\python3\pyrcc5.bat" \
-D CMAKE_C_COMPILER_LAUNCHER=ccache \
-D CMAKE_CXX_COMPILER_LAUNCHER=ccache \
-D WITH_QTWEBKIT=OFF \

View File

@ -26,18 +26,19 @@ set (WITH_DESKTOP TRUE CACHE BOOL "Determines whether QGIS desktop should be bui
set (WITH_GUI TRUE CACHE BOOL "Determines whether QGIS GUI library should be built")
set(WITH_VCPKG FALSE CACHE BOOL "Use the vcpkg submodule for dependency management.")
set(WITH_VCPKG TRUE CACHE BOOL "Use the vcpkg submodule for dependency management.")
set(SDK_PATH "" CACHE STRING "Build with VCPKG SDK")
if(NOT SDK_PATH STREQUAL "")
message(STATUS "Building with SDK -- ${SDK_PATH}")
set(CMAKE_TOOLCHAIN_FILE "${SDK_PATH}/scripts/buildsystems/vcpkg.cmake")
set(VCPKG_INSTALL_PREFIX "${SDK_PATH}/installed")
if(APPLE AND NOT VCPKG_TARGET_TRIPLET)
message(FATAL_ERROR "VCPKG_TARGET_TRIPLET not set (set it to arm64-osx-dynamic-release or x64-osx-dynamic-release")
endif()
set(WITH_VCPKG ON)
elseif(WITH_VCPKG)
message(STATUS "Building local dependencies with VCPKG --")
set(VCPKG_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/vcpkg_installed")
include(VcpkgToolchain)
else()
message(STATUS "Building with system libraries --")
@ -49,6 +50,9 @@ if(WITH_VCPKG)
else()
list(APPEND CMAKE_PROGRAM_PATH "${VCPKG_INSTALL_PREFIX}/${VCPKG_TARGET_TRIPLET}/bin")
endif()
set(PREFER_INTERNAL_LIBS FALSE)
else()
set(PREFER_INTERNAL_LIBS TRUE)
endif()
#############################################################
@ -276,7 +280,8 @@ if(WITH_CORE)
endif()
# try to configure and build POLY2TRI support
set (WITH_INTERNAL_POLY2TRI TRUE CACHE BOOL "Determines whether POLY2TRI should be built from internal copy")
set (WITH_INTERNAL_POLY2TRI ${PREFER_INTERNAL_LIBS} CACHE BOOL "Determines whether POLY2TRI should be built from internal copy")
set (WITH_INTERNAL_MESHOPTIMIZER ${PREFER_INTERNAL_LIBS} CACHE BOOL "Determines whether MESHOPTIMIZER should be built from internal copy")
# try to configure and build POSTGRESQL support
set (WITH_POSTGRESQL TRUE CACHE BOOL "Determines whether POSTGRESQL support should be built")
@ -389,7 +394,7 @@ if(WITH_CORE)
find_package(EXPAT REQUIRED)
find_package(Spatialindex REQUIRED)
find_package(LibZip REQUIRED)
set (WITH_INTERNAL_NLOHMANN_JSON ON CACHE BOOL "Determines whether the vendored copy of nlohmann-json should be used")
set (WITH_INTERNAL_NLOHMANN_JSON ${PREFER_INTERNAL_LIBS} CACHE BOOL "Determines whether the vendored copy of nlohmann-json should be used")
find_package(nlohmann_json REQUIRED)
# The following bypasses the FindSQLite3 module introduced in CMake 3.14

View File

@ -26,17 +26,17 @@ Building QGIS from source - step by step
* [3.11.3. Additional tools for QGIS development](#3113-additional-tools-for-qgis-development)
* [4. Building on Windows](#4-building-on-windows)
* [4.1. Building with Microsoft Visual Studio](#41-building-with-microsoft-visual-studio)
* [4.1.1. Visual Studio 2019 Community Edition](#411-visual-studio-2019-community-edition)
* [4.1.1. Visual Studio 2022 Community Edition](#411-visual-studio-2022-community-edition)
* [4.1.2. Other tools and dependencies](#412-other-tools-and-dependencies)
* [4.1.3. Clone the QGIS Source Code](#413-clone-the-qgis-source-code)
* [4.1.4. OSGeo4W](#414-OSGeo4W)
* [4.1.4. OSGeo4W](#414-osgeo4w)
* [4.2. Building on Linux with mingw64](#42-building-on-linux-with-mingw64)
* [4.2.1. Building with Docker](#421-building-with-docker)
* [4.2.1.1. Initial setup](#4211-initial-setup)
* [4.2.1.2. Building the dependencies](#4212-building-the-dependencies)
* [4.2.1.3. Cross-Building QGIS](#4213-cross-building-qgis)
* [4.2.2. Testing QGIS](#422-testing-qgis)
* [4.3 Building for Qt 6 with VCPKG in Microsoft Visual Studio](#41-building-with-qt6)
* [4.3 Building for Qt 6 with VCPKG in Microsoft Visual Studio](43-building-on-windows-with-vcpkg)
* [5. Building on MacOS X](#5-building-on-macos-x)
* [5.1. Install Developer Tools](#51-install-developer-tools)
* [5.2. Install CMake and other build tools](#52-install-cmake-and-other-build-tools)

View File

@ -11,19 +11,28 @@
##
MACRO(ADD_QGIS_RESOURCES SOURCE_PREFIX TARGET_PREFIX DEST_FILES SOURCE_FILE_PATHS)
# On build copy all resource files to build folder
# Create a list of all copy commands, source paths and destination paths
SET(ALL_COPY_COMMANDS "")
SET(ALL_SOURCE_FILES "")
FOREACH(RESOURCE_FILE ${SOURCE_FILE_PATHS})
ADD_CUSTOM_COMMAND(
OUTPUT "${CMAKE_BINARY_DIR}/output/data/${TARGET_PREFIX}/${RESOURCE_FILE}"
LIST(APPEND ALL_COPY_COMMANDS
COMMAND ${CMAKE_COMMAND} -E copy
"${SOURCE_PREFIX}/${RESOURCE_FILE}"
"${CMAKE_BINARY_DIR}/output/data/${TARGET_PREFIX}/${RESOURCE_FILE}"
DEPENDS "${SOURCE_PREFIX}/${RESOURCE_FILE}"
)
LIST(APPEND ALL_SOURCE_FILES "${SOURCE_PREFIX}/${RESOURCE_FILE}")
LIST(APPEND ${DEST_FILES}
"${CMAKE_BINARY_DIR}/output/data/${TARGET_PREFIX}/${RESOURCE_FILE}")
ENDFOREACH(RESOURCE_FILE)
# Add a single custom command to install all resources to system resource folder
ADD_CUSTOM_COMMAND(
OUTPUT ${${DEST_FILES}}
${ALL_COPY_COMMANDS}
COMMENT "Copying '${TARGET_PREFIX}' resources"
DEPENDS ${ALL_SOURCE_FILES}
)
# Install resources to system resource folder
FOREACH(RESOURCE_FILE ${SOURCE_FILE_PATHS})
GET_FILENAME_COMPONENT(PATH_NAME "${TARGET_PREFIX}/${RESOURCE_FILE}" PATH)

View File

@ -39,25 +39,33 @@ ELSE(SIP_VERSION)
STRING(REGEX REPLACE ".*\nsip_version_num:([^\n]+).*$" "\\1" SIP_VERSION_NUM ${sip_config})
STRING(REGEX REPLACE ".*\nsip_version_str:([^\n]+).*$" "\\1" SIP_VERSION_STR ${sip_config})
STRING(REGEX REPLACE ".*\ndefault_sip_dir:([^\n]+).*$" "\\1" SIP_DEFAULT_SIP_DIR ${sip_config})
IF(NOT SIP_FIND_QUIETLY)
MESSAGE(STATUS "Found SIP version: ${SIP_VERSION_STR}")
ENDIF(NOT SIP_FIND_QUIETLY)
IF(${SIP_VERSION_STR} VERSION_LESS 5)
STRING(REGEX REPLACE ".*\nsip_bin:([^\n]+).*$" "\\1" SIP_BINARY_PATH ${sip_config})
STRING(REGEX REPLACE ".*\nsip_inc_dir:([^\n]+).*$" "\\1" SIP_INCLUDE_DIR ${sip_config})
STRING(REGEX REPLACE ".*\nsip_module_dir:([^\n]+).*$" "\\1" SIP_MODULE_DIR ${sip_config})
SET(SIP_FOUND TRUE)
ELSE(${SIP_VERSION_STR} VERSION_LESS 5)
FIND_PROGRAM(SIP_BUILD_EXECUTABLE sip-build)
IF(SIP_BUILD_EXECUTABLE)
IF(NOT SIP_FIND_QUIETLY)
MESSAGE(STATUS "Found sip-build executable: ${SIP_BUILD_EXECUTABLE}")
ENDIF(NOT SIP_FIND_QUIETLY)
SET(SIP_FOUND TRUE)
ELSE(SIP_BUILD_EXECUTABLE)
MESSAGE (FATAL_ERROR "Could not find sip-build executable")
ENDIF(SIP_BUILD_EXECUTABLE)
ENDIF(${SIP_VERSION_STR} VERSION_LESS 5)
SET(SIP_FOUND TRUE)
ENDIF(sip_config)
IF(SIP_FOUND)
IF(NOT SIP_FIND_QUIETLY)
MESSAGE(STATUS "Found SIP version: ${SIP_VERSION_STR}")
ENDIF(NOT SIP_FIND_QUIETLY)
ELSE(SIP_FOUND)
IF(NOT SIP_FOUND)
IF(SIP_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find SIP")
ENDIF(SIP_FIND_REQUIRED)
ENDIF(SIP_FOUND)
ENDIF(NOT SIP_FOUND)
ENDIF(SIP_VERSION)

View File

@ -153,12 +153,12 @@ The number of planes is equal to the size of ``clipPlaneEquations``.
A plane equation contains 4 elements.
A simple way to define a clip plane equation is to define a normalized normal to
the plane and its distance from the origin of the scene.
In that case, the first 3 elements are the coordinates of the normal of the plane as (X, Y, Z).
In that case, the first 3 elements are the coordinates of the normal of the plane as ``(X, Y, Z)``.
They need to be normalized.
The last element is the distance of the plane from the origin of the scene.
In mathematical terms, a 3d plane can be defined with the equation ax+by+cz+d=0
The normal is (a, b, c) with |a, b, c| = 1
The distance is -d.
In mathematical terms, a 3d plane can be defined with the equation ``ax+by+cz+d=0``
The normal is ``(a, b, c)`` with ``|a, b, c| = 1``
The distance is ``-d``.
By default, OpenGL supports up to 8 additional clipping planes. If ``clipPlaneEquations``
contains more than 8 planes, only the first 8 ones will be used.

View File

@ -191,9 +191,9 @@ Returns transform for individual objects represented by the symbol
Sets transform for individual objects represented by the symbol
%End
QMatrix4x4 billboardTransform() const;
float billboardHeight() const;
%Docstring
Returns transform for billboards
Returns how much the billboard should be elevated upwards
%End
private:

View File

@ -425,8 +425,8 @@ QgsPhongTexturedMaterialSettings.type: src/3d/materials/qgsphongtexturedmaterial
QgsPhongTexturedMaterialSettings.writeXml: src/3d/materials/qgsphongtexturedmaterialsettings.h#L127
QgsPhongTexturedMaterialSettings: src/3d/materials/qgsphongtexturedmaterialsettings.h#L36
QgsPoint3DSymbol.altitudeClamping: src/3d/symbols/qgspoint3dsymbol.h#L64
QgsPoint3DSymbol.billboardHeight: src/3d/symbols/qgspoint3dsymbol.h#L168
QgsPoint3DSymbol.billboardSymbol: src/3d/symbols/qgspoint3dsymbol.h#L158
QgsPoint3DSymbol.billboardTransform: src/3d/symbols/qgspoint3dsymbol.h#L168
QgsPoint3DSymbol.clone: src/3d/symbols/qgspoint3dsymbol.h#L56
QgsPoint3DSymbol.create: src/3d/symbols/qgspoint3dsymbol.h#L53
QgsPoint3DSymbol.materialSettings: src/3d/symbols/qgspoint3dsymbol.h#L69

View File

@ -153,12 +153,12 @@ The number of planes is equal to the size of ``clipPlaneEquations``.
A plane equation contains 4 elements.
A simple way to define a clip plane equation is to define a normalized normal to
the plane and its distance from the origin of the scene.
In that case, the first 3 elements are the coordinates of the normal of the plane as (X, Y, Z).
In that case, the first 3 elements are the coordinates of the normal of the plane as ``(X, Y, Z)``.
They need to be normalized.
The last element is the distance of the plane from the origin of the scene.
In mathematical terms, a 3d plane can be defined with the equation ax+by+cz+d=0
The normal is (a, b, c) with |a, b, c| = 1
The distance is -d.
In mathematical terms, a 3d plane can be defined with the equation ``ax+by+cz+d=0``
The normal is ``(a, b, c)`` with ``|a, b, c| = 1``
The distance is ``-d``.
By default, OpenGL supports up to 8 additional clipping planes. If ``clipPlaneEquations``
contains more than 8 planes, only the first 8 ones will be used.

View File

@ -191,9 +191,9 @@ Returns transform for individual objects represented by the symbol
Sets transform for individual objects represented by the symbol
%End
QMatrix4x4 billboardTransform() const;
float billboardHeight() const;
%Docstring
Returns transform for billboards
Returns how much the billboard should be elevated upwards
%End
private:

View File

@ -425,8 +425,8 @@ QgsPhongTexturedMaterialSettings.type: src/3d/materials/qgsphongtexturedmaterial
QgsPhongTexturedMaterialSettings.writeXml: src/3d/materials/qgsphongtexturedmaterialsettings.h#L127
QgsPhongTexturedMaterialSettings: src/3d/materials/qgsphongtexturedmaterialsettings.h#L36
QgsPoint3DSymbol.altitudeClamping: src/3d/symbols/qgspoint3dsymbol.h#L64
QgsPoint3DSymbol.billboardHeight: src/3d/symbols/qgspoint3dsymbol.h#L168
QgsPoint3DSymbol.billboardSymbol: src/3d/symbols/qgspoint3dsymbol.h#L158
QgsPoint3DSymbol.billboardTransform: src/3d/symbols/qgspoint3dsymbol.h#L168
QgsPoint3DSymbol.clone: src/3d/symbols/qgspoint3dsymbol.h#L56
QgsPoint3DSymbol.create: src/3d/symbols/qgspoint3dsymbol.h#L53
QgsPoint3DSymbol.materialSettings: src/3d/symbols/qgspoint3dsymbol.h#L69

View File

@ -653,9 +653,6 @@ except ModuleNotFoundError:
QgsGeometry.as_shapely = _geometry_as_shapely
QgsRasterBlock.as_numpy.__doc__ = """
Returns the block data as a numpy array.
@ -665,6 +662,7 @@ If `use_masking` is `True` then the returned array will be a numpy masked array,
.. versionadded:: 3.40
"""
QgsRasterLayer.as_numpy.__doc__ = """
Returns the layer data as a numpy array.
@ -676,6 +674,19 @@ If `bands` is provided, only the specified bands will be included in the returne
.. versionadded:: 3.40
"""
QgsGeometry.as_numpy.__doc__ = """Returns the geometry data as a numpy array or list of numpy arrays."""
QgsGeometry.as_shapely.__doc__ = """Returns the geometry data as a shapely object."""
QgsGeometry.as_numpy.__doc__ = """
Returns the geometry data as a numpy array or list of numpy arrays.
:raises QgsNotSupportedException: if numpy is not available on the system
.. versionadded:: 3.40
"""
QgsGeometry.as_shapely.__doc__ = """
Returns the geometry data as a shapely object.
:raises QgsNotSupportedException: if shapely is not available on the system
.. versionadded:: 3.40
"""

View File

@ -13,7 +13,7 @@ try:
except NameError:
pass
try:
QgsLayoutExporter.ImageExportSettings.__attribute_docs__ = {'dpi': 'Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.', 'imageSize': "Manual size in pixels for output image. If imageSize is not\nset then it will be automatically calculated based on the\noutput dpi and layout size.\n\nIf cropToContents is ``True`` then imageSize has no effect.\n\nBe careful when specifying manual sizes if pages in the layout\nhave differing sizes! It's likely not going to give a reasonable\noutput in this case, and the automatic dpi-based image size should be\nused instead.", 'cropToContents': 'Set to ``True`` if image should be cropped so only parts of the layout\ncontaining items are exported.', 'cropMargins': 'Crop to content margins, in pixels. These margins will be added\nto the bounds of the exported layout if cropToContents is ``True``.', 'pages': 'List of specific pages to export, or an empty list to\nexport all pages.\n\nPage numbers are 0 index based, so the first page in the\nlayout corresponds to page 0.', 'generateWorldFile': 'Set to ``True`` to generate an external world file alongside\nexported images.', 'exportMetadata': "Indicates whether image export should include metadata generated\nfrom the layout's project's metadata.\n\n.. versionadded:: 3.2", 'flags': 'Layout context flags, which control how the export will be created.', 'predefinedMapScales': 'A list of predefined scales to use with the layout. This is used\nfor maps which are set to the predefined atlas scaling mode.\n\n.. versionadded:: 3.10'}
QgsLayoutExporter.ImageExportSettings.__attribute_docs__ = {'dpi': 'Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.', 'imageSize': "Manual size in pixels for output image. If imageSize is not\nset then it will be automatically calculated based on the\noutput dpi and layout size.\n\nIf cropToContents is ``True`` then imageSize has no effect.\n\nBe careful when specifying manual sizes if pages in the layout\nhave differing sizes! It's likely not going to give a reasonable\noutput in this case, and the automatic dpi-based image size should be\nused instead.", 'cropToContents': 'Set to ``True`` if image should be cropped so only parts of the layout\ncontaining items are exported.', 'cropMargins': 'Crop to content margins, in pixels. These margins will be added\nto the bounds of the exported layout if cropToContents is ``True``.', 'pages': 'List of specific pages to export, or an empty list to\nexport all pages.\n\nPage numbers are 0 index based, so the first page in the\nlayout corresponds to page 0.', 'generateWorldFile': 'Set to ``True`` to generate an external world file alongside\nexported images.', 'exportMetadata': "Indicates whether image export should include metadata generated\nfrom the layout's project's metadata.\n\n.. versionadded:: 3.2", 'flags': 'Layout context flags, which control how the export will be created.', 'predefinedMapScales': 'A list of predefined scales to use with the layout. This is used\nfor maps which are set to the predefined atlas scaling mode.\n\n.. versionadded:: 3.10', 'quality': 'Image quality, typically used for JPEG compression (whose quality ranges from 1 to 100)\nif quality is set to -1, the default quality will be used.\n\n.. versionadded:: 3.42'}
QgsLayoutExporter.ImageExportSettings.__doc__ = """Contains settings relating to exporting layouts to raster images"""
QgsLayoutExporter.ImageExportSettings.__group__ = ['layout']
except NameError:

View File

@ -1,11 +1,16 @@
# The following has been generated automatically from src/core/qgsrenderchecker.h
# monkey patching scoped based enum
QgsRenderChecker.Flag.AvoidExportingRenderedImage.__doc__ = "Avoids exporting rendered images to reports"
QgsRenderChecker.Flag.Silent.__doc__ = "Don't output non-critical messages to console \n.. versionadded:: 3.40"
QgsRenderChecker.Flag.__doc__ = """Render checker flags.
.. versionadded:: 3.28
* ``AvoidExportingRenderedImage``: Avoids exporting rendered images to reports
* ``Silent``: Don't output non-critical messages to console
.. versionadded:: 3.40
"""
# --

View File

@ -1,6 +1,6 @@
# The following has been generated automatically from src/core/qgstemporalutils.h
try:
QgsTemporalUtils.AnimationExportSettings.__attribute_docs__ = {'animationRange': 'Dictates the overall temporal range of the animation.', 'frameDuration': 'Duration of individual export frames', 'outputDirectory': 'Destination directory for created image files.', 'fileNameTemplate': "The filename template for exporting the frames.\n\nThis must be in format prefix####.format, where number of\n``# ``characters represents how many 0's should be left-padded to the frame number\ne.g. my###.jpg will create frames my001.jpg, my002.jpg, etc", 'decorations': 'List of decorations to draw onto exported frames.', 'availableTemporalRanges': 'Contains the list of all available temporal ranges which have data available.\n\nThe list can be a list of non-contiguous ranges (i.e. containing gaps)\nwhich together describe the complete range of times which contain data.\n\nThis list is required whenever the :py:class:`QgsUnitTypes`.TemporalIrregularStep interval is used\nfor an animation.\n\n.. versionadded:: 3.30', 'frameRate': 'Target animation frame rate in frames per second.\n\n.. versionadded:: 3.26'}
QgsTemporalUtils.AnimationExportSettings.__attribute_docs__ = {'animationRange': 'Dictates the overall temporal range of the animation.', 'frameDuration': 'Duration of individual export frames', 'outputDirectory': 'Destination directory for created image files.', 'fileNameTemplate': "The filename template for exporting the frames.\n\nThis must be in format ``prefix####.format``, where number of\n````#`` ``characters represents how many 0's should be left-padded to the frame number\ne.g. ``my###.jpg`` will create frames ``my001.jpg``, ``my002.jpg``, etc", 'decorations': 'List of decorations to draw onto exported frames.', 'availableTemporalRanges': 'Contains the list of all available temporal ranges which have data available.\n\nThe list can be a list of non-contiguous ranges (i.e. containing gaps)\nwhich together describe the complete range of times which contain data.\n\nThis list is required whenever the :py:class:`QgsUnitTypes`.TemporalIrregularStep interval is used\nfor an animation.\n\n.. versionadded:: 3.30', 'frameRate': 'Target animation frame rate in frames per second.\n\n.. versionadded:: 3.26'}
QgsTemporalUtils.AnimationExportSettings.__doc__ = """Contains settings relating to exporting animations"""
except NameError:
pass

View File

@ -80,7 +80,7 @@ Initializes the storage.
.. note::
The default implementation does nothing and returns ``True``.
The default implementation does nothing and returns ``True``.
This method is called by the authentication manager when the storage is added to the manager.
%End

View File

@ -36,7 +36,7 @@ extent of a geometry or collection of geometries.
public:
QgsBox3D( SIP_PYOBJECT x /TypeHint="Optional[Union[QgsPoint, QgsRectangle, float]]"/ = Py_None, SIP_PYOBJECT y /TypeHint="Optional[QgsPoint, float]"/ = Py_None, SIP_PYOBJECT z /TypeHint="Optional[Union[bool, float]]"/ = Py_None, SIP_PYOBJECT x2 /TypeHint="Optional[Union[bool, float]]"/ = Py_None, SIP_PYOBJECT y2 /TypeHint="Optional[float]"/ = Py_None, SIP_PYOBJECT z2 /TypeHint="Optional[float]"/ = Py_None, SIP_PYOBJECT n /TypeHint="Optional[bool]"/ = Py_None ) [( double x = 0.0, double y = 0.0, double z = 0.0, double x2 = 0.0, double y2 = 0.0, double z2 = 0.0, bool n = true )];
QgsBox3D( SIP_PYOBJECT x /TypeHint="Optional[Union[QgsPoint, QgsVector3D, QgsRectangle, float]]"/ = Py_None, SIP_PYOBJECT y /TypeHint="Optional[QgsPoint, QgsVector3D, float]"/ = Py_None, SIP_PYOBJECT z /TypeHint="Optional[Union[bool, float]]"/ = Py_None, SIP_PYOBJECT x2 /TypeHint="Optional[Union[bool, float]]"/ = Py_None, SIP_PYOBJECT y2 /TypeHint="Optional[float]"/ = Py_None, SIP_PYOBJECT z2 /TypeHint="Optional[float]"/ = Py_None, SIP_PYOBJECT n /TypeHint="Optional[bool]"/ = Py_None ) [( double x = 0.0, double y = 0.0, double z = 0.0, double x2 = 0.0, double y2 = 0.0, double z2 = 0.0, bool n = true )];
%Docstring
Constructor for QgsBox3D which accepts the ranges of x/y/z coordinates. If ``normalize`` is ``False`` then
the normalization step will not be applied automatically.
@ -85,6 +85,30 @@ the normalization step will not be applied automatically.
}
}
}
else if ( sipCanConvertToType( a0, sipType_QgsVector3D, SIP_NOT_NONE ) && sipCanConvertToType( a1, sipType_QgsVector3D, SIP_NOT_NONE ) && a3 == Py_None && a4 == Py_None && a5 == Py_None && a6 == Py_None )
{
int state;
sipIsErr = 0;
QgsVector3D *corner1 = reinterpret_cast<QgsVector3D *>( sipConvertToType( a0, sipType_QgsVector3D, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( corner1, sipType_QgsVector3D, state );
}
else
{
QgsVector3D *corner2 = reinterpret_cast<QgsVector3D *>( sipConvertToType( a1, sipType_QgsVector3D, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( corner2, sipType_QgsVector3D, state );
}
else
{
bool n = a2 == Py_None ? true : PyObject_IsTrue( a2 );
sipCpp = new QgsBox3D( *corner1, *corner2, n );
}
}
}
else if (
( a0 == Py_None || PyFloat_AsDouble( a0 ) != -1.0 || !PyErr_Occurred() ) &&
( a1 == Py_None || PyFloat_AsDouble( a1 ) != -1.0 || !PyErr_Occurred() ) &&
@ -375,6 +399,13 @@ If no ``center`` point is specified then the current center of the box will be u
Scale the rectangle around a center coordinates.
.. versionadded:: 3.26
%End
void grow( double delta );
%Docstring
Grows the box in place by the specified amount in all dimensions.
.. versionadded:: 3.42
%End
bool isNull() const /HoldGIL/;

View File

@ -2957,7 +2957,7 @@ geometry will retain the same dimensionality as the input geometry.
:param maxAngle: maximum angle at node (0-180) at which smoothing will be applied
%End
static QgsGeometryEngine *createGeometryEngine( const QgsAbstractGeometry *geometry, double precision = 0.0 ) /Factory/;
static QgsGeometryEngine *createGeometryEngine( const QgsAbstractGeometry *geometry, double precision = 0.0, Qgis::GeosCreationFlags flags = Qgis::GeosCreationFlag::SkipEmptyInteriorRings ) /Factory/;
%Docstring
Creates and returns a new geometry engine representing the specified ``geometry`` using ``precision`` on a grid. The ``precision`` argument was added in 3.36.
@ -2972,6 +2972,8 @@ Many methods available in the :py:class:`QgsGeometryEngine` class can benefit fr
a large number of spatial relationships will be tested (such as calling :py:func:`~QgsGeometry.intersects`, :py:func:`~QgsGeometry.within`, etc) then the
geometry should first be prepared by calling :py:func:`~QgsGeometry.prepareGeometry` before performing the tests.
The ``flags`` argument was added in QGIS 3.40 to allow control over the resultant GEOS geometry.
Example
-------------------------------------

View File

@ -643,6 +643,17 @@ If ``useZValues`` is ``True`` then z values will also be considered when testing
QVector<QgsLineString *> splitToDisjointXYParts() const /Factory/;
%Docstring
Divides the linestring into parts that don't share any points or lines.
This method throws away Z and M coordinates.
The ownership of returned pointers is transferred to the caller.
.. versionadded:: 3.40
%End
double length3D() const /HoldGIL/;
%Docstring
Returns the length in 3D world of the line string.

View File

@ -24,6 +24,7 @@ Handles rendering and exports of layouts to various formats.
struct PageExportDetails
{
QString directory;
@ -142,6 +143,9 @@ Returns the rendered image, or a null QImage if the image does not fit into avai
QVector<qreal> predefinedMapScales;
int quality;
};
ExportResult exportToImage( const QString &filePath, const QgsLayoutExporter::ImageExportSettings &settings );

View File

@ -111,6 +111,15 @@ Deselects any selected nodes.
virtual double estimatedFrameBleed() const;
virtual bool isValid() const = 0;
%Docstring
Must be reimplemented in subclasses.
Typically a polyline is valid if it has at least 2 distinct nodes,
while a polygon is valid if it has at least 3 distinct nodes.
.. versionadded:: 3.40
%End
protected:
QgsLayoutNodesItem( QgsLayout *layout );

View File

@ -53,6 +53,8 @@ The caller takes responsibility for deleting the returned object.
virtual QgsGeometry clipPath() const;
virtual bool isValid() const;
QgsFillSymbol *symbol();
%Docstring

View File

@ -55,6 +55,8 @@ The caller takes responsibility for deleting the returned object.
virtual QPainterPath shape() const;
virtual bool isValid() const;
QgsLineSymbol *symbol();
%Docstring

View File

@ -368,6 +368,13 @@ Returns a reference to the collection's guide collection, which manages page sna
%End
void applyPropertiesToAllOtherPages( int sourcePage );
%Docstring
Apply the source page properties (size & background color) to all other pages
.. versionadded:: 3.42
%End
public slots:
void redraw();

View File

@ -301,6 +301,7 @@ Emitted when point cloud generation state is changed
protected:
};
/************************************************************************

View File

@ -183,6 +183,7 @@ Sets the largest allowable difference in size between the rendered and the expec
enum class Flag /BaseType=IntFlag/
{
AvoidExportingRenderedImage,
Silent,
};
typedef QFlags<QgsRenderChecker::Flag> Flags;

View File

@ -1345,66 +1345,66 @@ QgsAuthConfigSslServer.sslPeerVerifyMode: src/core/auth/qgsauthconfig.h#L418
QgsAuthConfigSslServer.sslProtocol: src/core/auth/qgsauthconfig.h#L406
QgsAuthConfigSslServer.version: src/core/auth/qgsauthconfig.h#L435
QgsAuthConfigSslServer: src/core/auth/qgsauthconfig.h#L389
QgsAuthConfigurationStorage.authMethodConfigs: src/core/auth/qgsauthconfigurationstorage.h#L164
QgsAuthConfigurationStorage.authMethodConfigsWithPayload: src/core/auth/qgsauthconfigurationstorage.h#L174
QgsAuthConfigurationStorage.authSettingExists: src/core/auth/qgsauthconfigurationstorage.h#L241
QgsAuthConfigurationStorage.authSettingsChanged: src/core/auth/qgsauthconfigurationstorage.h#L524
QgsAuthConfigurationStorage.capabilities: src/core/auth/qgsauthconfigurationstorage.h#L118
QgsAuthConfigurationStorage.certAuthorityChanged: src/core/auth/qgsauthconfigurationstorage.h#L542
QgsAuthConfigurationStorage.certAuthorityExists: src/core/auth/qgsauthconfigurationstorage.h#L394
QgsAuthConfigurationStorage.certAuthorityIds: src/core/auth/qgsauthconfigurationstorage.h#L378
QgsAuthConfigurationStorage.certIdentityChanged: src/core/auth/qgsauthconfigurationstorage.h#L537
QgsAuthConfigurationStorage.certIdentityExists: src/core/auth/qgsauthconfigurationstorage.h#L298
QgsAuthConfigurationStorage.certIdentityIds: src/core/auth/qgsauthconfigurationstorage.h#L290
QgsAuthConfigurationStorage.certTrustPolicyExists: src/core/auth/qgsauthconfigurationstorage.h#L449
QgsAuthConfigurationStorage.clearMasterPasswords: src/core/auth/qgsauthconfigurationstorage.h#L473
QgsAuthConfigurationStorage.clearMethodConfigs: src/core/auth/qgsauthconfigurationstorage.h#L488
QgsAuthConfigurationStorage.authMethodConfigs: src/core/auth/qgsauthconfigurationstorage.h#L165
QgsAuthConfigurationStorage.authMethodConfigsWithPayload: src/core/auth/qgsauthconfigurationstorage.h#L175
QgsAuthConfigurationStorage.authSettingExists: src/core/auth/qgsauthconfigurationstorage.h#L242
QgsAuthConfigurationStorage.authSettingsChanged: src/core/auth/qgsauthconfigurationstorage.h#L525
QgsAuthConfigurationStorage.capabilities: src/core/auth/qgsauthconfigurationstorage.h#L119
QgsAuthConfigurationStorage.certAuthorityChanged: src/core/auth/qgsauthconfigurationstorage.h#L543
QgsAuthConfigurationStorage.certAuthorityExists: src/core/auth/qgsauthconfigurationstorage.h#L395
QgsAuthConfigurationStorage.certAuthorityIds: src/core/auth/qgsauthconfigurationstorage.h#L379
QgsAuthConfigurationStorage.certIdentityChanged: src/core/auth/qgsauthconfigurationstorage.h#L538
QgsAuthConfigurationStorage.certIdentityExists: src/core/auth/qgsauthconfigurationstorage.h#L299
QgsAuthConfigurationStorage.certIdentityIds: src/core/auth/qgsauthconfigurationstorage.h#L291
QgsAuthConfigurationStorage.certTrustPolicyExists: src/core/auth/qgsauthconfigurationstorage.h#L450
QgsAuthConfigurationStorage.clearMasterPasswords: src/core/auth/qgsauthconfigurationstorage.h#L474
QgsAuthConfigurationStorage.clearMethodConfigs: src/core/auth/qgsauthconfigurationstorage.h#L489
QgsAuthConfigurationStorage.description: src/core/auth/qgsauthconfigurationstorage.h#L87
QgsAuthConfigurationStorage.erase: src/core/auth/qgsauthconfigurationstorage.h#L480
QgsAuthConfigurationStorage.erase: src/core/auth/qgsauthconfigurationstorage.h#L481
QgsAuthConfigurationStorage.id: src/core/auth/qgsauthconfigurationstorage.h#L93
QgsAuthConfigurationStorage.initialize: src/core/auth/qgsauthconfigurationstorage.h#L102
QgsAuthConfigurationStorage.isEnabled: src/core/auth/qgsauthconfigurationstorage.h#L138
QgsAuthConfigurationStorage.isEncrypted: src/core/auth/qgsauthconfigurationstorage.h#L133
QgsAuthConfigurationStorage.isReadOnly: src/core/auth/qgsauthconfigurationstorage.h#L157
QgsAuthConfigurationStorage.isReady: src/core/auth/qgsauthconfigurationstorage.h#L113
QgsAuthConfigurationStorage.lastError: src/core/auth/qgsauthconfigurationstorage.h#L107
QgsAuthConfigurationStorage.loadAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L225
QgsAuthConfigurationStorage.loadCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L386
QgsAuthConfigurationStorage.loadCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L268
QgsAuthConfigurationStorage.loadCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L433
QgsAuthConfigurationStorage.loadMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L184
QgsAuthConfigurationStorage.loadSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L323
QgsAuthConfigurationStorage.loadSslCertCustomConfigByHost: src/core/auth/qgsauthconfigurationstorage.h#L331
QgsAuthConfigurationStorage.loggerTag: src/core/auth/qgsauthconfigurationstorage.h#L578
QgsAuthConfigurationStorage.masterPasswordChanged: src/core/auth/qgsauthconfigurationstorage.h#L519
QgsAuthConfigurationStorage.messageLog: src/core/auth/qgsauthconfigurationstorage.h#L500
QgsAuthConfigurationStorage.methodConfigChanged: src/core/auth/qgsauthconfigurationstorage.h#L514
QgsAuthConfigurationStorage.methodConfigExists: src/core/auth/qgsauthconfigurationstorage.h#L208
QgsAuthConfigurationStorage.initialize: src/core/auth/qgsauthconfigurationstorage.h#L103
QgsAuthConfigurationStorage.isEnabled: src/core/auth/qgsauthconfigurationstorage.h#L139
QgsAuthConfigurationStorage.isEncrypted: src/core/auth/qgsauthconfigurationstorage.h#L134
QgsAuthConfigurationStorage.isReadOnly: src/core/auth/qgsauthconfigurationstorage.h#L158
QgsAuthConfigurationStorage.isReady: src/core/auth/qgsauthconfigurationstorage.h#L114
QgsAuthConfigurationStorage.lastError: src/core/auth/qgsauthconfigurationstorage.h#L108
QgsAuthConfigurationStorage.loadAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L226
QgsAuthConfigurationStorage.loadCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L387
QgsAuthConfigurationStorage.loadCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L269
QgsAuthConfigurationStorage.loadCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L434
QgsAuthConfigurationStorage.loadMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L185
QgsAuthConfigurationStorage.loadSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L324
QgsAuthConfigurationStorage.loadSslCertCustomConfigByHost: src/core/auth/qgsauthconfigurationstorage.h#L332
QgsAuthConfigurationStorage.loggerTag: src/core/auth/qgsauthconfigurationstorage.h#L579
QgsAuthConfigurationStorage.masterPasswordChanged: src/core/auth/qgsauthconfigurationstorage.h#L520
QgsAuthConfigurationStorage.messageLog: src/core/auth/qgsauthconfigurationstorage.h#L501
QgsAuthConfigurationStorage.methodConfigChanged: src/core/auth/qgsauthconfigurationstorage.h#L515
QgsAuthConfigurationStorage.methodConfigExists: src/core/auth/qgsauthconfigurationstorage.h#L209
QgsAuthConfigurationStorage.name: src/core/auth/qgsauthconfigurationstorage.h#L74
QgsAuthConfigurationStorage.readOnlyChanged: src/core/auth/qgsauthconfigurationstorage.h#L529
QgsAuthConfigurationStorage.removeAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L233
QgsAuthConfigurationStorage.removeCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L402
QgsAuthConfigurationStorage.removeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L260
QgsAuthConfigurationStorage.removeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L306
QgsAuthConfigurationStorage.removeCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L441
QgsAuthConfigurationStorage.removeMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L200
QgsAuthConfigurationStorage.removeSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L363
QgsAuthConfigurationStorage.setCapabilities: src/core/auth/qgsauthconfigurationstorage.h#L561
QgsAuthConfigurationStorage.setEnabled: src/core/auth/qgsauthconfigurationstorage.h#L144
QgsAuthConfigurationStorage.setError: src/core/auth/qgsauthconfigurationstorage.h#L566
QgsAuthConfigurationStorage.setReadOnly: src/core/auth/qgsauthconfigurationstorage.h#L151
QgsAuthConfigurationStorage.sslCertCustomConfigChanged: src/core/auth/qgsauthconfigurationstorage.h#L547
QgsAuthConfigurationStorage.sslCertCustomConfigExists: src/core/auth/qgsauthconfigurationstorage.h#L354
QgsAuthConfigurationStorage.sslCertCustomConfigIds: src/core/auth/qgsauthconfigurationstorage.h#L345
QgsAuthConfigurationStorage.sslCertTrustPolicyChanged: src/core/auth/qgsauthconfigurationstorage.h#L552
QgsAuthConfigurationStorage.storageChanged: src/core/auth/qgsauthconfigurationstorage.h#L509
QgsAuthConfigurationStorage.storeAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L217
QgsAuthConfigurationStorage.storeCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L371
QgsAuthConfigurationStorage.storeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L252
QgsAuthConfigurationStorage.storeCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L425
QgsAuthConfigurationStorage.storeMasterPassword: src/core/auth/qgsauthconfigurationstorage.h#L466
QgsAuthConfigurationStorage.storeMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L193
QgsAuthConfigurationStorage.storeSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L314
QgsAuthConfigurationStorage.readOnlyChanged: src/core/auth/qgsauthconfigurationstorage.h#L530
QgsAuthConfigurationStorage.removeAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L234
QgsAuthConfigurationStorage.removeCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L403
QgsAuthConfigurationStorage.removeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L261
QgsAuthConfigurationStorage.removeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L307
QgsAuthConfigurationStorage.removeCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L442
QgsAuthConfigurationStorage.removeMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L201
QgsAuthConfigurationStorage.removeSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L364
QgsAuthConfigurationStorage.setCapabilities: src/core/auth/qgsauthconfigurationstorage.h#L562
QgsAuthConfigurationStorage.setEnabled: src/core/auth/qgsauthconfigurationstorage.h#L145
QgsAuthConfigurationStorage.setError: src/core/auth/qgsauthconfigurationstorage.h#L567
QgsAuthConfigurationStorage.setReadOnly: src/core/auth/qgsauthconfigurationstorage.h#L152
QgsAuthConfigurationStorage.sslCertCustomConfigChanged: src/core/auth/qgsauthconfigurationstorage.h#L548
QgsAuthConfigurationStorage.sslCertCustomConfigExists: src/core/auth/qgsauthconfigurationstorage.h#L355
QgsAuthConfigurationStorage.sslCertCustomConfigIds: src/core/auth/qgsauthconfigurationstorage.h#L346
QgsAuthConfigurationStorage.sslCertTrustPolicyChanged: src/core/auth/qgsauthconfigurationstorage.h#L553
QgsAuthConfigurationStorage.storageChanged: src/core/auth/qgsauthconfigurationstorage.h#L510
QgsAuthConfigurationStorage.storeAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L218
QgsAuthConfigurationStorage.storeCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L372
QgsAuthConfigurationStorage.storeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L253
QgsAuthConfigurationStorage.storeCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L426
QgsAuthConfigurationStorage.storeMasterPassword: src/core/auth/qgsauthconfigurationstorage.h#L467
QgsAuthConfigurationStorage.storeMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L194
QgsAuthConfigurationStorage.storeSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L315
QgsAuthConfigurationStorage.type: src/core/auth/qgsauthconfigurationstorage.h#L81
QgsAuthConfigurationStorage: src/core/auth/qgsauthconfigurationstorage.h#L36
QgsAuthConfigurationStorageDb.authDatabaseConnection: src/core/auth/qgsauthconfigurationstoragedb.h#L75
@ -4884,7 +4884,7 @@ QgsGeometry.Error.hasWhere: src/core/geometry/qgsgeometry.h#L2776
QgsGeometry.Error.what: src/core/geometry/qgsgeometry.h#L2766
QgsGeometry.Error.where: src/core/geometry/qgsgeometry.h#L2771
QgsGeometry.Error: src/core/geometry/qgsgeometry.h#L2747
QgsGeometry.QVariant: src/core/geometry/qgsgeometry.h#L3183
QgsGeometry.QVariant: src/core/geometry/qgsgeometry.h#L3185
QgsGeometry.QgsGeometry: src/core/geometry/qgsgeometry.h#L184
QgsGeometry.__repr__: src/core/geometry/qgsgeometry.h#L2185
QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L930
@ -4938,8 +4938,8 @@ QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1465
QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1472
QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1483
QgsGeometry.convertGeometryCollectionToSubclass: src/core/geometry/qgsgeometry.h#L2609
QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3170
QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3177
QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3172
QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3179
QgsGeometry.convertToCurvedMultiType: src/core/geometry/qgsgeometry.h#L2587
QgsGeometry.convertToCurves: src/core/geometry/qgsgeometry.h#L1674
QgsGeometry.convertToMultiType: src/core/geometry/qgsgeometry.h#L2570
@ -4947,7 +4947,7 @@ QgsGeometry.convertToSingleType: src/core/geometry/qgsgeometry.h#L2598
QgsGeometry.convertToStraightSegment: src/core/geometry/qgsgeometry.h#L2843
QgsGeometry.convertToType: src/core/geometry/qgsgeometry.h#L2252
QgsGeometry.convexHull: src/core/geometry/qgsgeometry.h#L1804
QgsGeometry.createGeometryEngine: src/core/geometry/qgsgeometry.h#L3163
QgsGeometry.createGeometryEngine: src/core/geometry/qgsgeometry.h#L3165
QgsGeometry.createPolygonFromQPolygonF: src/core/geometry/qgsgeometry.h#L2952
QgsGeometry.createPolylineFromQPolygonF: src/core/geometry/qgsgeometry.h#L2943
QgsGeometry.createWedgeBuffer: src/core/geometry/qgsgeometry.h#L347
@ -6710,29 +6710,29 @@ QgsLayoutEffect.compositionMode: src/core/layout/qgslayouteffect.h#L60
QgsLayoutEffect.draw: src/core/layout/qgslayouteffect.h#L64
QgsLayoutEffect.setCompositionMode: src/core/layout/qgslayouteffect.h#L51
QgsLayoutEffect: src/core/layout/qgslayouteffect.h#L36
QgsLayoutExporter.computeWorldFileParameters: src/core/layout/qgslayoutexporter.h#L664
QgsLayoutExporter.computeWorldFileParameters: src/core/layout/qgslayoutexporter.h#L671
QgsLayoutExporter.containsAdvancedEffects: src/core/layout/qgslayoutexporter.h#L690
QgsLayoutExporter.errorFile: src/core/layout/qgslayoutexporter.h#L608
QgsLayoutExporter.errorMessage: src/core/layout/qgslayoutexporter.h#L615
QgsLayoutExporter.exportToImage: src/core/layout/qgslayoutexporter.h#L246
QgsLayoutExporter.exportToImage: src/core/layout/qgslayoutexporter.h#L259
QgsLayoutExporter.exportToPdf: src/core/layout/qgslayoutexporter.h#L406
QgsLayoutExporter.exportToPdf: src/core/layout/qgslayoutexporter.h#L419
QgsLayoutExporter.exportToPdfs: src/core/layout/qgslayoutexporter.h#L435
QgsLayoutExporter.exportToSvg: src/core/layout/qgslayoutexporter.h#L587
QgsLayoutExporter.computeWorldFileParameters: src/core/layout/qgslayoutexporter.h#L676
QgsLayoutExporter.computeWorldFileParameters: src/core/layout/qgslayoutexporter.h#L683
QgsLayoutExporter.containsAdvancedEffects: src/core/layout/qgslayoutexporter.h#L702
QgsLayoutExporter.errorFile: src/core/layout/qgslayoutexporter.h#L620
QgsLayoutExporter.errorMessage: src/core/layout/qgslayoutexporter.h#L627
QgsLayoutExporter.exportToImage: src/core/layout/qgslayoutexporter.h#L258
QgsLayoutExporter.exportToImage: src/core/layout/qgslayoutexporter.h#L271
QgsLayoutExporter.exportToPdf: src/core/layout/qgslayoutexporter.h#L418
QgsLayoutExporter.exportToPdf: src/core/layout/qgslayoutexporter.h#L431
QgsLayoutExporter.exportToPdfs: src/core/layout/qgslayoutexporter.h#L447
QgsLayoutExporter.exportToSvg: src/core/layout/qgslayoutexporter.h#L599
QgsLayoutExporter.generateFileName: src/core/layout/qgslayoutexporter.h#L699
QgsLayoutExporter.georeferenceOutput: src/core/layout/qgslayoutexporter.h#L655
QgsLayoutExporter.layout: src/core/layout/qgslayoutexporter.h#L90
QgsLayoutExporter.print: src/core/layout/qgslayoutexporter.h#L480
QgsLayoutExporter.print: src/core/layout/qgslayoutexporter.h#L489
QgsLayoutExporter.renderPage: src/core/layout/qgslayoutexporter.h#L100
QgsLayoutExporter.renderPageToImage: src/core/layout/qgslayoutexporter.h#L120
QgsLayoutExporter.renderRegion: src/core/layout/qgslayoutexporter.h#L129
QgsLayoutExporter.renderRegionToImage: src/core/layout/qgslayoutexporter.h#L147
QgsLayoutExporter.requiresRasterization: src/core/layout/qgslayoutexporter.h#L681
QgsLayoutExporter: src/core/layout/qgslayoutexporter.h#L50
QgsLayoutExporter.exportToSvg: src/core/layout/qgslayoutexporter.h#L611
QgsLayoutExporter.generateFileName: src/core/layout/qgslayoutexporter.h#L711
QgsLayoutExporter.georeferenceOutput: src/core/layout/qgslayoutexporter.h#L667
QgsLayoutExporter.layout: src/core/layout/qgslayoutexporter.h#L94
QgsLayoutExporter.print: src/core/layout/qgslayoutexporter.h#L492
QgsLayoutExporter.print: src/core/layout/qgslayoutexporter.h#L501
QgsLayoutExporter.renderPage: src/core/layout/qgslayoutexporter.h#L104
QgsLayoutExporter.renderPageToImage: src/core/layout/qgslayoutexporter.h#L124
QgsLayoutExporter.renderRegion: src/core/layout/qgslayoutexporter.h#L133
QgsLayoutExporter.renderRegionToImage: src/core/layout/qgslayoutexporter.h#L151
QgsLayoutExporter.requiresRasterization: src/core/layout/qgslayoutexporter.h#L693
QgsLayoutExporter: src/core/layout/qgslayoutexporter.h#L51
QgsLayoutFrame.cleanup: src/core/layout/qgslayoutframe.h#L54
QgsLayoutFrame.create: src/core/layout/qgslayoutframe.h#L46
QgsLayoutFrame.createExpressionContext: src/core/layout/qgslayoutframe.h#L112
@ -7567,53 +7567,55 @@ QgsLayoutItemPicture.svgStrokeWidth: src/core/layout/qgslayoutitempicture.h#L209
QgsLayoutItemPicture.type: src/core/layout/qgslayoutitempicture.h#L63
QgsLayoutItemPicture.writePropertiesToElement: src/core/layout/qgslayoutitempicture.h#L313
QgsLayoutItemPicture: src/core/layout/qgslayoutitempicture.h#L34
QgsLayoutItemPolygon._addNode: src/core/layout/qgslayoutitempolygon.h#L76
QgsLayoutItemPolygon._draw: src/core/layout/qgslayoutitempolygon.h#L78
QgsLayoutItemPolygon._readXmlStyle: src/core/layout/qgslayoutitempolygon.h#L79
QgsLayoutItemPolygon._removeNode: src/core/layout/qgslayoutitempolygon.h#L77
QgsLayoutItemPolygon._writeXmlStyle: src/core/layout/qgslayoutitempolygon.h#L80
QgsLayoutItemPolygon._addNode: src/core/layout/qgslayoutitempolygon.h#L77
QgsLayoutItemPolygon._draw: src/core/layout/qgslayoutitempolygon.h#L79
QgsLayoutItemPolygon._readXmlStyle: src/core/layout/qgslayoutitempolygon.h#L80
QgsLayoutItemPolygon._removeNode: src/core/layout/qgslayoutitempolygon.h#L78
QgsLayoutItemPolygon._writeXmlStyle: src/core/layout/qgslayoutitempolygon.h#L81
QgsLayoutItemPolygon.accept: src/core/layout/qgslayoutitempolygon.h#L58
QgsLayoutItemPolygon.clipPath: src/core/layout/qgslayoutitempolygon.h#L60
QgsLayoutItemPolygon.create: src/core/layout/qgslayoutitempolygon.h#L53
QgsLayoutItemPolygon.displayName: src/core/layout/qgslayoutitempolygon.h#L57
QgsLayoutItemPolygon.icon: src/core/layout/qgslayoutitempolygon.h#L56
QgsLayoutItemPolygon.isValid: src/core/layout/qgslayoutitempolygon.h#L61
QgsLayoutItemPolygon.itemFlags: src/core/layout/qgslayoutitempolygon.h#L59
QgsLayoutItemPolygon.setSymbol: src/core/layout/qgslayoutitempolygon.h#L73
QgsLayoutItemPolygon.symbol: src/core/layout/qgslayoutitempolygon.h#L66
QgsLayoutItemPolygon.setSymbol: src/core/layout/qgslayoutitempolygon.h#L74
QgsLayoutItemPolygon.symbol: src/core/layout/qgslayoutitempolygon.h#L67
QgsLayoutItemPolygon.type: src/core/layout/qgslayoutitempolygon.h#L55
QgsLayoutItemPolygon: src/core/layout/qgslayoutitempolygon.h#L29
QgsLayoutItemPolyline._addNode: src/core/layout/qgslayoutitempolyline.h#L197
QgsLayoutItemPolyline._draw: src/core/layout/qgslayoutitempolyline.h#L199
QgsLayoutItemPolyline._readXmlStyle: src/core/layout/qgslayoutitempolyline.h#L200
QgsLayoutItemPolyline._removeNode: src/core/layout/qgslayoutitempolyline.h#L198
QgsLayoutItemPolyline._writeXmlStyle: src/core/layout/qgslayoutitempolyline.h#L201
QgsLayoutItemPolyline.accept: src/core/layout/qgslayoutitempolyline.h#L193
QgsLayoutItemPolyline.arrowHeadFillColor: src/core/layout/qgslayoutitempolyline.h#L170
QgsLayoutItemPolyline.arrowHeadStrokeColor: src/core/layout/qgslayoutitempolyline.h#L156
QgsLayoutItemPolyline.arrowHeadStrokeWidth: src/core/layout/qgslayoutitempolyline.h#L191
QgsLayoutItemPolyline.arrowHeadWidth: src/core/layout/qgslayoutitempolyline.h#L121
QgsLayoutItemPolyline._addNode: src/core/layout/qgslayoutitempolyline.h#L198
QgsLayoutItemPolyline._draw: src/core/layout/qgslayoutitempolyline.h#L200
QgsLayoutItemPolyline._readXmlStyle: src/core/layout/qgslayoutitempolyline.h#L201
QgsLayoutItemPolyline._removeNode: src/core/layout/qgslayoutitempolyline.h#L199
QgsLayoutItemPolyline._writeXmlStyle: src/core/layout/qgslayoutitempolyline.h#L202
QgsLayoutItemPolyline.accept: src/core/layout/qgslayoutitempolyline.h#L194
QgsLayoutItemPolyline.arrowHeadFillColor: src/core/layout/qgslayoutitempolyline.h#L171
QgsLayoutItemPolyline.arrowHeadStrokeColor: src/core/layout/qgslayoutitempolyline.h#L157
QgsLayoutItemPolyline.arrowHeadStrokeWidth: src/core/layout/qgslayoutitempolyline.h#L192
QgsLayoutItemPolyline.arrowHeadWidth: src/core/layout/qgslayoutitempolyline.h#L122
QgsLayoutItemPolyline.create: src/core/layout/qgslayoutitempolyline.h#L63
QgsLayoutItemPolyline.displayName: src/core/layout/qgslayoutitempolyline.h#L67
QgsLayoutItemPolyline.endMarker: src/core/layout/qgslayoutitempolyline.h#L102
QgsLayoutItemPolyline.endSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L149
QgsLayoutItemPolyline.endMarker: src/core/layout/qgslayoutitempolyline.h#L103
QgsLayoutItemPolyline.endSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L150
QgsLayoutItemPolyline.icon: src/core/layout/qgslayoutitempolyline.h#L66
QgsLayoutItemPolyline.readPropertiesFromElement: src/core/layout/qgslayoutitempolyline.h#L203
QgsLayoutItemPolyline.setArrowHeadFillColor: src/core/layout/qgslayoutitempolyline.h#L177
QgsLayoutItemPolyline.setArrowHeadStrokeColor: src/core/layout/qgslayoutitempolyline.h#L163
QgsLayoutItemPolyline.setArrowHeadStrokeWidth: src/core/layout/qgslayoutitempolyline.h#L184
QgsLayoutItemPolyline.setArrowHeadWidth: src/core/layout/qgslayoutitempolyline.h#L115
QgsLayoutItemPolyline.setEndMarker: src/core/layout/qgslayoutitempolyline.h#L109
QgsLayoutItemPolyline.setEndSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L142
QgsLayoutItemPolyline.setStartMarker: src/core/layout/qgslayoutitempolyline.h#L95
QgsLayoutItemPolyline.setStartSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L128
QgsLayoutItemPolyline.setSymbol: src/core/layout/qgslayoutitempolyline.h#L81
QgsLayoutItemPolyline.isValid: src/core/layout/qgslayoutitempolyline.h#L69
QgsLayoutItemPolyline.readPropertiesFromElement: src/core/layout/qgslayoutitempolyline.h#L204
QgsLayoutItemPolyline.setArrowHeadFillColor: src/core/layout/qgslayoutitempolyline.h#L178
QgsLayoutItemPolyline.setArrowHeadStrokeColor: src/core/layout/qgslayoutitempolyline.h#L164
QgsLayoutItemPolyline.setArrowHeadStrokeWidth: src/core/layout/qgslayoutitempolyline.h#L185
QgsLayoutItemPolyline.setArrowHeadWidth: src/core/layout/qgslayoutitempolyline.h#L116
QgsLayoutItemPolyline.setEndMarker: src/core/layout/qgslayoutitempolyline.h#L110
QgsLayoutItemPolyline.setEndSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L143
QgsLayoutItemPolyline.setStartMarker: src/core/layout/qgslayoutitempolyline.h#L96
QgsLayoutItemPolyline.setStartSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L129
QgsLayoutItemPolyline.setSymbol: src/core/layout/qgslayoutitempolyline.h#L82
QgsLayoutItemPolyline.shape: src/core/layout/qgslayoutitempolyline.h#L68
QgsLayoutItemPolyline.startMarker: src/core/layout/qgslayoutitempolyline.h#L88
QgsLayoutItemPolyline.startSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L135
QgsLayoutItemPolyline.symbol: src/core/layout/qgslayoutitempolyline.h#L74
QgsLayoutItemPolyline.startMarker: src/core/layout/qgslayoutitempolyline.h#L89
QgsLayoutItemPolyline.startSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L136
QgsLayoutItemPolyline.symbol: src/core/layout/qgslayoutitempolyline.h#L75
QgsLayoutItemPolyline.type: src/core/layout/qgslayoutitempolyline.h#L65
QgsLayoutItemPolyline.updateBoundingRect: src/core/layout/qgslayoutitempolyline.h#L207
QgsLayoutItemPolyline.writePropertiesToElement: src/core/layout/qgslayoutitempolyline.h#L202
QgsLayoutItemPolyline.updateBoundingRect: src/core/layout/qgslayoutitempolyline.h#L208
QgsLayoutItemPolyline.writePropertiesToElement: src/core/layout/qgslayoutitempolyline.h#L203
QgsLayoutItemPolyline: src/core/layout/qgslayoutitempolyline.h#L32
QgsLayoutItemRegistry.addLayoutItemType: src/core/layout/qgslayoutitemregistry.h#L429
QgsLayoutItemRegistry.addLayoutMultiFrameType: src/core/layout/qgslayoutitemregistry.h#L435
@ -7853,33 +7855,34 @@ QgsLayoutMultiFrameAbstractMetadata.resolvePaths: src/core/layout/qgslayoutitemr
QgsLayoutMultiFrameAbstractMetadata.type: src/core/layout/qgslayoutitemregistry.h#L204
QgsLayoutMultiFrameAbstractMetadata.visibleName: src/core/layout/qgslayoutitemregistry.h#L214
QgsLayoutMultiFrameAbstractMetadata: src/core/layout/qgslayoutitemregistry.h#L186
QgsLayoutNodesItem._addNode: src/core/layout/qgslayoutitemnodeitem.h#L140
QgsLayoutNodesItem._draw: src/core/layout/qgslayoutitemnodeitem.h#L146
QgsLayoutNodesItem._readXmlStyle: src/core/layout/qgslayoutitemnodeitem.h#L149
QgsLayoutNodesItem._removeNode: src/core/layout/qgslayoutitemnodeitem.h#L143
QgsLayoutNodesItem._writeXmlStyle: src/core/layout/qgslayoutitemnodeitem.h#L152
QgsLayoutNodesItem._addNode: src/core/layout/qgslayoutitemnodeitem.h#L149
QgsLayoutNodesItem._draw: src/core/layout/qgslayoutitemnodeitem.h#L155
QgsLayoutNodesItem._readXmlStyle: src/core/layout/qgslayoutitemnodeitem.h#L158
QgsLayoutNodesItem._removeNode: src/core/layout/qgslayoutitemnodeitem.h#L152
QgsLayoutNodesItem._writeXmlStyle: src/core/layout/qgslayoutitemnodeitem.h#L161
QgsLayoutNodesItem.addNode: src/core/layout/qgslayoutitemnodeitem.h#L54
QgsLayoutNodesItem.boundingRect: src/core/layout/qgslayoutitemnodeitem.h#L110
QgsLayoutNodesItem.computeDistance: src/core/layout/qgslayoutitemnodeitem.h#L161
QgsLayoutNodesItem.computeDistance: src/core/layout/qgslayoutitemnodeitem.h#L170
QgsLayoutNodesItem.deselectNode: src/core/layout/qgslayoutitemnodeitem.h#L107
QgsLayoutNodesItem.draw: src/core/layout/qgslayoutitemnodeitem.h#L128
QgsLayoutNodesItem.draw: src/core/layout/qgslayoutitemnodeitem.h#L137
QgsLayoutNodesItem.estimatedFrameBleed: src/core/layout/qgslayoutitemnodeitem.h#L114
QgsLayoutNodesItem.itemFlags: src/core/layout/qgslayoutitemnodeitem.h#L129
QgsLayoutNodesItem.isValid: src/core/layout/qgslayoutitemnodeitem.h#L123
QgsLayoutNodesItem.itemFlags: src/core/layout/qgslayoutitemnodeitem.h#L138
QgsLayoutNodesItem.moveNode: src/core/layout/qgslayoutitemnodeitem.h#L66
QgsLayoutNodesItem.nodeAtPosition: src/core/layout/qgslayoutitemnodeitem.h#L76
QgsLayoutNodesItem.nodePosition: src/core/layout/qgslayoutitemnodeitem.h#L84
QgsLayoutNodesItem.nodes: src/core/layout/qgslayoutitemnodeitem.h#L44
QgsLayoutNodesItem.nodesSize: src/core/layout/qgslayoutitemnodeitem.h#L92
QgsLayoutNodesItem.readPropertiesFromElement: src/core/layout/qgslayoutitemnodeitem.h#L131
QgsLayoutNodesItem.readPropertiesFromElement: src/core/layout/qgslayoutitemnodeitem.h#L140
QgsLayoutNodesItem.removeNode: src/core/layout/qgslayoutitemnodeitem.h#L89
QgsLayoutNodesItem.rescaleToFitBoundingBox: src/core/layout/qgslayoutitemnodeitem.h#L158
QgsLayoutNodesItem.rescaleToFitBoundingBox: src/core/layout/qgslayoutitemnodeitem.h#L167
QgsLayoutNodesItem.selectedNode: src/core/layout/qgslayoutitemnodeitem.h#L102
QgsLayoutNodesItem.setDisplayNodes: src/core/layout/qgslayoutitemnodeitem.h#L59
QgsLayoutNodesItem.setNodes: src/core/layout/qgslayoutitemnodeitem.h#L38
QgsLayoutNodesItem.setSelectedNode: src/core/layout/qgslayoutitemnodeitem.h#L97
QgsLayoutNodesItem.updateBoundingRect: src/core/layout/qgslayoutitemnodeitem.h#L175
QgsLayoutNodesItem.updateSceneRect: src/core/layout/qgslayoutitemnodeitem.h#L164
QgsLayoutNodesItem.writePropertiesToElement: src/core/layout/qgslayoutitemnodeitem.h#L130
QgsLayoutNodesItem.updateBoundingRect: src/core/layout/qgslayoutitemnodeitem.h#L184
QgsLayoutNodesItem.updateSceneRect: src/core/layout/qgslayoutitemnodeitem.h#L173
QgsLayoutNodesItem.writePropertiesToElement: src/core/layout/qgslayoutitemnodeitem.h#L139
QgsLayoutNodesItem: src/core/layout/qgslayoutitemnodeitem.h#L28
QgsLayoutNorthArrowHandler.arrowRotation: src/core/layout/qgslayoutnortharrowhandler.h#L52
QgsLayoutNorthArrowHandler.arrowRotationChanged: src/core/layout/qgslayoutnortharrowhandler.h#L99
@ -7906,8 +7909,9 @@ QgsLayoutObject.writeObjectPropertiesToElement: src/core/layout/qgslayoutobject.
QgsLayoutObject: src/core/layout/qgslayoutobject.h#L38
QgsLayoutPageCollection.QgsLayoutPageCollection: src/core/layout/qgslayoutpagecollection.h#L49
QgsLayoutPageCollection.addPage: src/core/layout/qgslayoutpagecollection.h#L159
QgsLayoutPageCollection.applyPropertiesToAllOtherPages: src/core/layout/qgslayoutpagecollection.h#L396
QgsLayoutPageCollection.beginPageSizeChange: src/core/layout/qgslayoutpagecollection.h#L245
QgsLayoutPageCollection.changed: src/core/layout/qgslayoutpagecollection.h#L403
QgsLayoutPageCollection.changed: src/core/layout/qgslayoutpagecollection.h#L410
QgsLayoutPageCollection.clear: src/core/layout/qgslayoutpagecollection.h#L216
QgsLayoutPageCollection.deletePage: src/core/layout/qgslayoutpagecollection.h#L200
QgsLayoutPageCollection.deletePage: src/core/layout/qgslayoutpagecollection.h#L210
@ -7919,7 +7923,7 @@ QgsLayoutPageCollection.layout: src/core/layout/qgslayoutpagecollection.h#L54
QgsLayoutPageCollection.maximumPageSize: src/core/layout/qgslayoutpagecollection.h#L275
QgsLayoutPageCollection.maximumPageWidth: src/core/layout/qgslayoutpagecollection.h#L267
QgsLayoutPageCollection.page: src/core/layout/qgslayoutpagecollection.h#L76
QgsLayoutPageCollection.pageAboutToBeRemoved: src/core/layout/qgslayoutpagecollection.h#L411
QgsLayoutPageCollection.pageAboutToBeRemoved: src/core/layout/qgslayoutpagecollection.h#L418
QgsLayoutPageCollection.pageAtPoint: src/core/layout/qgslayoutpagecollection.h#L328
QgsLayoutPageCollection.pageCount: src/core/layout/qgslayoutpagecollection.h#L67
QgsLayoutPageCollection.pageIsEmpty: src/core/layout/qgslayoutpagecollection.h#L113
@ -7932,7 +7936,7 @@ QgsLayoutPageCollection.pageStyleSymbol: src/core/layout/qgslayoutpagecollection
QgsLayoutPageCollection.positionOnPage: src/core/layout/qgslayoutpagecollection.h#L347
QgsLayoutPageCollection.predictPageNumberForPoint: src/core/layout/qgslayoutpagecollection.h#L316
QgsLayoutPageCollection.readXml: src/core/layout/qgslayoutpagecollection.h#L379
QgsLayoutPageCollection.redraw: src/core/layout/qgslayoutpagecollection.h#L396
QgsLayoutPageCollection.redraw: src/core/layout/qgslayoutpagecollection.h#L403
QgsLayoutPageCollection.reflow: src/core/layout/qgslayoutpagecollection.h#L259
QgsLayoutPageCollection.resizeToContents: src/core/layout/qgslayoutpagecollection.h#L367
QgsLayoutPageCollection.setPageStyleSymbol: src/core/layout/qgslayoutpagecollection.h#L229
@ -8395,14 +8399,14 @@ QgsLineSegment2D.startX: src/core/geometry/qgslinesegment.h#L80
QgsLineSegment2D.startY: src/core/geometry/qgslinesegment.h#L90
QgsLineSegment2D: src/core/geometry/qgslinesegment.h#L31
QgsLineString.QgsLineString: src/core/geometry/qgslinestring.h#L257
QgsLineString.__delitem__: src/core/geometry/qgslinestring.h#L1159
QgsLineString.__getitem__: src/core/geometry/qgslinestring.h#L1100
QgsLineString.__repr__: src/core/geometry/qgslinestring.h#L1082
QgsLineString.__setitem__: src/core/geometry/qgslinestring.h#L1128
QgsLineString.addMValue: src/core/geometry/qgslinestring.h#L1050
QgsLineString.addToPainterPath: src/core/geometry/qgslinestring.h#L1021
QgsLineString.__delitem__: src/core/geometry/qgslinestring.h#L1169
QgsLineString.__getitem__: src/core/geometry/qgslinestring.h#L1110
QgsLineString.__repr__: src/core/geometry/qgslinestring.h#L1092
QgsLineString.__setitem__: src/core/geometry/qgslinestring.h#L1138
QgsLineString.addMValue: src/core/geometry/qgslinestring.h#L1060
QgsLineString.addToPainterPath: src/core/geometry/qgslinestring.h#L1031
QgsLineString.addVertex: src/core/geometry/qgslinestring.h#L918
QgsLineString.addZValue: src/core/geometry/qgslinestring.h#L1049
QgsLineString.addZValue: src/core/geometry/qgslinestring.h#L1059
QgsLineString.append: src/core/geometry/qgslinestring.h#L912
QgsLineString.asGml2: src/core/geometry/qgslinestring.h#L982
QgsLineString.asGml3: src/core/geometry/qgslinestring.h#L983
@ -8412,25 +8416,25 @@ QgsLineString.asWkb: src/core/geometry/qgslinestring.h#L980
QgsLineString.asWkt: src/core/geometry/qgslinestring.h#L981
QgsLineString.boundingBoxIntersects: src/core/geometry/qgslinestring.h#L961
QgsLineString.boundingBoxIntersects: src/core/geometry/qgslinestring.h#L962
QgsLineString.calculateBoundingBox3D: src/core/geometry/qgslinestring.h#L1189
QgsLineString.calculateBoundingBox3d: src/core/geometry/qgslinestring.h#L1182
QgsLineString.centroid: src/core/geometry/qgslinestring.h#L1035
QgsLineString.calculateBoundingBox3D: src/core/geometry/qgslinestring.h#L1199
QgsLineString.calculateBoundingBox3d: src/core/geometry/qgslinestring.h#L1192
QgsLineString.centroid: src/core/geometry/qgslinestring.h#L1045
QgsLineString.clear: src/core/geometry/qgslinestring.h#L953
QgsLineString.clone: src/core/geometry/qgslinestring.h#L952
QgsLineString.close: src/core/geometry/qgslinestring.h#L921
QgsLineString.closestSegment: src/core/geometry/qgslinestring.h#L1032
QgsLineString.compareToSameClass: src/core/geometry/qgslinestring.h#L1242
QgsLineString.convertTo: src/core/geometry/qgslinestring.h#L1056
QgsLineString.createEmptyWithSameType: src/core/geometry/qgslinestring.h#L1079
QgsLineString.curveSubstring: src/core/geometry/qgslinestring.h#L1030
QgsLineString.curveToLine: src/core/geometry/qgslinestring.h#L1010
QgsLineString.deleteVertex: src/core/geometry/qgslinestring.h#L1026
QgsLineString.closestSegment: src/core/geometry/qgslinestring.h#L1042
QgsLineString.compareToSameClass: src/core/geometry/qgslinestring.h#L1252
QgsLineString.convertTo: src/core/geometry/qgslinestring.h#L1066
QgsLineString.createEmptyWithSameType: src/core/geometry/qgslinestring.h#L1089
QgsLineString.curveSubstring: src/core/geometry/qgslinestring.h#L1040
QgsLineString.curveToLine: src/core/geometry/qgslinestring.h#L1020
QgsLineString.deleteVertex: src/core/geometry/qgslinestring.h#L1036
QgsLineString.dimension: src/core/geometry/qgslinestring.h#L951
QgsLineString.draw: src/core/geometry/qgslinestring.h#L1016
QgsLineString.drawAsPolygon: src/core/geometry/qgslinestring.h#L1022
QgsLineString.dropMValue: src/core/geometry/qgslinestring.h#L1053
QgsLineString.dropZValue: src/core/geometry/qgslinestring.h#L1052
QgsLineString.endPoint: src/core/geometry/qgslinestring.h#L1002
QgsLineString.draw: src/core/geometry/qgslinestring.h#L1026
QgsLineString.drawAsPolygon: src/core/geometry/qgslinestring.h#L1032
QgsLineString.dropMValue: src/core/geometry/qgslinestring.h#L1063
QgsLineString.dropZValue: src/core/geometry/qgslinestring.h#L1062
QgsLineString.endPoint: src/core/geometry/qgslinestring.h#L1012
QgsLineString.equals: src/core/geometry/qgslinestring.h#L429
QgsLineString.extend: src/core/geometry/qgslinestring.h#L934
QgsLineString.fromBezierCurve: src/core/geometry/qgslinestring.h#L296
@ -8441,28 +8445,28 @@ QgsLineString.fuzzyDistanceEqual: src/core/geometry/qgslinestring.h#L424
QgsLineString.fuzzyEqual: src/core/geometry/qgslinestring.h#L395
QgsLineString.geometryType: src/core/geometry/qgslinestring.h#L950
QgsLineString.indexOf: src/core/geometry/qgslinestring.h#L955
QgsLineString.insertVertex: src/core/geometry/qgslinestring.h#L1024
QgsLineString.interpolateM: src/core/geometry/qgslinestring.h#L1212
QgsLineString.interpolatePoint: src/core/geometry/qgslinestring.h#L1029
QgsLineString.insertVertex: src/core/geometry/qgslinestring.h#L1034
QgsLineString.interpolateM: src/core/geometry/qgslinestring.h#L1222
QgsLineString.interpolatePoint: src/core/geometry/qgslinestring.h#L1039
QgsLineString.isClosed2D: src/core/geometry/qgslinestring.h#L960
QgsLineString.isClosed: src/core/geometry/qgslinestring.h#L959
QgsLineString.isEmpty: src/core/geometry/qgslinestring.h#L954
QgsLineString.isValid: src/core/geometry/qgslinestring.h#L956
QgsLineString.length3D: src/core/geometry/qgslinestring.h#L1000
QgsLineString.length3D: src/core/geometry/qgslinestring.h#L1010
QgsLineString.length: src/core/geometry/qgslinestring.h#L988
QgsLineString.lineLocatePointByM: src/core/geometry/qgslinestring.h#L1238
QgsLineString.lineLocatePointByM: src/core/geometry/qgslinestring.h#L1248
QgsLineString.mAt: src/core/geometry/qgslinestring.h#L698
QgsLineString.measuredLine: src/core/geometry/qgslinestring.h#L1197
QgsLineString.moveVertex: src/core/geometry/qgslinestring.h#L1025
QgsLineString.nCoordinates: src/core/geometry/qgslinestring.h#L1013
QgsLineString.numPoints: src/core/geometry/qgslinestring.h#L1012
QgsLineString.pointAt: src/core/geometry/qgslinestring.h#L1033
QgsLineString.measuredLine: src/core/geometry/qgslinestring.h#L1207
QgsLineString.moveVertex: src/core/geometry/qgslinestring.h#L1035
QgsLineString.nCoordinates: src/core/geometry/qgslinestring.h#L1023
QgsLineString.numPoints: src/core/geometry/qgslinestring.h#L1022
QgsLineString.pointAt: src/core/geometry/qgslinestring.h#L1043
QgsLineString.pointN: src/core/geometry/qgslinestring.h#L449
QgsLineString.points: src/core/geometry/qgslinestring.h#L1014
QgsLineString.points: src/core/geometry/qgslinestring.h#L1024
QgsLineString.removeDuplicateNodes: src/core/geometry/qgslinestring.h#L958
QgsLineString.reversed: src/core/geometry/qgslinestring.h#L1028
QgsLineString.scroll: src/core/geometry/qgslinestring.h#L1059
QgsLineString.segmentLength: src/core/geometry/qgslinestring.h#L1048
QgsLineString.reversed: src/core/geometry/qgslinestring.h#L1038
QgsLineString.scroll: src/core/geometry/qgslinestring.h#L1069
QgsLineString.segmentLength: src/core/geometry/qgslinestring.h#L1058
QgsLineString.setMAt: src/core/geometry/qgslinestring.h#L868
QgsLineString.setPoints: src/core/geometry/qgslinestring.h#L906
QgsLineString.setXAt: src/core/geometry/qgslinestring.h#L739
@ -8470,14 +8474,14 @@ QgsLineString.setYAt: src/core/geometry/qgslinestring.h#L780
QgsLineString.setZAt: src/core/geometry/qgslinestring.h#L824
QgsLineString.simplifyByDistance: src/core/geometry/qgslinestring.h#L975
QgsLineString.snappedToGrid: src/core/geometry/qgslinestring.h#L957
QgsLineString.startPoint: src/core/geometry/qgslinestring.h#L1001
QgsLineString.sumUpArea: src/core/geometry/qgslinestring.h#L1045
QgsLineString.swapXy: src/core/geometry/qgslinestring.h#L1054
QgsLineString.startPoint: src/core/geometry/qgslinestring.h#L1011
QgsLineString.sumUpArea: src/core/geometry/qgslinestring.h#L1055
QgsLineString.swapXy: src/core/geometry/qgslinestring.h#L1064
QgsLineString.toCurveType: src/core/geometry/qgslinestring.h#L927
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1018
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1019
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1058
QgsLineString.vertexAngle: src/core/geometry/qgslinestring.h#L1047
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1028
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1029
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1068
QgsLineString.vertexAngle: src/core/geometry/qgslinestring.h#L1057
QgsLineString.wkbSize: src/core/geometry/qgslinestring.h#L979
QgsLineString.xAt: src/core/geometry/qgslinestring.h#L481
QgsLineString.yAt: src/core/geometry/qgslinestring.h#L511
@ -14879,20 +14883,20 @@ QgsRemappingSinkDefinition.setSourceCrs: src/core/qgsremappingproxyfeaturesink.h
QgsRemappingSinkDefinition.sourceCrs: src/core/qgsremappingproxyfeaturesink.h#L82
QgsRemappingSinkDefinition.toVariant: src/core/qgsremappingproxyfeaturesink.h#L138
QgsRemappingSinkDefinition: src/core/qgsremappingproxyfeaturesink.h#L38
QgsRenderChecker.compareImages: src/core/qgsrenderchecker.h#L240
QgsRenderChecker.compareImages: src/core/qgsrenderchecker.h#L247
QgsRenderChecker.compareImages: src/core/qgsrenderchecker.h#L241
QgsRenderChecker.compareImages: src/core/qgsrenderchecker.h#L248
QgsRenderChecker.controlImagePath: src/core/qgsrenderchecker.h#L74
QgsRenderChecker.drawBackground: src/core/qgsrenderchecker.h#L265
QgsRenderChecker.drawBackground: src/core/qgsrenderchecker.h#L266
QgsRenderChecker.elapsedTime: src/core/qgsrenderchecker.h#L129
QgsRenderChecker.enableDashBuffering: src/core/qgsrenderchecker.h#L281
QgsRenderChecker.expectedImageFile: src/core/qgsrenderchecker.h#L272
QgsRenderChecker.enableDashBuffering: src/core/qgsrenderchecker.h#L282
QgsRenderChecker.expectedImageFile: src/core/qgsrenderchecker.h#L273
QgsRenderChecker.imageToHash: src/core/qgsrenderchecker.h#L156
QgsRenderChecker.isKnownAnomaly: src/core/qgsrenderchecker.h#L259
QgsRenderChecker.isKnownAnomaly: src/core/qgsrenderchecker.h#L260
QgsRenderChecker.markdownReport: src/core/qgsrenderchecker.h#L103
QgsRenderChecker.matchPercent: src/core/qgsrenderchecker.h#L112
QgsRenderChecker.renderedImage: src/core/qgsrenderchecker.h#L175
QgsRenderChecker.report: src/core/qgsrenderchecker.h#L92
QgsRenderChecker.runTest: src/core/qgsrenderchecker.h#L225
QgsRenderChecker.runTest: src/core/qgsrenderchecker.h#L226
QgsRenderChecker.setColorTolerance: src/core/qgsrenderchecker.h#L185
QgsRenderChecker.setControlExtension: src/core/qgsrenderchecker.h#L145
QgsRenderChecker.setControlImagePath: src/core/qgsrenderchecker.h#L82
@ -14905,7 +14909,7 @@ QgsRenderChecker.setMapSettings: src/core/qgsrenderchecker.h#L177
QgsRenderChecker.setRenderedImage: src/core/qgsrenderchecker.h#L161
QgsRenderChecker.setSizeTolerance: src/core/qgsrenderchecker.h#L192
QgsRenderChecker.shouldGenerateReport: src/core/qgsrenderchecker.h#L65
QgsRenderChecker.sourcePath: src/core/qgsrenderchecker.h#L296
QgsRenderChecker.sourcePath: src/core/qgsrenderchecker.h#L297
QgsRenderChecker.testReportDir: src/core/qgsrenderchecker.h#L57
QgsRenderChecker: src/core/qgsrenderchecker.h#L41
QgsRenderContext.addSymbolLayerClipGeometry: src/core/qgsrendercontext.h#L1028

View File

@ -17,7 +17,7 @@
***************************************************************************
"""
from qgis.PyQt.QtWidgets import QWidget, QComboBox
from qgis.PyQt.QtWidgets import QComboBox
from qgis.core import QgsSettingsEntryBase
from qgis.gui import QgsSettingsEditorWidgetWrapper
@ -46,23 +46,25 @@ class PyQgsSettingsEnumEditorWidgetWrapper(QgsSettingsEditorWidgetWrapper):
def setWidgetFromSetting(self):
if self.setting:
return self.setWidgetFromVariant(self.setting.value(self.dynamicKeyPartList()))
return self.setWidgetFromVariant(self.setting.valueAsVariant(self.dynamicKeyPartList()))
return False
def setSettingFromWidget(self):
if self.editor:
self.setting.setValue(self.variantValueFromWidget(), self.dynamicKeyPartList())
self.setting.setVariantValue(self.variantValueFromWidget(), self.dynamicKeyPartList())
return True
else:
return False
def variantValueFromWidget(self):
if self.editor:
return self.setting.defaultValue().__class__(self.editor.currentData())
return self.editor.currentData()
return None
def setWidgetFromVariant(self, value):
if self.editor:
if self.editor and value is not None:
if isinstance(value, int):
value = self.setting.metaEnum().valueToKey(value)
idx = self.editor.findData(value)
self.editor.setCurrentIndex(idx)
return idx >= 0
@ -71,7 +73,7 @@ class PyQgsSettingsEnumEditorWidgetWrapper(QgsSettingsEditorWidgetWrapper):
def createEditorPrivate(self, parent=None):
return QComboBox(parent)
def configureEditorPrivate(self, editor: QWidget, setting: QgsSettingsEntryBase):
def configureEditorPrivate(self, editor: QComboBox, setting: QgsSettingsEntryBase):
self.setting = setting
if isinstance(editor, QComboBox):
self.editor = editor
@ -79,7 +81,7 @@ class PyQgsSettingsEnumEditorWidgetWrapper(QgsSettingsEditorWidgetWrapper):
value = self.setting.metaEnum().value(i)
key = self.setting.metaEnum().key(i)
text = self.displayStrings.get(value, key)
self.editor.addItem(text, value)
self.editor.addItem(text, key)
return True
else:
return False

View File

@ -34,12 +34,19 @@ Adds an editor widget ``wrapper`` to the registry
If an editor widget with same id already exists, the wrapper is deleted and ``False`` is returned.
%End
QgsSettingsEditorWidgetWrapper *createWrapper( const QString &id, QObject *parent ) const;
void addWrapperForSetting( QgsSettingsEditorWidgetWrapper *wrapper /Transfer/, const QgsSettingsEntryBase *setting /KeepReference/ );
%Docstring
Adds an editor widget ``wrapper`` for a specific setting to the registry
.. versionadded:: 3.40
%End
QgsSettingsEditorWidgetWrapper *createWrapper( const QString &id, QObject *parent ) const /Factory/;
%Docstring
Returns a new instance of the editor widget for the given ``id``
%End
QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList, QWidget *parent = 0 ) const /Factory/;
QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList, QWidget *parent = 0 ) const /TransferBack/;
%Docstring
Creates an editor widget for the given ``setting`` using the corresponding registered wrapper
%End

View File

@ -23,7 +23,7 @@ Base class for settings editor wrappers
#include "qgssettingseditorwidgetwrapper.h"
%End
public:
static QgsSettingsEditorWidgetWrapper *fromWidget( const QWidget *widget ) /Factory/;
static QgsSettingsEditorWidgetWrapper *fromWidget( const QWidget *widget );
%Docstring
Creates a wrapper from the definition stored in a ``widget`` created by :py:func:`~QgsSettingsEditorWidgetWrapper.createEditor`
%End
@ -44,12 +44,12 @@ This id of the type of settings it handles
This mostly correspond to the content of :py:class:`Qgis`.SettingsType but it's a string since custom Python implementation are possible.
%End
virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = 0 ) const = 0;
virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = 0 ) const = 0 /Factory/;
%Docstring
Creates a new instance of the editor wrapper so it can be configured for a widget and a setting
%End
QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList = QStringList(), QWidget *parent = 0 );
QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList = QStringList(), QWidget *parent = 0 ) /TransferBack/;
%Docstring
Creates the editor widget for the given ``setting``
%End
@ -77,7 +77,7 @@ Returns the value from the widget as a variant
The wrapper must be configured before calling this medthod
%End
virtual void setWidgetFromVariant( const QVariant &value ) const = 0;
virtual bool setWidgetFromVariant( const QVariant &value ) const = 0;
%Docstring
Sets the ``value`` of the widget
The wrapper must be configured before calling this medthod
@ -106,12 +106,12 @@ Returns the dynamic key parts
protected:
virtual QWidget *createEditorPrivate( QWidget *parent = 0 ) const = 0;
virtual QWidget *createEditorPrivate( QWidget *parent = 0 ) const = 0 /TransferBack/;
%Docstring
Creates the widgets
%End
virtual bool configureEditorPrivate( QWidget *editor, const QgsSettingsEntryBase *setting ) = 0;
virtual bool configureEditorPrivate( QWidget *editor /TransferBack/, const QgsSettingsEntryBase *setting /KeepReference/ ) = 0;
%Docstring
Configures an existing ``editor`` widget
%End

View File

@ -36,7 +36,7 @@ Constructor
virtual bool setSettingFromWidget() const = 0;
virtual void setWidgetFromVariant( const QVariant &value ) const;
virtual bool setWidgetFromVariant( const QVariant &value ) const;
virtual bool setWidgetValue( const U &value ) const = 0;
%Docstring

View File

@ -6732,8 +6732,9 @@ QgsSettingsDoubleSpinBoxWrapper.setWidgetValue: src/gui/settings/qgssettingsedit
QgsSettingsDoubleSpinBoxWrapper.valueFromWidget: src/gui/settings/qgssettingseditorwidgetwrapperimpl.h#L285
QgsSettingsDoubleSpinBoxWrapper: src/gui/settings/qgssettingseditorwidgetwrapperimpl.h#L267
QgsSettingsEditorWidgetRegistry.addWrapper: src/gui/settings/qgssettingseditorwidgetregistry.h#L46
QgsSettingsEditorWidgetRegistry.createEditor: src/gui/settings/qgssettingseditorwidgetregistry.h#L52
QgsSettingsEditorWidgetRegistry.createWrapper: src/gui/settings/qgssettingseditorwidgetregistry.h#L49
QgsSettingsEditorWidgetRegistry.addWrapperForSetting: src/gui/settings/qgssettingseditorwidgetregistry.h#L52
QgsSettingsEditorWidgetRegistry.createEditor: src/gui/settings/qgssettingseditorwidgetregistry.h#L58
QgsSettingsEditorWidgetRegistry.createWrapper: src/gui/settings/qgssettingseditorwidgetregistry.h#L55
QgsSettingsEditorWidgetRegistry: src/gui/settings/qgssettingseditorwidgetregistry.h#L35
QgsSettingsEditorWidgetWrapper.configureAutomaticUpdate: src/gui/settings/qgssettingseditorwidgetwrapper.h#L95
QgsSettingsEditorWidgetWrapper.configureEditor: src/gui/settings/qgssettingseditorwidgetwrapper.h#L59

View File

@ -662,10 +662,6 @@ except ModuleNotFoundError:
QgsGeometry.as_shapely = _geometry_as_shapely
QgsRasterBlock.as_numpy.__doc__ = """
Returns the block data as a numpy array.
@ -675,6 +671,7 @@ If `use_masking` is `True` then the returned array will be a numpy masked array,
.. versionadded:: 3.40
"""
QgsRasterLayer.as_numpy.__doc__ = """
Returns the layer data as a numpy array.
@ -686,6 +683,19 @@ If `bands` is provided, only the specified bands will be included in the returne
.. versionadded:: 3.40
"""
QgsGeometry.as_numpy.__doc__ = """Returns the geometry data as a numpy array or list of numpy arrays."""
QgsGeometry.as_shapely.__doc__ = """Returns the geometry data as a shapely object."""
QgsGeometry.as_numpy.__doc__ = """
Returns the geometry data as a numpy array or list of numpy arrays.
:raises QgsNotSupportedException: if numpy is not available on the system
.. versionadded:: 3.40
"""
QgsGeometry.as_shapely.__doc__ = """
Returns the geometry data as a shapely object.
:raises QgsNotSupportedException: if shapely is not available on the system
.. versionadded:: 3.40
"""

View File

@ -6,7 +6,7 @@ try:
except NameError:
pass
try:
QgsLayoutExporter.ImageExportSettings.__attribute_docs__ = {'dpi': 'Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.', 'imageSize': "Manual size in pixels for output image. If imageSize is not\nset then it will be automatically calculated based on the\noutput dpi and layout size.\n\nIf cropToContents is ``True`` then imageSize has no effect.\n\nBe careful when specifying manual sizes if pages in the layout\nhave differing sizes! It's likely not going to give a reasonable\noutput in this case, and the automatic dpi-based image size should be\nused instead.", 'cropToContents': 'Set to ``True`` if image should be cropped so only parts of the layout\ncontaining items are exported.', 'cropMargins': 'Crop to content margins, in pixels. These margins will be added\nto the bounds of the exported layout if cropToContents is ``True``.', 'pages': 'List of specific pages to export, or an empty list to\nexport all pages.\n\nPage numbers are 0 index based, so the first page in the\nlayout corresponds to page 0.', 'generateWorldFile': 'Set to ``True`` to generate an external world file alongside\nexported images.', 'exportMetadata': "Indicates whether image export should include metadata generated\nfrom the layout's project's metadata.\n\n.. versionadded:: 3.2", 'flags': 'Layout context flags, which control how the export will be created.', 'predefinedMapScales': 'A list of predefined scales to use with the layout. This is used\nfor maps which are set to the predefined atlas scaling mode.\n\n.. versionadded:: 3.10'}
QgsLayoutExporter.ImageExportSettings.__attribute_docs__ = {'dpi': 'Resolution to export layout at. If dpi <= 0 the default layout dpi will be used.', 'imageSize': "Manual size in pixels for output image. If imageSize is not\nset then it will be automatically calculated based on the\noutput dpi and layout size.\n\nIf cropToContents is ``True`` then imageSize has no effect.\n\nBe careful when specifying manual sizes if pages in the layout\nhave differing sizes! It's likely not going to give a reasonable\noutput in this case, and the automatic dpi-based image size should be\nused instead.", 'cropToContents': 'Set to ``True`` if image should be cropped so only parts of the layout\ncontaining items are exported.', 'cropMargins': 'Crop to content margins, in pixels. These margins will be added\nto the bounds of the exported layout if cropToContents is ``True``.', 'pages': 'List of specific pages to export, or an empty list to\nexport all pages.\n\nPage numbers are 0 index based, so the first page in the\nlayout corresponds to page 0.', 'generateWorldFile': 'Set to ``True`` to generate an external world file alongside\nexported images.', 'exportMetadata': "Indicates whether image export should include metadata generated\nfrom the layout's project's metadata.\n\n.. versionadded:: 3.2", 'flags': 'Layout context flags, which control how the export will be created.', 'predefinedMapScales': 'A list of predefined scales to use with the layout. This is used\nfor maps which are set to the predefined atlas scaling mode.\n\n.. versionadded:: 3.10', 'quality': 'Image quality, typically used for JPEG compression (whose quality ranges from 1 to 100)\nif quality is set to -1, the default quality will be used.\n\n.. versionadded:: 3.42'}
QgsLayoutExporter.ImageExportSettings.__doc__ = """Contains settings relating to exporting layouts to raster images"""
QgsLayoutExporter.ImageExportSettings.__group__ = ['layout']
except NameError:

View File

@ -1,11 +1,16 @@
# The following has been generated automatically from src/core/qgsrenderchecker.h
# monkey patching scoped based enum
QgsRenderChecker.Flag.AvoidExportingRenderedImage.__doc__ = "Avoids exporting rendered images to reports"
QgsRenderChecker.Flag.Silent.__doc__ = "Don't output non-critical messages to console \n.. versionadded:: 3.40"
QgsRenderChecker.Flag.__doc__ = """Render checker flags.
.. versionadded:: 3.28
* ``AvoidExportingRenderedImage``: Avoids exporting rendered images to reports
* ``Silent``: Don't output non-critical messages to console
.. versionadded:: 3.40
"""
# --

View File

@ -1,6 +1,6 @@
# The following has been generated automatically from src/core/qgstemporalutils.h
try:
QgsTemporalUtils.AnimationExportSettings.__attribute_docs__ = {'animationRange': 'Dictates the overall temporal range of the animation.', 'frameDuration': 'Duration of individual export frames', 'outputDirectory': 'Destination directory for created image files.', 'fileNameTemplate': "The filename template for exporting the frames.\n\nThis must be in format prefix####.format, where number of\n``# ``characters represents how many 0's should be left-padded to the frame number\ne.g. my###.jpg will create frames my001.jpg, my002.jpg, etc", 'decorations': 'List of decorations to draw onto exported frames.', 'availableTemporalRanges': 'Contains the list of all available temporal ranges which have data available.\n\nThe list can be a list of non-contiguous ranges (i.e. containing gaps)\nwhich together describe the complete range of times which contain data.\n\nThis list is required whenever the :py:class:`QgsUnitTypes`.TemporalIrregularStep interval is used\nfor an animation.\n\n.. versionadded:: 3.30', 'frameRate': 'Target animation frame rate in frames per second.\n\n.. versionadded:: 3.26'}
QgsTemporalUtils.AnimationExportSettings.__attribute_docs__ = {'animationRange': 'Dictates the overall temporal range of the animation.', 'frameDuration': 'Duration of individual export frames', 'outputDirectory': 'Destination directory for created image files.', 'fileNameTemplate': "The filename template for exporting the frames.\n\nThis must be in format ``prefix####.format``, where number of\n````#`` ``characters represents how many 0's should be left-padded to the frame number\ne.g. ``my###.jpg`` will create frames ``my001.jpg``, ``my002.jpg``, etc", 'decorations': 'List of decorations to draw onto exported frames.', 'availableTemporalRanges': 'Contains the list of all available temporal ranges which have data available.\n\nThe list can be a list of non-contiguous ranges (i.e. containing gaps)\nwhich together describe the complete range of times which contain data.\n\nThis list is required whenever the :py:class:`QgsUnitTypes`.TemporalIrregularStep interval is used\nfor an animation.\n\n.. versionadded:: 3.30', 'frameRate': 'Target animation frame rate in frames per second.\n\n.. versionadded:: 3.26'}
QgsTemporalUtils.AnimationExportSettings.__doc__ = """Contains settings relating to exporting animations"""
except NameError:
pass

View File

@ -80,7 +80,7 @@ Initializes the storage.
.. note::
The default implementation does nothing and returns ``True``.
The default implementation does nothing and returns ``True``.
This method is called by the authentication manager when the storage is added to the manager.
%End

View File

@ -36,7 +36,7 @@ extent of a geometry or collection of geometries.
public:
QgsBox3D( SIP_PYOBJECT x /TypeHint="Optional[Union[QgsPoint, QgsRectangle, float]]"/ = Py_None, SIP_PYOBJECT y /TypeHint="Optional[QgsPoint, float]"/ = Py_None, SIP_PYOBJECT z /TypeHint="Optional[Union[bool, float]]"/ = Py_None, SIP_PYOBJECT x2 /TypeHint="Optional[Union[bool, float]]"/ = Py_None, SIP_PYOBJECT y2 /TypeHint="Optional[float]"/ = Py_None, SIP_PYOBJECT z2 /TypeHint="Optional[float]"/ = Py_None, SIP_PYOBJECT n /TypeHint="Optional[bool]"/ = Py_None ) [( double x = 0.0, double y = 0.0, double z = 0.0, double x2 = 0.0, double y2 = 0.0, double z2 = 0.0, bool n = true )];
QgsBox3D( SIP_PYOBJECT x /TypeHint="Optional[Union[QgsPoint, QgsVector3D, QgsRectangle, float]]"/ = Py_None, SIP_PYOBJECT y /TypeHint="Optional[QgsPoint, QgsVector3D, float]"/ = Py_None, SIP_PYOBJECT z /TypeHint="Optional[Union[bool, float]]"/ = Py_None, SIP_PYOBJECT x2 /TypeHint="Optional[Union[bool, float]]"/ = Py_None, SIP_PYOBJECT y2 /TypeHint="Optional[float]"/ = Py_None, SIP_PYOBJECT z2 /TypeHint="Optional[float]"/ = Py_None, SIP_PYOBJECT n /TypeHint="Optional[bool]"/ = Py_None ) [( double x = 0.0, double y = 0.0, double z = 0.0, double x2 = 0.0, double y2 = 0.0, double z2 = 0.0, bool n = true )];
%Docstring
Constructor for QgsBox3D which accepts the ranges of x/y/z coordinates. If ``normalize`` is ``False`` then
the normalization step will not be applied automatically.
@ -85,6 +85,30 @@ the normalization step will not be applied automatically.
}
}
}
else if ( sipCanConvertToType( a0, sipType_QgsVector3D, SIP_NOT_NONE ) && sipCanConvertToType( a1, sipType_QgsVector3D, SIP_NOT_NONE ) && a3 == Py_None && a4 == Py_None && a5 == Py_None && a6 == Py_None )
{
int state;
sipIsErr = 0;
QgsVector3D *corner1 = reinterpret_cast<QgsVector3D *>( sipConvertToType( a0, sipType_QgsVector3D, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( corner1, sipType_QgsVector3D, state );
}
else
{
QgsVector3D *corner2 = reinterpret_cast<QgsVector3D *>( sipConvertToType( a1, sipType_QgsVector3D, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( corner2, sipType_QgsVector3D, state );
}
else
{
bool n = a2 == Py_None ? true : PyObject_IsTrue( a2 );
sipCpp = new QgsBox3D( *corner1, *corner2, n );
}
}
}
else if (
( a0 == Py_None || PyFloat_AsDouble( a0 ) != -1.0 || !PyErr_Occurred() ) &&
( a1 == Py_None || PyFloat_AsDouble( a1 ) != -1.0 || !PyErr_Occurred() ) &&
@ -375,6 +399,13 @@ If no ``center`` point is specified then the current center of the box will be u
Scale the rectangle around a center coordinates.
.. versionadded:: 3.26
%End
void grow( double delta );
%Docstring
Grows the box in place by the specified amount in all dimensions.
.. versionadded:: 3.42
%End
bool isNull() const /HoldGIL/;

View File

@ -2957,7 +2957,7 @@ geometry will retain the same dimensionality as the input geometry.
:param maxAngle: maximum angle at node (0-180) at which smoothing will be applied
%End
static QgsGeometryEngine *createGeometryEngine( const QgsAbstractGeometry *geometry, double precision = 0.0 ) /Factory/;
static QgsGeometryEngine *createGeometryEngine( const QgsAbstractGeometry *geometry, double precision = 0.0, Qgis::GeosCreationFlags flags = Qgis::GeosCreationFlag::SkipEmptyInteriorRings ) /Factory/;
%Docstring
Creates and returns a new geometry engine representing the specified ``geometry`` using ``precision`` on a grid. The ``precision`` argument was added in 3.36.
@ -2972,6 +2972,8 @@ Many methods available in the :py:class:`QgsGeometryEngine` class can benefit fr
a large number of spatial relationships will be tested (such as calling :py:func:`~QgsGeometry.intersects`, :py:func:`~QgsGeometry.within`, etc) then the
geometry should first be prepared by calling :py:func:`~QgsGeometry.prepareGeometry` before performing the tests.
The ``flags`` argument was added in QGIS 3.40 to allow control over the resultant GEOS geometry.
Example
-------------------------------------

View File

@ -643,6 +643,17 @@ If ``useZValues`` is ``True`` then z values will also be considered when testing
QVector<QgsLineString *> splitToDisjointXYParts() const /Factory/;
%Docstring
Divides the linestring into parts that don't share any points or lines.
This method throws away Z and M coordinates.
The ownership of returned pointers is transferred to the caller.
.. versionadded:: 3.40
%End
double length3D() const /HoldGIL/;
%Docstring
Returns the length in 3D world of the line string.

View File

@ -24,6 +24,7 @@ Handles rendering and exports of layouts to various formats.
struct PageExportDetails
{
QString directory;
@ -142,6 +143,9 @@ Returns the rendered image, or a null QImage if the image does not fit into avai
QVector<qreal> predefinedMapScales;
int quality;
};
ExportResult exportToImage( const QString &filePath, const QgsLayoutExporter::ImageExportSettings &settings );

View File

@ -111,6 +111,15 @@ Deselects any selected nodes.
virtual double estimatedFrameBleed() const;
virtual bool isValid() const = 0;
%Docstring
Must be reimplemented in subclasses.
Typically a polyline is valid if it has at least 2 distinct nodes,
while a polygon is valid if it has at least 3 distinct nodes.
.. versionadded:: 3.40
%End
protected:
QgsLayoutNodesItem( QgsLayout *layout );

View File

@ -53,6 +53,8 @@ The caller takes responsibility for deleting the returned object.
virtual QgsGeometry clipPath() const;
virtual bool isValid() const;
QgsFillSymbol *symbol();
%Docstring

View File

@ -55,6 +55,8 @@ The caller takes responsibility for deleting the returned object.
virtual QPainterPath shape() const;
virtual bool isValid() const;
QgsLineSymbol *symbol();
%Docstring

View File

@ -368,6 +368,13 @@ Returns a reference to the collection's guide collection, which manages page sna
%End
void applyPropertiesToAllOtherPages( int sourcePage );
%Docstring
Apply the source page properties (size & background color) to all other pages
.. versionadded:: 3.42
%End
public slots:
void redraw();

View File

@ -301,6 +301,7 @@ Emitted when point cloud generation state is changed
protected:
};
/************************************************************************

View File

@ -183,6 +183,7 @@ Sets the largest allowable difference in size between the rendered and the expec
enum class Flag
{
AvoidExportingRenderedImage,
Silent,
};
typedef QFlags<QgsRenderChecker::Flag> Flags;

View File

@ -1345,66 +1345,66 @@ QgsAuthConfigSslServer.sslPeerVerifyMode: src/core/auth/qgsauthconfig.h#L418
QgsAuthConfigSslServer.sslProtocol: src/core/auth/qgsauthconfig.h#L406
QgsAuthConfigSslServer.version: src/core/auth/qgsauthconfig.h#L435
QgsAuthConfigSslServer: src/core/auth/qgsauthconfig.h#L389
QgsAuthConfigurationStorage.authMethodConfigs: src/core/auth/qgsauthconfigurationstorage.h#L164
QgsAuthConfigurationStorage.authMethodConfigsWithPayload: src/core/auth/qgsauthconfigurationstorage.h#L174
QgsAuthConfigurationStorage.authSettingExists: src/core/auth/qgsauthconfigurationstorage.h#L241
QgsAuthConfigurationStorage.authSettingsChanged: src/core/auth/qgsauthconfigurationstorage.h#L524
QgsAuthConfigurationStorage.capabilities: src/core/auth/qgsauthconfigurationstorage.h#L118
QgsAuthConfigurationStorage.certAuthorityChanged: src/core/auth/qgsauthconfigurationstorage.h#L542
QgsAuthConfigurationStorage.certAuthorityExists: src/core/auth/qgsauthconfigurationstorage.h#L394
QgsAuthConfigurationStorage.certAuthorityIds: src/core/auth/qgsauthconfigurationstorage.h#L378
QgsAuthConfigurationStorage.certIdentityChanged: src/core/auth/qgsauthconfigurationstorage.h#L537
QgsAuthConfigurationStorage.certIdentityExists: src/core/auth/qgsauthconfigurationstorage.h#L298
QgsAuthConfigurationStorage.certIdentityIds: src/core/auth/qgsauthconfigurationstorage.h#L290
QgsAuthConfigurationStorage.certTrustPolicyExists: src/core/auth/qgsauthconfigurationstorage.h#L449
QgsAuthConfigurationStorage.clearMasterPasswords: src/core/auth/qgsauthconfigurationstorage.h#L473
QgsAuthConfigurationStorage.clearMethodConfigs: src/core/auth/qgsauthconfigurationstorage.h#L488
QgsAuthConfigurationStorage.authMethodConfigs: src/core/auth/qgsauthconfigurationstorage.h#L165
QgsAuthConfigurationStorage.authMethodConfigsWithPayload: src/core/auth/qgsauthconfigurationstorage.h#L175
QgsAuthConfigurationStorage.authSettingExists: src/core/auth/qgsauthconfigurationstorage.h#L242
QgsAuthConfigurationStorage.authSettingsChanged: src/core/auth/qgsauthconfigurationstorage.h#L525
QgsAuthConfigurationStorage.capabilities: src/core/auth/qgsauthconfigurationstorage.h#L119
QgsAuthConfigurationStorage.certAuthorityChanged: src/core/auth/qgsauthconfigurationstorage.h#L543
QgsAuthConfigurationStorage.certAuthorityExists: src/core/auth/qgsauthconfigurationstorage.h#L395
QgsAuthConfigurationStorage.certAuthorityIds: src/core/auth/qgsauthconfigurationstorage.h#L379
QgsAuthConfigurationStorage.certIdentityChanged: src/core/auth/qgsauthconfigurationstorage.h#L538
QgsAuthConfigurationStorage.certIdentityExists: src/core/auth/qgsauthconfigurationstorage.h#L299
QgsAuthConfigurationStorage.certIdentityIds: src/core/auth/qgsauthconfigurationstorage.h#L291
QgsAuthConfigurationStorage.certTrustPolicyExists: src/core/auth/qgsauthconfigurationstorage.h#L450
QgsAuthConfigurationStorage.clearMasterPasswords: src/core/auth/qgsauthconfigurationstorage.h#L474
QgsAuthConfigurationStorage.clearMethodConfigs: src/core/auth/qgsauthconfigurationstorage.h#L489
QgsAuthConfigurationStorage.description: src/core/auth/qgsauthconfigurationstorage.h#L87
QgsAuthConfigurationStorage.erase: src/core/auth/qgsauthconfigurationstorage.h#L480
QgsAuthConfigurationStorage.erase: src/core/auth/qgsauthconfigurationstorage.h#L481
QgsAuthConfigurationStorage.id: src/core/auth/qgsauthconfigurationstorage.h#L93
QgsAuthConfigurationStorage.initialize: src/core/auth/qgsauthconfigurationstorage.h#L102
QgsAuthConfigurationStorage.isEnabled: src/core/auth/qgsauthconfigurationstorage.h#L138
QgsAuthConfigurationStorage.isEncrypted: src/core/auth/qgsauthconfigurationstorage.h#L133
QgsAuthConfigurationStorage.isReadOnly: src/core/auth/qgsauthconfigurationstorage.h#L157
QgsAuthConfigurationStorage.isReady: src/core/auth/qgsauthconfigurationstorage.h#L113
QgsAuthConfigurationStorage.lastError: src/core/auth/qgsauthconfigurationstorage.h#L107
QgsAuthConfigurationStorage.loadAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L225
QgsAuthConfigurationStorage.loadCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L386
QgsAuthConfigurationStorage.loadCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L268
QgsAuthConfigurationStorage.loadCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L433
QgsAuthConfigurationStorage.loadMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L184
QgsAuthConfigurationStorage.loadSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L323
QgsAuthConfigurationStorage.loadSslCertCustomConfigByHost: src/core/auth/qgsauthconfigurationstorage.h#L331
QgsAuthConfigurationStorage.loggerTag: src/core/auth/qgsauthconfigurationstorage.h#L578
QgsAuthConfigurationStorage.masterPasswordChanged: src/core/auth/qgsauthconfigurationstorage.h#L519
QgsAuthConfigurationStorage.messageLog: src/core/auth/qgsauthconfigurationstorage.h#L500
QgsAuthConfigurationStorage.methodConfigChanged: src/core/auth/qgsauthconfigurationstorage.h#L514
QgsAuthConfigurationStorage.methodConfigExists: src/core/auth/qgsauthconfigurationstorage.h#L208
QgsAuthConfigurationStorage.initialize: src/core/auth/qgsauthconfigurationstorage.h#L103
QgsAuthConfigurationStorage.isEnabled: src/core/auth/qgsauthconfigurationstorage.h#L139
QgsAuthConfigurationStorage.isEncrypted: src/core/auth/qgsauthconfigurationstorage.h#L134
QgsAuthConfigurationStorage.isReadOnly: src/core/auth/qgsauthconfigurationstorage.h#L158
QgsAuthConfigurationStorage.isReady: src/core/auth/qgsauthconfigurationstorage.h#L114
QgsAuthConfigurationStorage.lastError: src/core/auth/qgsauthconfigurationstorage.h#L108
QgsAuthConfigurationStorage.loadAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L226
QgsAuthConfigurationStorage.loadCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L387
QgsAuthConfigurationStorage.loadCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L269
QgsAuthConfigurationStorage.loadCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L434
QgsAuthConfigurationStorage.loadMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L185
QgsAuthConfigurationStorage.loadSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L324
QgsAuthConfigurationStorage.loadSslCertCustomConfigByHost: src/core/auth/qgsauthconfigurationstorage.h#L332
QgsAuthConfigurationStorage.loggerTag: src/core/auth/qgsauthconfigurationstorage.h#L579
QgsAuthConfigurationStorage.masterPasswordChanged: src/core/auth/qgsauthconfigurationstorage.h#L520
QgsAuthConfigurationStorage.messageLog: src/core/auth/qgsauthconfigurationstorage.h#L501
QgsAuthConfigurationStorage.methodConfigChanged: src/core/auth/qgsauthconfigurationstorage.h#L515
QgsAuthConfigurationStorage.methodConfigExists: src/core/auth/qgsauthconfigurationstorage.h#L209
QgsAuthConfigurationStorage.name: src/core/auth/qgsauthconfigurationstorage.h#L74
QgsAuthConfigurationStorage.readOnlyChanged: src/core/auth/qgsauthconfigurationstorage.h#L529
QgsAuthConfigurationStorage.removeAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L233
QgsAuthConfigurationStorage.removeCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L402
QgsAuthConfigurationStorage.removeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L260
QgsAuthConfigurationStorage.removeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L306
QgsAuthConfigurationStorage.removeCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L441
QgsAuthConfigurationStorage.removeMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L200
QgsAuthConfigurationStorage.removeSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L363
QgsAuthConfigurationStorage.setCapabilities: src/core/auth/qgsauthconfigurationstorage.h#L561
QgsAuthConfigurationStorage.setEnabled: src/core/auth/qgsauthconfigurationstorage.h#L144
QgsAuthConfigurationStorage.setError: src/core/auth/qgsauthconfigurationstorage.h#L566
QgsAuthConfigurationStorage.setReadOnly: src/core/auth/qgsauthconfigurationstorage.h#L151
QgsAuthConfigurationStorage.sslCertCustomConfigChanged: src/core/auth/qgsauthconfigurationstorage.h#L547
QgsAuthConfigurationStorage.sslCertCustomConfigExists: src/core/auth/qgsauthconfigurationstorage.h#L354
QgsAuthConfigurationStorage.sslCertCustomConfigIds: src/core/auth/qgsauthconfigurationstorage.h#L345
QgsAuthConfigurationStorage.sslCertTrustPolicyChanged: src/core/auth/qgsauthconfigurationstorage.h#L552
QgsAuthConfigurationStorage.storageChanged: src/core/auth/qgsauthconfigurationstorage.h#L509
QgsAuthConfigurationStorage.storeAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L217
QgsAuthConfigurationStorage.storeCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L371
QgsAuthConfigurationStorage.storeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L252
QgsAuthConfigurationStorage.storeCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L425
QgsAuthConfigurationStorage.storeMasterPassword: src/core/auth/qgsauthconfigurationstorage.h#L466
QgsAuthConfigurationStorage.storeMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L193
QgsAuthConfigurationStorage.storeSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L314
QgsAuthConfigurationStorage.readOnlyChanged: src/core/auth/qgsauthconfigurationstorage.h#L530
QgsAuthConfigurationStorage.removeAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L234
QgsAuthConfigurationStorage.removeCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L403
QgsAuthConfigurationStorage.removeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L261
QgsAuthConfigurationStorage.removeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L307
QgsAuthConfigurationStorage.removeCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L442
QgsAuthConfigurationStorage.removeMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L201
QgsAuthConfigurationStorage.removeSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L364
QgsAuthConfigurationStorage.setCapabilities: src/core/auth/qgsauthconfigurationstorage.h#L562
QgsAuthConfigurationStorage.setEnabled: src/core/auth/qgsauthconfigurationstorage.h#L145
QgsAuthConfigurationStorage.setError: src/core/auth/qgsauthconfigurationstorage.h#L567
QgsAuthConfigurationStorage.setReadOnly: src/core/auth/qgsauthconfigurationstorage.h#L152
QgsAuthConfigurationStorage.sslCertCustomConfigChanged: src/core/auth/qgsauthconfigurationstorage.h#L548
QgsAuthConfigurationStorage.sslCertCustomConfigExists: src/core/auth/qgsauthconfigurationstorage.h#L355
QgsAuthConfigurationStorage.sslCertCustomConfigIds: src/core/auth/qgsauthconfigurationstorage.h#L346
QgsAuthConfigurationStorage.sslCertTrustPolicyChanged: src/core/auth/qgsauthconfigurationstorage.h#L553
QgsAuthConfigurationStorage.storageChanged: src/core/auth/qgsauthconfigurationstorage.h#L510
QgsAuthConfigurationStorage.storeAuthSetting: src/core/auth/qgsauthconfigurationstorage.h#L218
QgsAuthConfigurationStorage.storeCertAuthority: src/core/auth/qgsauthconfigurationstorage.h#L372
QgsAuthConfigurationStorage.storeCertIdentity: src/core/auth/qgsauthconfigurationstorage.h#L253
QgsAuthConfigurationStorage.storeCertTrustPolicy: src/core/auth/qgsauthconfigurationstorage.h#L426
QgsAuthConfigurationStorage.storeMasterPassword: src/core/auth/qgsauthconfigurationstorage.h#L467
QgsAuthConfigurationStorage.storeMethodConfig: src/core/auth/qgsauthconfigurationstorage.h#L194
QgsAuthConfigurationStorage.storeSslCertCustomConfig: src/core/auth/qgsauthconfigurationstorage.h#L315
QgsAuthConfigurationStorage.type: src/core/auth/qgsauthconfigurationstorage.h#L81
QgsAuthConfigurationStorage: src/core/auth/qgsauthconfigurationstorage.h#L36
QgsAuthConfigurationStorageDb.authDatabaseConnection: src/core/auth/qgsauthconfigurationstoragedb.h#L75
@ -4884,7 +4884,7 @@ QgsGeometry.Error.hasWhere: src/core/geometry/qgsgeometry.h#L2776
QgsGeometry.Error.what: src/core/geometry/qgsgeometry.h#L2766
QgsGeometry.Error.where: src/core/geometry/qgsgeometry.h#L2771
QgsGeometry.Error: src/core/geometry/qgsgeometry.h#L2747
QgsGeometry.QVariant: src/core/geometry/qgsgeometry.h#L3183
QgsGeometry.QVariant: src/core/geometry/qgsgeometry.h#L3185
QgsGeometry.QgsGeometry: src/core/geometry/qgsgeometry.h#L184
QgsGeometry.__repr__: src/core/geometry/qgsgeometry.h#L2185
QgsGeometry.addPart: src/core/geometry/qgsgeometry.h#L930
@ -4938,8 +4938,8 @@ QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1465
QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1472
QgsGeometry.contains: src/core/geometry/qgsgeometry.h#L1483
QgsGeometry.convertGeometryCollectionToSubclass: src/core/geometry/qgsgeometry.h#L2609
QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3170
QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3177
QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3172
QgsGeometry.convertPointList: src/core/geometry/qgsgeometry.h#L3179
QgsGeometry.convertToCurvedMultiType: src/core/geometry/qgsgeometry.h#L2587
QgsGeometry.convertToCurves: src/core/geometry/qgsgeometry.h#L1674
QgsGeometry.convertToMultiType: src/core/geometry/qgsgeometry.h#L2570
@ -4947,7 +4947,7 @@ QgsGeometry.convertToSingleType: src/core/geometry/qgsgeometry.h#L2598
QgsGeometry.convertToStraightSegment: src/core/geometry/qgsgeometry.h#L2843
QgsGeometry.convertToType: src/core/geometry/qgsgeometry.h#L2252
QgsGeometry.convexHull: src/core/geometry/qgsgeometry.h#L1804
QgsGeometry.createGeometryEngine: src/core/geometry/qgsgeometry.h#L3163
QgsGeometry.createGeometryEngine: src/core/geometry/qgsgeometry.h#L3165
QgsGeometry.createPolygonFromQPolygonF: src/core/geometry/qgsgeometry.h#L2952
QgsGeometry.createPolylineFromQPolygonF: src/core/geometry/qgsgeometry.h#L2943
QgsGeometry.createWedgeBuffer: src/core/geometry/qgsgeometry.h#L347
@ -6710,29 +6710,29 @@ QgsLayoutEffect.compositionMode: src/core/layout/qgslayouteffect.h#L60
QgsLayoutEffect.draw: src/core/layout/qgslayouteffect.h#L64
QgsLayoutEffect.setCompositionMode: src/core/layout/qgslayouteffect.h#L51
QgsLayoutEffect: src/core/layout/qgslayouteffect.h#L36
QgsLayoutExporter.computeWorldFileParameters: src/core/layout/qgslayoutexporter.h#L664
QgsLayoutExporter.computeWorldFileParameters: src/core/layout/qgslayoutexporter.h#L671
QgsLayoutExporter.containsAdvancedEffects: src/core/layout/qgslayoutexporter.h#L690
QgsLayoutExporter.errorFile: src/core/layout/qgslayoutexporter.h#L608
QgsLayoutExporter.errorMessage: src/core/layout/qgslayoutexporter.h#L615
QgsLayoutExporter.exportToImage: src/core/layout/qgslayoutexporter.h#L246
QgsLayoutExporter.exportToImage: src/core/layout/qgslayoutexporter.h#L259
QgsLayoutExporter.exportToPdf: src/core/layout/qgslayoutexporter.h#L406
QgsLayoutExporter.exportToPdf: src/core/layout/qgslayoutexporter.h#L419
QgsLayoutExporter.exportToPdfs: src/core/layout/qgslayoutexporter.h#L435
QgsLayoutExporter.exportToSvg: src/core/layout/qgslayoutexporter.h#L587
QgsLayoutExporter.computeWorldFileParameters: src/core/layout/qgslayoutexporter.h#L676
QgsLayoutExporter.computeWorldFileParameters: src/core/layout/qgslayoutexporter.h#L683
QgsLayoutExporter.containsAdvancedEffects: src/core/layout/qgslayoutexporter.h#L702
QgsLayoutExporter.errorFile: src/core/layout/qgslayoutexporter.h#L620
QgsLayoutExporter.errorMessage: src/core/layout/qgslayoutexporter.h#L627
QgsLayoutExporter.exportToImage: src/core/layout/qgslayoutexporter.h#L258
QgsLayoutExporter.exportToImage: src/core/layout/qgslayoutexporter.h#L271
QgsLayoutExporter.exportToPdf: src/core/layout/qgslayoutexporter.h#L418
QgsLayoutExporter.exportToPdf: src/core/layout/qgslayoutexporter.h#L431
QgsLayoutExporter.exportToPdfs: src/core/layout/qgslayoutexporter.h#L447
QgsLayoutExporter.exportToSvg: src/core/layout/qgslayoutexporter.h#L599
QgsLayoutExporter.generateFileName: src/core/layout/qgslayoutexporter.h#L699
QgsLayoutExporter.georeferenceOutput: src/core/layout/qgslayoutexporter.h#L655
QgsLayoutExporter.layout: src/core/layout/qgslayoutexporter.h#L90
QgsLayoutExporter.print: src/core/layout/qgslayoutexporter.h#L480
QgsLayoutExporter.print: src/core/layout/qgslayoutexporter.h#L489
QgsLayoutExporter.renderPage: src/core/layout/qgslayoutexporter.h#L100
QgsLayoutExporter.renderPageToImage: src/core/layout/qgslayoutexporter.h#L120
QgsLayoutExporter.renderRegion: src/core/layout/qgslayoutexporter.h#L129
QgsLayoutExporter.renderRegionToImage: src/core/layout/qgslayoutexporter.h#L147
QgsLayoutExporter.requiresRasterization: src/core/layout/qgslayoutexporter.h#L681
QgsLayoutExporter: src/core/layout/qgslayoutexporter.h#L50
QgsLayoutExporter.exportToSvg: src/core/layout/qgslayoutexporter.h#L611
QgsLayoutExporter.generateFileName: src/core/layout/qgslayoutexporter.h#L711
QgsLayoutExporter.georeferenceOutput: src/core/layout/qgslayoutexporter.h#L667
QgsLayoutExporter.layout: src/core/layout/qgslayoutexporter.h#L94
QgsLayoutExporter.print: src/core/layout/qgslayoutexporter.h#L492
QgsLayoutExporter.print: src/core/layout/qgslayoutexporter.h#L501
QgsLayoutExporter.renderPage: src/core/layout/qgslayoutexporter.h#L104
QgsLayoutExporter.renderPageToImage: src/core/layout/qgslayoutexporter.h#L124
QgsLayoutExporter.renderRegion: src/core/layout/qgslayoutexporter.h#L133
QgsLayoutExporter.renderRegionToImage: src/core/layout/qgslayoutexporter.h#L151
QgsLayoutExporter.requiresRasterization: src/core/layout/qgslayoutexporter.h#L693
QgsLayoutExporter: src/core/layout/qgslayoutexporter.h#L51
QgsLayoutFrame.cleanup: src/core/layout/qgslayoutframe.h#L54
QgsLayoutFrame.create: src/core/layout/qgslayoutframe.h#L46
QgsLayoutFrame.createExpressionContext: src/core/layout/qgslayoutframe.h#L112
@ -7567,53 +7567,55 @@ QgsLayoutItemPicture.svgStrokeWidth: src/core/layout/qgslayoutitempicture.h#L209
QgsLayoutItemPicture.type: src/core/layout/qgslayoutitempicture.h#L63
QgsLayoutItemPicture.writePropertiesToElement: src/core/layout/qgslayoutitempicture.h#L313
QgsLayoutItemPicture: src/core/layout/qgslayoutitempicture.h#L34
QgsLayoutItemPolygon._addNode: src/core/layout/qgslayoutitempolygon.h#L76
QgsLayoutItemPolygon._draw: src/core/layout/qgslayoutitempolygon.h#L78
QgsLayoutItemPolygon._readXmlStyle: src/core/layout/qgslayoutitempolygon.h#L79
QgsLayoutItemPolygon._removeNode: src/core/layout/qgslayoutitempolygon.h#L77
QgsLayoutItemPolygon._writeXmlStyle: src/core/layout/qgslayoutitempolygon.h#L80
QgsLayoutItemPolygon._addNode: src/core/layout/qgslayoutitempolygon.h#L77
QgsLayoutItemPolygon._draw: src/core/layout/qgslayoutitempolygon.h#L79
QgsLayoutItemPolygon._readXmlStyle: src/core/layout/qgslayoutitempolygon.h#L80
QgsLayoutItemPolygon._removeNode: src/core/layout/qgslayoutitempolygon.h#L78
QgsLayoutItemPolygon._writeXmlStyle: src/core/layout/qgslayoutitempolygon.h#L81
QgsLayoutItemPolygon.accept: src/core/layout/qgslayoutitempolygon.h#L58
QgsLayoutItemPolygon.clipPath: src/core/layout/qgslayoutitempolygon.h#L60
QgsLayoutItemPolygon.create: src/core/layout/qgslayoutitempolygon.h#L53
QgsLayoutItemPolygon.displayName: src/core/layout/qgslayoutitempolygon.h#L57
QgsLayoutItemPolygon.icon: src/core/layout/qgslayoutitempolygon.h#L56
QgsLayoutItemPolygon.isValid: src/core/layout/qgslayoutitempolygon.h#L61
QgsLayoutItemPolygon.itemFlags: src/core/layout/qgslayoutitempolygon.h#L59
QgsLayoutItemPolygon.setSymbol: src/core/layout/qgslayoutitempolygon.h#L73
QgsLayoutItemPolygon.symbol: src/core/layout/qgslayoutitempolygon.h#L66
QgsLayoutItemPolygon.setSymbol: src/core/layout/qgslayoutitempolygon.h#L74
QgsLayoutItemPolygon.symbol: src/core/layout/qgslayoutitempolygon.h#L67
QgsLayoutItemPolygon.type: src/core/layout/qgslayoutitempolygon.h#L55
QgsLayoutItemPolygon: src/core/layout/qgslayoutitempolygon.h#L29
QgsLayoutItemPolyline._addNode: src/core/layout/qgslayoutitempolyline.h#L197
QgsLayoutItemPolyline._draw: src/core/layout/qgslayoutitempolyline.h#L199
QgsLayoutItemPolyline._readXmlStyle: src/core/layout/qgslayoutitempolyline.h#L200
QgsLayoutItemPolyline._removeNode: src/core/layout/qgslayoutitempolyline.h#L198
QgsLayoutItemPolyline._writeXmlStyle: src/core/layout/qgslayoutitempolyline.h#L201
QgsLayoutItemPolyline.accept: src/core/layout/qgslayoutitempolyline.h#L193
QgsLayoutItemPolyline.arrowHeadFillColor: src/core/layout/qgslayoutitempolyline.h#L170
QgsLayoutItemPolyline.arrowHeadStrokeColor: src/core/layout/qgslayoutitempolyline.h#L156
QgsLayoutItemPolyline.arrowHeadStrokeWidth: src/core/layout/qgslayoutitempolyline.h#L191
QgsLayoutItemPolyline.arrowHeadWidth: src/core/layout/qgslayoutitempolyline.h#L121
QgsLayoutItemPolyline._addNode: src/core/layout/qgslayoutitempolyline.h#L198
QgsLayoutItemPolyline._draw: src/core/layout/qgslayoutitempolyline.h#L200
QgsLayoutItemPolyline._readXmlStyle: src/core/layout/qgslayoutitempolyline.h#L201
QgsLayoutItemPolyline._removeNode: src/core/layout/qgslayoutitempolyline.h#L199
QgsLayoutItemPolyline._writeXmlStyle: src/core/layout/qgslayoutitempolyline.h#L202
QgsLayoutItemPolyline.accept: src/core/layout/qgslayoutitempolyline.h#L194
QgsLayoutItemPolyline.arrowHeadFillColor: src/core/layout/qgslayoutitempolyline.h#L171
QgsLayoutItemPolyline.arrowHeadStrokeColor: src/core/layout/qgslayoutitempolyline.h#L157
QgsLayoutItemPolyline.arrowHeadStrokeWidth: src/core/layout/qgslayoutitempolyline.h#L192
QgsLayoutItemPolyline.arrowHeadWidth: src/core/layout/qgslayoutitempolyline.h#L122
QgsLayoutItemPolyline.create: src/core/layout/qgslayoutitempolyline.h#L63
QgsLayoutItemPolyline.displayName: src/core/layout/qgslayoutitempolyline.h#L67
QgsLayoutItemPolyline.endMarker: src/core/layout/qgslayoutitempolyline.h#L102
QgsLayoutItemPolyline.endSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L149
QgsLayoutItemPolyline.endMarker: src/core/layout/qgslayoutitempolyline.h#L103
QgsLayoutItemPolyline.endSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L150
QgsLayoutItemPolyline.icon: src/core/layout/qgslayoutitempolyline.h#L66
QgsLayoutItemPolyline.readPropertiesFromElement: src/core/layout/qgslayoutitempolyline.h#L203
QgsLayoutItemPolyline.setArrowHeadFillColor: src/core/layout/qgslayoutitempolyline.h#L177
QgsLayoutItemPolyline.setArrowHeadStrokeColor: src/core/layout/qgslayoutitempolyline.h#L163
QgsLayoutItemPolyline.setArrowHeadStrokeWidth: src/core/layout/qgslayoutitempolyline.h#L184
QgsLayoutItemPolyline.setArrowHeadWidth: src/core/layout/qgslayoutitempolyline.h#L115
QgsLayoutItemPolyline.setEndMarker: src/core/layout/qgslayoutitempolyline.h#L109
QgsLayoutItemPolyline.setEndSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L142
QgsLayoutItemPolyline.setStartMarker: src/core/layout/qgslayoutitempolyline.h#L95
QgsLayoutItemPolyline.setStartSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L128
QgsLayoutItemPolyline.setSymbol: src/core/layout/qgslayoutitempolyline.h#L81
QgsLayoutItemPolyline.isValid: src/core/layout/qgslayoutitempolyline.h#L69
QgsLayoutItemPolyline.readPropertiesFromElement: src/core/layout/qgslayoutitempolyline.h#L204
QgsLayoutItemPolyline.setArrowHeadFillColor: src/core/layout/qgslayoutitempolyline.h#L178
QgsLayoutItemPolyline.setArrowHeadStrokeColor: src/core/layout/qgslayoutitempolyline.h#L164
QgsLayoutItemPolyline.setArrowHeadStrokeWidth: src/core/layout/qgslayoutitempolyline.h#L185
QgsLayoutItemPolyline.setArrowHeadWidth: src/core/layout/qgslayoutitempolyline.h#L116
QgsLayoutItemPolyline.setEndMarker: src/core/layout/qgslayoutitempolyline.h#L110
QgsLayoutItemPolyline.setEndSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L143
QgsLayoutItemPolyline.setStartMarker: src/core/layout/qgslayoutitempolyline.h#L96
QgsLayoutItemPolyline.setStartSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L129
QgsLayoutItemPolyline.setSymbol: src/core/layout/qgslayoutitempolyline.h#L82
QgsLayoutItemPolyline.shape: src/core/layout/qgslayoutitempolyline.h#L68
QgsLayoutItemPolyline.startMarker: src/core/layout/qgslayoutitempolyline.h#L88
QgsLayoutItemPolyline.startSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L135
QgsLayoutItemPolyline.symbol: src/core/layout/qgslayoutitempolyline.h#L74
QgsLayoutItemPolyline.startMarker: src/core/layout/qgslayoutitempolyline.h#L89
QgsLayoutItemPolyline.startSvgMarkerPath: src/core/layout/qgslayoutitempolyline.h#L136
QgsLayoutItemPolyline.symbol: src/core/layout/qgslayoutitempolyline.h#L75
QgsLayoutItemPolyline.type: src/core/layout/qgslayoutitempolyline.h#L65
QgsLayoutItemPolyline.updateBoundingRect: src/core/layout/qgslayoutitempolyline.h#L207
QgsLayoutItemPolyline.writePropertiesToElement: src/core/layout/qgslayoutitempolyline.h#L202
QgsLayoutItemPolyline.updateBoundingRect: src/core/layout/qgslayoutitempolyline.h#L208
QgsLayoutItemPolyline.writePropertiesToElement: src/core/layout/qgslayoutitempolyline.h#L203
QgsLayoutItemPolyline: src/core/layout/qgslayoutitempolyline.h#L32
QgsLayoutItemRegistry.addLayoutItemType: src/core/layout/qgslayoutitemregistry.h#L429
QgsLayoutItemRegistry.addLayoutMultiFrameType: src/core/layout/qgslayoutitemregistry.h#L435
@ -7853,33 +7855,34 @@ QgsLayoutMultiFrameAbstractMetadata.resolvePaths: src/core/layout/qgslayoutitemr
QgsLayoutMultiFrameAbstractMetadata.type: src/core/layout/qgslayoutitemregistry.h#L204
QgsLayoutMultiFrameAbstractMetadata.visibleName: src/core/layout/qgslayoutitemregistry.h#L214
QgsLayoutMultiFrameAbstractMetadata: src/core/layout/qgslayoutitemregistry.h#L186
QgsLayoutNodesItem._addNode: src/core/layout/qgslayoutitemnodeitem.h#L140
QgsLayoutNodesItem._draw: src/core/layout/qgslayoutitemnodeitem.h#L146
QgsLayoutNodesItem._readXmlStyle: src/core/layout/qgslayoutitemnodeitem.h#L149
QgsLayoutNodesItem._removeNode: src/core/layout/qgslayoutitemnodeitem.h#L143
QgsLayoutNodesItem._writeXmlStyle: src/core/layout/qgslayoutitemnodeitem.h#L152
QgsLayoutNodesItem._addNode: src/core/layout/qgslayoutitemnodeitem.h#L149
QgsLayoutNodesItem._draw: src/core/layout/qgslayoutitemnodeitem.h#L155
QgsLayoutNodesItem._readXmlStyle: src/core/layout/qgslayoutitemnodeitem.h#L158
QgsLayoutNodesItem._removeNode: src/core/layout/qgslayoutitemnodeitem.h#L152
QgsLayoutNodesItem._writeXmlStyle: src/core/layout/qgslayoutitemnodeitem.h#L161
QgsLayoutNodesItem.addNode: src/core/layout/qgslayoutitemnodeitem.h#L54
QgsLayoutNodesItem.boundingRect: src/core/layout/qgslayoutitemnodeitem.h#L110
QgsLayoutNodesItem.computeDistance: src/core/layout/qgslayoutitemnodeitem.h#L161
QgsLayoutNodesItem.computeDistance: src/core/layout/qgslayoutitemnodeitem.h#L170
QgsLayoutNodesItem.deselectNode: src/core/layout/qgslayoutitemnodeitem.h#L107
QgsLayoutNodesItem.draw: src/core/layout/qgslayoutitemnodeitem.h#L128
QgsLayoutNodesItem.draw: src/core/layout/qgslayoutitemnodeitem.h#L137
QgsLayoutNodesItem.estimatedFrameBleed: src/core/layout/qgslayoutitemnodeitem.h#L114
QgsLayoutNodesItem.itemFlags: src/core/layout/qgslayoutitemnodeitem.h#L129
QgsLayoutNodesItem.isValid: src/core/layout/qgslayoutitemnodeitem.h#L123
QgsLayoutNodesItem.itemFlags: src/core/layout/qgslayoutitemnodeitem.h#L138
QgsLayoutNodesItem.moveNode: src/core/layout/qgslayoutitemnodeitem.h#L66
QgsLayoutNodesItem.nodeAtPosition: src/core/layout/qgslayoutitemnodeitem.h#L76
QgsLayoutNodesItem.nodePosition: src/core/layout/qgslayoutitemnodeitem.h#L84
QgsLayoutNodesItem.nodes: src/core/layout/qgslayoutitemnodeitem.h#L44
QgsLayoutNodesItem.nodesSize: src/core/layout/qgslayoutitemnodeitem.h#L92
QgsLayoutNodesItem.readPropertiesFromElement: src/core/layout/qgslayoutitemnodeitem.h#L131
QgsLayoutNodesItem.readPropertiesFromElement: src/core/layout/qgslayoutitemnodeitem.h#L140
QgsLayoutNodesItem.removeNode: src/core/layout/qgslayoutitemnodeitem.h#L89
QgsLayoutNodesItem.rescaleToFitBoundingBox: src/core/layout/qgslayoutitemnodeitem.h#L158
QgsLayoutNodesItem.rescaleToFitBoundingBox: src/core/layout/qgslayoutitemnodeitem.h#L167
QgsLayoutNodesItem.selectedNode: src/core/layout/qgslayoutitemnodeitem.h#L102
QgsLayoutNodesItem.setDisplayNodes: src/core/layout/qgslayoutitemnodeitem.h#L59
QgsLayoutNodesItem.setNodes: src/core/layout/qgslayoutitemnodeitem.h#L38
QgsLayoutNodesItem.setSelectedNode: src/core/layout/qgslayoutitemnodeitem.h#L97
QgsLayoutNodesItem.updateBoundingRect: src/core/layout/qgslayoutitemnodeitem.h#L175
QgsLayoutNodesItem.updateSceneRect: src/core/layout/qgslayoutitemnodeitem.h#L164
QgsLayoutNodesItem.writePropertiesToElement: src/core/layout/qgslayoutitemnodeitem.h#L130
QgsLayoutNodesItem.updateBoundingRect: src/core/layout/qgslayoutitemnodeitem.h#L184
QgsLayoutNodesItem.updateSceneRect: src/core/layout/qgslayoutitemnodeitem.h#L173
QgsLayoutNodesItem.writePropertiesToElement: src/core/layout/qgslayoutitemnodeitem.h#L139
QgsLayoutNodesItem: src/core/layout/qgslayoutitemnodeitem.h#L28
QgsLayoutNorthArrowHandler.arrowRotation: src/core/layout/qgslayoutnortharrowhandler.h#L52
QgsLayoutNorthArrowHandler.arrowRotationChanged: src/core/layout/qgslayoutnortharrowhandler.h#L99
@ -7906,8 +7909,9 @@ QgsLayoutObject.writeObjectPropertiesToElement: src/core/layout/qgslayoutobject.
QgsLayoutObject: src/core/layout/qgslayoutobject.h#L38
QgsLayoutPageCollection.QgsLayoutPageCollection: src/core/layout/qgslayoutpagecollection.h#L49
QgsLayoutPageCollection.addPage: src/core/layout/qgslayoutpagecollection.h#L159
QgsLayoutPageCollection.applyPropertiesToAllOtherPages: src/core/layout/qgslayoutpagecollection.h#L396
QgsLayoutPageCollection.beginPageSizeChange: src/core/layout/qgslayoutpagecollection.h#L245
QgsLayoutPageCollection.changed: src/core/layout/qgslayoutpagecollection.h#L403
QgsLayoutPageCollection.changed: src/core/layout/qgslayoutpagecollection.h#L410
QgsLayoutPageCollection.clear: src/core/layout/qgslayoutpagecollection.h#L216
QgsLayoutPageCollection.deletePage: src/core/layout/qgslayoutpagecollection.h#L200
QgsLayoutPageCollection.deletePage: src/core/layout/qgslayoutpagecollection.h#L210
@ -7919,7 +7923,7 @@ QgsLayoutPageCollection.layout: src/core/layout/qgslayoutpagecollection.h#L54
QgsLayoutPageCollection.maximumPageSize: src/core/layout/qgslayoutpagecollection.h#L275
QgsLayoutPageCollection.maximumPageWidth: src/core/layout/qgslayoutpagecollection.h#L267
QgsLayoutPageCollection.page: src/core/layout/qgslayoutpagecollection.h#L76
QgsLayoutPageCollection.pageAboutToBeRemoved: src/core/layout/qgslayoutpagecollection.h#L411
QgsLayoutPageCollection.pageAboutToBeRemoved: src/core/layout/qgslayoutpagecollection.h#L418
QgsLayoutPageCollection.pageAtPoint: src/core/layout/qgslayoutpagecollection.h#L328
QgsLayoutPageCollection.pageCount: src/core/layout/qgslayoutpagecollection.h#L67
QgsLayoutPageCollection.pageIsEmpty: src/core/layout/qgslayoutpagecollection.h#L113
@ -7932,7 +7936,7 @@ QgsLayoutPageCollection.pageStyleSymbol: src/core/layout/qgslayoutpagecollection
QgsLayoutPageCollection.positionOnPage: src/core/layout/qgslayoutpagecollection.h#L347
QgsLayoutPageCollection.predictPageNumberForPoint: src/core/layout/qgslayoutpagecollection.h#L316
QgsLayoutPageCollection.readXml: src/core/layout/qgslayoutpagecollection.h#L379
QgsLayoutPageCollection.redraw: src/core/layout/qgslayoutpagecollection.h#L396
QgsLayoutPageCollection.redraw: src/core/layout/qgslayoutpagecollection.h#L403
QgsLayoutPageCollection.reflow: src/core/layout/qgslayoutpagecollection.h#L259
QgsLayoutPageCollection.resizeToContents: src/core/layout/qgslayoutpagecollection.h#L367
QgsLayoutPageCollection.setPageStyleSymbol: src/core/layout/qgslayoutpagecollection.h#L229
@ -8395,14 +8399,14 @@ QgsLineSegment2D.startX: src/core/geometry/qgslinesegment.h#L80
QgsLineSegment2D.startY: src/core/geometry/qgslinesegment.h#L90
QgsLineSegment2D: src/core/geometry/qgslinesegment.h#L31
QgsLineString.QgsLineString: src/core/geometry/qgslinestring.h#L257
QgsLineString.__delitem__: src/core/geometry/qgslinestring.h#L1159
QgsLineString.__getitem__: src/core/geometry/qgslinestring.h#L1100
QgsLineString.__repr__: src/core/geometry/qgslinestring.h#L1082
QgsLineString.__setitem__: src/core/geometry/qgslinestring.h#L1128
QgsLineString.addMValue: src/core/geometry/qgslinestring.h#L1050
QgsLineString.addToPainterPath: src/core/geometry/qgslinestring.h#L1021
QgsLineString.__delitem__: src/core/geometry/qgslinestring.h#L1169
QgsLineString.__getitem__: src/core/geometry/qgslinestring.h#L1110
QgsLineString.__repr__: src/core/geometry/qgslinestring.h#L1092
QgsLineString.__setitem__: src/core/geometry/qgslinestring.h#L1138
QgsLineString.addMValue: src/core/geometry/qgslinestring.h#L1060
QgsLineString.addToPainterPath: src/core/geometry/qgslinestring.h#L1031
QgsLineString.addVertex: src/core/geometry/qgslinestring.h#L918
QgsLineString.addZValue: src/core/geometry/qgslinestring.h#L1049
QgsLineString.addZValue: src/core/geometry/qgslinestring.h#L1059
QgsLineString.append: src/core/geometry/qgslinestring.h#L912
QgsLineString.asGml2: src/core/geometry/qgslinestring.h#L982
QgsLineString.asGml3: src/core/geometry/qgslinestring.h#L983
@ -8412,25 +8416,25 @@ QgsLineString.asWkb: src/core/geometry/qgslinestring.h#L980
QgsLineString.asWkt: src/core/geometry/qgslinestring.h#L981
QgsLineString.boundingBoxIntersects: src/core/geometry/qgslinestring.h#L961
QgsLineString.boundingBoxIntersects: src/core/geometry/qgslinestring.h#L962
QgsLineString.calculateBoundingBox3D: src/core/geometry/qgslinestring.h#L1189
QgsLineString.calculateBoundingBox3d: src/core/geometry/qgslinestring.h#L1182
QgsLineString.centroid: src/core/geometry/qgslinestring.h#L1035
QgsLineString.calculateBoundingBox3D: src/core/geometry/qgslinestring.h#L1199
QgsLineString.calculateBoundingBox3d: src/core/geometry/qgslinestring.h#L1192
QgsLineString.centroid: src/core/geometry/qgslinestring.h#L1045
QgsLineString.clear: src/core/geometry/qgslinestring.h#L953
QgsLineString.clone: src/core/geometry/qgslinestring.h#L952
QgsLineString.close: src/core/geometry/qgslinestring.h#L921
QgsLineString.closestSegment: src/core/geometry/qgslinestring.h#L1032
QgsLineString.compareToSameClass: src/core/geometry/qgslinestring.h#L1242
QgsLineString.convertTo: src/core/geometry/qgslinestring.h#L1056
QgsLineString.createEmptyWithSameType: src/core/geometry/qgslinestring.h#L1079
QgsLineString.curveSubstring: src/core/geometry/qgslinestring.h#L1030
QgsLineString.curveToLine: src/core/geometry/qgslinestring.h#L1010
QgsLineString.deleteVertex: src/core/geometry/qgslinestring.h#L1026
QgsLineString.closestSegment: src/core/geometry/qgslinestring.h#L1042
QgsLineString.compareToSameClass: src/core/geometry/qgslinestring.h#L1252
QgsLineString.convertTo: src/core/geometry/qgslinestring.h#L1066
QgsLineString.createEmptyWithSameType: src/core/geometry/qgslinestring.h#L1089
QgsLineString.curveSubstring: src/core/geometry/qgslinestring.h#L1040
QgsLineString.curveToLine: src/core/geometry/qgslinestring.h#L1020
QgsLineString.deleteVertex: src/core/geometry/qgslinestring.h#L1036
QgsLineString.dimension: src/core/geometry/qgslinestring.h#L951
QgsLineString.draw: src/core/geometry/qgslinestring.h#L1016
QgsLineString.drawAsPolygon: src/core/geometry/qgslinestring.h#L1022
QgsLineString.dropMValue: src/core/geometry/qgslinestring.h#L1053
QgsLineString.dropZValue: src/core/geometry/qgslinestring.h#L1052
QgsLineString.endPoint: src/core/geometry/qgslinestring.h#L1002
QgsLineString.draw: src/core/geometry/qgslinestring.h#L1026
QgsLineString.drawAsPolygon: src/core/geometry/qgslinestring.h#L1032
QgsLineString.dropMValue: src/core/geometry/qgslinestring.h#L1063
QgsLineString.dropZValue: src/core/geometry/qgslinestring.h#L1062
QgsLineString.endPoint: src/core/geometry/qgslinestring.h#L1012
QgsLineString.equals: src/core/geometry/qgslinestring.h#L429
QgsLineString.extend: src/core/geometry/qgslinestring.h#L934
QgsLineString.fromBezierCurve: src/core/geometry/qgslinestring.h#L296
@ -8441,28 +8445,28 @@ QgsLineString.fuzzyDistanceEqual: src/core/geometry/qgslinestring.h#L424
QgsLineString.fuzzyEqual: src/core/geometry/qgslinestring.h#L395
QgsLineString.geometryType: src/core/geometry/qgslinestring.h#L950
QgsLineString.indexOf: src/core/geometry/qgslinestring.h#L955
QgsLineString.insertVertex: src/core/geometry/qgslinestring.h#L1024
QgsLineString.interpolateM: src/core/geometry/qgslinestring.h#L1212
QgsLineString.interpolatePoint: src/core/geometry/qgslinestring.h#L1029
QgsLineString.insertVertex: src/core/geometry/qgslinestring.h#L1034
QgsLineString.interpolateM: src/core/geometry/qgslinestring.h#L1222
QgsLineString.interpolatePoint: src/core/geometry/qgslinestring.h#L1039
QgsLineString.isClosed2D: src/core/geometry/qgslinestring.h#L960
QgsLineString.isClosed: src/core/geometry/qgslinestring.h#L959
QgsLineString.isEmpty: src/core/geometry/qgslinestring.h#L954
QgsLineString.isValid: src/core/geometry/qgslinestring.h#L956
QgsLineString.length3D: src/core/geometry/qgslinestring.h#L1000
QgsLineString.length3D: src/core/geometry/qgslinestring.h#L1010
QgsLineString.length: src/core/geometry/qgslinestring.h#L988
QgsLineString.lineLocatePointByM: src/core/geometry/qgslinestring.h#L1238
QgsLineString.lineLocatePointByM: src/core/geometry/qgslinestring.h#L1248
QgsLineString.mAt: src/core/geometry/qgslinestring.h#L698
QgsLineString.measuredLine: src/core/geometry/qgslinestring.h#L1197
QgsLineString.moveVertex: src/core/geometry/qgslinestring.h#L1025
QgsLineString.nCoordinates: src/core/geometry/qgslinestring.h#L1013
QgsLineString.numPoints: src/core/geometry/qgslinestring.h#L1012
QgsLineString.pointAt: src/core/geometry/qgslinestring.h#L1033
QgsLineString.measuredLine: src/core/geometry/qgslinestring.h#L1207
QgsLineString.moveVertex: src/core/geometry/qgslinestring.h#L1035
QgsLineString.nCoordinates: src/core/geometry/qgslinestring.h#L1023
QgsLineString.numPoints: src/core/geometry/qgslinestring.h#L1022
QgsLineString.pointAt: src/core/geometry/qgslinestring.h#L1043
QgsLineString.pointN: src/core/geometry/qgslinestring.h#L449
QgsLineString.points: src/core/geometry/qgslinestring.h#L1014
QgsLineString.points: src/core/geometry/qgslinestring.h#L1024
QgsLineString.removeDuplicateNodes: src/core/geometry/qgslinestring.h#L958
QgsLineString.reversed: src/core/geometry/qgslinestring.h#L1028
QgsLineString.scroll: src/core/geometry/qgslinestring.h#L1059
QgsLineString.segmentLength: src/core/geometry/qgslinestring.h#L1048
QgsLineString.reversed: src/core/geometry/qgslinestring.h#L1038
QgsLineString.scroll: src/core/geometry/qgslinestring.h#L1069
QgsLineString.segmentLength: src/core/geometry/qgslinestring.h#L1058
QgsLineString.setMAt: src/core/geometry/qgslinestring.h#L868
QgsLineString.setPoints: src/core/geometry/qgslinestring.h#L906
QgsLineString.setXAt: src/core/geometry/qgslinestring.h#L739
@ -8470,14 +8474,14 @@ QgsLineString.setYAt: src/core/geometry/qgslinestring.h#L780
QgsLineString.setZAt: src/core/geometry/qgslinestring.h#L824
QgsLineString.simplifyByDistance: src/core/geometry/qgslinestring.h#L975
QgsLineString.snappedToGrid: src/core/geometry/qgslinestring.h#L957
QgsLineString.startPoint: src/core/geometry/qgslinestring.h#L1001
QgsLineString.sumUpArea: src/core/geometry/qgslinestring.h#L1045
QgsLineString.swapXy: src/core/geometry/qgslinestring.h#L1054
QgsLineString.startPoint: src/core/geometry/qgslinestring.h#L1011
QgsLineString.sumUpArea: src/core/geometry/qgslinestring.h#L1055
QgsLineString.swapXy: src/core/geometry/qgslinestring.h#L1064
QgsLineString.toCurveType: src/core/geometry/qgslinestring.h#L927
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1018
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1019
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1058
QgsLineString.vertexAngle: src/core/geometry/qgslinestring.h#L1047
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1028
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1029
QgsLineString.transform: src/core/geometry/qgslinestring.h#L1068
QgsLineString.vertexAngle: src/core/geometry/qgslinestring.h#L1057
QgsLineString.wkbSize: src/core/geometry/qgslinestring.h#L979
QgsLineString.xAt: src/core/geometry/qgslinestring.h#L481
QgsLineString.yAt: src/core/geometry/qgslinestring.h#L511
@ -14879,20 +14883,20 @@ QgsRemappingSinkDefinition.setSourceCrs: src/core/qgsremappingproxyfeaturesink.h
QgsRemappingSinkDefinition.sourceCrs: src/core/qgsremappingproxyfeaturesink.h#L82
QgsRemappingSinkDefinition.toVariant: src/core/qgsremappingproxyfeaturesink.h#L138
QgsRemappingSinkDefinition: src/core/qgsremappingproxyfeaturesink.h#L38
QgsRenderChecker.compareImages: src/core/qgsrenderchecker.h#L240
QgsRenderChecker.compareImages: src/core/qgsrenderchecker.h#L247
QgsRenderChecker.compareImages: src/core/qgsrenderchecker.h#L241
QgsRenderChecker.compareImages: src/core/qgsrenderchecker.h#L248
QgsRenderChecker.controlImagePath: src/core/qgsrenderchecker.h#L74
QgsRenderChecker.drawBackground: src/core/qgsrenderchecker.h#L265
QgsRenderChecker.drawBackground: src/core/qgsrenderchecker.h#L266
QgsRenderChecker.elapsedTime: src/core/qgsrenderchecker.h#L129
QgsRenderChecker.enableDashBuffering: src/core/qgsrenderchecker.h#L281
QgsRenderChecker.expectedImageFile: src/core/qgsrenderchecker.h#L272
QgsRenderChecker.enableDashBuffering: src/core/qgsrenderchecker.h#L282
QgsRenderChecker.expectedImageFile: src/core/qgsrenderchecker.h#L273
QgsRenderChecker.imageToHash: src/core/qgsrenderchecker.h#L156
QgsRenderChecker.isKnownAnomaly: src/core/qgsrenderchecker.h#L259
QgsRenderChecker.isKnownAnomaly: src/core/qgsrenderchecker.h#L260
QgsRenderChecker.markdownReport: src/core/qgsrenderchecker.h#L103
QgsRenderChecker.matchPercent: src/core/qgsrenderchecker.h#L112
QgsRenderChecker.renderedImage: src/core/qgsrenderchecker.h#L175
QgsRenderChecker.report: src/core/qgsrenderchecker.h#L92
QgsRenderChecker.runTest: src/core/qgsrenderchecker.h#L225
QgsRenderChecker.runTest: src/core/qgsrenderchecker.h#L226
QgsRenderChecker.setColorTolerance: src/core/qgsrenderchecker.h#L185
QgsRenderChecker.setControlExtension: src/core/qgsrenderchecker.h#L145
QgsRenderChecker.setControlImagePath: src/core/qgsrenderchecker.h#L82
@ -14905,7 +14909,7 @@ QgsRenderChecker.setMapSettings: src/core/qgsrenderchecker.h#L177
QgsRenderChecker.setRenderedImage: src/core/qgsrenderchecker.h#L161
QgsRenderChecker.setSizeTolerance: src/core/qgsrenderchecker.h#L192
QgsRenderChecker.shouldGenerateReport: src/core/qgsrenderchecker.h#L65
QgsRenderChecker.sourcePath: src/core/qgsrenderchecker.h#L296
QgsRenderChecker.sourcePath: src/core/qgsrenderchecker.h#L297
QgsRenderChecker.testReportDir: src/core/qgsrenderchecker.h#L57
QgsRenderChecker: src/core/qgsrenderchecker.h#L41
QgsRenderContext.addSymbolLayerClipGeometry: src/core/qgsrendercontext.h#L1028

View File

@ -17,7 +17,7 @@
***************************************************************************
"""
from qgis.PyQt.QtWidgets import QWidget, QComboBox
from qgis.PyQt.QtWidgets import QComboBox
from qgis.core import QgsSettingsEntryBase
from qgis.gui import QgsSettingsEditorWidgetWrapper
@ -46,23 +46,25 @@ class PyQgsSettingsEnumEditorWidgetWrapper(QgsSettingsEditorWidgetWrapper):
def setWidgetFromSetting(self):
if self.setting:
return self.setWidgetFromVariant(self.setting.value(self.dynamicKeyPartList()))
return self.setWidgetFromVariant(self.setting.valueAsVariant(self.dynamicKeyPartList()))
return False
def setSettingFromWidget(self):
if self.editor:
self.setting.setValue(self.variantValueFromWidget(), self.dynamicKeyPartList())
self.setting.setVariantValue(self.variantValueFromWidget(), self.dynamicKeyPartList())
return True
else:
return False
def variantValueFromWidget(self):
if self.editor:
return self.setting.defaultValue().__class__(self.editor.currentData())
return self.editor.currentData()
return None
def setWidgetFromVariant(self, value):
if self.editor:
if self.editor and value is not None:
if isinstance(value, int):
value = self.setting.metaEnum().valueToKey(value)
idx = self.editor.findData(value)
self.editor.setCurrentIndex(idx)
return idx >= 0
@ -71,7 +73,7 @@ class PyQgsSettingsEnumEditorWidgetWrapper(QgsSettingsEditorWidgetWrapper):
def createEditorPrivate(self, parent=None):
return QComboBox(parent)
def configureEditorPrivate(self, editor: QWidget, setting: QgsSettingsEntryBase):
def configureEditorPrivate(self, editor: QComboBox, setting: QgsSettingsEntryBase):
self.setting = setting
if isinstance(editor, QComboBox):
self.editor = editor
@ -79,7 +81,7 @@ class PyQgsSettingsEnumEditorWidgetWrapper(QgsSettingsEditorWidgetWrapper):
value = self.setting.metaEnum().value(i)
key = self.setting.metaEnum().key(i)
text = self.displayStrings.get(value, key)
self.editor.addItem(text, value)
self.editor.addItem(text, key)
return True
else:
return False

View File

@ -34,12 +34,19 @@ Adds an editor widget ``wrapper`` to the registry
If an editor widget with same id already exists, the wrapper is deleted and ``False`` is returned.
%End
QgsSettingsEditorWidgetWrapper *createWrapper( const QString &id, QObject *parent ) const;
void addWrapperForSetting( QgsSettingsEditorWidgetWrapper *wrapper /Transfer/, const QgsSettingsEntryBase *setting /KeepReference/ );
%Docstring
Adds an editor widget ``wrapper`` for a specific setting to the registry
.. versionadded:: 3.40
%End
QgsSettingsEditorWidgetWrapper *createWrapper( const QString &id, QObject *parent ) const /Factory/;
%Docstring
Returns a new instance of the editor widget for the given ``id``
%End
QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList, QWidget *parent = 0 ) const /Factory/;
QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList, QWidget *parent = 0 ) const /TransferBack/;
%Docstring
Creates an editor widget for the given ``setting`` using the corresponding registered wrapper
%End

View File

@ -23,7 +23,7 @@ Base class for settings editor wrappers
#include "qgssettingseditorwidgetwrapper.h"
%End
public:
static QgsSettingsEditorWidgetWrapper *fromWidget( const QWidget *widget ) /Factory/;
static QgsSettingsEditorWidgetWrapper *fromWidget( const QWidget *widget );
%Docstring
Creates a wrapper from the definition stored in a ``widget`` created by :py:func:`~QgsSettingsEditorWidgetWrapper.createEditor`
%End
@ -44,12 +44,12 @@ This id of the type of settings it handles
This mostly correspond to the content of :py:class:`Qgis`.SettingsType but it's a string since custom Python implementation are possible.
%End
virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = 0 ) const = 0;
virtual QgsSettingsEditorWidgetWrapper *createWrapper( QObject *parent = 0 ) const = 0 /Factory/;
%Docstring
Creates a new instance of the editor wrapper so it can be configured for a widget and a setting
%End
QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList = QStringList(), QWidget *parent = 0 );
QWidget *createEditor( const QgsSettingsEntryBase *setting, const QStringList &dynamicKeyPartList = QStringList(), QWidget *parent = 0 ) /TransferBack/;
%Docstring
Creates the editor widget for the given ``setting``
%End
@ -77,7 +77,7 @@ Returns the value from the widget as a variant
The wrapper must be configured before calling this medthod
%End
virtual void setWidgetFromVariant( const QVariant &value ) const = 0;
virtual bool setWidgetFromVariant( const QVariant &value ) const = 0;
%Docstring
Sets the ``value`` of the widget
The wrapper must be configured before calling this medthod
@ -106,12 +106,12 @@ Returns the dynamic key parts
protected:
virtual QWidget *createEditorPrivate( QWidget *parent = 0 ) const = 0;
virtual QWidget *createEditorPrivate( QWidget *parent = 0 ) const = 0 /TransferBack/;
%Docstring
Creates the widgets
%End
virtual bool configureEditorPrivate( QWidget *editor, const QgsSettingsEntryBase *setting ) = 0;
virtual bool configureEditorPrivate( QWidget *editor /TransferBack/, const QgsSettingsEntryBase *setting /KeepReference/ ) = 0;
%Docstring
Configures an existing ``editor`` widget
%End

View File

@ -36,7 +36,7 @@ Constructor
virtual bool setSettingFromWidget() const = 0;
virtual void setWidgetFromVariant( const QVariant &value ) const;
virtual bool setWidgetFromVariant( const QVariant &value ) const;
virtual bool setWidgetValue( const U &value ) const = 0;
%Docstring

View File

@ -6732,8 +6732,9 @@ QgsSettingsDoubleSpinBoxWrapper.setWidgetValue: src/gui/settings/qgssettingsedit
QgsSettingsDoubleSpinBoxWrapper.valueFromWidget: src/gui/settings/qgssettingseditorwidgetwrapperimpl.h#L285
QgsSettingsDoubleSpinBoxWrapper: src/gui/settings/qgssettingseditorwidgetwrapperimpl.h#L267
QgsSettingsEditorWidgetRegistry.addWrapper: src/gui/settings/qgssettingseditorwidgetregistry.h#L46
QgsSettingsEditorWidgetRegistry.createEditor: src/gui/settings/qgssettingseditorwidgetregistry.h#L52
QgsSettingsEditorWidgetRegistry.createWrapper: src/gui/settings/qgssettingseditorwidgetregistry.h#L49
QgsSettingsEditorWidgetRegistry.addWrapperForSetting: src/gui/settings/qgssettingseditorwidgetregistry.h#L52
QgsSettingsEditorWidgetRegistry.createEditor: src/gui/settings/qgssettingseditorwidgetregistry.h#L58
QgsSettingsEditorWidgetRegistry.createWrapper: src/gui/settings/qgssettingseditorwidgetregistry.h#L55
QgsSettingsEditorWidgetRegistry: src/gui/settings/qgssettingseditorwidgetregistry.h#L35
QgsSettingsEditorWidgetWrapper.configureAutomaticUpdate: src/gui/settings/qgssettingseditorwidgetwrapper.h#L95
QgsSettingsEditorWidgetWrapper.configureEditor: src/gui/settings/qgssettingseditorwidgetwrapper.h#L59

View File

@ -463,7 +463,9 @@ class GrassUtils:
if 'r.out' in line or 'v.out' in line:
grassOutDone = True
loglines.append(line)
if any([l in line for l in ['WARNING', 'ERROR']]):
if any([l in line for l in ['WARNING', GrassUtils.tr('WARNING')]]):
feedback.pushWarning(line.strip())
elif any([l in line for l in ['ERROR', GrassUtils.tr('ERROR')]]):
feedback.reportError(line.strip())
elif 'Segmentation fault' in line:
feedback.reportError(line.strip())

View File

@ -29,9 +29,10 @@ if (HAVE_OPENCL)
endif()
# Server, also install server subdirectory
set(SERVER_DEST_RESOURCE_FILES "")
if (WITH_SERVER)
file(GLOB_RECURSE SERVER_RESOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} server/*)
set(RESOURCES_FILES ${RESOURCES_FILES} ${SERVER_RESOURCE_FILES})
add_qgis_resources("${CMAKE_CURRENT_SOURCE_DIR}" resources SERVER_DEST_RESOURCE_FILES "${SERVER_RESOURCE_FILES}")
endif()
# Server landingpage webapp
@ -43,6 +44,32 @@ if (WITH_SERVER_LANDINGPAGE_WEBAPP)
add_custom_target (server_landingpage ALL DEPENDS ${LANDINGPAGE_OUTPUT_PATH}/landingpage.stamp)
# add_custom_command does not support OUTPUT_QUIET, so we need to make a cmake subcommand first:
file(WRITE ${CMAKE_BINARY_DIR}/yarn_commands.cmake
"execute_process(
COMMAND ${YARN} install --frozen-lockfile
WORKING_DIRECTORY ${LANDINGPAGE_OUTPUT_PATH}
OUTPUT_QUIET
ERROR_FILE ${CMAKE_BINARY_DIR}/yarn_error.log
RESULT_VARIABLE YARN_RESULT
)
if(NOT YARN_RESULT EQUAL 0)
file(READ ${CMAKE_BINARY_DIR}/yarn_error.log ERROR_CONTENTS)
message(FATAL_ERROR \${ERROR_CONTENTS})
endif()
execute_process(
COMMAND ${YARN} build
WORKING_DIRECTORY ${LANDINGPAGE_OUTPUT_PATH}
OUTPUT_QUIET
ERROR_FILE ${CMAKE_BINARY_DIR}/yarn_error.log
RESULT_VARIABLE YARN_RESULT
)
if(NOT YARN_RESULT EQUAL 0)
file(READ ${CMAKE_BINARY_DIR}/yarn_error.log ERROR_CONTENTS)
message(FATAL_ERROR \${ERROR_CONTENTS})
endif()
")
add_custom_command(
POST_BUILD
OUTPUT ${LANDINGPAGE_OUTPUT_PATH}/landingpage.stamp
@ -51,7 +78,7 @@ if (WITH_SERVER_LANDINGPAGE_WEBAPP)
${CMAKE_CURRENT_SOURCE_DIR}/server/src/landingpage/
${LANDINGPAGE_OUTPUT_PATH}/
COMMAND ${CMAKE_COMMAND} -E touch ${LANDINGPAGE_OUTPUT_PATH}/landingpage.stamp
COMMAND cd ${LANDINGPAGE_OUTPUT_PATH} && ${YARN} install --frozen-lockfile && ${YARN} build
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/yarn_commands.cmake
)
endif()
@ -77,4 +104,5 @@ list(APPEND DEST_RESOURCE_FILES
"${CMAKE_CURRENT_BINARY_DIR}/srs.db")
install(FILES ${SRSDB} DESTINATION ${QGIS_DATA_DIR}/resources RENAME srs.db)
list(APPEND DEST_RESOURCE_FILES ${SERVER_DEST_RESOURCE_FILES})
add_custom_target(resources ALL DEPENDS ${DEST_RESOURCE_FILES})

View File

@ -5184,9 +5184,9 @@ http-parser-js@>=0.5.1:
integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==
http-proxy-middleware@^2.0.3:
version "2.0.6"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f"
integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==
version "2.0.7"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz#915f236d92ae98ef48278a95dedf17e991936ec6"
integrity sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==
dependencies:
"@types/http-proxy" "^1.17.8"
http-proxy "^1.18.1"

View File

@ -31,16 +31,16 @@
///@cond PRIVATE
static float screenSpaceError( QgsChunkNode *node, const QgsChunkedEntity::SceneContext &sceneContext )
static float screenSpaceError( const QgsAABB &nodeBbox, float nodeError, const QgsChunkedEntity::SceneContext &sceneContext )
{
if ( node->error() <= 0 ) //it happens for meshes
if ( nodeError <= 0 ) //it happens for meshes
return 0;
float dist = node->bbox().distanceFromPoint( sceneContext.cameraPos );
float dist = nodeBbox.distanceFromPoint( sceneContext.cameraPos );
// TODO: what to do when distance == 0 ?
float sse = Qgs3DUtils::screenSpaceError( node->error(), dist, sceneContext.screenSizePx, sceneContext.cameraFov );
float sse = Qgs3DUtils::screenSpaceError( nodeError, dist, sceneContext.screenSizePx, sceneContext.cameraFov );
return sse;
}
@ -194,7 +194,7 @@ void QgsChunkedEntity::handleSceneUpdate( const SceneContext &sceneContext )
{
QList<QgsAABB> bboxes;
for ( QgsChunkNode *n : std::as_const( mActiveNodes ) )
bboxes << n->bbox();
bboxes << Qgs3DUtils::mapToWorldExtent( n->box3D(), mMapSettings->origin() );
mBboxesEntity->setBoxes( bboxes );
}
@ -282,7 +282,7 @@ QgsRange<float> QgsChunkedEntity::getNearFarPlaneRange( const QMatrix4x4 &viewMa
{
// project each corner of bbox to camera coordinates
// and determine closest and farthest point.
QgsAABB bbox = node->bbox();
QgsAABB bbox = Qgs3DUtils::mapToWorldExtent( node->box3D(), mMapSettings->origin() );
float bboxfnear;
float bboxffar;
Qgs3DUtils::computeBoundingBoxNearFarPlanes( bbox, viewMatrix, bboxfnear, bboxffar );
@ -344,7 +344,8 @@ void QgsChunkedEntity::pruneLoaderQueue( const SceneContext &sceneContext )
while ( e )
{
Q_ASSERT( e->chunk->state() == QgsChunkNode::QueuedForLoad || e->chunk->state() == QgsChunkNode::QueuedForUpdate );
if ( Qgs3DUtils::isCullable( e->chunk->bbox(), sceneContext.viewProjectionMatrix ) )
const QgsAABB bbox = Qgs3DUtils::mapToWorldExtent( e->chunk->box3D(), mMapSettings->origin() );
if ( Qgs3DUtils::isCullable( bbox, sceneContext.viewProjectionMatrix ) )
{
toRemoveFromLoaderQueue.append( e->chunk );
}
@ -417,14 +418,16 @@ void QgsChunkedEntity::update( QgsChunkNode *root, const SceneContext &sceneCont
};
int renderedCount = 0;
std::priority_queue<slotItem, std::vector<slotItem>, decltype( cmp_funct )> pq( cmp_funct );
pq.push( std::make_pair( root, screenSpaceError( root, sceneContext ) ) );
const QgsAABB rootBbox = Qgs3DUtils::mapToWorldExtent( root->box3D(), mMapSettings->origin() );
pq.push( std::make_pair( root, screenSpaceError( rootBbox, root->error(), sceneContext ) ) );
while ( !pq.empty() && renderedCount <= mPrimitivesBudget )
{
slotItem s = pq.top();
pq.pop();
QgsChunkNode *node = s.first;
if ( Qgs3DUtils::isCullable( node->bbox(), sceneContext.viewProjectionMatrix ) )
const QgsAABB bbox = Qgs3DUtils::mapToWorldExtent( node->box3D(), mMapSettings->origin() );
if ( Qgs3DUtils::isCullable( bbox, sceneContext.viewProjectionMatrix ) )
{
++mFrustumCulled;
continue;
@ -453,7 +456,7 @@ void QgsChunkedEntity::update( QgsChunkNode *root, const SceneContext &sceneCont
// make sure all nodes leading to children are always loaded
// so that zooming out does not create issues
double dist = node->bbox().center().distanceToPoint( sceneContext.cameraPos );
double dist = bbox.center().distanceToPoint( sceneContext.cameraPos );
residencyRequests.push_back( ResidencyRequest( node, dist, node->level() ) );
if ( !node->entity() && node->hasData() )
@ -470,7 +473,7 @@ void QgsChunkedEntity::update( QgsChunkNode *root, const SceneContext &sceneCont
// or not, it's the best we'll ever get...
becomesActive = true;
}
else if ( mTau > 0 && screenSpaceError( node, sceneContext ) <= mTau && node->hasData() )
else if ( mTau > 0 && screenSpaceError( bbox, node->error(), sceneContext ) <= mTau && node->hasData() )
{
// acceptable error for the current chunk - let's render it
becomesActive = true;
@ -492,18 +495,19 @@ void QgsChunkedEntity::update( QgsChunkNode *root, const SceneContext &sceneCont
QgsChunkNode *const *children = node->children();
for ( int i = 0; i < node->childCount(); ++i )
{
const QgsAABB childBbox = Qgs3DUtils::mapToWorldExtent( children[i]->box3D(), mMapSettings->origin() );
if ( children[i]->entity() || !children[i]->hasData() )
{
// chunk is resident - let's visit it recursively
pq.push( std::make_pair( children[i], screenSpaceError( children[i], sceneContext ) ) );
pq.push( std::make_pair( children[i], screenSpaceError( childBbox, children[i]->error(), sceneContext ) ) );
}
else
{
// chunk is not yet resident - let's try to load it
if ( Qgs3DUtils::isCullable( children[i]->bbox(), sceneContext.viewProjectionMatrix ) )
if ( Qgs3DUtils::isCullable( childBbox, sceneContext.viewProjectionMatrix ) )
continue;
double dist = children[i]->bbox().center().distanceToPoint( sceneContext.cameraPos );
double dist = childBbox.center().distanceToPoint( sceneContext.cameraPos );
residencyRequests.push_back( ResidencyRequest( children[i], dist, children[i]->level() ) );
}
}
@ -517,7 +521,10 @@ void QgsChunkedEntity::update( QgsChunkNode *root, const SceneContext &sceneCont
{
QgsChunkNode *const *children = node->children();
for ( int i = 0; i < node->childCount(); ++i )
pq.push( std::make_pair( children[i], screenSpaceError( children[i], sceneContext ) ) );
{
const QgsAABB childBbox = Qgs3DUtils::mapToWorldExtent( children[i]->box3D(), mMapSettings->origin() );
pq.push( std::make_pair( children[i], screenSpaceError( childBbox, children[i]->error(), sceneContext ) ) );
}
}
else
{
@ -526,7 +533,8 @@ void QgsChunkedEntity::update( QgsChunkNode *root, const SceneContext &sceneCont
QgsChunkNode *const *children = node->children();
for ( int i = 0; i < node->childCount(); ++i )
{
double dist = children[i]->bbox().center().distanceToPoint( sceneContext.cameraPos );
const QgsAABB childBbox = Qgs3DUtils::mapToWorldExtent( children[i]->box3D(), mMapSettings->origin() );
double dist = childBbox.center().distanceToPoint( sceneContext.cameraPos );
residencyRequests.push_back( ResidencyRequest( children[i], dist, children[i]->level() ) );
}
}

View File

@ -23,17 +23,17 @@ QgsQuadtreeChunkLoaderFactory::QgsQuadtreeChunkLoaderFactory() = default;
QgsQuadtreeChunkLoaderFactory::~QgsQuadtreeChunkLoaderFactory() = default;
void QgsQuadtreeChunkLoaderFactory::setupQuadtree( const QgsAABB &rootBbox, float rootError, int maxLevel, const QgsAABB &clippingBbox )
void QgsQuadtreeChunkLoaderFactory::setupQuadtree( const QgsBox3D &rootBox3D, float rootError, int maxLevel, const QgsBox3D &clippingBox3D )
{
mRootBbox = rootBbox;
mRootBox3D = rootBox3D;
mRootError = rootError;
mMaxLevel = maxLevel;
mClippingBbox = clippingBbox;
mClippingBox3D = clippingBox3D;
}
QgsChunkNode *QgsQuadtreeChunkLoaderFactory::createRootNode() const
{
return new QgsChunkNode( QgsChunkNodeId( 0, 0, 0 ), mRootBbox, mRootError );
return new QgsChunkNode( QgsChunkNodeId( 0, 0, 0 ), mRootBox3D, mRootError );
}
QVector<QgsChunkNode *> QgsQuadtreeChunkLoaderFactory::createChildren( QgsChunkNode *node ) const
@ -45,25 +45,24 @@ QVector<QgsChunkNode *> QgsQuadtreeChunkLoaderFactory::createChildren( QgsChunkN
const QgsChunkNodeId nodeId = node->tileId();
const float childError = node->error() / 2;
const QgsAABB bbox = node->bbox();
float xc = bbox.xCenter(), zc = bbox.zCenter();
const QgsBox3D box3D = node->box3D();
QgsVector3D center = box3D.center();
for ( int i = 0; i < 4; ++i )
{
int dx = i & 1, dy = !!( i & 2 );
const QgsChunkNodeId childId( nodeId.d + 1, nodeId.x * 2 + dx, nodeId.y * 2 + ( dy ? 0 : 1 ) ); // TODO: inverse dy?
// the Y and Z coordinates below are intentionally flipped, because
// in chunk node IDs the X,Y axes define horizontal plane,
// while in our 3D scene the X,Z axes define the horizontal plane
const float chXMin = dx ? xc : bbox.xMin;
const float chXMax = dx ? bbox.xMax : xc;
const float chZMin = dy ? zc : bbox.zMin;
const float chZMax = dy ? bbox.zMax : zc;
const float chYMin = bbox.yMin;
const float chYMax = bbox.yMax;
const QgsAABB childBbox = QgsAABB( chXMin, chYMin, chZMin, chXMax, chYMax, chZMax );
if ( mClippingBbox.isEmpty() || childBbox.intersects( mClippingBbox ) )
children << new QgsChunkNode( childId, childBbox, childError, node );
const QgsChunkNodeId childId( nodeId.d + 1, nodeId.x * 2 + dx, nodeId.y * 2 + dy );
const double chXMin = dx ? center.x() : box3D.xMinimum();
const double chXMax = dx ? box3D.xMaximum() : center.x();
const double chYMin = dy ? center.y() : box3D.yMinimum();
const double chYMax = dy ? box3D.yMaximum() : center.y();
const double chZMin = box3D.zMinimum();
const double chZMax = box3D.zMaximum();
const QgsBox3D childBox3D( chXMin, chYMin, chZMin, chXMax, chYMax, chZMax );
if ( mClippingBox3D.isEmpty() || childBox3D.intersects( mClippingBox3D ) )
children << new QgsChunkNode( childId, childBox3D, childError, node );
}
return children;
}

View File

@ -27,7 +27,9 @@
// version without notice, or even be removed.
//
#include "qgis_3d.h"
#include "qgschunkqueuejob.h"
#include "qgsbox3d.h"
#define SIP_NO_FILE
@ -109,8 +111,6 @@ class QgsChunkLoaderFactory : public QObject
};
#include "qgsaabb.h"
/**
* \ingroup 3d
* \brief Base class for factories where the hierarchy is a quadtree where all leaves
@ -126,14 +126,14 @@ class _3D_EXPORT QgsQuadtreeChunkLoaderFactory : public QgsChunkLoaderFactory
virtual ~QgsQuadtreeChunkLoaderFactory();
//! Initializes the root node setup (bounding box and error) and tree depth
void setupQuadtree( const QgsAABB &rootBbox, float rootError, int maxLevel, const QgsAABB &clippingBbox = QgsAABB() );
void setupQuadtree( const QgsBox3D &rootBox3D, float rootError, int maxLevel, const QgsBox3D &clippingBox3D = QgsBox3D() );
virtual QgsChunkNode *createRootNode() const override;
virtual QVector<QgsChunkNode *> createChildren( QgsChunkNode *node ) const override;
protected:
QgsAABB mRootBbox;
QgsAABB mClippingBbox;
QgsBox3D mRootBox3D;
QgsBox3D mClippingBox3D;
float mRootError = 0;
//! maximum allowed depth of quad tree
int mMaxLevel = 0;

View File

@ -22,8 +22,8 @@
///@cond PRIVATE
QgsChunkNode::QgsChunkNode( const QgsChunkNodeId &nodeId, const QgsAABB &bbox, float error, QgsChunkNode *parent )
: mBbox( bbox )
QgsChunkNode::QgsChunkNode( const QgsChunkNodeId &nodeId, const QgsBox3D &box3D, float error, QgsChunkNode *parent )
: mBox3D( box3D )
, mError( error )
, mNodeId( nodeId )
, mParent( parent )
@ -238,9 +238,9 @@ void QgsChunkNode::setUpdated()
mState = QgsChunkNode::Loaded;
}
void QgsChunkNode::setExactBbox( const QgsAABB &box )
void QgsChunkNode::setExactBox3D( const QgsBox3D &box3D )
{
mBbox = box;
mBox3D = box3D;
// TODO: propagate better estimate to children?
}
@ -251,40 +251,40 @@ void QgsChunkNode::updateParentBoundingBoxesRecursively() const
while ( currentNode )
{
QgsChunkNode *const *currentNodeChildren = currentNode->children();
float xMin = std::numeric_limits< float >::max();
float xMax = -std::numeric_limits< float >::max();
float yMin = std::numeric_limits< float >::max();
float yMax = -std::numeric_limits< float >::max();
float zMin = std::numeric_limits< float >::max();
float zMax = -std::numeric_limits< float >::max();
double xMin = std::numeric_limits< double >::max();
double xMax = -std::numeric_limits< double >::max();
double yMin = std::numeric_limits< double >::max();
double yMax = -std::numeric_limits< double >::max();
double zMin = std::numeric_limits< double >::max();
double zMax = -std::numeric_limits< double >::max();
for ( int i = 0; i < currentNode->childCount(); ++i )
{
const QgsAABB childBBox = currentNodeChildren[i]->bbox();
const QgsBox3D childBox3D = currentNodeChildren[i]->box3D();
// Nodes without data have an empty bbox and should be skipped
if ( childBBox.isEmpty() )
if ( childBox3D.isEmpty() )
continue;
if ( childBBox.xMin < xMin )
xMin = childBBox.xMin;
if ( childBBox.yMin < yMin )
yMin = childBBox.yMin;
if ( childBBox.zMin < zMin )
zMin = childBBox.zMin;
if ( childBBox.xMax > xMax )
xMax = childBBox.xMax;
if ( childBBox.yMax > yMax )
yMax = childBBox.yMax;
if ( childBBox.zMax > zMax )
zMax = childBBox.zMax;
if ( childBox3D.xMinimum() < xMin )
xMin = childBox3D.xMinimum();
if ( childBox3D.yMinimum() < yMin )
yMin = childBox3D.yMinimum();
if ( childBox3D.zMinimum() < zMin )
zMin = childBox3D.zMinimum();
if ( childBox3D.xMaximum() > xMax )
xMax = childBox3D.xMaximum();
if ( childBox3D.yMaximum() > yMax )
yMax = childBox3D.yMaximum();
if ( childBox3D.zMaximum() > zMax )
zMax = childBox3D.zMaximum();
}
// QgsAABB is normalized in its constructor, so that min values are always smaller than max.
// QgsBox3D is normalized in its constructor, so that min values are always smaller than max.
// If all child bboxes were empty, we can end up with min > max, so let's have an empty bbox instead.
const QgsAABB currentNodeBbox = xMin > xMax || yMin > yMax || zMin > zMax ? QgsAABB() : QgsAABB( xMin, yMin, zMin, xMax, yMax, zMax );
const QgsBox3D currentNodeBox3D = xMin > xMax || yMin > yMax || zMin > zMax ? QgsBox3D() : QgsBox3D( xMin, yMin, zMin, xMax, yMax, zMax );
currentNode->setExactBbox( currentNodeBbox );
currentNode->setExactBox3D( currentNodeBox3D );
currentNode = currentNode->parent();
}
}

View File

@ -28,6 +28,7 @@
//
#include "qgsaabb.h"
#include "qgsbox3d.h"
#include "qgis.h"
#include <QTime>
@ -113,7 +114,9 @@ struct QgsChunkNodeId
* This is currently used for rendering of terrain, but it is not limited to it and may be used for
* other data as well.
*
* The data structure is essentially a quadtree: each node may have four child nodes. Nodes can exist
* The data structure is a tree: each node may have several child nodes, all child nodes should
* have their bounding box within the bounding box of their parent. Typically this is a quadtree,
* an octree, but it may be also more general structure (with variable number of children). Nodes can exist
* in several states (e.g. skeleton or loaded state) and they keep being loaded and unloaded as necessary
* by the 3D rendering.
*
@ -123,7 +126,7 @@ class QgsChunkNode
public:
//! constructs a skeleton chunk
QgsChunkNode( const QgsChunkNodeId &nodeId, const QgsAABB &bbox, float error, QgsChunkNode *parent = nullptr );
QgsChunkNode( const QgsChunkNodeId &nodeId, const QgsBox3D &box3D, float error, QgsChunkNode *parent = nullptr );
~QgsChunkNode();
@ -155,8 +158,8 @@ class QgsChunkNode
Updating, //!< Data are being updated right now
};
//! Returns 3D bounding box of the chunk
QgsAABB bbox() const { return mBbox; }
//! Returns 3D bounding box (in map coordinates) of the chunk
QgsBox3D box3D() const { return mBox3D; }
//! Returns measure geometric/texture error of the chunk (in world coordinates)
float error() const { return mError; }
//! Returns chunk tile coordinates of the tiling scheme
@ -238,8 +241,8 @@ class QgsChunkNode
//! mark node that it finished updating - back to loaded node
void setUpdated();
//! called when bounding box
void setExactBbox( const QgsAABB &box );
//! called when the true bounding box is known so that we can use tighter bounding box
void setExactBox3D( const QgsBox3D &box3D );
/**
* Triggers a recursive update of the node's parent's bounding boxes to ensure
@ -256,7 +259,7 @@ class QgsChunkNode
bool hasData() const { return mHasData; }
private:
QgsAABB mBbox; //!< Bounding box in world coordinates
QgsBox3D mBox3D; //!< Bounding box in map coordinates
float mError; //!< Error of the node in world coordinates (negative error means that chunk at this level has no data, but there may be children that do)
QgsChunkNodeId mNodeId; //!< Chunk coordinates (for use with a tiling scheme)

View File

@ -471,10 +471,10 @@ void Qgs3DMapScene::createTerrainDeferred()
{
double tile0width = mMap.terrainGenerator()->rootChunkExtent().width();
int maxZoomLevel = Qgs3DUtils::maxZoomLevel( tile0width, mMap.mapTileResolution(), mMap.maxTerrainGroundError() );
QgsAABB rootBbox = mMap.terrainGenerator()->rootChunkBbox( mMap );
const QgsBox3D rootBox3D = mMap.terrainGenerator()->rootChunkBox3D( mMap );
float rootError = mMap.terrainGenerator()->rootChunkError( mMap );
const QgsAABB clippingBbox = Qgs3DUtils::mapToWorldExtent( mMap.extent(), rootBbox.zMin, rootBbox.zMax, mMap.origin() );
mMap.terrainGenerator()->setupQuadtree( rootBbox, rootError, maxZoomLevel, clippingBbox );
const QgsBox3D clippingBox3D( mMap.extent(), rootBox3D.zMinimum(), rootBox3D.zMaximum() );
mMap.terrainGenerator()->setupQuadtree( rootBox3D, rootError, maxZoomLevel, clippingBox3D );
mTerrain = new QgsTerrainEntity( &mMap );
mTerrain->setParent( this );
@ -1069,9 +1069,9 @@ QgsDoubleRange Qgs3DMapScene::elevationRange() const
double yMax = std::numeric_limits< double >::lowest();
if ( mMap.terrainRenderingEnabled() && mTerrain )
{
const QgsAABB bbox = mTerrain->rootNode()->bbox();
yMin = std::min( yMin, static_cast< double >( bbox.yMin ) );
yMax = std::max( yMax, static_cast< double >( bbox.yMax ) );
const QgsBox3D box3D = mTerrain->rootNode()->box3D();
yMin = std::min( yMin, box3D.zMinimum() );
yMax = std::max( yMax, box3D.zMaximum() );
}
for ( auto it = mLayerEntities.constBegin(); it != mLayerEntities.constEnd(); it++ )

View File

@ -220,12 +220,12 @@ class _3D_EXPORT Qgs3DMapScene : public QObject
* A plane equation contains 4 elements.
* A simple way to define a clip plane equation is to define a normalized normal to
* the plane and its distance from the origin of the scene.
* In that case, the first 3 elements are the coordinates of the normal of the plane as (X, Y, Z).
* In that case, the first 3 elements are the coordinates of the normal of the plane as ``(X, Y, Z)``.
* They need to be normalized.
* The last element is the distance of the plane from the origin of the scene.
* In mathematical terms, a 3d plane can be defined with the equation ax+by+cz+d=0
* The normal is (a, b, c) with |a, b, c| = 1
* The distance is -d.
* In mathematical terms, a 3d plane can be defined with the equation ``ax+by+cz+d=0``
* The normal is ``(a, b, c)`` with ``|a, b, c| = 1``
* The distance is ``-d``.
*
* By default, OpenGL supports up to 8 additional clipping planes. If \a clipPlaneEquations
* contains more than 8 planes, only the first 8 ones will be used.

View File

@ -488,7 +488,7 @@ QMatrix4x4 Qgs3DUtils::stringToMatrix4x4( const QString &str )
return m;
}
void Qgs3DUtils::extractPointPositions( const QgsFeature &f, const Qgs3DRenderContext &context, Qgis::AltitudeClamping altClamp, QVector<QVector3D> &positions )
void Qgs3DUtils::extractPointPositions( const QgsFeature &f, const Qgs3DRenderContext &context, const QgsVector3D &chunkOrigin, Qgis::AltitudeClamping altClamp, QVector<QVector3D> &positions )
{
const QgsAbstractGeometry *g = f.geometry().constGet();
for ( auto it = g->vertices_begin(); it != g->vertices_end(); ++it )
@ -513,7 +513,10 @@ void Qgs3DUtils::extractPointPositions( const QgsFeature &f, const Qgs3DRenderCo
h = terrainZ + geomZ;
break;
}
positions.append( QVector3D( pt.x() - context.origin().x(), h, -( pt.y() - context.origin().y() ) ) );
positions.append( QVector3D(
static_cast<float>( pt.x() - chunkOrigin.x() ),
static_cast<float>( pt.y() - chunkOrigin.y() ),
h ) );
QgsDebugMsgLevel( QStringLiteral( "%1 %2 %3" ).arg( positions.last().x() ).arg( positions.last().y() ).arg( positions.last().z() ), 2 );
}
}
@ -630,6 +633,21 @@ QgsAABB Qgs3DUtils::mapToWorldExtent( const QgsRectangle &extent, double zMin, d
return rootBbox;
}
QgsAABB Qgs3DUtils::mapToWorldExtent( const QgsBox3D &box3D, const QgsVector3D &mapOrigin )
{
const QgsVector3D extentMin3D( box3D.xMinimum(), box3D.yMinimum(), box3D.zMinimum() );
const QgsVector3D extentMax3D( box3D.xMaximum(), box3D.yMaximum(), box3D.zMaximum() );
const QgsVector3D worldExtentMin3D = mapToWorldCoordinates( extentMin3D, mapOrigin );
const QgsVector3D worldExtentMax3D = mapToWorldCoordinates( extentMax3D, mapOrigin );
// casting to float should be ok, assuming that the map origin is not too far from the box
return QgsAABB( static_cast<float>( worldExtentMin3D.x() ),
static_cast<float>( worldExtentMin3D.y() ),
static_cast<float>( worldExtentMin3D.z() ),
static_cast<float>( worldExtentMax3D.x() ),
static_cast<float>( worldExtentMax3D.y() ),
static_cast<float>( worldExtentMax3D.z() ) );
}
QgsRectangle Qgs3DUtils::worldToMapExtent( const QgsAABB &bbox, const QgsVector3D &mapOrigin )
{
const QgsVector3D worldExtentMin3D = Qgs3DUtils::worldToMapCoordinates( QgsVector3D( bbox.xMin, bbox.yMin, bbox.zMin ), mapOrigin );

View File

@ -143,7 +143,7 @@ class _3D_EXPORT Qgs3DUtils
static QMatrix4x4 stringToMatrix4x4( const QString &str );
//! Calculates (x,y,z) positions of (multi)point from the given feature
static void extractPointPositions( const QgsFeature &f, const Qgs3DRenderContext &context, Qgis::AltitudeClamping altClamp, QVector<QVector3D> &positions );
static void extractPointPositions( const QgsFeature &f, const Qgs3DRenderContext &context, const QgsVector3D &chunkOrigin, Qgis::AltitudeClamping altClamp, QVector<QVector3D> &positions );
/**
* Returns TRUE if bbox is completely outside the current viewing volume.
@ -174,6 +174,12 @@ class _3D_EXPORT Qgs3DUtils
*/
static QgsAABB mapToWorldExtent( const QgsRectangle &extent, double zMin, double zMax, const QgsVector3D &mapOrigin );
/**
* Converts 3D box in map coordinates to AABB in world coordinates.
* \since QGIS 3.42
*/
static QgsAABB mapToWorldExtent( const QgsBox3D &box3D, const QgsVector3D &mapOrigin );
/**
* Converts axis aligned bounding box in 3D world coordinates to extent in map coordinates
* \since QGIS 3.12

View File

@ -28,10 +28,10 @@ void QgsFeature3DHandler::updateZRangeFromPositions( const QVector<QVector3D> &p
{
for ( const QVector3D &pos : positions )
{
if ( pos.y() < mZMin )
mZMin = pos.y();
if ( pos.y() > mZMax )
mZMax = pos.y();
if ( pos.z() < mZMin )
mZMin = pos.z();
if ( pos.z() > mZMax )
mZMax = pos.z();
}
}

View File

@ -49,7 +49,7 @@ class QgsFeature3DHandler
* Called before feature iteration starts to initialize, get required attributes.
* \returns TRUE on success (on FALSE the handler failed to initialize and processFeature() / finalize() should not be called
*/
virtual bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) = 0;
virtual bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin ) = 0;
/**
* Called for every feature to extract information out of it into some

View File

@ -81,8 +81,8 @@ QgsPointCloudLayerChunkLoader::QgsPointCloudLayerChunkLoader( const QgsPointClou
mFutureWatcher = new QFutureWatcher<void>( this );
connect( mFutureWatcher, &QFutureWatcher<void>::finished, this, &QgsChunkQueueJob::finished );
const QgsAABB bbox = node->bbox();
const QFuture<void> future = QtConcurrent::run( [pc, pcNode, bbox, this]
const QgsBox3D box3D = node->box3D();
const QFuture<void> future = QtConcurrent::run( [pc, pcNode, box3D, this]
{
const QgsEventTracing::ScopedEvent e( QStringLiteral( "3D" ), QStringLiteral( "PC chunk load" ) );
@ -101,7 +101,7 @@ QgsPointCloudLayerChunkLoader::QgsPointCloudLayerChunkLoader( const QgsPointClou
}
if ( mContext.symbol()->renderAsTriangles() )
mHandler->triangulate( pc, pcNode, mContext, bbox );
mHandler->triangulate( pc, pcNode, mContext, box3D );
} );
// emit finished() as soon as the handler is populated with features
@ -177,13 +177,38 @@ int QgsPointCloudLayerChunkLoaderFactory::primitivesCount( QgsChunkNode *node )
return mPointCloudIndex->nodePointCount( n );
}
QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const Qgs3DRenderContext &context, const QgsCoordinateTransform &coordinateTransform, double zValueOffset );
QgsBox3D nodeBoundsToBox3D( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const QgsCoordinateTransform &coordinateTransform, double zValueOffset, double zValueScale )
{
QgsVector3D extentMin3D( static_cast<double>( nodeBounds.xMin() ) * scale.x() + offset.x(),
static_cast<double>( nodeBounds.yMin() ) * scale.y() + offset.y(),
( static_cast<double>( nodeBounds.zMin() ) * scale.z() + offset.z() ) * zValueScale + zValueOffset );
QgsVector3D extentMax3D( static_cast<double>( nodeBounds.xMax() ) * scale.x() + offset.x(),
static_cast<double>( nodeBounds.yMax() ) * scale.y() + offset.y(),
( static_cast<double>( nodeBounds.zMax() ) * scale.z() + offset.z() ) * zValueScale + zValueOffset );
QgsCoordinateTransform extentTransform = coordinateTransform;
extentTransform.setBallparkTransformsAreAppropriate( true );
try
{
extentMin3D = extentTransform.transform( extentMin3D );
extentMax3D = extentTransform.transform( extentMax3D );
}
catch ( QgsCsException & )
{
QgsDebugError( QStringLiteral( "Error transforming node bounds coordinate" ) );
}
return QgsBox3D( extentMin3D.x(), extentMin3D.y(), extentMin3D.z(),
extentMax3D.x(), extentMax3D.y(), extentMax3D.z() );
}
QgsChunkNode *QgsPointCloudLayerChunkLoaderFactory::createRootNode() const
{
const QgsAABB bbox = nodeBoundsToAABB( mPointCloudIndex->nodeBounds( IndexedPointCloudNode( 0, 0, 0, 0 ) ), mPointCloudIndex->offset(), mPointCloudIndex->scale(), mRenderContext, mCoordinateTransform, mZValueOffset );
const QgsPointCloudDataBounds rootNodeBounds = mPointCloudIndex->nodeBounds( IndexedPointCloudNode( 0, 0, 0, 0 ) );
QgsBox3D rootNodeBox3D = nodeBoundsToBox3D( rootNodeBounds, mPointCloudIndex->offset(), mPointCloudIndex->scale(), mCoordinateTransform, mZValueOffset, mZValueScale );
const float error = mPointCloudIndex->nodeError( IndexedPointCloudNode( 0, 0, 0, 0 ) );
QgsChunkNode *node = new QgsChunkNode( QgsChunkNodeId( 0, 0, 0, 0 ), bbox, error );
QgsChunkNode *node = new QgsChunkNode( QgsChunkNodeId( 0, 0, 0, 0 ), rootNodeBox3D, error );
node->setRefinementProcess( mSymbol->renderAsTriangles() ? Qgis::TileRefinementProcess::Replacement : Qgis::TileRefinementProcess::Additive );
return node;
}
@ -192,9 +217,7 @@ QVector<QgsChunkNode *> QgsPointCloudLayerChunkLoaderFactory::createChildren( Qg
{
QVector<QgsChunkNode *> children;
const QgsChunkNodeId nodeId = node->tileId();
const QgsAABB bbox = node->bbox();
const float childError = node->error() / 2;
float xc = bbox.xCenter(), yc = bbox.yCenter(), zc = bbox.zCenter();
for ( int i = 0; i < 8; ++i )
{
@ -207,17 +230,10 @@ QVector<QgsChunkNode *> QgsPointCloudLayerChunkLoaderFactory::createChildren( Qg
!mPointCloudIndex->nodeMapExtent( IndexedPointCloudNode( childId.d, childId.x, childId.y, childId.z ) ).intersects( mExtent ) )
continue;
// the Y and Z coordinates below are intentionally flipped, because
// in chunk node IDs the X,Y axes define horizontal plane,
// while in our 3D scene the X,Z axes define the horizontal plane
const float chXMin = dx ? xc : bbox.xMin;
const float chXMax = dx ? bbox.xMax : xc;
// Z axis: values are increasing to the south
const float chZMin = !dy ? zc : bbox.zMin;
const float chZMax = !dy ? bbox.zMax : zc;
const float chYMin = dz ? yc : bbox.yMin;
const float chYMax = dz ? bbox.yMax : yc;
QgsChunkNode *child = new QgsChunkNode( childId, QgsAABB( chXMin, chYMin, chZMin, chXMax, chYMax, chZMax ), childError, node );
const QgsPointCloudDataBounds childBounds = mPointCloudIndex->nodeBounds( IndexedPointCloudNode( childId.d, childId.x, childId.y, childId.z ) );
QgsBox3D childBox3D = nodeBoundsToBox3D( childBounds, mPointCloudIndex->offset(), mPointCloudIndex->scale(), mCoordinateTransform, mZValueOffset, mZValueScale );
QgsChunkNode *child = new QgsChunkNode( childId, childBox3D, childError, node );
child->setRefinementProcess( mSymbol->renderAsTriangles() ? Qgis::TileRefinementProcess::Replacement : Qgis::TileRefinementProcess::Additive );
children << child;
}
@ -227,29 +243,6 @@ QVector<QgsChunkNode *> QgsPointCloudLayerChunkLoaderFactory::createChildren( Qg
///////////////
QgsAABB nodeBoundsToAABB( QgsPointCloudDataBounds nodeBounds, QgsVector3D offset, QgsVector3D scale, const Qgs3DRenderContext &context, const QgsCoordinateTransform &coordinateTransform, double zValueOffset )
{
QgsVector3D extentMin3D( nodeBounds.xMin() * scale.x() + offset.x(), nodeBounds.yMin() * scale.y() + offset.y(), nodeBounds.zMin() * scale.z() + offset.z() + zValueOffset );
QgsVector3D extentMax3D( nodeBounds.xMax() * scale.x() + offset.x(), nodeBounds.yMax() * scale.y() + offset.y(), nodeBounds.zMax() * scale.z() + offset.z() + zValueOffset );
QgsCoordinateTransform extentTransform = coordinateTransform;
extentTransform.setBallparkTransformsAreAppropriate( true );
try
{
extentMin3D = extentTransform.transform( extentMin3D );
extentMax3D = extentTransform.transform( extentMax3D );
}
catch ( QgsCsException & )
{
QgsDebugError( QStringLiteral( "Error transforming node bounds coordinate" ) );
}
const QgsVector3D worldExtentMin3D = Qgs3DUtils::mapToWorldCoordinates( extentMin3D, context.origin() );
const QgsVector3D worldExtentMax3D = Qgs3DUtils::mapToWorldCoordinates( extentMax3D, context.origin() );
QgsAABB rootBbox( worldExtentMin3D.x(), worldExtentMin3D.y(), worldExtentMin3D.z(),
worldExtentMax3D.x(), worldExtentMax3D.y(), worldExtentMax3D.z() );
return rootBbox;
}
QgsPointCloudLayerChunkedEntity::QgsPointCloudLayerChunkedEntity( Qgs3DMapSettings *map, QgsPointCloudIndex *pc,
const QgsCoordinateTransform &coordinateTransform, QgsPointCloud3DSymbol *symbol,
float maximumScreenSpaceError, bool showBoundingBoxes,
@ -313,7 +306,8 @@ QVector<QgsRayCastingUtils::RayHit> QgsPointCloudLayerChunkedEntity::rayIntersec
if ( !index->hasNode( n ) )
continue;
if ( !QgsRayCastingUtils::rayBoxIntersection( ray, node->bbox() ) )
const QgsAABB nodeBbox = Qgs3DUtils::mapToWorldExtent( node->box3D(), mMapSettings->origin() );
if ( !QgsRayCastingUtils::rayBoxIntersection( ray, nodeBbox ) )
continue;
std::unique_ptr<QgsPointCloudBlock> block( index->nodeData( n, request ) );

View File

@ -80,6 +80,10 @@ QgsRubberBand3D::QgsRubberBand3D( Qgs3DMapSettings &map, QgsWindow3DEngine *engi
mLineEntity->addComponent( mLineMaterial );
Qt3DCore::QTransform *lineTransform = new Qt3DCore::QTransform;
lineTransform->setRotation( QQuaternion::fromAxisAndAngle( QVector3D( 1, 0, 0 ), -90 ) ); // flip map (x,y,z) to world (x,z,-y)
mLineEntity->addComponent( lineTransform );
// Rubberband vertex markers
mMarkerEntity = new Qt3DCore::QEntity( parentEntity );
mMarkerGeometry = new QgsBillboardGeometry();
@ -99,6 +103,10 @@ QgsRubberBand3D::QgsRubberBand3D( Qgs3DMapSettings &map, QgsWindow3DEngine *engi
mMarkerSymbol = QgsMarkerSymbol::createSimple( props );
updateMarkerMaterial();
mMarkerEntity->addComponent( mMarkerGeometryRenderer );
Qt3DCore::QTransform *markerTransform = new Qt3DCore::QTransform;
markerTransform->setRotation( QQuaternion::fromAxisAndAngle( QVector3D( 1, 0, 0 ), -90 ) ); // flip map (x,y,z) to world (x,z,-y)
mMarkerEntity->addComponent( markerTransform );
}
QgsRubberBand3D::~QgsRubberBand3D()
@ -167,7 +175,7 @@ void QgsRubberBand3D::updateGeometry()
{
QgsLineVertexData lineData;
lineData.withAdjacency = true;
lineData.init( Qgis::AltitudeClamping::Absolute, Qgis::AltitudeBinding::Vertex, 0, Qgs3DRenderContext::fromMapSettings( mMapSettings ) );
lineData.init( Qgis::AltitudeClamping::Absolute, Qgis::AltitudeBinding::Vertex, 0, Qgs3DRenderContext::fromMapSettings( mMapSettings ), mMapSettings->origin() );
lineData.addLineString( mLineString );
mPositionAttribute->buffer()->setData( lineData.createVertexBuffer() );

View File

@ -262,12 +262,12 @@ void QgsRuleBased3DRenderer::Rule::createHandlers( QgsVectorLayer *layer, QgsRul
}
void QgsRuleBased3DRenderer::Rule::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, QgsRuleBased3DRenderer::RuleToHandlerMap &handlers ) const
void QgsRuleBased3DRenderer::Rule::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin, QgsRuleBased3DRenderer::RuleToHandlerMap &handlers ) const
{
if ( mSymbol )
{
QgsFeature3DHandler *handler = handlers[this];
if ( !handler->prepare( context, attributeNames ) )
if ( !handler->prepare( context, attributeNames, chunkOrigin ) )
{
handlers.remove( this );
delete handler;
@ -283,7 +283,7 @@ void QgsRuleBased3DRenderer::Rule::prepare( const Qgs3DRenderContext &context, Q
// call recursively
for ( Rule *rule : std::as_const( mChildren ) )
{
rule->prepare( context, attributeNames, handlers );
rule->prepare( context, attributeNames, chunkOrigin, handlers );
}
}

View File

@ -242,7 +242,7 @@ class _3D_EXPORT QgsRuleBased3DRenderer : public QgsAbstractVectorLayer3DRendere
* call prepare() on handlers and populate attributeNames
* \note not available in Python bindings
*/
void prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, RuleToHandlerMap &handlers ) const SIP_SKIP;
void prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin, RuleToHandlerMap &handlers ) const SIP_SKIP;
/**
* register individual features

View File

@ -50,6 +50,12 @@ QgsRuleBasedChunkLoader::QgsRuleBasedChunkLoader( const QgsRuleBasedChunkLoaderF
QgsVectorLayer *layer = mFactory->mLayer;
// only a subset of data to be queried
const QgsRectangle rect = node->box3D().toRectangle();
// origin for coordinates of the chunk - it is kind of arbitrary, but it should be
// picked so that the coordinates are relatively small to avoid numerical precision issues
QgsVector3D chunkOrigin( rect.center().x(), rect.center().y(), 0 );
QgsExpressionContext exprContext( Qgs3DUtils::globalProjectLayerExpressionContext( layer ) );
exprContext.setFields( layer->fields() );
mContext.setExpressionContext( exprContext );
@ -63,15 +69,12 @@ QgsRuleBasedChunkLoader::QgsRuleBasedChunkLoader( const QgsRuleBasedChunkLoaderF
mRootRule->createHandlers( layer, mHandlers );
QSet<QString> attributeNames;
mRootRule->prepare( mContext, attributeNames, mHandlers );
mRootRule->prepare( mContext, attributeNames, chunkOrigin, mHandlers );
// build the feature request
QgsFeatureRequest req;
req.setDestinationCrs( mContext.crs(), mContext.transformContext() );
req.setSubsetOfAttributes( attributeNames, layer->fields() );
// only a subset of data to be queried
const QgsRectangle rect = Qgs3DUtils::worldToMapExtent( node->bbox(), mContext.origin() );
req.setFilterRect( rect );
//
@ -150,10 +153,10 @@ Qt3DCore::QEntity *QgsRuleBasedChunkLoader::createEntity( Qt3DCore::QEntity *par
// fix the vertical range of the node from the estimated vertical range to the true range
if ( zMin != std::numeric_limits<float>::max() && zMax != std::numeric_limits<float>::lowest() )
{
QgsAABB box = mNode->bbox();
box.yMin = zMin;
box.yMax = zMax;
mNode->setExactBbox( box );
QgsBox3D box = mNode->box3D();
box.setZMinimum( zMin );
box.setZMaximum( zMax );
mNode->setExactBox3D( box );
mNode->updateParentBoundingBoxesRecursively();
}
@ -170,8 +173,8 @@ QgsRuleBasedChunkLoaderFactory::QgsRuleBasedChunkLoaderFactory( const Qgs3DRende
, mRootRule( rootRule->clone() )
, mLeafLevel( leafLevel )
{
const QgsAABB rootBbox = Qgs3DUtils::mapToWorldExtent( context.extent(), zMin, zMax, context.origin() );
setupQuadtree( rootBbox, -1, leafLevel ); // negative root error means that the node does not contain anything
const QgsBox3D rootBox3D( context.extent(), zMin, zMax );
setupQuadtree( rootBox3D, -1, leafLevel ); // negative root error means that the node does not contain anything
}
QgsRuleBasedChunkLoaderFactory::~QgsRuleBasedChunkLoaderFactory() = default;
@ -266,6 +269,6 @@ void QgsRuleBasedChunkedEntity::onTerrainElevationOffsetChanged( float newOffset
QVector<QgsRayCastingUtils::RayHit> QgsRuleBasedChunkedEntity::rayIntersection( const QgsRayCastingUtils::Ray3D &ray, const QgsRayCastingUtils::RayCastContext &context ) const
{
return QgsVectorLayerChunkedEntity::rayIntersection( activeNodes(), mTransform->matrix(), ray, context );
return QgsVectorLayerChunkedEntity::rayIntersection( activeNodes(), mTransform->matrix(), ray, context, mMapSettings->origin() );
}
/// @endcond

View File

@ -82,42 +82,6 @@ QgsTessellatedPolygonGeometry::QgsTessellatedPolygonGeometry( bool _withNormals,
}
}
void QgsTessellatedPolygonGeometry::setPolygons( const QList<QgsPolygon *> &polygons, const QList<QgsFeatureId> &featureIds, const QgsPointXY &origin, float extrusionHeight, const QList<float> &extrusionHeightPerPolygon )
{
Q_ASSERT( polygons.count() == featureIds.count() );
mTriangleIndexStartingIndices.reserve( polygons.count() );
mTriangleIndexFids.reserve( polygons.count() );
QgsTessellator tessellator( origin.x(), origin.y(), mWithNormals, mInvertNormals, mAddBackFaces, false, mAddTextureCoords );
for ( int i = 0; i < polygons.count(); ++i )
{
Q_ASSERT( tessellator.dataVerticesCount() % 3 == 0 );
const uint startingTriangleIndex = static_cast<uint>( tessellator.dataVerticesCount() / 3 );
mTriangleIndexStartingIndices.append( startingTriangleIndex );
mTriangleIndexFids.append( featureIds[i] );
QgsPolygon *polygon = polygons.at( i );
const float extr = extrusionHeightPerPolygon.isEmpty() ? extrusionHeight : extrusionHeightPerPolygon.at( i );
tessellator.addPolygon( *polygon, extr );
}
if ( !tessellator.error().isEmpty() )
{
QgsMessageLog::logMessage( tessellator.error(), QObject::tr( "3D" ) );
}
qDeleteAll( polygons );
const QByteArray data( ( const char * )tessellator.data().constData(), tessellator.data().count() * sizeof( float ) );
const int nVerts = data.count() / tessellator.stride();
mVertexBuffer->setData( data );
mPositionAttribute->setCount( nVerts );
if ( mNormalAttribute )
mNormalAttribute->setCount( nVerts );
if ( mAddTextureCoords )
mTextureCoordsAttribute->setCount( nVerts );
}
void QgsTessellatedPolygonGeometry::setData( const QByteArray &vertexBufferData, int vertexCount, const QVector<QgsFeatureId> &triangleIndexFids, const QVector<uint> &triangleIndexStartingIndices )
{
mTriangleIndexStartingIndices = triangleIndexStartingIndices;

View File

@ -91,9 +91,6 @@ class QgsTessellatedPolygonGeometry : public Qt3DCore::QGeometry
*/
void setAddTextureCoords( bool add ) { mAddTextureCoords = add; }
//! Initializes vertex buffer from given polygons. Takes ownership of passed polygon geometries
void setPolygons( const QList<QgsPolygon *> &polygons, const QList<QgsFeatureId> &featureIds, const QgsPointXY &origin, float extrusionHeight, const QList<float> &extrusionHeightPerPolygon = QList<float>() );
/**
* Initializes vertex buffer (and other members) from data that were already tessellated.
* This is an alternative to setPolygons() - this method does not do any expensive work in the body.

View File

@ -16,6 +16,7 @@
#include "qgstiledscenechunkloader_p.h"
#include "qgs3dmapsettings.h"
#include "qgs3dutils.h"
#include "qgsapplication.h"
#include "qgscesiumutils.h"
#include "qgscoordinatetransform.h"
@ -168,32 +169,24 @@ QgsChunkLoader *QgsTiledSceneChunkLoaderFactory::createChunkLoader( QgsChunkNode
return new QgsTiledSceneChunkLoader( node, mIndex, *this, mZValueScale, mZValueOffset );
}
// converts box from map coordinates to world coords (also flips [X,Y] to [X,-Z])
static QgsAABB aabbConvert( const QgsBox3D &b0, const QgsVector3D &sceneOriginTargetCrs )
{
const QgsBox3D b = b0 - sceneOriginTargetCrs;
return QgsAABB( b.xMinimum(), b.zMinimum(), -b.yMaximum(), b.xMaximum(), b.zMaximum(), -b.yMinimum() );
}
QgsChunkNode *QgsTiledSceneChunkLoaderFactory::nodeForTile( const QgsTiledSceneTile &t, const QgsChunkNodeId &nodeId, QgsChunkNode *parent ) const
{
QgsChunkNode *node = nullptr;
if ( hasLargeBounds( t, mBoundsTransform ) )
{
// use the full extent of the scene
QgsVector3D v0 = mRenderContext.mapToWorldCoordinates( QgsVector3D( mRenderContext.extent().xMinimum(), mRenderContext.extent().yMinimum(), -100 ) );
QgsVector3D v1 = mRenderContext.mapToWorldCoordinates( QgsVector3D( mRenderContext.extent().xMaximum(), mRenderContext.extent().yMaximum(), +100 ) );
QgsAABB aabb( v0.x(), v0.y(), v0.z(), v1.x(), v1.y(), v1.z() );
QgsVector3D v0( mRenderContext.extent().xMinimum(), mRenderContext.extent().yMinimum(), -100 );
QgsVector3D v1( mRenderContext.extent().xMaximum(), mRenderContext.extent().yMaximum(), +100 );
QgsBox3D box3D( v0, v1 );
float err = std::min( 1e6, t.geometricError() );
node = new QgsChunkNode( nodeId, aabb, err, parent );
node = new QgsChunkNode( nodeId, box3D, err, parent );
}
else
{
QgsBox3D box = t.boundingVolume().bounds( mBoundsTransform );
box.setZMinimum( box.zMinimum() * mZValueScale + mZValueOffset );
box.setZMaximum( box.zMaximum() * mZValueScale + mZValueOffset );
const QgsAABB aabb = aabbConvert( box, mRenderContext.origin() );
node = new QgsChunkNode( nodeId, aabb, t.geometricError(), parent );
node = new QgsChunkNode( nodeId, box, t.geometricError(), parent );
}
node->setRefinementProcess( t.refinementProcess() );
@ -376,9 +369,12 @@ QVector<QgsRayCastingUtils::RayHit> QgsTiledSceneLayerChunkedEntity::rayIntersec
#ifdef QGISDEBUG
nodesAll++;
#endif
QgsAABB nodeBbox = Qgs3DUtils::mapToWorldExtent( node->box3D(), mMapSettings->origin() );
if ( node->entity() &&
( minDist < 0 || node->bbox().distanceFromPoint( ray.origin() ) < minDist ) &&
QgsRayCastingUtils::rayBoxIntersection( ray, node->bbox() ) )
( minDist < 0 || nodeBbox.distanceFromPoint( ray.origin() ) < minDist ) &&
QgsRayCastingUtils::rayBoxIntersection( ray, nodeBbox ) )
{
#ifdef QGISDEBUG
nodeUsed++;
@ -412,10 +408,10 @@ QVector<QgsRayCastingUtils::RayHit> QgsTiledSceneLayerChunkedEntity::rayIntersec
QVariantMap vm;
QgsTiledSceneTile tile = mIndex.getTile( minNode->tileId().uniqueId );
// at this point this is mostly for debugging - we may want to change/rename what's returned here
vm["node_id"] = tile.id();
vm["node_error"] = tile.geometricError();
vm["node_content"] = tile.resources().value( QStringLiteral( "content" ) );
vm["triangle_index"] = minTriangleIndex;
vm[ QStringLiteral( "node_id" ) ] = tile.id();
vm[ QStringLiteral( "node_error" ) ] = tile.geometricError();
vm[ QStringLiteral( "node_content" ) ] = tile.resources().value( QStringLiteral( "content" ) );
vm[ QStringLiteral( "triangle_index" ) ] = minTriangleIndex;
QgsRayCastingUtils::RayHit hit( minDist, intersectionPoint, FID_NULL, vm );
result.append( hit );
}

View File

@ -59,12 +59,18 @@ QgsVectorLayerChunkLoader::QgsVectorLayerChunkLoader( const QgsVectorLayerChunkL
}
mHandler.reset( handler );
// only a subset of data to be queried
const QgsRectangle rect = node->box3D().toRectangle();
// origin for coordinates of the chunk - it is kind of arbitrary, but it should be
// picked so that the coordinates are relatively small to avoid numerical precision issues
QgsVector3D chunkOrigin( rect.center().x(), rect.center().y(), 0 );
QgsExpressionContext exprContext( Qgs3DUtils::globalProjectLayerExpressionContext( layer ) );
exprContext.setFields( layer->fields() );
mRenderContext.setExpressionContext( exprContext );
QSet<QString> attributeNames;
if ( !mHandler->prepare( mRenderContext, attributeNames ) )
if ( !mHandler->prepare( mRenderContext, attributeNames, chunkOrigin ) )
{
QgsDebugError( QStringLiteral( "Failed to prepare 3D feature handler!" ) );
return;
@ -76,9 +82,6 @@ QgsVectorLayerChunkLoader::QgsVectorLayerChunkLoader( const QgsVectorLayerChunkL
QgsCoordinateTransform( layer->crs3D(), mRenderContext.crs(), mRenderContext.transformContext() )
);
req.setSubsetOfAttributes( attributeNames, layer->fields() );
// only a subset of data to be queried
const QgsRectangle rect = Qgs3DUtils::worldToMapExtent( node->bbox(), mRenderContext.origin() );
req.setFilterRect( rect );
//
@ -133,7 +136,7 @@ Qt3DCore::QEntity *QgsVectorLayerChunkLoader::createEntity( Qt3DCore::QEntity *p
{
// an empty node, so we return no entity. This tags the node as having no data and effectively removes it.
// we just make sure first that its initial estimated vertical range does not affect its parents' bboxes calculation
mNode->setExactBbox( QgsAABB() );
mNode->setExactBox3D( QgsBox3D() );
mNode->updateParentBoundingBoxesRecursively();
return nullptr;
}
@ -145,10 +148,10 @@ Qt3DCore::QEntity *QgsVectorLayerChunkLoader::createEntity( Qt3DCore::QEntity *p
// fix the vertical range of the node from the estimated vertical range to the true range
if ( mHandler->zMinimum() != std::numeric_limits<float>::max() && mHandler->zMaximum() != std::numeric_limits<float>::lowest() )
{
QgsAABB box = mNode->bbox();
box.yMin = mHandler->zMinimum();
box.yMax = mHandler->zMaximum();
mNode->setExactBbox( box );
QgsBox3D box = mNode->box3D();
box.setZMinimum( mHandler->zMinimum() );
box.setZMaximum( mHandler->zMaximum() );
mNode->setExactBox3D( box );
mNode->updateParentBoundingBoxesRecursively();
}
@ -165,15 +168,10 @@ QgsVectorLayerChunkLoaderFactory::QgsVectorLayerChunkLoaderFactory( const Qgs3DR
, mSymbol( symbol->clone() )
, mLeafLevel( leafLevel )
{
QgsAABB rootBbox = Qgs3DUtils::mapToWorldExtent( context.extent(), zMin, zMax, context.origin() );
QgsBox3D rootBox3D( context.extent(), zMin, zMax );
// add small padding to avoid clipping of point features located at the edge of the bounding box
rootBbox.xMin -= 1.0;
rootBbox.xMax += 1.0;
rootBbox.yMin -= 1.0;
rootBbox.yMax += 1.0;
rootBbox.zMin -= 1.0;
rootBbox.zMax += 1.0;
setupQuadtree( rootBbox, -1, leafLevel ); // negative root error means that the node does not contain anything
rootBox3D.grow( 1.0 );
setupQuadtree( rootBox3D, -1, leafLevel ); // negative root error means that the node does not contain anything
}
QgsChunkLoader *QgsVectorLayerChunkLoaderFactory::createChunkLoader( QgsChunkNode *node ) const
@ -260,10 +258,10 @@ void QgsVectorLayerChunkedEntity::onTerrainElevationOffsetChanged( float newOffs
QVector<QgsRayCastingUtils::RayHit> QgsVectorLayerChunkedEntity::rayIntersection( const QgsRayCastingUtils::Ray3D &ray, const QgsRayCastingUtils::RayCastContext &context ) const
{
return QgsVectorLayerChunkedEntity::rayIntersection( activeNodes(), mTransform->matrix(), ray, context );
return QgsVectorLayerChunkedEntity::rayIntersection( activeNodes(), mTransform->matrix(), ray, context, mMapSettings->origin() );
}
QVector<QgsRayCastingUtils::RayHit> QgsVectorLayerChunkedEntity::rayIntersection( const QList<QgsChunkNode *> &activeNodes, const QMatrix4x4 &transformMatrix, const QgsRayCastingUtils::Ray3D &ray, const QgsRayCastingUtils::RayCastContext &context )
QVector<QgsRayCastingUtils::RayHit> QgsVectorLayerChunkedEntity::rayIntersection( const QList<QgsChunkNode *> &activeNodes, const QMatrix4x4 &transformMatrix, const QgsRayCastingUtils::Ray3D &ray, const QgsRayCastingUtils::RayCastContext &context, const QgsVector3D &origin )
{
Q_UNUSED( context )
QgsDebugMsgLevel( QStringLiteral( "Ray cast on vector layer" ), 2 );
@ -284,9 +282,12 @@ QVector<QgsRayCastingUtils::RayHit> QgsVectorLayerChunkedEntity::rayIntersection
#ifdef QGISDEBUG
nodesAll++;
#endif
QgsAABB nodeBbox = Qgs3DUtils::mapToWorldExtent( node->box3D(), origin );
if ( node->entity() &&
( minDist < 0 || node->bbox().distanceFromPoint( ray.origin() ) < minDist ) &&
QgsRayCastingUtils::rayBoxIntersection( ray, node->bbox() ) )
( minDist < 0 || nodeBbox.distanceFromPoint( ray.origin() ) < minDist ) &&
QgsRayCastingUtils::rayBoxIntersection( ray, nodeBbox ) )
{
#ifdef QGISDEBUG
nodeUsed++;

View File

@ -129,7 +129,7 @@ class QgsVectorLayerChunkedEntity : public QgsChunkedEntity
private:
friend class QgsRuleBasedChunkedEntity;
//! This implementation is shared between QgsVectorLayerChunkedEntity and QgsRuleBasedChunkedEntity
static QVector<QgsRayCastingUtils::RayHit> rayIntersection( const QList<QgsChunkNode *> &activeNodes, const QMatrix4x4 &transformMatrix, const QgsRayCastingUtils::Ray3D &ray, const QgsRayCastingUtils::RayCastContext &context );
static QVector<QgsRayCastingUtils::RayHit> rayIntersection( const QList<QgsChunkNode *> &activeNodes, const QMatrix4x4 &transformMatrix, const QgsRayCastingUtils::Ray3D &ray, const QgsRayCastingUtils::RayCastContext &context, const QgsVector3D &origin );
Qt3DCore::QTransform *mTransform = nullptr;

View File

@ -7,9 +7,9 @@ in vec3 pos;
out vec3 worldPosition;
out vec3 worldNormal;
uniform mat4 modelView;
uniform mat3 modelViewNormal;
uniform mat4 modelViewProjection;
uniform mat4 modelMatrix;
uniform mat3 modelNormalMatrix;
uniform mat4 mvp;
uniform mat4 inst; // transform of individual object instance
uniform mat4 instNormal; // should be mat3 but Qt3D only supports mat4...
@ -20,15 +20,26 @@ uniform mat4 instNormal; // should be mat3 but Qt3D only supports mat4...
void main()
{
// TODO: i think this is not entirely correct: the translation by "pos" works
// like this only because we assume that "inst" matrix only does translation/scale/rotation
// which all keep "w" set to 1. correctly we should use translation matrix...
vec4 offsetPos = inst * vec4(vertexPosition, 1.0) + vec4(pos, 0.0);
// vertexPosition uses XZ plane as the base plane, with Y going upwards
// and the coordinates are local to the object
worldNormal = normalize(mat3(instNormal) * vertexNormal);
worldPosition = vec3(offsetPos);
// first let's apply user defined transform for each object (translation, rotation, scaling)
vec3 vertexPositionObject = vec3(inst * vec4(vertexPosition, 1.0));
vec3 vertexNormalObject = mat3(instNormal) * vertexNormal;
gl_Position = modelViewProjection * offsetPos;
// next let's flip axes, so we have XY plane as the base plane (like in map coordinates)
vertexPositionObject = vec3(vertexPositionObject.x, -vertexPositionObject.z, vertexPositionObject.y);
vertexNormalObject = vec3(vertexNormalObject.x, -vertexNormalObject.z, vertexNormalObject.y);
// add offset of the object relative to the chunk's origin
vec3 vertexPositionChunk = vertexPositionObject + pos;
// Transform position and normal to world space
worldPosition = vec3(modelMatrix * vec4(vertexPositionChunk, 1.0));
worldNormal = normalize(modelNormalMatrix * vertexNormalObject);
// Calculate vertex position in clip coordinates
gl_Position = mvp * vec4(vertexPositionChunk, 1.0);
#ifdef CLIPPING
setClipDistance(worldPosition);

View File

@ -33,6 +33,7 @@
#include "qgsphongtexturedmaterialsettings.h"
#include "qgsmessagelog.h"
#include <Qt3DCore/QTransform>
#include <Qt3DExtras/QPhongMaterial>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <Qt3DRender/QAttribute>
@ -63,7 +64,7 @@ class QgsBufferedLine3DSymbolHandler : public QgsFeature3DHandler
: mSymbol( static_cast< QgsLine3DSymbol *>( symbol->clone() ) )
, mSelectedIds( selectedIds ) {}
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin ) override;
void processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context ) override;
void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
@ -86,6 +87,9 @@ class QgsBufferedLine3DSymbolHandler : public QgsFeature3DHandler
// inputs - generic
QgsFeatureIds mSelectedIds;
//! origin (in the map coordinates) for output geometries (e.g. at the center of the chunk)
QgsVector3D mChunkOrigin;
// outputs
LineData outNormal; //!< Features that are not selected
LineData outSelected; //!< Features that are selected
@ -93,17 +97,19 @@ class QgsBufferedLine3DSymbolHandler : public QgsFeature3DHandler
bool QgsBufferedLine3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
bool QgsBufferedLine3DSymbolHandler::prepare( const Qgs3DRenderContext &, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin )
{
Q_UNUSED( attributeNames )
mChunkOrigin = chunkOrigin;
const QgsPhongTexturedMaterialSettings *texturedMaterialSettings = dynamic_cast< const QgsPhongTexturedMaterialSettings * >( mSymbol->materialSettings() );
outNormal.tessellator.reset( new QgsTessellator( context.origin().x(), context.origin().y(), true,
outNormal.tessellator.reset( new QgsTessellator( chunkOrigin.x(), chunkOrigin.y(), true,
false, false, false, texturedMaterialSettings ? texturedMaterialSettings->requiresTextureCoordinates() : false,
3,
texturedMaterialSettings ? texturedMaterialSettings->textureRotation() : 0 ) );
outSelected.tessellator.reset( new QgsTessellator( context.origin().x(), context.origin().y(), true,
outSelected.tessellator.reset( new QgsTessellator( chunkOrigin.x(), chunkOrigin.y(), true,
false, false, false, texturedMaterialSettings ? texturedMaterialSettings->requiresTextureCoordinates() : false,
3,
texturedMaterialSettings ? texturedMaterialSettings->textureRotation() : 0 ) );
@ -217,10 +223,16 @@ void QgsBufferedLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, cons
Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
renderer->setGeometry( geometry );
// add transform (our geometry has coordinates relative to mChunkOrigin)
Qt3DCore::QTransform *tr = new Qt3DCore::QTransform;
QVector3D nodeTranslation = ( mChunkOrigin - context.origin() ).toVector3D();
tr->setTranslation( QVector3D( nodeTranslation.x(), nodeTranslation.z(), -nodeTranslation.y() ) );
// make entity
Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
entity->addComponent( renderer );
entity->addComponent( mat );
entity->addComponent( tr );
entity->setParent( parent );
if ( !selected )
@ -243,7 +255,7 @@ class QgsThickLine3DSymbolHandler : public QgsFeature3DHandler
{
}
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin ) override;
void processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context ) override;
void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
@ -259,6 +271,9 @@ class QgsThickLine3DSymbolHandler : public QgsFeature3DHandler
// inputs - generic
QgsFeatureIds mSelectedIds;
//! origin (in the map coordinates) for output geometries (e.g. at the center of the chunk)
QgsVector3D mChunkOrigin;
// outputs
QgsLineVertexData outNormal; //!< Features that are not selected
QgsLineVertexData outSelected; //!< Features that are selected
@ -266,14 +281,16 @@ class QgsThickLine3DSymbolHandler : public QgsFeature3DHandler
bool QgsThickLine3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
bool QgsThickLine3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin )
{
Q_UNUSED( attributeNames )
mChunkOrigin = chunkOrigin;
outNormal.withAdjacency = true;
outSelected.withAdjacency = true;
outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context );
outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context );
outNormal.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context, chunkOrigin );
outSelected.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), mSymbol->offset(), context, chunkOrigin );
QSet<QString> attrs = mSymbol->dataDefinedProperties().referencedFields( context.expressionContext() );
attributeNames.unite( attrs );
@ -374,9 +391,16 @@ void QgsThickLine3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Q
renderer->setPrimitiveRestartEnabled( true );
renderer->setRestartIndexValue( 0 );
// add transform (our geometry has coordinates relative to mChunkOrigin)
Qt3DCore::QTransform *tr = new Qt3DCore::QTransform;
tr->setRotation( QQuaternion::fromAxisAndAngle( QVector3D( 1, 0, 0 ), -90 ) ); // flip map (x,y,z) to world (x,z,-y)
QVector3D nodeTranslation = ( mChunkOrigin - context.origin() ).toVector3D();
tr->setTranslation( QVector3D( nodeTranslation.x(), nodeTranslation.z(), -nodeTranslation.y() ) );
// make entity
entity->addComponent( renderer );
entity->addComponent( mat );
entity->addComponent( tr );
entity->setParent( parent );
}

View File

@ -46,12 +46,13 @@ QgsLineVertexData::QgsLineVertexData()
vertices << QVector3D();
}
void QgsLineVertexData::init( Qgis::AltitudeClamping clamping, Qgis::AltitudeBinding binding, float height, const Qgs3DRenderContext &context )
void QgsLineVertexData::init( Qgis::AltitudeClamping clamping, Qgis::AltitudeBinding binding, float height, const Qgs3DRenderContext &context, const QgsVector3D &chunkOrigin )
{
altClamping = clamping;
altBinding = binding;
baseHeight = height;
renderContext = context;
origin = chunkOrigin;
}
QByteArray QgsLineVertexData::createVertexBuffer()
@ -135,9 +136,9 @@ void QgsLineVertexData::addLineString( const QgsLineString &lineString, float ex
QgsPoint p = lineString.pointN( i );
float z = Qgs3DUtils::clampAltitude( p, altClamping, altBinding, baseHeight + extraHeightOffset, centroid, renderContext );
vertices << QVector3D( static_cast< float >( p.x() - renderContext.origin().x() ),
z,
static_cast< float >( -( p.y() - renderContext.origin().y() ) ) );
vertices << QVector3D( static_cast< float >( p.x() - origin.x() ),
static_cast< float >( p.y() - origin.y() ),
z );
indexes << vertices.count() - 1;
}
@ -168,13 +169,13 @@ void QgsLineVertexData::addVerticalLines( const QgsLineString &lineString, float
if ( withAdjacency )
indexes << vertices.count(); // add the following vertex (for adjacency)
vertices << QVector3D( static_cast< float >( p.x() - renderContext.origin().x() ),
z,
static_cast< float >( -( p.y() - renderContext.origin().y() ) ) );
vertices << QVector3D( static_cast< float >( p.x() - origin.x() ),
static_cast< float >( p.y() - origin.y() ),
z );
indexes << vertices.count() - 1;
vertices << QVector3D( static_cast< float >( p.x() - renderContext.origin().x() ),
z2,
static_cast< float >( -( p.y() - renderContext.origin().y() ) ) );
vertices << QVector3D( static_cast< float >( p.x() - origin.x() ),
static_cast< float >( p.y() - origin.y() ),
z2 );
indexes << vertices.count() - 1;
if ( withAdjacency )

View File

@ -80,11 +80,12 @@ struct QgsLineVertexData
Qgis::AltitudeClamping altClamping = Qgis::AltitudeClamping::Relative;
Qgis::AltitudeBinding altBinding = Qgis::AltitudeBinding::Vertex;
float baseHeight = 0;
Qgs3DRenderContext renderContext;
Qgs3DRenderContext renderContext; // used for altitude clamping
QgsVector3D origin; // all coordinates are relative to this origin (e.g. center of the chunk)
QgsLineVertexData();
void init( Qgis::AltitudeClamping clamping, Qgis::AltitudeBinding binding, float height, const Qgs3DRenderContext &renderContext );
void init( Qgis::AltitudeClamping clamping, Qgis::AltitudeBinding binding, float height, const Qgs3DRenderContext &renderContext, const QgsVector3D &chunkOrigin );
QByteArray createVertexBuffer();
QByteArray createIndexBuffer();

View File

@ -272,12 +272,9 @@ QVariant QgsPoint3DSymbol::shapeProperty( const QString &property ) const
return mShapeProperties.value( property );
}
QMatrix4x4 QgsPoint3DSymbol::billboardTransform() const
float QgsPoint3DSymbol::billboardHeight() const
{
QMatrix4x4 billboardTransformMatrix;
billboardTransformMatrix.translate( QVector3D( 0, mTransform.data()[13], 0 ) );
return billboardTransformMatrix;
return mTransform.data()[13];
}
QgsAbstractMaterialSettings *QgsPoint3DSymbol::materialSettings() const

View File

@ -164,8 +164,8 @@ class _3D_EXPORT QgsPoint3DSymbol : public QgsAbstract3DSymbol SIP_NODEFAULTCTOR
//! Sets transform for individual objects represented by the symbol
void setTransform( const QMatrix4x4 &transform ) { mTransform = transform; }
//! Returns transform for billboards
QMatrix4x4 billboardTransform() const;
//! Returns how much the billboard should be elevated upwards
float billboardHeight() const;
/**
* Exports the geometries contained within the hierarchy of entity.

View File

@ -77,7 +77,7 @@ class QgsInstancedPoint3DSymbolHandler : public QgsFeature3DHandler
: mSymbol( static_cast< QgsPoint3DSymbol *>( symbol->clone() ) )
, mSelectedIds( selectedIds ) {}
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin ) override;
void processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context ) override;
void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
@ -100,16 +100,22 @@ class QgsInstancedPoint3DSymbolHandler : public QgsFeature3DHandler
// inputs - generic
QgsFeatureIds mSelectedIds;
//! origin (in the map coordinates) for output geometries (e.g. at the center of the chunk)
QgsVector3D mChunkOrigin;
// outputs
PointData outNormal; //!< Features that are not selected
PointData outSelected; //!< Features that are selected
};
bool QgsInstancedPoint3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
bool QgsInstancedPoint3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin )
{
Q_UNUSED( context )
Q_UNUSED( attributeNames )
mChunkOrigin = chunkOrigin;
return true;
}
@ -120,7 +126,7 @@ void QgsInstancedPoint3DSymbolHandler::processFeature( const QgsFeature &feature
if ( feature.geometry().isNull() )
return;
Qgs3DUtils::extractPointPositions( feature, context, mSymbol->altitudeClamping(), out.positions );
Qgs3DUtils::extractPointPositions( feature, context, mChunkOrigin, mSymbol->altitudeClamping(), out.positions );
mFeatureCount++;
}
@ -207,10 +213,17 @@ void QgsInstancedPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, co
materialContext.setSelectionColor( context.selectionColor() );
QgsMaterial *mat = material( mSymbol.get(), materialContext );
// add transform (our geometry has coordinates relative to mChunkOrigin)
Qt3DCore::QTransform *tr = new Qt3DCore::QTransform;
tr->setRotation( QQuaternion::fromAxisAndAngle( QVector3D( 1, 0, 0 ), -90 ) ); // flip map (x,y,z) to world (x,z,-y)
QVector3D nodeTranslation = ( mChunkOrigin - context.origin() ).toVector3D();
tr->setTranslation( QVector3D( nodeTranslation.x(), nodeTranslation.z(), -nodeTranslation.y() ) );
// build the entity
Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
entity->addComponent( renderer( mSymbol.get(), out.positions ) );
entity->addComponent( mat );
entity->addComponent( tr );
entity->setParent( parent );
// cppcheck wrongly believes entity will leak
@ -401,15 +414,15 @@ class QgsModelPoint3DSymbolHandler : public QgsFeature3DHandler
: mSymbol( static_cast< QgsPoint3DSymbol * >( symbol->clone() ) )
, mSelectedIds( selectedIds ) {}
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin ) override;
void processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context ) override;
void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
private:
static void addSceneEntities( const Qgs3DRenderContext &context, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent );
static void addMeshEntities( const Qgs3DRenderContext &context, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, bool are_selected );
static Qt3DCore::QTransform *transform( QVector3D position, const QgsPoint3DSymbol *symbol );
static void addSceneEntities( const Qgs3DRenderContext &context, const QVector<QVector3D> &positions, const QgsVector3D &chunkOrigin, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent );
static void addMeshEntities( const Qgs3DRenderContext &context, const QVector<QVector3D> &positions, const QgsVector3D &chunkOrigin, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, bool are_selected );
static Qt3DCore::QTransform *transform( QVector3D position, const QgsPoint3DSymbol *symbol, const QgsVector3D &chunkOrigin, const QgsVector3D &contextOrigin );
//! temporary data we will pass to the tessellator
struct PointData
@ -424,15 +437,21 @@ class QgsModelPoint3DSymbolHandler : public QgsFeature3DHandler
// inputs - generic
QgsFeatureIds mSelectedIds;
//! origin (in the map coordinates) for output geometries (e.g. at the center of the chunk)
QgsVector3D mChunkOrigin;
// outputs
PointData outNormal; //!< Features that are not selected
PointData outSelected; //!< Features that are selected
};
bool QgsModelPoint3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
bool QgsModelPoint3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin )
{
Q_UNUSED( context )
Q_UNUSED( attributeNames )
mChunkOrigin = chunkOrigin;
return true;
}
@ -443,7 +462,7 @@ void QgsModelPoint3DSymbolHandler::processFeature( const QgsFeature &feature, co
if ( feature.geometry().isNull() )
return;
Qgs3DUtils::extractPointPositions( feature, context, mSymbol->altitudeClamping(), out.positions );
Qgs3DUtils::extractPointPositions( feature, context, mChunkOrigin, mSymbol->altitudeClamping(), out.positions );
mFeatureCount++;
}
@ -465,7 +484,7 @@ void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const
{
if ( selected )
{
addMeshEntities( context, out.positions, mSymbol.get(), parent, true );
addMeshEntities( context, out.positions, mChunkOrigin, mSymbol.get(), parent, true );
}
else
{
@ -473,18 +492,18 @@ void QgsModelPoint3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const
if ( mSymbol->shapeProperty( QStringLiteral( "overwriteMaterial" ) ).toBool()
|| ( mSymbol->materialSettings() && mSymbol->materialSettings()->type() != QLatin1String( "null" ) ) )
{
addMeshEntities( context, out.positions, mSymbol.get(), parent, false );
addMeshEntities( context, out.positions, mChunkOrigin, mSymbol.get(), parent, false );
}
else
{
addSceneEntities( context, out.positions, mSymbol.get(), parent );
addSceneEntities( context, out.positions, mChunkOrigin, mSymbol.get(), parent );
}
}
}
void QgsModelPoint3DSymbolHandler::addSceneEntities( const Qgs3DRenderContext &, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
void QgsModelPoint3DSymbolHandler::addSceneEntities( const Qgs3DRenderContext &context, const QVector<QVector3D> &positions, const QgsVector3D &chunkOrigin, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent )
{
for ( const QVector3D &position : positions )
{
@ -500,7 +519,7 @@ void QgsModelPoint3DSymbolHandler::addSceneEntities( const Qgs3DRenderContext &,
modelLoader->setSource( url );
entity->addComponent( modelLoader );
entity->addComponent( transform( position, symbol ) );
entity->addComponent( transform( position, symbol, chunkOrigin, context.origin() ) );
entity->setParent( parent );
// cppcheck wrongly believes entity will leak
@ -509,7 +528,7 @@ void QgsModelPoint3DSymbolHandler::addSceneEntities( const Qgs3DRenderContext &,
}
}
void QgsModelPoint3DSymbolHandler::addMeshEntities( const Qgs3DRenderContext &context, const QVector<QVector3D> &positions, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, bool are_selected )
void QgsModelPoint3DSymbolHandler::addMeshEntities( const Qgs3DRenderContext &context, const QVector<QVector3D> &positions, const QgsVector3D &chunkOrigin, const QgsPoint3DSymbol *symbol, Qt3DCore::QEntity *parent, bool are_selected )
{
if ( positions.empty() )
return;
@ -535,7 +554,7 @@ void QgsModelPoint3DSymbolHandler::addMeshEntities( const Qgs3DRenderContext &co
entity->addComponent( mesh );
entity->addComponent( mat );
entity->addComponent( transform( position, symbol ) );
entity->addComponent( transform( position, symbol, chunkOrigin, context.origin() ) );
entity->setParent( parent );
// cppcheck wrongly believes entity will leak
@ -544,11 +563,15 @@ void QgsModelPoint3DSymbolHandler::addMeshEntities( const Qgs3DRenderContext &co
}
}
Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position, const QgsPoint3DSymbol *symbol )
Qt3DCore::QTransform *QgsModelPoint3DSymbolHandler::transform( QVector3D position, const QgsPoint3DSymbol *symbol, const QgsVector3D &chunkOrigin, const QgsVector3D &contextOrigin )
{
Qt3DCore::QTransform *tr = new Qt3DCore::QTransform;
tr->setMatrix( symbol->transform() );
tr->setTranslation( position + tr->translation() );
// position is relative to chunkOrigin
QVector3D nodeTranslation = ( chunkOrigin - contextOrigin ).toVector3D();
tr->setTranslation( tr->translation() +
QVector3D( position.x(), position.z(), -position.y() ) +
QVector3D( nodeTranslation.x(), nodeTranslation.z(), -nodeTranslation.y() ) );
return tr;
}
@ -563,7 +586,7 @@ class QgsPoint3DBillboardSymbolHandler : public QgsFeature3DHandler
: mSymbol( static_cast< QgsPoint3DSymbol * >( symbol->clone() ) )
, mSelectedIds( selectedIds ) {}
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin ) override;
void processFeature( const QgsFeature &feature, const Qgs3DRenderContext &context ) override;
void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
@ -582,15 +605,21 @@ class QgsPoint3DBillboardSymbolHandler : public QgsFeature3DHandler
// inputs - generic
QgsFeatureIds mSelectedIds;
//! origin (in the map coordinates) for output geometries (e.g. at the center of the chunk)
QgsVector3D mChunkOrigin;
// outputs
PointData outNormal; //!< Features that are not selected
PointData outSelected; //!< Features that are selected
};
bool QgsPoint3DBillboardSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
bool QgsPoint3DBillboardSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin )
{
Q_UNUSED( context )
Q_UNUSED( attributeNames )
mChunkOrigin = chunkOrigin;
return true;
}
@ -601,7 +630,7 @@ void QgsPoint3DBillboardSymbolHandler::processFeature( const QgsFeature &feature
if ( feature.geometry().isNull() )
return;
Qgs3DUtils::extractPointPositions( feature, context, mSymbol->altitudeClamping(), out.positions );
Qgs3DUtils::extractPointPositions( feature, context, mChunkOrigin, mSymbol->altitudeClamping(), out.positions );
mFeatureCount++;
}
@ -646,7 +675,11 @@ void QgsPoint3DBillboardSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, co
// Billboard Transform
Qt3DCore::QTransform *billboardTransform = new Qt3DCore::QTransform();
billboardTransform->setMatrix( mSymbol->billboardTransform() );
billboardTransform->setRotation( QQuaternion::fromAxisAndAngle( QVector3D( 1, 0, 0 ), -90 ) ); // flip map (x,y,z) to world (x,z,-y)
QVector3D billboardHeightTranslation( 0, mSymbol->billboardHeight(), 0 );
// our geometry has coordinates relative to mChunkOrigin
QVector3D nodeTranslation = ( mChunkOrigin - context.origin() ).toVector3D();
billboardTransform->setTranslation( billboardHeightTranslation + QVector3D( nodeTranslation.x(), nodeTranslation.z(), -nodeTranslation.y() ) );
// Build the entity
Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;

View File

@ -359,7 +359,7 @@ void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const
}
std::vector<double> QgsPointCloud3DSymbolHandler::getVertices( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsAABB &bbox )
std::vector<double> QgsPointCloud3DSymbolHandler::getVertices( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsBox3D &box3D )
{
bool hasColorData = !outNormal.colors.empty();
@ -382,11 +382,10 @@ std::vector<double> QgsPointCloud3DSymbolHandler::getVertices( QgsPointCloudInde
//factor to take account of the density of the point to calculate extension of the bounding box
// with a usual value span = 128, bounding box is extended by 12.5 % on each side.
double extraBoxFactor = 16 / span;
double extraX = extraBoxFactor * bbox.xExtent();
double extraY = extraBoxFactor * bbox.yExtent();
// We keep all points in vertical direction to avoid odd triangulation if points are isolated on top
const QgsAABB extendedBBox( bbox.xMin - extraX, bbox.yMin - extraY, -std::numeric_limits<float>::max(), bbox.xMax + extraX, bbox.yMax + extraY, std::numeric_limits<float>::max() );
QgsRectangle rectRelativeToChunkOrigin = ( box3D - outNormal.positionsOrigin ).toRectangle();
rectRelativeToChunkOrigin.grow( extraBoxFactor * std::max( box3D.width(), box3D.height() ) );
PointData filteredExtraPointData;
while ( parentNode.d() >= 0 )
@ -400,7 +399,7 @@ std::vector<double> QgsPointCloud3DSymbolHandler::getVertices( QgsPointCloudInde
for ( int i = 0; i < outputParent.positions.count(); ++i )
{
const QVector3D pos = outputParent.positions.at( i ) + originDifference;
if ( extendedBBox.intersects( pos.x(), pos.y(), pos.z() ) )
if ( rectRelativeToChunkOrigin.contains( pos.x(), pos.y() ) )
{
filteredExtraPointData.positions.append( pos );
vertices.push_back( pos.x() );
@ -458,7 +457,7 @@ void QgsPointCloud3DSymbolHandler::calculateNormals( const std::vector<size_t> &
}
}
void QgsPointCloud3DSymbolHandler::filterTriangles( const std::vector<size_t> &triangleIndexes, const QgsPointCloud3DRenderContext &context, const QgsAABB &bbox )
void QgsPointCloud3DSymbolHandler::filterTriangles( const std::vector<size_t> &triangleIndexes, const QgsPointCloud3DRenderContext &context, const QgsBox3D &box3D )
{
outNormal.triangles.resize( triangleIndexes.size() * sizeof( quint32 ) );
quint32 *indexPtr = reinterpret_cast<quint32 *>( outNormal.triangles.data() );
@ -469,6 +468,8 @@ void QgsPointCloud3DSymbolHandler::filterTriangles( const std::vector<size_t> &t
float horizontalThreshold = context.symbol()->horizontalFilterThreshold();
float verticalThreshold = context.symbol()->verticalFilterThreshold();
QgsBox3D boxRelativeToChunkOrigin = box3D - outNormal.positionsOrigin;
for ( size_t i = 0; i < triangleIndexes.size(); i += 3 )
{
bool atLeastOneInBox = false;
@ -477,7 +478,7 @@ void QgsPointCloud3DSymbolHandler::filterTriangles( const std::vector<size_t> &t
for ( size_t j = 0; j < 3; j++ )
{
QVector3D pos = outNormal.positions.at( triangleIndexes.at( i + j ) );
atLeastOneInBox |= bbox.intersects( pos.x(), pos.y(), pos.z() );
atLeastOneInBox |= boxRelativeToChunkOrigin.contains( pos.x(), pos.y(), pos.z() );
if ( verticalFilter || horizontalFilter )
{
@ -519,30 +520,16 @@ void QgsPointCloud3DSymbolHandler::filterTriangles( const std::vector<size_t> &t
}
}
void QgsPointCloud3DSymbolHandler::triangulate( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsAABB &bbox )
void QgsPointCloud3DSymbolHandler::triangulate( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsBox3D &box3D )
{
if ( outNormal.positions.isEmpty() )
return;
// The bbox we get is in world coordinates, we need to transform it to map coordinates
// (flip axes and add scene origin vector), but relative to the chunk's origin (subtract it)
// because that's the coordinate system used within the chunk
QgsBox3D boxRelativeToChunkOrigin(
bbox.xMin + context.origin().x() - outNormal.positionsOrigin.x(),
-bbox.zMax + context.origin().y() - outNormal.positionsOrigin.y(),
bbox.yMin + context.origin().z() - outNormal.positionsOrigin.z(),
bbox.xMax + context.origin().x() - outNormal.positionsOrigin.x(),
-bbox.zMin + context.origin().y() - outNormal.positionsOrigin.y(),
bbox.yMax + context.origin().z() - outNormal.positionsOrigin.z() );
QgsAABB aabbRelativeToChunkOrigin(
boxRelativeToChunkOrigin.xMinimum(), boxRelativeToChunkOrigin.yMinimum(), boxRelativeToChunkOrigin.zMinimum(),
boxRelativeToChunkOrigin.xMaximum(), boxRelativeToChunkOrigin.yMaximum(), boxRelativeToChunkOrigin.zMaximum() );
// Triangulation happens here
std::unique_ptr<delaunator::Delaunator> triangulation;
try
{
std::vector<double> vertices = getVertices( pc, n, context, aabbRelativeToChunkOrigin );
std::vector<double> vertices = getVertices( pc, n, context, box3D );
triangulation.reset( new delaunator::Delaunator( vertices ) );
}
catch ( std::exception &e )
@ -557,7 +544,7 @@ void QgsPointCloud3DSymbolHandler::triangulate( QgsPointCloudIndex *pc, const In
const std::vector<size_t> &triangleIndexes = triangulation->triangles;
calculateNormals( triangleIndexes );
filterTriangles( triangleIndexes, context, aabbRelativeToChunkOrigin );
filterTriangles( triangleIndexes, context, box3D );
}
std::unique_ptr<QgsPointCloudBlock> QgsPointCloud3DSymbolHandler::pointCloudBlock( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloudRequest &request, const QgsPointCloud3DRenderContext &context )

View File

@ -48,7 +48,7 @@ class QgsPointCloud3DSymbolHandler
virtual void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, PointData *output = nullptr ) = 0; // override;
virtual void finalize( Qt3DCore::QEntity *parent, const QgsPointCloud3DRenderContext &context ) = 0;// override;
void triangulate( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsAABB &bbox );
void triangulate( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsBox3D &box3D );
float zMinimum() const { return mZMin; }
float zMaximum() const { return mZMax; }
@ -83,7 +83,7 @@ class QgsPointCloud3DSymbolHandler
private:
//! Returns all vertices of the node \a n, and of its parents contained in \a bbox and in an extension of this box depending of the density of the points
std::vector<double> getVertices( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsAABB &bbox );
std::vector<double> getVertices( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsBox3D &box3D );
//! Calculates the normals of triangles dedined by index contained in \a triangles. Must be used only in the method triangulate().
void calculateNormals( const std::vector<size_t> &triangles );
@ -91,12 +91,12 @@ class QgsPointCloud3DSymbolHandler
/**
* Applies a filter on triangles to improve the rendering:
*
* - keeps only triangles that have a least one point in the bounding box \a bbox
* - keeps only triangles that have a least one point in the bounding box \a box3D
* - if options are selected, skips triangles with horizontal or vertical size greater than a threshold
*
* Must be used only in the method triangulate().
*/
void filterTriangles( const std::vector<size_t> &triangleIndexes, const QgsPointCloud3DRenderContext &context, const QgsAABB &bbox );
void filterTriangles( const std::vector<size_t> &triangleIndexes, const QgsPointCloud3DRenderContext &context, const QgsBox3D &box3D );
};
class QgsSingleColorPointCloud3DSymbolHandler : public QgsPointCloud3DSymbolHandler

View File

@ -54,7 +54,7 @@ class QgsPolygon3DSymbolHandler : public QgsFeature3DHandler
: mSymbol( static_cast< QgsPolygon3DSymbol *>( symbol->clone() ) )
, mSelectedIds( selectedIds ) {}
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames ) override;
bool prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin ) override;
void processFeature( const QgsFeature &f, const Qgs3DRenderContext &context ) override;
void finalize( Qt3DCore::QEntity *parent, const Qgs3DRenderContext &context ) override;
@ -79,6 +79,9 @@ class QgsPolygon3DSymbolHandler : public QgsFeature3DHandler
// inputs - generic
QgsFeatureIds mSelectedIds;
//! origin (in the map coordinates) for output geometries (e.g. at the center of the chunk)
QgsVector3D mChunkOrigin;
// outputs
PolygonData outNormal; //!< Features that are not selected
PolygonData outSelected; //!< Features that are selected
@ -87,18 +90,20 @@ class QgsPolygon3DSymbolHandler : public QgsFeature3DHandler
};
bool QgsPolygon3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames )
bool QgsPolygon3DSymbolHandler::prepare( const Qgs3DRenderContext &context, QSet<QString> &attributeNames, const QgsVector3D &chunkOrigin )
{
outEdges.withAdjacency = true;
outEdges.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), 0, context );
outEdges.init( mSymbol->altitudeClamping(), mSymbol->altitudeBinding(), 0, context, chunkOrigin );
mChunkOrigin = chunkOrigin;
const QgsPhongTexturedMaterialSettings *texturedMaterialSettings = dynamic_cast< const QgsPhongTexturedMaterialSettings * >( mSymbol->materialSettings() );
outNormal.tessellator.reset( new QgsTessellator( context.origin().x(), context.origin().y(), true, mSymbol->invertNormals(), mSymbol->addBackFaces(), false,
outNormal.tessellator.reset( new QgsTessellator( chunkOrigin.x(), chunkOrigin.y(), true, mSymbol->invertNormals(), mSymbol->addBackFaces(), false,
texturedMaterialSettings && texturedMaterialSettings->requiresTextureCoordinates(),
mSymbol->renderedFacade(),
texturedMaterialSettings ? texturedMaterialSettings->textureRotation() : 0 ) );
outSelected.tessellator.reset( new QgsTessellator( context.origin().x(), context.origin().y(), true, mSymbol->invertNormals(),
outSelected.tessellator.reset( new QgsTessellator( chunkOrigin.x(), chunkOrigin.y(), true, mSymbol->invertNormals(),
mSymbol->addBackFaces(), false,
texturedMaterialSettings && texturedMaterialSettings->requiresTextureCoordinates(),
mSymbol->renderedFacade(),
@ -253,9 +258,16 @@ void QgsPolygon3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const Qgs3D
renderer->setPrimitiveRestartEnabled( true );
renderer->setRestartIndexValue( 0 );
// add transform (our geometry has coordinates relative to mChunkOrigin)
Qt3DCore::QTransform *tr = new Qt3DCore::QTransform;
tr->setRotation( QQuaternion::fromAxisAndAngle( QVector3D( 1, 0, 0 ), -90 ) ); // flip map (x,y,z) to world (x,z,-y)
QVector3D nodeTranslation = ( mChunkOrigin - context.origin() ).toVector3D();
tr->setTranslation( QVector3D( nodeTranslation.x(), nodeTranslation.z(), -nodeTranslation.y() ) );
// make entity
entity->addComponent( renderer );
entity->addComponent( mat );
entity->addComponent( tr );
entity->setParent( parent );
}
}
@ -285,11 +297,17 @@ void QgsPolygon3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const Qgs
Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
renderer->setGeometry( geometry );
// add transform (our geometry has coordinates relative to mChunkOrigin)
Qt3DCore::QTransform *tr = new Qt3DCore::QTransform;
QVector3D nodeTranslation = ( mChunkOrigin - context.origin() ).toVector3D();
tr->setTranslation( QVector3D( nodeTranslation.x(), nodeTranslation.z(), -nodeTranslation.y() ) );
// make entity
Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
entity->setObjectName( parent->objectName() + "_CHUNK_MESH" );
entity->addComponent( renderer );
entity->addComponent( mat );
entity->addComponent( tr );
entity->setParent( parent );
if ( !selected )

View File

@ -123,7 +123,8 @@ Qt3DCore::QEntity *QgsDemTerrainTileLoader::createEntity( Qt3DCore::QEntity *par
transform->setScale( side );
transform->setTranslation( QVector3D( x0 + half, 0, - ( y0 + half ) ) );
mNode->setExactBbox( QgsAABB( x0, zMin * map->terrainVerticalScale(), -y0, x0 + side, zMax * map->terrainVerticalScale(), -( y0 + side ) ) );
mNode->setExactBox3D( QgsBox3D( extent.xMinimum(), extent.yMinimum(), zMin * map->terrainVerticalScale(),
extent.xMinimum() + side, extent.yMinimum() + side, zMax * map->terrainVerticalScale() ) );
mNode->updateParentBoundingBoxesRecursively();
entity->setParent( parent );

View File

@ -62,22 +62,22 @@ Qt3DCore::QEntity *FlatTerrainChunkLoader::createEntity( Qt3DCore::QEntity *pare
entity->addComponent( transform );
// set up transform according to the extent covered by the quad geometry
const QgsAABB bbox = mNode->bbox();
const QgsBox3D box3D = mNode->box3D();
const QgsBox3D mapFullBox3D( map->extent(), box3D.zMinimum(), box3D.zMaximum() );
const QgsAABB mapFullExtent = Qgs3DUtils::mapToWorldExtent( map->extent(), bbox.yMin, bbox.yMax, map->origin() );
const QgsBox3D commonExtent( std::max( box3D.xMinimum(), mapFullBox3D.xMinimum() ),
std::max( box3D.yMinimum(), mapFullBox3D.yMinimum() ),
box3D.zMinimum(),
std::min( box3D.xMaximum(), mapFullBox3D.xMaximum() ),
std::min( box3D.yMaximum(), mapFullBox3D.yMaximum() ),
box3D.zMaximum() );
const double xSide = commonExtent.width();
const double ySide = commonExtent.height();
const double xMin = commonExtent.xMinimum() - map->origin().x();
const double yMin = commonExtent.yMinimum() - map->origin().y();
const QgsAABB commonExtent = QgsAABB( std::max( bbox.xMin, mapFullExtent.xMin ),
bbox.yMin,
std::max( bbox.zMin, mapFullExtent.zMin ),
std::min( bbox.xMax, mapFullExtent.xMax ),
bbox.yMax,
std::min( bbox.zMax, mapFullExtent.zMax )
);
const double xSide = commonExtent.xExtent();
const double zSide = commonExtent.zExtent();
transform->setScale3D( QVector3D( xSide, 1, zSide ) );
transform->setTranslation( QVector3D( commonExtent.xMin + xSide / 2, 0, commonExtent.zMin + zSide / 2 ) );
transform->setScale3D( QVector3D( static_cast<float>( xSide ), 1, static_cast<float>( ySide ) ) );
transform->setTranslation( QVector3D( static_cast<float>( xMin + xSide / 2 ), 0, static_cast<float>( -( yMin + ySide / 2 ) ) ) );
createTextureComponent( entity, map->isTerrainShadingEnabled(), map->terrainShadingMaterial(), !map->layers().empty() );

View File

@ -104,16 +104,14 @@ QgsQuantizedMeshTerrainChunkLoader::QgsQuantizedMeshTerrainChunkLoader( QgsTerra
try
{
QgsAABB bbox = node->bbox();
QgsBox3D box3D = node->box3D();
QgsQuantizedMeshTile qmTile( content );
qmTile.removeDegenerateTriangles();
// We now know the exact height range of the tile, set it to the node.
node->setExactBbox(
QgsAABB(
// Note that in the 3D view, Y is up!
bbox.xMin, qmTile.mHeader.MinimumHeight * vertScale, bbox.zMin,
bbox.xMax, qmTile.mHeader.MaximumHeight * vertScale, bbox.zMax ) );
box3D.setZMinimum( qmTile.mHeader.MinimumHeight * vertScale );
box3D.setZMaximum( qmTile.mHeader.MaximumHeight * vertScale );
node->setExactBox3D( box3D );
if ( shadingEnabled && qmTile.mNormalCoords.size() == 0 )
{
@ -308,7 +306,7 @@ QgsChunkNode *QgsQuantizedMeshTerrainGenerator::createRootNode() const
{
return new QgsChunkNode(
{0, 0, 0},
mRootBbox, // Given to us by setupQuadtree()
mRootBox3D, // Given to us by setupQuadtree()
mMetadata->geometricErrorAtZoom( -1 ) );
}
@ -333,16 +331,12 @@ QVector<QgsChunkNode *> QgsQuantizedMeshTerrainGenerator::createChildren( QgsChu
continue; // Don't render terrain inside layer extent, but outside map extent
Q_ASSERT( mTerrain );
QgsRectangle mapExtent2d = mTileCrsToMapCrs.transform( extent2d );
QgsVector3D corner1 = mTerrain->mapSettings()->mapToWorldCoordinates(
{mapExtent2d.xMinimum(), mapExtent2d.yMinimum(), mMetadata->dummyZRange.lower()} );
QgsVector3D corner2 = mTerrain->mapSettings()->mapToWorldCoordinates(
{mapExtent2d.xMaximum(), mapExtent2d.yMaximum(), mMetadata->dummyZRange.upper()} );
QgsVector3D corner1( mapExtent2d.xMinimum(), mapExtent2d.yMinimum(), mMetadata->dummyZRange.lower() );
QgsVector3D corner2( mapExtent2d.xMaximum(), mapExtent2d.yMaximum(), mMetadata->dummyZRange.upper() );
children.push_back(
new QgsChunkNode(
childId,
QgsAABB(
corner1.x(), corner1.y(), corner1.z(),
corner2.x(), corner2.y(), corner2.z() ),
QgsBox3D( corner1, corner2 ),
mMetadata->geometricErrorAtZoom( tile.zoomLevel() ),
node ) );
}

View File

@ -120,9 +120,12 @@ QVector<QgsRayCastingUtils::RayHit> QgsTerrainEntity::rayIntersection( const Qgs
const QList<QgsChunkNode *> activeNodes = this->activeNodes();
for ( QgsChunkNode *node : activeNodes )
{
QgsAABB nodeBbox = Qgs3DUtils::mapToWorldExtent( node->box3D(), mMapSettings->origin() );
if ( node->entity() &&
( minDist < 0 || node->bbox().distanceFromPoint( ray.origin() ) < minDist ) &&
QgsRayCastingUtils::rayBoxIntersection( ray, node->bbox() ) )
( minDist < 0 || nodeBbox.distanceFromPoint( ray.origin() ) < minDist ) &&
QgsRayCastingUtils::rayBoxIntersection( ray, nodeBbox ) )
{
Qt3DRender::QGeometryRenderer *rend = node->entity()->findChild<Qt3DRender::QGeometryRenderer *>();
auto *geom = rend->geometry();

View File

@ -15,18 +15,18 @@
#include "qgsterraingenerator.h"
#include "qgsaabb.h"
#include "qgs3dmapsettings.h"
#include "qgs3dutils.h"
#include "qgscoordinatetransform.h"
QgsAABB QgsTerrainGenerator::rootChunkBbox( const Qgs3DMapSettings &map ) const
QgsBox3D QgsTerrainGenerator::rootChunkBox3D( const Qgs3DMapSettings &map ) const
{
QgsRectangle te = Qgs3DUtils::tryReprojectExtent2D( rootChunkExtent(), crs(), map.crs(), map.transformContext() );
float hMin, hMax;
rootChunkHeightRange( hMin, hMax );
return Qgs3DUtils::mapToWorldExtent( te, hMin * map.terrainVerticalScale(), hMax * map.terrainVerticalScale(), map.origin() );
return QgsBox3D( te.xMinimum(), te.yMinimum(), hMin * map.terrainVerticalScale(),
te.xMaximum(), te.yMaximum(), hMax * map.terrainVerticalScale() );
}
float QgsTerrainGenerator::rootChunkError( const Qgs3DMapSettings &map ) const

View File

@ -79,8 +79,8 @@ class _3D_EXPORT QgsTerrainGenerator : public QgsQuadtreeChunkLoaderFactory
//! extent of the terrain's root chunk in terrain's CRS
virtual QgsRectangle rootChunkExtent() const = 0;
//! Returns bounding box of the root chunk
virtual QgsAABB rootChunkBbox( const Qgs3DMapSettings &map ) const;
//! Returns 3D box (in map coordinates) of the root chunk
virtual QgsBox3D rootChunkBox3D( const Qgs3DMapSettings &map ) const;
//! Returns error of the root chunk in world coordinates
virtual float rootChunkError( const Qgs3DMapSettings &map ) const;

View File

@ -187,7 +187,7 @@ bool QgsGeometryAreaCheck::mergeWithNeighbor( const QMap<QString, QgsFeaturePool
// Merge geometries
const QgsGeometry mergeFeatureGeom = mergeFeature.geometry();
const QgsAbstractGeometry *mergeGeom = mergeFeatureGeom.constGet();
std::unique_ptr<QgsGeometryEngine> geomEngine( QgsGeometryCheckerUtils::createGeomEngine( QgsGeometryCheckerUtils::getGeomPart( mergeGeom, mergePartIdx ), mContext->reducedTolerance ) );
std::unique_ptr<QgsGeometryEngine> geomEngine( QgsGeometry::createGeometryEngine( QgsGeometryCheckerUtils::getGeomPart( mergeGeom, mergePartIdx ), mContext->reducedTolerance ) );
QgsAbstractGeometry *combinedGeom = geomEngine->combine( QgsGeometryCheckerUtils::getGeomPart( geom, partIdx ), &errMsg );
if ( !combinedGeom || combinedGeom->isEmpty() || !QgsWkbTypes::isSingleType( combinedGeom->wkbType() ) )
{

View File

@ -265,11 +265,6 @@ QgsGeometryCheckerUtils::LayerFeatures::iterator QgsGeometryCheckerUtils::LayerF
/////////////////////////////////////////////////////////////////////////////
std::unique_ptr<QgsGeometryEngine> QgsGeometryCheckerUtils::createGeomEngine( const QgsAbstractGeometry *geometry, double tolerance )
{
return std::make_unique<QgsGeos>( geometry, tolerance );
}
QgsAbstractGeometry *QgsGeometryCheckerUtils::getGeomPart( QgsAbstractGeometry *geom, int partIdx )
{
if ( QgsGeometryCollection *collection = qgsgeometry_cast<QgsGeometryCollection *>( geom ) )

View File

@ -214,8 +214,6 @@ class ANALYSIS_EXPORT QgsGeometryCheckerUtils
#ifndef SIP_RUN
static std::unique_ptr<QgsGeometryEngine> createGeomEngine( const QgsAbstractGeometry *geometry, double tolerance );
static QgsAbstractGeometry *getGeomPart( QgsAbstractGeometry *geom, int partIdx );
static const QgsAbstractGeometry *getGeomPart( const QgsAbstractGeometry *geom, int partIdx );

View File

@ -27,7 +27,7 @@ void QgsGeometryContainedCheck::collectErrors( const QMap<QString, QgsFeaturePoo
for ( const QgsGeometryCheckerUtils::LayerFeature &layerFeatureA : layerFeaturesA )
{
const QgsRectangle bboxA = layerFeatureA.geometry().boundingBox();
std::unique_ptr< QgsGeometryEngine > geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( layerFeatureA.geometry().constGet(), mContext->tolerance );
std::unique_ptr< QgsGeometryEngine > geomEngineA( QgsGeometry::createGeometryEngine( layerFeatureA.geometry().constGet(), mContext->tolerance ) );
if ( !geomEngineA->isValid() )
{
messages.append( tr( "Contained check failed for (%1): the geometry is invalid" ).arg( layerFeatureA.id() ) );
@ -40,7 +40,7 @@ void QgsGeometryContainedCheck::collectErrors( const QMap<QString, QgsFeaturePoo
{
continue;
}
std::unique_ptr< QgsGeometryEngine > geomEngineB = QgsGeometryCheckerUtils::createGeomEngine( layerFeatureB.geometry().constGet(), mContext->tolerance );
std::unique_ptr< QgsGeometryEngine > geomEngineB( QgsGeometry::createGeometryEngine( layerFeatureB.geometry().constGet(), mContext->tolerance ) );
if ( !geomEngineB->isValid() )
{
messages.append( tr( "Contained check failed for (%1): the geometry is invalid" ).arg( layerFeatureB.id() ) );
@ -79,8 +79,8 @@ void QgsGeometryContainedCheck::fixError( const QMap<QString, QgsFeaturePool *>
const QgsGeometryCheckerUtils::LayerFeature layerFeatureA( featurePoolA, featureA, mContext, true );
const QgsGeometryCheckerUtils::LayerFeature layerFeatureB( featurePoolB, featureB, mContext, true );
std::unique_ptr< QgsGeometryEngine > geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( layerFeatureA.geometry().constGet(), mContext->tolerance );
std::unique_ptr< QgsGeometryEngine > geomEngineB = QgsGeometryCheckerUtils::createGeomEngine( layerFeatureB.geometry().constGet(), mContext->tolerance );
std::unique_ptr< QgsGeometryEngine > geomEngineA( QgsGeometry::createGeometryEngine( layerFeatureA.geometry().constGet(), mContext->tolerance ) );
std::unique_ptr< QgsGeometryEngine > geomEngineB( QgsGeometry::createGeometryEngine( layerFeatureB.geometry().constGet(), mContext->tolerance ) );
if ( !( geomEngineB->contains( layerFeatureA.geometry().constGet() ) && !geomEngineA->contains( layerFeatureB.geometry().constGet() ) ) )
{

View File

@ -51,7 +51,7 @@ void QgsGeometryDuplicateCheck::collectErrors( const QMap<QString, QgsFeaturePoo
const QgsGeometry geomA = layerFeatureA.geometry();
const QgsRectangle bboxA = geomA.boundingBox();
std::unique_ptr< QgsGeometryEngine > geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( geomA.constGet(), mContext->tolerance );
std::unique_ptr< QgsGeometryEngine > geomEngineA( QgsGeometry::createGeometryEngine( geomA.constGet(), mContext->tolerance, Qgis::GeosCreationFlags() ) );
if ( !geomEngineA->isValid() )
{
messages.append( tr( "Duplicate check failed for (%1): the geometry is invalid" ).arg( layerFeatureA.id() ) );
@ -105,7 +105,7 @@ void QgsGeometryDuplicateCheck::fixError( const QMap<QString, QgsFeaturePool *>
else if ( method == RemoveDuplicates )
{
const QgsGeometryCheckerUtils::LayerFeature layerFeatureA( featurePoolA, featureA, mContext, true );
std::unique_ptr< QgsGeometryEngine > geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( layerFeatureA.geometry().constGet(), mContext->tolerance );
std::unique_ptr< QgsGeometryEngine > geomEngineA( QgsGeometry::createGeometryEngine( layerFeatureA.geometry().constGet(), mContext->tolerance ) );
QgsGeometryDuplicateCheckError *duplicateError = static_cast<QgsGeometryDuplicateCheckError *>( error );
const QMap<QString, QList<QgsFeatureId>> duplicates = duplicateError->duplicates();

View File

@ -57,7 +57,7 @@ void QgsGeometryFollowBoundariesCheck::collectErrors( const QMap<QString, QgsFea
QgsGeometry geomt( geom->clone() );
geomt.transform( crst );
std::unique_ptr< QgsGeometryEngine > geomEngine = QgsGeometryCheckerUtils::createGeomEngine( geomt.constGet(), mContext->tolerance );
std::unique_ptr< QgsGeometryEngine > geomEngine( QgsGeometry::createGeometryEngine( geomt.constGet(), mContext->tolerance ) );
// Get potential reference features
QgsRectangle searchBounds = geomt.constGet()->boundingBox();
@ -79,7 +79,7 @@ void QgsGeometryFollowBoundariesCheck::collectErrors( const QMap<QString, QgsFea
while ( refFeatureIt.nextFeature( refFeature ) )
{
const QgsAbstractGeometry *refGeom = refFeature.geometry().constGet();
std::unique_ptr<QgsGeometryEngine> refgeomEngine( QgsGeometryCheckerUtils::createGeomEngine( refGeom, mContext->tolerance ) );
std::unique_ptr<QgsGeometryEngine> refgeomEngine( QgsGeometry::createGeometryEngine( refGeom, mContext->tolerance ) );
const QgsGeometry reducedRefGeom( refgeomEngine->buffer( -mContext->tolerance, 0 ) );
if ( !( geomEngine->contains( reducedRefGeom.constGet() ) || geomEngine->disjoint( reducedRefGeom.constGet() ) ) )
{

View File

@ -74,12 +74,12 @@ void QgsGeometryGapCheck::collectErrors( const QMap<QString, QgsFeaturePool *> &
allowedGaps.append( gg );
}
std::unique_ptr< QgsGeometryEngine > allowedGapsEngine = QgsGeometryCheckerUtils::createGeomEngine( nullptr, mContext->tolerance );
std::unique_ptr< QgsGeometryEngine > allowedGapsEngine( QgsGeometry::createGeometryEngine( nullptr, mContext->tolerance ) );
// Create union of allowed gaps
QString errMsg;
allowedGapsGeom.reset( allowedGapsEngine->combine( allowedGaps, &errMsg ) );
allowedGapsGeomEngine = QgsGeometryCheckerUtils::createGeomEngine( allowedGapsGeom.get(), mContext->tolerance );
allowedGapsGeomEngine.reset( QgsGeometry::createGeometryEngine( allowedGapsGeom.get(), mContext->tolerance ) );
allowedGapsGeomEngine->prepareGeometry();
}
@ -102,7 +102,7 @@ void QgsGeometryGapCheck::collectErrors( const QMap<QString, QgsFeaturePool *> &
return;
}
std::unique_ptr< QgsGeometryEngine > geomEngine = QgsGeometryCheckerUtils::createGeomEngine( nullptr, mContext->tolerance );
std::unique_ptr< QgsGeometryEngine > geomEngine( QgsGeometry::createGeometryEngine( nullptr, mContext->tolerance ) );
// Create union of geometry
QString errMsg;
@ -114,7 +114,7 @@ void QgsGeometryGapCheck::collectErrors( const QMap<QString, QgsFeaturePool *> &
}
// Get envelope of union
geomEngine = QgsGeometryCheckerUtils::createGeomEngine( unionGeom.get(), mContext->tolerance );
geomEngine.reset( QgsGeometry::createGeometryEngine( unionGeom.get(), mContext->tolerance ) );
geomEngine->prepareGeometry();
std::unique_ptr<QgsAbstractGeometry> envelope( geomEngine->envelope( &errMsg ) );
if ( !envelope )
@ -124,13 +124,13 @@ void QgsGeometryGapCheck::collectErrors( const QMap<QString, QgsFeaturePool *> &
}
// Buffer envelope
geomEngine = QgsGeometryCheckerUtils::createGeomEngine( envelope.get(), mContext->tolerance );
geomEngine.reset( QgsGeometry::createGeometryEngine( envelope.get(), mContext->tolerance ) );
geomEngine->prepareGeometry();
QgsAbstractGeometry *bufEnvelope = geomEngine->buffer( 2, 0, Qgis::EndCapStyle::Square, Qgis::JoinStyle::Miter, 4. ); //#spellok //#spellok
envelope.reset( bufEnvelope );
// Compute difference between envelope and union to obtain gap polygons
geomEngine = QgsGeometryCheckerUtils::createGeomEngine( envelope.get(), mContext->tolerance );
geomEngine.reset( QgsGeometry::createGeometryEngine( envelope.get(), mContext->tolerance ) );
geomEngine->prepareGeometry();
std::unique_ptr<QgsAbstractGeometry> diffGeom( geomEngine->difference( unionGeom.get(), &errMsg ) );
if ( !diffGeom )
@ -162,7 +162,7 @@ void QgsGeometryGapCheck::collectErrors( const QMap<QString, QgsFeaturePool *> &
// Get neighboring polygons
QMap<QString, QgsFeatureIds> neighboringIds;
const QgsGeometryCheckerUtils::LayerFeatures layerFeatures( featurePools, featureIds.keys(), gapAreaBBox, compatibleGeometryTypes(), mContext );
std::unique_ptr< QgsGeometryEngine > gapGeomEngine = QgsGeometryCheckerUtils::createGeomEngine( gapGeom, mContext->tolerance );
std::unique_ptr< QgsGeometryEngine > gapGeomEngine( QgsGeometry::createGeometryEngine( gapGeom, mContext->tolerance ) );
gapGeomEngine->prepareGeometry();
for ( const QgsGeometryCheckerUtils::LayerFeature &layerFeature : layerFeatures )
{
@ -407,7 +407,7 @@ bool QgsGeometryGapCheck::mergeWithNeighbor( const QMap<QString, QgsFeaturePool
errLayerGeom->transform( ct, Qgis::TransformDirection::Reverse );
const QgsGeometry mergeFeatureGeom = mergeFeature.geometry();
const QgsAbstractGeometry *mergeGeom = mergeFeatureGeom.constGet();
std::unique_ptr< QgsGeometryEngine > geomEngine = QgsGeometryCheckerUtils::createGeomEngine( errLayerGeom.get(), 0 );
std::unique_ptr< QgsGeometryEngine > geomEngine( QgsGeometry::createGeometryEngine( errLayerGeom.get(), 0 ) );
std::unique_ptr<QgsAbstractGeometry> combinedGeom( geomEngine->combine( QgsGeometryCheckerUtils::getGeomPart( mergeGeom, mergePartIdx ), &errMsg ) );
if ( !combinedGeom || combinedGeom->isEmpty() || !QgsWkbTypes::isSingleType( combinedGeom->wkbType() ) )
{

Some files were not shown because too many files have changed in this diff Show More