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() # Render with else rule and all activated renderer.startRender(ctx, vl.fields()) self.assertTrue(renderer.willRenderFeature(ft, ctx)) renderer.stopRender(ctx) # Render 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() 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'}) 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] self.mapsettings.setLayers(rendered_layers)
def set_rule_based_layer_style(layer: QgsVectorLayer, rules: List['StyleRule']) -> None: """Sets the rule based layer style.""" # Create a new rule-based renderer. symbol = QgsSymbol.defaultSymbol(layer.geometryType()) renderer = QgsRuleBasedRenderer(symbol) # Get the "root" rule. root_rule = renderer.rootRule() for r in rules: # Create a clone (i.e. a copy) of the default rule. rule = root_rule.children()[0].clone() # Set the label, expression and color. rule.setLabel(r.label) rule.setFilterExpression(r.expression) rule.symbol().setColor(QColor(r.color_name)) rule.symbol().setOpacity(r.opacity) # Set the scale limits if they have been specified. if r.scale_min_denom is not None and r.scale_max_denom is not None: rule.setScaleMinDenom(r.scale_min_denom) rule.setScaleMaxDenom(r.scale_max_denom) # Append the rule to the list of rules. root_rule.appendChild(rule) # Delete the default rule. root_rule.removeChildAt(0) # Apply the renderer to the layer. layer.setRenderer(renderer)
def create_elimlyr(canvas): elim_lyr = QgsVectorLayer(r"LineString?crs=epsg:4326&index=yes", elimedge_lname, r"memory") p_elimedge = elim_lyr.dataProvider() QgsProject.instance().addMapLayer(elim_lyr, True) # Case of only one color (elimedge_mono set in global_vars) if elimedge_mono: rend_symb=QgsSymbol.defaultSymbol(elim_lyr.geometryType()) rend_symb.setWidth(elimedge_wdt) rend_symb.setColor(QColor(elimedge_col)) rend_symb.setOpacity(elimedge_opc) rend_elimedge = QgsSingleSymbolRenderer(rend_symb) # Case of multiple colors depending on the type of elimination else: rend_elimedge = QgsRuleBasedRenderer(QgsLineSymbol()) edge_root_rule = rend_elimedge.rootRule() edge_rules = ((inter_rfu, "\"pb_type\" = '" + inter_rfu + "'", elimedge_col, elimedge_wdt), (inter_new, "\"pb_type\" = '" + inter_new + "'", elimedge_col2, elimedge_wdt)) for label, expression, color, width in edge_rules: rule = edge_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setWidth(width) rule.symbol().setOpacity(elimedge_opc) edge_root_rule.appendChild(rule) edge_root_rule.removeChildAt(0) elim_lyr.setRenderer(rend_elimedge) p_elimedge.addAttributes(elimlyr_atts) elim_lyr.updateFields() # Refresh the canvas elim_lyr.triggerRepaint() return elim_lyr
def setupBackgroundLayer(self, stateLayer): ''' Sets symbol rules for background layer in localization component ''' symbol = QgsSymbol.defaultSymbol(stateLayer.geometryType()) registry = QgsSymbolLayerRegistry() fillMeta = registry.symbolLayerMetadata("SimpleFill") fillSymbolLayer = fillMeta.createSymbolLayer({ 'color': '201,201,201', 'outline_width': 0.1 }) # Replace the default style symbol.deleteSymbolLayer(0) symbol.appendSymbolLayer(fillSymbolLayer) renderer = QgsRuleBasedRenderer(symbol) rootRule = renderer.rootRule() for state in self.estados: # Appends the rule to the rootRule rule = self.createStateRule(rootRule, state) rootRule.appendChild(rule) # Delete the default rule rootRule.removeChildAt(0) # Apply the renderer to the layer stateLayer.setRenderer(renderer) stateLayer.triggerRepaint()
def setStyleIcon(self, svg): #Dato il path di un'icona svg la setta come stile per le sole features selezionate nel layer dei beni vlayer = self.getLayerBeni() if len(vlayer.selectedFeatures()) == 1: svgStyle = { "name": svg, "outline": "#000000", "size": "15", } svgLayer = QgsSvgMarkerSymbolLayer.create(svgStyle) svgSymbol = QgsMarkerSymbol() svgSymbol.changeSymbolLayer(0, svgLayer) symbol = QgsSymbol.defaultSymbol(vlayer.geometryType()) symbol.setColor(QColor("Blue")) centroid = QgsCentroidFillSymbolLayer() centroid.setSubSymbol(svgSymbol) selectedSymbol = QgsFillSymbol() selectedSymbol.changeSymbolLayer(0, centroid) renderer = QgsRuleBasedRenderer(symbol) rule = QgsRuleBasedRenderer.Rule(selectedSymbol, label="Selected", filterExp="is_selected()") renderer.rootRule().appendChild(rule) vlayer.setRenderer(renderer) vlayer.triggerRepaint()
def testPointsUsedAttributes(self): points_shp = os.path.join(TEST_DATA_DIR, 'points.shp') points_layer = QgsVectorLayer(points_shp, 'Points', 'ogr') QgsProject.instance().addMapLayer(points_layer) # Create rulebased style sym1 = QgsMarkerSymbol() l1 = QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayer.Triangle, 5) l1.setColor(QColor(255, 0, 0)) l1.setStrokeStyle(Qt.NoPen) l1.setDataDefinedProperty(QgsSymbolLayer.PropertyAngle, QgsProperty.fromField("Heading")) sym1.changeSymbolLayer(0, l1) sym2 = QgsMarkerSymbol() l2 = QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayer.Triangle, 5) l2.setColor(QColor(0, 255, 0)) l2.setStrokeStyle(Qt.NoPen) l2.setDataDefinedProperty(QgsSymbolLayer.PropertyAngle, QgsProperty.fromField("Heading")) sym2.changeSymbolLayer(0, l2) sym3 = QgsMarkerSymbol() l3 = QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayer.Triangle, 5) l3.setColor(QColor(0, 0, 255)) l3.setStrokeStyle(Qt.NoPen) l3.setDataDefinedProperty(QgsSymbolLayer.PropertyAngle, QgsProperty.fromField("Heading")) sym3.changeSymbolLayer(0, l3) r1 = QgsRuleBasedRenderer.Rule(sym1, 0, 0, '"Class" = \'B52\'') r2 = QgsRuleBasedRenderer.Rule(sym2, 0, 0, '"Class" = \'Biplane\'') r3 = QgsRuleBasedRenderer.Rule(sym3, 0, 0, '"Class" = \'Jet\'') rootrule = QgsRuleBasedRenderer.Rule(None) rootrule.appendChild(r1) rootrule.appendChild(r2) rootrule.appendChild(r3) renderer = QgsRuleBasedRenderer(rootrule) points_layer.setRenderer(renderer) ms = QgsMapSettings() ms.setOutputSize(QSize(400, 400)) ms.setOutputDpi(96) ms.setExtent(QgsRectangle(-133, 22, -70, 52)) ms.setLayers([points_layer]) ctx = QgsRenderContext.fromMapSettings(ms) ctx.expressionContext().appendScope(points_layer.createExpressionContextScope()) # for symbol layer self.assertCountEqual(l1.usedAttributes(ctx), {'Heading'}) # for symbol self.assertCountEqual(sym1.usedAttributes(ctx), {'Heading'}) # for symbol renderer self.assertCountEqual(renderer.usedAttributes(ctx), {'Class', 'Heading'}) QgsProject.instance().removeMapLayer(points_layer)
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 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 defStyle(self, layer): # # fs=l.renderer().rootRule().children()[1].symbols()[0] # sl ==> QgsSimpleLineSymbolLayer # sl=fs.symbolLayers()[0] # symbol = QgsSymbol.defaultSymbol(layer.geometryType()) # Exporterle Style (.qml) pour determiner les attributs symb_def = { 'color': '53,227,47,77', 'joinstyle': 'bevel', 'outline_color': '0,0,0,255', 'outline_style': 'dash', 'outline_width': '0.5', 'outline_width_unit': 'MM', 'style': 'solid' } symbol = QgsFillSymbol.createSimple(symb_def) renderer = QgsRuleBasedRenderer(symbol) root_rule = renderer.rootRule() rule = root_rule.children()[0] rule.setLabel("Valide") rule.setFilterExpression( "\"valide\" is not null and \"supprime\" is null") # root_rule.appendChild(rule) symb_def = { 'capstyle': 'square', 'customdash': '5;2', 'customdash_unit': 'MM', 'customdash_unit': '0', 'line_style': 'dash', 'line_color': '200,194,194,255', 'joinstyle': 'bevel', 'line_width': '0.80', 'line_width_unit': 'MM', 'offset': '0', 'use_custom_dash': '1' } symbol = QgsFillSymbol.createSimple(symb_def) symbol.changeSymbolLayer(0, QgsSimpleLineSymbolLayer.create(symb_def)) rule = QgsRuleBasedRenderer.Rule(symbol) rule.setLabel("En attente") rule.setFilterExpression("\"valide\" is null and \"supprime\" is null") root_rule.appendChild(rule) layer.setRenderer(renderer)
def testUsedAttributes(self): ctx = QgsRenderContext.fromMapSettings(self.mapsettings) # Create rulebased style sym2 = QgsFillSymbol.createSimple({'color': '#71bd6c', 'outline_color': 'black'}) sym3 = QgsFillSymbol.createSimple({'color': '#1f78b4', 'outline_color': 'black'}) self.rx2 = QgsRuleBasedRenderer.Rule(sym2, 0, 0, '"id" = 200') self.rx3 = QgsRuleBasedRenderer.Rule(sym3, 1000, 100000000, 'ELSE') rootrule = QgsRuleBasedRenderer.Rule(None) rootrule.appendChild(self.rx2) rootrule.appendChild(self.rx3) renderer = QgsRuleBasedRenderer(rootrule) self.assertCountEqual(renderer.usedAttributes(ctx), {'id'})
def set_selection_based_style(layer, s_color, else_color): # noinspection PyCallByClass fill_for_selected = QgsFillSymbol.createSimple({'color': 'blue'}) fill_for_selected.setColor(s_color) rule_s = QgsRuleBasedRenderer.Rule(fill_for_selected, label=tr(u"Selected"), filterExp="is_selected()") fill_for_else = fill_for_selected.clone() fill_for_else.setColor(else_color) rule_else = QgsRuleBasedRenderer.Rule(fill_for_else, label=tr(u"Not Selected"), elseRule=True) renderer = QgsRuleBasedRenderer(QgsRuleBasedRenderer.Rule(None)) root_rule = renderer.rootRule() root_rule.appendChild(rule_s) root_rule.appendChild(rule_else) layer.setRenderer(renderer) return layer
def setUp(self): myShpFile = os.path.join(TEST_DATA_DIR, 'rectangles.shp') layer = QgsVectorLayer(myShpFile, 'Rectangles', 'ogr') vfield = QgsField('fa_cy-fie+ld', QVariant.Int) layer.addExpressionField('"id"', vfield) 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) self.mapsettings_archive.append(self.mapsettings)
def testGroupAndElseRules(self): vl = self.mapsettings.layers()[0] # 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(None, 0, 0, '"id" < 3') self.rx2 = QgsRuleBasedRenderer.Rule(sym3, 0, 0, 'ELSE') self.subrx1 = QgsRuleBasedRenderer.Rule(sym1, 0, 0, '"id" = 1') self.subrx2 = QgsRuleBasedRenderer.Rule(sym2, 0, 0, '"id" = 2') self.rx1.appendChild(self.subrx1) self.rx1.appendChild(self.subrx2) rootrule = QgsRuleBasedRenderer.Rule(None) rootrule.appendChild(self.rx1) rootrule.appendChild(self.rx2) rootrule.children()[0].children()[0].setActive(False) rootrule.children()[0].children()[1].setActive(False) vl.setRenderer(QgsRuleBasedRenderer(rootrule)) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_rulebased_group_else') self.assertTrue(renderchecker.runTest('rulebased_group_else'))
def color_depares(layer, isoBreaks): # https://gis.stackexchange.com/a/282345 # DEPARE COLORS and LIMITS # [land, intertidal, danger, shallow, deep] limits = [0, 2, 5, 8] limits = isoBreaks landLimit = [-10e9, limits[0]] intertidalLimit = [limits[0], limits[1]] dangerLimit = [limits[1], limits[2]] shallowLimit = [limits[2], limits[3]] deepLimit = [limits[3], 10e9] landColor = [248, 243, 161] intertidalColor = [187, 217, 146] dangerColor = [190, 229, 238] shallowColor = [232, 246, 249] deepColor = [255, 255, 255] # fullList = [[landLimit, landColor, 'land'], [intertidalLimit, intertidalColor, 'intertidal'], [dangerLimit, dangerColor, 'danger'], [shallowLimit, shallowColor, 'shallow'], [deepLimit, deepColor, 'deep']] fullList.reverse() # print('depare!') # layer = iface.activeLayer() symbol = QgsSymbol.defaultSymbol(layer.geometryType()) renderer = QgsRuleBasedRenderer(symbol) # for pair in fullList: expression = ' if(\"dep_min\" < {}, True, None) '.format(pair[0][1]) color = pair[1] label = '{} (>{})'.format(pair[2], pair[0][1]) rule_based_style(layer, symbol, renderer, label, expression, color) renderer.rootRule().removeChildAt(0) iface.layerTreeView().refreshLayerSymbology(layer.id())
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 apply_style(layer, style, is_new, name): """Apply the style to a new or existing layer :param layer: QGIS layer instance :type layer: QgsVectorLayer :param style: optional, dictionary with style properties: example {'color': [100, 50, 123], 'transparency': 0.5, 'stroke_width: 3 } :type style: dict :param is_new: True is the layer is a new layer :type is_new: bool :param name: name of the isochrone, if blank/None create a timestamp for the name if the layer is not new :type name: str """ if style is None: return def _set_labeling(): pal_layer = QgsPalLayerSettings() pal_layer.fieldName = 'value' pal_layer.enabled = True pal_layer.placementFlags = QgsLabeling.OnLine pal_layer.placement = QgsPalLayerSettings.PerimeterCurved text_format = pal_layer.format() buffer = text_format.buffer() buffer.setColor(QColor(255, 255, 255)) buffer.setOpacity(0.5) buffer.setEnabled(True) text_format.setBuffer(buffer) pal_layer.setFormat(text_format) labels = QgsVectorLayerSimpleLabeling(pal_layer) return labels def _set_rule(renderer): root_rule = renderer.rootRule() if is_new: rule = root_rule.children()[0] else: rule = root_rule.children()[0].clone() rule.setLabel(name) expression = '"name" = {}'.format(QgsExpression.quotedString(name)) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(*style['color'], 255)) rule.symbol().setOpacity(1 - style['transparency']) rule.symbol().symbolLayers()[0].setStrokeWidth(style['stroke_width']) rule.symbol().symbolLayers()[0].setStrokeColor(QColor(255, 255, 255)) if not is_new: root_rule.appendChild(rule) if is_new: # Create the new style symbol = QgsSymbol.defaultSymbol(layer.geometryType()) renderer = QgsRuleBasedRenderer(symbol) req = QgsFeatureRequest() req.addOrderBy('"value"', False, False) renderer.setOrderBy(req.orderBy()) renderer.setOrderByEnabled(True) _set_rule(renderer) # Delete first rule layer.setRenderer(renderer) labels = _set_labeling() layer.setLabeling(labels) layer.setCustomProperty("labeling/bufferDraw", True) layer.setLabelsEnabled(True) else: # Check for rule based renderer, pass if not present renderer = layer.renderer() if isinstance(renderer, QgsRuleBasedRenderer): _set_rule(renderer)
def layer_to_QgsVectorLayer( source_layer, # pylint: disable=too-many-locals,too-many-branches,too-many-statements input_file, context: Context, fallback_crs=QgsCoordinateReferenceSystem(), defer_layer_uri_set: bool = False): """ Converts a vector layer """ if source_layer.__class__.__name__ == 'CadFeatureLayer': layer = source_layer.layer else: layer = source_layer crs = CrsConverter.convert_crs( layer.layer_extent.crs, context) if layer.layer_extent else QgsCoordinateReferenceSystem() if not crs.isValid(): crs = fallback_crs subset_string = '' if layer.selection_set: subset_string = 'fid in ({})'.format(','.join( [str(s) for s in layer.selection_set])) elif layer.definition_query: subset_string = ExpressionConverter.convert_esri_sql( layer.definition_query) base, _ = os.path.split(input_file) uri, wkb_type, provider, encoding, file_name = VectorLayerConverter.get_uri( source_layer=source_layer, obj=layer, base=base, crs=crs, subset=subset_string, context=context) if wkb_type is None or wkb_type == QgsWkbTypes.Unknown: wkb_type = VectorLayerConverter.layer_to_wkb_type(layer) context.layer_type_hint = wkb_type if Qgis.QGIS_VERSION_INT >= 31600: # try to get the layer name so that we can remove it from field references. # e.g. if layer name is polys then qgis won't support to arcgis style "polys.field" format parts = QgsProviderRegistry.instance().decodeUri(provider, uri) context.main_layer_name = parts.get('layerName') if not context.main_layer_name and provider == 'ogr': context.main_layer_name = Path(parts['path']).stem if context.main_layer_name: subset_string = subset_string.replace( context.main_layer_name + '.', '') else: context.main_layer_name = None if provider == 'ogr' and (not file_name or not os.path.exists(file_name) ) and context.invalid_layer_resolver: res = context.invalid_layer_resolver(layer.name, uri, wkb_type) uri = res.uri provider = res.providerKey if Qgis.QGIS_VERSION_INT >= 31000: opts = QgsVectorLayer.LayerOptions() if wkb_type is not None: opts.fallbackWkbType = wkb_type if provider == 'ogr' and subset_string: uri += '|subset={}'.format(subset_string) original_uri = uri if defer_layer_uri_set: uri = 'xxxxxxxxx' + uri vl = QgsVectorLayer(uri, layer.name, provider, opts) if defer_layer_uri_set: vl.setCustomProperty('original_uri', original_uri) else: vl = QgsMemoryProviderUtils.createMemoryLayer( layer.name, QgsFields(), wkb_type, crs) # context.style_folder, _ = os.path.split(output_file) if layer.renderer: renderer = VectorRendererConverter.convert_renderer( layer.renderer, context) try: if not renderer.usingSymbolLevels(): renderer.setUsingSymbolLevels( layer.use_advanced_symbol_levels) except AttributeError: pass if layer.use_page_definition_query: filter_expression = '"{}" {} @atlas_pagename'.format( layer.page_name_field, layer.page_name_match_operator) root_rule = QgsRuleBasedRenderer.Rule(None) # special case -- convert a simple renderer if isinstance(renderer, QgsSingleSymbolRenderer): filter_rule = QgsRuleBasedRenderer.Rule( renderer.symbol().clone()) filter_rule.setFilterExpression(filter_expression) filter_rule.setLabel(layer.name) filter_rule.setDescription(layer.name) root_rule.appendChild(filter_rule) else: source_rule_renderer = QgsRuleBasedRenderer.convertFromRenderer( renderer) filter_rule = QgsRuleBasedRenderer.Rule(None) filter_rule.setFilterExpression(filter_expression) filter_rule.setLabel('Current Atlas Page') filter_rule.setDescription('Current Atlas Page') root_rule.appendChild(filter_rule) for child in source_rule_renderer.rootRule().children(): filter_rule.appendChild(child.clone()) renderer = QgsRuleBasedRenderer(root_rule) if renderer: vl.setRenderer(renderer) vl.triggerRepaint() else: vl.setRenderer(QgsNullSymbolRenderer()) vl.triggerRepaint() metadata = vl.metadata() metadata.setAbstract(layer.description) vl.setMetadata(metadata) # # layer.zoom_max = "don't show when zoomed out beyond" zoom_max = layer.zoom_max # layer.zoom_min = "don't show when zoomed in beyond" zoom_min = layer.zoom_min enabled_scale_range = bool(zoom_max or zoom_min) if zoom_max and zoom_min and zoom_min > zoom_max: # inconsistent scale range -- zoom_max should be bigger number than zoom_min zoom_min, zoom_max = zoom_max, zoom_min # qgis minimum scale = don't show when zoomed out beyond, i.e. ArcGIS zoom_max vl.setMinimumScale( zoom_max if enabled_scale_range else layer.stored_zoom_max) # qgis maximum scale = don't show when zoomed in beyond, i.e. ArcGIS zoom_min vl.setMaximumScale( zoom_min if enabled_scale_range else layer.stored_zoom_min) vl.setScaleBasedVisibility(enabled_scale_range) vl.setOpacity(1.0 - (layer.transparency or 0) / 100) if layer.display_expression_properties and layer.display_expression_properties.expression and layer.display_expression_properties.expression_parser is not None: vl.setDisplayExpression( ExpressionConverter.convert( layer.display_expression_properties.expression, layer.display_expression_properties.expression_parser, layer.display_expression_properties.advanced, context)) if Qgis.QGIS_VERSION_INT < 31000: vl.setDataSource(uri, layer.name, provider) if encoding: vl.dataProvider().setEncoding(encoding) if subset_string: vl.setSubsetString(subset_string) vl.setCrs(crs) for e in layer.extensions: if e.__class__.__name__ == 'ServerLayerExtension': if 'CopyrightText' in e.properties.properties: layer_credits = e.properties.properties['CopyrightText'] metadata = vl.metadata() rights = metadata.rights() rights.append(layer_credits) metadata.setRights(rights) vl.setMetadata(metadata) LabelConverter.convert_annotation_collection( layer.annotation_collection, dest_layer=vl, context=context) vl.setLabelsEnabled(layer.labels_enabled) DiagramConverter.convert_diagrams(layer.renderer, dest_layer=vl, context=context) # setup joins join_layer = VectorLayerConverter.add_joined_layer( source_layer=layer, input_file=input_file, base_layer=vl, context=context) context.dataset_name = '' vl.setLegend(QgsMapLayerLegend.defaultVectorLegend(vl)) if layer.hyperlinks: VectorLayerConverter.convert_hyperlinks(layer.hyperlinks, vl) vl.setDisplayExpression( QgsExpression.quotedColumnRef(layer.display_field)) res = [vl] if join_layer: res.append(join_layer) context.main_layer_name = None return res
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 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 processAlgorithm(self, parameters, context, feedback): t_file = self.parameterAsVectorLayer( parameters, self.FILE_TABLE, context ) t_troncon = self.parameterAsVectorLayer( parameters, self.SEGMENTS_TABLE, context ) t_obs = self.parameterAsVectorLayer( parameters, self.OBSERVATIONS_TABLE, context ) t_regard = self.parameterAsVectorLayer( parameters, self.MANHOLES_TABLE, context ) g_regard = self.parameterAsVectorLayer( parameters, self.GEOM_MANHOLES, context ) g_troncon = self.parameterAsVectorLayer( parameters, self.GEOM_SEGMENT, context ) g_obs = self.parameterAsVectorLayer( parameters, self.GEOM_OBSERVATION, context ) v_regard = self.parameterAsVectorLayer( parameters, self.VIEW_MANHOLES_GEOLOCALIZED, context ) # define variables variables = context.project().customVariables() variables['itv_rerau_t_file'] = t_file.id() variables['itv_rerau_t_troncon'] = t_troncon.id() variables['itv_rerau_t_obs'] = t_obs.id() variables['itv_rerau_t_regard'] = t_regard.id() variables['itv_rerau_g_regard'] = g_regard.id() variables['itv_rerau_g_troncon'] = g_troncon.id() variables['itv_rerau_g_obs'] = g_obs.id() context.project().setCustomVariables(variables) # define relations relations = [ { 'id': 'fk_obs_id_file', 'name': tr('Link File - Observation'), 'referencingLayer': t_obs.id(), 'referencingField': 'id_file', 'referencedLayer': t_file.id(), 'referencedField': 'id' }, { 'id': 'fk_regard_id_file', 'name': tr('Link File - Manhole'), 'referencingLayer': t_regard.id(), 'referencingField': 'id_file', 'referencedLayer': t_file.id(), 'referencedField': 'id' }, { 'id': 'fk_troncon_id_file', 'name': tr('Link File - Pipe segment'), 'referencingLayer': t_troncon.id(), 'referencingField': 'id_file', 'referencedLayer': t_file.id(), 'referencedField': 'id' }, { 'id': 'fk_obs_id_troncon', 'name': tr('Link Pipe segment - Observation'), 'referencingLayer': t_obs.id(), 'referencingField': 'id_troncon', 'referencedLayer': t_troncon.id(), 'referencedField': 'id' }, { 'id': 'fk_regard_id_geom_regard', 'name': tr('Link Manhole inspection - Reference'), 'referencingLayer': t_regard.id(), 'referencingField': 'id_geom_regard', 'referencedLayer': g_regard.id(), 'referencedField': 'id' }, { 'id': 'fk_troncon_id_geom_trononc', 'name': tr('Link Pipe segment inspection - Reference'), 'referencingLayer': t_troncon.id(), 'referencingField': 'id_geom_troncon', 'referencedLayer': g_troncon.id(), 'referencedField': 'id' } ] relation_manager = context.project().relationManager() for rel_def in relations: feedback.pushInfo( 'Link: {}'.format(rel_def['name']) ) rel = QgsRelation() rel.setId(rel_def['id']) rel.setName(rel_def['name']) rel.setReferencingLayer(rel_def['referencingLayer']) rel.setReferencedLayer(rel_def['referencedLayer']) rel.addFieldPair( rel_def['referencingField'], rel_def['referencedField'] ) rel.setStrength(QgsRelation.Association) relation_manager.addRelation(rel) feedback.pushInfo( 'Count relations {}'.format( len(relation_manager.relations()) ) ) joins = [ { 'layer': t_obs, 'targetField': 'id_troncon', 'joinLayer': t_troncon, 'joinField': 'id', 'fieldNamesSubset': ['ack'] }, { 'layer': g_obs, 'targetField': 'id', 'joinLayer': t_obs, 'joinField': 'id', 'fieldNamesSubset': [] } ] for j_def in joins: layer = j_def['layer'] join = QgsVectorLayerJoinInfo() join.setJoinFieldName(j_def['joinField']) join.setJoinLayerId(j_def['joinLayer'].id()) join.setTargetFieldName(j_def['targetField']) if j_def['fieldNamesSubset']: join.setJoinFieldNamesSubset(j_def['fieldNamesSubset']) join.setUsingMemoryCache(False) join.setPrefix('') join.setEditable(False) join.setCascadedDelete(False) join.setJoinLayer(j_def['joinLayer']) layer.addJoin(join) layer.updateFields() # load styles styles = [ { 'layer': t_file, 'namedStyles': [ { 'file': 'itv_file_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_file_actions.qml', 'type': QgsMapLayer.Actions } ] }, { 'layer': t_troncon, 'namedStyles': [ { 'file': 'itv_troncon_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_troncon_table.qml', 'type': QgsMapLayer.AttributeTable } ] }, { 'layer': t_obs, 'namedStyles': [ { 'file': 'itv_obs_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_obs_table.qml', 'type': QgsMapLayer.AttributeTable } ] }, { 'layer': t_regard, 'namedStyles': [ { 'file': 'itv_regard_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_regard_forms.qml', 'type': QgsMapLayer.Forms }, { 'file': 'itv_regard_table.qml', 'type': QgsMapLayer.AttributeTable } ] }, { 'layer': g_regard, 'namedStyles': [ { 'file': 'itv_geom_regard_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_geom_regard_symbology.qml', 'type': QgsMapLayer.Symbology } ] }, { 'layer': g_troncon, 'namedStyles': [ { 'file': 'itv_geom_troncon_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_geom_troncon_symbology.qml', 'type': QgsMapLayer.Symbology }, { 'file': 'itv_geom_troncon_actions.qml', 'type': QgsMapLayer.Actions } ] }, { 'layer': g_obs, 'namedStyles': [ { 'file': 'itv_geom_obs_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_geom_obs_symbology.qml', 'type': QgsMapLayer.Symbology } ] }, { 'layer': v_regard, 'namedStyles': [ { 'file': 'itv_view_regard_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_view_regard_symbology.qml', 'type': QgsMapLayer.Symbology }, { 'file': 'itv_view_regard_labeling.qml', 'type': QgsMapLayer.Labeling } ] } ] for style in styles: layer = style['layer'] for n_style in style['namedStyles']: layer.loadNamedStyle( resources_path('styles', n_style['file']), categories=n_style['type'] ) # layer.saveStyleToDatabase('style', 'default style', True, '') layer.triggerRepaint() # Creation de la symbologie g_obs g_obs_rules = ( 'BAA', 'BAB', 'BAC', 'BAD', 'BAE', 'BAF', 'BAG', 'BAH', 'BAI', 'BAJ', 'BAK', 'BAL', 'BAM', 'BAN', 'BAO', 'BAP', 'BBA', 'BBB', 'BBC', 'BBD', 'BBE', 'BBF', 'BBG', 'BBH', 'BCA', 'BCB', 'BCC', 'BDA', 'BDB', 'BDC', 'BDD', 'BDE', 'BDF', 'BDG' ) g_obs_rule_descs = { 'BAA': 'Déformation', 'BAB': 'Fissure', 'BAC': 'Rupture/Effondrement', 'BAD': 'Elt maçonnerie', 'BAE': 'Mortier manquant', 'BAF': 'Dégradation de surface', 'BAG': 'Branchement pénétrant', 'BAH': 'Raccordement défectueux', 'BAI': 'Joint étanchéité apparent', 'BAJ': 'Déplacement d\'assemblage', 'BAK': 'Défaut de révêtement', 'BAL': 'Réparation défectueuse', 'BAM': 'Défaut soudure', 'BAN': 'Conduite poreuse', 'BAO': 'Sol visible', 'BAP': 'Trou visible', 'BBA': 'Racines', 'BBB': 'Dépots Adhérents', 'BBC': 'Dépôts', 'BBD': 'Entrée de terre', 'BBE': 'Autres obstacles', 'BBF': 'Infiltration', 'BBG': 'Exfiltration', 'BBH': 'Vermine', 'BCA': 'Raccordement', 'BCB': 'Réparation', 'BCC': 'Courbure de collecteur', 'BDA': 'Photographie générale', 'BDB': 'Remarque générale', 'BDC': 'Inspection abandonnée', 'BDD': 'Niveau d\'eau', 'BDE': 'Ecoulement dans une canlisation entrante', 'BDF': 'Atmosphère canalisation', 'BDG': 'Perte de visibilité' } g_obs_rootrule = QgsRuleBasedRenderer.Rule(None) rendering_pass_idx = len(g_obs_rules) for rule in g_obs_rules: # get svg path svg_path = resources_path('styles', 'img_obs', rule + '.svg') # create svg symbol layer svg_symbol_layer = QgsSvgMarkerSymbolLayer(svg_path) svg_symbol_layer.setRenderingPass(rendering_pass_idx) # create white square symbol layer for the backend simple_symbol_layer = QgsSimpleMarkerSymbolLayer( shape=QgsSimpleMarkerSymbolLayerBase.Circle, size=svg_symbol_layer.size(), color=QColor('white'), strokeColor=QColor('white') ) simple_symbol_layer.setRenderingPass(rendering_pass_idx) # create marker svg_marker = QgsMarkerSymbol() # set the backend symbol layer svg_marker.changeSymbolLayer(0, simple_symbol_layer) # add svg symbol layer svg_marker.appendSymbolLayer(svg_symbol_layer) # create rule svg_rule = QgsRuleBasedRenderer.Rule( svg_marker, 0, 10000, QgsExpression.createFieldEqualityExpression('a', rule), rule ) if rule in g_obs_rule_descs: svg_rule.setLabel(g_obs_rule_descs[rule]) svg_rule.setDescription('{}: {}'.format( rule, g_obs_rule_descs[rule] )) # add rule g_obs_rootrule.appendChild(svg_rule) rendering_pass_idx -= 1 g_obs_rootrule.appendChild( QgsRuleBasedRenderer.Rule( QgsMarkerSymbol.createSimple( { 'name': 'circle', 'color': '#0000b2', 'outline_color': '#0000b2', 'size': '1' } ), 0, 10000, 'ELSE', 'Autres' ) ) g_obs.setRenderer(QgsRuleBasedRenderer(g_obs_rootrule)) feedback.pushInfo('Project has been setup') return {}
def extract_layers(self, tree): """Return a list of RFU layers.""" # Create vector layers.. l_vertex = QgsVectorLayer(r"Point?crs=epsg:4326&index=yes", "Sommet RFU", r"memory") l_edge = QgsVectorLayer(r"LineString?crs=epsg:4326&index=yes", "Limite RFU", r"memory") p_vertex = l_vertex.dataProvider() p_edge = l_edge.dataProvider() # Define default style renderer.. renderer_vertex = QgsRuleBasedRenderer(QgsMarkerSymbol()) vertex_root_rule = renderer_vertex.rootRule() # Modified in v2.1 (som_nature replaced by som_typologie_nature) >> vertex_rules = ( (("Borne, borne à puce, pierre, piquet, clou ou broche"), ("$id >= 0 AND \"som_typologie_nature\" IN ('Borne'," "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche')"), r"#EC0000", 2.2), (("Axe cours d'eau, axe fossé, haut de talus, pied de talus"), ("$id >= 0 AND \"som_typologie_nature\" IN ('Axe cours d\'\'eau'," "'Axe fossé', 'Haut de talus', 'Pied de talus')"), r"#EE8012", 2.2), (("Angle de bâtiment, axe de mur, angle de mur, " "angle de clôture, pylône et toute autre valeur"), ("$id >= 0 AND \"som_typologie_nature\" NOT IN ('Borne'," "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche'," "'Axe cours d\'\'eau', 'Axe fossé', 'Haut de talus'," "'Pied de talus')"), r"#9784EC", 2.2), ("Temporaire", r"$id < 0", "cyan", 2.4), ("Point nouveau à traiter car proche d'un existant", r"point_rfu_proche is not null", "#bcff03", 3)) # >> for label, expression, color, size in vertex_rules: rule = vertex_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setSize(size) vertex_root_rule.appendChild(rule) vertex_root_rule.removeChildAt(0) l_vertex.setRenderer(renderer_vertex) renderer_edge = QgsRuleBasedRenderer(QgsLineSymbol()) edge_root_rule = renderer_edge.rootRule() # Modified in v2.1 (lim_typologie_nature added) << edge_rules = (("Limite privée", "$id >= 0 AND \"lim_typologie_nature\" = '" + lim_typo_nat_vals[0] + "'", "#0A0AFF", 0.5), ("Limite naturelle", "$id >= 0 AND \"lim_typologie_nature\" = '" + lim_typo_nat_vals[1] + "'", "#aa876d", 0.5), ("Temporaire", "$id < 0", "cyan", 1)) # >> for label, expression, color, width in edge_rules: rule = edge_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setWidth(width) edge_root_rule.appendChild(rule) edge_root_rule.removeChildAt(0) l_edge.setRenderer(renderer_edge) # Add fields.. p_vertex.addAttributes(vtx_atts) p_edge.addAttributes(edge_atts) # Add features from xml tree.. # ..to vertex layer.. fts_vertex = [] for e in tree.findall(r"sommet"): ft_vertex = QgsFeature() ft_vertex.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_noeud = int(e.attrib[r"id_noeud"]) _version = int(e.attrib[r"version"]) som_ge_createur = str(e.find(r"./som_ge_createur").text) som_nature = str(e.find(r"./som_nature").text) som_prec_rattcht = int( e.find(r"./som_precision_rattachement").text) som_coord_est = float(e.find(r"./som_coord_est").text) som_coord_nord = float(e.find(r"./som_coord_nord").text) som_repres_plane = str(e.find(r"./som_representation_plane").text) som_tolerance = float(e.find(r"./som_tolerance").text) # Field used to store the attestation_qualite value # when modifying a vertex ("false" or "true") attestation_qualite = "false" som_delim_pub = str(e.find(r"./som_delimitation_publique").text) som_typo_nature = str(e.find(r"./som_typologie_nature").text) ft_vertex.setAttributes([ _id_noeud, _version, som_ge_createur, som_delim_pub, som_typo_nature, som_nature, som_prec_rattcht, som_coord_est, som_coord_nord, som_repres_plane, som_tolerance, attestation_qualite, NULL ]) fts_vertex.append(ft_vertex) # ..to edge layer.. fts_edge = [] for e in tree.findall(r"limite"): ft_edge = QgsFeature() ft_edge.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_arc = int(e.attrib[r"id_arc"]) _version = int(e.attrib[r"version"]) lim_ge_createur = str(e.find(r"./lim_ge_createur").text) lim_typo_nature = str(e.find(r"./lim_typologie_nature").text) lim_delim_pub = str(e.find(r"./lim_delimitation_publique").text) ft_edge.setAttributes([ _id_arc, _version, lim_ge_createur, lim_delim_pub, lim_typo_nature ]) fts_edge.append(ft_edge) # Add features to layers.. p_vertex.addFeatures(fts_vertex) p_edge.addFeatures(fts_edge) # Update fields.. l_vertex.updateFields() l_edge.updateFields() # Update layer's extent.. l_vertex.updateExtents() l_edge.updateExtents() # Check if valid.. if not l_vertex.isValid() or not l_edge.isValid(): raise Exception( "Une erreur est survenue lors du chargement de la couche.") # Then return layers.. return [l_vertex, l_edge]
def test_legend_key_to_expression(self): root_rule = QgsRuleBasedRenderer.Rule(None) renderer = QgsRuleBasedRenderer(root_rule) exp, ok = renderer.legendKeyToExpression('xxxx', None) self.assertFalse(ok) exp, ok = renderer.legendKeyToExpression(root_rule.ruleKey(), None) self.assertTrue(ok) self.assertEqual(exp, 'TRUE') rule2 = QgsRuleBasedRenderer.Rule(None, filterExp='"field_name" = 5') rule3 = QgsRuleBasedRenderer.Rule(None, maximumScale=2000, filterExp='"field_name" = 6') rule4 = QgsRuleBasedRenderer.Rule(None, minimumScale=1000, filterExp='"field_name" = 7') rule5 = QgsRuleBasedRenderer.Rule(None, minimumScale=3000, maximumScale=1000) root_rule.appendChild(rule2) root_rule.appendChild(rule3) root_rule.appendChild(rule4) root_rule.appendChild(rule5) exp, ok = renderer.legendKeyToExpression(root_rule.ruleKey(), None) self.assertTrue(ok) self.assertEqual(exp, 'TRUE') exp, ok = renderer.legendKeyToExpression(rule2.ruleKey(), None) self.assertTrue(ok) self.assertEqual(exp, '"field_name" = 5') exp, ok = renderer.legendKeyToExpression(rule3.ruleKey(), None) self.assertTrue(ok) self.assertEqual(exp, '("field_name" = 6) AND (@map_scale >= 2000)') exp, ok = renderer.legendKeyToExpression(rule4.ruleKey(), None) self.assertTrue(ok) self.assertEqual(exp, '("field_name" = 7) AND (@map_scale <= 1000)') exp, ok = renderer.legendKeyToExpression(rule5.ruleKey(), None) self.assertTrue(ok) self.assertEqual(exp, '(@map_scale <= 3000) AND (@map_scale >= 1000)') rule6 = QgsRuleBasedRenderer.Rule(None, filterExp='"field_name" = \'a\'') rule4.appendChild(rule6) exp, ok = renderer.legendKeyToExpression(rule6.ruleKey(), None) self.assertTrue(ok) self.assertEqual( exp, '("field_name" = \'a\') AND (("field_name" = 7) AND (@map_scale <= 1000))' ) # group only rule rule7 = QgsRuleBasedRenderer.Rule(None) rule3.appendChild(rule7) rule8 = QgsRuleBasedRenderer.Rule(None, filterExp='"field_name" = \'c\'') rule7.appendChild(rule8) exp, ok = renderer.legendKeyToExpression(rule7.ruleKey(), None) self.assertTrue(ok) self.assertEqual(exp, '("field_name" = 6) AND (@map_scale >= 2000)') exp, ok = renderer.legendKeyToExpression(rule8.ruleKey(), None) self.assertTrue(ok) self.assertEqual( exp, """("field_name" = 'c') AND (("field_name" = 6) AND (@map_scale >= 2000))""" ) # else rules root_rule = QgsRuleBasedRenderer.Rule(None) renderer = QgsRuleBasedRenderer(root_rule) rule2 = QgsRuleBasedRenderer.Rule(None, filterExp='"field_name" = 5') rule3 = QgsRuleBasedRenderer.Rule(None, maximumScale=2000, filterExp='"field_name" = 6') rule4 = QgsRuleBasedRenderer.Rule(None, elseRule=True) root_rule.appendChild(rule2) root_rule.appendChild(rule3) root_rule.appendChild(rule4) exp, ok = renderer.legendKeyToExpression(root_rule.ruleKey(), None) self.assertTrue(ok) self.assertEqual(exp, 'TRUE') exp, ok = renderer.legendKeyToExpression(rule2.ruleKey(), None) self.assertTrue(ok) self.assertEqual(exp, '"field_name" = 5') exp, ok = renderer.legendKeyToExpression(rule3.ruleKey(), None) self.assertTrue(ok) self.assertEqual(exp, '("field_name" = 6) AND (@map_scale >= 2000)') exp, ok = renderer.legendKeyToExpression(rule4.ruleKey(), None) self.assertTrue(ok) self.assertEqual( exp, 'NOT (("field_name" = 5) OR (("field_name" = 6) AND (@map_scale >= 2000)))' ) rule5 = QgsRuleBasedRenderer.Rule(None, filterExp='"field_name" = 11') rule4.appendChild(rule5) exp, ok = renderer.legendKeyToExpression(rule5.ruleKey(), None) self.assertTrue(ok) self.assertEqual( exp, '("field_name" = 11) AND (NOT (("field_name" = 5) OR (("field_name" = 6) AND (@map_scale >= 2000))))' ) # isolated ELSE rule, with no siblings root_rule = QgsRuleBasedRenderer.Rule(None) renderer = QgsRuleBasedRenderer(root_rule) rule2 = QgsRuleBasedRenderer.Rule(None, filterExp='"field_name" = 5') rule3 = QgsRuleBasedRenderer.Rule(None, maximumScale=2000, filterExp='"field_name" = 6') root_rule.appendChild(rule2) root_rule.appendChild(rule3) rule4 = QgsRuleBasedRenderer.Rule(None, elseRule=True) rule3.appendChild(rule4) exp, ok = renderer.legendKeyToExpression(rule4.ruleKey(), None) self.assertTrue(ok) self.assertEqual( exp, '(TRUE) AND (("field_name" = 6) AND (@map_scale >= 2000))')