I'm trying to make it so that a layout label always displays the name of the municipality which intersects with the center of the layout map extent.
To do this I've tried using the following expression:
aggregate(layer:='Cont_AAD_CAOP2021',
aggregate:='concatenate',expression:="Concelho",
filter:=intersection( geometry(Cont_AAD_CAOP2021),
geometry(item_variables('Map 1')['map_extent_center'])))
In which "Cont_AAD_CAOP2021" is the shapefile containing municipality information, and "Concelho" is a string field containing the municipality names. "Map 1" is the name of the map in the layout.
However, all I get is an empty output, even if the expression gives no error message. I'm guessing the problem is with the filter, but I'm not sure.
I'm using QGIS 3.22.5
EDIT: The data I'm using and an example project can be found here
Best Answer
You approach is possible, but very inefficient. I would heavily advice to create an atlas (see my other solution). However, just to answer your question and show a way to solve your problem with the approach you tried. There are in fact two problems with what you tried:
CRS issue
Use the same CRS for the project and the layer(s) you use to get the intersection. You had
EPSG:32629
as project CRS (used also for your layout), butEPSG:3763
for the layerCont_AAD_CAOP2021
. Reproject the layer to the project CRS, then intersection will work.Expression/syntax
Now use the following expression - see below for explanation:
Explanation:
The correct syntax to get the center of the current layout page is:
map_get (item_variables ('Map 1'), 'map_extent_center')
, seeitem_variables()
andmap_get()
.Instead of aggregate/concatenate the names of the attribute
"Concelho"
and filtering by intersection, rather useaggregate/array_agg
to get an array of all id's of the layer, then useget_feature_by_id ()
andgeometry()
to get an array of the geometries from the layer. Witharray-foreach()
an anif()
clause then test if these geometries intersect with the center of the layout (step 2).For the geometry that returns true (intersects with the center of the current layout), get the value of the field
Concelho
usingattribute()
.Use
array_max()
to get rid of the empty values and keep only the value of the fieldConcelho
that indeed intersects the layout's center.