def testDecodeArrowType(self): type, ok = QgsSymbolLayerUtils.decodeArrowType(0) self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.ArrowPlain) type, ok = QgsSymbolLayerUtils.decodeArrowType('plain') self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.ArrowPlain) type, ok = QgsSymbolLayerUtils.decodeArrowType(' PLAIN ') self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.ArrowPlain) type, ok = QgsSymbolLayerUtils.decodeArrowType(1) self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.ArrowLeftHalf) type, ok = QgsSymbolLayerUtils.decodeArrowType('lefthalf') self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.ArrowLeftHalf) type, ok = QgsSymbolLayerUtils.decodeArrowType(2) self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.ArrowRightHalf) type, ok = QgsSymbolLayerUtils.decodeArrowType('righthalf') self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.ArrowRightHalf) type, ok = QgsSymbolLayerUtils.decodeArrowType('xxxxx') self.assertFalse(ok) type, ok = QgsSymbolLayerUtils.decodeArrowType(34) self.assertFalse(ok)
def testDecodeArrowHeadType(self): type, ok = QgsSymbolLayerUtils.decodeArrowHeadType(0) self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.HeadSingle) type, ok = QgsSymbolLayerUtils.decodeArrowHeadType('single') self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.HeadSingle) type, ok = QgsSymbolLayerUtils.decodeArrowHeadType(' SINGLE ') self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.HeadSingle) type, ok = QgsSymbolLayerUtils.decodeArrowHeadType(1) self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.HeadReversed) type, ok = QgsSymbolLayerUtils.decodeArrowHeadType('reversed') self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.HeadReversed) type, ok = QgsSymbolLayerUtils.decodeArrowHeadType(2) self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.HeadDouble) type, ok = QgsSymbolLayerUtils.decodeArrowHeadType('double') self.assertTrue(ok) self.assertEqual(type, QgsArrowSymbolLayer.HeadDouble) type, ok = QgsSymbolLayerUtils.decodeArrowHeadType('xxxxx') self.assertFalse(ok) type, ok = QgsSymbolLayerUtils.decodeArrowHeadType(34) self.assertFalse(ok)
def testEncodeDecodeSize(self): s = QSizeF() string = QgsSymbolLayerUtils.encodeSize(s) s2 = QgsSymbolLayerUtils.decodeSize(string) self.assertEqual(s2, s) s = QSizeF(1.5, 2.5) string = QgsSymbolLayerUtils.encodeSize(s) s2 = QgsSymbolLayerUtils.decodeSize(string) self.assertEqual(s2, s) # bad string s2 = QgsSymbolLayerUtils.decodeSize('') self.assertEqual(s2, QSizeF(0, 0))
def testEncodeDecodePoint(self): s = QPointF() string = QgsSymbolLayerUtils.encodePoint(s) s2 = QgsSymbolLayerUtils.decodePoint(string) self.assertEqual(s2, s) s = QPointF(1.5, 2.5) string = QgsSymbolLayerUtils.encodePoint(s) s2 = QgsSymbolLayerUtils.decodePoint(string) self.assertEqual(s2, s) # bad string s2 = QgsSymbolLayerUtils.decodePoint('') self.assertEqual(s2, QPointF())
def testSymbolToFromMimeData(self): """ Test converting symbols to and from mime data """ symbol = QgsMarkerSymbol.createSimple({}) symbol.setColor(QColor(255, 0, 255)) self.assertFalse(QgsSymbolLayerUtils.symbolFromMimeData(None)) self.assertFalse(QgsSymbolLayerUtils.symbolToMimeData(None)) mime = QgsSymbolLayerUtils.symbolToMimeData(symbol) self.assertTrue(mime is not None) symbol2 = QgsSymbolLayerUtils.symbolFromMimeData(mime) self.assertTrue(symbol2 is not None) self.assertEqual(symbol2.color().name(), symbol.color().name())
def categorized(defs, sln, layer, renderer, legendFolder, stylesFolder, layer_alpha): cluster = False defs += """ function categories_%s(feature, value, size, resolution, labelText, labelFont, labelFill) { switch(value.toString()) {""" % sln cats = [] useAnyMapUnits = False for cnt, cat in enumerate(renderer.categories()): legendIcon = QgsSymbolLayerUtils.symbolPreviewPixmap(cat.symbol(), QSize(16, 16)) legendIcon.save(os.path.join(legendFolder, sln + "_" + unicode(cnt) + ".png")) if (cat.value() is not None and cat.value() != ""): categoryStr = "case '%s':" % unicode( cat.value()).replace("'", "\\'") else: categoryStr = "default:" (style, pattern, setPattern, useMapUnits) = (getSymbolAsStyle(cat.symbol(), stylesFolder, layer_alpha, renderer, sln, layer)) if useMapUnits: useAnyMapUnits = True categoryStr += ''' return %s; break;''' % style cats.append(categoryStr) defs += "\n".join(cats) + "}};" style = """ var style = categories_%s(feature, value, size, resolution, labelText, labelFont, labelFill)""" % sln value = getValue(layer, renderer) return (style, pattern, setPattern, value, defs, useAnyMapUnits)
def getLegend(layer, renderer, outputProjectFileName, safeLayerName): if isinstance(renderer, QgsSingleSymbolRenderer): symbol = renderer.symbol() legendIcon = QgsSymbolLayerUtils.symbolPreviewPixmap(symbol, QSize(16, 16)) legendIcon.save(os.path.join(outputProjectFileName, "legend", safeLayerName + ".png")) legend = ('<img src="legend/' + safeLayerName + '.png" /> ') legend += layer.name() else: if isinstance(renderer, QgsCategorizedSymbolRenderer): classes = renderer.categories() elif isinstance(renderer, QgsGraduatedSymbolRenderer): classes = renderer.ranges() elif isinstance(renderer, QgsRuleBasedRenderer): classes = renderer.rootRule().children() legend = layer.name().replace("'", "\\'") + "<br />" legend += "<table>" for cnt, c in enumerate(classes): symbol = c.symbol() legend = iconLegend(symbol, c, outputProjectFileName, safeLayerName, legend, cnt) legend += "</table>" symbol = classes[0].symbol() return (legend, symbol)
def testRingFilter(self): # test filtering rings during rendering s = QgsFillSymbol() s.deleteSymbolLayer(0) hash_line = QgsHashedLineSymbolLayer(True) hash_line.setPlacement(QgsTemplatedLineSymbolLayerBase.Interval) hash_line.setInterval(6) simple_line = QgsSimpleLineSymbolLayer() simple_line.setColor(QColor(0, 255, 0)) simple_line.setWidth(1) line_symbol = QgsLineSymbol() line_symbol.changeSymbolLayer(0, simple_line) hash_line.setSubSymbol(line_symbol) hash_line.setHashLength(10) hash_line.setAverageAngleLength(0) s.appendSymbolLayer(hash_line.clone()) self.assertEqual(s.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.AllRings) s.symbolLayer(0).setRingFilter(QgsLineSymbolLayer.ExteriorRingOnly) self.assertEqual(s.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.ExteriorRingOnly) s2 = s.clone() self.assertEqual(s2.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.ExteriorRingOnly) doc = QDomDocument() context = QgsReadWriteContext() element = QgsSymbolLayerUtils.saveSymbol('test', s, doc, context) s2 = QgsSymbolLayerUtils.loadSymbol(element, context) self.assertEqual(s2.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.ExteriorRingOnly) # rendering test s3 = QgsFillSymbol() s3.deleteSymbolLayer(0) s3.appendSymbolLayer( hash_line.clone()) s3.symbolLayer(0).setRingFilter(QgsLineSymbolLayer.ExteriorRingOnly) g = QgsGeometry.fromWkt('Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))') rendered_image = self.renderGeometry(s3, g) assert self.imageCheck('hashline_exterioronly', 'hashline_exterioronly', rendered_image) s3.symbolLayer(0).setRingFilter(QgsLineSymbolLayer.InteriorRingsOnly) g = QgsGeometry.fromWkt('Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))') rendered_image = self.renderGeometry(s3, g) assert self.imageCheck('hashline_interioronly', 'hashline_interioronly', rendered_image)
def testRingFilter(self): # test filtering rings during rendering s = QgsFillSymbol() s.deleteSymbolLayer(0) marker_line = QgsMarkerLineSymbolLayer(True) marker_line.setPlacement(QgsMarkerLineSymbolLayer.FirstVertex) marker = QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayer.Triangle, 4) marker.setColor(QColor(255, 0, 0)) marker.setStrokeStyle(Qt.NoPen) marker_symbol = QgsMarkerSymbol() marker_symbol.changeSymbolLayer(0, marker) marker_line.setSubSymbol(marker_symbol) s.appendSymbolLayer(marker_line.clone()) self.assertEqual(s.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.AllRings) s.symbolLayer(0).setRingFilter(QgsLineSymbolLayer.ExteriorRingOnly) self.assertEqual(s.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.ExteriorRingOnly) s2 = s.clone() self.assertEqual(s2.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.ExteriorRingOnly) doc = QDomDocument() context = QgsReadWriteContext() element = QgsSymbolLayerUtils.saveSymbol('test', s, doc, context) s2 = QgsSymbolLayerUtils.loadSymbol(element, context) self.assertEqual(s2.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.ExteriorRingOnly) # rendering test s3 = QgsFillSymbol() s3.deleteSymbolLayer(0) s3.appendSymbolLayer( QgsMarkerLineSymbolLayer()) s3.symbolLayer(0).setRingFilter(QgsLineSymbolLayer.ExteriorRingOnly) s3.symbolLayer(0).setAverageAngleLength(0) g = QgsGeometry.fromWkt('Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))') rendered_image = self.renderGeometry(s3, g) assert self.imageCheck('markerline_exterioronly', 'markerline_exterioronly', rendered_image) s3.symbolLayer(0).setRingFilter(QgsLineSymbolLayer.InteriorRingsOnly) g = QgsGeometry.fromWkt('Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))') rendered_image = self.renderGeometry(s3, g) assert self.imageCheck('markerline_interioronly', 'markerline_interioronly', rendered_image)
def testMapUnitScaleFactor(self): # test QgsSymbolLayerUtils::mapUnitScaleFactor() using QgsMapUnitScale ms = QgsMapSettings() ms.setExtent(QgsRectangle(0, 0, 100, 100)) ms.setOutputSize(QSize(100, 50)) ms.setOutputDpi(300) r = QgsRenderContext.fromMapSettings(ms) # renderer scale should be about 1:291937841 c = QgsMapUnitScale() sf = QgsSymbolLayerUtils.mapUnitScaleFactor(r, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(sf, 1.0, places=5) sf = QgsSymbolLayerUtils.mapUnitScaleFactor(r, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(sf, 23.622047, places=5) sf = QgsSymbolLayerUtils.mapUnitScaleFactor(r, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(sf, 2.0, places=5)
def testConvertFromMapUnits(self): # test QgsSymbolLayerUtils::convertToMapUnits() without QgsMapUnitScale ms = QgsMapSettings() ms.setExtent(QgsRectangle(0, 0, 100, 100)) ms.setOutputSize(QSize(100, 50)) ms.setOutputDpi(300) r = QgsRenderContext.fromMapSettings(ms) # renderer scale should be about 1:291937841 size = QgsSymbolLayerUtils.convertFromMapUnits(r, 2, QgsUnitTypes.RenderMapUnits) self.assertEqual(size, 2.0) size = QgsSymbolLayerUtils.convertFromMapUnits(r, 50, QgsUnitTypes.RenderMillimeters) self.assertAlmostEqual(size, 2.1166666666, places=5) size = QgsSymbolLayerUtils.convertFromMapUnits(r, 50, QgsUnitTypes.RenderPoints) self.assertAlmostEqual(size, 6.0000000015, places=5) size = QgsSymbolLayerUtils.convertFromMapUnits(r, 4, QgsUnitTypes.RenderPixels) self.assertAlmostEqual(size, 2.0, places=5)
def testSaveRestore(self): """ Test saving and restoring base symbol layer properties to xml""" layer = QgsSimpleFillSymbolLayer() layer.setEnabled(False) layer.setLocked(True) layer.setRenderingPass(5) symbol = QgsFillSymbol() symbol.changeSymbolLayer(0, layer) doc = QDomDocument("testdoc") elem = QgsSymbolLayerUtils.saveSymbol('test', symbol, doc, QgsReadWriteContext()) restored_symbol = QgsSymbolLayerUtils.loadSymbol(elem, QgsReadWriteContext()) restored_layer = restored_symbol.symbolLayer(0) self.assertFalse(restored_layer.enabled()) self.assertTrue(restored_layer.isLocked()) self.assertEqual(restored_layer.renderingPass(), 5)
def testForceRHR(self): # test forcing right hand rule during rendering s = QgsFillSymbol() s.deleteSymbolLayer(0) s.appendSymbolLayer( QgsSimpleFillSymbolLayer(color=QColor(255, 0, 0), strokeColor=QColor(0, 255, 0))) self.assertFalse(s.forceRHR()) s.setForceRHR(True) self.assertTrue(s.forceRHR()) s.setForceRHR(False) self.assertFalse(s.forceRHR()) s.setForceRHR(True) doc = QDomDocument() context = QgsReadWriteContext() element = QgsSymbolLayerUtils.saveSymbol('test', s, doc, context) s2 = QgsSymbolLayerUtils.loadSymbol(element, context) self.assertTrue(s2.forceRHR()) # rendering test s3 = QgsFillSymbol() s3.deleteSymbolLayer(0) s3.appendSymbolLayer( QgsSimpleFillSymbolLayer(color=QColor(255, 200, 200), strokeColor=QColor(0, 255, 0), strokeWidth=2)) marker_line = QgsMarkerLineSymbolLayer(True) marker_line.setPlacement(QgsMarkerLineSymbolLayer.FirstVertex) marker = QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayer.Triangle, 4) marker.setColor(QColor(255, 0, 0)) marker.setStrokeStyle(Qt.NoPen) marker_symbol = QgsMarkerSymbol() marker_symbol.changeSymbolLayer(0, marker) marker_line.setSubSymbol(marker_symbol) s3.appendSymbolLayer(marker_line) g = QgsGeometry.fromWkt('Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))') rendered_image = self.renderGeometry(s3, g) assert self.imageCheck('force_rhr_off', 'polygon_forcerhr_off', rendered_image) s3.setForceRHR(True) rendered_image = self.renderGeometry(s3, g) assert self.imageCheck('force_rhr_on', 'polygon_forcerhr_on', rendered_image)
def singleSymbol(renderer, stylesFolder, layer_alpha, sln, legendFolder, layer): symbol = renderer.symbol() (style, pattern, setPattern, useMapUnits) = getSymbolAsStyle(symbol, stylesFolder, layer_alpha, renderer, sln, layer) style = "var style = " + style legendIcon = QgsSymbolLayerUtils.symbolPreviewPixmap( symbol, QSize(16, 16)) legendIcon.save(os.path.join(legendFolder, sln + ".png")) value = 'var value = ""' return (style, pattern, setPattern, value, useMapUnits)
def testSaveRestore(self): """ Test saving and restoring base symbol layer properties to xml""" layer = QgsSimpleFillSymbolLayer() layer.setEnabled(False) layer.setLocked(True) layer.setRenderingPass(5) symbol = QgsFillSymbol() symbol.changeSymbolLayer(0, layer) doc = QDomDocument("testdoc") elem = QgsSymbolLayerUtils.saveSymbol('test', symbol, doc, QgsReadWriteContext()) restored_symbol = QgsSymbolLayerUtils.loadSymbol( elem, QgsReadWriteContext()) restored_layer = restored_symbol.symbolLayer(0) self.assertFalse(restored_layer.enabled()) self.assertTrue(restored_layer.isLocked()) self.assertEqual(restored_layer.renderingPass(), 5)
def testPreviewColorRampVerticalFlipped(self): r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255)) pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(100, 200), direction=Qt.Vertical, flipDirection=True) img = QImage(pix) self.assertTrue( self.imageCheck('color_ramp_vertical_flipped', 'color_ramp_vertical_flipped', img))
def testDecodeSldUom(self): """ Test Decodes a SLD unit of measure string to a render unit """ # meter decode = None decode = QgsSymbolLayerUtils.decodeSldUom( "http://www.opengeospatial.org/se/units/metre") self.assertEqual(decode, (QgsUnitTypes.RenderMapUnits, 1000.0)) # foot decode = None decode = QgsSymbolLayerUtils.decodeSldUom( "http://www.opengeospatial.org/se/units/foot") self.assertEqual(decode, (QgsUnitTypes.RenderMapUnits, 304.8)) # pixel decode = None decode = QgsSymbolLayerUtils.decodeSldUom( "http://www.opengeospatial.org/se/units/pixel") self.assertEqual(decode, (QgsUnitTypes.RenderPixels, 1.0))
def testConvertFromMapUnits(self): # test QgsSymbolLayerUtils::convertToMapUnits() without QgsMapUnitScale ms = QgsMapSettings() ms.setExtent(QgsRectangle(0, 0, 100, 100)) ms.setOutputSize(QSize(100, 50)) ms.setOutputDpi(300) r = QgsRenderContext.fromMapSettings(ms) # renderer scale should be about 1:291937841 size = QgsSymbolLayerUtils.convertFromMapUnits( r, 2, QgsUnitTypes.RenderMapUnits) self.assertEqual(size, 2.0) size = QgsSymbolLayerUtils.convertFromMapUnits( r, 50, QgsUnitTypes.RenderMillimeters) self.assertAlmostEqual(size, 2.1166666666, places=5) size = QgsSymbolLayerUtils.convertFromMapUnits( r, 50, QgsUnitTypes.RenderPoints) self.assertAlmostEqual(size, 6.0000000015, places=5) size = QgsSymbolLayerUtils.convertFromMapUnits( r, 4, QgsUnitTypes.RenderPixels) self.assertAlmostEqual(size, 2.0, places=5)
def testMapUnitScaleFactor(self): # test QgsSymbolLayerUtils::mapUnitScaleFactor() using QgsMapUnitScale ms = QgsMapSettings() ms.setExtent(QgsRectangle(0, 0, 100, 100)) ms.setOutputSize(QSize(100, 50)) ms.setOutputDpi(300) r = QgsRenderContext.fromMapSettings(ms) # renderer scale should be about 1:291937841 c = QgsMapUnitScale() sf = QgsSymbolLayerUtils.mapUnitScaleFactor( r, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(sf, 1.0, places=5) sf = QgsSymbolLayerUtils.mapUnitScaleFactor( r, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(sf, 23.622047, places=5) sf = QgsSymbolLayerUtils.mapUnitScaleFactor(r, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(sf, 2.0, places=5)
def testConvertToPainterUnits(self): # test QgsSymbolLayerUtils::convertToPainterUnits() using QgsMapUnitScale ms = QgsMapSettings() ms.setExtent(QgsRectangle(0, 0, 100, 100)) ms.setOutputSize(QSize(100, 50)) ms.setOutputDpi(300) r = QgsRenderContext.fromMapSettings(ms) # renderer scale should be about 1:291937841 # start with no min/max scale c = QgsMapUnitScale() size = QgsSymbolLayerUtils.convertToPainterUnits(r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 1.0, places=5) size = QgsSymbolLayerUtils.convertToPainterUnits(r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 23.622047, places=5) size = QgsSymbolLayerUtils.convertToPainterUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 2.0, places=5) # minimum size greater than the calculated size, so size should be limited to minSizeMM c.minSizeMM = 5 c.minSizeMMEnabled = True size = QgsSymbolLayerUtils.convertToPainterUnits(r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 59.0551181, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToPainterUnits(r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 23.622047, places=5) size = QgsSymbolLayerUtils.convertToPainterUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 2.0, places=5) c.minSizeMMEnabled = False # maximum size less than the calculated size, so size should be limited to maxSizeMM c.maxSizeMM = 0.1 c.maxSizeMMEnabled = True size = QgsSymbolLayerUtils.convertToPainterUnits(r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 1.0, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToPainterUnits(r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 23.622047, places=5) size = QgsSymbolLayerUtils.convertToPainterUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 2.0, places=5)
def testEncodeSldUom(self): """ Test Encodes a SLD unit of measure string to a render unit """ # millimeter encode = None encode = QgsSymbolLayerUtils.encodeSldUom( QgsUnitTypes.RenderMillimeters) self.assertTupleEqual(encode, ('', 3.571428571428571)) # mapunits encode = None encode = QgsSymbolLayerUtils.encodeSldUom(QgsUnitTypes.RenderMapUnits) self.assertTupleEqual( encode, ('http://www.opengeospatial.org/se/units/metre', 0.001)) # meters at scale encode = None encode = QgsSymbolLayerUtils.encodeSldUom( QgsUnitTypes.RenderMetersInMapUnits) self.assertTupleEqual( encode, ('http://www.opengeospatial.org/se/units/metre', 1.0))
def testDashPatternOffset(self): s = QgsLineSymbol.createSimple({'outline_color': '#ff0000', 'outline_width': '0.6'}) s.symbolLayer(0).setDashPatternOffset(1.2) s.symbolLayer(0).setDashPatternOffsetUnit(QgsUnitTypes.RenderPoints) s.symbolLayer(0).setDashPatternOffsetMapUnitScale(QgsMapUnitScale(5, 10)) s2 = s.clone() self.assertEqual(s2.symbolLayer(0).dashPatternOffset(), 1.2) self.assertEqual(s2.symbolLayer(0).dashPatternOffsetUnit(), QgsUnitTypes.RenderPoints) self.assertEqual(s2.symbolLayer(0).dashPatternOffsetMapUnitScale().minScale, 5) self.assertEqual(s2.symbolLayer(0).dashPatternOffsetMapUnitScale().maxScale, 10) doc = QDomDocument() context = QgsReadWriteContext() element = QgsSymbolLayerUtils.saveSymbol('test', s, doc, context) s2 = QgsSymbolLayerUtils.loadSymbol(element, context) self.assertEqual(s2.symbolLayer(0).dashPatternOffset(), 1.2) self.assertEqual(s2.symbolLayer(0).dashPatternOffsetUnit(), QgsUnitTypes.RenderPoints) self.assertEqual(s2.symbolLayer(0).dashPatternOffsetMapUnitScale().minScale, 5) self.assertEqual(s2.symbolLayer(0).dashPatternOffsetMapUnitScale().maxScale, 10)
def testDashTweaks(self): s = QgsLineSymbol.createSimple({ 'outline_color': '#ff0000', 'outline_width': '0.6' }) self.assertFalse(s.symbolLayer(0).alignDashPattern()) self.assertFalse(s.symbolLayer(0).tweakDashPatternOnCorners()) s.symbolLayer(0).setAlignDashPattern(True) s.symbolLayer(0).setTweakDashPatternOnCorners(True) s2 = s.clone() self.assertTrue(s2.symbolLayer(0).alignDashPattern()) self.assertTrue(s2.symbolLayer(0).tweakDashPatternOnCorners()) doc = QDomDocument() context = QgsReadWriteContext() element = QgsSymbolLayerUtils.saveSymbol('test', s, doc, context) s2 = QgsSymbolLayerUtils.loadSymbol(element, context) self.assertTrue(s2.symbolLayer(0).alignDashPattern()) self.assertTrue(s2.symbolLayer(0).tweakDashPatternOnCorners())
def testRingFilter(self): # test filtering rings during rendering s = QgsFillSymbol() s.deleteSymbolLayer(0) s.appendSymbolLayer( QgsSimpleLineSymbolLayer(color=QColor(255, 0, 0), width=2)) self.assertEqual(s.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.AllRings) s.symbolLayer(0).setRingFilter(QgsLineSymbolLayer.ExteriorRingOnly) self.assertEqual(s.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.ExteriorRingOnly) s2 = s.clone() self.assertEqual(s2.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.ExteriorRingOnly) doc = QDomDocument() context = QgsReadWriteContext() element = QgsSymbolLayerUtils.saveSymbol('test', s, doc, context) s2 = QgsSymbolLayerUtils.loadSymbol(element, context) self.assertEqual(s2.symbolLayer(0).ringFilter(), QgsLineSymbolLayer.ExteriorRingOnly) # rendering test s3 = QgsFillSymbol() s3.deleteSymbolLayer(0) s3.appendSymbolLayer( QgsSimpleLineSymbolLayer(color=QColor(255, 0, 0), width=2)) s3.symbolLayer(0).setRingFilter(QgsLineSymbolLayer.ExteriorRingOnly) g = QgsGeometry.fromWkt('Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))') rendered_image = self.renderGeometry(s3, g) assert self.imageCheck('simpleline_exterioronly', 'simpleline_exterioronly', rendered_image) s3.symbolLayer(0).setRingFilter(QgsLineSymbolLayer.InteriorRingsOnly) g = QgsGeometry.fromWkt('Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))') rendered_image = self.renderGeometry(s3, g) assert self.imageCheck('simpleline_interioronly', 'simpleline_interioronly', rendered_image)
def testEncodeDecode(self): # test encoding and decoding QgsMapUnitScale s = QgsMapUnitScale() s.minScale = 100 s.maxScale = 50 s.minSizeMMEnabled = True s.minSizeMM = 3 s.maxSizeMMEnabled = False s.maxSizeMM = 99 encode = QgsSymbolLayerUtils.encodeMapUnitScale(s) r = QgsSymbolLayerUtils.decodeMapUnitScale(encode) self.assertEqual(s, r) # check old style encoding encode = '9,78.3' r = QgsSymbolLayerUtils.decodeMapUnitScale(encode) self.assertAlmostEqual(r.minScale, 1.0 / 9, 3) self.assertAlmostEqual(r.maxScale, 1.0 / 78.3, 3) self.assertFalse(r.minSizeMMEnabled) self.assertEqual(r.minSizeMM, 0) self.assertFalse(r.maxSizeMMEnabled) self.assertEqual(r.maxSizeMM, 0)
def testPixelSizeScaleFactor(self): # test QgsSymbolLayerUtils::pixelSizeScaleFactor() using QgsMapUnitScale ms = QgsMapSettings() ms.setExtent(QgsRectangle(0, 0, 100, 100)) ms.setOutputSize(QSize(100, 50)) ms.setOutputDpi(300) r = QgsRenderContext.fromMapSettings(ms) # renderer scale should be about 1:291937841 # start with no min/max scale c = QgsMapUnitScale() sf = QgsSymbolLayerUtils.pixelSizeScaleFactor(r, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(sf, 0.5, places=5) sf = QgsSymbolLayerUtils.pixelSizeScaleFactor(r, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(sf, 11.8110236, places=5) sf = QgsSymbolLayerUtils.pixelSizeScaleFactor(r, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(sf, 1.0, places=5) # minimum scale greater than the renderer scale, so should be limited to minScale c.minScale = 1 / 150000000.0 sf = QgsSymbolLayerUtils.pixelSizeScaleFactor(r, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(sf, 3.8925045, places=5) # only conversion from mapunits should be affected sf = QgsSymbolLayerUtils.pixelSizeScaleFactor(r, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(sf, 11.811023, places=5) sf = QgsSymbolLayerUtils.pixelSizeScaleFactor(r, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(sf, 1.0, places=5) c.minScale = 0 # maximum scale less than the renderer scale, so should be limited to maxScale c.maxScale = 1 / 350000000.0 sf = QgsSymbolLayerUtils.pixelSizeScaleFactor(r, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(sf, 0.5, places=5) # only conversion from mapunits should be affected sf = QgsSymbolLayerUtils.pixelSizeScaleFactor(r, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(sf, 11.8110236, places=5) sf = QgsSymbolLayerUtils.pixelSizeScaleFactor(r, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(sf, 1.0, places=5)
def iconLegend(symbol, catr, outputProjectFileName, layerName, catLegend, cnt): try: iconSize = (symbol.size() * 4) + 5 except: iconSize = 16 legendIcon = QgsSymbolLayerUtils.symbolPreviewPixmap(symbol, QSize(iconSize, iconSize)) safeLabel = re.sub(r'[\W_]+', '', catr.label()) + unicode(cnt) legendIcon.save(os.path.join(outputProjectFileName, "legend", layerName + "_" + safeLabel + ".png")) catLegend += """<tr><td style="text-align: center;"><img src="legend/""" catLegend += layerName + "_" + safeLabel + """.png" /></td><td>""" catLegend += catr.label().replace("'", "\\'") + "</td></tr>" return catLegend
def test_renderer_frame_rate(self): # renderer without an animated symbol marker_symbol = QgsMarkerSymbol.createSimple({}) renderer = QgsSingleSymbolRenderer(marker_symbol) self.assertEqual(QgsSymbolLayerUtils.rendererFrameRate(renderer), -1) # renderer with an animated symbol marker_symbol = QgsMarkerSymbol() animated_marker = QgsAnimatedMarkerSymbolLayer() animated_marker.setFrameRate(30) marker_symbol.appendSymbolLayer(animated_marker) renderer = QgsSingleSymbolRenderer(marker_symbol) self.assertEqual(QgsSymbolLayerUtils.rendererFrameRate(renderer), 30) # renderer with two animated symbol layers marker_symbol = QgsMarkerSymbol() animated_marker = QgsAnimatedMarkerSymbolLayer() animated_marker.setFrameRate(30) marker_symbol.appendSymbolLayer(animated_marker) animated_marker = QgsAnimatedMarkerSymbolLayer() animated_marker.setFrameRate(60) marker_symbol.appendSymbolLayer(animated_marker) renderer = QgsSingleSymbolRenderer(marker_symbol) self.assertEqual(QgsSymbolLayerUtils.rendererFrameRate(renderer), 60)
def toDomElement(self, domDocument): """ Returns a QDomElement with the object instance settings """ spColumnElement = domDocument.createElement("SpatialField") spColumnElement.setAttribute("name", self._spatialField) spColumnElement.setAttribute("labelField", self._labelField) spColumnElement.setAttribute("itemid", self._itemId) spColumnElement.setAttribute("srid", self._srid) spColumnElement.setAttribute("geomType", self._geomType) spColumnElement.setAttribute('zoomType', self._zoom_type) spColumnElement.setAttribute("zoom", str(self._zoom_level)) symbolElement = domDocument.createElement("Symbol") # Append symbol properties element if self._symbol is not None: prop = self._symbol.properties() QgsSymbolLayerUtils.saveProperties(prop, domDocument, symbolElement) symbolElement.setAttribute("layerType", self._layerType) spColumnElement.appendChild(symbolElement) return spColumnElement
def iconLegend(symbol, catr, outputProjectFileName, layerName, catLegend, cnt): try: iconSize = (symbol.size() * 4) + 5 except Exception: iconSize = 16 legendIcon = QgsSymbolLayerUtils.symbolPreviewPixmap( symbol, QSize(iconSize, iconSize)) safeLabel = re.sub(r'[\W_]+', '', catr.label()) + str(cnt) legendIcon.save( os.path.join(outputProjectFileName, "legend", layerName + "_" + safeLabel + ".png")) catLegend += """<tr><td style="text-align: center;"><img src="legend/""" catLegend += layerName + "_" + safeLabel + """.png" /></td><td>""" catLegend += catr.label().replace("'", "\\'") + "</td></tr>" return catLegend
def create(dom_document): """ Create an instance of the 'SpatialFieldsConfiguration' object from a DOM document. Returns None if the dom_document is invalid. """ from stdm import SpatialFieldMapping dataSourceElem = dom_document.documentElement().firstChildElement("DataSource") if dataSourceElem == None: return None spatialFieldsConfigElement = dataSourceElem.firstChildElement("SpatialFields") spFieldsConfig = SpatialFieldsConfiguration() #Get spatial field mappings spatialFieldMappingList = spatialFieldsConfigElement.elementsByTagName("SpatialField") numItems = spatialFieldMappingList.length() for i in range(numItems): spatialFieldMappingElement = spatialFieldMappingList.item(i).toElement() labelField = spatialFieldMappingElement.attribute("labelField") spatialField = spatialFieldMappingElement.attribute("name") itemId = spatialFieldMappingElement.attribute("itemid") srid = int(spatialFieldMappingElement.attribute("srid")) geomType = spatialFieldMappingElement.attribute("geomType") zoom = float(spatialFieldMappingElement.attribute("zoom")) zoom_type = spatialFieldMappingElement.attribute('zoomType', 'RELATIVE') #Create spatial field mapping spFieldMapping = SpatialFieldMapping(spatialField,labelField) spFieldMapping.setItemId(itemId) spFieldMapping.setSRID(srid) spFieldMapping.setGeometryType(geomType) spFieldMapping.setZoomLevel(zoom) spFieldMapping.zoom_type = zoom_type symbolElement = spatialFieldMappingElement.firstChildElement("Symbol") if not symbolElement is None: layerType = symbolElement.attribute("layerType") layerProps = QgsSymbolLayerUtils.parseProperties(symbolElement) symbolLayer = QgsApplication.symbolLayerRegistry().createSymbolLayer(layerType,layerProps) spFieldMapping.setSymbolLayer(symbolLayer) spFieldsConfig.addSpatialFieldMapping(spFieldMapping) return spFieldsConfig
def test_decode_line_clip(self): """ Test decode line clip """ self.assertEqual(QgsSymbolLayerUtils.decodeLineClipMode(''), (Qgis.LineClipMode.ClipPainterOnly, False)) self.assertEqual(QgsSymbolLayerUtils.decodeLineClipMode('xxx'), (Qgis.LineClipMode.ClipPainterOnly, False)) self.assertEqual(QgsSymbolLayerUtils.decodeLineClipMode(' no '), (Qgis.LineClipMode.NoClipping, True)) self.assertEqual(QgsSymbolLayerUtils.decodeLineClipMode(' NO '), (Qgis.LineClipMode.NoClipping, True)) self.assertEqual( QgsSymbolLayerUtils.decodeLineClipMode(' during_render '), (Qgis.LineClipMode.ClipPainterOnly, True)) self.assertEqual( QgsSymbolLayerUtils.decodeLineClipMode(' DURING_Render '), (Qgis.LineClipMode.ClipPainterOnly, True)) self.assertEqual( QgsSymbolLayerUtils.decodeLineClipMode(' before_render '), (Qgis.LineClipMode.ClipToIntersection, True)) self.assertEqual( QgsSymbolLayerUtils.decodeLineClipMode(' BEFORE_REnder '), (Qgis.LineClipMode.ClipToIntersection, True))
def graduated(layer, renderer, legendFolder, sln, stylesFolder, layer_alpha): cluster = False ranges = [] elseif = "" useAnyMapUnits = False for cnt, ran in enumerate(renderer.ranges()): legendIcon = QgsSymbolLayerUtils.symbolPreviewPixmap( ran.symbol(), QSize(16, 16)) legendIcon.save(os.path.join( legendFolder, sln + "_" + unicode(cnt) + ".png")) (symbolstyle, pattern, setPattern, useMapUnits) = getSymbolAsStyle(ran.symbol(), stylesFolder, layer_alpha, renderer, sln, layer) ranges.append("""%sif (value >= %f && value <= %f) { style = %s }""" % (elseif, ran.lowerValue(), ran.upperValue(), symbolstyle)) elseif = " else " if useMapUnits: useAnyMapUnits = True style = "".join(ranges) value = getValue(layer, renderer) return (style, pattern, setPattern, value, useAnyMapUnits)
def test_mask_symbollayer_preview(self): # # Masks should be visible in previews # p = QgsMarkerSymbol.createSimple({'color': '#fdbf6f', 'size': "7"}) circle_symbol = QgsMarkerSymbol.createSimple({'size': '10'}) mask_layer = QgsMaskMarkerSymbolLayer() mask_layer.setSubSymbol(circle_symbol) p.insertSymbolLayer(0, mask_layer) for control_name, render_function in [ ("as_image", lambda: p.asImage(QSize(64, 64)).save(tmp)), ("as_big_preview", lambda: p.bigSymbolPreviewImage().save(tmp)), ("sl_preview", lambda: QgsSymbolLayerUtils.symbolLayerPreviewIcon( mask_layer, QgsUnitTypes.RenderPixels, QSize(64, 64)).pixmap( QSize(64, 64)).save(tmp)) ]: tmp = getTempfilePath('png') render_function() self.checker.setControlName(control_name) self.checker.setRenderedImage(tmp) self.assertTrue(self.checker.compareImages(control_name))
def parse_xml(self): """Parse the xml file. Returns false if there is failure.""" xml_file = QFile(self._xml_path) if not xml_file.open(QIODevice.ReadOnly): return False document = QDomDocument() if not document.setContent(xml_file): return False xml_file.close() document_element = document.documentElement() if document_element.tagName() != 'qgis_style': return False # Get all the symbols self._symbols = [] symbols_element = document_element.firstChildElement('symbols') symbol_element = symbols_element.firstChildElement() context = QgsReadWriteContext() context.setPathResolver(QgsProject.instance().pathResolver()) while not symbol_element.isNull(): if symbol_element.tagName() == 'symbol': symbol = QgsSymbolLayerUtils.loadSymbol( symbol_element, context) if symbol: self._symbols.append({ 'name': symbol_element.attribute('name'), 'symbol': symbol }) symbol_element = symbol_element.nextSiblingElement() return True
def categorized(defs, sln, layer, renderer, legendFolder, stylesFolder, layer_alpha): cluster = False defs += """ function categories_%s(feature, value, size, resolution, labelText, labelFont, labelFill, bufferColor, bufferWidth, placement) { switch(value.toString()) {""" % sln cats = [] useAnyMapUnits = False for cnt, cat in enumerate(renderer.categories()): legendIcon = QgsSymbolLayerUtils.symbolPreviewPixmap(cat.symbol(), QSize(16, 16)) legendIcon.save(os.path.join(legendFolder, sln + "_" + unicode(cnt) + ".png")) if (cat.value() is not None and cat.value() != ""): categoryStr = "case '%s':" % unicode( cat.value()).replace("'", "\\'") else: categoryStr = "default:" (style, pattern, setPattern, useMapUnits) = (getSymbolAsStyle(cat.symbol(), stylesFolder, layer_alpha, renderer, sln, layer)) if useMapUnits: useAnyMapUnits = True categoryStr += ''' return %s; break;''' % style cats.append(categoryStr) defs += "\n".join(cats) + "}};" style = """ var style = categories_%s(feature, value, size, resolution, labelText, labelFont, labelFill, bufferColor, bufferWidth, placement)""" % sln value = getValue(layer, renderer) return (style, pattern, setPattern, value, defs, useAnyMapUnits)
def testQgsGraduatedSymbolRenderer_1(self): """Test QgsGraduatedSymbolRenderer: Basic get/set functions """ # Create a renderer renderer = QgsGraduatedSymbolRenderer() symbol = createMarkerSymbol() renderer.setSourceSymbol(symbol.clone()) self.assertEqual(symbol.dump(), renderer.sourceSymbol().dump(), "Get/set renderer source symbol") attr = '"value"*"value"' renderer.setClassAttribute(attr) self.assertEqual(attr, renderer.classAttribute(), "Get/set renderer class attribute") for m in ( QgsGraduatedSymbolRenderer.Custom, QgsGraduatedSymbolRenderer.EqualInterval, QgsGraduatedSymbolRenderer.Quantile, QgsGraduatedSymbolRenderer.Jenks, QgsGraduatedSymbolRenderer.Pretty, QgsGraduatedSymbolRenderer.StdDev, ): renderer.setMode(m) self.assertEqual(m, renderer.mode(), "Get/set renderer mode") format = createLabelFormat() renderer.setLabelFormat(format) self.assertEqual( dumpLabelFormat(format), dumpLabelFormat(renderer.labelFormat()), "Get/set renderer label format") ramp = createColorRamp() renderer.setSourceColorRamp(ramp) self.assertEqual( dumpColorRamp(ramp), dumpColorRamp(renderer.sourceColorRamp()), "Get/set renderer color ramp") renderer.setInvertedColorRamp(True) self.assertTrue(renderer.invertedColorRamp(), "Get/set renderer inverted color ramp") renderer.setInvertedColorRamp(False) self.assertFalse(renderer.invertedColorRamp(), "Get/set renderer inverted color ramp") value = '"value"*2' exp = QgsSymbolLayerUtils.fieldOrExpressionToExpression(value) valuestr = QgsSymbolLayerUtils.fieldOrExpressionFromExpression(exp) renderer.setRotationField(value) self.assertEqual(valuestr, renderer.rotationField(), "Get/set renderer rotation field") value = '"value"*3' exp = QgsSymbolLayerUtils.fieldOrExpressionToExpression(value) valuestr = QgsSymbolLayerUtils.fieldOrExpressionFromExpression(exp) renderer.setSizeScaleField(value) self.assertEqual(valuestr, renderer.sizeScaleField(), "Get/set renderer size scale field") renderer.setSourceColorRamp(ramp) self.assertEqual( dumpColorRamp(ramp), dumpColorRamp(renderer.sourceColorRamp()), "Get/set renderer color ramp") for sm in ( QgsSymbol.ScaleArea, QgsSymbol.ScaleDiameter, ): renderer.setScaleMethod(sm) self.assertEqual(str(sm), str(renderer.scaleMethod()), "Get/set renderer scale method") # test for classificatio with varying size renderer.setGraduatedMethod(QgsGraduatedSymbolRenderer.GraduatedSize) renderer.setSourceColorRamp(None) renderer.addClassLowerUpper(0, 2) renderer.addClassLowerUpper(2, 4) renderer.addClassLowerUpper(4, 6) renderer.setSymbolSizes(2, 13) self.assertEqual(renderer.maxSymbolSize(), 13) self.assertEqual(renderer.minSymbolSize(), 2) refSizes = [2, (13 + 2) * .5, 13] ctx = QgsRenderContext() for idx, symbol in enumerate(renderer.symbols2(ctx)): self.assertEqual(symbol.size(), refSizes[idx])
def testPreviewColorRampHorizontalNoCheckboard(self): r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255)) pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(200, 100), drawTransparentBackground=False) img = QImage(pix) self.assertTrue(self.imageCheck('color_ramp_no_check', 'color_ramp_no_check', img))
def testPixelSizeScaleFactor(self): # test QgsSymbolLayerUtils::pixelSizeScaleFactor() using QgsMapUnitScale ms = QgsMapSettings() ms.setExtent(QgsRectangle(0, 0, 100, 100)) ms.setOutputSize(QSize(100, 50)) ms.setOutputDpi(300) r = QgsRenderContext.fromMapSettings(ms) # renderer scale should be about 1:291937841 # start with no min/max scale c = QgsMapUnitScale() sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(sf, 0.5, places=5) sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(sf, 11.8110236, places=5) sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderPoints, c) self.assertAlmostEqual(sf, 33.48006689762, places=5) sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(sf, 1.0, places=5) # minimum scale greater than the renderer scale, so should be limited to minScale c.minScale = 1 / 150000000.0 sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(sf, 3.8925045, places=5) # only conversion from mapunits should be affected sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(sf, 11.811023, places=5) sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderPoints, c) self.assertAlmostEqual(sf, 33.48006689762, places=5) sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(sf, 1.0, places=5) c.minScale = 0 # maximum scale less than the renderer scale, so should be limited to maxScale c.maxScale = 1 / 350000000.0 sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(sf, 0.5, places=5) # only conversion from mapunits should be affected sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(sf, 11.8110236, places=5) sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderPoints, c) self.assertAlmostEqual(sf, 33.48006689762, places=5) sf = QgsSymbolLayerUtils.pixelSizeScaleFactor( r, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(sf, 1.0, places=5)
def testCondenseFillAndOutline(self): """ Test QgsSymbolLayerUtils.condenseFillAndOutline """ self.assertFalse(QgsSymbolLayerUtils.condenseFillAndOutline( None, None)) # not simple fill or line self.assertFalse( QgsSymbolLayerUtils.condenseFillAndOutline( QgsShapeburstFillSymbolLayer(), QgsSimpleLineSymbolLayer())) self.assertFalse( QgsSymbolLayerUtils.condenseFillAndOutline( QgsSimpleFillSymbolLayer(), QgsMarkerLineSymbolLayer())) # simple fill/line fill = QgsSimpleFillSymbolLayer() line = QgsSimpleLineSymbolLayer() # set incompatible settings on outline line.setUseCustomDashPattern(True) self.assertFalse(QgsSymbolLayerUtils.condenseFillAndOutline( fill, line)) line = QgsSimpleLineSymbolLayer() line.setDashPatternOffset(1) self.assertFalse(QgsSymbolLayerUtils.condenseFillAndOutline( fill, line)) line = QgsSimpleLineSymbolLayer() line.setAlignDashPattern(True) self.assertFalse(QgsSymbolLayerUtils.condenseFillAndOutline( fill, line)) line = QgsSimpleLineSymbolLayer() line.setTweakDashPatternOnCorners(True) self.assertFalse(QgsSymbolLayerUtils.condenseFillAndOutline( fill, line)) line = QgsSimpleLineSymbolLayer() line.setTrimDistanceStart(1) self.assertFalse(QgsSymbolLayerUtils.condenseFillAndOutline( fill, line)) line = QgsSimpleLineSymbolLayer() line.setTrimDistanceEnd(1) self.assertFalse(QgsSymbolLayerUtils.condenseFillAndOutline( fill, line)) line = QgsSimpleLineSymbolLayer() line.setDrawInsidePolygon(True) self.assertFalse(QgsSymbolLayerUtils.condenseFillAndOutline( fill, line)) line = QgsSimpleLineSymbolLayer() line.setRingFilter(QgsSimpleLineSymbolLayer.ExteriorRingOnly) self.assertFalse(QgsSymbolLayerUtils.condenseFillAndOutline( fill, line)) line = QgsSimpleLineSymbolLayer() line.setOffset(1) self.assertFalse(QgsSymbolLayerUtils.condenseFillAndOutline( fill, line)) line = QgsSimpleLineSymbolLayer() line.setDataDefinedProperty(QgsSymbolLayer.PropertyTrimEnd, QgsProperty.fromValue(4)) self.assertFalse(QgsSymbolLayerUtils.condenseFillAndOutline( fill, line)) # compatible! line = QgsSimpleLineSymbolLayer() line.setColor(QColor(255, 0, 0)) line.setWidth(1.2) line.setWidthUnit(QgsUnitTypes.RenderPoints) line.setWidthMapUnitScale(QgsMapUnitScale(1, 2)) line.setPenJoinStyle(Qt.MiterJoin) line.setPenStyle(Qt.DashDotDotLine) self.assertTrue(QgsSymbolLayerUtils.condenseFillAndOutline(fill, line)) self.assertEqual(fill.strokeColor(), QColor(255, 0, 0)) self.assertEqual(fill.strokeWidth(), 1.2) self.assertEqual(fill.strokeWidthUnit(), QgsUnitTypes.RenderPoints) self.assertEqual(fill.strokeWidthMapUnitScale(), QgsMapUnitScale(1, 2)) self.assertEqual(fill.penJoinStyle(), Qt.MiterJoin) self.assertEqual(fill.strokeStyle(), Qt.DashDotDotLine)
def testToSize(self): s2, ok = QgsSymbolLayerUtils.toSize(None) self.assertFalse(ok) s2, ok = QgsSymbolLayerUtils.toSize(4) self.assertFalse(ok) s2, ok = QgsSymbolLayerUtils.toSize('4') self.assertFalse(ok) # arrays s2, ok = QgsSymbolLayerUtils.toSize([4]) self.assertFalse(ok) s2, ok = QgsSymbolLayerUtils.toSize([]) self.assertFalse(ok) s2, ok = QgsSymbolLayerUtils.toSize([4, 5, 6]) self.assertFalse(ok) s2, ok = QgsSymbolLayerUtils.toSize([4, 5]) self.assertTrue(ok) self.assertEqual(s2, QSizeF(4, 5)) s2, ok = QgsSymbolLayerUtils.toSize(['4', '5']) self.assertTrue(ok) self.assertEqual(s2, QSizeF(4, 5)) # string values s = QSizeF() string = QgsSymbolLayerUtils.encodeSize(s) s2, ok = QgsSymbolLayerUtils.toSize(string) self.assertTrue(ok) self.assertEqual(s2, s) s = QSizeF(1.5, 2.5) string = QgsSymbolLayerUtils.encodeSize(s) s2, ok = QgsSymbolLayerUtils.toSize(string) self.assertTrue(ok) self.assertEqual(s2, s) # bad string s2, ok = QgsSymbolLayerUtils.toSize('') self.assertFalse(ok) self.assertEqual(s2, QSizeF())
def testColorFromMimeData(self): data = QMimeData() color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data) self.assertFalse(color.isValid()) # color data data.setColorData(QColor(255, 0, 255)) color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data) self.assertTrue(color.isValid()) self.assertEqual(color.name(), '#ff00ff') # should be true regardless of the actual color's opacity -- a QColor object has innate knowledge of the alpha, # so our input color HAS an alpha of 255 self.assertTrue(has_alpha) self.assertEqual(color.alpha(), 255) data.setColorData(QColor(255, 0, 255, 100)) color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data) self.assertTrue(color.isValid()) self.assertEqual(color.name(), '#ff00ff') self.assertEqual(color.alpha(), 100) self.assertTrue(has_alpha) # text data data = QMimeData() data.setText('#ff00ff') color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data) self.assertTrue(color.isValid()) self.assertEqual(color.name(), '#ff00ff') # should be False -- no alpha was specified self.assertFalse(has_alpha) self.assertEqual(color.alpha(), 255) data.setText('#ff00ff66') color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data) self.assertTrue(color.isValid()) self.assertEqual(color.name(), '#ff00ff') self.assertTrue(has_alpha) self.assertEqual(color.alpha(), 102) # "#" is optional data.setText('ff00ff66') color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data) self.assertTrue(color.isValid()) self.assertEqual(color.name(), '#ff00ff') self.assertTrue(has_alpha) self.assertEqual(color.alpha(), 102) data.setText('255,0,255') color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data) self.assertTrue(color.isValid()) self.assertEqual(color.name(), '#ff00ff') self.assertFalse(has_alpha) self.assertEqual(color.alpha(), 255) data.setText('255,0,255,0.5') color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data) self.assertTrue(color.isValid()) self.assertEqual(color.name(), '#ff00ff') self.assertTrue(has_alpha) self.assertEqual(color.alpha(), 128) data.setText('rgba(255,0,255,0.5)') color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data) self.assertTrue(color.isValid()) self.assertEqual(color.name(), '#ff00ff') self.assertTrue(has_alpha) self.assertEqual(color.alpha(), 128) # wrong data type data = QMimeData() data.setImageData(QImage()) color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data) self.assertFalse(color.isValid())
def testPolylineSubstring(self): res = QgsSymbolLayerUtils.polylineSubstring(QPolygonF(), 1, 2) # no crash self.assertFalse(res) res = QgsSymbolLayerUtils.polylineSubstring(QPolygonF(), -1, 2) # no crash self.assertFalse(res) res = QgsSymbolLayerUtils.polylineSubstring(QPolygonF(), 1, -2) # no crash self.assertFalse(res) res = QgsSymbolLayerUtils.polylineSubstring(QPolygonF(), -1, -2) # no crash self.assertFalse(res) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), 0, -110) self.assertEqual([p for p in res], []) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), 0, 110) self.assertEqual( [p for p in res], [QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), -1, -1000) self.assertFalse([p for p in res]) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), 1, -1000) self.assertFalse([p for p in res]) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), -1, 1000) self.assertEqual( [p for p in res], [QPointF(110.0, 12.0), QPointF(111.0, 12.0)]) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), 100000, -10000) self.assertFalse([p for p in res]) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), 1, -109) self.assertEqual([p for p in res], []) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), 1, 109) self.assertEqual( [p for p in res], [QPointF(11.0, 3.0), QPointF(11.0, 12.0), QPointF(110.0, 12.0)]) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), -109, 109) self.assertEqual( [p for p in res], [QPointF(11.0, 3.0), QPointF(11.0, 12.0), QPointF(110.0, 12.0)]) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), 1, -1000) self.assertEqual([p for p in res], []) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), 1, 10) self.assertEqual([p for p in res], [QPointF(11, 3), QPointF(11, 12)]) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), 1, 0) self.assertEqual( [p for p in res], [QPointF(11, 3), QPointF(11, 12), QPointF(111, 12)]) res = QgsSymbolLayerUtils.polylineSubstring( QPolygonF([QPointF(11, 2), QPointF(11, 12), QPointF(111, 12)]), 1, -90) self.assertEqual( [p for p in res], [QPointF(11, 3), QPointF(11, 12), QPointF(21, 12)])
def testConvertToMapUnits(self): # test QgsSymbolLayerUtils::convertToMapUnits() using QgsMapUnitScale ms = QgsMapSettings() ms.setExtent(QgsRectangle(0, 0, 100, 100)) ms.setOutputSize(QSize(100, 50)) ms.setOutputDpi(300) r = QgsRenderContext.fromMapSettings(ms) # renderer scale should be about 1:291937841 # start with no min/max scale c = QgsMapUnitScale() size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertEqual(size, 2.0) size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 47.244094, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 5.66929, QgsUnitTypes.RenderPoints, c) self.assertAlmostEqual(size, 47.2440833, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 4.0, places=5) # minimum size greater than the calculated size, so size should be limited to minSizeMM c.minSizeMM = 5 c.minSizeMMEnabled = True size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 118.1102362, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 47.244094, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 5.66929, QgsUnitTypes.RenderPoints, c) self.assertAlmostEqual(size, 47.2440833, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 4.0, places=5) c.minSizeMMEnabled = False # maximum size less than the calculated size, so size should be limited to maxSizeMM c.maxSizeMM = 0.05 c.maxSizeMMEnabled = True size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 1.1811023622047245, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 47.244094, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 5.66929, QgsUnitTypes.RenderPoints, c) self.assertAlmostEqual(size, 47.2440833, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 4.0, places=5) c.maxSizeMMEnabled = False # test with minimum scale set c.minScale = 1 / 150000000.0 size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 15.57001821, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 47.244094, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 5.66929, QgsUnitTypes.RenderPoints, c) self.assertAlmostEqual(size, 47.2440833, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 4.0, places=5) c.minScale = 0 # test with maximum scale set c.maxScale = 1 / 1550000000.0 size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 1.50677595625, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 47.244094, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 5.66929, QgsUnitTypes.RenderPoints, c) self.assertAlmostEqual(size, 47.2440833, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 4.0, places=5) c.maxScale = 0
def run(self): """Run method that performs all the real work""" # project folder qgz_path = QgsProject.instance().fileName() filename = QFileDialog.getSaveFileName(QFileDialog(), "Save Folder", qgz_path, 'QGZ files (*.qgz)') # temporary folder temp_path = tempfile.gettempdir() QgsMessageLog.logMessage("Start", 'embedded SVG', 0) try: # extraction of qgs file with ZipFile(qgz_path, "r") as in_qgz: for f in in_qgz.infolist(): if f.filename.endswith('.qgs'): in_qgz.extract(f.filename, temp_path) datafile = temp_path + "\\" + f.filename with open(datafile, 'r') as f: tree = ET.parse(datafile) root = tree.getroot() # search for layers for symbol in root.iter("layer-tree-layer"): sym_att = symbol.attrib text = json.dumps(str(sym_att), ensure_ascii=False).encode('utf-8') try: if b".shp" not in text: continue else: test = text.decode().split("'") matching = [s for s in test if ".shp" in s] layer_paths = [ layer.source() for layer in QgsProject.instance().mapLayers().values() ] for layer in layer_paths: test = matching[0].split("/") if test[-1] in layer: symbol.set("source", layer) for symbol2 in root.iter("datasource"): if test[-1] in symbol2.text and test[ -1] in layer: symbol2.text = layer except Exception as e: QgsMessageLog.logMessage(" search fail: " + str(e), 'embedded SVG', 0) # search for svg filenames for symbol in root.iter("prop"): sym_att = symbol.attrib text = json.dumps(str(sym_att), ensure_ascii=False).encode('utf-8') try: if b".svg" not in text: continue else: test = text.decode().split("'") matching = [s for s in test if ".svg" in s] # SVG Ordner des Alkis Plugins svg_folder = QgsSymbolLayerUtils.listSvgFiles() # search for svg name in svg folder for svg_pic in svg_folder: if matching[0] in svg_pic: image = open(svg_pic, 'r') # encode svg file to base64 and write into qgs image_read = str(image.read()) image_64_encode = base64.b64encode( image_read.encode("utf-8")) image_64_encode_str = str(image_64_encode, "utf-8") encoded_svg = "base64:" + image_64_encode_str symbol.set("v", encoded_svg) except Exception as e: QgsMessageLog.logMessage(" search fail: " + str(e), 'embedded SVG', 0) tree.write(datafile) file_paths = [] # new zipfile for new qgs file with ZipFile(filename[0][:-4] + ".qgz", 'w') as zip: # with ZipFile(qgz_path[:-4] + "_svg_embedded.qgz", 'w') as zip: zip.write(datafile, basename(datafile)) os.remove(datafile) QgsMessageLog.logMessage("Finish", 'embedded SVG', 0) except Exception as e: QgsMessageLog.logMessage(" search fail: " + str(e), 'embedded SVG', 0)
def testConvertToMapUnits(self): # test QgsSymbolLayerUtils::convertToMapUnits() using QgsMapUnitScale ms = QgsMapSettings() ms.setExtent(QgsRectangle(0, 0, 100, 100)) ms.setOutputSize(QSize(100, 50)) ms.setOutputDpi(300) r = QgsRenderContext.fromMapSettings(ms) # renderer scale should be about 1:291937841 # start with no min/max scale c = QgsMapUnitScale() size = QgsSymbolLayerUtils.convertToMapUnits( r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertEqual(size, 2.0) size = QgsSymbolLayerUtils.convertToMapUnits( r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 47.244094, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 4.0, places=5) # minimum size greater than the calculated size, so size should be limited to minSizeMM c.minSizeMM = 5 c.minSizeMMEnabled = True size = QgsSymbolLayerUtils.convertToMapUnits( r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 118.1102362, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToMapUnits( r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 47.244094, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 4.0, places=5) c.minSizeMMEnabled = False # maximum size less than the calculated size, so size should be limited to maxSizeMM c.maxSizeMM = 0.05 c.maxSizeMMEnabled = True size = QgsSymbolLayerUtils.convertToMapUnits( r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 1.1811023622047245, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToMapUnits( r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 47.244094, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 4.0, places=5) c.maxSizeMMEnabled = False # test with minimum scale set c.minScale = 1 / 150000000.0 size = QgsSymbolLayerUtils.convertToMapUnits( r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 15.57001821, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToMapUnits( r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 47.244094, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 4.0, places=5) c.minScale = 0 # test with maximum scale set c.maxScale = 1 / 1550000000.0 size = QgsSymbolLayerUtils.convertToMapUnits( r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 1.50677595625, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToMapUnits( r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 47.244094, places=5) size = QgsSymbolLayerUtils.convertToMapUnits(r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 4.0, places=5) c.maxScale = 0
def fetch_values_from_layer(self): # pylint: disable=too-many-locals, too-many-branches, too-many-statements """ (Re)fetches plot values from the source layer. """ # Note: we keep things nice and efficient and only iterate a single time over the layer! if not self.context_generator: context = QgsExpressionContext() context.appendScopes( QgsExpressionContextUtils.globalProjectLayerScopes( self.source_layer)) else: context = self.context_generator.createExpressionContext() # add a new scope corresponding to the source layer -- this will potentially overwrite any other # layer scopes which may be present in the context (e.g. from atlas layers), but we need to ensure # that source layer fields and attributes are present in the context context.appendScope( self.source_layer.createExpressionContextScope()) self.settings.data_defined_properties.prepare(context) self.fetch_layout_properties(context) def add_source_field_or_expression(field_or_expression): field_index = self.source_layer.fields().lookupField( field_or_expression) if field_index == -1: expression = QgsExpression(field_or_expression) if not expression.hasParserError(): expression.prepare(context) return expression, expression.needsGeometry( ), expression.referencedColumns() return None, False, {field_or_expression} x_expression, x_needs_geom, x_attrs = add_source_field_or_expression(self.settings.properties['x_name']) if \ self.settings.properties[ 'x_name'] else (None, False, set()) y_expression, y_needs_geom, y_attrs = add_source_field_or_expression(self.settings.properties['y_name']) if \ self.settings.properties[ 'y_name'] else (None, False, set()) z_expression, z_needs_geom, z_attrs = add_source_field_or_expression(self.settings.properties['z_name']) if \ self.settings.properties[ 'z_name'] else (None, False, set()) additional_info_expression, additional_needs_geom, additional_attrs = add_source_field_or_expression( self.settings.layout['additional_info_expression'] ) if self.settings.layout['additional_info_expression'] else (None, False, set()) attrs = set().union( self.settings.data_defined_properties.referencedFields(), x_attrs, y_attrs, z_attrs, additional_attrs) request = QgsFeatureRequest() if self.settings.data_defined_properties.property( PlotSettings.PROPERTY_FILTER).isActive(): expression = self.settings.data_defined_properties.property( PlotSettings.PROPERTY_FILTER).asExpression() request.setFilterExpression(expression) request.setExpressionContext(context) request.setSubsetOfAttributes(attrs, self.source_layer.fields()) if not x_needs_geom and not y_needs_geom and not z_needs_geom and not additional_needs_geom and not self.settings.data_defined_properties.hasActiveProperties( ): request.setFlags(QgsFeatureRequest.NoGeometry) visible_geom_engine = None if self.visible_features_only and self.visible_region is not None: ct = QgsCoordinateTransform( self.visible_region.crs(), self.source_layer.crs(), QgsProject.instance().transformContext()) try: rect = ct.transformBoundingBox(self.visible_region) request.setFilterRect(rect) except QgsCsException: pass elif self.visible_features_only and self.polygon_filter is not None: ct = QgsCoordinateTransform( self.polygon_filter.crs(), self.source_layer.crs(), QgsProject.instance().transformContext()) try: rect = ct.transformBoundingBox( self.polygon_filter.geometry.boundingBox()) request.setFilterRect(rect) g = self.polygon_filter.geometry g.transform(ct) visible_geom_engine = QgsGeometry.createGeometryEngine( g.constGet()) visible_geom_engine.prepareGeometry() except QgsCsException: pass if self.selected_features_only: it = self.source_layer.getSelectedFeatures(request) else: it = self.source_layer.getFeatures(request) # Some plot types don't draw individual glyphs for each feature, but aggregate them instead. # In that case it doesn't make sense to evaluate expressions for settings like marker size or color for each # feature. Instead, the evaluation should be executed only once for these settings. aggregating = self.settings.plot_type in ['box', 'histogram'] executed = False xx = [] yy = [] zz = [] additional_hover_text = [] marker_sizes = [] colors = [] stroke_colors = [] stroke_widths = [] for f in it: if visible_geom_engine and not visible_geom_engine.intersects( f.geometry().constGet()): continue self.settings.feature_ids.append(f.id()) context.setFeature(f) x = None if x_expression: x = x_expression.evaluate(context) if x == NULL or x is None: continue elif self.settings.properties['x_name']: x = f[self.settings.properties['x_name']] if x == NULL or x is None: continue y = None if y_expression: y = y_expression.evaluate(context) if y == NULL or y is None: continue elif self.settings.properties['y_name']: y = f[self.settings.properties['y_name']] if y == NULL or y is None: continue z = None if z_expression: z = z_expression.evaluate(context) if z == NULL or z is None: continue elif self.settings.properties['z_name']: z = f[self.settings.properties['z_name']] if z == NULL or z is None: continue if additional_info_expression: additional_hover_text.append( additional_info_expression.evaluate(context)) elif self.settings.layout['additional_info_expression']: additional_hover_text.append( f[self.settings.layout['additional_info_expression']]) if x is not None: xx.append(x) if y is not None: yy.append(y) if z is not None: zz.append(z) if self.settings.data_defined_properties.isActive( PlotSettings.PROPERTY_MARKER_SIZE): default_value = self.settings.properties['marker_size'] context.setOriginalValueVariable(default_value) value, _ = self.settings.data_defined_properties.valueAsDouble( PlotSettings.PROPERTY_MARKER_SIZE, context, default_value) marker_sizes.append(value) if self.settings.data_defined_properties.isActive( PlotSettings.PROPERTY_STROKE_WIDTH): default_value = self.settings.properties['marker_width'] context.setOriginalValueVariable(default_value) value, _ = self.settings.data_defined_properties.valueAsDouble( PlotSettings.PROPERTY_STROKE_WIDTH, context, default_value) stroke_widths.append(value) if self.settings.data_defined_properties.isActive( PlotSettings.PROPERTY_COLOR) and (not aggregating or not executed): default_value = QColor(self.settings.properties['in_color']) value, conversion_success = self.settings.data_defined_properties.valueAsColor( PlotSettings.PROPERTY_COLOR, context, default_value) if conversion_success: # We were given a valid color specification, use that color colors.append(value.name()) else: try: # Attempt to interpret the value as a list of color specifications value_list = self.settings.data_defined_properties.value( PlotSettings.PROPERTY_COLOR, context) color_list = [ QgsSymbolLayerUtils.decodeColor(item).name() for item in value_list ] colors.extend(color_list) except TypeError: # Not a list of color specifications, use the default color instead colors.append(default_value.name()) if self.settings.data_defined_properties.isActive( PlotSettings.PROPERTY_STROKE_COLOR) and (not aggregating or not executed): default_value = QColor(self.settings.properties['out_color']) value, conversion_success = self.settings.data_defined_properties.valueAsColor( PlotSettings.PROPERTY_STROKE_COLOR, context, default_value) if conversion_success: # We were given a valid color specification, use that color stroke_colors.append(value.name()) else: try: # Attempt to interpret the value as a list of color specifications value_list = self.settings.data_defined_properties.value( PlotSettings.PROPERTY_STROKE_COLOR, context) color_list = [ QgsSymbolLayerUtils.decodeColor(item).name() for item in value_list ] stroke_colors.extend(color_list) except TypeError: # Not a list of color specifications, use the default color instead stroke_colors.append(default_value.name()) executed = True self.settings.additional_hover_text = additional_hover_text self.settings.x = xx self.settings.y = yy self.settings.z = zz if marker_sizes: self.settings.data_defined_marker_sizes = marker_sizes if colors: self.settings.data_defined_colors = colors if stroke_colors: self.settings.data_defined_stroke_colors = stroke_colors if stroke_widths: self.settings.data_defined_stroke_widths = stroke_widths
def testConvertToPainterUnits(self): # test QgsSymbolLayerUtils::convertToPainterUnits() using QgsMapUnitScale ms = QgsMapSettings() ms.setExtent(QgsRectangle(0, 0, 100, 100)) ms.setOutputSize(QSize(100, 50)) ms.setOutputDpi(300) r = QgsRenderContext.fromMapSettings(ms) # renderer scale should be about 1:291937841 # start with no min/max scale c = QgsMapUnitScale() size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 1.0, places=5) size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 23.622047, places=5) size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderPoints, c) self.assertAlmostEqual(size, 66.9601332, places=5) size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 2.0, places=5) # minimum size greater than the calculated size, so size should be limited to minSizeMM c.minSizeMM = 5 c.minSizeMMEnabled = True size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 59.0551181, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 23.622047, places=5) size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderPoints, c) self.assertAlmostEqual(size, 66.9601332, places=5) size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 2.0, places=5) c.minSizeMMEnabled = False # maximum size less than the calculated size, so size should be limited to maxSizeMM c.maxSizeMM = 0.1 c.maxSizeMMEnabled = True size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderMapUnits, c) self.assertAlmostEqual(size, 1.0, places=5) # only conversion from mapunits should be affected size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderMillimeters, c) self.assertAlmostEqual(size, 23.622047, places=5) size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderPoints, c) self.assertAlmostEqual(size, 66.9601332, places=5) size = QgsSymbolLayerUtils.convertToPainterUnits( r, 2, QgsUnitTypes.RenderPixels, c) self.assertAlmostEqual(size, 2.0, places=5)