How to use the "geometry generator" to intersect geometries with an entire layer in QGIS?

@DPSSpatial's response - use of a filter - will style entire polygons of which some part intersects with a single feature from another layer.

I gather you want to style only the intersections, in which case your use of intersection() in the geometry generator is correct, but you want to style intersections of all features from another layer, not just one as with geometry(get_feature()).

If you are sticking purely to the Expression String Builder I'm not sure if this is possible with QGIS 2 without using custom functions. (see e.g. here, here, here)

However, if you are willing to try out QGIS 3, there is a way...


Firstly, let me assume that:

  • the LEFT is what you want as a style
  • and the RIGHT is what you're getting with get_feature() - one feature at a time.

Full intersection Intersecting one feature at a time


QGIS 3 introduces the new collect aggregate function, which treats all the features in a layer (either current or other specified) as one multigeometry.

Using the following code in the geometry generator, you can generate the areas in PINK below (2collect_cond)

intersection(collect($geometry),
             aggregate('target_layer','collect',$geometry,
                        intersects($geometry,geometry(@parent))))

QGIS 3 Geometry Generator Intersection

This intersects a collection of the source geometry, with a collection of the target geometry, only where it intersects with the source (sounds kooky but read on)

  • collect() collects the geometry of the current, source layer.
    • NOTE 1: You must collect() the source geometry, or else it (a) won't work at all, or (b) shows collect_cond - only intersections where 1 source feature intersects 1 target feature (in this example, B/D/E)
  • aggregate() lets you specify features from other layers. Within it, collect is the function that works with geometries.
    • First you specify the target layer.
    • Then the field to collect is of course $geometry (now of the target layer, since we are within aggregate()).
    • NOTE 2: you need to filter the results of aggregate() to include only target layer features that intersect with any feature from the source layer. Otherwise you end up with collect_simp - totally borky.
    • The filter is specified with intersect($geometry,geometry(@parent)).
    • Remember, $geometry here refers to the target layer, so to specify the source feature you need to write @parent, then get the geometry from it with geometry().

Bonus: You could further refine the results by source and/or target layer attributes by modifying the collect() and/or attribute() filter parameters respectively.

intersection(collect($geometry, filter:="source_attribute"='VALUE'),
             aggregate('target_layer','collect',$geometry,
                        intersects($geometry,geometry(@parent))
                        AND "target_attribute"='VALUE'))

Style by source or target layer attributes

NOTE: If you try this out in the "Filter" field by swapping out intersection() for intersects(), it only works for target layer attributes, AFAICT.


I just got this to work with the following:

First, set up a rule-based renderer.

Then for the rule filter, use:

intersects($geometry, geometry(get_feature('Board_Current', 'BOARD_DIST', '3')))

Where:

$geometry refers to the geometry of the point layer
'Board_Current' is the layer_name (variable) of the polygon layer
'BOARD_DIST' is the column in the polygon layer I want to filter on
'3' is the value in the BOARD_DIST column I want to intersect features in the points layer

Works great! Thanks for getting me started with the code - I think the key might be the rule-based renderer, and pay attention to single and double quotes (I still get hung up on which is used where...)