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.
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))))
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) showscollect_cond
- only intersections where 1 source feature intersects 1 target feature (in this example, B/D/E)
- NOTE 1: You must
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 withinaggregate()
). - 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 withcollect_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 withgeometry()
.
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'))
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...)