diff --git a/python/core/auto_generated/qgsmapsettings.sip.in b/python/core/auto_generated/qgsmapsettings.sip.in index accff9729d5..d19603f40cf 100644 --- a/python/core/auto_generated/qgsmapsettings.sip.in +++ b/python/core/auto_generated/qgsmapsettings.sip.in @@ -74,6 +74,25 @@ Set coordinates of the rectangle which should be rendered. The actual visible extent used for rendering could be slightly different since the given extent may be expanded in order to fit the aspect ratio of output size. Use visibleExtent() to get the resulting extent. +%End + + double extentBuffer() const; +%Docstring +Returns the buffer in map units to use around the visible extent for rendering +symbols whose corresponding geometries are outside the visible extent. + +.. seealso:: :py:func:`setExtentBuffer` + +.. versionadded:: 3.10 +%End + + void setExtentBuffer( double buffer ); +%Docstring +Sets the buffer in map units to use around the visible extent for rendering +symbols whose corresponding geometries are outside the visible extent. This +is useful when using tiles to avoid cut symbols at tile boundaries. + +.. versionadded:: 3.10 %End QSize outputSize() const; diff --git a/python/server/auto_generated/qgsserverprojectutils.sip.in b/python/server/auto_generated/qgsserverprojectutils.sip.in index 550dbff41d9..d0c98cfeac7 100644 --- a/python/server/auto_generated/qgsserverprojectutils.sip.in +++ b/python/server/auto_generated/qgsserverprojectutils.sip.in @@ -152,6 +152,17 @@ Returns the quality for WMS images defined in a QGIS project. :param project: the QGIS project :return: quality if defined in project, -1 otherwise. +%End + + int wmsTileBuffer( const QgsProject &project ); +%Docstring +Returns the tile buffer in pixels for WMS images defined in a QGIS project. + +:param project: the QGIS project + +:return: tile buffer if defined in project, 0 otherwise. + +.. versionadded:: 3.10 %End int wmsMaxAtlasFeatures( const QgsProject &project ); diff --git a/src/app/qgsprojectproperties.cpp b/src/app/qgsprojectproperties.cpp index 0dbff208603..1499edf3114 100644 --- a/src/app/qgsprojectproperties.cpp +++ b/src/app/qgsprojectproperties.cpp @@ -644,6 +644,9 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas *mapCanvas, QWidget *pa mWMSImageQualitySpinBox->setValue( imageQuality ); } + // WMS tileBuffer + mWMSTileBufferSpinBox->setValue( QgsProject::instance()->readNumEntry( QStringLiteral( "WMSTileBuffer" ), QStringLiteral( "/" ), 0 ) ); + mWMSMaxAtlasFeaturesSpinBox->setValue( QgsProject::instance()->readNumEntry( QStringLiteral( "WMSMaxAtlasFeatures" ), QStringLiteral( "/" ), 1 ) ); QString defaultValueToolTip = tr( "In case of no other information to evaluate the map unit sized symbols, it uses default scale (on projected CRS) or default map units per mm (on geographic CRS)." ); @@ -1323,6 +1326,9 @@ void QgsProjectProperties::apply() QgsProject::instance()->writeEntry( QStringLiteral( "WMSImageQuality" ), QStringLiteral( "/" ), imageQualityValue ); } + // WMS TileBuffer + QgsProject::instance()->writeEntry( QStringLiteral( "WMSTileBuffer" ), QStringLiteral( "/" ), mWMSTileBufferSpinBox->value() ); + int maxAtlasFeatures = mWMSMaxAtlasFeaturesSpinBox->value(); QgsProject::instance()->writeEntry( QStringLiteral( "WMSMaxAtlasFeatures" ), QStringLiteral( "/" ), maxAtlasFeatures ); diff --git a/src/core/qgsmaprendererjob.cpp b/src/core/qgsmaprendererjob.cpp index 38ed011900b..2edb96ddc62 100644 --- a/src/core/qgsmaprendererjob.cpp +++ b/src/core/qgsmaprendererjob.cpp @@ -254,6 +254,7 @@ LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter *painter, QgsLabelingEn } QgsRectangle r1 = mSettings.visibleExtent(), r2; + r1.grow( mSettings.extentBuffer() ); QgsCoordinateTransform ct; ct = mSettings.layerTransform( ml ); diff --git a/src/core/qgsmapsettings.cpp b/src/core/qgsmapsettings.cpp index f7df8db371e..05fcf8c0d24 100644 --- a/src/core/qgsmapsettings.cpp +++ b/src/core/qgsmapsettings.cpp @@ -87,6 +87,16 @@ void QgsMapSettings::setExtent( const QgsRectangle &extent, bool magnified ) updateDerived(); } +double QgsMapSettings::extentBuffer() const +{ + return mExtentBuffer; +} + +void QgsMapSettings::setExtentBuffer( const double buffer ) +{ + mExtentBuffer = buffer; +} + double QgsMapSettings::rotation() const { return mRotation; diff --git a/src/core/qgsmapsettings.h b/src/core/qgsmapsettings.h index b128dc40006..cc78c1f39c8 100644 --- a/src/core/qgsmapsettings.h +++ b/src/core/qgsmapsettings.h @@ -102,6 +102,22 @@ class CORE_EXPORT QgsMapSettings */ void setExtent( const QgsRectangle &rect, bool magnified = true ); + /** + * Returns the buffer in map units to use around the visible extent for rendering + * symbols whose corresponding geometries are outside the visible extent. + * \see setExtentBuffer() + * \since QGIS 3.10 + */ + double extentBuffer() const; + + /** + * Sets the buffer in map units to use around the visible extent for rendering + * symbols whose corresponding geometries are outside the visible extent. This + * is useful when using tiles to avoid cut symbols at tile boundaries. + * \since QGIS 3.10 + */ + void setExtentBuffer( double buffer ); + //! Returns the size of the resulting map image QSize outputSize() const; //! Sets the size of the resulting map image @@ -539,6 +555,7 @@ class CORE_EXPORT QgsMapSettings float mDevicePixelRatio = 1.0; QgsRectangle mExtent; + double mExtentBuffer = 0.0; double mRotation = 0.0; double mMagnificationFactor = 1.0; diff --git a/src/core/qgsrendercontext.cpp b/src/core/qgsrendercontext.cpp index 72d301321c6..d8583c700ba 100644 --- a/src/core/qgsrendercontext.cpp +++ b/src/core/qgsrendercontext.cpp @@ -157,8 +157,10 @@ bool QgsRenderContext::testFlag( QgsRenderContext::Flag flag ) const QgsRenderContext QgsRenderContext::fromMapSettings( const QgsMapSettings &mapSettings ) { QgsRenderContext ctx; + QgsRectangle extent = mapSettings.visibleExtent(); + extent.grow( mapSettings.extentBuffer() ); ctx.setMapToPixel( mapSettings.mapToPixel() ); - ctx.setExtent( mapSettings.visibleExtent() ); + ctx.setExtent( extent ); ctx.setMapExtent( mapSettings.visibleExtent() ); ctx.setFlag( DrawEditingInfo, mapSettings.testFlag( QgsMapSettings::DrawEditingInfo ) ); ctx.setFlag( ForceVectorOutput, mapSettings.testFlag( QgsMapSettings::ForceVectorOutput ) ); diff --git a/src/server/qgsserverprojectutils.cpp b/src/server/qgsserverprojectutils.cpp index ede6667e15a..67cc1285efa 100644 --- a/src/server/qgsserverprojectutils.cpp +++ b/src/server/qgsserverprojectutils.cpp @@ -111,6 +111,11 @@ int QgsServerProjectUtils::wmsImageQuality( const QgsProject &project ) return project.readNumEntry( QStringLiteral( "WMSImageQuality" ), QStringLiteral( "/" ), -1 ); } +int QgsServerProjectUtils::wmsTileBuffer( const QgsProject &project ) +{ + return project.readNumEntry( QStringLiteral( "WMSTileBuffer" ), QStringLiteral( "/" ), 0 ); +} + int QgsServerProjectUtils::wmsMaxAtlasFeatures( const QgsProject &project ) { return project.readNumEntry( QStringLiteral( "WMSMaxAtlasFeatures" ), QStringLiteral( "/" ), 1 ); diff --git a/src/server/qgsserverprojectutils.h b/src/server/qgsserverprojectutils.h index fcce3c3f0dd..d26432ff4b0 100644 --- a/src/server/qgsserverprojectutils.h +++ b/src/server/qgsserverprojectutils.h @@ -147,6 +147,14 @@ namespace QgsServerProjectUtils */ SERVER_EXPORT int wmsImageQuality( const QgsProject &project ); + /** + * Returns the tile buffer in pixels for WMS images defined in a QGIS project. + * \param project the QGIS project + * \returns tile buffer if defined in project, 0 otherwise. + * \since QGIS 3.10 + */ + SERVER_EXPORT int wmsTileBuffer( const QgsProject &project ); + /** * Returns the maximum number of atlas features which can be printed in a request * \param project the QGIS project diff --git a/src/server/services/wms/qgswmsgetmap.cpp b/src/server/services/wms/qgswmsgetmap.cpp index d1d7d650811..c4f7aed9f9a 100644 --- a/src/server/services/wms/qgswmsgetmap.cpp +++ b/src/server/services/wms/qgswmsgetmap.cpp @@ -44,6 +44,7 @@ namespace QgsWms context.setFlag( QgsWmsRenderContext::AddHighlightLayers ); context.setFlag( QgsWmsRenderContext::AddExternalLayers ); context.setFlag( QgsWmsRenderContext::SetAccessControl ); + context.setFlag( QgsWmsRenderContext::UseTileBuffer ); context.setParameters( parameters ); // rendering diff --git a/src/server/services/wms/qgswmsparameters.cpp b/src/server/services/wms/qgswmsparameters.cpp index cb260a3a655..8e61a6f6def 100644 --- a/src/server/services/wms/qgswmsparameters.cpp +++ b/src/server/services/wms/qgswmsparameters.cpp @@ -223,6 +223,11 @@ namespace QgsWms QVariant( 0 ) ); save( pQuality ); + const QgsWmsParameter pTiled( QgsWmsParameter::TILED, + QVariant::Bool, + QVariant( false ) ); + save( pTiled ); + const QgsWmsParameter pBoxSpace( QgsWmsParameter::BOXSPACE, QVariant::Double, QVariant( 2.0 ) ); @@ -944,6 +949,16 @@ namespace QgsWms return mWmsParameters[ QgsWmsParameter::IMAGE_QUALITY ].toInt(); } + QString QgsWmsParameters::tiled() const + { + return mWmsParameters[ QgsWmsParameter::TILED ].toString(); + } + + bool QgsWmsParameters::tiledAsBool() const + { + return mWmsParameters[ QgsWmsParameter::TILED ].toBool(); + } + QString QgsWmsParameters::showFeatureCount() const { return mWmsParameters[ QgsWmsParameter::SHOWFEATURECOUNT ].toString(); diff --git a/src/server/services/wms/qgswmsparameters.h b/src/server/services/wms/qgswmsparameters.h index 503fbb76b0f..ad8d3a09857 100644 --- a/src/server/services/wms/qgswmsparameters.h +++ b/src/server/services/wms/qgswmsparameters.h @@ -177,7 +177,8 @@ namespace QgsWms ATLAS_PK, FORMAT_OPTIONS, SRCWIDTH, - SRCHEIGHT + SRCHEIGHT, + TILED }; Q_ENUM( Name ) @@ -628,6 +629,20 @@ namespace QgsWms */ int imageQualityAsInt() const; + /** + * Returns TILED parameter or an empty string if not + * defined. + * \since QGIS 3.10 + */ + QString tiled() const; + + /** + * Returns TILED parameter as a boolean. + * \throws QgsBadRequestException + * \since QGIS 3.10 + */ + bool tiledAsBool() const; + /** * Returns infoFormat. If the INFO_FORMAT parameter is not used, then the * default value is text/plain. diff --git a/src/server/services/wms/qgswmsrendercontext.cpp b/src/server/services/wms/qgswmsrendercontext.cpp index f41c9581d4b..c842bb58e6e 100644 --- a/src/server/services/wms/qgswmsrendercontext.cpp +++ b/src/server/services/wms/qgswmsrendercontext.cpp @@ -24,7 +24,6 @@ using namespace QgsWms; const double OGC_PX_M = 0.00028; // OGC reference pixel size in meter - QgsWmsRenderContext::QgsWmsRenderContext( const QgsProject *project, QgsServerInterface *interface ) : mProject( project ) , mInterface( interface ) @@ -132,6 +131,18 @@ int QgsWmsRenderContext::imageQuality() const return imageQuality; } +int QgsWmsRenderContext::tileBuffer() const +{ + int tileBuffer = 0; + + if ( mParameters.tiledAsBool() ) + { + tileBuffer = QgsServerProjectUtils::wmsTileBuffer( *mProject ); + } + + return tileBuffer; +} + int QgsWmsRenderContext::precision() const { int precision = QgsServerProjectUtils::wmsFeatureInfoPrecision( *mProject ); @@ -638,6 +649,26 @@ bool QgsWmsRenderContext::isValidWidthHeight() const return true; } +double QgsWmsRenderContext::mapTileBuffer( const int mapWidth ) const +{ + double buffer; + if ( mFlags & UseTileBuffer ) + { + const QgsRectangle extent = mParameters.bboxAsRectangle(); + if ( !mParameters.bbox().isEmpty() && extent.isEmpty() ) + { + throw QgsBadRequestException( QgsServiceException::QGIS_InvalidParameterValue, + mParameters[QgsWmsParameter::BBOX] ); + } + buffer = tileBuffer() * ( extent.width() / mapWidth ); + } + else + { + buffer = 0; + } + return buffer; +} + QSize QgsWmsRenderContext::mapSize( const bool aspectRatio ) const { int width = mapWidth(); diff --git a/src/server/services/wms/qgswmsrendercontext.h b/src/server/services/wms/qgswmsrendercontext.h index 43b5f9c6749..e776339f6b5 100644 --- a/src/server/services/wms/qgswmsrendercontext.h +++ b/src/server/services/wms/qgswmsrendercontext.h @@ -47,7 +47,8 @@ namespace QgsWms AddQueryLayers = 0x80, UseWfsLayersOnly = 0x100, AddExternalLayers = 0x200, - UseSrcWidthHeight = 0x400 + UseSrcWidthHeight = 0x400, + UseTileBuffer = 0x800 }; Q_DECLARE_FLAGS( Flags, Flag ) @@ -148,6 +149,13 @@ namespace QgsWms */ int imageQuality() const; + /** + * Returns the tile buffer value to use for rendering according to the + * current configuration. + * \since QGIS 3.10 + */ + int tileBuffer() const; + /** * Returns the precision to use according to the current configuration. */ @@ -200,6 +208,12 @@ namespace QgsWms */ QMap > layerGroups() const; + /** + * Returns the tile buffer in geographical units for the given map width in pixels. + * \since QGIS 3.10 + */ + double mapTileBuffer( int mapWidth ) const; + /** * Returns the size (in pixels) of the map to render, according to width * and height WMS parameters as well as the \a aspectRatio option. diff --git a/src/server/services/wms/qgswmsrenderer.cpp b/src/server/services/wms/qgswmsrenderer.cpp index a172b1c2bee..6dc7a46572e 100644 --- a/src/server/services/wms/qgswmsrenderer.cpp +++ b/src/server/services/wms/qgswmsrenderer.cpp @@ -17,7 +17,6 @@ * * ***************************************************************************/ - #include "qgswmsutils.h" #include "qgsjsonutils.h" #include "qgswmsrenderer.h" @@ -1028,6 +1027,9 @@ namespace QgsWms mapSettings.setExtent( mapExtent ); + // set the extent buffer + mapSettings.setExtentBuffer( mContext.mapTileBuffer( paintDevice->width() ) ); + /* Define the background color * Transparent or colored */ diff --git a/src/ui/qgsprojectpropertiesbase.ui b/src/ui/qgsprojectpropertiesbase.ui index 75f737ef87a..ef6e3c32683 100644 --- a/src/ui/qgsprojectpropertiesbase.ui +++ b/src/ui/qgsprojectpropertiesbase.ui @@ -236,7 +236,7 @@ - 4 + 8 @@ -265,8 +265,8 @@ 0 0 - 537 - 795 + 535 + 740 @@ -863,8 +863,8 @@ 0 0 - 546 - 164 + 544 + 155 @@ -938,8 +938,8 @@ 0 0 - 269 - 553 + 266 + 524 @@ -1514,8 +1514,8 @@ 0 0 - 167 - 55 + 165 + 52 @@ -1575,9 +1575,9 @@ 0 - 0 - 598 - 2732 + -793 + 671 + 2614 @@ -2437,6 +2437,23 @@ + + + + + + When using tiles set this to the size of the larger symbols to avoid cut symbols at tile boundaries. This works by drawing features that are outside the tile extent. + + + Tile buffer in pixels + + + + + + + + diff --git a/tests/src/core/testqgsmapsettings.cpp b/tests/src/core/testqgsmapsettings.cpp index 7a7bf00cd67..ac8c0310b7d 100644 --- a/tests/src/core/testqgsmapsettings.cpp +++ b/tests/src/core/testqgsmapsettings.cpp @@ -40,6 +40,7 @@ class TestQgsMapSettings: public QObject void testGettersSetters(); void testLabelingEngineSettings(); void visibleExtent(); + void extentBuffer(); void mapUnitsPerPixel(); void testDevicePixelRatio(); void visiblePolygon(); @@ -160,6 +161,17 @@ void TestQgsMapSettings::visibleExtent() QCOMPARE( ms.visibleExtent().toString( 0 ), QString( "-56,-81 : 156,131" ) ); } +void TestQgsMapSettings::extentBuffer() +{ + QgsMapSettings ms; + ms.setExtent( QgsRectangle( 50, 50, 100, 100 ) ); + ms.setOutputSize( QSize( 50, 50 ) ); + ms.setExtentBuffer( 10 ); + QgsRectangle visibleExtent = ms.visibleExtent(); + visibleExtent.grow( ms.extentBuffer() ); + QCOMPARE( visibleExtent.toString( 0 ), QString( "40,40 : 110,110" ) ); +} + void TestQgsMapSettings::mapUnitsPerPixel() { QgsMapSettings ms; diff --git a/tests/src/python/test_qgsserver_wms_getmap.py b/tests/src/python/test_qgsserver_wms_getmap.py index aaec138527b..6d7d8057b11 100644 --- a/tests/src/python/test_qgsserver_wms_getmap.py +++ b/tests/src/python/test_qgsserver_wms_getmap.py @@ -1578,6 +1578,62 @@ class TestQgsServerWMSGetMap(QgsServerTestBase): r, h = self._result(self._execute_request(qs)) self._img_diff_error(r, h, "WMS_GetMap_Group_Layer_Order") + def test_wms_getmap_tile_buffer(self): + """Test the implementation of tile_map_edge_buffer from mapserver.""" + + # Check without tiled parameters (default is false) + qs = "?" + "&".join(["%s=%s" % i for i in list({ + "MAP": urllib.parse.quote(os.path.join(self.testdata_path, 'wms_tile_buffer.qgs')), + "SERVICE": "WMS", + "VERSION": "1.3.0", + "REQUEST": "GetMap", + "BBOX": "310187,6163153,324347,6177313", + "CRS": "EPSG:3857", + "WIDTH": "512", + "HEIGHT": "512", + "LAYERS": "wms_tile_buffer_data", + "FORMAT": "image/png" + }.items())]) + + r, h = self._result(self._execute_request(qs)) + self._img_diff_error(r, h, "WMS_GetMap_Tiled_False") + + # Check with tiled=false + qs = "?" + "&".join(["%s=%s" % i for i in list({ + "MAP": urllib.parse.quote(os.path.join(self.testdata_path, 'wms_tile_buffer.qgs')), + "SERVICE": "WMS", + "VERSION": "1.3.0", + "REQUEST": "GetMap", + "BBOX": "310187,6163153,324347,6177313", + "CRS": "EPSG:3857", + "WIDTH": "512", + "HEIGHT": "512", + "LAYERS": "wms_tile_buffer_data", + "FORMAT": "image/png", + "TILED": "false" + }.items())]) + + r, h = self._result(self._execute_request(qs)) + self._img_diff_error(r, h, "WMS_GetMap_Tiled_False") + + # Check with tiled=true + qs = "?" + "&".join(["%s=%s" % i for i in list({ + "MAP": urllib.parse.quote(os.path.join(self.testdata_path, 'wms_tile_buffer.qgs')), + "SERVICE": "WMS", + "VERSION": "1.3.0", + "REQUEST": "GetMap", + "BBOX": "310187,6163153,324347,6177313", + "CRS": "EPSG:3857", + "WIDTH": "512", + "HEIGHT": "512", + "LAYERS": "wms_tile_buffer_data", + "FORMAT": "image/png", + "TILED": "true" + }.items())]) + + r, h = self._result(self._execute_request(qs)) + self._img_diff_error(r, h, "WMS_GetMap_Tiled_True") + if __name__ == '__main__': unittest.main() diff --git a/tests/testdata/control_images/qgis_server/WMS_GetMap_Tiled_False/WMS_GetMap_Tiled_False.png b/tests/testdata/control_images/qgis_server/WMS_GetMap_Tiled_False/WMS_GetMap_Tiled_False.png new file mode 100644 index 00000000000..c633e4803b0 Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetMap_Tiled_False/WMS_GetMap_Tiled_False.png differ diff --git a/tests/testdata/control_images/qgis_server/WMS_GetMap_Tiled_True/WMS_GetMap_Tiled_True.png b/tests/testdata/control_images/qgis_server/WMS_GetMap_Tiled_True/WMS_GetMap_Tiled_True.png new file mode 100644 index 00000000000..212b9a96d4a Binary files /dev/null and b/tests/testdata/control_images/qgis_server/WMS_GetMap_Tiled_True/WMS_GetMap_Tiled_True.png differ diff --git a/tests/testdata/qgis_server/wms_tile_buffer.qgs b/tests/testdata/qgis_server/wms_tile_buffer.qgs new file mode 100644 index 00000000000..6a3d8c20468 --- /dev/null +++ b/tests/testdata/qgis_server/wms_tile_buffer.qgs @@ -0,0 +1,598 @@ + + + + + + + + + + +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + WGS84 + false + + + + + + + + + wms_tile_buffer_data_fcfdbf36_dd5a_45d6_b770_bdbb3794cf98 + + + + + + + + + + meters + + 304918.47943539364496246 + 6160178.90903625823557377 + 329687.225462922884617 + 6174497.13128242827951908 + + 0 + + + +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + WGS84 + false + + + 0 + + + + + + + + + + + + + 289998 + 6156740 + 344497 + 6188080 + + wms_tile_buffer_data_fcfdbf36_dd5a_45d6_b770_bdbb3794cf98 + ./wms_tile_buffer_data.gpkg|layername=wms_tile_buffer_data + + + + wms_tile_buffer_data + + + +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs + 3857 + 3857 + EPSG:3857 + WGS 84 / Pseudo-Mercator + merc + WGS84 + false + + + + + + + + + + + + + + + + 0 + 0 + + + + + true + + + + + ogr + + + + + + + + + + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + . + + 0 + + + 0 + generatedlayout + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id + + + + + + + + + + + + + 1 + true + + + 255 + 255 + 255 + 255 + 0 + 255 + 255 + + + false + + + + + + WGS84 + + + <unknown> + meters + + + 50 + 16 + 30 + true + false + 0 + false + false + true + 0 + + + false + + + true + 2 + MU + + + 1 + + + + + + + + + + + None + true + + + + + + 1 + conditions unknown + 90 + + + + 1 + + 8 + false + + false + + false + + 60 + + false + + + + + + + + wms_tile_buffer_data_fcfdbf36_dd5a_45d6_b770_bdbb3794cf98 + + true + + + + + wms_tile_buffer_data_fcfdbf36_dd5a_45d6_b770_bdbb3794cf98 + + true + + 5000 + + + + wms_tile_buffer_data_fcfdbf36_dd5a_45d6_b770_bdbb3794cf98 + + true + + + + + + + + + + + + + + + + + + + + + + + SALSE Alice + 2019-02-13T15:29:32 + + + + diff --git a/tests/testdata/qgis_server/wms_tile_buffer_data.gpkg b/tests/testdata/qgis_server/wms_tile_buffer_data.gpkg new file mode 100644 index 00000000000..03df3608b80 Binary files /dev/null and b/tests/testdata/qgis_server/wms_tile_buffer_data.gpkg differ