Geographic Information Systems Asked on April 12, 2021
I have two oracle layer (point(p1) and polygon(pl1)). I want to build a rule-based symbology which is based on current selection on two cases:
Case 1– When I select a point from table p1, I want that the polygons from table pl1 to be coloured differently based one the relation that they have with table p1 which is p1.id_b=pl1.id_b (one to many).
Case 2– When I select a polygon from table pl1 other polygons from the same layer that are related to current selection to be coloured differently. Relation between polygons is on the field pl1.id_group, so polygons are grouped by the same pl1.id_group (one to many).
Software used is QGIS.
For illustration I select point one and the related polygons are coloured differently from the others.
Solution for Case 1:
Open Based-on selected points
rule, open expression window for Filter
.
Go to Function Editor
tab and add the following script as function.
from qgis.core import *
from qgis.gui import *
@qgsfunction(args='auto', group='Custom')
def related_rule_based(layer_name, field1, field2, feature, parent):
layer = QgsProject.instance().mapLayersByName(layer_name)[0]
selected_features = layer.selectedFeatures()
if selected_features:
feat = selected_features[0]
if feat[field1] == feature[field2]:
return True
else:
return False
Click Save and Load Functions
. Then, in Expression
tab, enter the next line: (p1
: point layer name, first id_b
: field in point layer, second id_b
: field in polygon layer)
related_rule_based('p1', 'id_b', 'id_b')
This solution is for just one selected point. If you select more points, one polygon group will remain selected.
Solution for Case 2:
Enter the following expression as rule.
related_rule_based(@layer_name, 'id_b', 'id_b')
Note: If two cases occur, one of both will be effective.
Answered by Kadir Şahbaz on April 12, 2021
This script creates a rule based style which refreshes upon the selection of a feature with the logic you described.You only need to enter the layer names below and run it in QGIS.
class Restyler:
def __init__(self, polygonLayerName, pointLayerName):
self.polygonLayer = QgsProject.instance().mapLayersByName(polygonLayerName)[0]
self.pointLayer = QgsProject.instance().mapLayersByName(pointLayerName)[0]
self.polygonLayer.selectionChanged.connect(self.polygonSelected)
self.pointLayer.selectionChanged.connect(self.pointSelected)
self.addRules()
def addRules(self):
layer = self.polygonLayer
symbol = QgsSymbol.defaultSymbol(layer.geometryType())
renderer = QgsRuleBasedRenderer(symbol)
root_rule = renderer.rootRule()
rule = root_rule.children()[0].clone()
rule.setFilterExpression('"id_b" = @selected_id_b')
rule.symbol().setColor(QColor('pink'))
rule2 = rule.clone()
rule2.setFilterExpression('"id_group" = @selected_id_group')
root_rule.appendChild(rule)
root_rule.appendChild(rule2)
layer.setRenderer(renderer)
iface.layerTreeView().refreshLayerSymbology(layer.id())
def pointSelected(self):
if self.pointLayer.selectedFeatureCount() == 1:
selectedIdb = self.pointLayer.selectedFeatures()[0]['id_b']
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(),'selected_id_b', selectedIdb)
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(),'selected_id_group', '')
print("Point selected. id_b: {}".format(selectedIdb))
self.polygonLayer.triggerRepaint()
else:
print("Error. One feature should be selected")
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(),'selected_id_group', '')
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(),'selected_id_b', '')
self.polygonLayer.triggerRepaint()
def polygonSelected(self):
if self.polygonLayer.selectedFeatureCount() == 1:
selectedIdGroup = self.polygonLayer.selectedFeatures()[0]['id_group']
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(),'selected_id_group', selectedIdGroup)
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(),'selected_id_b', '')
print("Polygon selected. id_group: {}".format(selectedIdGroup))
else:
print("Error. One feature should be selected")
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(),'selected_id_group', '')
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(),'selected_id_b', '')
self.polygonLayer.triggerRepaint()
#you only need to input your layer names
polygonLayerName = 'wojewodztwa'
pointLayerName = 'testcsv_geocoded'
restyler = Restyler(polygonLayerName, pointLayerName)
Answered by Leon Powałka on April 12, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP