4

I work with QGIS 3.16 Hannover and I have three polygon layers 'A', 'B', 'C' with multiple geometries in each.

In the image, layer 'A' has the bold polygons and, for each of them (meaning within each of them), I need to calculate the percentage of the area of all the blue polygons (layer 'B') that is covered by the squared polygons (layer 'C')

enter image description here

Following the guidelines given by @MrXsquared in this post, I built the following code in the field calculator for layer 'A', but it returns null or wrong values

area(
     intersection(
                  (buffer(collect_geometries(overlay_intersects('B', $geometry)),0)), 
                  (buffer(collect_geometries(overlay_intersects('C', $geometry)),0)))) 
*100/area(buffer(collect_geometries(overlay_intersects('B', $geometry)),0))

Any idea of what's wrong?

4
  • Could you provide a screenshot how the layers look like and indicate which kind of overlapping you want to calculate? Or do you have some sample data you could share? What do you mean by "doesn't work properly" - what does not work? – Babel Apr 2 at 19:43
  • You want to calculate the area where all three layer overlap, but as percentage related to the area of each feature of layer A? – Babel Apr 2 at 19:50
  • I have edited the question. Hope it is clearer now. – Jesús Pinilla Apr 2 at 20:04
  • Thanks for providing more details, hope my solution provides what you're looking for. – Babel Apr 2 at 20:34
4

The problem with the expression you provided was that the intersection () part only calculated the overlap of C and B, notwithstanding if they are inside A or not. You have to add another overlap, pseudocode: overlap of A with ( overlap of B and C) - you had only the part inside the paranthesis.

To create the overlap you're interested in, the expression looks like (for the area and percentage see below):

intersection (
    $geometry ,
    intersection(
        buffer(
            collect_geometries(
                overlay_intersects(
                    'B', 
                    $geometry
                )
            ),
            0
        ), 
        buffer(
            collect_geometries(
                overlay_intersects(
                    'C', 
                    $geometry
                )
            ),
            0
        )
    )
)

Screenshot: A= black lines; B: blue; C: green; red: overlap calculated with the expression above: enter image description here

So based on this, calculating the percentage of ovelapping for each polygon of A is easy - pseudocode: area of the overlap created above / area of each polygon of A * 100. In fact, buffering by 0 is not necessary, you can leave this part away. Thus the expression to calculate the percentage looks like this:

area (
    intersection (
        $geometry ,
        intersection(
            collect_geometries(
                overlay_intersects(
                    'B', 
                    $geometry
                )
            ),
            collect_geometries(
                overlay_intersects(
                    'C', 
                    $geometry
                )
            )
        )
    )
)
/area($geometry)*100

Screenshot: the label is created dynamically with the expression above (+ a round() to round to one decimal). Polygon A on the right (balck outlined) contains four overlapping areas (red), the polygon at the bottom left 2, the other two just one red area. The percentage is calculated as the sum of all red areas inside a polygon, whereas the area of the black outlined polygon A features is 100% for each polygon: enter image description here

If however the percentage of ovelapping you need is not for each polygon of A, but for the area of the blue polygons that are within each polygon of A, than replace the last line /area($geometry)*100 with this expression:

/area (
    intersection (
        $geometry ,
        collect_geometries(
            overlay_intersects(
                'B', 
                $geometry
            )
        )
    )
)*100

After some tries, the final expression that works for the date of the OP includes the buffers of 0:

area (
    buffer(
        intersection (
            $geometry ,
            buffer (
                intersection(
                    buffer( 
                        collect_geometries( 
                            overlay_intersects(
                                'B', 
                                $geometry
                            )
                        ),
                        0
                    ),
                    buffer(
                        collect_geometries(
                            overlay_intersects(
                                'C', 
                                $geometry
                            )
                        ),0
                    )
                ),0
            )
        ),0
    )
)/area(
    buffer(
        collect_geometries(
            overlay_intersects(
                'B', 
                $geometry
            )
        ),0
    )
)*100
5
  • Many thanks indeed for such a detailed explanation. However, the percentage of ovelapping that I need is not for each polygon of A, but for the area of the blue polygons that are within each polygon of A. The pseudocode: area of the overlap in red / overlap of A and B (* 100). So, if I'm not mistaken, the code for the overlap of A and B would be intersection(collect_geometries(overlay_intersects('B', $geometry). BTW, the "* 100", shouldn't it be in the numerator? – Jesús Pinilla Apr 2 at 22:01
  • 1
    Updated that part. if *100 is in the numerator or not does not play a role: test the preview of the expression editor for something like 10*5/2 and 10/2*5 - the result is the same. – Babel Apr 2 at 22:21
  • By the way: are all the layers in the same CRS? – Babel Apr 2 at 22:23
  • Yes, they are in the same CRS – Jesús Pinilla Apr 3 at 17:27
  • OK, pasted your solution to my answer. In the case of my test-polygons, aplying the buffer does not play a role - I'm not sure why in your case this is crucial. This shows that a soution might depend on the kind of data you have - so adding some sample data to a question can be helpful as creating own test data will not always reflect the problem in it's whole complexity. Glad you resolved your problem. – Babel Apr 4 at 20:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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