1

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 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 high light only the tracks, related to the selected way sign?

What I did: With this rule in styling settings I can realized the wanted result with one layer (waysigs OR tracks): I select the way sign /tracks and it becomes red, because I defined it as 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 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, which tracks are related to which way sign, I simply would like to select the way sign, and get its related tracks.

4
4

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 new function in "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 "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 out.

Solution 3 would be creating temporary layer containing the related features. Solution 4 would be somehow styling the related features by means of "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... – MAP Jun 7 '20 at 7:13
1

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.

2) 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

2
  • 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 Apr 7 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 Apr 7 at 12:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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