I have 2 shapefiles that cover a similar region, a river catchment and a hex-grid of surface water bodies within the catchment. The catchment has subcatchments, and I'm trying to link the hex-grids that overlay each sub-catchment in a column in the attribute table.

Using the geometry expressions in the Field Calculator in QGIS 3.28.4 LTR, I have got an expression that covers hexes that lie within (overlay_within), but I also want to include the hexes that Overlap (Overlap) in the expression.

I've been using the QGIS Documentation to understand the expression I want to write (Select By Location and 'Overlay_' geometry expressions), but my results only show the ones within, the ones that cross, or the ones that intersect, not only the first two that I want.

I've illustrated what I mean; enter image description here

I want the expression to list in the hex-grid attribute table that Circle 1 AND Circle 2 are spatially connected to the Orange Box. Circles 3 and 4 would be spatially connected to Box 2.

At the moment I only have 2 separate expressions

array_to_string(overlay_within('Box',Box_ID)) which returns

Circle ID Connected to Box_ID
1 Box 1
4 Box 2

I can't have NULL values for shared-overlapping circles (hexes), because then they won't be factored in at all for later spatial operations.

array_to_string(overlay_intersects('Box',Box_ID)) which returns

Circle ID Connected to Box_ID
1 Box 1
2 [Box 1, Box 3]
3 [Box 1, Box 2]
4 Box 2

I can't have arrays or multiple spatial relations for one Circle (Hex) because that will cause issues later down the line.

overlap I found I couldn't use because I couldn't get it to include only the Box_ID attribute, just the entirre shapefile name (i.e. All the Circles are connected to 'Boxes.shp').

What I want is just overlay_within and overlap (or intersect minus touch) that produces this result below with

Circle ID Connected to Box_ID
1 Box 1
2 Box 1
3 Box 2
4 Box 2

How would I construct the expression for what I'm specifying, or is this a multiple and separate expression operation?

  • 1
    Does using the centroid will work ? In your exemple the centroid will be the center of the circle (so circle 2 centroid will fall in box 1) but with very irregular feature you may get case where the centroid fall in the wrong box
    – J.R
    Apr 27, 2023 at 13:31
  • @J.R I'm using identical sized hexes, so the centroids might work! I'll figure out if I can do that on a per-hex basis within the Field Calculator and then I can try that with overlay_within. Apr 27, 2023 at 14:59
  • So I've tried array_to_string(overlay_intersects('Box_Layer', Box_ID, centroid($geometry))) and while it does check out, it only returns a Null values for all features. Similar results with array_to_string(overlay_contains('Box_Layer', Box_ID, centroid($geometry))) Apr 27, 2023 at 17:11

1 Answer 1


Try this:

overlay_intersects('Box_Layer', Box_ID, sort_by_intersection_size:='des')[0]

This code will get all intersecting boxes ID's and sort them in an array by size of intersection with descending order (biggest intersections first). Then [0] index takes first array's element - it's the box with biggest common area with the circle.

  • Thanks, I tried this and it appears to have the same issue - The syntax checks out within the Field Calculator, but it only produces NULL results. Similar if I repeat it with array_to_string(overlay_intersects('Box_Layer', Box_ID, sort_by_intersection_size:='des')[0]) or if I put double quotes around the Box_ID ("Box_ID"). Does it matter very much if the Box ID of the Box and Circle's 'Box_ID' attribute is an integer? Apr 28, 2023 at 9:01
  • 1
    Update: I accidentally used the wrong layer without the Box_ID set, hence the Null Value. This actually worked perfectly! Thank you very much. Apr 28, 2023 at 9:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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