5

I am trying to perform some calculations on a polygons layer I have, but there is a bit of complexity to it. I have this polygons layer, and underneath that layer, I have a population count data layer (1 dot = 1 person). I then draw 1-mile buffers around the centroid of each polygon (These are conceptual examples of course as I have not actually figured out yet how to do this with my own data):

enter image description here

Then I want to count, for each polygon, how many people fall within that polygon's buffer, regardless of whether that buffer overlaps with the buffer from another polygon. I want to calculate this value for each polygon and append it as a column to the layer's attribute table (we'll call this column "raw_count"). Now here is the complicated part. For every polygon, I now want to calculate the count value within that polygon's buffer, but where the dots that are overlapped by the buffer of another polygon are not counted. I want to create a new column with this new count value for each polygon and then append it to the layer's attribute table (we'll call this new column "clipped_count". Here is an example for polygon 1 (in grey):

enter image description here

There are 5 dots within the buffer for polygon 1 (both green and red). I only want to count the green dots. Since the red dots are overlapped with another buffer, I do not want to count them for polygon 1. And so the "clipped" count for polygon 1 would be 3. Then I want to move to polygon 2 (in grey):

enter image description here

There are a total of 6 dots within polygon 2's buffer. I only want to count the green dots. I do not want to count the red dots, because they overlap with the buffers of other polygons. And so the "clipped" count for polygon 2 would be 3. Now I want to do the same for polygon 3 (in grey):

enter image description here

The buffer for polygon 3 has 4 dots within it, all green. Since there are no overlapped buffers, I only need to worry about counting those 4 green dots. And so the "clipped" count for polygon 3 would be 4. (Note that all dots are the same throughout this post and I just change from red/green to indicate which ones I want to count at the moment).

I want to repeat this entire counting process for every polygon in the layer (hundreds of polygons), so essentially iterating through every polygon with this process. So the end goal would be to have my polygons layer with two additional columns appended to the attribute table: 1) "raw_counts" and 2) "clipped_counts".

Can this be done in QGIS? Or would this require Python? I am unsure of how to iterate through all polygons in the layer with these processes. How can I accomplish this?

3 Answers 3

1

The solution is quite easy, using QGIS expressions with the function overlay_within() (available since QGIS 3.16):

  1. Count for each point in the population layer within how many of the buffers it lies. Use this expression to create a new attribute called "in_buffers" in the population layer:

     array_length(overlay_within('buffer', $id))
    
  2. Count the number of population-points within each buffer - with the condition that only points are considered that lie in exactly 1 buffer (not in 2 or more and not in 0). Use this expression (replace in_buffers with the name of the layer created in step 1):

    array_length(overlay_contains('population', $id, filter:=in_buffers=1))
    

Screenshot: the blue points (=population) are labeled with the expression from step 1 and show the number of buffers they are within; the bold numbers in the middle of the buffers are created with the expression from step 2, showing the population-dots that are exclusively within this buffer:

enter image description here

0

In QGIS go to view->control panels -> processing toolbox.

On the right sidebar search for the specific process. The workflow could be the following (process:explanation).

(fieldcalculator:create new field with expression "$id" to identify the result ide)

(centroids:create centroids in the middle of the polygons, like you showed)

(buffer:create buffer of centroids)

(polygonstolines: lines that will cut buffer)

(splitwithlines: split buffer --> duplicates will be generated on some parts)

(centroids: create a centroid on each part of the splitted buffer)

(countpointsinpolygon: count points in the splitted buffer --> overlapping areas have more than 1)

(extractbyattribute: extract polygons that have counted 1 point)

(difference: remove original quadric polyogon from the result)

(countpointsinpolygon: now count the points in the result NUMPOINTS)

enter image description here

0

Create the exclusive geometry of each buffer (keep only the non-overlapping parts of each circle), then count the number of points within this remaining part of the buffer-geometry.

The expression is here used as a dynamic label that labels each buffer with the number of points within the exclusive (non overlapping) part: only points in the blue hatched area are counted: enter image description here

Use this expression for that (e.g. with field calculator or as dynamic label):

array_sum (
    array_foreach (
        overlay_intersects( 
            'population',
            $geometry
        ),
        within (
            @element,
            intersection (
                $geometry,
                if (
                    overlay_intersects(
                        'buffer'
                    ),
                    difference (
                        $geometry, 
                        collect_geometries(
                            overlay_intersects( 
                                'buffer', 
                                $geometry,
                                limit:=100
                    ))),
                    $geometry))
)))

To create the exclusive (non overlapping) part of the the buffer, use the part of the expression starting from line 9: intersection ( until the second last line: $geometry)).

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.