def testRingNoDupe(self): s = QgsLineSymbol() s.deleteSymbolLayer(0) marker_line = QgsMarkerLineSymbolLayer(True) marker_line.setPlacement(QgsTemplatedLineSymbolLayerBase.Interval) marker_line.setInterval(10) marker_line.setIntervalUnit(QgsUnitTypes.RenderMapUnits) marker = QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayer.Circle, 4) marker.setColor(QColor(255, 0, 0, 100)) marker.setStrokeStyle(Qt.NoPen) marker_symbol = QgsMarkerSymbol() marker_symbol.changeSymbolLayer(0, marker) marker_line.setSubSymbol(marker_symbol) line_symbol = QgsLineSymbol() line_symbol.changeSymbolLayer(0, marker_line) s.appendSymbolLayer(marker_line.clone()) g = QgsGeometry.fromWkt('LineString(0 0, 0 10, 10 10, 10 0, 0 0)') rendered_image = self.renderGeometry(s, g) assert self.imageCheck('markerline_ring_no_dupes', 'markerline_ring_no_dupes', rendered_image)
def testMarkerAverageAngleCenter(self): s = QgsLineSymbol() s.deleteSymbolLayer(0) marker_line = QgsMarkerLineSymbolLayer(True) marker_line.setPlacement(QgsTemplatedLineSymbolLayerBase.CentralPoint) marker = QgsSimpleMarkerSymbolLayer( QgsSimpleMarkerSymbolLayer.Triangle, 4) marker.setColor(QColor(255, 0, 0)) marker.setStrokeStyle(Qt.NoPen) marker_symbol = QgsMarkerSymbol() marker_symbol.changeSymbolLayer(0, marker) marker_line.setSubSymbol(marker_symbol) marker_line.setAverageAngleLength(60) line_symbol = QgsLineSymbol() line_symbol.changeSymbolLayer(0, marker_line) s.appendSymbolLayer(marker_line.clone()) g = QgsGeometry.fromWkt('LineString(0 0, 10 10, 10 0)') rendered_image = self.renderGeometry(s, g) assert self.imageCheck('markerline_center_average_angle', 'markerline_center_average_angle', rendered_image)
def testSizeMapUnitScale(self): # test sizeMapUnitScale and setSizeMapUnitScale # create a marker symbol with a single layer markerSymbol = QgsMarkerSymbol() markerSymbol.deleteSymbolLayer(0) markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayerBase.Star, color=QColor(255, 0, 0), strokeColor=QColor(0, 255, 0), size=10)) markerSymbol.symbolLayer(0).setSizeMapUnitScale(QgsMapUnitScale(10000, 20000)) self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(10000, 20000)) markerSymbol.setSizeMapUnitScale(QgsMapUnitScale(1000, 2000)) self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(1000, 2000)) self.assertEqual(markerSymbol.symbolLayer(0).sizeMapUnitScale(), QgsMapUnitScale(1000, 2000)) # add additional layers markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayerBase.Star, color=QColor(255, 0, 0), strokeColor=QColor(0, 255, 0), size=10)) markerSymbol.appendSymbolLayer(QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayerBase.Star, color=QColor(255, 0, 0), strokeColor=QColor(0, 255, 0), size=30)) # should take first layer's map unit scale self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(1000, 2000)) markerSymbol.setSizeMapUnitScale(QgsMapUnitScale(3000, 4000)) self.assertEqual(markerSymbol.sizeMapUnitScale(), QgsMapUnitScale(3000, 4000)) # all layers should have size unit set self.assertEqual(markerSymbol.symbolLayer(0).sizeMapUnitScale(), QgsMapUnitScale(3000, 4000)) self.assertEqual(markerSymbol.symbolLayer(1).sizeMapUnitScale(), QgsMapUnitScale(3000, 4000)) self.assertEqual(markerSymbol.symbolLayer(2).sizeMapUnitScale(), QgsMapUnitScale(3000, 4000))
def testConvertFromGraduatedRenderer(self): # Test converting graduated renderer to rule based # First, try with a field based category (id) ranges = [] ranges.append(QgsRendererRange(0, 1, QgsMarkerSymbol(), "0-1")) ranges.append(QgsRendererRange(1, 2, QgsMarkerSymbol(), "1-2")) g = QgsGraduatedSymbolRenderer("id", ranges) r = QgsRuleBasedRenderer.convertFromRenderer(g) self.assertEqual(r.rootRule().children()[0].filterExpression(), '"id" >= 0.000000 AND "id" <= 1.000000') self.assertEqual(r.rootRule().children()[1].filterExpression(), '"id" > 1.000000 AND "id" <= 2.000000') # Next try with an expression based range ranges = [] ranges.append(QgsRendererRange(0, 1, QgsMarkerSymbol(), "0-1")) ranges.append(QgsRendererRange(1, 2, QgsMarkerSymbol(), "1-2")) g = QgsGraduatedSymbolRenderer("id / 2", ranges) r = QgsRuleBasedRenderer.convertFromRenderer(g) self.assertEqual(r.rootRule().children()[0].filterExpression(), '(id / 2) >= 0.000000 AND (id / 2) <= 1.000000') self.assertEqual(r.rootRule().children()[1].filterExpression(), '(id / 2) > 1.000000 AND (id / 2) <= 2.000000') # Last try with an expression which is just a quoted field name ranges = [] ranges.append(QgsRendererRange(0, 1, QgsMarkerSymbol(), "0-1")) ranges.append(QgsRendererRange(1, 2, QgsMarkerSymbol(), "1-2")) g = QgsGraduatedSymbolRenderer('"id"', ranges) r = QgsRuleBasedRenderer.convertFromRenderer(g) self.assertEqual(r.rootRule().children()[0].filterExpression(), '"id" >= 0.000000 AND "id" <= 1.000000') self.assertEqual(r.rootRule().children()[1].filterExpression(), '"id" > 1.000000 AND "id" <= 2.000000')
def testRefineWithRanges(self): # Test refining rule with ranges (refs #10815) # First, try with a field based category (id) ranges = [] ranges.append(QgsRendererRange(0, 1, QgsMarkerSymbol(), "0-1")) ranges.append(QgsRendererRange(1, 2, QgsMarkerSymbol(), "1-2")) g = QgsGraduatedSymbolRenderer("id", ranges) QgsRuleBasedRenderer.refineRuleRanges(self.r2, g) assert self.r2.children()[0].filterExpression( ) == '"id" >= 0.0000 AND "id" <= 1.0000' assert self.r2.children()[1].filterExpression( ) == '"id" > 1.0000 AND "id" <= 2.0000' # Next try with an expression based range ranges = [] ranges.append(QgsRendererRange(0, 1, QgsMarkerSymbol(), "0-1")) ranges.append(QgsRendererRange(1, 2, QgsMarkerSymbol(), "1-2")) g = QgsGraduatedSymbolRenderer("id / 2", ranges) QgsRuleBasedRenderer.refineRuleRanges(self.r1, g) assert self.r1.children()[0].filterExpression( ) == '(id / 2) >= 0.0000 AND (id / 2) <= 1.0000' assert self.r1.children()[1].filterExpression( ) == '(id / 2) > 1.0000 AND (id / 2) <= 2.0000' # Last try with an expression which is just a quoted field name ranges = [] ranges.append(QgsRendererRange(0, 1, QgsMarkerSymbol(), "0-1")) ranges.append(QgsRendererRange(1, 2, QgsMarkerSymbol(), "1-2")) g = QgsGraduatedSymbolRenderer('"id"', ranges) QgsRuleBasedRenderer.refineRuleRanges(self.r3, g) assert self.r3.children()[0].filterExpression( ) == '"id" >= 0.0000 AND "id" <= 1.0000' assert self.r3.children()[1].filterExpression( ) == '"id" > 1.0000 AND "id" <= 2.0000'
def extract_layers(self, tree): """Return a list of RFU layers.""" # Create vector layers.. l_vertex = QgsVectorLayer(r"Point?crs=epsg:4326&index=yes", "Sommet RFU", r"memory") l_edge = QgsVectorLayer(r"LineString?crs=epsg:4326&index=yes", "Limite RFU", r"memory") p_vertex = l_vertex.dataProvider() p_edge = l_edge.dataProvider() # Define default style renderer.. renderer_vertex = QgsRuleBasedRenderer(QgsMarkerSymbol()) vertex_root_rule = renderer_vertex.rootRule() # Modified in v2.1 (som_nature replaced by som_typologie_nature) >> vertex_rules = ( (("Borne, borne à puce, pierre, piquet, clou ou broche"), ("$id >= 0 AND \"som_typologie_nature\" IN ('Borne'," "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche')"), r"#EC0000", 2.2), (("Axe cours d'eau, axe fossé, haut de talus, pied de talus"), ("$id >= 0 AND \"som_typologie_nature\" IN ('Axe cours d\'\'eau'," "'Axe fossé', 'Haut de talus', 'Pied de talus')"), r"#EE8012", 2.2), (("Angle de bâtiment, axe de mur, angle de mur, " "angle de clôture, pylône et toute autre valeur"), ("$id >= 0 AND \"som_typologie_nature\" NOT IN ('Borne'," "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche'," "'Axe cours d\'\'eau', 'Axe fossé', 'Haut de talus'," "'Pied de talus')"), r"#9784EC", 2.2), ("Temporaire", r"$id < 0", "cyan", 2.4), ("Point nouveau à traiter car proche d'un existant", r"point_rfu_proche is not null", "#bcff03", 3)) # >> for label, expression, color, size in vertex_rules: rule = vertex_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setSize(size) vertex_root_rule.appendChild(rule) vertex_root_rule.removeChildAt(0) l_vertex.setRenderer(renderer_vertex) renderer_edge = QgsRuleBasedRenderer(QgsLineSymbol()) edge_root_rule = renderer_edge.rootRule() # Modified in v2.1 (lim_typologie_nature added) << edge_rules = (("Limite privée", "$id >= 0 AND \"lim_typologie_nature\" = '" + lim_typo_nat_vals[0] + "'", "#0A0AFF", 0.5), ("Limite naturelle", "$id >= 0 AND \"lim_typologie_nature\" = '" + lim_typo_nat_vals[1] + "'", "#aa876d", 0.5), ("Temporaire", "$id < 0", "cyan", 1)) # >> for label, expression, color, width in edge_rules: rule = edge_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setWidth(width) edge_root_rule.appendChild(rule) edge_root_rule.removeChildAt(0) l_edge.setRenderer(renderer_edge) # Add fields.. p_vertex.addAttributes(vtx_atts) p_edge.addAttributes(edge_atts) # Add features from xml tree.. # ..to vertex layer.. fts_vertex = [] for e in tree.findall(r"sommet"): ft_vertex = QgsFeature() ft_vertex.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_noeud = int(e.attrib[r"id_noeud"]) _version = int(e.attrib[r"version"]) som_ge_createur = str(e.find(r"./som_ge_createur").text) som_nature = str(e.find(r"./som_nature").text) som_prec_rattcht = int( e.find(r"./som_precision_rattachement").text) som_coord_est = float(e.find(r"./som_coord_est").text) som_coord_nord = float(e.find(r"./som_coord_nord").text) som_repres_plane = str(e.find(r"./som_representation_plane").text) som_tolerance = float(e.find(r"./som_tolerance").text) # Field used to store the attestation_qualite value # when modifying a vertex ("false" or "true") attestation_qualite = "false" som_delim_pub = str(e.find(r"./som_delimitation_publique").text) som_typo_nature = str(e.find(r"./som_typologie_nature").text) ft_vertex.setAttributes([ _id_noeud, _version, som_ge_createur, som_delim_pub, som_typo_nature, som_nature, som_prec_rattcht, som_coord_est, som_coord_nord, som_repres_plane, som_tolerance, attestation_qualite, NULL ]) fts_vertex.append(ft_vertex) # ..to edge layer.. fts_edge = [] for e in tree.findall(r"limite"): ft_edge = QgsFeature() ft_edge.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_arc = int(e.attrib[r"id_arc"]) _version = int(e.attrib[r"version"]) lim_ge_createur = str(e.find(r"./lim_ge_createur").text) lim_typo_nature = str(e.find(r"./lim_typologie_nature").text) lim_delim_pub = str(e.find(r"./lim_delimitation_publique").text) ft_edge.setAttributes([ _id_arc, _version, lim_ge_createur, lim_delim_pub, lim_typo_nature ]) fts_edge.append(ft_edge) # Add features to layers.. p_vertex.addFeatures(fts_vertex) p_edge.addFeatures(fts_edge) # Update fields.. l_vertex.updateFields() l_edge.updateFields() # Update layer's extent.. l_vertex.updateExtents() l_edge.updateExtents() # Check if valid.. if not l_vertex.isValid() or not l_edge.isValid(): raise Exception( "Une erreur est survenue lors du chargement de la couche.") # Then return layers.. return [l_vertex, l_edge]
def processAlgorithm(self, parameters, context, feedback): t_file = self.parameterAsVectorLayer( parameters, self.FILE_TABLE, context ) t_troncon = self.parameterAsVectorLayer( parameters, self.SEGMENTS_TABLE, context ) t_obs = self.parameterAsVectorLayer( parameters, self.OBSERVATIONS_TABLE, context ) t_regard = self.parameterAsVectorLayer( parameters, self.MANHOLES_TABLE, context ) g_regard = self.parameterAsVectorLayer( parameters, self.GEOM_MANHOLES, context ) g_troncon = self.parameterAsVectorLayer( parameters, self.GEOM_SEGMENT, context ) g_obs = self.parameterAsVectorLayer( parameters, self.GEOM_OBSERVATION, context ) v_regard = self.parameterAsVectorLayer( parameters, self.VIEW_MANHOLES_GEOLOCALIZED, context ) # define variables variables = context.project().customVariables() variables['itv_rerau_t_file'] = t_file.id() variables['itv_rerau_t_troncon'] = t_troncon.id() variables['itv_rerau_t_obs'] = t_obs.id() variables['itv_rerau_t_regard'] = t_regard.id() variables['itv_rerau_g_regard'] = g_regard.id() variables['itv_rerau_g_troncon'] = g_troncon.id() variables['itv_rerau_g_obs'] = g_obs.id() context.project().setCustomVariables(variables) # define relations relations = [ { 'id': 'fk_obs_id_file', 'name': tr('Link File - Observation'), 'referencingLayer': t_obs.id(), 'referencingField': 'id_file', 'referencedLayer': t_file.id(), 'referencedField': 'id' }, { 'id': 'fk_regard_id_file', 'name': tr('Link File - Manhole'), 'referencingLayer': t_regard.id(), 'referencingField': 'id_file', 'referencedLayer': t_file.id(), 'referencedField': 'id' }, { 'id': 'fk_troncon_id_file', 'name': tr('Link File - Pipe segment'), 'referencingLayer': t_troncon.id(), 'referencingField': 'id_file', 'referencedLayer': t_file.id(), 'referencedField': 'id' }, { 'id': 'fk_obs_id_troncon', 'name': tr('Link Pipe segment - Observation'), 'referencingLayer': t_obs.id(), 'referencingField': 'id_troncon', 'referencedLayer': t_troncon.id(), 'referencedField': 'id' }, { 'id': 'fk_regard_id_geom_regard', 'name': tr('Link Manhole inspection - Reference'), 'referencingLayer': t_regard.id(), 'referencingField': 'id_geom_regard', 'referencedLayer': g_regard.id(), 'referencedField': 'id' }, { 'id': 'fk_troncon_id_geom_trononc', 'name': tr('Link Pipe segment inspection - Reference'), 'referencingLayer': t_troncon.id(), 'referencingField': 'id_geom_troncon', 'referencedLayer': g_troncon.id(), 'referencedField': 'id' } ] relation_manager = context.project().relationManager() for rel_def in relations: feedback.pushInfo( 'Link: {}'.format(rel_def['name']) ) rel = QgsRelation() rel.setId(rel_def['id']) rel.setName(rel_def['name']) rel.setReferencingLayer(rel_def['referencingLayer']) rel.setReferencedLayer(rel_def['referencedLayer']) rel.addFieldPair( rel_def['referencingField'], rel_def['referencedField'] ) rel.setStrength(QgsRelation.Association) relation_manager.addRelation(rel) feedback.pushInfo( 'Count relations {}'.format( len(relation_manager.relations()) ) ) joins = [ { 'layer': t_obs, 'targetField': 'id_troncon', 'joinLayer': t_troncon, 'joinField': 'id', 'fieldNamesSubset': ['ack'] }, { 'layer': g_obs, 'targetField': 'id', 'joinLayer': t_obs, 'joinField': 'id', 'fieldNamesSubset': [] } ] for j_def in joins: layer = j_def['layer'] join = QgsVectorLayerJoinInfo() join.setJoinFieldName(j_def['joinField']) join.setJoinLayerId(j_def['joinLayer'].id()) join.setTargetFieldName(j_def['targetField']) if j_def['fieldNamesSubset']: join.setJoinFieldNamesSubset(j_def['fieldNamesSubset']) join.setUsingMemoryCache(False) join.setPrefix('') join.setEditable(False) join.setCascadedDelete(False) join.setJoinLayer(j_def['joinLayer']) layer.addJoin(join) layer.updateFields() # load styles styles = [ { 'layer': t_file, 'namedStyles': [ { 'file': 'itv_file_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_file_actions.qml', 'type': QgsMapLayer.Actions } ] }, { 'layer': t_troncon, 'namedStyles': [ { 'file': 'itv_troncon_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_troncon_table.qml', 'type': QgsMapLayer.AttributeTable } ] }, { 'layer': t_obs, 'namedStyles': [ { 'file': 'itv_obs_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_obs_table.qml', 'type': QgsMapLayer.AttributeTable } ] }, { 'layer': t_regard, 'namedStyles': [ { 'file': 'itv_regard_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_regard_forms.qml', 'type': QgsMapLayer.Forms }, { 'file': 'itv_regard_table.qml', 'type': QgsMapLayer.AttributeTable } ] }, { 'layer': g_regard, 'namedStyles': [ { 'file': 'itv_geom_regard_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_geom_regard_symbology.qml', 'type': QgsMapLayer.Symbology } ] }, { 'layer': g_troncon, 'namedStyles': [ { 'file': 'itv_geom_troncon_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_geom_troncon_symbology.qml', 'type': QgsMapLayer.Symbology }, { 'file': 'itv_geom_troncon_actions.qml', 'type': QgsMapLayer.Actions } ] }, { 'layer': g_obs, 'namedStyles': [ { 'file': 'itv_geom_obs_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_geom_obs_symbology.qml', 'type': QgsMapLayer.Symbology } ] }, { 'layer': v_regard, 'namedStyles': [ { 'file': 'itv_view_regard_fields.qml', 'type': QgsMapLayer.Fields }, { 'file': 'itv_view_regard_symbology.qml', 'type': QgsMapLayer.Symbology }, { 'file': 'itv_view_regard_labeling.qml', 'type': QgsMapLayer.Labeling } ] } ] for style in styles: layer = style['layer'] for n_style in style['namedStyles']: layer.loadNamedStyle( resources_path('styles', n_style['file']), categories=n_style['type'] ) # layer.saveStyleToDatabase('style', 'default style', True, '') layer.triggerRepaint() # Creation de la symbologie g_obs g_obs_rules = ( 'BAA', 'BAB', 'BAC', 'BAD', 'BAE', 'BAF', 'BAG', 'BAH', 'BAI', 'BAJ', 'BAK', 'BAL', 'BAM', 'BAN', 'BAO', 'BAP', 'BBA', 'BBB', 'BBC', 'BBD', 'BBE', 'BBF', 'BBG', 'BBH', 'BCA', 'BCB', 'BCC', 'BDA', 'BDB', 'BDC', 'BDD', 'BDE', 'BDF', 'BDG' ) g_obs_rule_descs = { 'BAA': 'Déformation', 'BAB': 'Fissure', 'BAC': 'Rupture/Effondrement', 'BAD': 'Elt maçonnerie', 'BAE': 'Mortier manquant', 'BAF': 'Dégradation de surface', 'BAG': 'Branchement pénétrant', 'BAH': 'Raccordement défectueux', 'BAI': 'Joint étanchéité apparent', 'BAJ': 'Déplacement d\'assemblage', 'BAK': 'Défaut de révêtement', 'BAL': 'Réparation défectueuse', 'BAM': 'Défaut soudure', 'BAN': 'Conduite poreuse', 'BAO': 'Sol visible', 'BAP': 'Trou visible', 'BBA': 'Racines', 'BBB': 'Dépots Adhérents', 'BBC': 'Dépôts', 'BBD': 'Entrée de terre', 'BBE': 'Autres obstacles', 'BBF': 'Infiltration', 'BBG': 'Exfiltration', 'BBH': 'Vermine', 'BCA': 'Raccordement', 'BCB': 'Réparation', 'BCC': 'Courbure de collecteur', 'BDA': 'Photographie générale', 'BDB': 'Remarque générale', 'BDC': 'Inspection abandonnée', 'BDD': 'Niveau d\'eau', 'BDE': 'Ecoulement dans une canlisation entrante', 'BDF': 'Atmosphère canalisation', 'BDG': 'Perte de visibilité' } g_obs_rootrule = QgsRuleBasedRenderer.Rule(None) rendering_pass_idx = len(g_obs_rules) for rule in g_obs_rules: # get svg path svg_path = resources_path('styles', 'img_obs', rule + '.svg') # create svg symbol layer svg_symbol_layer = QgsSvgMarkerSymbolLayer(svg_path) svg_symbol_layer.setRenderingPass(rendering_pass_idx) # create white square symbol layer for the backend simple_symbol_layer = QgsSimpleMarkerSymbolLayer( shape=QgsSimpleMarkerSymbolLayerBase.Circle, size=svg_symbol_layer.size(), color=QColor('white'), strokeColor=QColor('white') ) simple_symbol_layer.setRenderingPass(rendering_pass_idx) # create marker svg_marker = QgsMarkerSymbol() # set the backend symbol layer svg_marker.changeSymbolLayer(0, simple_symbol_layer) # add svg symbol layer svg_marker.appendSymbolLayer(svg_symbol_layer) # create rule svg_rule = QgsRuleBasedRenderer.Rule( svg_marker, 0, 10000, QgsExpression.createFieldEqualityExpression('a', rule), rule ) if rule in g_obs_rule_descs: svg_rule.setLabel(g_obs_rule_descs[rule]) svg_rule.setDescription('{}: {}'.format( rule, g_obs_rule_descs[rule] )) # add rule g_obs_rootrule.appendChild(svg_rule) rendering_pass_idx -= 1 g_obs_rootrule.appendChild( QgsRuleBasedRenderer.Rule( QgsMarkerSymbol.createSimple( { 'name': 'circle', 'color': '#0000b2', 'outline_color': '#0000b2', 'size': '1' } ), 0, 10000, 'ELSE', 'Autres' ) ) g_obs.setRenderer(QgsRuleBasedRenderer(g_obs_rootrule)) feedback.pushInfo('Project has been setup') return {}
def 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 testPointsUsedAttributes(self): points_shp = os.path.join(TEST_DATA_DIR, 'points.shp') points_layer = QgsVectorLayer(points_shp, 'Points', 'ogr') QgsProject.instance().addMapLayer(points_layer) # Create rulebased style sym1 = QgsMarkerSymbol() l1 = QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayer.Triangle, 5) l1.setColor(QColor(255, 0, 0)) l1.setStrokeStyle(Qt.NoPen) l1.setDataDefinedProperty(QgsSymbolLayer.PropertyAngle, QgsProperty.fromField("Heading")) sym1.changeSymbolLayer(0, l1) sym2 = QgsMarkerSymbol() l2 = QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayer.Triangle, 5) l2.setColor(QColor(0, 255, 0)) l2.setStrokeStyle(Qt.NoPen) l2.setDataDefinedProperty(QgsSymbolLayer.PropertyAngle, QgsProperty.fromField("Heading")) sym2.changeSymbolLayer(0, l2) sym3 = QgsMarkerSymbol() l3 = QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayer.Triangle, 5) l3.setColor(QColor(0, 0, 255)) l3.setStrokeStyle(Qt.NoPen) l3.setDataDefinedProperty(QgsSymbolLayer.PropertyAngle, QgsProperty.fromField("Heading")) sym3.changeSymbolLayer(0, l3) r1 = QgsRuleBasedRenderer.Rule(sym1, 0, 0, '"Class" = \'B52\'') r2 = QgsRuleBasedRenderer.Rule(sym2, 0, 0, '"Class" = \'Biplane\'') r3 = QgsRuleBasedRenderer.Rule(sym3, 0, 0, '"Class" = \'Jet\'') rootrule = QgsRuleBasedRenderer.Rule(None) rootrule.appendChild(r1) rootrule.appendChild(r2) rootrule.appendChild(r3) renderer = QgsRuleBasedRenderer(rootrule) points_layer.setRenderer(renderer) ms = QgsMapSettings() ms.setOutputSize(QSize(400, 400)) ms.setOutputDpi(96) ms.setExtent(QgsRectangle(-133, 22, -70, 52)) ms.setLayers([points_layer]) ctx = QgsRenderContext.fromMapSettings(ms) ctx.expressionContext().appendScope( points_layer.createExpressionContextScope()) # for symbol layer self.assertCountEqual(l1.usedAttributes(ctx), {'Heading'}) # for symbol self.assertCountEqual(sym1.usedAttributes(ctx), {'Heading'}) # for symbol renderer self.assertCountEqual(renderer.usedAttributes(ctx), {'Class', 'Heading'}) QgsProject.instance().removeMapLayer(points_layer)
def 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 symbolForCode(code, size): # noinspection PyBroadException,PyUnusedLocal try: symbol = QgsMarkerSymbol() for i in range(symbol.symbolLayerCount()): symbol.takeSymbolLayer(0) echelonCode = code[3] + code[8:10] echelonLayer = getSymbolLayer('Echelon', echelonCode, size) if echelonLayer is not None: symbol.insertSymbolLayer(0, echelonLayer) # log.debug('echelon: %s %s' % (echelonCode, # str(echelonLayer is not None))) amplifierCode = code[3] + code[8:10] amplifierLayer = getSymbolLayer('Amplifier', amplifierCode, size) if amplifierLayer is not None: symbol.insertSymbolLayer(0, amplifierLayer) # log.debug('amplifier: %s %s' % ( # amplifierCode, str(amplifierLayer is not None))) hqtffdCode = code[3:6] + code[7] hqtffdLayer = getSymbolLayer('HQTFFD', hqtffdCode, size) if hqtffdLayer is not None: symbol.insertSymbolLayer(0, hqtffdLayer) # log.debug('hqtffd: %s %s' % # (hqtffdCode, str(hqtffdLayer is not None))) ocaCode = code[2:7] + '2' ocaLayer = getSymbolLayer('OCA', ocaCode, size) if ocaLayer is not None: symbol.insertSymbolLayer(0, ocaLayer) # log.debug('oca: %s %s' % (ocaCode, str(ocaLayer is not None))) mainCode = code[4:6] + code[10:16] mainLayer = getSymbolLayer('Appendices', mainCode, size) if mainLayer is not None: symbol.insertSymbolLayer(0, mainLayer) # log.debug('main: %s %s' % (mainCode, str(mainLayer is not None))) modifier1Code = code[4:6] + code[16:18] + '1' modifier1Layer = getSymbolLayer('Appendices', modifier1Code, size) if modifier1Layer is not None: symbol.insertSymbolLayer(0, modifier1Layer) modifier2Code = code[4:6] + code[18:20] + '2' modifier2Layer = getSymbolLayer('Appendices', modifier2Code, size) if modifier2Layer is not None: symbol.insertSymbolLayer(0, modifier2Layer) frameCode = '%s_%s_%s' % (code[2], code[3:6], code[0]) frameLayer = getSymbolLayer('Frames', frameCode, size) if frameLayer is not None: symbol.insertSymbolLayer(0, frameLayer) # log.debug('frame: %s %s' % (frameCode, str(frameLayer is not None))) if symbol.symbolLayerCount() == 0: symbol = None except Exception as e: symbol = None return symbol
def testSimple(self): s = QgsFillSymbol() s.deleteSymbolLayer(0) random_fill = QgsRandomMarkerFillSymbolLayer(10, seed=481523) marker = QgsSimpleMarkerSymbolLayer( QgsSimpleMarkerSymbolLayer.Triangle, 4) marker.setColor(QColor(255, 0, 0)) marker.setStrokeStyle(Qt.NoPen) marker_symbol = QgsMarkerSymbol() marker_symbol.changeSymbolLayer(0, marker) random_fill.setSubSymbol(marker_symbol) s.appendSymbolLayer(random_fill.clone()) self.assertEqual(s.symbolLayer(0).pointCount(), 10) self.assertEqual(s.symbolLayer(0).seed(), 481523) s.symbolLayer(0).setPointCount(5) s.symbolLayer(0).setSeed(42) self.assertEqual(s.symbolLayer(0).pointCount(), 5) self.assertEqual(s.symbolLayer(0).seed(), 42) s2 = s.clone() self.assertEqual(s2.symbolLayer(0).pointCount(), 5) self.assertEqual(s2.symbolLayer(0).seed(), 42) doc = QDomDocument() context = QgsReadWriteContext() element = QgsSymbolLayerUtils.saveSymbol('test', s, doc, context) s2 = QgsSymbolLayerUtils.loadSymbol(element, context) self.assertEqual(s2.symbolLayer(0).pointCount(), 5) self.assertEqual(s2.symbolLayer(0).seed(), 42) # rendering test s3 = QgsFillSymbol() s3.deleteSymbolLayer(0) s3.appendSymbolLayer(random_fill.clone()) g = QgsGeometry.fromWkt( 'Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))' ) rendered_image = self.renderGeometry(s3, g) self.assertTrue( self.imageCheck('randommarkerfill', 'randommarkerfill', rendered_image)) s3.symbolLayer(0).setPointCount(3) g = QgsGeometry.fromWkt( 'Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))' ) rendered_image = self.renderGeometry(s3, g) self.assertTrue( self.imageCheck('randommarkerfill_3', 'randommarkerfill_3', rendered_image)) s3.symbolLayer(0).setSeed(12783) g = QgsGeometry.fromWkt( 'Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))' ) rendered_image = self.renderGeometry(s3, g) self.assertTrue( self.imageCheck('randommarkerfill_seed', 'randommarkerfill_seed', rendered_image)) # random seed s3.symbolLayer(0).setSeed(0) g = QgsGeometry.fromWkt( 'Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))' ) rendered_image = self.renderGeometry(s3, g) self.assertFalse( self.imageCheck('randommarkerfill_seed', 'randommarkerfill_seed', rendered_image, expect_fail=True)) # density-based count s3.symbolLayer(0).setSeed(1) s3.symbolLayer(0).setCountMethod( QgsRandomMarkerFillSymbolLayer.DensityBasedCount) s3.symbolLayer(0).setPointCount(5) s3.symbolLayer(0).setDensityArea(250) # 250 square millimeter g = QgsGeometry.fromWkt( 'Polygon((0 0, 10 0, 10 10, 0 10, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1),(8 8, 9 8, 9 9, 8 9, 8 8))' ) rendered_image = self.renderGeometry(s3, g) self.assertTrue( self.imageCheck('randommarkerfill_densitybasedcount', 'randommarkerfill_densitybasedcount', rendered_image))
def test_localizedCategories(self): # Default locale for tests is EN original_locale = QLocale() locale = QLocale(QLocale.English) locale.setNumberOptions(QLocale.DefaultNumberOptions) QLocale().setDefault(locale) layer = QgsVectorLayer("Point?field=flddbl:double&field=fldint:integer", "addfeat", "memory") result = QgsCategorizedSymbolRenderer.createCategories([1234.5, 2345.6, 3456.7], QgsMarkerSymbol(), layer, 'flddouble') self.assertEqual(result[0].label(), '1,234.5') self.assertEqual(result[1].label(), '2,345.6') self.assertEqual(result[2].label(), '3,456.7') # Test a non-dot locale QLocale().setDefault(QLocale(QLocale.Italian)) result = QgsCategorizedSymbolRenderer.createCategories([[1234.5, 6789.1], 2345.6, 3456.7], QgsMarkerSymbol(), layer, 'flddouble') self.assertEqual(result[0].label(), '1.234,5;6.789,1') self.assertEqual(result[1].label(), '2.345,6') self.assertEqual(result[2].label(), '3.456,7') # Test round trip temp_dir = QTemporaryDir() temp_file = os.path.join(temp_dir.path(), 'project.qgs') project = QgsProject() layer.setRenderer(QgsCategorizedSymbolRenderer('Class', result)) project.addMapLayers([layer]) project.write(temp_file) QLocale().setDefault(original_locale) project = QgsProject() project.read(temp_file) results = project.mapLayersByName('addfeat')[0].renderer().categories() self.assertEqual(result[0].label(), '1.234,5;6.789,1') self.assertEqual(result[1].label(), '2.345,6') self.assertEqual(result[2].label(), '3.456,7') self.assertEqual(result[0].value(), [1234.5, 6789.1]) self.assertEqual(result[1].value(), 2345.6) self.assertEqual(result[2].value(), 3456.7)