qgis/QGIS

QGIS expression overlay: filter based on other layers

Babelgit opened this issue ยท 7 comments

The very handy overlay functions to QGIS expressions introduced in version 3.16 have an optional filter argument. However, it seems that it works only for the layer that is refered to - the help says:

an optional expression to filter the target features to check

It would be nice if this filter condition could be used to write filter conditions based on other layers that are refered to e.g. using expressions that allow referring other layers like get_feature_by_id (). Right now, this does not seem to be possible. See here for a use case: https://gis.stackexchange.com/questions/391120/qgis-expression-with-overlay-fuction-filter-condition-based-on-comparison-of-at

I can't check right now (and may have quickly read the SE discussion) but should this not be possible using the @parent variable? Might be some examples of it's usage in the docs or other functions (eg, aggregates)

With @parent, you can't refer to another layer, as far as I can see. The filter condition allows only to filter inside the refered layer. At least, I don't know how the syntax would be to be able to compare values from two layers for the filter condition.

Mind testing something like filter:="id2" <> attribute(@parent, 'id1') ?

Tested it with no success, see screenshots with and without the filter. Result should look like screenshot 1, but without the lines connecting blue point 1 to red point 1, blue 2 to red 2 etc.: just points where id1<>id2 should be connected: blue points 17 and 19 to red point 1, blue 15 to red 2 etc.

See here for screenshots and the project + layers: https://drive.switch.ch/index.php/s/af5cHue6P3NA9xM

I think I get your expected result with (filter out the identical ID after we get the array of results)

collect_geometries(
    array_foreach(
        array_filter(
            overlay_nearest( 
                'layer2',
                "id2"
            ), 
            "id1"<> @element
        ),		
        make_line ( $geometry,
                    geometry( get_feature( 'layer2', 'id2', @element ) )
        )
    )
)

Back to the feature request, I think the purpose of the filter parameter is to reduce the dataset (layer2) to use for research, so it's applied before it proceeds to any overlay test; that new set of features is used for all the checks hence should somehow be the same. So not sure if it would have worked in your case (id1 changes every time), but there indeed might be case where you want to filter consistently the dataset using another layer. maybe should be done previously using a variable to store it?
But I may be misinterpreting. @olivierdalang ?

Yes, your expression does exactly what I wanted to do. The explanation that the filter condition is mainly there to limit the number of features to evaluate (and thus reduce processing time) makes sense. Apart from that, it still would be nice if it would be implemented.

@Babelgit please see #45744
Such PR makes it possible (since QGIS 3.22.1 and 3.23.0) to use a simple workaround that allows to write a filter string also referring to a source layer (or any other layer) field like: eval('overlay_nearest( \'target_layer\', $currentfeature, filter:=field_target_layer=' || "field_source_layer" || ')')

So, for your project:

make_line (
	eval( 'overlay_nearest( \'layer2\', $geometry, filter:=id2<>' || "id1" || ' )' )[0],
	$geometry
)

image