def testMultiPoint(self): """ Test multipoint handling """ layer = QgsVectorLayer('Multipoint?field=cat:string', '', 'memory') self.assertTrue(layer.isValid()) f = QgsFeature(layer.fields()) f.setAttributes(['a']) f.setGeometry(QgsGeometry.fromWkt('MultiPoint(5 5, 5 6, 9 9)')) layer.dataProvider().addFeature(f) f.setAttributes(['b']) f.setGeometry(QgsGeometry.fromWkt('MultiPoint(2 1, 2 2, 5 5)')) layer.dataProvider().addFeature(f) f.setAttributes(['c']) f.setGeometry(QgsGeometry.fromWkt('MultiPoint(9 1)')) layer.dataProvider().addFeature(f) renderer = QgsPointDisplacementRenderer() sym1 = QgsMarkerSymbol.createSimple({ 'color': '#ff00ff', 'size': '3', 'outline_style': 'no' }) sym_renderer = QgsCategorizedSymbolRenderer() sym_renderer.setClassAttribute('cat') sym1.setColor(QColor(255, 0, 0)) sym_renderer.addCategory(QgsRendererCategory('a', sym1.clone(), 'a')) sym1.setColor(QColor(0, 255, 0)) sym_renderer.addCategory(QgsRendererCategory('b', sym1.clone(), 'b')) sym1.setColor(QColor(0, 0, 255)) sym_renderer.addCategory(QgsRendererCategory('c', sym1.clone(), 'c')) renderer.setEmbeddedRenderer(sym_renderer) renderer.setCircleRadiusAddition(2) renderer.setCircleWidth(1) renderer.setCircleColor(QColor(0, 0, 0)) renderer.setCenterSymbol( QgsMarkerSymbol.createSimple({ 'color': '#ffff00', 'size': '3', 'outline_style': 'no' })) renderer.setToleranceUnit(QgsUnitTypes.RenderMapUnits) renderer.setTolerance(2) layer.setRenderer(renderer) rendered_layers = [layer] mapsettings = QgsMapSettings() mapsettings.setOutputSize(QSize(400, 400)) mapsettings.setOutputDpi(96) mapsettings.setExtent(QgsRectangle(0, 0, 10, 10)) mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(mapsettings) renderchecker.setControlPathPrefix('displacement_renderer') renderchecker.setControlName('expected_displacement_multipoint') result = renderchecker.runTest('expected_displacement_multipoint') self.report += renderchecker.report() self.assertTrue(result)
def testLegendRenderWithMapTheme(self): """Test rendering legends linked to map themes""" QgsProject.instance().removeAllMapLayers() point_path = os.path.join(TEST_DATA_DIR, 'points.shp') point_layer = QgsVectorLayer(point_path, 'points', 'ogr') line_path = os.path.join(TEST_DATA_DIR, 'lines.shp') line_layer = QgsVectorLayer(line_path, 'lines', 'ogr') QgsProject.instance().clear() QgsProject.instance().addMapLayers([point_layer, line_layer]) marker_symbol = QgsMarkerSymbol.createSimple({'color': '#ff0000', 'outline_style': 'no', 'size': '5'}) point_layer.setRenderer(QgsSingleSymbolRenderer(marker_symbol)) point_layer.styleManager().addStyleFromLayer("red") line_symbol = QgsLineSymbol.createSimple({'color': '#ff0000', 'line_width': '2'}) line_layer.setRenderer(QgsSingleSymbolRenderer(line_symbol)) line_layer.styleManager().addStyleFromLayer("red") red_record = QgsMapThemeCollection.MapThemeRecord() point_red_record = QgsMapThemeCollection.MapThemeLayerRecord(point_layer) point_red_record.usingCurrentStyle = True point_red_record.currentStyle = 'red' red_record.addLayerRecord(point_red_record) line_red_record = QgsMapThemeCollection.MapThemeLayerRecord(line_layer) line_red_record.usingCurrentStyle = True line_red_record.currentStyle = 'red' red_record.addLayerRecord(line_red_record) QgsProject.instance().mapThemeCollection().insert('red', red_record) marker_symbol1 = QgsMarkerSymbol.createSimple({'color': '#0000ff', 'outline_style': 'no', 'size': '5'}) marker_symbol2 = QgsMarkerSymbol.createSimple( {'color': '#0000ff', 'name': 'diamond', 'outline_style': 'no', 'size': '5'}) marker_symbol3 = QgsMarkerSymbol.createSimple( {'color': '#0000ff', 'name': 'rectangle', 'outline_style': 'no', 'size': '5'}) point_layer.setRenderer(QgsCategorizedSymbolRenderer('Class', [QgsRendererCategory('B52', marker_symbol1, ''), QgsRendererCategory('Biplane', marker_symbol2, ''), QgsRendererCategory('Jet', marker_symbol3, ''), ])) point_layer.styleManager().addStyleFromLayer("blue") line_symbol = QgsLineSymbol.createSimple({'color': '#0000ff', 'line_width': '2'}) line_layer.setRenderer(QgsSingleSymbolRenderer(line_symbol)) line_layer.styleManager().addStyleFromLayer("blue") blue_record = QgsMapThemeCollection.MapThemeRecord() point_blue_record = QgsMapThemeCollection.MapThemeLayerRecord(point_layer) point_blue_record.usingCurrentStyle = True point_blue_record.currentStyle = 'blue' blue_record.addLayerRecord(point_blue_record) line_blue_record = QgsMapThemeCollection.MapThemeLayerRecord(line_layer) line_blue_record.usingCurrentStyle = True line_blue_record.currentStyle = 'blue' blue_record.addLayerRecord(line_blue_record) QgsProject.instance().mapThemeCollection().insert('blue', blue_record) layout = QgsLayout(QgsProject.instance()) layout.initializeDefaults() map1 = QgsLayoutItemMap(layout) map1.attemptSetSceneRect(QRectF(20, 20, 80, 80)) map1.setFrameEnabled(True) map1.setLayers([point_layer, line_layer]) layout.addLayoutItem(map1) map1.setExtent(point_layer.extent()) map1.setFollowVisibilityPreset(True) map1.setFollowVisibilityPresetName('red') map2 = QgsLayoutItemMap(layout) map2.attemptSetSceneRect(QRectF(20, 120, 80, 80)) map2.setFrameEnabled(True) map2.setLayers([point_layer, line_layer]) layout.addLayoutItem(map2) map2.setExtent(point_layer.extent()) map2.setFollowVisibilityPreset(True) map2.setFollowVisibilityPresetName('blue') legend = QgsLayoutItemLegend(layout) legend.setTitle("Legend") legend.attemptSetSceneRect(QRectF(120, 20, 80, 80)) legend.setFrameEnabled(True) legend.setFrameStrokeWidth(QgsLayoutMeasurement(2)) legend.setBackgroundColor(QColor(200, 200, 200)) legend.setTitle('') layout.addLayoutItem(legend) legend.setLinkedMap(map1) legend2 = QgsLayoutItemLegend(layout) legend2.setTitle("Legend") legend2.attemptSetSceneRect(QRectF(120, 120, 80, 80)) legend2.setFrameEnabled(True) legend2.setFrameStrokeWidth(QgsLayoutMeasurement(2)) legend2.setBackgroundColor(QColor(200, 200, 200)) legend2.setTitle('') layout.addLayoutItem(legend2) legend2.setLinkedMap(map2) checker = QgsLayoutChecker( 'composer_legend_theme', layout) checker.setControlPathPrefix("composer_legend") result, message = checker.testLayout() TestQgsLayoutItemLegend.report += checker.report() self.assertTrue(result, message) QgsProject.instance().clear()
def testRendererCategory(self): self.assertEqual(QgsRendererCategory().__repr__(), '<QgsRendererCategory>') self.assertEqual(QgsRendererCategory(5, None, None).__repr__(), '<QgsRendererCategory: 5>') self.assertEqual(QgsRendererCategory('abc', None, None).__repr__(), '<QgsRendererCategory: abc>') self.assertEqual(QgsRendererCategory('abc', None, 'my class').__repr__(), '<QgsRendererCategory: abc (my class)>')
def run(self): #coloco el puntero arriba del todo #QgsProject.instance().layerTreeRegistryBridge().setLayerInsertionPoint( QgsProject.instance().layerTreeRoot(), 0 ) #genero una lista con los campos de la capa selecionada layer = iface.activeLayer() if layer is None: iface.messageBar().pushMessage("ATENCION", "Selecciona una capa de puntos", duration=10) if layer.wkbType() == 1 or layer.wkbType() == 1001: prov = layer.dataProvider() field_names = [field.name() for field in prov.fields()] self.dlg.mycomboBox.clear() for element in field_names: self.dlg.mycomboBox.addItem(element) """Run method that performs all the real work""" # 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: global index_campo_seleccionado distanciaminima = int(self.dlg.lineEdit_distancia.text()) # "layer" is a QgsVectorLayer instance layer = iface.activeLayer() idx = layer.fields().indexFromName("distanc") if idx == -1: print("ya existe") res = layer.dataProvider().addAttributes( [QgsField("distanc", QVariant.String)]) #layer.addAttribute(QgsField("valido", QVariant.String)) layer.updateFields() features = layer.getFeatures() for feature in features: # retrieve every feature with its geometry and attributes #print("Feature ID: ", feature.id()) # fetch geometry # show some information about the feature geometry geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type() == QgsWkbTypes.PointGeometry: punto = geom.asPoint() x = punto.x() y = punto.y() #print("analizo los puntos",x,y) features2 = layer.getFeatures() for feature2 in features2: geom2 = feature2.geometry() punto2 = geom2.asPoint() x3 = punto2.x() y3 = punto2.y() d = ((x3 - x)**2 + (y3 - y)**2)**0.5 if d < distanciaminima: if feature2.id() == feature.id(): pass else: layer.startEditing() feature.setAttribute("distanc", 'no') print(feature2.id()) layer.updateFeature(feature) #Call commit to save the changes layer.commitChanges() categorias = [] sym = QgsMarkerSymbol.createSimple({ 'name': 'circle', 'color': 'red', 'size': '3' }) categoria = QgsRendererCategory("no", sym, "No cumple") categorias.append(categoria) sym = QgsMarkerSymbol.createSimple({ 'name': 'circle', 'color': 'blue', 'size': '2' }) categoria = QgsRendererCategory("", sym, "Cumple") categorias.append(categoria) renderer = QgsCategorizedSymbolRenderer("distanc", categorias) layer.setRenderer(renderer) # update layer's extent when new features have been added # because change of extent in provider is not propagated to the layer #Configure label settings settings = QgsPalLayerSettings() settings.fieldName = field_names[ index_campo_seleccionado] #'name' textFormat = QgsTextFormat() textFormat.setSize(10) settings.setFormat(textFormat) #create and append a new rule root = QgsRuleBasedLabeling.Rule(QgsPalLayerSettings()) rule = QgsRuleBasedLabeling.Rule(settings) #rule.setDescription(fieldName) rule.setFilterExpression(''' "distanc" = 'no' ''') root.appendChild(rule) #Apply label configuration rules = QgsRuleBasedLabeling(root) layer.setLabeling(rules) layer.setLabelsEnabled(True) layer.triggerRepaint() else: iface.messageBar().pushMessage("ATENCION", "Selecciona una capa de puntos", duration=10)
for unique_value in unique_values: count += 1 for unique_value in unique_values: symbol = QgsSymbol.defaultSymbol(layer.geometryType()) layer_style = {} increase = 256 / count layer_style['color'] = '%d, %d, %d' % (0, (256 - (iteration * (increase/2))), 0) """layer_style['color'] = '%d, %d, %d' % (randrange(0,256), randrange(0,256), randrange(0,256))""" layer_style['outline'] = '#000000' symbol_layer = QgsSimpleFillSymbolLayer.create(layer_style) if symbol_layer is not None: symbol.changeSymbolLayer(0, symbol_layer) category = QgsRendererCategory(unique_value, symbol, str(unique_value)) categories.append(category) iteration += 1 renderer = QgsCategorizedSymbolRenderer('ffh_typ_text', categories) if renderer is not None: valuableIntersected.setRenderer(renderer) valuableIntersected.triggerRepaint() """We do the same for the non-valuable habitats""" fni = nValuableIntersected.fields().indexFromName('bfn_biotop_text') unique_values = nValuableIntersected.dataProvider().uniqueValues(fni)
def testFilter(self): """Test filter creation""" renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('field') renderer.addCategory( QgsRendererCategory('a', createMarkerSymbol(), 'a')) renderer.addCategory( QgsRendererCategory('b', createMarkerSymbol(), 'b')) renderer.addCategory( QgsRendererCategory('c', createMarkerSymbol(), 'c')) # add default category renderer.addCategory( QgsRendererCategory('', createMarkerSymbol(), 'default')) fields = QgsFields() fields.append(QgsField('field', QVariant.String)) fields.append(QgsField('num', QVariant.Double)) self.assertEqual(renderer.filter(fields), '') # remove categories, leaving default assert renderer.updateCategoryRenderState(0, False) self.assertEqual(renderer.filter(fields), "(\"field\") NOT IN ('a') OR (\"field\") IS NULL") assert renderer.updateCategoryRenderState(1, False) self.assertEqual( renderer.filter(fields), "(\"field\") NOT IN ('a','b') OR (\"field\") IS NULL") assert renderer.updateCategoryRenderState(2, False) self.assertEqual( renderer.filter(fields), "(\"field\") NOT IN ('a','b','c') OR (\"field\") IS NULL") # remove default category assert renderer.updateCategoryRenderState(3, False) self.assertEqual(renderer.filter(fields), "FALSE") # add back other categories, leaving default disabled assert renderer.updateCategoryRenderState(0, True) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a')") assert renderer.updateCategoryRenderState(1, True) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b')") assert renderer.updateCategoryRenderState(2, True) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b','c')") renderer.deleteAllCategories() # just default category renderer.addCategory( QgsRendererCategory('', createMarkerSymbol(), 'default')) self.assertEqual(renderer.filter(fields), '') assert renderer.updateCategoryRenderState(0, False) self.assertEqual(renderer.filter(fields), 'FALSE') renderer.deleteAllCategories() # no default category renderer.addCategory( QgsRendererCategory('a', createMarkerSymbol(), 'a')) renderer.addCategory( QgsRendererCategory('b', createMarkerSymbol(), 'b')) renderer.addCategory( QgsRendererCategory('c', createMarkerSymbol(), 'c')) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b','c')") assert renderer.updateCategoryRenderState(0, False) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('b','c')") assert renderer.updateCategoryRenderState(2, False) self.assertEqual(renderer.filter(fields), "(\"field\") IN ('b')") assert renderer.updateCategoryRenderState(1, False) self.assertEqual(renderer.filter(fields), "FALSE") renderer.deleteAllCategories() renderer.setClassAttribute('num') # numeric categories renderer.addCategory(QgsRendererCategory(1, createMarkerSymbol(), 'a')) renderer.addCategory(QgsRendererCategory(2, createMarkerSymbol(), 'b')) renderer.addCategory(QgsRendererCategory(3, createMarkerSymbol(), 'c')) self.assertEqual(renderer.filter(fields), '(\"num\") IN (1,2,3)') assert renderer.updateCategoryRenderState(0, False) self.assertEqual(renderer.filter(fields), "(\"num\") IN (2,3)") assert renderer.updateCategoryRenderState(2, False) self.assertEqual(renderer.filter(fields), "(\"num\") IN (2)") assert renderer.updateCategoryRenderState(1, False) self.assertEqual(renderer.filter(fields), "FALSE")
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 legend_test(self): self.atlas_map.setAtlasDriven(True) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Auto) self.atlas_map.setAtlasMargin(0.10) # add a point layer ptLayer = QgsVectorLayer( "Point?crs=epsg:4326&field=attr:int(1)&field=label:string(20)", "points", "memory") pr = ptLayer.dataProvider() f1 = QgsFeature(1) f1.initAttributes(2) f1.setAttribute(0, 1) f1.setAttribute(1, "Test label 1") f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-0.638, 48.954))) f2 = QgsFeature(2) f2.initAttributes(2) f2.setAttribute(0, 2) f2.setAttribute(1, "Test label 2") f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-1.682, 48.550))) pr.addFeatures([f1, f2]) # categorized symbology r = QgsCategorizedSymbolRenderer("attr", [ QgsRendererCategory( 1, QgsMarkerSymbol.createSimple({ "color": "255,0,0", 'outline_color': 'black' }), "red"), QgsRendererCategory( 2, QgsMarkerSymbol.createSimple({ "color": "0,0,255", 'outline_color': 'black' }), "blue") ]) ptLayer.setRenderer(r) QgsProject.instance().addMapLayer(ptLayer) # add the point layer to the map settings layers = self.layers layers = [ptLayer] + layers self.atlas_map.setLayers(layers) self.overview.setLayers(layers) # add a legend legend = QgsLayoutItemLegend(self.layout) legend.attemptMove(QgsLayoutPoint(200, 100)) # sets the legend filter parameter legend.setLinkedMap(self.atlas_map) legend.setLegendFilterOutAtlas(True) self.layout.addLayoutItem(legend) self.atlas.beginRender() self.atlas.seekTo(0) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_legend', self.layout) myTestResult, myMessage = checker.testLayout() self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() # restore state self.atlas_map.setLayers([layers[1]]) self.layout.removeLayoutItem(legend) QgsProject.instance().removeMapLayer(ptLayer.id())
def run(self): """Run method that performs all the real work""" layers = self.iface.mapCanvas().layers() layer_list = [] self.dlg.layerComboBox.clear() for layer in layers: layer_list.append(layer.name()) self.dlg.layerComboBox.addItems(layer_list) # TODO: Make the active layer the selected item in combo box aLayer = qgis.utils.iface.activeLayer() # TODO: Add signal to update toleranceSpinBox.suffix (Degrees) from layerComboBox.crs.mapUnits when layer is selected: #my_UnitType = { 0: 'Meters', 1: 'Feet', 2: 'Degrees', 7: 'NauticalMiles', 8: 'Kilometers', 9: 'Yards', 10: 'Miles', 3: 'UnknownUnit'} #suffix = my_UnitType[aLayer.crs().mapUnits()] # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: if self.checkNetworkXModule() < 0: return -4 import networkx as nx layerName = self.dlg.layerComboBox.currentText() try: aLayer = QgsProject.instance().mapLayersByName(layerName)[0] except: self.iface.messageBar().pushMessage("Error", "Failed to load layer!", level=Qgis.Critical) return -1 try: previousEditingMode = True if not aLayer.isEditable(): aLayer.startEditing() #self.iface.messageBar().pushMessage("Info", "Layer " + aLayer.name() + " needs to be in edit mode", level=Qgis.Info) #self.iface.messageBar().pushMessage("Error", "Layer " + aLayer.name() + " needs to be in edit mode", level=Qgis.Critical) #return -2 previousEditingMode = False attrIdx = self.getAttributeIndex(aLayer) if attrIdx < 0: return -3 progressMessageBar = self.iface.messageBar().createMessage("Creating network graph...") progress = QProgressBar() progress.setMaximum(aLayer.featureCount()) progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) G = nx.Graph() aLayer.beginEditCommand("Clear group attribute, create graph") # construct undirected graph tolerance = self.dlg.toleranceSpinBox.value() if tolerance == 0: tolerance = 0.000001 count = 0 for feat in aLayer.getFeatures(): count += 1 progress.setValue(count) done = aLayer.changeAttributeValue(feat.id(), attrIdx, -1) geom = feat.geometry() QgsGeometry.convertToSingleType(geom) # QGIS 3.x seems to load single LineString as MultiLineString?? line = geom.asPolyline() for i in range(len(line)-1): G.add_edges_from([((int(line[i][0]/tolerance), int(line[i][1]/tolerance)), (int(line[i+1][0]/tolerance), int(line[i+1][1]/tolerance)), {'fid': feat.id()})]) # first scale by tolerance, then convert to int. Before doing this, there were problems (in NetworkX v1) with floats not equating, thus creating disconnects that weren't there. if count % 100 == 0: QApplication.processEvents() # keep the UI responsive, every 100 features #TODO: check to see if Esc pressed aLayer.endEditCommand() self.iface.messageBar().pushMessage("Finding connected subgraphs, please wait...", level=Qgis.Warning) # WARNING - to highlight the next stage, where we cannot show progress QApplication.processEvents() connected_components = list(G.subgraph(c) for c in nx.connected_components(G)) # this takes a long time. TODO: how to show progress? self.iface.messageBar().pushMessage("Updating group attribute...", level=Qgis.Info) QApplication.processEvents() # gather edges and components to which they belong fid_comp = {} for i, graph in enumerate(connected_components): for edge in graph.edges(data=True): fid_comp[edge[2].get('fid', None)] = i # write output to csv file #with open('C:/Tmp/Components.csv', 'wb') as f: # w = csv.DictWriter(f, fieldnames=['fid', 'group']) # w.writeheader() # for (fid, group) in fid_comp.items(): # w.writerow({'fid': fid, 'group': group}) aLayer.beginEditCommand("Update group attribute") for (fid, group) in fid_comp.items(): done = aLayer.changeAttributeValue(fid, attrIdx, group) aLayer.endEditCommand() groups = list(set(fid_comp.values())) if self.dlg.stylingCheckBox.isChecked(): aLayer.beginEditCommand("Update layer styling") categories = [] firstCat = True for cat in groups: symbol = QgsSymbol.defaultSymbol(aLayer.geometryType()) symbol.setColor(QColor(randint(0,255), randint(0,255), randint(0,255))) if firstCat: firstCat = False else: symbol.setWidth(symbol.width()*5) category = QgsRendererCategory(cat, symbol, "%d" % cat) categories.append(category) field = self.dlg.attributeNameEditBox.text() renderer = QgsCategorizedSymbolRenderer(field, categories) aLayer.setRenderer(renderer) # if self.iface.mapCanvas().isCachingEnabled(): # aLayer.setCacheImage(None) # else: # self.iface.mapCanvas().refresh() aLayer.triggerRepaint() aLayer.endEditCommand() self.iface.messageBar().clearWidgets() self.iface.messageBar().pushMessage("Found main network and %d disconnected islands in layer %s" % (len(groups)-1, aLayer.name()), level=Qgis.Success) aLayer.commitChanges() # if not previousEditingMode: except Exception as e: self.iface.messageBar().pushMessage("Error", "Exception caught: %s. Please report an issue to the author of the plugin." % repr(e), level=Qgis.Critical)
def __build_lines(self) -> None: """ Save the current self.__tmp_units in an in-memory layer called 'Parallel Unit Lines' Create a layer with the given name if it is not existing :return: Nothing """ unit_list = list() for unit in self.__tmp_units: unit_list.append([unit[0], unit[1].asGeometry()]) layers = [ lyr for lyr in self.__iface.mapCanvas().layers() if lyr.name() == "Parallel Unit Lines" ] if len(layers) == 0: current_layer = self.__iface.mapCanvas().currentLayer() # noinspection PyArgumentList crs = QgsProject.instance().crs().toWkt() uri = "linestring?crs=wkt:{}&field=name:string(255)".format(crs) vector_layer = QgsVectorLayer(uri, "Parallel Unit Lines", "memory") # noinspection PyArgumentList QgsProject.instance().addMapLayer(vector_layer) self.__iface.mapCanvas().setCurrentLayer(current_layer) else: vector_layer = layers[0] if (not vector_layer.isValid()) or (vector_layer.type() != QgsMapLayer.VectorLayer): self.__iface.messageBar(). \ pushCritical("Wrong Layer Type", "The layer \"Parallel Unit Lines\" cannot be created or has the wrong format") return vpr = vector_layer.dataProvider() fields = [f.name() for f in vpr.fields().toList()] if "name" not in fields: # noinspection PyArgumentList vpr.addAttributes([QgsField("name", QVariant.String, len=255)]) name_field_index = vpr.fields().indexOf("name") if vpr.fields()[name_field_index].typeName().lower() != "string": self.__iface.messageBar(). \ pushCritical("Wrong Attribute Type", "The name attribute of the layer \"Parallel Unit Lines\" is not of type \"String\"!") return try: # adding the features to the layer for unit in unit_list: f = QgsFeature() f.setGeometry(unit[1]) attr = list() for _ in vpr.fields().toList(): attr.append(None) attr[name_field_index] = unit[0] f.setAttributes(attr) vpr.addFeatures([f]) vector_layer.updateExtents() # at least: try to set symbology symbology = list() for index in range(self.model.rowCount()): row = self.model.row(index) # noinspection PyArgumentList sym = QgsSymbol.defaultSymbol(vector_layer.geometryType()) sym.setColor(row.color) sym.setWidth(0.4) category = QgsRendererCategory(row.name, sym, row.name) symbology.append(category) renderer = QgsCategorizedSymbolRenderer("name", symbology) vector_layer.setRenderer(renderer) vector_layer.triggerRepaint() except Exception as e: _, _, exc_traceback = sys.exc_info() text = "Error Message:\n{}\nTraceback:\n{}".format( str(e), '\n'.join(traceback.format_tb(exc_traceback))) # noinspection PyTypeChecker,PyCallByClass QgsMessageLog.logMessage(text, level=2) finally: self.reset()
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 stylePoly(self, layer, metric: str): """ Style isochrone polygon layer. :param QgsVectorLayer layer: Polygon layer to be styled. :param str metric: distance or time. """ field = layer.fields().lookupField('contour') unique_values = sorted(layer.uniqueValues(field)) colors = { "distance": { 0: QColor('#FCF0EE'), 1: QColor('#F9E1DC'), 2: QColor('#F6D2CB'), 3: QColor('#F3C3BA'), 4: QColor('#F0B3A8'), 5: QColor('#EDA396'), 6: QColor('#EA9485'), 7: QColor('#E78573'), 8: QColor('#E47662'), 9: QColor('#E16651') }, "time": { 0: QColor('#2b83ba'), 1: QColor('#64abb0'), 2: QColor('#9dd3a7'), 3: QColor('#c7e9ad'), 4: QColor('#edf8b9'), 5: QColor('#ffedaa'), 6: QColor('#fec980'), 7: QColor('#f99e59'), 8: QColor('#e85b3a'), 9: QColor('#d7191c') } } categories = [] for cid, unique_value in enumerate(unique_values): # initialize the default symbol for this geometry type symbol = QgsSymbol.defaultSymbol(layer.geometryType()) # configure a symbol layer symbol_layer = QgsSimpleFillSymbolLayer( color=colors[metric][cid], strokeColor=QColor('#000000')) # replace default symbol layer with the configured one if symbol_layer is not None: symbol.changeSymbolLayer(0, symbol_layer) # create renderer object category = QgsRendererCategory(unique_value, symbol, str(unique_value) + ' mins') # entry for the list of category items categories.append(category) # create renderer object renderer = QgsCategorizedSymbolRenderer('contour', categories) # assign the created renderer to the layer if renderer is not None: layer.setRenderer(renderer) layer.setOpacity(0.5) layer.triggerRepaint()
def open_file(dialog: QDialog = None, osm_file: str = None, output_geom_types: list = None, white_list_column: dict = None, key: Union[str, List[str]] = None, layer_name: str = "OsmFile", config_outputs: dict = None, output_dir: str = None, output_format: Format = None, final_query: str = None, prefix_file: str = None, subset: bool = False, subset_query: str = None, feedback: QgsFeedback = None) -> int: """ Open an osm file. Memory layer if no output directory is set, or Geojson in the output directory. :param final_query: The query where the file comes from. Might be empty if it's a local OSM file. :type final_query: basestring """ if output_geom_types is None: output_geom_types = OSM_LAYERS # Legacy, waiting to remove the OsmParser for QGIS >= 3.6 # Change in osm_file_dialog.py L131 too output_geom_legacy = [geom.value.lower() for geom in output_geom_types] if not white_list_column: white_list_column = None LOGGER.info('The OSM file is: {}'.format(osm_file)) if feedback: if feedback.isCanceled(): return None # Parsing the file osm_parser = OsmParser(osm_file=osm_file, layers=output_geom_legacy, output_format=output_format, output_dir=output_dir, prefix_file=prefix_file, layer_name=layer_name, key=key, white_list_column=white_list_column, subset=subset, subset_query=subset_query, feedback=feedback) if dialog: osm_parser.signalText.connect(dialog.set_progress_text) osm_parser.signalPercentage.connect(dialog.set_progress_percentage) start_time = time.time() layers = osm_parser.processing_parse() elapsed_time = time.time() - start_time parser_time = time.strftime("%Hh %Mm %Ss", time.gmtime(elapsed_time)) LOGGER.info('The OSM parser took: {}'.format(parser_time)) if feedback: if feedback.isCanceled(): return None # Finishing the process with an output format or memory layer num_layers = 0 for i, (layer, item) in enumerate(layers.items()): if dialog: dialog.set_progress_percentage(i / len(layers) * 100) QApplication.processEvents() if item['featureCount'] and (LayerType(layer.capitalize()) in output_geom_types): final_layer_name = layer_name # If configOutputs is not None (from My Queries) if config_outputs: if config_outputs[layer]['namelayer']: final_layer_name = config_outputs[layer]['namelayer'] new_layer = item['vector_layer'] new_layer.setName(final_layer_name) # Try to set styling if defined if config_outputs and config_outputs[layer]['style']: new_layer.loadNamedStyle(config_outputs[layer]['style']) else: if "colour" in item['tags']: index = item['tags'].index('colour') colors = new_layer.uniqueValues(index) categories = [] for value in colors: if str(value) == 'None': value = '' if layer in ['lines', 'multilinestrings']: symbol = QgsSymbol.defaultSymbol( QgsWkbTypes.LineGeometry) elif layer == "points": symbol = QgsSymbol.defaultSymbol( QgsWkbTypes.PointGeometry) elif layer == "multipolygons": symbol = QgsSymbol.defaultSymbol( QgsWkbTypes.PolygonGeometry) symbol.setColor(QColor(value)) category = QgsRendererCategory(str(value), symbol, str(value)) categories.append(category) renderer = QgsCategorizedSymbolRenderer( "colour", categories) new_layer.setRenderer(renderer) # Add action about OpenStreetMap actions.add_actions(new_layer, item['tags']) QgsProject.instance().addMapLayer(new_layer) if final_query: QgsExpressionContextUtils.setLayerVariable( new_layer, 'quickosm_query', final_query) actions.add_relaunch_action(new_layer, final_layer_name) if dialog: dialog.iface.addCustomActionForLayer( dialog.reload_action, new_layer) metadata = QgsLayerMetadata() metadata.setRights([tr("© OpenStreetMap contributors")]) metadata.setLicenses(['https://openstreetmap.org/copyright']) new_layer.setMetadata(metadata) num_layers += 1 return num_layers
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 stylize_map(layer: QgsVectorLayer) -> [List[str], List[str]]: """Stylize the layer with unique colors per timezone Args: layer (QgsVectorLayer): The layer to stylize Returns: [List[str], List[str]]: A list with all timezone ids and one with the respective color """ print("Reading timezones from file") timezones = layer.uniqueValues(layer.fields().indexOf("tzid")) timezones = list(timezones) timezones.sort() categorized_renderer = QgsCategorizedSymbolRenderer() print("Stylizing map") timezone_ids = [] timezone_colors = [] features = layer.getFeatures() categories = [] currentColor = 0 for tz in timezones: # Modify the Etc timezones to match the Qt format qt_tz = tz # There are a few exceptions where the Qt timezone ids differ from the dataset ids: match = re.match(r"Etc/GMT([+-])(\d+)", tz) if match: qt_tz = f"UTC{match.group(1)}{match.group(2):0>2}:00" elif tz == "Etc/UTC": qt_tz = "UTC" elif tz == "Etc/GMT": qt_tz = "UTC+00:00" # Generate a consecutive color for each timezone currentColor += 25000 r = (currentColor >> 16) & 255 g = (currentColor >> 8 ) & 255 b = (currentColor ) & 255 # Add it to the mapping rh = hex(r)[2:] gh = hex(g)[2:] bh = hex(b)[2:] timezone_ids.append(qt_tz) timezone_colors.append(f"#{rh:0>2}{gh:0>2}{bh:0>2}") symbol = QgsSymbol.defaultSymbol(layer.geometryType()) symbol_layer = QgsSimpleFillSymbolLayer.create({"color": f"{r}, {g}, {b}"}) symbol_layer.setStrokeWidth(0.0) symbol_layer.setStrokeStyle(Qt.PenStyle.NoPen) symbol.changeSymbolLayer(0, symbol_layer) category = QgsRendererCategory(tz, symbol, tz) categories.append(category) renderer = QgsCategorizedSymbolRenderer("tzid", categories) layer.setRenderer(renderer) layer.triggerRepaint() return timezone_ids, timezone_colors
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 _apply_symbology_fixed_divisions(self, layer, field, tbl_name, schema, min_v, max_v, steps): """Finds the amount of levels that is necessary to describe the layer, a maximum of 20 different levels is set. Parameters ---------- layer: QgsVectorLayer field: str tbl_name: str schema: str min_v: float max_v: float steps: int """ str_values = False if min_v is not None and max_v is not None: distinct_values = list(np.arange(min_v, max_v, steps)) elif not str_values: distinct = self.db.get_distinct(tbl_name, field, schema) if len(distinct) == 1: return distinct_values = [] distinct_count = [] for value, count in distinct: if value is None: continue distinct_values.append(value) distinct_count.append(count) if len(distinct_values) > 20: distinct_values.sort() temp_list = [] for val in range(0, len(distinct_values), int(np.floor(len(distinct_values)/20))): temp_list.append(distinct_values[val]) if temp_list[-1] != distinct_values[-1]: temp_list.append(distinct_values[-1]) distinct_values = temp_list if isinstance(distinct_values[0], str): str_values = True colors = self._create_colors(len(distinct_values)) if len(distinct_values) > 19 and not str_values: range_list = [] for i in range(len(distinct_values) - 1): red, green, blue = colors[i] range_list.append(self._make_symbology(layer, distinct_values[i], distinct_values[i + 1], str(distinct_values[i]) + ' - ' + str(distinct_values[i + 1]), QColor(int(red*255),int(green*255), int(blue*255), 128) ) ) renderer = QgsGraduatedSymbolRenderer(field, range_list) renderer.setMode(QgsGraduatedSymbolRenderer.Custom ) else: categories = [] for i in range(len(distinct_values)): symbol = QgsSymbol.defaultSymbol(layer.geometryType()) red, green, blue = colors[i] symbol.setColor(QColor(int(red*255),int(green*255), int(blue*255), 128)) symbol.symbolLayer(0).setStrokeColor(QColor(int(red*255),int(green*255), int(blue*255), 128)) category = QgsRendererCategory(str(distinct_values[i]), symbol, str(distinct_values[i])) categories.append(category) renderer = QgsCategorizedSymbolRenderer(field, categories) #renderer.setMode(QgsCategorizedSymbolRenderer.Custom) layer.setRenderer(renderer)
def testConvertFromCategorisedRendererNoLayer(self): # Test converting categorised renderer to rule based # First, try with a field based category (id) cats = [] cats.append(QgsRendererCategory(1, QgsMarkerSymbol(), "id 1")) cats.append(QgsRendererCategory(2, QgsMarkerSymbol(), "id 2")) cats.append(QgsRendererCategory('a\'b', QgsMarkerSymbol(), "id a'b")) cats.append(QgsRendererCategory('a\nb', QgsMarkerSymbol(), "id a\\nb")) cats.append(QgsRendererCategory('a\\b', QgsMarkerSymbol(), "id a\\\\b")) cats.append(QgsRendererCategory('a\tb', QgsMarkerSymbol(), "id a\\tb")) cats.append(QgsRendererCategory(['c', 'd'], QgsMarkerSymbol(), "c/d")) c = QgsCategorizedSymbolRenderer("id", cats) r = QgsRuleBasedRenderer.convertFromRenderer(c) self.assertEqual(len(r.rootRule().children()), 7) self.assertEqual(r.rootRule().children()[0].filterExpression(), '"id" = 1') self.assertEqual(r.rootRule().children()[1].filterExpression(), '"id" = 2') self.assertEqual(r.rootRule().children()[2].filterExpression(), '"id" = \'a\'\'b\'') self.assertEqual(r.rootRule().children()[3].filterExpression(), '"id" = \'a\\nb\'') self.assertEqual(r.rootRule().children()[4].filterExpression(), '"id" = \'a\\\\b\'') self.assertEqual(r.rootRule().children()[5].filterExpression(), '"id" = \'a\\tb\'') self.assertEqual(r.rootRule().children()[6].filterExpression(), '"id" IN (\'c\',\'d\')') # Next try with an expression based category cats = [] cats.append(QgsRendererCategory(1, QgsMarkerSymbol(), "result 1")) cats.append(QgsRendererCategory(2, QgsMarkerSymbol(), "result 2")) cats.append( QgsRendererCategory([3, 4], QgsMarkerSymbol(), "result 3/4")) c = QgsCategorizedSymbolRenderer("id + 1", cats) r = QgsRuleBasedRenderer.convertFromRenderer(c) self.assertEqual(len(r.rootRule().children()), 3) self.assertEqual(r.rootRule().children()[0].filterExpression(), 'id + 1 = 1') self.assertEqual(r.rootRule().children()[1].filterExpression(), 'id + 1 = 2') self.assertEqual(r.rootRule().children()[2].filterExpression(), 'id + 1 IN (3,4)') # Last try with an expression which is just a quoted field name cats = [] cats.append(QgsRendererCategory(1, QgsMarkerSymbol(), "result 1")) cats.append(QgsRendererCategory(2, QgsMarkerSymbol(), "result 2")) cats.append( QgsRendererCategory([3, 4], QgsMarkerSymbol(), "result 3/4")) c = QgsCategorizedSymbolRenderer('"id"', cats) r = QgsRuleBasedRenderer.convertFromRenderer(c) self.assertEqual(len(r.rootRule().children()), 3) self.assertEqual(r.rootRule().children()[0].filterExpression(), '"id" = 1') self.assertEqual(r.rootRule().children()[1].filterExpression(), '"id" = 2') self.assertEqual(r.rootRule().children()[2].filterExpression(), '"id" IN (3,4)') # Next try with a complex name -- in this case since we don't have a layer or # actual field names available, we must assume the complex field name is actually an expression cats = [] cats.append(QgsRendererCategory(1, QgsMarkerSymbol(), "fa_cy-fie+ld 1")) cats.append(QgsRendererCategory(2, QgsMarkerSymbol(), "fa_cy-fie+ld 2")) c = QgsCategorizedSymbolRenderer("fa_cy-fie+ld", cats) r = QgsRuleBasedRenderer.convertFromRenderer(c) self.assertEqual(r.rootRule().children()[0].filterExpression(), 'fa_cy-fie+ld = 1') self.assertEqual(r.rootRule().children()[1].filterExpression(), 'fa_cy-fie+ld = 2')
def run(self): """Run method that performs all the real work""" # 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 self.dlg = HealthSIGDialog() # Clear the contents of the comboBox from previous runs self.dlg.comboBox.clear() # Populate the comboBox self.dlg.comboBox.addItems(["Hospitais", "ACES", "Farmácias"]) # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed and check index index = self.dlg.comboBox.currentIndex() # file directory for relative paths dirn = os.path.dirname(__file__) # escolheu unidades de saude if result and index == 1: # create layer vl = QgsVectorLayer("Point?crs=epsg:3763&index=yes", "aces", "memory") pr = vl.dataProvider() # Enter editing mode vl.startEditing() # add fields pr.addAttributes([ QgsField("ACES", QVariant.String), QgsField("ARS", QVariant.String), QgsField("Coord_X", QVariant.Double), QgsField("Coord_Y", QVariant.Double), QgsField("Num_USF", QVariant.Int) ]) vl.updateFields( ) # tell the vector layer to fetch changes from the provider # add features ---> IR BUSCAR AO JSON.... filename = os.path.join(dirn, 'unidades_saude.json') #with open("/home/skywalker/.local/share/QGIS/QGIS3/profiles/default/python/plugins/health_sig/unidades_saude.json", # "r") as read_file: with open(filename, "r") as read_file: json_file = json.load(read_file) # transformar coordenadas gps para as pretendidas crsSrc = QgsCoordinateReferenceSystem(4326) # gps crsDest = QgsCoordinateReferenceSystem(3763) # pt xform = QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance()) # addfeatures for entry in json_file: if entry["fields"]["tempo"] == "2019-01": # valores recentes x_coord = float(entry["geometry"]["coordinates"][0]) y_coord = float(entry["geometry"]["coordinates"][1]) num_usf = int( entry["fields"] ["total_usf"]) #numero de unidades de saude familiares entidade = entry["fields"]["entidade"] ars = entry["fields"]["ars"] fet = QgsFeature() fet.setGeometry(QgsGeometry().buffer( distance=num_usf * 10, segments=100).fromPointXY( xform.transform(QgsPointXY(x_coord, y_coord)))) fet.setAttributes([ QVariant(entidade), QVariant(ars), QVariant(x_coord), QVariant(y_coord), QVariant(num_usf) ]) pr.addFeatures([fet]) vl.updateExtents() vl.commitChanges() # fazer render categorizado features = vl.getFeatures() categories = [] for feat in features: f = feat.attributes()[4] # num_usf entidade = feat.attributes()[0] # entidade symbol = QgsSymbol.defaultSymbol(vl.geometryType()) svgStyle = {} path_uni = os.path.join(dirn, 'medicine.svg') svgStyle['name'] = path_uni svgStyle['size'] = str((f / 10) + 1) symbol_layer = QgsSvgMarkerSymbolLayer.create(svgStyle) if symbol_layer is not None: symbol.changeSymbolLayer(0, symbol_layer) # create renderer object category = QgsRendererCategory(f, symbol, str(entidade)) # entry for the list of category items categories.append(category) # create renderer object renderer = QgsCategorizedSymbolRenderer('Num_USF', categories) # assign the created renderer to the layer if renderer is not None: vl.setRenderer(renderer) vl.triggerRepaint() QgsProject.instance().addMapLayer(vl) # hospitais elif result and index == 0: vl = QgsVectorLayer("Point?crs=epsg:3763&index=yes", "hospitais", "memory") pr = vl.dataProvider() # Enter editing mode vl.startEditing() # add fields pr.addAttributes([ QgsField("Hospital", QVariant.String), QgsField("Morada", QVariant.String), QgsField("Coord_X", QVariant.Double), QgsField("Coord_Y", QVariant.Double) ]) vl.updateFields( ) # tell the vector layer to fetch changes from the provider # add features ---> IR BUSCAR AO JSON.... filename = os.path.join(dirn, 'hospitais.json') with open(filename, "r") as read_file: json_file = json.load(read_file) # transformar coordenadas gps para as pretendidas crsSrc = QgsCoordinateReferenceSystem(4326) # gps crsDest = QgsCoordinateReferenceSystem(3763) # pt xform = QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance()) # addfeatures for entry in json_file.keys(): x_coord = float(json_file[entry][1][1]) y_coord = float(json_file[entry][1][0]) morada = json_file[entry][0] fet = QgsFeature() fet.setGeometry(QgsGeometry().fromPointXY( xform.transform(QgsPointXY(x_coord, y_coord)))) fet.setAttributes([ QVariant(entry), QVariant(morada), QVariant(x_coord), QVariant(y_coord) ]) pr.addFeatures([fet]) vl.updateExtents() vl.commitChanges() #symbol = QgsMarkerSymbol.createSimple({'name': 'square', 'color': 'red'}) svgStyle = {} path_hosp = os.path.join(dirn, 'hospital.svg') svgStyle['name'] = path_hosp svgStyle['size'] = '6' symbol_layer = QgsSvgMarkerSymbolLayer.create(svgStyle) symbol = QgsSymbol.defaultSymbol(vl.geometryType()) #vl.renderer().setSymbol(symbol) symbol.changeSymbolLayer(0, symbol_layer) vl.renderer().setSymbol(symbol) # show the change vl.triggerRepaint() QgsProject.instance().addMapLayer(vl) # farmacias elif result and index == 2: vl = QgsVectorLayer("Point?crs=epsg:3763&index=yes", "farmacias", "memory") pr = vl.dataProvider() # Enter editing mode vl.startEditing() # add fields pr.addAttributes([ QgsField("Farmácia", QVariant.String), QgsField("Morada", QVariant.String), QgsField("Coord_X", QVariant.Double), QgsField("Coord_Y", QVariant.Double) ]) vl.updateFields( ) # tell the vector layer to fetch changes from the provider # add features ---> IR BUSCAR AO JSON.... filename = os.path.join(dirn, 'farmacias.json') with open(filename, "r") as read_file: json_file = json.load(read_file) # transformar coordenadas gps para as pretendidas crsSrc = QgsCoordinateReferenceSystem(4326) # gps crsDest = QgsCoordinateReferenceSystem(3763) # pt xform = QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance()) # addfeatures for entry in json_file.keys(): x_coord = float(json_file[entry][1][1]) y_coord = float(json_file[entry][1][0]) morada = json_file[entry][0] fet = QgsFeature() fet.setGeometry(QgsGeometry().fromPointXY( xform.transform(QgsPointXY(x_coord, y_coord)))) fet.setAttributes([ QVariant(entry), QVariant(morada), QVariant(x_coord), QVariant(y_coord) ]) pr.addFeatures([fet]) vl.updateExtents() vl.commitChanges() #symbol = QgsMarkerSymbol.createSimple({'name': 'square', 'color': 'purplet'}) #vl.renderer().setSymbol(symbol) svgStyle = {} path_farm = os.path.join(dirn, 'pharmacy.svg') svgStyle['name'] = path_farm svgStyle['size'] = '4' symbol_layer = QgsSvgMarkerSymbolLayer.create(svgStyle) symbol = QgsSymbol.defaultSymbol(vl.geometryType()) # vl.renderer().setSymbol(symbol) symbol.changeSymbolLayer(0, symbol_layer) vl.renderer().setSymbol(symbol) # show the change vl.triggerRepaint() QgsProject.instance().addMapLayer(vl)
def testMatchToSymbols(self): """ Test QgsCategorizedSymbolRender.matchToSymbols """ renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('x') symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 0, 0)) renderer.addCategory(QgsRendererCategory('a', symbol_a, 'a')) symbol_b = createMarkerSymbol() symbol_b.setColor(QColor(0, 255, 0)) renderer.addCategory(QgsRendererCategory('b', symbol_b, 'b')) symbol_c = createMarkerSymbol() symbol_c.setColor(QColor(0, 0, 255)) renderer.addCategory(QgsRendererCategory('c ', symbol_c, 'c')) matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( None, QgsSymbol.Marker) self.assertEqual(matched, 0) style = QgsStyle() symbol_a = createMarkerSymbol() symbol_a.setColor(QColor(255, 10, 10)) self.assertTrue(style.addSymbol('a', symbol_a)) symbol_B = createMarkerSymbol() symbol_B.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('B ', symbol_B)) symbol_b = createFillSymbol() symbol_b.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('b', symbol_b)) symbol_C = createLineSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol('C', symbol_C)) symbol_C = createMarkerSymbol() symbol_C.setColor(QColor(10, 255, 10)) self.assertTrue(style.addSymbol(' ----c/- ', symbol_C)) # non-matching symbol type matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Line) self.assertEqual(matched, 0) self.assertEqual(unmatched_cats, ['a', 'b', 'c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'B ', 'C', 'a', 'b']) # exact match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Marker) self.assertEqual(matched, 1) self.assertEqual(unmatched_cats, ['b', 'c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'B ', 'C', 'b']) # make sure symbol was applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') renderer.stopRender(context) # case insensitive match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Marker, False) self.assertEqual(matched, 2) self.assertEqual(unmatched_cats, ['c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('b') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context) # case insensitive match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Marker, False) self.assertEqual(matched, 2) self.assertEqual(unmatched_cats, ['c ']) self.assertEqual(unmatched_symbols, [' ----c/- ', 'C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('b') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context) # tolerant match matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Marker, True, True) self.assertEqual(matched, 2) self.assertEqual(unmatched_cats, ['b']) self.assertEqual(unmatched_symbols, ['B ', 'C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('c ') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context) # tolerant match, case insensitive matched, unmatched_cats, unmatched_symbols = renderer.matchToSymbols( style, QgsSymbol.Marker, False, True) self.assertEqual(matched, 3) self.assertFalse(unmatched_cats) self.assertEqual(unmatched_symbols, ['C', 'b']) # make sure symbols were applied context = QgsRenderContext() renderer.startRender(context, QgsFields()) symbol, ok = renderer.symbolForValue2('a') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#ff0a0a') symbol, ok = renderer.symbolForValue2('b') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') symbol, ok = renderer.symbolForValue2('c ') self.assertTrue(ok) self.assertEqual(symbol.color().name(), '#0aff0a') renderer.stopRender(context)
def test_legend_key_to_expression(self): renderer = QgsCategorizedSymbolRenderer() renderer.setClassAttribute('field_name') exp, ok = renderer.legendKeyToExpression('xxxx', None) self.assertFalse(ok) # no categories exp, ok = renderer.legendKeyToExpression('0', None) self.assertFalse(ok) symbol_a = createMarkerSymbol() renderer.addCategory(QgsRendererCategory('a', symbol_a, 'a')) symbol_b = createMarkerSymbol() renderer.addCategory(QgsRendererCategory(5, symbol_b, 'b')) symbol_c = createMarkerSymbol() renderer.addCategory(QgsRendererCategory(5.5, symbol_c, 'c', False)) symbol_d = createMarkerSymbol() renderer.addCategory(QgsRendererCategory(['d', 'e'], symbol_d, 'de')) exp, ok = renderer.legendKeyToExpression('0', None) self.assertTrue(ok) self.assertEqual(exp, "field_name = 'a'") exp, ok = renderer.legendKeyToExpression('1', None) self.assertTrue(ok) self.assertEqual(exp, "field_name = 5") exp, ok = renderer.legendKeyToExpression('2', None) self.assertTrue(ok) self.assertEqual(exp, "field_name = 5.5") exp, ok = renderer.legendKeyToExpression('3', None) self.assertTrue(ok) self.assertEqual(exp, "field_name IN ('d', 'e')") layer = QgsVectorLayer( "Point?field=field_name:double&field=fldint:integer", "addfeat", "memory") # with layer exp, ok = renderer.legendKeyToExpression('3', layer) self.assertTrue(ok) self.assertEqual(exp, "\"field_name\" IN ('d', 'e')") # with expression as attribute renderer.setClassAttribute('upper("field_name")') exp, ok = renderer.legendKeyToExpression('0', None) self.assertTrue(ok) self.assertEqual(exp, """upper("field_name") = 'a'""") exp, ok = renderer.legendKeyToExpression('1', None) self.assertTrue(ok) self.assertEqual(exp, """upper("field_name") = 5""") exp, ok = renderer.legendKeyToExpression('2', None) self.assertTrue(ok) self.assertEqual(exp, """upper("field_name") = 5.5""") exp, ok = renderer.legendKeyToExpression('3', None) self.assertTrue(ok) self.assertEqual(exp, """upper("field_name") IN ('d', 'e')""") exp, ok = renderer.legendKeyToExpression('3', layer) self.assertTrue(ok) self.assertEqual(exp, """upper("field_name") IN ('d', 'e')""")
def testConvertFromCategorisedRenderer(self): # Test converting categorised renderer to rule based # First, try with a field based category (id) cats = [] cats.append(QgsRendererCategory(1, QgsMarkerSymbol(), "id 1")) cats.append(QgsRendererCategory(2, QgsMarkerSymbol(), "id 2")) cats.append(QgsRendererCategory('a\'b', QgsMarkerSymbol(), "id a'b")) cats.append(QgsRendererCategory('a\nb', QgsMarkerSymbol(), "id a\\nb")) cats.append(QgsRendererCategory('a\\b', QgsMarkerSymbol(), "id a\\\\b")) cats.append(QgsRendererCategory('a\tb', QgsMarkerSymbol(), "id a\\tb")) cats.append(QgsRendererCategory(['c', 'd'], QgsMarkerSymbol(), "c/d")) c = QgsCategorizedSymbolRenderer("id", cats) r = QgsRuleBasedRenderer.convertFromRenderer(c) self.assertEqual(len(r.rootRule().children()), 7) self.assertEqual(r.rootRule().children()[0].filterExpression(), '"id" = 1') self.assertEqual(r.rootRule().children()[1].filterExpression(), '"id" = 2') self.assertEqual(r.rootRule().children()[2].filterExpression(), '"id" = \'a\'\'b\'') self.assertEqual(r.rootRule().children()[3].filterExpression(), '"id" = \'a\\nb\'') self.assertEqual(r.rootRule().children()[4].filterExpression(), '"id" = \'a\\\\b\'') self.assertEqual(r.rootRule().children()[5].filterExpression(), '"id" = \'a\\tb\'') self.assertEqual(r.rootRule().children()[6].filterExpression(), '"id" IN (\'c\',\'d\')') # Next try with an expression based category cats = [] cats.append(QgsRendererCategory(1, QgsMarkerSymbol(), "result 1")) cats.append(QgsRendererCategory(2, QgsMarkerSymbol(), "result 2")) cats.append( QgsRendererCategory([3, 4], QgsMarkerSymbol(), "result 3/4")) c = QgsCategorizedSymbolRenderer("id + 1", cats) r = QgsRuleBasedRenderer.convertFromRenderer(c) self.assertEqual(len(r.rootRule().children()), 3) self.assertEqual(r.rootRule().children()[0].filterExpression(), 'id + 1 = 1') self.assertEqual(r.rootRule().children()[1].filterExpression(), 'id + 1 = 2') self.assertEqual(r.rootRule().children()[2].filterExpression(), 'id + 1 IN (3,4)') # Last try with an expression which is just a quoted field name cats = [] cats.append(QgsRendererCategory(1, QgsMarkerSymbol(), "result 1")) cats.append(QgsRendererCategory(2, QgsMarkerSymbol(), "result 2")) cats.append( QgsRendererCategory([3, 4], QgsMarkerSymbol(), "result 3/4")) c = QgsCategorizedSymbolRenderer('"id"', cats) r = QgsRuleBasedRenderer.convertFromRenderer(c) self.assertEqual(len(r.rootRule().children()), 3) self.assertEqual(r.rootRule().children()[0].filterExpression(), '"id" = 1') self.assertEqual(r.rootRule().children()[1].filterExpression(), '"id" = 2') self.assertEqual(r.rootRule().children()[2].filterExpression(), '"id" IN (3,4)')
def processAlgorithm(self, parameters, context, feedback): project = QgsProject() project.setFileName( os.path.join(parameters[self.FOLDER], "all-outputs-qgis.qgs")) project.setCrs(QgsCoordinateReferenceSystem('EPSG:27700')) def getMaxValue(layer, fieldname): maxfound = float("-inf") for f in layer.getFeatures(): attr = f.attribute(fieldname) assert attr >= 0 if attr > maxfound: maxfound = attr return maxfound with open( os.path.join(parameters[self.FOLDER], "all-town-metadata.json")) as f: metadata = json.load(f) classmethods = { 'quantile': QgsClassificationQuantile, 'jenks': QgsClassificationJenks, 'equal': QgsClassificationEqualInterval } html = "" output = [] views_sorted_by_mode = sorted(metadata["views"], key=lambda v: v["mode"]) for view in views_sorted_by_mode: keysymbol = u'🔑' viewname = view["label"] keysign = "" if viewname.find(keysymbol) != -1: viewname = viewname.replace(keysymbol, '', 1) keysign = "*** " viewname = keysign + view["mode"] + " " + viewname html += f""" <h2>{viewname}</h2> {view["description"]} <ul> """ for layer in view["layers"]: layername = viewname + " - " + layer["scalar_field_units"] layerpath = os.path.join(parameters[self.FOLDER], layer["file"]) vlayer = QgsVectorLayer(layerpath, layername, "ogr") if not vlayer.isValid(): feedback.pushInfo("Layer failed to load: " + layerpath) else: context.temporaryLayerStore().addMapLayer(vlayer) html += f"""<li><b>file:</b> {layer["file"]}""" if "symbol_field" in layer: html += f"""<ul> <li><b>symbol field:</b> {layer["symbol_field"]} </ul> """ categories = [] scalar_fieldname = layer["scalar_field"] maxvalue = getMaxValue(vlayer, scalar_fieldname) feedback.pushInfo("Max value for %s is %f" % (scalar_fieldname, maxvalue)) for formality in ["I", "F"]: for severity, colour in [(3, 'red'), (2, 'yellow'), (1, 'green')]: colour = { ("I", "red"): "#FF0000", ("I", "yellow"): "#FFFF00", ("I", "green"): "#00FF00", ("F", "red"): "#FF9999", ("F", "yellow"): "#FFFF66", ("F", "green"): "#99FF99", }[(formality, colour)] symbol_code = "%s%d" % (formality, severity) if formality == "F": symbol = QgsMarkerSymbol.createSimple({ 'color': colour, 'size': '3', 'outline_color': '#888888' }) else: assert (formality == "I") symbol = QgsMarkerSymbol.createSimple({ 'color': colour, 'size': '3', 'outline_color': '#000000', 'name': 'star' }) objTransf = QgsSizeScaleTransformer( QgsSizeScaleTransformer.Flannery, 0, #minvalue maxvalue, #maxvalue 3, #minsize 10, #maxsize 0, #nullsize 1) #exponent objProp = QgsProperty() objProp.setField(scalar_fieldname) objProp.setTransformer(objTransf) symbol.setDataDefinedSize(objProp) label = { "F": "Formal", "I": "Informal" }[formality] + " " + { 3: "Major", 2: "Secondary", 1: "Tertiary" }[severity] cat = QgsRendererCategory( symbol_code, symbol, label, True) categories.append(cat) renderer = QgsCategorizedSymbolRenderer( "Crossings", categories) renderer.setClassAttribute(layer["symbol_field"]) vlayer.setRenderer(renderer) else: html += f"""<ul> <li><b>field:</b> {layer["scalar_field"]} <li><b>units:</b> {layer["scalar_field_units"]} <li><b>recommended classification:</b> {layer["classes"]} </ul> """ default_style = QgsStyle().defaultStyle() color_ramp = default_style.colorRamp('bt') renderer = QgsGraduatedSymbolRenderer() renderer.setClassAttribute(layer["scalar_field"]) classmethod = classmethods[layer["classes"]]() renderer.setClassificationMethod(classmethod) renderer.updateClasses(vlayer, 5) renderer.updateColorRamp(color_ramp) vlayer.setRenderer(renderer) project.addMapLayer(vlayer) feedback.pushInfo("Loaded " + layerpath) html += "</ul>" project.write() town = views_sorted_by_mode[0]["town"] with open(os.path.join(parameters[self.FOLDER], "metadata.html"), "w") as htmlfile: htmlfile.write( f"<html><head><title>{town} metadata</title></head><body><h1>{town}</h1>{html}</body></html>" ) return {self.OUTPUT: output}