def setUp(self): self.iface = get_iface() myShpFile = os.path.join(TEST_DATA_DIR, "rectangles.shp") layer = QgsVectorLayer(myShpFile, "Points", "ogr") QgsMapLayerRegistry.instance().addMapLayer(layer) # Create rulebased style sym1 = QgsFillSymbol.createSimple({"color": "#fdbf6f"}) sym2 = QgsFillSymbol.createSimple({"color": "#71bd6c"}) sym3 = QgsFillSymbol.createSimple({"color": "#1f78b4"}) self.r1 = QgsRuleBasedRenderer.Rule(sym1, 0, 0, '"id" = 1') self.r2 = QgsRuleBasedRenderer.Rule(sym2, 0, 0, '"id" = 2') self.r3 = QgsRuleBasedRenderer.Rule(sym3, 0, 0, "ELSE") self.rootrule = QgsRuleBasedRenderer.Rule(None) self.rootrule.appendChild(self.r1) self.rootrule.appendChild(self.r2) self.rootrule.appendChild(self.r3) self.renderer = QgsRuleBasedRenderer(self.rootrule) layer.setRenderer(self.renderer) self.mapsettings = self.iface.mapCanvas().mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-163, 22, -70, 52)) rendered_layers = [layer.id()] self.mapsettings.setLayers(rendered_layers)
def setUp(self): myShpFile = os.path.join(TEST_DATA_DIR, 'rectangles.shp') layer = QgsVectorLayer(myShpFile, 'Points', 'ogr') QgsProject.instance().addMapLayer(layer) # Create rulebased style sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'}) sym2 = QgsFillSymbol.createSimple({'color': '#71bd6c', 'outline_color': 'black'}) sym3 = QgsFillSymbol.createSimple({'color': '#1f78b4', 'outline_color': 'black'}) self.r1 = QgsRuleBasedRenderer.Rule(sym1, 0, 0, '"id" = 1') self.r2 = QgsRuleBasedRenderer.Rule(sym2, 0, 0, '"id" = 2') self.r3 = QgsRuleBasedRenderer.Rule(sym3, 0, 0, 'ELSE') rootrule = QgsRuleBasedRenderer.Rule(None) rootrule.appendChild(self.r1) rootrule.appendChild(self.r2) rootrule.appendChild(self.r3) layer.setRenderer(QgsRuleBasedRenderer(rootrule)) self.mapsettings = QgsMapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-163, 22, -70, 52)) rendered_layers = [layer] self.mapsettings.setLayers(rendered_layers)
def testWillRenderFeatureNestedElse(self): vl = self.mapsettings.layers()[0] ft = vl.getFeature(0) # 'id' = 1 ctx = QgsRenderContext.fromMapSettings(self.mapsettings) ctx.expressionContext().setFeature(ft) # Create rulebased style sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'}) sym2 = QgsFillSymbol.createSimple({'color': '#71bd6c', 'outline_color': 'black'}) sym3 = QgsFillSymbol.createSimple({'color': '#1f78b4', 'outline_color': 'black'}) self.rx1 = QgsRuleBasedRenderer.Rule(sym1, 0, 0, '"id" = 1') self.rx2 = QgsRuleBasedRenderer.Rule(sym2, 0, 0, '"id" = 2') self.rx3 = QgsRuleBasedRenderer.Rule(sym3, 0, 0, 'ELSE') self.rx3.appendChild(self.rx1) rootrule = QgsRuleBasedRenderer.Rule(None) rootrule.appendChild(self.rx2) rootrule.appendChild(self.rx3) vl.setRenderer(QgsRuleBasedRenderer(rootrule)) renderer = vl.renderer() # Reunder with else rule and all activated renderer.startRender(ctx, vl.fields()) self.assertTrue(renderer.willRenderFeature(ft, ctx)) renderer.stopRender(ctx) # Reunder with else rule where else is deactivated renderer.rootRule().children()[1].setActive(False) renderer.startRender(ctx, vl.fields()) self.assertFalse(renderer.willRenderFeature(ft, ctx)) renderer.stopRender(ctx)
def setUp(self): self.iface = get_iface() polys_shp = os.path.join(TEST_DATA_DIR, 'polys.shp') points_shp = os.path.join(TEST_DATA_DIR, 'points.shp') lines_shp = os.path.join(TEST_DATA_DIR, 'lines.shp') self.polys_layer = QgsVectorLayer(polys_shp, 'Polygons', 'ogr') self.points_layer = QgsVectorLayer(points_shp, 'Points', 'ogr') self.lines_layer = QgsVectorLayer(lines_shp, 'Lines', 'ogr') QgsProject.instance().addMapLayer(self.polys_layer) QgsProject.instance().addMapLayer(self.lines_layer) QgsProject.instance().addMapLayer(self.points_layer) # Create style sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'}) sym2 = QgsLineSymbol.createSimple({'color': '#fdbf6f'}) sym3 = QgsMarkerSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'}) self.polys_layer.setRenderer(QgsSingleSymbolRenderer(sym1)) self.lines_layer.setRenderer(QgsSingleSymbolRenderer(sym2)) self.points_layer.setRenderer(QgsSingleSymbolRenderer(sym3)) self.mapsettings = self.iface.mapCanvas().mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-133, 22, -70, 52))
def testReadWriteXml(self): pr = QgsProject() l = QgsLayout(pr) p = QPolygonF() p.append(QPointF(0.0, 0.0)) p.append(QPointF(100.0, 0.0)) p.append(QPointF(200.0, 100.0)) shape = QgsLayoutItemPolygon(p, l) props = {} props["color"] = "green" props["style"] = "solid" props["style_border"] = "solid" props["color_border"] = "red" props["width_border"] = "10.0" props["joinstyle"] = "miter" style = QgsFillSymbol.createSimple(props) shape.setSymbol(style) #save original item to xml doc = QDomDocument("testdoc") elem = doc.createElement("test") self.assertTrue(shape.writeXml(elem, doc, QgsReadWriteContext())) shape2 = QgsLayoutItemPolygon(l) self.assertTrue(shape2.readXml(elem.firstChildElement(), doc, QgsReadWriteContext())) self.assertEqual(shape2.nodes(), shape.nodes()) self.assertEqual(shape2.symbol().symbolLayer(0).color().name(), '#008000') self.assertEqual(shape2.symbol().symbolLayer(0).strokeColor().name(), '#ff0000')
def testSize(self): """ test that map canvas annotation item size is correct """ a = QgsTextAnnotation() a.setFrameSize(QSizeF(300, 200)) a.setHasFixedMapPosition(False) a.setFillSymbol(QgsFillSymbol.createSimple({'color': 'blue', 'width_border': '0'})) canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) canvas.show() canvas.setExtent(QgsRectangle(10, 30, 20, 35)) i = QgsMapCanvasAnnotationItem(a, canvas) self.assertAlmostEqual(i.boundingRect().width(), 300, 1) self.assertAlmostEqual(i.boundingRect().height(), 200, 1) a.setHasFixedMapPosition(True) a.setFrameOffsetFromReferencePoint(QPointF(0, 0)) self.assertAlmostEqual(i.boundingRect().width(), 300, -1) self.assertAlmostEqual(i.boundingRect().height(), 200, -1) a.setFrameOffsetFromReferencePoint(QPointF(10, 20)) self.assertAlmostEqual(i.boundingRect().width(), 310, -1) self.assertAlmostEqual(i.boundingRect().height(), 220, -1)
def test_3(self): sym = self.lines_layer.renderer().symbol() # double headed sym_layer = QgsArrowSymbolLayer.create( { "arrow_width": "7", "head_length": "6", "head_thickness": "8", "head_type": "0", "arrow_type": "1", "is_curved": "0", } ) fill_sym = QgsFillSymbol.createSimple( {"color": "#8bcfff", "outline_color": "#000000", "outline_style": "solid", "outline_width": "1"} ) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() ms = self.mapsettings ms.setExtent(QgsRectangle(-101, 35, -99, 37)) renderchecker.setMapSettings(ms) renderchecker.setControlName("expected_arrowsymbollayer_3") self.assertTrue(renderchecker.runTest("arrowsymbollayer_3"))
def setUp(self): self.iface = get_iface() polys_shp = os.path.join(TEST_DATA_DIR, "polys.shp") points_shp = os.path.join(TEST_DATA_DIR, "points.shp") lines_shp = os.path.join(TEST_DATA_DIR, "lines.shp") self.polys_layer = QgsVectorLayer(polys_shp, "Polygons", "ogr") self.points_layer = QgsVectorLayer(points_shp, "Points", "ogr") self.lines_layer = QgsVectorLayer(lines_shp, "Lines", "ogr") QgsMapLayerRegistry.instance().addMapLayer(self.polys_layer) QgsMapLayerRegistry.instance().addMapLayer(self.lines_layer) QgsMapLayerRegistry.instance().addMapLayer(self.points_layer) # Create style sym1 = QgsFillSymbol.createSimple({"color": "#fdbf6f"}) sym2 = QgsLineSymbol.createSimple({"color": "#fdbf6f"}) sym3 = QgsMarkerSymbol.createSimple({"color": "#fdbf6f"}) self.polys_layer.setRenderer(QgsSingleSymbolRenderer(sym1)) self.lines_layer.setRenderer(QgsSingleSymbolRenderer(sym2)) self.points_layer.setRenderer(QgsSingleSymbolRenderer(sym3)) self.mapsettings = self.iface.mapCanvas().mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-133, 22, -70, 52))
def testBounds(self): pr = QgsProject() l = QgsLayout(pr) p = QPolygonF() p.append(QPointF(50.0, 30.0)) p.append(QPointF(100.0, 10.0)) p.append(QPointF(200.0, 100.0)) shape = QgsLayoutItemPolygon(p, l) props = {} props["color"] = "green" props["style"] = "solid" props["style_border"] = "solid" props["color_border"] = "red" props["width_border"] = "6.0" props["joinstyle"] = "miter" style = QgsFillSymbol.createSimple(props) shape.setSymbol(style) # scene bounding rect should include symbol outline bounds = shape.sceneBoundingRect() self.assertEqual(bounds.left(), 47.0) self.assertEqual(bounds.right(), 203.0) self.assertEqual(bounds.top(), 7.0) self.assertEqual(bounds.bottom(), 103.0) # rectWithFrame should include symbol outline too bounds = shape.rectWithFrame() self.assertEqual(bounds.left(), -3.0) self.assertEqual(bounds.right(), 153.0) self.assertEqual(bounds.top(), -3.0) self.assertEqual(bounds.bottom(), 93.0)
def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) self.mapSettings = QgsMapSettings() # create composition self.mComposition = QgsComposition(self.mapSettings) self.mComposition.setPaperSize(297, 210) # create polygon = QPolygonF() polygon.append(QPointF(0.0, 0.0)) polygon.append(QPointF(100.0, 0.0)) polygon.append(QPointF(200.0, 100.0)) polygon.append(QPointF(100.0, 200.0)) self.mComposerPolygon = QgsComposerPolygon(polygon, self.mComposition) self.mComposition.addComposerPolygon(self.mComposerPolygon) # style props = {} props["color"] = "green" props["style"] = "solid" props["style_border"] = "solid" props["color_border"] = "black" props["width_border"] = "10.0" props["joinstyle"] = "miter" style = QgsFillSymbol.createSimple(props) self.mComposerPolygon.setPolygonStyleSymbol(style)
def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) # create composition self.layout = QgsLayout(QgsProject.instance()) self.layout.initializeDefaults() # create polygon = QPolygonF() polygon.append(QPointF(0.0, 0.0)) polygon.append(QPointF(100.0, 0.0)) polygon.append(QPointF(200.0, 100.0)) polygon.append(QPointF(100.0, 200.0)) self.polygon = QgsLayoutItemPolygon(polygon, self.layout) self.layout.addLayoutItem(self.polygon) # style props = {} props["color"] = "green" props["style"] = "solid" props["style_border"] = "solid" props["color_border"] = "black" props["width_border"] = "10.0" props["joinstyle"] = "miter" style = QgsFillSymbol.createSimple(props) self.polygon.setSymbol(style)
def testFillSymbol(self): """ test rendering an annotation with fill symbol""" a = QgsTextAnnotation() a.setFrameSize(QSizeF(400, 250)) a.setHasFixedMapPosition(False) a.setFillSymbol(QgsFillSymbol.createSimple({'color': 'blue', 'width_border': '5', 'outline_color': 'black'})) im = self.renderAnnotation(a, QPointF(20, 30)) self.assertTrue(self.imageCheck('annotation_fillstyle', 'annotation_fillstyle', im))
def addParcelleMap(self): ''' Add content in the first page with a map and basic information ''' # First add headers for key, item in list(self.composerTemplates.items()): if 'sticky' in item: self.buildComposerLabel(key, item, 0) # Get feature extent exp = QgsExpression('"geo_parcelle" = \'%s\'' % self.geo_parcelle) request = QgsFeatureRequest(exp) extent = None features = self.layer.getFeatures(request) for feature in features: geom = feature.geometry() peri = geom.length() buf = peri / 20 extent = geom.buffer(buf,5).boundingBox() # Add memory layer to highlight parcelle if extent: if self.redlineLayer: self.mProject.removeMapLayer(self.redlineLayer.id()) crs = self.layer.crs().authid() vl = QgsVectorLayer("Polygon?crs=" + crs, "temporary", "memory") pr = vl.dataProvider() vl.startEditing() pr.addFeatures([f for f in self.layer.getFeatures(request)]) vl.commitChanges() vl.updateExtents() props = vl.renderer().symbol().symbolLayer(0).properties() props['outline_width'] = u'1' props['outline_color'] = u'0,85,255,255' props['outline_style'] = u'solid' props['style'] = u'no' vl.renderer().setSymbol(QgsFillSymbol.createSimple(props)) self.mProject.addMapLayer(vl) self.redlineLayer = vl # Add composer map & to parcelle miLayers = self.mInstance.layers() miLayers.insert( 0, vl ) cm = QgsLayoutItemMap(self.currentComposition) cm.updateBoundingRect() cm.setRect(QRectF(0, 0, 286, 190)) cm.setPos(6,15) cm.setLayers(self.mProject.mapThemeCollection().masterVisibleLayers()) if extent: cm.zoomToExtent(extent) cm.setFrameEnabled(True) cm.setBackgroundEnabled(True) self.currentComposition.addItem(cm)
def testAsMapLayer(self): l = QgsLayout(QgsProject.instance()) l.initializeDefaults() map = QgsLayoutItemMap(l) map.attemptSetSceneRect(QRectF(20, 20, 200, 100)) l.addLayoutItem(map) overviewMap = QgsLayoutItemMap(l) overviewMap.attemptSetSceneRect(QRectF(20, 130, 70, 70)) l.addLayoutItem(overviewMap) # zoom in myRectangle = QgsRectangle(96, -152, 160, -120) map.setExtent(myRectangle) myRectangle2 = QgsRectangle(0, -256, 256, 0) overviewMap.setExtent(myRectangle2) overviewMap.overview().setLinkedMap(map) layer = overviewMap.overview().asMapLayer() self.assertIsNotNone(layer) self.assertTrue(layer.isValid()) self.assertEqual([f.geometry().asWkt() for f in layer.getFeatures()], ['Polygon ((96 -120, 160 -120, 160 -152, 96 -152, 96 -120))']) # check that layer has correct renderer fill_symbol = QgsFillSymbol.createSimple({'color': '#00ff00', 'outline_color': '#ff0000', 'outline_width': '10'}) overviewMap.overview().setFrameSymbol(fill_symbol) layer = overviewMap.overview().asMapLayer() self.assertIsInstance(layer.renderer(), QgsSingleSymbolRenderer) self.assertEqual(layer.renderer().symbol().symbolLayer(0).properties()['color'], '0,255,0,255') self.assertEqual(layer.renderer().symbol().symbolLayer(0).properties()['outline_color'], '255,0,0,255') # test layer blend mode self.assertEqual(layer.blendMode(), QPainter.CompositionMode_SourceOver) overviewMap.overview().setBlendMode(QPainter.CompositionMode_Clear) layer = overviewMap.overview().asMapLayer() self.assertEqual(layer.blendMode(), QPainter.CompositionMode_Clear) # should have no effect overviewMap.setMapRotation(45) layer = overviewMap.overview().asMapLayer() self.assertEqual([f.geometry().asWkt() for f in layer.getFeatures()], ['Polygon ((96 -120, 160 -120, 160 -152, 96 -152, 96 -120))']) map.setMapRotation(15) layer = overviewMap.overview().asMapLayer() self.assertEqual([f.geometry().asWkt(0) for f in layer.getFeatures()], ['Polygon ((93 -129, 155 -112, 163 -143, 101 -160, 93 -129))']) # with reprojection map.setCrs(QgsCoordinateReferenceSystem('EPSG:3875')) layer = overviewMap.overview().asMapLayer() self.assertEqual([f.geometry().asWkt(0) for f in layer.getFeatures()], ['Polygon ((93 -129, 96 -128, 99 -127, 102 -126, 105 -126, 108 -125, 111 -124, 114 -123, 116 -123, 119 -122, 122 -121, 125 -120, 128 -119, 131 -119, 134 -118, 137 -117, 140 -116, 143 -115, 146 -115, 149 -114, 152 -113, 155 -112, 155 -114, 156 -115, 156 -117, 156 -118, 157 -120, 157 -121, 158 -123, 158 -124, 158 -126, 159 -127, 159 -128, 160 -130, 160 -131, 160 -133, 161 -134, 161 -136, 161 -137, 162 -139, 162 -140, 163 -142, 163 -143, 160 -144, 157 -145, 154 -146, 151 -146, 148 -147, 145 -148, 142 -149, 140 -149, 137 -150, 134 -151, 131 -152, 128 -153, 125 -153, 122 -154, 119 -155, 116 -156, 113 -157, 110 -157, 107 -158, 104 -159, 101 -160, 101 -158, 100 -157, 100 -155, 100 -154, 99 -152, 99 -151, 98 -149, 98 -148, 98 -146, 97 -145, 97 -144, 96 -142, 96 -141, 96 -139, 95 -138, 95 -136, 95 -135, 94 -133, 94 -132, 93 -130, 93 -129))']) map.setCrs(overviewMap.crs()) # with invert overviewMap.overview().setInverted(True) layer = overviewMap.overview().asMapLayer() self.assertEqual([f.geometry().asWkt(0) for f in layer.getFeatures()], ['Polygon ((-53 -128, 128 53, 309 -128, 128 -309, -53 -128),(93 -129, 101 -160, 163 -143, 155 -112, 93 -129))'])
def testWillRenderFeatureTwoElse(self): """Regression #21287, also test rulesForFeature since there were no tests any where and I've found a couple of issues""" vl = self.mapsettings.layers()[0] ft = vl.getFeature(0) # 'id' = 1 ctx = QgsRenderContext.fromMapSettings(self.mapsettings) ctx.expressionContext().setFeature(ft) # Create rulebased style sym2 = QgsFillSymbol.createSimple({'color': '#71bd6c', 'outline_color': 'black'}) sym3 = QgsFillSymbol.createSimple({'color': '#1f78b4', 'outline_color': 'black'}) sym4 = QgsFillSymbol.createSimple({'color': '#ff00ff', 'outline_color': 'black'}) self.rx2 = QgsRuleBasedRenderer.Rule(sym2, 0, 0, '"id" = 200') self.rx3 = QgsRuleBasedRenderer.Rule(sym3, 1000, 100000000, 'ELSE') # <<< - match this! self.rx4 = QgsRuleBasedRenderer.Rule(sym4, 0.1, 999, 'ELSE') rootrule = QgsRuleBasedRenderer.Rule(None) rootrule.appendChild(self.rx2) rootrule.appendChild(self.rx3) rootrule.appendChild(self.rx4) # <- failed in regression #21287 vl.setRenderer(QgsRuleBasedRenderer(rootrule)) renderer = vl.renderer() # Render with else rule and all activated renderer.startRender(ctx, vl.fields()) self.assertTrue(renderer.willRenderFeature(ft, ctx)) # No context? All rules self.assertEqual(len(rootrule.rulesForFeature(ft)), 2) self.assertTrue(set(rootrule.rulesForFeature(ft)), set([self.rx3, self.rx4])) # With context: only the matching one self.assertEqual(len(rootrule.rulesForFeature(ft, ctx)), 1) self.assertEqual(rootrule.rulesForFeature(ft, ctx)[0], self.rx3) renderer.stopRender(ctx)
def test_2(self): sym = self.lines_layer.renderer().symbol() # double headed sym_layer = QgsArrowSymbolLayer.create({'arrow_width': '5', 'head_length': '4', 'head_thickness': '6', 'head_type': '2'}) fill_sym = QgsFillSymbol.createSimple({'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1'}) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_arrowsymbollayer_2') self.assertTrue(renderchecker.runTest('arrowsymbollayer_2'))
def testPartCount(self): # Create rulebased style sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'}) renderer = QgsSingleSymbolRenderer(sym1) renderer.symbols(QgsRenderContext())[0].symbolLayers()[0].setDataDefinedProperty(QgsSymbolLayer.PropertyFillColor, QgsProperty.fromExpression('color_rgb( (@geometry_part_count - 1) * 200, 0, 0 )')) self.layer.setRenderer(renderer) # Setup rendering check renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_geometry_part_count') result = renderchecker.runTest('part_geometry_part_count') self.assertTrue(result)
def testSymbolColor(self): # Create rulebased style sym1 = QgsFillSymbol.createSimple({'color': '#ff0000', 'outline_color': 'black'}) renderer = QgsSingleSymbolRenderer(sym1) renderer.symbols(QgsRenderContext())[0].symbolLayers()[0].setDataDefinedProperty(QgsSymbolLayer.PropertyFillColor, QgsProperty.fromExpression('set_color_part( @symbol_color, \'value\', "Value" * 4)')) self.layer.setRenderer(renderer) # Setup rendering check renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_symbol_color_variable') result = renderchecker.runTest('symbol_color_variable', 50) self.assertTrue(result)
def testSymbolColor(self): # Create rulebased style sym1 = QgsFillSymbol.createSimple({"color": "#ff0000"}) renderer = QgsSingleSymbolRenderer(sym1) renderer.symbols()[0].symbolLayers()[0].setDataDefinedProperty( "color", "set_color_part( @symbol_color, 'value', \"Value\" * 4)" ) self.layer.setRenderer(renderer) # Setup rendering check renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName("expected_symbol_color_variable") result = renderchecker.runTest("symbol_color_variable", 50) self.assertTrue(result)
def testPartCount(self): # Create rulebased style sym1 = QgsFillSymbol.createSimple({"color": "#fdbf6f"}) renderer = QgsSingleSymbolRenderer(sym1) renderer.symbols()[0].symbolLayers()[0].setDataDefinedProperty( "color", "color_rgb( (@geometry_part_count - 1) * 200, 0, 0 )" ) self.layer.setRenderer(renderer) # Setup rendering check renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName("expected_geometry_part_count") result = renderchecker.runTest("part_geometry_part_count") self.assertTrue(result)
def test_3(self): sym = self.lines_layer.renderer().symbol() # double headed sym_layer = QgsArrowSymbolLayer.create({'arrow_width': '7', 'head_length': '6', 'head_thickness': '8', 'head_type': '0', 'arrow_type': '1', 'is_curved': '0'}) fill_sym = QgsFillSymbol.createSimple({'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1'}) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() ms = self.mapsettings ms.setExtent(QgsRectangle(-101, 35, -99, 37)) renderchecker.setMapSettings(ms) renderchecker.setControlName('expected_arrowsymbollayer_3') self.assertTrue(renderchecker.runTest('arrowsymbollayer_3'))
def setUp(self): self.iface = get_iface() myShpFile = os.path.join(TEST_DATA_DIR, 'polys_overlapping.shp') layer = QgsVectorLayer(myShpFile, 'Polys', 'ogr') QgsProject.instance().addMapLayer(layer) # Create rulebased style sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'}) self.renderer = QgsSingleSymbolRenderer(sym1) layer.setRenderer(self.renderer) rendered_layers = [layer] self.mapsettings = self.iface.mapCanvas().mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-163, 22, -70, 52)) self.mapsettings.setLayers(rendered_layers)
def test_2(self): sym = self.lines_layer.renderer().symbol() # double headed sym_layer = QgsArrowSymbolLayer.create( {"arrow_width": "5", "head_length": "4", "head_thickness": "6", "head_type": "2"} ) fill_sym = QgsFillSymbol.createSimple( {"color": "#8bcfff", "outline_color": "#000000", "outline_style": "solid", "outline_width": "1"} ) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName("expected_arrowsymbollayer_2") self.assertTrue(renderchecker.runTest("arrowsymbollayer_2"))
def test_1(self): sym = self.lines_layer.renderer().symbol() sym_layer = QgsArrowSymbolLayer.create({'head_length': '6.5', 'head_thickness': '6.5'}) dd = QgsProperty.fromExpression("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty(QgsSymbolLayer.PropertyArrowWidth, dd) dd2 = QgsProperty.fromExpression("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty(QgsSymbolLayer.PropertyArrowHeadLength, dd2) dd3 = QgsProperty.fromExpression("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty(QgsSymbolLayer.PropertyArrowHeadThickness, dd3) fill_sym = QgsFillSymbol.createSimple({'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1'}) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_arrowsymbollayer_1') self.assertTrue(renderchecker.runTest('arrowsymbollayer_1'))
def prepareIteratorLayout(self): layer_path = os.path.join(TEST_DATA_DIR, 'france_parts.shp') layer = QgsVectorLayer(layer_path, 'test', "ogr") project = QgsProject() project.addMapLayers([layer]) # select epsg:2154 crs = QgsCoordinateReferenceSystem() crs.createFromSrid(2154) project.setCrs(crs) layout = QgsPrintLayout(project) layout.initializeDefaults() # fix the renderer, fill with green props = {"color": "0,127,0", "outline_width": "4", "outline_color": '255,255,255'} fillSymbol = QgsFillSymbol.createSimple(props) renderer = QgsSingleSymbolRenderer(fillSymbol) layer.setRenderer(renderer) # the atlas map atlas_map = QgsLayoutItemMap(layout) atlas_map.attemptSetSceneRect(QRectF(20, 20, 130, 130)) atlas_map.setFrameEnabled(True) atlas_map.setLayers([layer]) layout.addLayoutItem(atlas_map) # the atlas atlas = layout.atlas() atlas.setCoverageLayer(layer) atlas.setEnabled(True) atlas_map.setExtent( QgsRectangle(332719.06221504929, 6765214.5887386119, 560957.85090677091, 6993453.3774303338)) atlas_map.setAtlasDriven(True) atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Auto) atlas_map.setAtlasMargin(0.10) return project, layout
def test_1(self): sym = self.lines_layer.renderer().symbol() sym_layer = QgsArrowSymbolLayer.create({"head_length": "6.5", "head_thickness": "6.5"}) dd = QgsDataDefined("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty("arrow_width", dd) dd2 = QgsDataDefined("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty("head_length", dd2) dd3 = QgsDataDefined("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty("head_thickness", dd3) fill_sym = QgsFillSymbol.createSimple( {"color": "#8bcfff", "outline_color": "#000000", "outline_style": "solid", "outline_width": "1"} ) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName("expected_arrowsymbollayer_1") self.assertTrue(renderchecker.runTest("arrowsymbollayer_1"))
def testSize(self): """ test that map canvas annotation item size is correct """ a = QgsTextAnnotation() a.setFrameSizeMm(QSizeF(300 / 3.7795275, 200 / 3.7795275)) a.setHasFixedMapPosition(False) a.setFillSymbol(QgsFillSymbol.createSimple({'color': 'blue', 'width_border': '0'})) canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) canvas.show() canvas.setExtent(QgsRectangle(10, 30, 20, 35)) i = QgsMapCanvasAnnotationItem(a, canvas) # ugly, but Travis has different default DPI: if 299 < i.boundingRect().width() < 301: self.assertAlmostEqual(i.boundingRect().width(), 300, 1) self.assertAlmostEqual(i.boundingRect().height(), 200, 1) a.setHasFixedMapPosition(True) a.setFrameOffsetFromReferencePoint(QPointF(0, 0)) self.assertAlmostEqual(i.boundingRect().width(), 300, -1) self.assertAlmostEqual(i.boundingRect().height(), 200, -1) a.setFrameOffsetFromReferencePoint(QPointF(10, 20)) self.assertAlmostEqual(i.boundingRect().width(), 310, -1) self.assertAlmostEqual(i.boundingRect().height(), 220, -1) else: self.assertAlmostEqual(i.boundingRect().width(), 312.5, 1) self.assertAlmostEqual(i.boundingRect().height(), 208.33, 1) a.setHasFixedMapPosition(True) a.setFrameOffsetFromReferencePoint(QPointF(0, 0)) self.assertAlmostEqual(i.boundingRect().width(), 312.5, -1) self.assertAlmostEqual(i.boundingRect().height(), 208.33, -1) a.setFrameOffsetFromReferencePoint(QPointF(10, 20)) self.assertAlmostEqual(i.boundingRect().width(), 322.91, -1) self.assertAlmostEqual(i.boundingRect().height(), 229.166, -1)
def get_style(self): """Get map styles. Get Fill color, label font, outline color. This function takes layer as input and configures style dictionary which is sent as HTTP request in order to adequatly represent map style on GIS Cloud. """ LOGGER.debug('Started map_styles function') if ISQGIS3: self.scale_pixels = \ iface.mapCanvas().mapSettings().outputDpi() / 72 else: self.scale_pixels = \ iface.mapCanvas().mapRenderer().outputDpi() / 72 self.unit_to_px = { "MM": 3.78 * self.scale_pixels, "Point": 1.33 * self.scale_pixels, "Inch": 96 * self.scale_pixels, # these two aren't yet supported by GC rendering, # so defaulting them to value of 1 px "MapUnit": None, "RenderMetersInMapUnits": None } layer_fromlevel = 0 layer_tolevel = 0 if self.qgis_layer.hasScaleBasedVisibility(): dpi = iface.mainWindow().physicalDpiX() max_scale_per_pixel = 156543.04 inches_per_meter = 39.37 factor = dpi * inches_per_meter * max_scale_per_pixel if self.qgis_layer.minimumScale() > 0: layer_fromlevel = int( round( math.log((factor / self.qgis_layer.minimumScale()), 2), 0)) if self.qgis_layer.maximumScale() > 0: layer_tolevel = int( round( math.log((factor / self.qgis_layer.maximumScale()), 2), 0)) if not ISQGIS3: # QGis2 has oposite logic with min/max scales # so we need to switch them (layer_tolevel, layer_fromlevel) = \ (layer_fromlevel, layer_tolevel) styles = [] tmp_dir = self.gc_api.qgis_api.tmp_dir if ISQGIS3: renderer = QgsRuleBasedRenderer.convertFromRenderer( self.qgis_layer.renderer()) else: renderer = QgsRuleBasedRendererV2.convertFromRenderer( self.qgis_layer.rendererV2()) for rule in renderer.rootRule().children(): symbol = rule.symbol() sym_size = 0 if self.layer.type[0] == "point": for layer_sym in symbol.symbolLayers(): temp_style = layer_sym.properties() self.convert_units_to_px(temp_style) if "size" in temp_style and \ float(temp_style["size"]) > sym_size: sym_size = float(temp_style["size"]) is_first_sym = True index = symbol.symbolLayerCount() while index > 0: index = index - 1 layer_sym = symbol.symbolLayer(index) temp_style = layer_sym.properties() self.convert_units_to_px(temp_style) val_label = None # in case of multiple symbolLayers() # labels should be set only once if is_first_sym: if ISQGIS3: if self.qgis_layer.labelsEnabled(): val_label = self.qgis_layer.labeling().settings() else: val_label = QgsPalLayerSettings() val_label.readFromLayer(self.qgis_layer) style = {} line_style = "line_style" line_width = 0 if self.layer.type[0] == "point": size = int(round(sym_size)) + 2 md5 = hashlib.md5() properties = str(temp_style) + self.dump_symbol_properties( layer_sym.subSymbol()) md5.update(properties.encode('utf-8')) symbol_file = "{}_{}.png".format(self.layer.id, md5.hexdigest()) style['iconsoverlap'] = 2 style['url'] = { "full_path": tmp_dir + '/' + symbol_file, "file": symbol_file, "symbol": symbol.clone(), "size": QSize(size, size) } elif self.layer.type[0] == "line": LOGGER.info('entered line_type part of function') LOGGER.info(temp_style) try: if u'line_color' in temp_style: style['color'] = ','.join( temp_style[u'line_color'].split(',')[0:3]) style['bordercolor'] = style['color'] if u'line_width' in temp_style: style['width'] = temp_style[u'line_width'] else: style['width'] = '1' line_width = float(style['width']) except Exception: LOGGER.info( 'Failed while mapping style for line vector layer', exc_info=True) if ('color' or 'bordercolor') not in style: style['color'] = '0,0,0' style['bordercolor'] = '0,0,0' LOGGER.info('Style is{}'.format(style)) # VectorPolygonLayer styles -> dashed line # and offset possibilities elif self.layer.type[0] == "polygon": line_style = "outline_style" has_border = not ("outline_style" in temp_style and temp_style["outline_style"] == "no") if layer_sym.layerType() == 'SimpleFill': if u'outline_color' in temp_style and has_border: style['bordercolor'] = \ ','.join( temp_style[u'outline_color'] .split(',')[0:3]) if u'outline_width' in temp_style and has_border: style['borderwidth'] = temp_style[u'outline_width'] if u'color' in temp_style and \ "style" in temp_style and \ temp_style["style"] == "solid": style['color'] = ','.join( temp_style[u'color'].split(',')[0:3]) elif layer_sym.layerType() == 'SimpleLine': if u'line_color' in temp_style: style['bordercolor'] = \ ','.join( temp_style[u'line_color'] .split(',')[0:3]) if u'line_width' in temp_style: style['line_width'] = temp_style[u'line_width'] elif u'color1' in temp_style: style['color'] = ','.join( temp_style[u'color1'].split(',')[0:3]) style['borderwidth'] = '1' if has_border: style['bordercolor'] = '0,0,0' else: style['bordercolor'] = '0,0,0' if has_border: style['borderwidth'] = '1' style['color'] = '0,0,0' if "borderwidth" in style: line_width = float(style['borderwidth']) if (layer_sym.layerType() != "SimpleFill" and layer_sym.layerType() != "SimpleLine") or \ ("style" in temp_style and not temp_style["style"] in ["solid", "no"]): if layer_sym.layerType() != "SimpleFill": temp_symbol = symbol.clone() tmp_sym_layer = temp_symbol.symbolLayer(index) while temp_symbol.symbolLayerCount() > 1: if temp_symbol.symbolLayer(0) == tmp_sym_layer: temp_symbol.deleteSymbolLayer(1) else: temp_symbol.deleteSymbolLayer(0) else: temp_style_hatch = temp_style.copy() temp_style_hatch["outline_style"] = "no" if ISQGIS3: temp_symbol = QgsFillSymbol.createSimple( temp_style_hatch) else: temp_symbol = QgsFillSymbolV2.createSimple( temp_style_hatch) properties = self.dump_symbol_properties(temp_symbol) md5 = hashlib.md5() md5.update(properties.encode('utf-8')) symbol_file = "{}_{}.png"\ .format(self.layer.id, md5.hexdigest()) style['hatchUrl'] = { "full_path": tmp_dir + '/' + symbol_file, "file": symbol_file, "symbol": temp_symbol, "size": QSize(64, 64) } if "use_custom_dash" in temp_style and \ temp_style["use_custom_dash"] == '1': style['dashed'] = temp_style[u'customdash'].replace( ';', ',') if ("dashed" not in style and line_style in temp_style and not temp_style[line_style] in ["solid", "no"]): process_dash_param(temp_style[line_style], line_width, style) if ISQGIS3: if val_label is not None: label_format = val_label.format() style['fontsize'] = label_format.size() style['labelfield'] = val_label.fieldName.lower() style['fontcolor'] = \ rgb_int2tuple(label_format.color().rgb()) if label_format.buffer().enabled(): style['outline'] = \ rgb_int2tuple( label_format.buffer().color().rgb()) if self.qgis_layer.geometryType() == 1: style['labelfield'] = '' style['textfield'] = val_label.fieldName.lower() if str(label_format.font().family()) in \ self.supported_fonts: style['fontname'] = label_format.font().family() else: style['fontname'] = 'Arial' LOGGER.info( ("Choosen font is not supported, " + "so every font style has been changed " + "to {0}").format(style['fontname'])) self.setup_label_offset(val_label, style) else: if val_label is not None and val_label.enabled: style['fontsize'] = val_label.textFont.pointSize() style['labelfield'] = val_label.fieldName.lower() style['fontcolor'] = rgb_int2tuple( val_label.textColor.rgb()) if val_label.bufferDraw: style['outline'] = rgb_int2tuple( val_label.bufferColor.rgb()) if self.qgis_layer.geometryType() == 1: style['labelfield'] = '' style['textfield'] = val_label.fieldName.lower() if str(val_label.textFont.family()) in \ self.supported_fonts: style['fontname'] = val_label.textFont.family() else: style['fontname'] = 'Arial' LOGGER.info("Choosen font is not supported, so " + "every font style has been changed " + " to {0}".format(style['fontname'])) self.setup_label_offset(val_label, style) if rule.filterExpression(): style['expression'] = rule.filterExpression().replace( '"', '') expression = self.qgis_layer.subsetString().replace('"', '') if expression and expression != '': if 'expression' in style and style['expression'] != '': style['expression'] = "(" + \ style['expression'] + \ ") AND (" + expression + ")" else: style['expression'] = expression if rule.label(): style['label'] = rule.label() style['showlabel'] = 't' \ if val_label is not None and \ 'labelfield' in style \ else 'f' style['visible'] = '1' if self.qgis_layer.hasScaleBasedVisibility(): factor = dpi * inches_per_meter * max_scale_per_pixel if ISQGIS3 and rule.minimumScale() > 0: style['fromlevel'] = \ int(round( math.log((factor / rule.minimumScale()), 2), 0)) elif layer_fromlevel > 0: style['fromlevel'] = layer_fromlevel if ISQGIS3 and rule.maximumScale() > 0: style['tolevel'] = \ int(round( math.log((factor / rule.maximumScale()), 2), 0)) elif layer_tolevel > 0: style['tolevel'] = layer_tolevel if 'borderwidth' in styles and \ style['borderwidth'] and \ float(style['borderwidth']) < 1: style['borderwidth'] = '1' key = "hatchUrl" if "hatchUrl" in style else "url" if key in style: asset = style[key] self.layer.assets.append(asset) LOGGER.info('URL for image upload: {}'.format( asset["file"])) style[key] = '/{}/qgis/map{}/{}'.format( self.gc_api.user.user_md5, self.gc_api.map.map_id, asset["file"]) styles.append(style) is_first_sym = False # all point styles are merged into one as we export the symbol # so it's not required to iterrate symbolLayers() if self.layer.type[0] == "point": break LOGGER.info('Styles function output {}'.format(styles)) LOGGER.debug('Finished map_styles function') return styles
def styleCreator(self, layer, index, id_attr, id_value, spacing, crossX, crossY, scale, color, fontSize, font, fontLL, llcolor, utmcheck): """Getting Input Data For Grid Generation""" grid_spacing = spacing geo_number_x = crossX geo_number_y = crossY fSize = fontSize fontType = font LLfontType = fontLL #Loading feature layer_bound = layer query = '"' + str(id_attr) + '"=' + str(id_value) layer_bound.selectByExpression(query, QgsVectorLayer.SelectBehavior(0)) feature_bound = layer_bound.selectedFeatures()[0] layer_bound.removeSelection() #Getting Feature Source CRS and Geometry if utmcheck: feature_geometry = feature_bound.geometry() bound_UTM = layer_bound.crs().authid() feature_bbox = feature_geometry.boundingBox() bound_UTM_bb = str(feature_bbox).replace(',', '').replace('>', '') # Transforming to Geographic transform_feature = QgsCoordinateTransform( QgsCoordinateReferenceSystem(bound_UTM), QgsCoordinateReferenceSystem('EPSG:4674'), QgsProject.instance()) feature_geometry.transform(transform_feature) bound_sourcecrs = 'EPSG:4674' feature_bbox = feature_geometry.boundingBox() feature_bbox_or = feature_geometry.orientedMinimumBoundingBox() else: feature_geometry = feature_bound.geometry() bound_sourcecrs = layer_bound.crs().authid() feature_bbox = feature_geometry.boundingBox() feature_bbox_or = feature_geometry.orientedMinimumBoundingBox() geo_bound_bb = str(feature_bbox).replace(',', '').replace('>', '') oriented_geo_bb = str(feature_bbox_or).replace(',', '').replace( '>', '').replace('((', '').replace('))', '') #Defining CRSs Transformations inom = feature_bound[index] if inom[0] == 'N': bound_UTM = 'EPSG:319' + str(72 + int(inom[3:5]) - 18) elif inom[0] == 'S': bound_UTM = 'EPSG:319' + str(78 + int(inom[3:5]) - 18) else: iface.messageBar().pushMessage("Error", "Invalid index attribute", level=Qgis.Critical) return trLLUTM = QgsCoordinateTransform( QgsCoordinateReferenceSystem(bound_sourcecrs), QgsCoordinateReferenceSystem(bound_UTM), QgsProject.instance()) trUTMLL = QgsCoordinateTransform( QgsCoordinateReferenceSystem(bound_UTM), QgsCoordinateReferenceSystem(bound_sourcecrs), QgsProject.instance()) #Defining UTM Grid Symbology Type renderer = layer.renderer() properties = {'color': 'black'} grid_symb = QgsFillSymbol.createSimple(properties) symb_out = QgsSimpleFillSymbolLayer() symb_out.setStrokeColor(QColor('black')) symb_out.setFillColor(QColor('white')) symb_out.setStrokeWidth(0.05) """ Creating UTM Grid """ if not utmcheck: geo_UTM = feature_bound.geometry() geo_UTM.transform(trLLUTM) bound_UTM_bb = str(geo_UTM.boundingBox()).replace(',', '').replace( '>', '') xmin_UTM = float(bound_UTM_bb.split()[1]) ymin_UTM = float(bound_UTM_bb.split()[2]) xmax_UTM = float(bound_UTM_bb.split()[3]) ymax_UTM = float(bound_UTM_bb.split()[4]) if grid_spacing > 0: UTM_num_x = floor(xmax_UTM / grid_spacing) - floor( xmin_UTM / grid_spacing) UTM_num_y = floor(ymax_UTM / grid_spacing) - floor( ymin_UTM / grid_spacing) #Generating Vertical Lines for x in range(1, UTM_num_x + 1): grid_symb = self.utm_symb_generator( grid_spacing, trUTMLL, trLLUTM, grid_symb, properties, geo_number_x, geo_number_y, UTM_num_x, UTM_num_y, x, 0, geo_bound_bb, bound_UTM_bb, utmcheck) #Generating Horizontal Lines for y in range(1, UTM_num_y + 1): grid_symb = self.utm_symb_generator( grid_spacing, trUTMLL, trLLUTM, grid_symb, properties, geo_number_x, geo_number_y, UTM_num_x, UTM_num_y, 0, y, geo_bound_bb, bound_UTM_bb, utmcheck) """ Creating Geo Grid """ grid_symb = self.geoGridcreator(grid_symb, geo_bound_bb, geo_number_x, geo_number_y, scale, utmcheck, trLLUTM) """ Rendering UTM and Geographic Grid """ #Changing UTM Grid Color grid_symb.setColor(color) grid_symb.changeSymbolLayer(0, symb_out) #Creating Rule Based Renderer (Rule For The Other Features) properties = {'color': 'white'} ext_grid_symb = QgsFillSymbol.createSimple(properties) symb_ot = QgsRuleBasedRenderer.Rule(ext_grid_symb) symb_ot.setFilterExpression('\"' + str(id_attr) + '\" <> ' + str(id_value)) symb_ot.setLabel('other') #Creating Rule Based Renderer (Rule For The Selected Feature, Root Rule) symb_new = QgsRuleBasedRenderer.Rule(grid_symb) symb_new.setFilterExpression('\"' + str(id_attr) + '\" = ' + str(id_value)) symb_new.setLabel('layer') symb_new.appendChild(symb_ot) #Applying New Renderer render_base = QgsRuleBasedRenderer(symb_new) new_renderer = QgsInvertedPolygonRenderer.convertFromRenderer( render_base) layer_bound.setRenderer(new_renderer) """ Labeling Geo Grid """ if utmcheck: dx = [ 2 * scale * fSize / 1.5, -13.6 * scale * fSize / 1.5, 6 * scale * fSize / 1.5 ] dy = [1.7 * scale * fSize / 1.5, -3.8 * scale * fSize / 1.5] else: dx = [0.000018 * scale, -0.000120 * scale, 0.00005 * scale] dy = [0.000015 * scale, -0.000040 * scale] root_rule = self.geoGridlabelPlacer(geo_bound_bb, geo_number_x, geo_number_y, dx, dy, fSize, LLfontType, trLLUTM, trUTMLL, llcolor, utmcheck, scale) """ Labeling UTM Grid""" if utmcheck: dx = [-2.7, -9.7, -6.2, 5.4] dx = [i * scale * fSize / 1.5 for i in dx] dy = [2.5, -1.7, -0.5, -1.5] dy = [i * scale * fSize / 1.5 for i in dy] dy0 = [5.45, -4.8, -3.2, -4.2] dy0 = [i * scale * fSize / 1.5 for i in dy0] dy1 = [2.15, 1.2] dy1 = [i * scale * fSize / 1.5 for i in dy1] else: dx = [-0.00003, -0.000107, -0.000070, 0.000060] dx = [i * scale * fSize / 1.5 for i in dx] dy = [0.000027, 0.000016, -0.000041, -0.000052] dy = [i * scale * fSize / 1.5 for i in dy] dy0 = [0.0000644, 0.000053, -0.000076, -0.000087] dy0 = [i * scale * fSize / 1.5 for i in dy0] dy1 = [0.000032, 0.000020] dy1 = [i * scale * fSize / 1.5 for i in dy1] root_rule = self.utmGridlabelPlacer( root_rule, grid_spacing, geo_bound_bb, bound_UTM_bb, geo_number_x, geo_number_y, UTM_num_x, UTM_num_y, trUTMLL, trLLUTM, dx, dy, dy0, dy1, fSize, fontType, scale, utmcheck, oriented_geo_bb) """ Activating Labels """ rules = QgsRuleBasedLabeling(root_rule) layer.setLabeling(rules) layer.setLabelsEnabled(True) layer.triggerRepaint() return
def styleCreator(self, feature_geometry, layer_bound, utmSRID, id_attr, id_value, spacing, crossX, crossY, scale, fontSize, font, fontLL, llcolor, linwidth_geo, linwidth_utm, linwidth_buffer_geo, linwidth_buffer_utm, geo_grid_color, utm_grid_color, geo_grid_buffer_color, utm_grid_buffer_color, masks_check): """Getting Input Data For Grid Generation""" linwidth_buffer_utm += linwidth_utm linwidth_buffer_geo += linwidth_geo grid_spacing = spacing geo_number_x = crossX geo_number_y = crossY fSize = fontSize fontType = font LLfontType = fontLL #Defining CRSs Transformations trLLUTM = QgsCoordinateTransform( QgsCoordinateReferenceSystem('EPSG:4326'), QgsCoordinateReferenceSystem('EPSG:' + str(utmSRID)), QgsProject.instance()) trUTMLL = QgsCoordinateTransform( QgsCoordinateReferenceSystem('EPSG:' + str(utmSRID)), QgsCoordinateReferenceSystem('EPSG:4326'), QgsProject.instance()) #Transforming to Geographic and defining bounding boxes feature_bbox = feature_geometry.boundingBox() bound_UTM_bb = str(feature_bbox).replace(',', '').replace('>', '') feature_geometry.transform(trUTMLL) feature_geo_bbox = feature_geometry.boundingBox() feature_bbox_or = feature_geometry.orientedMinimumBoundingBox() geo_bound_bb = str(feature_geo_bbox).replace(',', '').replace('>', '') oriented_geo_bb = str(feature_bbox_or).replace(',', '').replace( '>', '').replace('((', '').replace('))', '') #Defining UTM Grid Symbology Type properties = {'color': 'black'} grid_symb = QgsFillSymbol.createSimple(properties) """ Creating UTM Grid """ extentsUTM = (float(bound_UTM_bb.split()[1]), float(bound_UTM_bb.split()[2]), float(bound_UTM_bb.split()[3]), float(bound_UTM_bb.split()[4])) extentsGeo = (float(geo_bound_bb.split()[1]), float(geo_bound_bb.split()[2]), float(geo_bound_bb.split()[3]), float(geo_bound_bb.split()[4])) if grid_spacing > 0: UTM_num_x = floor(extentsUTM[2] / grid_spacing) - floor( extentsUTM[0] / grid_spacing) UTM_num_y = floor(extentsUTM[3] / grid_spacing) - floor( extentsUTM[1] / grid_spacing) if linwidth_buffer_utm != linwidth_utm: #Generating Buffer Vertical Lines for x in range(1, UTM_num_x + 1): grid_symb = self.utm_Symb_Generator( utmSRID, grid_spacing, trUTMLL, trLLUTM, grid_symb, properties, UTM_num_x, UTM_num_y, x, 0, extentsGeo, extentsUTM, linwidth_buffer_utm, utm_grid_buffer_color) #Generating Buffer Horizontal Lines for y in range(1, UTM_num_y + 1): grid_symb = self.utm_Symb_Generator( utmSRID, grid_spacing, trUTMLL, trLLUTM, grid_symb, properties, UTM_num_x, UTM_num_y, 0, y, extentsGeo, extentsUTM, linwidth_buffer_utm, utm_grid_buffer_color) #Generating Vertical Lines for x in range(1, UTM_num_x + 1): grid_symb = self.utm_Symb_Generator( utmSRID, grid_spacing, trUTMLL, trLLUTM, grid_symb, properties, UTM_num_x, UTM_num_y, x, 0, extentsGeo, extentsUTM, linwidth_utm, utm_grid_color) #Generating Horizontal Lines for y in range(1, UTM_num_y + 1): grid_symb = self.utm_Symb_Generator( utmSRID, grid_spacing, trUTMLL, trLLUTM, grid_symb, properties, UTM_num_x, UTM_num_y, 0, y, extentsGeo, extentsUTM, linwidth_utm, utm_grid_color) """ Creating Geo Grid """ px = (round(extentsGeo[2], 6) - round(extentsGeo[0], 6)) / (geo_number_x + 1) py = (round(extentsGeo[3], 6) - round(extentsGeo[1], 6)) / (geo_number_y + 1) if linwidth_buffer_geo != linwidth_geo: grid_symb = self.geoGridcreator(utmSRID, grid_symb, extentsGeo, px, py, geo_number_x, geo_number_y, scale, trLLUTM, linwidth_buffer_geo, geo_grid_buffer_color) grid_symb = self.geoGridcreator(utmSRID, grid_symb, extentsGeo, px, py, geo_number_x, geo_number_y, scale, trLLUTM, linwidth_geo, geo_grid_color) """ Rendering UTM and Geographic Grid """ #Changing UTM Grid Color grid_symb.deleteSymbolLayer(0) #Creating Rule Based Renderer (Rule For The Selected Feature, Root Rule) symb_new = QgsRuleBasedRenderer.Rule(grid_symb) symb_new.setFilterExpression('\"' + str(id_attr) + '\" = ' + str(id_value)) symb_new.setLabel('layer') #Appending rules to symbol root rule root_symbol_rule = QgsRuleBasedRenderer.Rule(None) root_symbol_rule.setFilterExpression('') root_symbol_rule.appendChild(symb_new) #Applying New Renderer render_base = QgsRuleBasedRenderer(root_symbol_rule) layer_bound.setRenderer(render_base) """Rendering outside area""" #Duplicating original layer layers_names = [ i.name() for i in QgsProject.instance().mapLayers().values() ] if (layer_bound.name() + "_outside") not in layers_names: outside_bound_layer = QgsVectorLayer( layer_bound.source(), layer_bound.name() + "_outside", layer_bound.providerType()) if layer_bound.providerType() == 'memory': feats = [feat for feat in layer_bound.getFeatures()] outside_bound_layer_data = outside_bound_layer.dataProvider() outside_bound_layer_data.addFeatures(feats) QgsProject.instance().addMapLayer(outside_bound_layer) else: outside_bound_layer = QgsProject.instance().mapLayersByName( layer_bound.name() + "_outside")[0] #Creating Rule Based Renderer (Rule For The Other Features) properties = {'color': 'white'} ext_grid_symb = QgsFillSymbol.createSimple(properties) symb_out = QgsSimpleFillSymbolLayer() symb_out.setFillColor(QColor('white')) symb_out.setStrokeWidth(linwidth_utm) ext_grid_symb.changeSymbolLayer(0, symb_out) rule_out = QgsRuleBasedRenderer.Rule(ext_grid_symb) rule_out.setFilterExpression('\"' + str(id_attr) + '\" = ' + str(id_value)) rule_out.setLabel('outside') root_symbol_rule_out = QgsRuleBasedRenderer.Rule(None) root_symbol_rule_out.appendChild(rule_out) render_base_out = QgsRuleBasedRenderer(root_symbol_rule_out) new_renderer = QgsInvertedPolygonRenderer.convertFromRenderer( render_base_out) outside_bound_layer.setRenderer(new_renderer) """ Labeling Geo Grid """ dx = [2.0, -11.0, -8.0, -3.6] dx = [i * scale * fSize / 1.5 for i in dx] dy = [1.7, -3.8, -0.8, -0.8] dy = [i * scale * fSize / 1.5 for i in dy] root_rule = self.geoGridlabelPlacer(extentsGeo, px, py, geo_number_x, geo_number_y, dx, dy, fSize, LLfontType, trLLUTM, llcolor, scale, layer_bound, trUTMLL) """ Labeling UTM Grid""" dx = [-2.9, -2.9, -8.9, 2.0] dx = [i * scale * fSize / 1.5 for i in dx] dy = [1.4, -4.6, -0.5, -1.5] dy = [i * scale * fSize / 1.5 for i in dy] dy0 = [5.0, -7.2, -3.2, -4.2] dy0 = [i * scale * fSize / 1.5 for i in dy0] dy1 = [2.15, 1.2] dy1 = [i * scale * fSize / 1.5 for i in dy1] root_rule = self.utmGridlabelPlacer(root_rule, grid_spacing, extentsGeo, extentsUTM, px, py, UTM_num_x, UTM_num_y, trUTMLL, trLLUTM, dx, dy, dy0, dy1, fSize, fontType, scale, oriented_geo_bb, layer_bound) """ Activating Labels """ rules = QgsRuleBasedLabeling(root_rule) layer_bound.setLabeling(rules) layer_bound.setLabelsEnabled(True) if masks_check: self.apply_masks(layer_bound) layer_bound.triggerRepaint() return
def testBasic(self): props = QgsVectorLayerElevationProperties(None) self.assertEqual(props.zScale(), 1) self.assertEqual(props.zOffset(), 0) self.assertFalse(props.extrusionEnabled()) self.assertEqual(props.extrusionHeight(), 0) self.assertFalse(props.hasElevation()) self.assertEqual(props.clamping(), Qgis.AltitudeClamping.Terrain) self.assertEqual(props.binding(), Qgis.AltitudeBinding.Centroid) props.setZOffset(0.5) props.setZScale(2) props.setClamping(Qgis.AltitudeClamping.Relative) props.setBinding(Qgis.AltitudeBinding.Vertex) props.setExtrusionHeight(10) props.setExtrusionEnabled(True) self.assertEqual(props.zScale(), 2) self.assertEqual(props.zOffset(), 0.5) self.assertEqual(props.extrusionHeight(), 10) self.assertTrue(props.hasElevation()) self.assertTrue(props.extrusionEnabled()) self.assertEqual(props.clamping(), Qgis.AltitudeClamping.Relative) self.assertEqual(props.binding(), Qgis.AltitudeBinding.Vertex) sym = QgsLineSymbol.createSimple({ 'outline_color': '#ff4433', 'outline_width': 0.5 }) props.setProfileLineSymbol(sym) self.assertEqual(props.profileLineSymbol().color().name(), '#ff4433') sym = QgsFillSymbol.createSimple({ 'color': '#ff4455', 'outline_width': 0.5 }) props.setProfileFillSymbol(sym) self.assertEqual(props.profileFillSymbol().color().name(), '#ff4455') sym = QgsMarkerSymbol.createSimple({ 'color': '#ff1122', 'outline_width': 0.5 }) props.setProfileMarkerSymbol(sym) self.assertEqual(props.profileMarkerSymbol().color().name(), '#ff1122') doc = QDomDocument("testdoc") elem = doc.createElement('test') props.writeXml(elem, doc, QgsReadWriteContext()) props2 = QgsVectorLayerElevationProperties(None) props2.readXml(elem, QgsReadWriteContext()) self.assertEqual(props2.zScale(), 2) self.assertEqual(props2.zOffset(), 0.5) self.assertEqual(props2.clamping(), Qgis.AltitudeClamping.Relative) self.assertEqual(props2.binding(), Qgis.AltitudeBinding.Vertex) self.assertEqual(props2.extrusionHeight(), 10) self.assertTrue(props2.extrusionEnabled()) self.assertEqual(props2.profileLineSymbol().color().name(), '#ff4433') self.assertEqual(props2.profileFillSymbol().color().name(), '#ff4455') self.assertEqual(props2.profileMarkerSymbol().color().name(), '#ff1122')
def test_rendered_items(self): canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326')) canvas.setFrameStyle(0) canvas.resize(600, 400) canvas.setCachingEnabled(True) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer.isValid()) layer2 = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer2.isValid()) item = QgsAnnotationPolygonItem( QgsPolygon( QgsLineString([ QgsPoint(11.5, 13), QgsPoint(12, 13), QgsPoint(12, 13.5), QgsPoint(11.5, 13) ]))) item.setSymbol( QgsFillSymbol.createSimple({ 'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2' })) item.setZIndex(1) i1_id = layer.addItem(item) item = QgsAnnotationLineItem( QgsLineString( [QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)])) item.setZIndex(2) i2_id = layer.addItem(item) item = QgsAnnotationMarkerItem(QgsPoint(12, 13)) item.setZIndex(3) i3_id = layer2.addItem(item) layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) layer2.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) canvas.setLayers([layer, layer2]) canvas.setExtent(QgsRectangle(10, 10, 18, 18)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() results = canvas.renderedItemResults() self.assertCountEqual([i.itemId() for i in results.renderedItems()], [i1_id, i2_id, i3_id]) # turn off a layer -- the other layer will be rendered direct from the cached version canvas.setLayers([layer2]) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() results = canvas.renderedItemResults() # only layer2 items should be present in results -- but these MUST be present while layer2 is visible in the canvas, # even though the most recent canvas redraw used a cached version of layer2 and didn't actually have to redraw the layer self.assertEqual([i.itemId() for i in results.renderedItems()], [i3_id]) # turn layer 1 back on canvas.setLayers([layer, layer2]) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() results = canvas.renderedItemResults() # both layer1 and layer2 items should be present in results -- even though NEITHER of these layers were re-rendered, # and instead we used precached renders of both layers self.assertCountEqual([i.itemId() for i in results.renderedItems()], [i1_id, i2_id, i3_id])
def createFillSymbol(): symbol = QgsFillSymbol.createSimple({ "color": "100,150,50" }) return symbol
def createFillSymbol(): symbol = QgsFillSymbol.createSimple({"color": "100,150,50"}) return symbol
def testCase(self): self.TEST_DATA_DIR = unitTestDataPath() tmppath = tempfile.mkdtemp() for file in glob.glob( os.path.join(self.TEST_DATA_DIR, 'france_parts.*')): shutil.copy(os.path.join(self.TEST_DATA_DIR, file), tmppath) vectorFileInfo = QFileInfo(tmppath + "/france_parts.shp") mVectorLayer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") QgsProject.instance().addMapLayers([mVectorLayer]) self.layers = [mVectorLayer] # create layout with layout map # select epsg:2154 crs = QgsCoordinateReferenceSystem() crs.createFromSrid(2154) QgsProject.instance().setCrs(crs) self.layout = QgsPrintLayout(QgsProject.instance()) self.layout.initializeDefaults() # fix the renderer, fill with green props = {"color": "0,127,0", 'outline_color': 'black'} fillSymbol = QgsFillSymbol.createSimple(props) renderer = QgsSingleSymbolRenderer(fillSymbol) mVectorLayer.setRenderer(renderer) # the atlas map self.atlas_map = QgsLayoutItemMap(self.layout) self.atlas_map.attemptSetSceneRect(QRectF(20, 20, 130, 130)) self.atlas_map.setFrameEnabled(True) self.atlas_map.setLayers([mVectorLayer]) self.layout.addLayoutItem(self.atlas_map) # the atlas self.atlas = self.layout.atlas() self.atlas.setCoverageLayer(mVectorLayer) self.atlas.setEnabled(True) # an overview self.overview = QgsLayoutItemMap(self.layout) self.overview.attemptSetSceneRect(QRectF(180, 20, 50, 50)) self.overview.setFrameEnabled(True) self.overview.overview().setLinkedMap(self.atlas_map) self.overview.setLayers([mVectorLayer]) self.layout.addLayoutItem(self.overview) nextent = QgsRectangle(49670.718, 6415139.086, 699672.519, 7065140.887) self.overview.setExtent(nextent) # set the fill symbol of the overview map props2 = {"color": "127,0,0,127", 'outline_color': 'black'} fillSymbol2 = QgsFillSymbol.createSimple(props2) self.overview.overview().setFrameSymbol(fillSymbol2) # header label self.mLabel1 = QgsLayoutItemLabel(self.layout) self.layout.addLayoutItem(self.mLabel1) self.mLabel1.setText("[% \"NAME_1\" %] area") self.mLabel1.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel1.adjustSizeToText() self.mLabel1.attemptSetSceneRect(QRectF(150, 5, 60, 15)) self.mLabel1.setMarginX(1) self.mLabel1.setMarginY(1) # feature number label self.mLabel2 = QgsLayoutItemLabel(self.layout) self.layout.addLayoutItem(self.mLabel2) self.mLabel2.setText( "# [%@atlas_featurenumber || ' / ' || @atlas_totalfeatures%]") self.mLabel2.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel2.adjustSizeToText() self.mLabel2.attemptSetSceneRect(QRectF(150, 200, 60, 15)) self.mLabel2.setMarginX(1) self.mLabel2.setMarginY(1) self.filename_test() self.autoscale_render_test() self.fixedscale_render_test() self.predefinedscales_render_test() self.hidden_render_test() self.legend_test() self.rotation_test() shutil.rmtree(tmppath, True)
def route(self): try: import urllib.request import json origin_dest = [] featurelist = [] if self.dlg.inputpoint.isChecked(): vp_layer = self.dlg.point.currentLayer() countfeat = vp_layer.featureCount() else: vp_layer = iface.activeLayer() vp_layer.commitChanges() countfeat = vp_layer.featureCount() result = processing.run( "native:addautoincrementalfield", { 'INPUT': vp_layer, 'FIELD_NAME': 'id', 'START': 1, 'GROUP_FIELDS': [], 'SORT_EXPRESSION': '\"id\"', 'SORT_ASCENDING': True, 'SORT_NULLS_FIRST': False, 'OUTPUT': 'memory:{0}'.format(self.dlg.route_id.text()) }) QgsProject.instance().removeMapLayer(vp_layer) vp_layer = result['OUTPUT'] QgsProject.instance().addMapLayer(vp_layer) features = vp_layer.getFeatures() points = [] pointdist = [] waypoints = [] # if vp_layer.featureCount() == 2: for feature in vp_layer.getFeatures(): point = feature.geometry().asPoint() xpoint = point.x() ypoint = point.y() Qpoint = QgsPointXY(xpoint, ypoint) points.append(Qpoint) distcheck = 0 if self.dlg.direction.currentText() == 'Start->End': # for i in points: # distance = QgsDistanceArea() # Qpoint1 = i # for j in points: # Qpoint2 = j # dist = distance.measureLine(Qpoint1, Qpoint2) # pointdist.append(dist) # if dist > distcheck: # distcheck = dist self.origin = points[0] self.destination = points[countfeat - 1] # print('End->Start', self.origin, self.destination) elif self.dlg.direction.currentText() == 'End->Start': # for i in points: # distance = QgsDistanceArea() # Qpoint1 = i # for j in points: # Qpoint2 = j # dist = distance.measureLine(Qpoint1, Qpoint2) # pointdist.append(dist) # if dist > distcheck: # distcheck = dist self.origin = points[countfeat - 1] self.destination = points[0] # print('Start->End', self.origin, self.destination) # print(vp_layer.featureCount()) if vp_layer.featureCount() > 3: for i in range(countfeat - 1): if i != 0 and i != countfeat - 1: if self.dlg.direction.currentText() == 'Start->End': if len(waypoints) < 1: waypoints.append('optimize:true|via:' + str(points[i].y()) + ',' + str(points[i].x())) else: waypoints.append('via:' + str(points[i].y()) + ',' + str(points[i].x())) elif self.dlg.direction.currentText() == 'End->Start': if len(waypoints) < 1: waypoints.append( 'optimize:true|via:' + str(points[countfeat - i].y()) + ',' + str(points[countfeat - i].x())) else: waypoints.append( 'via:' + str(points[countfeat - i].y()) + ',' + str(points[countfeat - i].x())) print('|'.join(waypoints)) elif vp_layer.featureCount() == 3: for i in points: if i != self.origin and i != self.destination: waypoints.append('optimize:true|via:' + str(i.y()) + ',' + str(i.x())) else: pass # print(waypoints[0], 'waypoints') # print(distcheck, 'dist') # print(pointdist, 'pointdist') # print(origin.x(),origin.y(), destination.x(),destination.y(), 'origin_dest') # vp_layer.select(origin) # vp_layer.select(destination) for feature in vp_layer.getFeatures(): geometry = feature.geometry() origin_dest.append( {geometry.asPoint().y(), geometry.asPoint().x()}) # print(origin_dest) endpoint = 'https://maps.googleapis.com/maps/api/directions/json?' APIkey = self.dlg.api.text() # mode = 'driving' origin_str = self.origin.y(), self.origin.x() destination_str = self.destination.y(), self.destination.x() # departure_time = (self.dlg.timeEdit.time().hour()*3600 + self.dlg.timeEdit.time().minute()*60+ self.dlg.timeEdit.time().second()) # print(departure_time) import time import datetime # departure = self.totimestamp(self.dlg.timeEdit.dateTime()) if self.dlg.nowtime.isChecked(): departure = 'now' else: departure = self.dlg.timeEdit.dateTime().toSecsSinceEpoch() print(departure) if vp_layer.featureCount() > 3: if self.dlg.avoid.currentText() == 'None': nav_request = 'origin={0},{1}&destination={2},{3}&waypoints={4}&departure_time={5}&mode={6}&model={7}&key={8}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), '|'.join(waypoints), departure, self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) else: nav_request = 'origin={0},{1}&destination={2},{3}&waypoints={4}&departure_time={5}&avoid={6}&mode={7}&model={8}&key={9}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), '|'.join(waypoints), departure, self.dlg.avoid.currentText(), self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) elif vp_layer.featureCount() == 3: if self.dlg.avoid.currentText() == 'None': nav_request = 'origin={0},{1}&destination={2},{3}&waypoints={4}&departure_time={5}&mode={6}&model={7}&key={8}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), waypoints[0], departure, self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) else: nav_request = 'origin={0},{1}&destination={2},{3}&waypoints={4}&departure_time={5}&avoid={6}&mode={7}&model={8}&key={9}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), waypoints[0], departure, self.dlg.avoid.currentText(), self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) else: if self.dlg.avoid.currentText() == 'None': nav_request = 'origin={0},{1}&destination={2},{3}&departure_time={4}&mode={5}&model={6}&key={7}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), departure, self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) # print(nav_request) else: nav_request = 'origin={0},{1}&destination={2},{3}&departure_time{4}&avoid={5}&mode={6}&model={7}&key={8}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), departure, self.dlg.avoid.currentText(), self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) request = endpoint + nav_request print(request) response = urllib.request.urlopen(request).read() directions = json.loads(response) keys = directions.keys() # print(keys) # print(directions['error_message'], directions['routes']) routes = directions['routes'] legs = routes[0]['legs'] line = routes[0]['overview_polyline'] # print(routes) points = polyline.decode(line['points']) self.route_layer = QgsVectorLayer( "Point?crs=EPSG:4326&field=route_id:String(100)&field=distance:String(100)&field=time:String(100)&field=ascending/descending:String(100)&field=departure_time:String(100)&field=roads_to_avoid:String(100)&field=traffic_model:String(100)", "route_points", "memory") provider = self.route_layer.dataProvider() # QgsProject.instance().addMapLayer(self.route_layer) if len(legs[0]['duration']['text'].split(' ')) == 2: duration1 = legs[0]['duration']['text'].split(' ') print(duration1, 'dur') duration = duration1[0] else: duration1 = legs[0]['duration']['text'].split(' ') print(duration1, 'dur1') duration = str((int(duration1[0]) * 60) + int(duration1[2])) self.route_layer.startEditing() route_attrib = [ self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(), (self.dlg.timeEdit.dateTime()), self.dlg.avoid.currentText(), self.dlg.model.currentText() ] # print((self.dlg.timeEdit.time())) # print(route_attrib) for i in points: outelem = QgsFeature(self.route_layer.fields()) outelem.setGeometry( QgsGeometry.fromPointXY(QgsPointXY(i[1], i[0]))) outelem.setFields(self.route_layer.fields()) outelem.setAttributes(route_attrib) featurelist.append(outelem) # print(outelem) self.route_layer.dataProvider().addFeatures(featurelist) self.route_layer.commitChanges() result = processing.run( "qgis:pointstopath", { 'INPUT': self.route_layer, 'ORDER_FIELD': 'route_id', 'GROUP_FIELD': None, 'DATE_FORMAT': '', 'OUTPUT': 'memory:' }) if not self.dlg.checkBox.isChecked(): route = QgsVectorLayer( "Linestring?crs=EPSG:4326&field=route_id:String(100)&field=distance(km):String(100)&field=time(min):String(100)&field=ascending/descending:String(100)&field=departure_time:String(100)&field=duration_in_traffic(min):String(100)&field=roads_to_avoid:String(100)&field=traffic_model:String(100)&field=no_of_nodes:String(100)", "route", "memory") else: # print(self.dlg.route_id.text(), route_attrib2) route = self.dlg.layer.currentLayer() fields = route.dataProvider().fields() field_name = [field.name() for field in fields] # line_layer = QgsVectorLayer(result['OUTPUT'], 'route') featurelist2 = [] # if self.dlg.mode.currentText() not in ['walking', 'bicycling', 'transit']: if 'duration_in_traffic' in legs[0].keys(): if len(legs[0]['duration']['text'].split(' ')) == 2: duration1 = legs[0]['duration_in_traffic']['text'].split( ' ') print(duration1, 'dur12') duration_in_traffic = duration1[0] else: duration1 = legs[0]['duration_in_traffic']['text'].split( ' ') print(duration1, 'dur13') duration_in_traffic = str((int(duration1[0]) * 60) + int(duration1[2])) if 'fid' in field_name: route_attrib2 = [ route.featureCount(), self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(), (self.dlg.timeEdit.dateTime()), duration_in_traffic, self.dlg.avoid.currentText(), self.dlg.model.currentText(), str(self.route_layer.featureCount()) ] else: route_attrib2 = [ self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(), (self.dlg.timeEdit.dateTime()), duration_in_traffic, self.dlg.avoid.currentText(), self.dlg.model.currentText(), str(self.route_layer.featureCount()) ] else: if 'fid' in field_name: route_attrib2 = [ route.featureCount(), self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(), (self.dlg.timeEdit.dateTime()), 'None', self.dlg.avoid.currentText(), self.dlg.model.currentText(), str(self.route_layer.featureCount()) ] else: route_attrib2 = [ self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(), (self.dlg.timeEdit.dateTime()), duration_in_traffic, self.dlg.avoid.currentText(), self.dlg.model.currentText(), str(self.route_layer.featureCount()) ] # print(field_name) # if 'fid' in field_name: # # route.startEditing() # # print(route.dataProvider().fieldNameIndex('fid')) # # route.dataProvider().deleteAttributes([route.dataProvider().fieldNameIndex('fid')]) # # route.updateFields() # # field_name = [field.name() for field in fields] # # print(field_name) # # route_attrib2 = [route.featureCount(), self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(),(self.dlg.timeEdit.dateTime()),'None',self.dlg.avoid.currentText(), self.dlg.model.currentText(), str(self.route_layer.featureCount())] # else: # pass provider = route.dataProvider() route.startEditing() request = QgsFeatureRequest() # set order by field clause = QgsFeatureRequest.OrderByClause('route_id', ascending=False) orderby = QgsFeatureRequest.OrderBy([clause]) request.setOrderBy(orderby) fields = route.dataProvider().fields() field_name = [field.name() for field in fields] for feature in result['OUTPUT'].getFeatures(): outelem = QgsFeature(route.fields()) outelem.setGeometry(feature.geometry()) outelem.setFields(route.fields()) if 'fid' not in field_name: outelem.setAttributes(route_attrib2) else: for index, field in enumerate(field_name): if field != 'fid': print(field, route_attrib2[index]) outelem[field] = route_attrib2[index] featurelist2.append(outelem) route.dataProvider().addFeatures(featurelist2) # route.updateFeature(feature) route.commitChanges() # QgsProject.instance().addMapLayer(route) if route.featureCount() == 1: file_path = os.path.abspath( os.path.join(os.path.dirname(__file__), "route_style.qml")) route.loadNamedStyle(file_path) else: # result_del = processing.run("qgis:deletecolumn", { # 'INPUT': route, # 'COLUMN': ['gid'], 'OUTPUT': 'memory:'}) # QgsProject.instance().addMapLayer(result_del['OUTPUT']) # result = processing.run("native:addautoincrementalfield", # {'INPUT': result_del['OUTPUT'], # 'FIELD_NAME': 'gid', 'START': 1, 'GROUP_FIELDS': [], # 'SORT_EXPRESSION': '', # 'SORT_ASCENDING': False, 'SORT_NULLS_FIRST': False, 'OUTPUT': 'memory:route'}) # # QgsProject.instance().removeMapLayer(route) # route = result['OUTPUT'] QgsProject.instance().addMapLayer(route) # provide file name index and field's unique values # fni = route.dataProvider().fieldNameIndex('route_id') # unique_values = route.uniqueValues(fni) # fni2 = route.dataProvider().fieldNameIndex('route_id') # unique_values2 = route.uniqueValues(fni2) # unique_values2 = sorted(unique_values2) unique_values2 = [] unique_values = [] request = QgsFeatureRequest() # set order by field clause = QgsFeatureRequest.OrderByClause('route_id', ascending=False) orderby = QgsFeatureRequest.OrderBy([clause]) request.setOrderBy(orderby) for feature in route.getFeatures(): attrib = feature.attributes() unique_values2.append(attrib[ route.dataProvider().fieldNameIndex('route_id')]) unique_values.append(attrib[ route.dataProvider().fieldNameIndex('route_id')]) from random import randrange # fill categories categories = [] # print(unique_values) # unique_values = sorted(unique_values) print(unique_values, unique_values2) for index, unique_value in enumerate(unique_values): # initialize the default symbol for this geometry type # symbol = QgsSymbol.defaultSymbol(route.geometryType()) # symbol = QgsSymbol.Symbol().setShape(QgsSimpleMarkerSymbolLayerBase.Star # symbol.appendSymbolLayer(symbol_layer) # configure a symbol layer # sym = route.renderer().symbol() # double headed symbol = QgsSymbol.defaultSymbol(route.geometryType()) # double headed sym_layer = QgsArrowSymbolLayer.create({ "arrow_width": "1", "arrow_start_width": "1", "head_length": "1.5", "head_thickness": "1.5", "head_type": "0", "arrow_type": "0", "is_curved": "0", }) fill_sym = QgsFillSymbol.createSimple({ "color": '%d, %d, %d' % (randrange(0, 256), randrange( 0, 256), randrange(0, 256)) }) sym_layer.setSubSymbol(fill_sym) symbol.changeSymbolLayer(0, sym_layer) # layer_style = {} # layer_style['color'] = '%d, %d, %d' % (randrange(0, 256), randrange(0, 256), randrange(0, 256)) # layer_style['outline'] = '#FF0000' # # layer_style['width'] = '7.6' # symbol_layer = QgsSimpleFillSymbolLayer.create(layer_style) # replace default symbol layer with the configured one # if symbol_layer is not None: # symbol.changeSymbolLayer(0, symbol_layer) # symbol.setWidth(0.66) # create renderer object category = QgsRendererCategory(unique_value, symbol, str(unique_values2[index])) # entry for the list of category items categories.append(category) # create renderer object renderer = QgsCategorizedSymbolRenderer('route_id', categories) # assign the created renderer to the layer if renderer is not None: route.setRenderer(renderer) route.triggerRepaint() ltl = QgsProject.instance().layerTreeRoot().findLayer( route.id()) ltm = iface.layerTreeView() # ltm.sortItems(0, Qt.AscendingOrder) # view = iface.layerTreeView() # ltm.model().AllowNodeReorder() index_newfeat = ltm.model().index(0, 0) node = ltm.model().index2node(index_newfeat) nodes = ltm.model().layerLegendNodes(node) legendNodes = ltm.model().layerLegendNodes(ltl) legend_dict = {} legend_dict[node.name()] = legendNodes # print(legend_dict) ltm.setSortingEnabled(True) ltm.sortByColumn(0, Qt.DescendingOrder) for index, ln in enumerate(legendNodes): if index + 1 != route.featureCount(): ln.setData(Qt.Unchecked, Qt.CheckStateRole) # index_newfeat = ltm.model().index(route.featureCount()-1, 0) # print(index_newfeat) # node = ltm.model().index2node(index_newfeat) # print(node) # nodes = ltm.model().layerLegendNodes(node) # # layer_and_nodes[n.name()] = nodes # # print(layer_and_nodes) # # legend_get = ltm.model().index2legendNode(nodes) # print(nodes) # print(index, ln) # print(index, ltm.model().legendRootIndex(ln), ltm.model().legendNode2index(ln), ln, index_newfeat) # if index+1 != int(self.dlg.route_id.text()): # ln.setData(Qt.Checked, Qt.CheckStateRole) if not self.dlg.checkBox.isChecked(): if self.dlg.output.text() != '': path = self.dlg.output.text() QgsVectorFileWriter.writeAsVectorFormat( route, path, 'UTF-8', route.crs(), 'ESRI Shapefile') # layer = QgsProject.instance().layerTreeRoot().findLayer(route.id()) # print(layer.name()) output = self.dlg.output.text().split('/') route_path = QgsVectorLayer( path, output[len(output) - 1].split('.')[0]) QgsProject.instance().addMapLayer(route_path) else: QgsProject.instance().addMapLayer(route) listselect = [] for index, feature in enumerate(route.getFeatures()): if index + 1 == route.featureCount(): listselect.append(feature.id()) route.select(listselect) iface.actionZoomToSelected().trigger() except Exception as e: alert = QMessageBox() alert.setWindowTitle('Alert') if self.dlg.mode.currentText() in [ 'walking', 'bicycling', 'transit' ]: alert.setText( str(e) + '\nRoute not available for selected mode.') else: alert.setText(str(e)) result = alert.exec_() print(e)
def testMapTheme(self): canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer", "memory") # add a polygon to layer f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) # create a style sym1 = QgsFillSymbol.createSimple({'color': '#ffb200'}) renderer = QgsSingleSymbolRenderer(sym1) layer.setRenderer(renderer) canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add some styles layer.styleManager().addStyleFromLayer('style1') sym2 = QgsFillSymbol.createSimple({'color': '#00b2ff'}) renderer2 = QgsSingleSymbolRenderer(sym2) layer.setRenderer(renderer2) layer.styleManager().addStyleFromLayer('style2') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme2', 'theme2', canvas)) layer.styleManager().setCurrentStyle('style1') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # OK, so all good with setting/rendering map styles # try setting canvas to a particular theme # make some themes... theme1 = QgsMapThemeCollection.MapThemeRecord() record1 = QgsMapThemeCollection.MapThemeLayerRecord(layer) record1.currentStyle = 'style1' record1.usingCurrentStyle = True theme1.setLayerRecords([record1]) theme2 = QgsMapThemeCollection.MapThemeRecord() record2 = QgsMapThemeCollection.MapThemeLayerRecord(layer) record2.currentStyle = 'style2' record2.usingCurrentStyle = True theme2.setLayerRecords([record2]) QgsProject.instance().mapThemeCollection().insert('theme1', theme1) QgsProject.instance().mapThemeCollection().insert('theme2', theme2) canvas.setTheme('theme2') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme2', 'theme2', canvas)) canvas.setTheme('theme1') canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add another layer layer2 = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer2", "memory") f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer2.dataProvider().addFeatures([f])) # create a style sym1 = QgsFillSymbol.createSimple({'color': '#b2ff00'}) renderer = QgsSingleSymbolRenderer(sym1) layer2.setRenderer(renderer) # rerender canvas - should NOT show new layer canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # test again - this time refresh all layers canvas.refreshAllLayers() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas)) # add layer 2 to theme1 record3 = QgsMapThemeCollection.MapThemeLayerRecord(layer2) theme1.setLayerRecords([record3]) QgsProject.instance().mapThemeCollection().update('theme1', theme1) canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme3', 'theme3', canvas)) # change the appearance of an active style layer2.styleManager().addStyleFromLayer('original') layer2.styleManager().addStyleFromLayer('style4') record3.currentStyle = 'style4' record3.usingCurrentStyle = True theme1.setLayerRecords([record3]) QgsProject.instance().mapThemeCollection().update('theme1', theme1) canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme3', 'theme3', canvas)) layer2.styleManager().setCurrentStyle('style4') sym3 = QgsFillSymbol.createSimple({'color': '#b200b2'}) layer2.renderer().setSymbol(sym3) canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) # try setting layers while a theme is in place canvas.setLayers([layer]) canvas.refresh() # should be no change... setLayers should be ignored if canvas is following a theme! canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) # setLayerStyleOverrides while theme is in place canvas.setLayerStyleOverrides({layer2.id(): 'original'}) # should be no change... setLayerStyleOverrides should be ignored if canvas is following a theme! canvas.refresh() canvas.waitWhileRendering() self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas)) # clear theme canvas.setTheme('') canvas.refresh() canvas.waitWhileRendering() # should be different - we should now render project layers self.assertFalse(self.canvasImageCheck('theme4', 'theme4', canvas))
def on_classifyPushButton_clicked(self): input_raster_layer_name = self.rasterLayerComboBox.currentText() input_vector_layer_name = self.vectorLayerComboBox.currentText() # 调用QGIS区域统计工具 processing.run( 'qgis:zonalstatistics', { 'INPUT_RASTER': input_raster_layer_name, 'RASTER_BAND': 1, 'INPUT_VECTOR': input_vector_layer_name, 'COLUMN_PREFIX': 'Band1_', 'STATS': 2 }) processing.run( 'qgis:zonalstatistics', { 'INPUT_RASTER': input_raster_layer_name, 'RASTER_BAND': 2, 'INPUT_VECTOR': input_vector_layer_name, 'COLUMN_PREFIX': 'Band2_', 'STATS': 2 }) processing.run( 'qgis:zonalstatistics', { 'INPUT_RASTER': input_raster_layer_name, 'RASTER_BAND': 3, 'INPUT_VECTOR': input_vector_layer_name, 'COLUMN_PREFIX': 'Band3_', 'STATS': 2 }) # QgsProject.instance().addMapLayer(vector_layer) # 获取计算结果 input_vector_layer = QgsProject.instance().mapLayersByName( input_vector_layer_name)[0] features = input_vector_layer.getFeatures() feature_id_list = [] feature_band_list = [] for feature in features: feature_id_list.append(feature.id()) feature_band_list.append([ feature['Band1_mean'], feature['Band2_mean'], feature['Band3_mean'] ]) # 聚类 cluster_num = self.spinBox.value() cluster_result = cluster(np.array(feature_band_list)) # 添加聚类结果到字段,字段存在则删除。只要涉及字段操作,每次操作都要更新字段 field_name_list = [ field.name() for field in input_vector_layer.fields() ] if 'cluster_id' in field_name_list: input_vector_layer.dataProvider().deleteAttributes( [field_name_list.index('cluster_id')]) input_vector_layer.updateFields() input_vector_layer.dataProvider().addAttributes( [QgsField("cluster_id", QVariant.Int)]) input_vector_layer.updateFields() field_name_list = [ field.name() for field in input_vector_layer.fields() ] print(field_name_list) cluster_id_field_index = field_name_list.index('cluster_id') for index, fid in enumerate(feature_id_list): attrs = {cluster_id_field_index: int(cluster_result[index])} change_result = input_vector_layer.dataProvider( ).changeAttributeValues({fid: attrs}) print(fid) print(attrs) print(change_result) input_vector_layer.updateFields() # 符号化 categorized_renderer = QgsCategorizedSymbolRenderer() categorized_renderer.setClassAttribute('cluster_id') for cluster_id in range(cluster_num): fill_symbol = QgsFillSymbol.createSimple({}) fill_symbol.setColor( QtGui.QColor(*np.random.randint(0, 256, 3), 200)) categorized_renderer.addCategory( QgsRendererCategory(cluster_id, fill_symbol, f'cluster {cluster_id}')) input_vector_layer.setRenderer(categorized_renderer)
def testRenderMultipleRenderersAboveAndBelow(self): poly_layer = QgsVectorLayer(os.path.join(TEST_DATA_DIR, 'polys.shp')) self.assertTrue(poly_layer.isValid()) sym1 = QgsFillSymbol.createSimple({'color': '#ffaaff', 'outline_color': '#000000', 'outline_width': '1'}) renderer = QgsSingleSymbolRenderer(sym1) poly_layer.setRenderer(renderer) # add secondary renderer, for rendering below class Gen1(QgsFeatureRendererGenerator): def id(self): return 'Gen1' def level(self): return 3 def createRenderer(self): renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('Name') cf1 = QgsCentroidFillSymbolLayer() cf1.setSubSymbol(QgsMarkerSymbol.createSimple( {'color': '#33aa33', 'outline_style': 'no', 'size': '5'})) sym1 = QgsFillSymbol([cf1]) cf2 = QgsCentroidFillSymbolLayer() cf2.setSubSymbol(QgsMarkerSymbol.createSimple( {'color': '#aa33aa', 'outline_style': 'no', 'size': '5'})) sym2 = QgsFillSymbol([cf2]) renderer.addCategory(QgsRendererCategory('Dam', sym1, 'Dam')) renderer.addCategory(QgsRendererCategory('Lake', sym2, 'Lake')) return renderer # add secondary renderer, for rendering below class Gen2(QgsFeatureRendererGenerator): def id(self): return 'Gen2' def level(self): return 2 def createRenderer(self): renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('Value < 12') cf1 = QgsCentroidFillSymbolLayer() cf1.setSubSymbol(QgsMarkerSymbol.createSimple( {'color': '#aa1111', 'outline_style': 'no', 'size': '8'})) sym1 = QgsFillSymbol([cf1]) cf2 = QgsCentroidFillSymbolLayer() cf2.setSubSymbol(QgsMarkerSymbol.createSimple( {'color': '#1111dd', 'outline_style': 'no', 'size': '8'})) sym2 = QgsFillSymbol([cf2]) renderer.addCategory(QgsRendererCategory('1', sym1, '1')) renderer.addCategory(QgsRendererCategory('0', sym2, '0')) return renderer # add secondary renderer, for rendering below class Gen1b(QgsFeatureRendererGenerator): def id(self): return 'Gen1b' def level(self): return -2 def createRenderer(self): renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('Name') sym1 = QgsFillSymbol.createSimple( {'color': '#ffaaff', 'outline_color': '#33aa33', 'outline_width': '3'}) sym2 = QgsFillSymbol.createSimple( {'color': '#ffaaff', 'outline_color': '#aa33aa', 'outline_width': '3'}) renderer.addCategory(QgsRendererCategory('Dam', sym1, 'Dam')) renderer.addCategory(QgsRendererCategory('Lake', sym2, 'Lake')) return renderer # add secondary renderer, for rendering below class Gen2b(QgsFeatureRendererGenerator): def id(self): return 'Gen2b' def level(self): return -3 def createRenderer(self): renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('Value < 12') sym1 = QgsFillSymbol.createSimple( {'color': '#ffaaff', 'outline_color': '#aa1111', 'outline_width': '5'}) sym2 = QgsFillSymbol.createSimple( {'color': '#ffaaff', 'outline_color': '#1111dd', 'outline_width': '5'}) renderer.addCategory(QgsRendererCategory('1', sym1, '1')) renderer.addCategory(QgsRendererCategory('0', sym2, '0')) return renderer poly_layer.addFeatureRendererGenerator(Gen1()) poly_layer.addFeatureRendererGenerator(Gen2()) poly_layer.addFeatureRendererGenerator(Gen1b()) poly_layer.addFeatureRendererGenerator(Gen2b()) 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]) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(mapsettings) renderchecker.setControlPathPrefix('vectorlayerrenderer') renderchecker.setControlName('expected_multiple_renderers_both_above_below') result = renderchecker.runTest('expected_multiple_renderers_both_above_below') self.report += renderchecker.report() self.assertTrue(result) # also try with symbol levels renderer.setUsingSymbolLevels(True) poly_layer.setRenderer(renderer) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(mapsettings) renderchecker.setControlPathPrefix('vectorlayerrenderer') renderchecker.setControlName('expected_multiple_renderers_both_above_below') result = renderchecker.runTest('expected_multiple_renderers_both_above_below') self.report += renderchecker.report() self.assertTrue(result)
def testRenderMultipleRenderersSelection(self): """ Test that selection colors only apply to main renderer :return: """ poly_layer = QgsVectorLayer(os.path.join(TEST_DATA_DIR, 'polys.shp')) self.assertTrue(poly_layer.isValid()) poly_layer.selectAll() sym1 = QgsFillSymbol.createSimple({'color': '#ffaaff', 'outline_color': '#000000', 'outline_style': 'no'}) renderer = QgsSingleSymbolRenderer(sym1) poly_layer.setRenderer(renderer) # add secondary renderer, for rendering below class Gen1(QgsFeatureRendererGenerator): def id(self): return 'Gen1' def level(self): return -2 def createRenderer(self): renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('Name') sym1 = QgsFillSymbol.createSimple( {'color': '#ffaaff', 'outline_color': '#33aa33', 'outline_width': '3'}) sym2 = QgsFillSymbol.createSimple( {'color': '#ffaaff', 'outline_color': '#aa33aa', 'outline_width': '3'}) renderer.addCategory(QgsRendererCategory('Dam', sym1, 'Dam')) renderer.addCategory(QgsRendererCategory('Lake', sym2, 'Lake')) return renderer poly_layer.addFeatureRendererGenerator(Gen1()) 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]) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(mapsettings) renderchecker.setControlPathPrefix('vectorlayerrenderer') renderchecker.setControlName('expected_multiple_renderers_selection') result = renderchecker.runTest('expected_multiple_renderers_selection') self.report += renderchecker.report() self.assertTrue(result) # also try with symbol levels renderer.setUsingSymbolLevels(True) poly_layer.setRenderer(renderer) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(mapsettings) renderchecker.setControlPathPrefix('vectorlayerrenderer') renderchecker.setControlName('expected_multiple_renderers_selection') result = renderchecker.runTest('expected_multiple_renderers_selection') self.report += renderchecker.report() self.assertTrue(result)
def add_design_to_map(qris_project, item, node): """adds designs to the map""" # Establish paths to layers design_id = item.data(item_code['feature_id']) subset_string = ("design_id = " + str(design_id)) design_name = item.text() geopackage_path = qris_project.project_designs.geopackage_path( qris_project.project_path) designs_layer = QgsVectorLayer(geopackage_path + "|layername=designs", "Designs", "ogr") structure_types_layer = QgsVectorLayer( geopackage_path + "|layername=structure_types", "Structure Types", "ogr") phases_layer = QgsVectorLayer(geopackage_path + "|layername=phases", "Implementation Phases", "ogr") zoi_layer = QgsVectorLayer(geopackage_path + "|layername=zoi", "ZOI", "ogr") zoi_types_layer = QgsVectorLayer(geopackage_path + "|layername=zoi_types", "ZOI", "ogr") complexes_layer = QgsVectorLayer(geopackage_path + "|layername=complexes", "Complexes", "ogr") structure_points_layer = QgsVectorLayer( geopackage_path + "|layername=structure_points", "Structures", "ogr") structure_lines_layer = QgsVectorLayer( geopackage_path + "|layername=structure_lines", "Structures", "ogr") # Get the structure geometry type # Could also do this with SQL design_iterator = designs_layer.getFeatures( QgsFeatureRequest().setFilterFid(design_id)) design_feature = next(design_iterator) structure_geometry = design_feature['structure_geometry'] def add_design_table(display_name, table_name, qml_name, read_only, group_node): """A handy way to add design layers and tables to the map""" if not any([c.name() == display_name for c in group_node.children()]): layer = QgsProject.instance().addMapLayer( QgsVectorLayer(geopackage_path + "|layername=" + table_name, display_name, "ogr"), False) if qml_name: layer_qml = os.path.join(symbology_path, 'symbology', qml_name) layer.loadNamedStyle(layer_qml) if read_only: layer.setReadOnly() group_node.addLayer(layer) # Summary tables (views) if any([c.name() == "Low-Tech Tables" for c in node.children()]): # if is there set it to the design node table_node = next(n for n in node.children() if n.name() == "Low-Tech Tables") else: # if not add the node as a group table_node = node.addGroup("Low-Tech Tables") table_node.setExpanded(False) # Summary tables (views) if any([c.name() == "Summary Tables" for c in table_node.children()]): # if is there set it to the design node summary_node = next(n for n in table_node.children() if n.name() == "Summary Tables") else: # if not add the node as a group summary_node = table_node.addGroup("Summary Tables") summary_node.setExpanded(False) add_design_table('Structure Totals - Points', 'qry_total_structures_points', None, True, summary_node) add_design_table('Structure Totals - Lines', 'qry_total_structures_lines', None, True, summary_node) add_design_table('Structure Summary - Points', 'qry_structure_summary_points', None, True, summary_node) add_design_table('Structure Summary - Lines', 'qry_structure_summary_lines', None, True, summary_node) add_design_table('Complexes Summary - Points', 'qry_complexes_by_type_points', None, True, summary_node) add_design_table('Complexes Summary - Lines', 'qry_complexes_by_type_lines', None, True, summary_node) add_design_table('ZOI Summary', 'qry_zoi_summary', None, True, summary_node) # Lookup Tables if any([c.name() == "Lookup Tables" for c in table_node.children()]): # if is there set it to the design node lookup_node = next(n for n in table_node.children() if n.name() == "Lookup Tables") else: # if not add the node as a group lookup_node = table_node.addGroup("Lookup Tables") lookup_node.setExpanded(False) add_design_table('Design Status', 'lkp_design_status', 'lkp_design_status.qml', True, lookup_node) add_design_table('Phase Action', 'lkp_phase_action', 'lkp_phase_action.qml', True, lookup_node) add_design_table('ZOI Influence', 'lkp_zoi_influence', 'lkp_zoi_influence.qml', True, lookup_node) add_design_table('ZOI Stage', 'lkp_zoi_stage', 'lkp_zoi_stage.qml', True, lookup_node) add_design_table('Structure Mimics', 'lkp_structure_mimics', 'lkp_structure_mimics.qml', True, lookup_node) # Add Design Tables if any([c.name() == "Design Tables" for c in table_node.children()]): # if is there set it to the design node design_tables_node = next(n for n in table_node.children() if n.name() == "Design Tables") else: # if not add the node as a group design_tables_node = table_node.addGroup("Design Tables") design_tables_node.setExpanded(False) # Check if the designs table has been added and if not add it. add_design_table('Designs', 'designs', 'designs.qml', False, design_tables_node) add_design_table('Structure Types', 'structure_types', 'structure_types.qml', False, design_tables_node) add_design_table('ZOI Types', 'zoi_types', 'zoi_types.qml', False, design_tables_node) add_design_table('Phases', 'phases', 'phases.qml', False, design_tables_node) # Check if the design node is already added design_group_name = str(design_id) + "-" + item.text() if any([c.name() == design_group_name for c in node.children()]): # if is there set it to the design node design_node = next(n for n in node.children() if n.name() == design_group_name) else: # if not add the node as a group design_node = node.addGroup(design_group_name) # Add structures structure_layer_name = str(design_id) + "-Structures" if structure_geometry == 'Point': # Start setting custom symbology # TODO Refactor into a functio unique_values = [] for feature in structure_types_layer.getFeatures(): values = (feature["fid"], feature["name"]) unique_values.append(values) categories = [] for value in unique_values: layer_style = {} layer_style["color"] = '%d, %d, %d' % (randrange( 0, 256), randrange(0, 256), randrange(0, 256)) layer_style['size'] = '3' layer_style['outline_color'] = 'black' symbol_layer = QgsMarkerSymbol.createSimple(layer_style) category = QgsRendererCategory(str(value[0]), symbol_layer, value[1]) categories.append(category) renderer = QgsCategorizedSymbolRenderer('structure_type_id', categories) if not any( [c.name() == structure_layer_name for c in design_node.children()]): # Adding the type suffix as I could see adding qml that symbolizes on other attributes structure_points_qml = os.path.join(symbology_path, 'symbology', 'structure_points.qml') structure_points_layer.loadNamedStyle(structure_points_qml) QgsExpressionContextUtils.setLayerVariable(structure_points_layer, 'parent_id', design_id) structure_points_layer.setSubsetString(subset_string) QgsProject.instance().addMapLayer(structure_points_layer, False) structure_points_layer.setName(structure_layer_name) design_node.addLayer(structure_points_layer) layer_node = design_node.findLayer(structure_points_layer.id()) layer_node.setExpanded(False) else: structure_points_layer = QgsProject.instance().mapLayersByName( structure_layer_name)[0] if renderer is not None: structure_points_layer.setRenderer(renderer) structure_points_layer.triggerRepaint() else: # Add line structures # Start setting custom symbology # TODO Refactor into a function unique_values = [] for feature in structure_types_layer.getFeatures(): values = (feature["fid"], feature["name"]) unique_values.append(values) categories = [] for value in unique_values: layer_style = {} layer_style["color"] = '%d, %d, %d' % (randrange( 0, 256), randrange(0, 256), randrange(0, 256)) layer_style['width'] = '1' layer_style['capstyle'] = 'round' symbol_layer = QgsLineSymbol.createSimple(layer_style) category = QgsRendererCategory(str(value[0]), symbol_layer, value[1]) categories.append(category) renderer = QgsCategorizedSymbolRenderer('structure_type_id', categories) # end custom symbology if not any( [c.name() == structure_layer_name for c in design_node.children()]): structures_lines_qml = os.path.join(symbology_path, 'symbology', 'structure_lines.qml') structure_lines_layer.loadNamedStyle(structures_lines_qml) QgsExpressionContextUtils.setLayerVariable(structure_lines_layer, 'parent_id', design_id) structure_lines_layer.setSubsetString(subset_string) QgsProject.instance().addMapLayer(structure_lines_layer, False) structure_lines_layer.setName(structure_layer_name) design_node.addLayer(structure_lines_layer) layer_node = design_node.findLayer(structure_lines_layer.id()) layer_node.setExpanded(False) else: structure_lines_layer = QgsProject.instance().mapLayersByName( structure_layer_name)[0] if renderer is not None: structure_lines_layer.setRenderer(renderer) structure_lines_layer.triggerRepaint() # Add zoi zoi_layer_name = str(design_id) + "-ZOI" # TODO Refactor into a function # TODO Refactor into sql query unique_values = [] for feature in zoi_types_layer.getFeatures(): values = (feature["fid"], feature["name"]) unique_values.append(values) categories = [] for value in unique_values: layer_style = {} alpha = 60 layer_style["color"] = "{}, {}, {}, {}".format(randrange(0, 256), randrange(0, 256), randrange(0, 256), alpha) layer_style["outline_width"] = '0.50' layer_style["outline_style"] = 'dash' symbol_layer = QgsFillSymbol.createSimple(layer_style) category = QgsRendererCategory(str(value[0]), symbol_layer, value[1]) categories.append(category) renderer = QgsCategorizedSymbolRenderer('influence_type_id', categories) # End custom symbology # check for the zoi layer, and if it is not there symbolize and add it if not any([c.name() == zoi_layer_name for c in design_node.children()]): zoi_qml = os.path.join(symbology_path, 'symbology', 'zoi.qml') zoi_layer.loadNamedStyle(zoi_qml) QgsExpressionContextUtils.setLayerVariable(zoi_layer, 'parent_id', design_id) zoi_layer.setSubsetString(subset_string) QgsProject.instance().addMapLayer(zoi_layer, False) zoi_layer.setName(zoi_layer_name) design_node.addLayer(zoi_layer) layer_node = design_node.findLayer(zoi_layer.id()) layer_node.setExpanded(False) else: zoi_layer = QgsProject.instance().mapLayersByName(zoi_layer_name)[0] if renderer is not None: zoi_layer.setRenderer(renderer) zoi_layer.triggerRepaint() # Add complexes complex_layer_name = str(design_id) + "-Complexes" if not any( [c.name() == complex_layer_name for c in design_node.children()]): complex_qml = os.path.join(symbology_path, 'symbology', 'complexes.qml') complexes_layer.loadNamedStyle(complex_qml) QgsExpressionContextUtils.setLayerVariable(complexes_layer, 'parent_id', design_id) complexes_layer.setSubsetString(subset_string) QgsProject.instance().addMapLayer(complexes_layer, False) complexes_layer.setName(complex_layer_name) design_node.addLayer(complexes_layer)
def testAsMapLayer(self): l = QgsLayout(QgsProject.instance()) l.initializeDefaults() map = QgsLayoutItemMap(l) map.attemptSetSceneRect(QRectF(20, 20, 200, 100)) l.addLayoutItem(map) overviewMap = QgsLayoutItemMap(l) overviewMap.attemptSetSceneRect(QRectF(20, 130, 70, 70)) l.addLayoutItem(overviewMap) # zoom in myRectangle = QgsRectangle(96, -152, 160, -120) map.setExtent(myRectangle) myRectangle2 = QgsRectangle(0, -256, 256, 0) overviewMap.setExtent(myRectangle2) overviewMap.overview().setLinkedMap(map) layer = overviewMap.overview().asMapLayer() self.assertIsNotNone(layer) self.assertTrue(layer.isValid()) self.assertEqual( [f.geometry().asWkt() for f in layer.getFeatures()], ['Polygon ((96 -120, 160 -120, 160 -152, 96 -152, 96 -120))']) # check that layer has correct renderer fill_symbol = QgsFillSymbol.createSimple({ 'color': '#00ff00', 'outline_color': '#ff0000', 'outline_width': '10' }) overviewMap.overview().setFrameSymbol(fill_symbol) layer = overviewMap.overview().asMapLayer() self.assertIsInstance(layer.renderer(), QgsSingleSymbolRenderer) self.assertEqual( layer.renderer().symbol().symbolLayer(0).properties()['color'], '0,255,0,255') self.assertEqual( layer.renderer().symbol().symbolLayer(0).properties() ['outline_color'], '255,0,0,255') # test layer blend mode self.assertEqual(layer.blendMode(), QPainter.CompositionMode_SourceOver) overviewMap.overview().setBlendMode(QPainter.CompositionMode_Clear) layer = overviewMap.overview().asMapLayer() self.assertEqual(layer.blendMode(), QPainter.CompositionMode_Clear) # should have no effect overviewMap.setMapRotation(45) layer = overviewMap.overview().asMapLayer() self.assertEqual( [f.geometry().asWkt() for f in layer.getFeatures()], ['Polygon ((96 -120, 160 -120, 160 -152, 96 -152, 96 -120))']) map.setMapRotation(15) layer = overviewMap.overview().asMapLayer() self.assertEqual( [f.geometry().asWkt(0) for f in layer.getFeatures()], ['Polygon ((93 -129, 155 -112, 163 -143, 101 -160, 93 -129))']) # with reprojection map.setCrs(QgsCoordinateReferenceSystem('EPSG:3875')) layer = overviewMap.overview().asMapLayer() self.assertEqual([ f.geometry().asWkt(0) for f in layer.getFeatures() ], [ 'Polygon ((93 -129, 96 -128, 99 -127, 102 -126, 105 -126, 108 -125, 111 -124, 114 -123, 116 -123, 119 -122, 122 -121, 125 -120, 128 -119, 131 -119, 134 -118, 137 -117, 140 -116, 143 -115, 146 -115, 149 -114, 152 -113, 155 -112, 155 -114, 156 -115, 156 -117, 156 -118, 157 -120, 157 -121, 158 -123, 158 -124, 158 -126, 159 -127, 159 -128, 160 -130, 160 -131, 160 -133, 161 -134, 161 -136, 161 -137, 162 -139, 162 -140, 163 -142, 163 -143, 160 -144, 157 -145, 154 -146, 151 -146, 148 -147, 145 -148, 142 -149, 140 -149, 137 -150, 134 -151, 131 -152, 128 -153, 125 -153, 122 -154, 119 -155, 116 -156, 113 -157, 110 -157, 107 -158, 104 -159, 101 -160, 101 -158, 100 -157, 100 -155, 100 -154, 99 -152, 99 -151, 98 -149, 98 -148, 98 -146, 97 -145, 97 -144, 96 -142, 96 -141, 96 -139, 95 -138, 95 -136, 95 -135, 94 -133, 94 -132, 93 -130, 93 -129))' ]) map.setCrs(overviewMap.crs()) # with invert overviewMap.overview().setInverted(True) layer = overviewMap.overview().asMapLayer() self.assertEqual([ f.geometry().asWkt(0) for f in layer.getFeatures() ], [ 'Polygon ((-53 -128, 128 53, 309 -128, 128 -309, -53 -128),(93 -129, 101 -160, 163 -143, 155 -112, 93 -129))' ])
def test_rendered_item_results_remove_outdated(self): """ Test that outdated results are removed from rendered item result caches """ canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326')) canvas.setFrameStyle(0) canvas.resize(600, 400) canvas.setCachingEnabled(True) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer.isValid()) layer2 = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer2.isValid()) item = QgsAnnotationPolygonItem( QgsPolygon( QgsLineString([ QgsPoint(11.5, 13), QgsPoint(12, 13), QgsPoint(12, 13.5), QgsPoint(11.5, 13) ]))) item.setSymbol( QgsFillSymbol.createSimple({ 'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2' })) item.setZIndex(1) i1_id = layer.addItem(item) item = QgsAnnotationLineItem( QgsLineString( [QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)])) item.setZIndex(2) i2_id = layer.addItem(item) item = QgsAnnotationMarkerItem(QgsPoint(12, 13)) item.setZIndex(3) i3_id = layer2.addItem(item) layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) layer2.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) canvas.setLayers([layer, layer2]) canvas.setExtent(QgsRectangle(10, 10, 18, 18)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() results = canvas.renderedItemResults() self.assertCountEqual([i.itemId() for i in results.renderedItems()], [i1_id, i2_id, i3_id]) # now try modifying an annotation in the layer -- it will redraw, and we don't want to reuse any previously # cached rendered item results for this layer! item = QgsAnnotationPolygonItem( QgsPolygon( QgsLineString([ QgsPoint(11.5, 13), QgsPoint(12.5, 13), QgsPoint(12.5, 13.5), QgsPoint(11.5, 13) ]))) item.setZIndex(1) layer.replaceItem(i1_id, item) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() item = QgsAnnotationMarkerItem(QgsPoint(17, 18)) item.setZIndex(3) layer2.replaceItem(i3_id, item) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() results = canvas.renderedItemResults() items_in_bounds = results.renderedAnnotationItemsInBounds( QgsRectangle(10, 10, 15, 15)) self.assertCountEqual([i.itemId() for i in items_in_bounds], [i1_id, i2_id]) items_in_bounds = results.renderedAnnotationItemsInBounds( QgsRectangle(15, 15, 20, 20)) self.assertCountEqual([i.itemId() for i in items_in_bounds], [i3_id])
def testRenderWithTransform(self): layer = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer.isValid()) item = QgsAnnotationPolygonItem( QgsPolygon( QgsLineString([ QgsPoint(11.5, 13), QgsPoint(12, 13), QgsPoint(12, 13.5), QgsPoint(11.5, 13) ]))) item.setSymbol( QgsFillSymbol.createSimple({ 'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2' })) item.setZIndex(1) layer.addItem(item) item = QgsAnnotationLineStringItem( QgsLineString( [QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)])) item.setSymbol( QgsLineSymbol.createSimple({ 'color': '#ffff00', 'line_width': '3' })) item.setZIndex(2) layer.addItem(item) item = QgsAnnotationMarkerItem(QgsPointXY(12, 13)) item.setSymbol( QgsMarkerSymbol.createSimple({ 'color': '100,200,200', 'size': '6', 'outline_color': 'black' })) item.setZIndex(3) layer.addItem(item) layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) settings = QgsMapSettings() settings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857')) settings.setExtent(QgsRectangle(1250958, 1386945, 1420709, 1532518)) settings.setOutputSize(QSize(300, 300)) settings.setFlag(QgsMapSettings.Antialiasing, False) rc = QgsRenderContext.fromMapSettings(settings) rc.setCoordinateTransform( QgsCoordinateTransform(layer.crs(), settings.destinationCrs(), QgsProject.instance())) image = QImage(200, 200, QImage.Format_ARGB32) image.setDotsPerMeterX(96 / 25.4 * 1000) image.setDotsPerMeterY(96 / 25.4 * 1000) image.fill(QColor(255, 255, 255)) painter = QPainter(image) rc.setPainter(painter) try: renderer = layer.createMapRenderer(rc) renderer.render() finally: painter.end() self.assertTrue( self.imageCheck('layer_render_transform', 'layer_render_transform', image))
def testMainAnnotationLayerRendered(self): """ test that main annotation layer is rendered above all other layers """ canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326')) canvas.setFrameStyle(0) canvas.resize(600, 400) self.assertEqual(canvas.width(), 600) self.assertEqual(canvas.height(), 400) layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string", "layer", "memory") sym3 = QgsFillSymbol.createSimple({'color': '#b200b2'}) layer.renderer().setSymbol(sym3) canvas.setLayers([layer]) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) canvas.show() # need to wait until first redraw can occur (note that we first need to wait till drawing starts!) while not canvas.isDrawing(): app.processEvents() canvas.waitWhileRendering() self.assertTrue( self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas)) # add polygon to layer f = QgsFeature() f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45))) self.assertTrue(layer.dataProvider().addFeatures([f])) # refresh canvas canvas.refresh() canvas.waitWhileRendering() # no annotation yet... self.assertFalse( self.canvasImageCheck('main_annotation_layer', 'main_annotation_layer', canvas, expect_fail=True)) annotation_layer = QgsProject.instance().mainAnnotationLayer() annotation_layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) annotation_geom = QgsGeometry.fromRect(QgsRectangle(12, 30, 18, 33)) annotation = QgsAnnotationPolygonItem( annotation_geom.constGet().clone()) sym3 = QgsFillSymbol.createSimple({ 'color': '#ff0000', 'outline_style': 'no' }) annotation.setSymbol(sym3) annotation_layer.addItem(annotation) # refresh canvas canvas.refresh() canvas.waitWhileRendering() # annotation must be rendered over other layers self.assertTrue( self.canvasImageCheck('main_annotation_layer', 'main_annotation_layer', canvas)) annotation_layer.clear()
def testIntersectionRuleBased(self): """ Test that rule based renderer using intersection clip paths correctly uses original feature area for rule evaluation, not clipped area """ 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' }) sym2 = QgsFillSymbol.createSimple({ 'color': '#00ffff', 'outline_color': '#000000', 'outline_width': '1' }) r1 = QgsRuleBasedRenderer.Rule(sym1, 0, 0, 'area($geometry)>25') r2 = QgsRuleBasedRenderer.Rule(sym2, 0, 0, 'ELSE') rootrule = QgsRuleBasedRenderer.Rule(None) rootrule.appendChild(r1) rootrule.appendChild(r2) renderer = QgsRuleBasedRenderer(rootrule) 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]) mapsettings.setEllipsoid('') region = QgsMapClippingRegion( QgsGeometry.fromWkt( 'Polygon ((-11725957 5368254, -12222900 4807501, -12246014 3834025, -12014878 3496059, -11259833 3518307, -10751333 3621153, -10574129 4516741, -10847640 5194995, -11105742 5325957, -11725957 5368254))' )) region.setFeatureClip( QgsMapClippingRegion.FeatureClippingType.ClipToIntersection) region2 = QgsMapClippingRegion( QgsGeometry.fromWkt( 'Polygon ((-11032549 5421399, -11533344 4693167, -11086481 4229112, -11167378 3742984, -10616504 3553984, -10161936 3925771, -9618766 4668482, -9472380 5620753, -10115709 5965063, -11032549 5421399))' )) region2.setFeatureClip( QgsMapClippingRegion.FeatureClippingType.ClipToIntersection) mapsettings.addClippingRegion(region) mapsettings.addClippingRegion(region2) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(mapsettings) renderchecker.setControlPathPrefix('vectorlayerrenderer') renderchecker.setControlName('expected_intersection_rule_based') result = renderchecker.runTest('expected_intersection_rule_based') self.report += renderchecker.report() self.assertTrue(result) # also try with symbol levels renderer.setUsingSymbolLevels(True) poly_layer.setRenderer(renderer) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(mapsettings) renderchecker.setControlPathPrefix('vectorlayerrenderer') renderchecker.setControlName('expected_intersection_rule_based') result = renderchecker.runTest('expected_intersection_rule_based') self.report += renderchecker.report() self.assertTrue(result)
def testCase(self): self.TEST_DATA_DIR = unitTestDataPath() tmppath = tempfile.mkdtemp() for file in glob.glob(os.path.join(self.TEST_DATA_DIR, 'france_parts.*')): shutil.copy(os.path.join(self.TEST_DATA_DIR, file), tmppath) vectorFileInfo = QFileInfo(tmppath + "/france_parts.shp") mVectorLayer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") QgsProject.instance().addMapLayers([mVectorLayer]) self.layers = [mVectorLayer] # create layout with layout map # select epsg:2154 crs = QgsCoordinateReferenceSystem() crs.createFromSrid(2154) QgsProject.instance().setCrs(crs) self.layout = QgsPrintLayout(QgsProject.instance()) self.layout.initializeDefaults() # fix the renderer, fill with green props = {"color": "0,127,0", 'outline_color': 'black'} fillSymbol = QgsFillSymbol.createSimple(props) renderer = QgsSingleSymbolRenderer(fillSymbol) mVectorLayer.setRenderer(renderer) # the atlas map self.atlas_map = QgsLayoutItemMap(self.layout) self.atlas_map.attemptSetSceneRect(QRectF(20, 20, 130, 130)) self.atlas_map.setFrameEnabled(True) self.atlas_map.setLayers([mVectorLayer]) self.layout.addLayoutItem(self.atlas_map) # the atlas self.atlas = self.layout.atlas() self.atlas.setCoverageLayer(mVectorLayer) self.atlas.setEnabled(True) # an overview self.overview = QgsLayoutItemMap(self.layout) self.overview.attemptSetSceneRect(QRectF(180, 20, 50, 50)) self.overview.setFrameEnabled(True) self.overview.overview().setLinkedMap(self.atlas_map) self.overview.setLayers([mVectorLayer]) self.layout.addLayoutItem(self.overview) nextent = QgsRectangle(49670.718, 6415139.086, 699672.519, 7065140.887) self.overview.setExtent(nextent) # set the fill symbol of the overview map props2 = {"color": "127,0,0,127", 'outline_color': 'black'} fillSymbol2 = QgsFillSymbol.createSimple(props2) self.overview.overview().setFrameSymbol(fillSymbol2) # header label self.mLabel1 = QgsLayoutItemLabel(self.layout) self.layout.addLayoutItem(self.mLabel1) self.mLabel1.setText("[% \"NAME_1\" %] area") self.mLabel1.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel1.adjustSizeToText() self.mLabel1.attemptSetSceneRect(QRectF(150, 5, 60, 15)) self.mLabel1.setMarginX(1) self.mLabel1.setMarginY(1) # feature number label self.mLabel2 = QgsLayoutItemLabel(self.layout) self.layout.addLayoutItem(self.mLabel2) self.mLabel2.setText("# [%@atlas_featurenumber || ' / ' || @atlas_totalfeatures%]") self.mLabel2.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel2.adjustSizeToText() self.mLabel2.attemptSetSceneRect(QRectF(150, 200, 60, 15)) self.mLabel2.setMarginX(1) self.mLabel2.setMarginY(1) self.filename_test() self.autoscale_render_test() self.fixedscale_render_test() self.predefinedscales_render_test() self.hidden_render_test() self.legend_test() self.rotation_test() shutil.rmtree(tmppath, True)
def style_maps(layer, style_by, iface, output_type='damages-rlzs', perils=None, add_null_class=False, render_higher_on_top=False, repaint=True, use_sgc_style=False): symbol = QgsSymbol.defaultSymbol(layer.geometryType()) # see properties at: # https://qgis.org/api/qgsmarkersymbollayerv2_8cpp_source.html#l01073 symbol.setOpacity(1) if isinstance(symbol, QgsMarkerSymbol): # do it only for the layer with points symbol.symbolLayer(0).setStrokeStyle(Qt.PenStyle(Qt.NoPen)) style = get_style(layer, iface.messageBar()) # this is the default, as specified in the user settings ramp = QgsGradientColorRamp(style['color_from'], style['color_to']) style_mode = style['style_mode'] # in most cases, we override the user-specified setting, and use # instead a setting that was required by scientists if output_type in OQ_TO_LAYER_TYPES: default_qgs_style = QgsStyle().defaultStyle() default_color_ramp_names = default_qgs_style.colorRampNames() if output_type in ( 'damages-rlzs', 'avg_losses-rlzs', 'avg_losses-stats', ): # options are EqualInterval, Quantile, Jenks, StdDev, Pretty # jenks = natural breaks if Qgis.QGIS_VERSION_INT < 31000: style_mode = QgsGraduatedSymbolRenderer.Jenks else: style_mode = 'Jenks' ramp_type_idx = default_color_ramp_names.index('Reds') symbol.setColor(QColor(RAMP_EXTREME_COLORS['Reds']['top'])) inverted = False elif (output_type in ('gmf_data', 'ruptures') or (output_type == 'hmaps' and not use_sgc_style)): # options are EqualInterval, Quantile, Jenks, StdDev, Pretty # jenks = natural breaks if output_type == 'ruptures': if Qgis.QGIS_VERSION_INT < 31000: style_mode = QgsGraduatedSymbolRenderer.Pretty else: style_mode = 'PrettyBreaks' else: if Qgis.QGIS_VERSION_INT < 31000: style_mode = QgsGraduatedSymbolRenderer.EqualInterval else: style_mode = 'EqualInterval' ramp_type_idx = default_color_ramp_names.index('Spectral') inverted = True symbol.setColor(QColor(RAMP_EXTREME_COLORS['Reds']['top'])) elif output_type == 'hmaps' and use_sgc_style: # FIXME: for SGC they were using size 10000 map units # options are EqualInterval, Quantile, Jenks, StdDev, Pretty # jenks = natural breaks if Qgis.QGIS_VERSION_INT < 31000: style_mode = QgsGraduatedSymbolRenderer.Pretty else: style_mode = 'PrettyBreaks' try: ramp_type_idx = default_color_ramp_names.index( 'SGC_Green2Red_Hmap_Color_Ramp') except ValueError: raise ValueError( 'Color ramp SGC_Green2Red_Hmap_Color_Ramp was ' 'not found. Please import it from ' 'Settings -> Style Manager, loading ' 'svir/resources/sgc_green2red_hmap_color_ramp.xml') inverted = False registry = QgsApplication.symbolLayerRegistry() symbol_props = { 'name': 'square', 'color': '0,0,0', 'color_border': '0,0,0', 'offset': '0,0', 'size': '1.5', # FIXME 'angle': '0', } square = registry.symbolLayerMetadata( "SimpleMarker").createSymbolLayer(symbol_props) symbol = QgsSymbol.defaultSymbol(layer.geometryType()).clone() symbol.deleteSymbolLayer(0) symbol.appendSymbolLayer(square) symbol.symbolLayer(0).setStrokeStyle(Qt.PenStyle(Qt.NoPen)) elif output_type in ['asset_risk', 'input']: # options are EqualInterval, Quantile, Jenks, StdDev, Pretty # jenks = natural breaks if Qgis.QGIS_VERSION_INT < 31000: style_mode = QgsGraduatedSymbolRenderer.EqualInterval else: style_mode = 'EqualInterval' # exposure_strings = ['number', 'occupants', 'value'] # setting exposure colors by default colors = { 'single': RAMP_EXTREME_COLORS['Blues']['top'], 'ramp_name': 'Blues' } inverted = False if output_type == 'asset_risk': damage_strings = perils for damage_string in damage_strings: if damage_string in style_by: colors = { 'single': RAMP_EXTREME_COLORS['Spectral']['top'], 'ramp_name': 'Spectral' } inverted = True break else: # 'input' colors = { 'single': RAMP_EXTREME_COLORS['Greens']['top'], 'ramp_name': 'Greens' } symbol.symbolLayer(0).setShape( QgsSimpleMarkerSymbolLayerBase.Square) single_color = colors['single'] ramp_name = colors['ramp_name'] ramp_type_idx = default_color_ramp_names.index(ramp_name) symbol.setColor(QColor(single_color)) else: raise NotImplementedError( 'Undefined color ramp for output type %s' % output_type) ramp = default_qgs_style.colorRamp( default_color_ramp_names[ramp_type_idx]) if inverted: ramp.invert() # get unique values fni = layer.fields().indexOf(style_by) unique_values = layer.dataProvider().uniqueValues(fni) num_unique_values = len(unique_values - {NULL}) if num_unique_values > 2: if Qgis.QGIS_VERSION_INT < 31000: renderer = QgsGraduatedSymbolRenderer.createRenderer( layer, style_by, min(num_unique_values, style['classes']), style_mode, symbol.clone(), ramp) else: renderer = QgsGraduatedSymbolRenderer(style_by, []) # NOTE: the following returns an instance of one of the # subclasses of QgsClassificationMethod classification_method = \ QgsApplication.classificationMethodRegistry().method( style_mode) renderer.setClassificationMethod(classification_method) renderer.updateColorRamp(ramp) renderer.updateSymbols(symbol.clone()) renderer.updateClasses( layer, min(num_unique_values, style['classes'])) if not use_sgc_style: if Qgis.QGIS_VERSION_INT < 31000: label_format = renderer.labelFormat() # NOTE: the following line might be useful # label_format.setTrimTrailingZeroes(True) label_format.setPrecision(2) renderer.setLabelFormat(label_format, updateRanges=True) else: renderer.classificationMethod().setLabelPrecision(2) renderer.calculateLabelPrecision() elif num_unique_values == 2: categories = [] for unique_value in unique_values: symbol = symbol.clone() try: symbol.setColor( QColor(RAMP_EXTREME_COLORS[ramp_name] ['bottom' if unique_value == min(unique_values) else 'top'])) except Exception: symbol.setColor( QColor(style['color_from'] if unique_value == min(unique_values) else style['color_to'])) category = QgsRendererCategory(unique_value, symbol, str(unique_value)) # entry for the list of category items categories.append(category) renderer = QgsCategorizedSymbolRenderer(style_by, categories) else: renderer = QgsSingleSymbolRenderer(symbol.clone()) if add_null_class and NULL in unique_values: # add a class for NULL values rule_renderer = QgsRuleBasedRenderer(symbol.clone()) root_rule = rule_renderer.rootRule() not_null_rule = root_rule.children()[0].clone() # strip parentheses from stringified color HSL not_null_rule.setFilterExpression( '%s IS NOT NULL' % QgsExpression.quotedColumnRef(style_by)) not_null_rule.setLabel('%s:' % style_by) root_rule.appendChild(not_null_rule) null_rule = root_rule.children()[0].clone() null_rule.setSymbol( QgsFillSymbol.createSimple({ 'color': '160,160,160', 'style': 'diagonal_x' })) null_rule.setFilterExpression( '%s IS NULL' % QgsExpression.quotedColumnRef(style_by)) null_rule.setLabel(tr('No points')) root_rule.appendChild(null_rule) if isinstance(renderer, QgsGraduatedSymbolRenderer): # create value ranges rule_renderer.refineRuleRanges(not_null_rule, renderer) # remove default rule elif isinstance(renderer, QgsCategorizedSymbolRenderer): rule_renderer.refineRuleCategoris(not_null_rule, renderer) for rule in rule_renderer.rootRule().children()[1].children(): label = rule.label() # by default, labels are like: # ('"collapse-structural-ASH_DRY_sum" >= 0.0000 AND # "collapse-structural-ASH_DRY_sum" <= 2.3949') first, second = label.split(" AND ") bottom = first.rsplit(" ", 1)[1] top = second.rsplit(" ", 1)[1] simplified = "%s - %s" % (bottom, top) rule.setLabel(simplified) root_rule.removeChildAt(0) renderer = rule_renderer if render_higher_on_top: renderer.setUsingSymbolLevels(True) symbol_items = [item for item in renderer.legendSymbolItems()] for i in range(len(symbol_items)): sym = symbol_items[i].symbol().clone() key = symbol_items[i].ruleKey() for lay in range(sym.symbolLayerCount()): sym.symbolLayer(lay).setRenderingPass(i) renderer.setLegendSymbolItem(key, sym) layer.setRenderer(renderer) if not use_sgc_style: layer.setOpacity(0.7) if repaint: layer.triggerRepaint() iface.setActiveLayer(layer) iface.zoomToActiveLayer() # NOTE QGIS3: probably not needed # iface.layerTreeView().refreshLayerSymbology(layer.id()) iface.mapCanvas().refresh()
def test_render_via_job(self): """ Test rendering an annotation layer via a map render job """ layer = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer.isValid()) item = QgsAnnotationPolygonItem( QgsPolygon( QgsLineString([ QgsPoint(11.5, 13), QgsPoint(12, 13), QgsPoint(12, 13.5), QgsPoint(11.5, 13) ]))) item.setSymbol( QgsFillSymbol.createSimple({ 'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2' })) item.setZIndex(1) i1_id = layer.addItem(item) item = QgsAnnotationLineItem( QgsLineString( [QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)])) item.setSymbol( QgsLineSymbol.createSimple({ 'color': '#ffff00', 'line_width': '3' })) item.setZIndex(2) i2_id = layer.addItem(item) item = QgsAnnotationMarkerItem(QgsPoint(12, 13)) item.setSymbol( QgsMarkerSymbol.createSimple({ 'color': '100,200,200', 'size': '6', 'outline_color': 'black' })) item.setZIndex(3) i3_id = layer.addItem(item) layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) settings = QgsMapSettings() settings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326')) settings.setExtent(QgsRectangle(10, 10, 18, 18)) settings.setOutputSize(QSize(200, 200)) settings.setLayers([layer]) job = QgsMapRendererParallelJob(settings) job.start() job.waitForFinished() # check rendered item results item_results = job.takeRenderedItemResults() item_details = item_results.renderedItems() self.assertEqual(len(item_details), 3) self.assertEqual([i.layerId() for i in item_details], [layer.id()] * 3) self.assertCountEqual([i.itemId() for i in item_details], [i1_id, i2_id, i3_id]) self.assertCountEqual([ i.itemId() for i in item_results.renderedAnnotationItemsInBounds( QgsRectangle(0, 0, 1, 1)) ], []) self.assertCountEqual([ i.itemId() for i in item_results.renderedAnnotationItemsInBounds( QgsRectangle(10, 10, 11, 18)) ], [i2_id]) self.assertCountEqual([ i.itemId() for i in item_results.renderedAnnotationItemsInBounds( QgsRectangle(10, 10, 12, 18)) ], [i1_id, i2_id, i3_id]) # bounds should be in map crs self.assertEqual( [i.boundingBox() for i in item_details if i.itemId() == i1_id][0], QgsRectangle(11.5, 13, 12, 13.5)) self.assertEqual( [i.boundingBox() for i in item_details if i.itemId() == i2_id][0], QgsRectangle(11, 13, 12, 15)) self.assertEqual([ i.boundingBox().toString(1) for i in item_details if i.itemId() == i3_id ][0], '11.5,12.5 : 12.5,13.5')
def setUp(self): # Create some simple symbols self.fill_symbol = QgsFillSymbol.createSimple({'color': '#ffffff', 'outline_color': 'black'}) self.line_symbol = QgsLineSymbol.createSimple({'color': '#ffffff', 'line_width': '3'}) self.marker_symbol = QgsMarkerSymbol.createSimple({'color': '#ffffff', 'size': '3', 'outline_color': 'black'}) self.report = "<h1>Python QgsSymbol Tests</h1>\n"
def testRenderLayerWithReferenceScale(self): layer = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) self.assertTrue(layer.isValid()) item = QgsAnnotationPolygonItem( QgsPolygon( QgsLineString([ QgsPoint(12, 13), QgsPoint(14, 13), QgsPoint(14, 15), QgsPoint(12, 13) ]))) item.setSymbol( QgsFillSymbol.createSimple({ 'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2' })) item.setZIndex(3) i1_id = layer.addItem(item) item = QgsAnnotationLineItem( QgsLineString( [QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)])) item.setSymbol( QgsLineSymbol.createSimple({ 'color': '#ffff00', 'line_width': '3' })) item.setZIndex(2) i2_id = layer.addItem(item) item = QgsAnnotationMarkerItem(QgsPoint(12, 13)) item.setSymbol( QgsMarkerSymbol.createSimple({ 'color': '100,200,200', 'size': '6', 'outline_color': 'black' })) item.setZIndex(1) i3_id = layer.addItem(item) settings = QgsMapSettings() settings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326')) settings.setExtent(QgsRectangle(10, 10, 18, 18)) settings.setOutputSize(QSize(300, 300)) settings.setFlag(QgsMapSettings.Antialiasing, False) rc = QgsRenderContext.fromMapSettings(settings) layer.item(i1_id).setUseSymbologyReferenceScale(True) layer.item(i1_id).setSymbologyReferenceScale(rc.rendererScale() * 2) # note item 3 has use symbology reference scale set to false, so should be ignored layer.item(i2_id).setUseSymbologyReferenceScale(False) layer.item(i2_id).setSymbologyReferenceScale(rc.rendererScale() * 2) layer.item(i3_id).setUseSymbologyReferenceScale(True) layer.item(i3_id).setSymbologyReferenceScale(rc.rendererScale() * 2) image = QImage(200, 200, QImage.Format_ARGB32) image.setDotsPerMeterX(int(96 / 25.4 * 1000)) image.setDotsPerMeterY(int(96 / 25.4 * 1000)) image.fill(QColor(255, 255, 255)) painter = QPainter(image) rc.setPainter(painter) try: renderer = layer.createMapRenderer(rc) renderer.render() finally: painter.end() self.assertTrue( self.imageCheck('layer_render_reference_scale', 'layer_render_reference_scale', image)) # also check details of rendered items item_details = renderer.takeRenderedItemDetails() self.assertEqual([i.layerId() for i in item_details], [layer.id()] * 3) self.assertCountEqual([i.itemId() for i in item_details], [i1_id, i2_id, i3_id]) self.assertEqual( [i.boundingBox() for i in item_details if i.itemId() == i1_id][0], QgsRectangle(12, 13, 14, 15)) self.assertEqual( [i.boundingBox() for i in item_details if i.itemId() == i2_id][0], QgsRectangle(11, 13, 12, 15)) self.assertEqual([ i.boundingBox().toString(1) for i in item_details if i.itemId() == i3_id ][0], '11.4,12.4 : 12.6,13.6')
def updateRenderer(self, layer, attribute_vals, settings): """ Creates a renderer for the layer based on this, and applies it The renderer uses GradientColourRamp to calculate the symbol colours @param layer: the selected QgsVectorLayer object """ geometry = layer.geometryType() # create a colour ramp based on colour range type, inverting symbols if required ramp_type = int(settings['colour_range']) invert = int(settings['invert_colour']) ramp = self.getColourRamp(ramp_type, invert) line_width = float(settings['line_width']) # calculate ranges: EqualInterval = 0; Quantile = 1; Jenks = 2; StdDev = 3; Pretty = 4; Custom = 5 intervals = int(settings['intervals']) mode = int(settings['interval_type']) attribute = attribute_vals['name'] renderer = None if mode < 3: # set symbol type and line width symbol = QgsSymbol.defaultSymbol(geometry) if symbol: if symbol.type() == 1: # line symbol.setWidth(line_width) elif symbol.type() == 2: # line symbol = QgsFillSymbol.createSimple({ 'style': 'solid', 'color': 'black', 'width_border': '%s' % line_width }) elif symbol.type() == 0: # point symbol.setSize(line_width) renderer = QgsGraduatedSymbolRenderer.createRenderer( layer, attribute, intervals, mode, symbol, ramp) renderer.setMode(mode) renderer.setSourceColorRamp(ramp) else: # calculate range values individually based on custom settings ranges = [] max_value = float(attribute_vals['max']) min_value = float(attribute_vals['min']) top_value = float(settings['top_value']) bottom_value = float(settings['bottom_value']) # calculate number of ranges depending on top/bottom difference from max/min: # is there really a range there? Otherwise this will calculate 1 or even 2 ranges less calc_intervals = intervals + 1 if top_value != max_value: calc_intervals -= 1 if bottom_value != min_value: calc_intervals -= 1 range_steps = [ r for r in np.linspace(bottom_value, top_value, calc_intervals) ] if top_value != max_value: range_steps.append(max_value) if bottom_value != min_value: range_steps.insert(0, min_value) for i in range(0, len(range_steps) - 1): symbol = QgsSymbol.defaultSymbol(geometry) if symbol: new_colour = ramp.color( i / (float(len(range_steps)) - 2)).getRgb() symbol.setColor(QColor(*new_colour)) symbol.setWidth(line_width) label = "%s - %s" % (range_steps[i], range_steps[i + 1]) this_range = QgsRendererRange(range_steps[i], range_steps[i + 1], symbol, label) ranges.append(this_range) if ranges: renderer = QgsGraduatedSymbolRenderer(attribute, ranges) # renderer.setMode(5) renderer.setSourceColorRamp(ramp) # configure symbol levels to display in specific order # the classic "reds on top" from space syntax, or the reverse if renderer: display_order = int(settings['display_order']) renderer.setUsingSymbolLevels(True) render_pass = 0 if display_order == 0: for symbol in renderer.symbols(QgsRenderContext()): for i in range(0, symbol.symbolLayerCount()): symbol.symbolLayer(i).setRenderingPass(render_pass) render_pass += 1 else: for symbol in reversed(renderer.symbols(QgsRenderContext())): for i in range(0, symbol.symbolLayerCount()): symbol.symbolLayer(i).setRenderingPass(render_pass) render_pass += 1 # set the symbols for monochrome ramp # varying line width, point size or polygon pattern density # doesn't use data column because it's not scaled according to line width values # the width is calculated linearly between min and given value if renderer: if ramp_type == 3: new_width = np.linspace(0.1, line_width, intervals) step = intervals / 8.0 # this is usd for fill patterns # color = QColor(ramp.color(0).getRgb()) # same as above for i in range(0, intervals): symbol = renderer.symbols(QgsRenderContext())[i] if invert: if symbol.type() == 1: # line symbol.setWidth(new_width[(intervals - 1) - i]) elif symbol.type() == 0: # point symbol.setSize(new_width[(intervals - 1) - i]) elif symbol.type() == 2: # polygon dense = int(i / step) if dense == 0: style = 'solid' else: style = 'dense%s' % dense symbol = QgsFillSymbol.createSimple({ 'style': style, 'color': 'black', 'width_border': '%s' % new_width[(intervals - 1) - i] }) else: if symbol.type() == 1: # line symbol.setWidth(new_width[i]) elif symbol.type() == 0: # point symbol.setSize(new_width[i]) elif symbol.type() == 2: # polygon dense = int(i / step) if dense == 7: style = 'solid' else: style = 'dense%s' % (7 - dense) symbol = QgsFillSymbol.createSimple({ 'style': style, 'color': 'black', 'width_border': '%s' % new_width[i] }) renderer.updateRangeSymbol(i, symbol) return renderer
def testRenderWithTransform(self): layer = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer.isValid()) item = QgsAnnotationPolygonItem( QgsPolygon( QgsLineString([ QgsPoint(11.5, 13), QgsPoint(12, 13), QgsPoint(12, 13.5), QgsPoint(11.5, 13) ]))) item.setSymbol( QgsFillSymbol.createSimple({ 'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2' })) item.setZIndex(1) i1_id = layer.addItem(item) item = QgsAnnotationLineItem( QgsLineString( [QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)])) item.setSymbol( QgsLineSymbol.createSimple({ 'color': '#ffff00', 'line_width': '3' })) item.setZIndex(2) i2_id = layer.addItem(item) item = QgsAnnotationMarkerItem(QgsPoint(12, 13)) item.setSymbol( QgsMarkerSymbol.createSimple({ 'color': '100,200,200', 'size': '6', 'outline_color': 'black' })) item.setZIndex(3) i3_id = layer.addItem(item) layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) settings = QgsMapSettings() settings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857')) settings.setExtent(QgsRectangle(1250958, 1386945, 1420709, 1532518)) settings.setOutputSize(QSize(300, 300)) settings.setFlag(QgsMapSettings.Antialiasing, False) rc = QgsRenderContext.fromMapSettings(settings) rc.setCoordinateTransform( QgsCoordinateTransform(layer.crs(), settings.destinationCrs(), QgsProject.instance())) rc.setExtent(rc.coordinateTransform().transformBoundingBox( settings.extent(), QgsCoordinateTransform.ReverseTransform)) image = QImage(200, 200, QImage.Format_ARGB32) image.setDotsPerMeterX(int(96 / 25.4 * 1000)) image.setDotsPerMeterY(int(96 / 25.4 * 1000)) image.fill(QColor(255, 255, 255)) painter = QPainter(image) rc.setPainter(painter) try: renderer = layer.createMapRenderer(rc) renderer.render() finally: painter.end() self.assertTrue( self.imageCheck('layer_render_transform', 'layer_render_transform', image)) # also check details of rendered items item_details = renderer.takeRenderedItemDetails() self.assertEqual([i.layerId() for i in item_details], [layer.id()] * 3) self.assertCountEqual([i.itemId() for i in item_details], [i1_id, i2_id, i3_id]) self.assertEqual( [i.boundingBox() for i in item_details if i.itemId() == i1_id][0], QgsRectangle(11.5, 13, 12, 13.5)) self.assertEqual( [i.boundingBox() for i in item_details if i.itemId() == i2_id][0], QgsRectangle(11, 13, 12, 15)) self.assertEqual([ i.boundingBox().toString(2) for i in item_details if i.itemId() == i3_id ][0], '11.94,12.94 : 12.06,13.06')
def testCase(self): self.TEST_DATA_DIR = unitTestDataPath() tmppath = tempfile.mkdtemp() for file in glob.glob(os.path.join(self.TEST_DATA_DIR, 'france_parts.*')): shutil.copy(os.path.join(self.TEST_DATA_DIR, file), tmppath) vectorFileInfo = QFileInfo(tmppath + "/france_parts.shp") mVectorLayer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") QgsProject.instance().addMapLayers([mVectorLayer]) self.layers = [mVectorLayer] # create composition with composer map # select epsg:2154 crs = QgsCoordinateReferenceSystem() crs.createFromSrid(2154) QgsProject.instance().setCrs(crs) self.mComposition = QgsComposition(QgsProject.instance()) self.mComposition.setPaperSize(297, 210) # fix the renderer, fill with green props = {"color": "0,127,0"} fillSymbol = QgsFillSymbol.createSimple(props) renderer = QgsSingleSymbolRenderer(fillSymbol) mVectorLayer.setRenderer(renderer) # the atlas map self.mAtlasMap = QgsComposerMap(self.mComposition, 20, 20, 130, 130) self.mAtlasMap.setFrameEnabled(True) self.mAtlasMap.setLayers([mVectorLayer]) self.mComposition.addComposerMap(self.mAtlasMap) # the atlas self.mAtlas = self.mComposition.atlasComposition() self.mAtlas.setCoverageLayer(mVectorLayer) self.mAtlas.setEnabled(True) self.mComposition.setAtlasMode(QgsComposition.ExportAtlas) # an overview self.mOverview = QgsComposerMap(self.mComposition, 180, 20, 50, 50) self.mOverview.setFrameEnabled(True) self.mOverview.overview().setFrameMap(self.mAtlasMap.id()) self.mOverview.setLayers([mVectorLayer]) self.mComposition.addComposerMap(self.mOverview) nextent = QgsRectangle(49670.718, 6415139.086, 699672.519, 7065140.887) self.mOverview.setNewExtent(nextent) # set the fill symbol of the overview map props2 = {"color": "127,0,0,127"} fillSymbol2 = QgsFillSymbol.createSimple(props2) self.mOverview.overview().setFrameSymbol(fillSymbol2) # header label self.mLabel1 = QgsComposerLabel(self.mComposition) self.mComposition.addComposerLabel(self.mLabel1) self.mLabel1.setText("[% \"NAME_1\" %] area") self.mLabel1.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel1.adjustSizeToText() self.mLabel1.setSceneRect(QRectF(150, 5, 60, 15)) qWarning( "header label font: %s exactMatch:%s" % (self.mLabel1.font().toString(), self.mLabel1.font().exactMatch())) # feature number label self.mLabel2 = QgsComposerLabel(self.mComposition) self.mComposition.addComposerLabel(self.mLabel2) self.mLabel2.setText("# [%@atlas_featurenumber || ' / ' || @atlas_totalfeatures%]") self.mLabel2.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel2.adjustSizeToText() self.mLabel2.setSceneRect(QRectF(150, 200, 60, 15)) qWarning("feature number label font: %s exactMatch:%s" % ( self.mLabel2.font().toString(), self.mLabel2.font().exactMatch())) self.filename_test() self.autoscale_render_test() self.fixedscale_render_test() self.predefinedscales_render_test() self.hidden_render_test() self.legend_test() shutil.rmtree(tmppath, True)
def testReprojectionErrorsWhileRendering(self): # WKT of a polygon which causes reprojection errors while rendering # (apologies for the ridiculously complex wkt, but I can't find a way to reproduce with simplifiction) wkt = 'MultiPolygon (((16.93392988400009358 42.77094147300012139, 16.88493899800005238 42.72939687700012712, ' \ '16.80298912900011032 42.76349518400014915, 16.85816491000014139 42.78400299700011544, ' \ '16.93392988400009358 42.77094147300012139)),((17.38200931100010393 42.79783763200002511, ' \ '17.65894616000011297 42.74298737200008702, 17.74887129000009622 42.69456614800010641, ' \ '17.32374108200008322 42.79083893400003547, 17.38200931100010393 42.79783763200002511)),' \ '((16.768565300000148 42.97223541900014254, 17.03207441500009622 42.98261139500014849, ' \ '17.13184655000009116 42.96954987200014386, 17.20020592500009116 42.92177969000012183, ' \ '16.85141035200010151 42.90070221600008438, 16.65544681100004709 42.92625560099999404, ' \ '16.70679772200014668 42.96954987200014386, 16.63168379000003938 42.98261139500014849, ' \ '16.768565300000148 42.97223541900014254)),((17.05567467500011958 43.02895742400001211, ' \ '17.24024498800011429 43.02277252800014651, 17.74146569100011561 42.83926015800001608, ' \ '17.70736738400009358 42.88703034100014122, 17.65334906206413734 42.8909283361407887, ' \ '17.70158573400010482 42.91950022500007833, 17.81175988700005064 42.909862570000044, ' \ '17.85847538200005147 42.81697418200012351, 18.22413781700009849 42.62807098500009317, ' \ '18.43735477700010961 42.55921213800017711, 18.4371480710000526 42.4934022020000981, ' \ '18.49642988400009358 42.41632721600008438, 18.23894290500010129 42.55906810100005089, ' \ '18.21753991000014139 42.6201032570001388, 18.07601972700010151 42.65131256700003348, ' \ '18.0432235040000819 42.70205312700007028, 17.90162194100014403 42.75189850500014188, ' \ '17.8928328790000819 42.79083893400003547, 17.72095787900005348 42.8262393250000315, ' \ '17.7618921230000808 42.77871328300012976, 17.74870853000004445 42.77204010600017625, ' \ '17.21387780000011958 42.98261139500014849, 17.04615319100011561 42.9950625670000619, ' \ '17.00163821700004974 43.05149974200010377, 17.05567467500011958 43.02895742400001211)),' \ '((16.19467207100007045 43.07440827000000638, 16.254893425000148 43.06854889500006323, ' \ '16.08716881600014403 43.01146067900008063, 16.04883873800011429 43.06517161700004692, ' \ '16.19467207100007045 43.07440827000000638)),((16.56275475400011032 43.22898997600010773, ' \ '16.65951582100009887 43.21596914300012315, 16.72771243600001867 43.16461823100003414, ' \ '17.19336998800014271 43.12726471600016964, 16.67017662900013875 43.12547435099999404, ' \ '16.37159264400014536 43.19550202000006323, 16.49642988400006516 43.21808502800014651, ' \ '16.58326256600014403 43.18866608300005794, 16.52051842500006273 43.22898997600010773, ' \ '16.56275475400011032 43.22898997600010773)),((16.80681399800010922 43.34247467700005529, ' \ '16.89234459700011826 43.31220123900006058, 16.84620201900008851 43.27338288000005662, ' \ '16.62826582100012729 43.26373932500008834, 16.50074303500014139 43.28424713700003679, ' \ '16.42188561300008587 43.31757233300011478, 16.40577233200011165 43.33270905200011214, ' \ '16.45346113400009358 43.35317617400009738, 16.42628014400008851 43.39411041900011412, ' \ '16.44703209700008983 43.39484284100014122, 16.80681399800010922 43.34247467700005529)),' \ '((16.29818769600012729 43.40363190300011809, 16.30274498800008587 43.38727448100009099, ' \ '16.39144941500012465 43.34638092700005529, 16.348643425000148 43.33869049700003018, ' \ '16.20045006600014403 43.40704987200003018, 16.29818769600012729 43.40363190300011809)),' \ '((16.33415774800010922 43.50153229400014254, 16.3752547540000819 43.49017975500008504, ' \ '16.21143639400008851 43.49005768400009231, 16.26441491000014139 43.51288483300011478, ' \ '16.33415774800010922 43.50153229400014254)),((15.67888431100004709 43.64801666900014254, ' \ '15.74040774800010922 43.62750885600009099, 15.67204837300002396 43.63743724200010377, ' \ '15.60377037900013875 43.67470937700007028, 15.67888431100004709 43.64801666900014254)),' \ '((15.36736087300005238 43.79010651200015047, 15.39568118600007551 43.7724063170000619, ' \ '15.22779381600014403 43.87445709800014981, 15.24073326900014536 43.88076406500009341, ' \ '15.36736087300005238 43.79010651200015047)),((15.44271894600009887 43.89907461100013109, ' \ '15.35865319100014403 43.91937897300014981, 15.26124108200011165 44.01105377800003282, ' \ '15.38404381600008719 43.9701602230000077, 15.44271894600009887 43.89907461100013109)),' \ '((15.22575931100010393 44.06622955900014915, 15.25440514400008851 44.01788971600014122, ' \ '15.12183678500014139 44.09223053600005926, 15.06251061300008587 44.16193268400012073, ' \ '15.22575931100010393 44.06622955900014915)),((14.83545983200014007 44.15102773600013109, ' \ '14.85726972700010151 44.15204498900000374, 14.86915123800014271 44.14052969000006499, ' \ '14.83521569100008719 44.14166901200009363, 14.81983483200014007 44.15302155199999845, ' \ '14.82243899800005238 44.16868724200004692, 14.83545983200014007 44.15102773600013109)),' \ '((14.98511803500011297 44.09096914300012315, 15.21680748800008587 43.91278717700008372, ' \ '15.13331139400011693 43.92121002800003282, 15.19450931100004709 43.87262604400017096, ' \ '15.10661868600007551 43.92544179900015422, 14.84961998800014271 44.17560455900014915, ' \ '14.98511803500011297 44.09096914300012315)),((14.765961134000122 44.26504140800015819, ' \ '14.74854576900014536 44.26166413000014188, 14.73959394600012729 44.28017812700015554, ' \ '14.79167728000007287 44.27252838700003679, 14.765961134000122 44.26504140800015819)),' \ '((14.66138756600011561 44.30866120000014519, 14.6407983730000808 44.31183502800003282, ' \ '14.59506269600007045 44.34711334800006455, 14.643565300000148 44.32575104400011412, ' \ '14.66138756600011561 44.30866120000014519)),((14.81120853000004445 44.35004303600000242, ' \ '14.75619550900009358 44.36399974200004692, 14.76343834700008983 44.41535065300017493, ' \ '14.80323326900008851 44.40550364800004957, 14.81120853000004445 44.35004303600000242)),' \ '((14.27116946700002131 44.61253489800004957, 14.23259524800005238 44.62604401200012205, ' \ '14.2657983730000808 44.67951080900003547, 14.28044681100007551 44.67755768400009231, ' \ '14.27116946700002131 44.61253489800004957)),((14.84522545700008322 44.60053131700011875, ' \ '14.93824303500014139 44.59414297100001079, 15.07553144600007045 44.48407623900006058, ' \ '14.91114342500011958 44.54547760600014783, 15.04802493600004709 44.43943919500001982, ' \ '15.09669030000009116 44.41518789300000947, 15.04151451900014536 44.47662995000008834, ' \ '15.25440514400008851 44.34003327000000638, 15.165049675000148 44.36737702000006323, ' \ '15.22022545700008322 44.3127302100001117, 15.13086998800008587 44.33258698100003414, ' \ '15.17237389400014536 44.29913971600016964, 15.12875410200007309 44.31199778900018771, ' \ '15.08920332100009887 44.37421295800000109, 15.11719811300014271 44.38719310099999404, ' \ '15.04900149800010922 44.39468008000015686, 14.89747155000009116 44.49091217699999845, ' \ '14.91863040500010129 44.50454336100013109, 14.87696373800011429 44.55975983300005794, ' \ '14.73365319100008719 44.70319245000014519, 14.84522545700008322 44.60053131700011875)),' \ '((14.41000410200010151 44.60097890800001608, 14.52662194100011561 44.50372955900012073, ' \ '14.53435306100010393 44.48407623900006058, 14.42261803500008455 44.57387929900009738, ' \ '14.36304772200014668 44.57343170800000109, 14.38257897200014668 44.60325755399999537, ' \ '14.33578535200007309 44.71678294500010509, 14.39747155000009116 44.6856143250000315, ' \ '14.41000410200010151 44.60097890800001608)),((14.75326582100007045 44.84585195500012844, ' \ '14.74048912900011032 44.82050202000000638, 14.82243899800005238 44.77142975500005662, ' \ '14.84961998800014271 44.70319245000014519, 14.65788821700004974 44.79877350500014188, ' \ '14.7268172540000819 44.79877350500014188, 14.6858016290000819 44.8471540390000456, ' \ '14.75326582100007045 44.84585195500012844)),((14.47103925900006516 44.95392487200003018, ' \ '14.45191491000008455 44.79877350500014188, 14.47217858200011165 44.7079531920000619, ' \ '14.53435306100010393 44.63426341400010244, 14.51335696700007816 44.618841864000089, ' \ '14.42790774800005238 44.65656159100014122, 14.29420006600008719 44.9086367860001161, ' \ '14.30152428500011297 44.94342682500014519, 14.38738040500004445 44.90900299700003018, ' \ '14.39031009200004974 44.96039459800012139, 14.41138756600008719 44.95636627800014651, ' \ '14.27849368600004709 45.1133487000000315, 14.29957116000014139 45.16233958499999801, ' \ '14.35621178500014139 45.16925690300008966, 14.387705925000148 45.03904857000013351, ' \ '14.47103925900006516 44.95392487200003018)),((14.56332441500012465 45.24974192900008063, ' \ '14.62378991000011297 45.17548248900006058, 14.59742272200011826 45.16644928600005926, ' \ '14.66529381600011561 45.16181061400011743, 14.66529381600011561 45.08734772300006455, ' \ '14.74048912900011032 45.07306549700014386, 14.81495201900008851 44.97748444200009033, ' \ '14.70639082100009887 44.9467227230000077, 14.62891686300014271 44.97817617400004053, ' \ '14.62086022200008983 45.04559967700011214, 14.61695397200008983 45.02464427300007799, ' \ '14.51050866000014139 45.03217194200011875, 14.43873131600014403 45.07050202000006323, ' \ '14.4670516290000819 45.12409088700015047, 14.53012129000009622 45.13483307500014519, ' \ '14.53435306100010393 45.23753489800002114, 14.56332441500012465 45.24974192900008063)),' \ '((16.36947066200013978 46.54057118800012915, 16.63767134600004738 46.47447703100009164, ' \ '16.75508020000012266 46.38187286400001597, 16.83765913900006694 46.38187286400001597, ' \ '16.88923221800007468 46.29216257800014489, 17.05294315600005461 46.15346303300005104, ' \ '17.20859257000006437 46.11656606000003933, 17.27587528500004055 46.01202463800002818, ' \ '17.31680301900004793 45.99765859000002877, 17.29013798000011093 45.98463612900009423, ' \ '17.40620324700006449 45.94365671800015605, 17.59110152100009827 45.93621531200012953, ' \ '17.65652388500006964 45.84541982000014571, 17.80917606600013414 45.81441396100005647, ' \ '17.85806197100004056 45.77172922800004073, 18.21121870900006456 45.78537180600012846, ' \ '18.40438521300006869 45.74180857400001798, 18.57347049900010916 45.81668772400014689, ' \ '18.6556360270001278 45.90758656800015558, 18.7755253500000947 45.88283355700004051, ' \ '18.90130578600007993 45.93120269800006383, 18.87288374800004931 45.89523590100002082, ' \ '18.90699019400011593 45.86795074500018643, 18.85531376100007606 45.85735707600009903, ' \ '18.84497847500006174 45.8157058720000947, 18.96848514800012708 45.66873809800016204, ' \ '18.90357954900008508 45.57308502200005762, 18.94171675700005153 45.53892689999999277, ' \ '19.01809452300011571 45.56740061400002162, 19.10625451700005328 45.51164174500017623, ' \ '19.00961958800010621 45.49867095900005154, 19.00300500400010151 45.45536611000007099, ' \ '19.03742150900006891 45.42229319300010104, 18.97592655400006834 45.39495636000008005, ' \ '19.09199182100007874 45.34999786400005917, 19.12475467900009107 45.29811472600006539, ' \ '19.36308638500014467 45.24824696900010679, 19.40783817500010855 45.20313344400013023, ' \ '19.39068160000005037 45.16933705700016333, 19.22593713300008744 45.16194732700016345, ' \ '19.12186079900010327 45.195795390000157, 19.13767378700009658 45.14603098600004216, ' \ '19.04486291500009543 45.13724599300006446, 19.08227665200013234 45.08494944300004192, ' \ '19.0872375890000967 44.97710072800013847, 19.13167932100006396 44.95317454000003465, ' \ '19.06667036900009293 44.90568389900012392, 18.99142948400006503 44.9149339800001286, ' \ '19.01582076000008215 44.86563466400004074, 18.88962691200009658 44.86119049100013001, ' \ '18.78338016700013213 44.91374542300012251, 18.79175174900009893 45.00154368100008639, ' \ '18.73831831900008638 45.0159097290000858, 18.68405806500004473 45.08479441400000098, ' \ '18.64871138500012648 45.06267689999999959, 18.61667199700013953 45.09766184500010411, ' \ '18.54959598800010667 45.09476796500011631, 18.51703983500007666 45.05585561200003042, ' \ '18.23788374800011525 45.15745147700012296, 18.15365116400005263 45.0975584930001645, ' \ '18.00347945100011771 45.1493382780000303, 17.83573775200005684 45.0644338990000648, ' \ '17.68473921700012852 45.1639627080000281, 17.48185754400009273 45.11440500900012296, ' \ '17.49622359200009214 45.1416901650001563, 17.44775109900012922 45.13430043600014585, ' \ '17.44330692500011537 45.16205068000009248, 17.38243208800008688 45.1396231090000839, ' \ '17.26895064300006766 45.18954254200015441, 17.24548954300007608 45.15538442000017483, ' \ '17.18709517400012032 45.14856313100001728, 17.0363033440001459 45.23047027600007652, ' \ '17.00829471800011561 45.21615590500009318, 17.00829471800011561 45.24416453100009505, ' \ '16.94731652900014751 45.23568959600000028, 16.9243721930001243 45.28452382500016427, ' \ '16.81171757000004163 45.18122263700009, 16.52894413300009546 45.22225372400005483, ' \ '16.38921106000003647 45.11683380099999852, 16.31624393700010955 45.00123362300008978, ' \ '16.12152714000009723 45.09616322900008356, 16.02044803900011516 45.213933818000001, ' \ '15.79234826700013627 45.18980092400012438, 15.76361617000014803 44.97555043600003444, ' \ '15.7308533120001357 44.92723297200008403, 15.77343469200010873 44.84501576800015243, ' \ '15.71607385200013596 44.80320953400008932, 15.72847619600008784 44.76910308800002269, ' \ '15.80568078600006743 44.69665273000013883, 15.88877648900006534 44.72424794500012979, ' \ '15.96897831200004703 44.63924021400013942, 16.02830285600006732 44.62471913700009907, ' \ '16.04473596200011798 44.58937245700018082, 16.00608199000004106 44.54100331600012908, ' \ '16.11646285000011858 44.52146962500013672, 16.15966434700004584 44.41610138000002905, ' \ '16.13827030500004867 44.37760243800015303, 16.20286584400008678 44.35977406800010669, ' \ '16.18756962000011868 44.28241444999999032, 16.21578495300011014 44.20815541600011045, ' \ '16.32688928200008149 44.08237498000012522, 16.50103885900011846 43.99271637000008184, ' \ '16.67859908100004418 43.8406843060001421, 16.71260217300007866 43.77151540100005889, ' \ '17.03051558500007445 43.54847991900005866, 17.27050093600007585 43.46321380700000248, ' \ '17.28993127500007176 43.3034302780000786, 17.44206669100009321 43.15243174300015028, ' \ '17.6284119050001209 43.04657257100008394, 17.66272505700004558 42.96569895500012137, ' \ '17.63450972400008254 42.950402731000068, 17.51563561300008587 42.95888906500012183, ' \ '17.47087649800005238 43.01341380400010905, 17.50196373800014271 43.03099192900005221, ' \ '17.43360436300014271 43.01740143400009231, 17.46021569100011561 43.03099192900005221, ' \ '17.42611738400009358 43.06517161700004692, 17.4045516290000819 43.05149974200010377, ' \ '17.31625410200012993 43.12726471600016964, 17.11394290500004445 43.21320221600008438, ' \ '16.88062584700011826 43.40595123900006058, 16.62582441500009622 43.44904205900009231, ' \ '16.52466881600011561 43.51080963700009363, 16.39144941500012465 43.51080963700009363, ' \ '16.47339928500008455 43.5381533870001789, 16.43384850400013875 43.54975006700000506, ' \ '16.11768639400008851 43.52448151200003679, 16.17237389400014536 43.4896914730000077, ' \ '16.11312910200004467 43.47890859600009605, 15.95948326900011693 43.50397370000008834, ' \ '15.987315300000148 43.54490794500010509, 15.92530358200011165 43.55857982000004824, ' \ '15.91895592500009116 43.62872955900012073, 15.96631920700011165 43.64118073100003414, ' \ '15.90479576900014536 43.64801666900014254, 15.95297285200010151 43.65086497599999404, ' \ '15.95045006600008719 43.68854401200015047, 15.70630944100008719 43.76341380400005221, ' \ '15.6174422540000819 43.82550690300017493, 15.66309655000009116 43.81297435099999404, ' \ '15.67888431100004709 43.81928131700011875, 15.45508873800014271 43.92804596600014122, ' \ '15.14454186300011429 44.19546133000015686, 15.15219160200012993 44.23529694200014717, ' \ '15.11036217500011958 44.26434967700011214, 15.14063561300011429 44.28245677300013483, ' \ '15.17660566500009622 44.24994538000005662, 15.20777428500008455 44.27277252800014651, ' \ '15.19809004000012465 44.30166250200007028, 15.295258009000122 44.25067780199999845, ' \ '15.30274498800008587 44.29913971600016964, 15.26124108200011165 44.33258698100003414, ' \ '15.42448978000001603 44.26797109600006763, 15.52865644600009887 44.27179596600008438, ' \ '15.30795332100009887 44.35439687700007028, 15.00733483200014007 44.56972890800012976, ' \ '14.883799675000148 44.7236188820001388, 14.883799675000148 44.86147695500012844, 14.92164147200008983 ' \ '44.95880768400009231, 14.85279381600011561 45.09365469000000815, 14.65788821700004974 ' \ '45.19660065300017493, 14.57081139400008851 45.29364655200011214, 14.31153405000009116 ' \ '45.34398021000005485, 14.23259524800005238 45.14935944200000506, 14.17937259200007816 ' \ '45.13450755400005221, 14.19312584700008983 45.10561758000012844, 14.14389082100007045 ' \ '45.05939362200003018, 14.151377800000148 44.97748444200009033, 14.06885826900014536 ' \ '44.94953034100014122, 14.08383222700007309 44.9863955750000315, 14.04029381600014403 ' \ '45.03896719000015025, 14.0756942070000548 44.98371002800003282, 14.02051842500011958 ' \ '44.90110911700004692, 13.97266686300011429 44.90110911700004692, 13.99301191500009622 ' \ '44.88129303600014453, 13.97266686300011429 44.82664622599999404, 14.00001061300008587 ' \ '44.81305573100003414, 13.89014733200011165 44.83348216400010244, 13.91797936300014271 ' \ '44.77826569200009033, 13.90316816500009622 44.77240631700014717, 13.89698326900011693 ' \ '44.81305573100003414, 13.78711998800014271 44.87506745000008834, 13.84229576900008851 ' \ '44.88812897300006455, 13.79460696700010658 44.89496491100008768, 13.77409915500007287 ' \ '44.96381256700014717, 13.6232202480000808 45.07306549700014386, 13.61255944100014403 ' \ '45.11786530199999845, 13.72624759200004974 45.13450755400005221, 13.5959578790000819 ' \ '45.14541250200001343, 13.57545006600011561 45.26487864800007799, 13.60271243600001867 ' \ '45.28534577000012007, 13.57545006600011561 45.30646393400006389, 13.60954837300005238 ' \ '45.32013580900017757, 13.54127037900013875 45.34613678600005926, 13.50709069100014403 ' \ '45.51190827000000638, 13.62901778100007277 45.45898346000016943, 13.75929406800014476 ' \ '45.46316925100011019, 13.88900191200011136 45.42363678000005223, 13.98263960800005634 ' \ '45.47531321200001742, 13.97189091000012695 45.5142255660000643, 14.09291711400010172 ' \ '45.47391794800002174, 14.21869755100007637 45.49717234400004884, 14.37279667100006009 ' \ '45.47784535800009564, 14.4689148350000778 45.52559438100014688, 14.49857710800012001 ' \ '45.59618438800005435, 14.58094934100009255 45.66780792200010808, 14.66848921700008646 ' \ '45.53396596300005683, 14.79716353300005949 45.46518463200006011, 14.88160282300009385 ' \ '45.46978383400001178, 14.9226339110000481 45.51494903600017494, 15.13926151500010064 ' \ '45.43004465799999991, 15.32519331800011742 45.45283396399999276, 15.36136682100004691 ' \ '45.48203114900003641, 15.29666792800006192 45.52295888300012905, 15.2685559480001416 ' \ '45.60166208900012919, 15.37376916500011248 45.64021270800010655, 15.25501672300006817 ' \ '45.72346344000011698, 15.42906294700014769 45.77529490200011253, 15.45128381300008868 ' \ '45.81513743100013869, 15.67607629400006886 45.84169911700014666, 15.65943648300003588 ' \ '45.88882802400014782, 15.69798710100010908 46.0362092080000167, 15.58988000500005455 ' \ '46.11351715100001059, 15.62284956800010605 46.19170359400006021, 16.01920780400010358 ' \ '46.29882883700007312, 16.05961877400008575 46.33231516600015709, 16.0579651280001201 ' \ '46.37753204400003426, 16.2756262620000598 46.37316538500006402, 16.23490523300009158 ' \ '46.4933389280001137, 16.36947066200013978 46.54057118800012915))) ' geom = QgsGeometry.fromWkt(wkt) f = QgsFeature() f.setGeometry(geom) image = QImage(200, 200, QImage.Format_RGB32) painter = QPainter() ms = QgsMapSettings() crs = QgsCoordinateReferenceSystem.fromProj4( '+proj=ortho +lat_0=36.5 +lon_0=-118.8 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs' ) self.assertTrue(crs.isValid()) ms.setDestinationCrs(crs) ms.setExtent(QgsRectangle(1374999.8, 3912610.7, 4724462.5, 6505499.6)) ms.setOutputSize(image.size()) context = QgsRenderContext.fromMapSettings(ms) context.setPainter(painter) context.setScaleFactor(96 / 25.4) # 96 DPI ct = QgsCoordinateTransform(QgsCoordinateReferenceSystem('epsg:4326'), crs, QgsProject.instance()) self.assertTrue(ct.isValid()) context.setCoordinateTransform(ct) context.setExtent( ct.transformBoundingBox(ms.extent(), QgsCoordinateTransform.ReverseTransform)) fill_symbol = QgsFillSymbol.createSimple({ 'color': '#ffffff', 'outline_color': '#ffffff', 'outline_width': '10' }) painter.begin(image) try: image.fill(QColor(0, 0, 0)) fill_symbol.startRender(context) fill_symbol.renderFeature(f, context) fill_symbol.stopRender(context) finally: painter.end() assert self.imageCheck('Reprojection errors polygon', 'reprojection_errors_polygon', image) #also test linestring linestring = QgsGeometry(geom.constGet().boundary()) f.setGeometry(linestring) line_symbol = QgsLineSymbol.createSimple({ 'color': '#ffffff', 'outline_width': '10' }) image = QImage(200, 200, QImage.Format_RGB32) painter.begin(image) try: image.fill(QColor(0, 0, 0)) line_symbol.startRender(context) line_symbol.renderFeature(f, context) line_symbol.stopRender(context) finally: painter.end() assert self.imageCheck('Reprojection errors linestring', 'reprojection_errors_linestring', image)
def test_render_via_job_with_transform(self): """ Test rendering an annotation layer via a map render job """ layer = QgsAnnotationLayer( 'test', QgsAnnotationLayer.LayerOptions( QgsProject.instance().transformContext())) self.assertTrue(layer.isValid()) item = QgsAnnotationPolygonItem( QgsPolygon( QgsLineString([ QgsPoint(11.5, 13), QgsPoint(12, 13), QgsPoint(12, 13.5), QgsPoint(11.5, 13) ]))) item.setSymbol( QgsFillSymbol.createSimple({ 'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2' })) item.setZIndex(1) i1_id = layer.addItem(item) item = QgsAnnotationLineItem( QgsLineString( [QgsPoint(11, 13), QgsPoint(12, 13), QgsPoint(12, 15)])) item.setSymbol( QgsLineSymbol.createSimple({ 'color': '#ffff00', 'line_width': '3' })) item.setZIndex(2) i2_id = layer.addItem(item) item = QgsAnnotationMarkerItem(QgsPoint(12, 13)) item.setSymbol( QgsMarkerSymbol.createSimple({ 'color': '100,200,200', 'size': '6', 'outline_color': 'black' })) item.setZIndex(3) i3_id = layer.addItem(item) layer.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) settings = QgsMapSettings() settings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857')) settings.setExtent(QgsRectangle(1250958, 1386945, 1420709, 1532518)) settings.setOutputSize(QSize(200, 200)) settings.setLayers([layer]) job = QgsMapRendererSequentialJob(settings) job.start() job.waitForFinished() # check rendered item results item_results = job.takeRenderedItemResults() item_details = item_results.renderedItems() self.assertEqual(len(item_details), 3) self.assertEqual([i.layerId() for i in item_details], [layer.id()] * 3) self.assertCountEqual([i.itemId() for i in item_details], [i1_id, i2_id, i3_id]) # bounds should be in map crs self.assertEqual( [ QgsGeometry.fromRect(i.boundingBox()).asWkt(0) for i in item_details if i.itemId() == i1_id ][0], 'Polygon ((1280174 1459732, 1335834 1459732, 1335834 1516914, 1280174 1516914, 1280174 1459732))' ) self.assertEqual( [ QgsGeometry.fromRect(i.boundingBox()).asWkt(0) for i in item_details if i.itemId() == i2_id ][0], 'Polygon ((1224514 1459732, 1335834 1459732, 1335834 1689200, 1224514 1689200, 1224514 1459732))' ) expected = 'Polygon ((1325786 1449684, 1345882 1449684, 1345882 1469780, 1325786 1469780, 1325786 1449684))' result = [ QgsGeometry.fromRect(i.boundingBox()).asWkt(0) for i in item_details if i.itemId() == i3_id ][0] self.assertTrue( compareWkt(result, expected, tol=1000), "mismatch Expected:\n{}\nGot:\n{}\n".format(expected, result))
def testClippingHideClipSource(self): """ When an item is set to be the clip source, it shouldn't render anything itself """ format = QgsTextFormat() format.setFont(QgsFontUtils.getStandardTestFont("Bold")) format.setSize(30) format.setNamedStyle("Bold") format.setColor(QColor(0, 0, 0)) settings = QgsPalLayerSettings() settings.setFormat(format) settings.fieldName = "'XXXX'" settings.isExpression = True settings.placement = QgsPalLayerSettings.OverPoint vl = QgsVectorLayer("Polygon?crs=epsg:4326&field=id:integer", "vl", "memory") props = { "color": "127,255,127", 'outline_style': 'solid', 'outline_width': '1', 'outline_color': '0,0,255' } fillSymbol = QgsFillSymbol.createSimple(props) renderer = QgsSingleSymbolRenderer(fillSymbol) vl.setRenderer(renderer) f = QgsFeature(vl.fields(), 1) for x in range(0, 15, 3): for y in range(0, 15, 3): f.setGeometry(QgsGeometry(QgsPoint(x, y)).buffer(1, 3)) vl.dataProvider().addFeature(f) vl.setLabeling(QgsVectorLayerSimpleLabeling(settings)) vl.setLabelsEnabled(True) p = QgsProject() p.addMapLayer(vl) layout = QgsLayout(p) layout.initializeDefaults() p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326')) map = QgsLayoutItemMap(layout) map.attemptSetSceneRect(QRectF(10, 10, 180, 180)) map.setFrameEnabled(False) map.zoomToExtent(vl.extent()) map.setLayers([vl]) layout.addLayoutItem(map) shape = QgsLayoutItemShape(layout) layout.addLayoutItem(shape) shape.setShapeType(QgsLayoutItemShape.Ellipse) shape.attemptSetSceneRect(QRectF(10, 10, 180, 180)) map.itemClippingSettings().setEnabled(True) map.itemClippingSettings().setSourceItem(shape) map.itemClippingSettings().setForceLabelsInsideClipPath(False) map.itemClippingSettings().setFeatureClippingType( QgsMapClippingRegion.FeatureClippingType.ClipToIntersection) checker = QgsLayoutChecker('composermap_itemclip_nodrawsource', layout) checker.setControlPathPrefix("composer_map") result, message = checker.testLayout() TestQgsLayoutMap.report += checker.report() self.assertTrue(result, message)
def run(self): print ("paso por el run") #coloco el puntero arriba del todo QgsProject.instance().layerTreeRegistryBridge().setLayerInsertionPoint( QgsProject.instance().layerTreeRoot(), 0 ) """Run method that performs all the real work""" #genero una lista con las columnas de la capa de puntos vl2=iface.activeLayer() if vl2 is None: iface.messageBar().pushMessage("ATENCION", "Selecciona una capa de puntos", duration=10) #if vl2.wkbType()< 1 or vl2.wkbType() > 1: #iface.messageBar().pushMessage("ATENCION", "Selecciona una capa de puntos", duration=10) #else: if vl2.wkbType()== 1 or vl2.wkbType()==1001: misdatos=[] misdatos = [f.name() for f in vl2.fields()] #trato de rellenar el desplegable con las columnas #anado un elemneto en blanco en el desplegable self.dlg.cb1.clear() self.dlg.cb1.addItem( "") for element in misdatos: self.dlg.cb1.addItem( element) # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start == True: self.first_start = False # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: column = self.dlg.cb1.currentIndex() columna=misdatos[int(column)-1] #parece que lo mejor sera la seleccion de una capa y dentro de ella de los elementos en ella seleccionados solo. Para ello habria que crear una capa temporal con solo los seleccioandos #if vl2.wkbType()== 1 or vl2.wkbType()==1001: selection = vl2.selectedFeatures() elementosseleccionados=len(selection) if elementosseleccionados ==0: vl2.selectAll() if elementosseleccionados ==1 or elementosseleccionados ==2: iface.messageBar().pushMessage("ATENCION", "Tienes algun elemento seleccionado pero no los suficientes para crear un poligono", duration=10) #onlySelectedFeatures results0=processing.run("native:saveselectedfeatures", {'INPUT':vl2,'OUTPUT':'memory:puntos_seleccionados_ptos2pol'}) result_layer0 = results0['OUTPUT'] entrada=result_layer0 QgsProject.instance().addMapLayer(result_layer0) #hay que hacer que cree una columna con el orden el solo por si por defecto no se pone ninguna params={'INPUT':entrada,'GROUP_FIELD':None,'ORDER_FIELD':columna,'DATE_FORMAT':'', 'OUTPUT':'memory:lineas_ptos2pol'} results=processing.run("qgis:pointstopath", params) result_layer = results['OUTPUT'] QgsProject.instance().addMapLayer(result_layer) params={'INPUT':result_layer,'OUTPUT':'memory:poligono_ptos2pol '} results2=processing.run("qgis:linestopolygons", params ) result_layer2 = results2['OUTPUT'] #por el mismo precio calculo la superficie #ADDING NEW FIELD layer_provider=result_layer2.dataProvider() layer_provider.addAttributes([QgsField("hectarea",QVariant.Double, "double", 10, 4)]) result_layer2.updateFields() #UPDATING/ADD ATTRIBUTE VALUE result_layer2.startEditing() features = result_layer2.getFeatures() for f in features: id=f.id() area=f.geometry().area()/10000 fieldindex = result_layer2.dataProvider().fieldNameIndex("hectarea") attr_value={fieldindex:area}#fieldindex, antes era 2 layer_provider.changeAttributeValues({id:attr_value}) result_layer2.commitChanges() #tendra que etiquetar la superficie con dos decimales y cambiar la simbologia, ya que estamos. sym1 = QgsFillSymbol.createSimple({'style': 'vertical','color': '0,0,0,0', 'outline_color': 'red'}) renderer=QgsSingleSymbolRenderer(sym1) #etiqueto layer_settings = QgsPalLayerSettings() text_format = QgsTextFormat() text_format.setFont(QFont("Arial", 12)) text_format.setSize(12) text_format.setColor(QColor("Red")) layer_settings.setFormat(text_format) layer_settings.fieldName = '''concat(round("hectarea",2),' ha.')''' layer_settings.isExpression = True layer_settings.enabled = True layer_settings = QgsVectorLayerSimpleLabeling(layer_settings) result_layer2.setLabelsEnabled(True) result_layer2.setLabeling(layer_settings) result_layer2.triggerRepaint() result_layer2.setRenderer(renderer) QgsProject.instance().addMapLayer(result_layer2) else: print(vl2.wkbType()) iface.messageBar().pushMessage("ATENCION", "Selecciona una capa de puntos", duration=10)
def testPasteSymbol(self): button = QgsSymbolButton() button.setSymbolType(QgsSymbol.Marker) symbol = QgsMarkerSymbol.createSimple({}) symbol.setColor(QColor(255, 0, 0)) button.setSymbol(symbol) button2 = QgsSymbolButton() button2.setSymbolType(QgsSymbol.Marker) symbol2 = QgsMarkerSymbol.createSimple({}) symbol2.setColor(QColor(0, 255, 0)) button2.setSymbol(symbol2) button.copySymbol() button2.pasteSymbol() self.assertEqual(button2.symbol().color(), QColor(255, 0, 0)) # try pasting incompatible symbol button2.setSymbolType(QgsSymbol.Fill) fill_symbol = QgsFillSymbol.createSimple({}) fill_symbol.setColor(QColor(0, 0, 255)) button2.setSymbol(fill_symbol) button.copySymbol() # copied a marker symbol button2.pasteSymbol() # should have no effect self.assertEqual(button2.symbol(), fill_symbol)