From 98d20ee4797f8ea1f4c7024a6774dfb2e9cc2e04 Mon Sep 17 00:00:00 2001 From: JuhoErvasti Date: Wed, 4 Dec 2024 09:33:51 +0200 Subject: [PATCH] Add tests for rendering with extent buffer --- .../src/python/test_qgsvectorlayerrenderer.py | 100 ++++++++++++++++++ .../expected_buffer_extent.png | Bin 0 -> 4825 bytes .../expected_buffer_extent_zero.png | Bin 0 -> 3618 bytes .../expected_negative_buffer_extent.png | Bin 0 -> 9219 bytes 4 files changed, 100 insertions(+) create mode 100644 tests/testdata/control_images/vectorlayerrenderer/expected_buffer_extent/expected_buffer_extent.png create mode 100644 tests/testdata/control_images/vectorlayerrenderer/expected_buffer_extent_zero/expected_buffer_extent_zero.png create mode 100644 tests/testdata/control_images/vectorlayerrenderer/expected_negative_buffer_extent/expected_negative_buffer_extent.png diff --git a/tests/src/python/test_qgsvectorlayerrenderer.py b/tests/src/python/test_qgsvectorlayerrenderer.py index 67644fc8a3b..eace39b992a 100644 --- a/tests/src/python/test_qgsvectorlayerrenderer.py +++ b/tests/src/python/test_qgsvectorlayerrenderer.py @@ -16,21 +16,27 @@ from qgis.PyQt.QtCore import QDir, QSize from qgis.PyQt.QtGui import QColor from qgis.core import ( + edit, Qgis, QgsCategorizedSymbolRenderer, QgsCentroidFillSymbolLayer, QgsCoordinateReferenceSystem, + QgsFeature, QgsFeatureRendererGenerator, QgsFillSymbol, QgsGeometry, + QgsGeometryGeneratorSymbolLayer, QgsLineSymbol, QgsMapClippingRegion, QgsMapSettings, QgsMarkerSymbol, + QgsPointXY, QgsRectangle, QgsRendererCategory, QgsRuleBasedRenderer, QgsSingleSymbolRenderer, + QgsSymbol, + QgsRenderContext, QgsVectorLayer, ) import unittest @@ -927,6 +933,100 @@ class TestQgsVectorLayerRenderer(QgisTestCase): ) ) + def testRenderWithExtentBuffer(self): + def createFeature(x: float, y: float) -> QgsFeature: + feat = QgsFeature() + feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(x, y))) + + return feat + + def createSymbol() -> QgsMarkerSymbol: + sym = QgsMarkerSymbol.createSimple({'color': '#33aa33', 'outline_style': 'no', 'size': '5'}) + return sym + + def createGeometryGenerator() -> QgsGeometryGeneratorSymbolLayer: + geomgen = QgsGeometryGeneratorSymbolLayer.create( + {'geometryModifier': 'make_point($x + if($x <= 0, 5, -5), $y)'} + ) + geomgen.setSymbolType(QgsSymbol.SymbolType.Marker) + geomgen.setSubSymbol(QgsMarkerSymbol.createSimple({'color': '#ff00ff', 'outline_style': 'no', 'size': '6'})) + + return geomgen + + point_layer = QgsVectorLayer("Point?crs=EPSG:3857", "point layer", "memory") + + with edit(point_layer): + point_layer.addFeature(createFeature(-15.999, 8)) + point_layer.addFeature(createFeature(-16.001, 6)) + point_layer.addFeature(createFeature(-13, 4)) + point_layer.addFeature(createFeature(-10, 2)) + point_layer.addFeature(createFeature(17, 0)) + point_layer.addFeature(createFeature(4, -2)) + point_layer.addFeature(createFeature(15.999, -4)) + point_layer.addFeature(createFeature(17, -6)) + point_layer.addFeature(createFeature(15.999, -8)) + + sym1 = createSymbol() + sym1.appendSymbolLayer(createGeometryGenerator()) + + renderer1 = QgsSingleSymbolRenderer(sym1) + point_layer.setRenderer(renderer1) + + mapsettings = QgsMapSettings() + mapsettings.setOutputSize(QSize(400, 400)) + mapsettings.setOutputDpi(96) + mapsettings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857')) + mapsettings.setExtent(QgsRectangle(-10, -10, 10, 10)) + mapsettings.setLayers([point_layer]) + + self.assertTrue( + self.render_map_settings_check( + 'buffer_extent_zero', + 'buffer_extent_zero', + mapsettings, + ) + ) + + sym2 = createSymbol() + sym2.appendSymbolLayer(createGeometryGenerator()) + sym2.setExtentBuffer(1) + + renderer2 = QgsSingleSymbolRenderer(sym2) + point_layer.setRenderer(renderer2) + + self.assertTrue( + self.render_map_settings_check( + 'buffer_extent', + 'buffer_extent', + mapsettings, + ) + ) + + def testRenderWithExtentBufferNegative(self): + poly_layer = QgsVectorLayer(os.path.join(TEST_DATA_DIR, 'polys.shp')) + self.assertTrue(poly_layer.isValid()) + + sym1 = QgsFillSymbol.createSimple({'color': '#ff00ff', 'outline_color': '#000000', 'outline_width': '1'}) + sym1.setExtentBuffer(-13.5) + + renderer = QgsSingleSymbolRenderer(sym1) + poly_layer.setRenderer(renderer) + + mapsettings = QgsMapSettings() + mapsettings.setOutputSize(QSize(400, 400)) + mapsettings.setOutputDpi(96) + mapsettings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857')) + mapsettings.setExtent(QgsRectangle(-13875783.2, 2266009.4, -8690110.7, 6673344.5)) + mapsettings.setLayers([poly_layer]) + + self.assertTrue( + self.render_map_settings_check( + 'negative_buffer_extent', + 'negative_buffer_extent', + mapsettings + ) + ) + if __name__ == "__main__": unittest.main() diff --git a/tests/testdata/control_images/vectorlayerrenderer/expected_buffer_extent/expected_buffer_extent.png b/tests/testdata/control_images/vectorlayerrenderer/expected_buffer_extent/expected_buffer_extent.png new file mode 100644 index 0000000000000000000000000000000000000000..9380ffb80814e74628dd2c91d176bf825b8b93aa GIT binary patch literal 4825 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 literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/vectorlayerrenderer/expected_buffer_extent_zero/expected_buffer_extent_zero.png b/tests/testdata/control_images/vectorlayerrenderer/expected_buffer_extent_zero/expected_buffer_extent_zero.png new file mode 100644 index 0000000000000000000000000000000000000000..ff30b65d25a48330cdc1a89fb396051d71e8e90a GIT binary patch literal 3618 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