4

I have: ways (tracks) and points (way signs). The tracks are outgoing from the way signs.

This should be the visible result: The ways with the name 'A' are visible (coloured) because the related way sign 'A' is selected. This is the result I'm looking for:

GIS

The question is: How do I show or highlight only the tracks, related to the selected way sign?

What I did: With this rule in styling settings, I can realize the wanted result with one layer (waysigs OR tracks): I select the way sign /tracks and it becomes red because I defined it as a styling rule.

enter image description hereenter image description here

Then I tried this for the tracks (without understanding, what I'm doing) related to the example syntax in the expression builder Help section¹:

    is_selected(get_feature('waysigns', 'fid', "name"), 'waysigns')

but without the expected result...


¹ s_selected(get_feature('streets', 'name', "street_name"), 'streets') → True if the current building's street is selected.


Why do I need this: In my project I have thousands of tracks and some way signs. A lot of the tracks are crossing each other and it is impossible, to see, which track comes from which way sign. To have a better overview, of which tracks are related to which way sign, I simply would like to select the way sign and get its related tracks.

4

2 Answers 2

7

Solution 1: Flashing the related features

Run this script in QGIS Python Editor. I couldn't solve how to disable flashing when another point was selected.

w_lyr = QgsProject.instance().mapLayersByName("way_signs")[0]
t_lyr = QgsProject.instance().mapLayersByName("tracts")[0]
f1, f2 = 'fid', 'name'
flashes, duration = 3, 3000 # 3 times, 3 second

def highlight(ids):
    if len(ids)==0:
        return
        
    w = w_lyr.getFeature(ids[0])
    r = f2 + " = '" + str(w[f1]) + "'" #r: request
    
    t_ids = [t.id() for t in t_lyr.getFeatures(r) 
                        if w[f1]==t[f2] and t.geometry().intersects(w.geometry())]
    
    iface.mapCanvas().flashFeatureIds(t_lyr, t_ids,
                                      flashes=flashes,
                                      duration=duration)

w_lyr.selectionChanged.connect(highlight)

enter image description here

Before you run the script again, be sure you disconnected the function using:

w_lyr.selectionChanged.disconnect(highlight)

Solution 2: Selecting the related features

Using a custom function, you can solve the issue. Add the next script as a new function in the "Function Editor" tab.

from qgis.core import *
from qgis.gui import *

@qgsfunction(args='auto', group='Custom', usesgeometry=True)
def select_related(point_layer_name, field1, field2, feature, parent):
    point_layer = QgsProject.instance().mapLayersByName(point_layer_name)[0]
    point = point_layer.selectedFeatures()[0]
    if point[field1]== feature[field2] and feature.geometry().intersects(point.geometry()):
        return True

Click "Save and Load Functions". Then, in the "Expression" tab, enter this line:

select_related('way_signs', 'fid', 'name')

enter image description here

There must be a solution which uses only built-in functions, but I didn't figure it out.


Solution 3: would be creating a temporary layer containing the related features.


Solution 4: would be somehow styling the related features by means of the "Layer Styling" panel like you try to do.

1
  • Great! But I don't need a selection. I simply want the related features "highlighted" in another color/style. I'll update my question to this...
    – MartinMap
    Commented Jun 7, 2020 at 7:13
5

You can achieve this using a virtual field on the point layer, and a virtual layer.

  1. Add a virtual field to the point layer, of type integer size 1 and populate it using the expression is_selected()

(note: don't use a boolean type because of this bug.)

`enter image description here

So when a point is selected, the value in this field will be set to 1.

  1. Create a virtual layer that will join the point layer to the line layer base on their geometry intersection. Then filter out the points to keep only the selected one.

At last, style this virtual layer as you wish.

When you select a point, you will have to pan the map a bit to refresh the virtual layer.

Go to the menu Layer > Add Layer > Add/Edit Virtual Layer... and enter the following query. Replace the layer name for yours

select l.*
from lines l 
  join points p 
    on st_intersects(p.geometry,l.geometry)
where  p.selected = 1

enter image description here

4
  • Conceptually this seemed like a nice idea to me, but in practice I find that it is very slow (working on a table with about 10 million records). Pity
    – Koen Ver
    Commented Apr 7, 2021 at 6:59
  • @KoenVer for larger datasets, I would put the data in a database - with proper spatial indexes - and create a view that does the join between the point/line layers. Then in QGIS the virtual layer would be used only to filter the view using the selected ID
    – JGH
    Commented Apr 7, 2021 at 12:24
  • Just to make myself clear: sorry for editing/improving your answer. Please do not consider it rude
    – Taras
    Commented Feb 3, 2023 at 21:16
  • 1
    Sorry, but I will disagree with you. (1) Regarding the indentation the reader needs to see where chapter 1 ends and chapter 2 starts, in the case of a numbered list it should follow the same logic. Everything that belongs to point 1 should be inside of it etc. (2) IMHO using links helps to promote the QGIS Documentation, as well as referring to vital sections i.e. virtual field and virtual layer However, I will be more critical about myself to avoid these contrary effects. For now, this is just my style ^_^
    – Taras
    Commented Feb 3, 2023 at 21:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.