I have two layers here (ignore the green layer), blue polygons and black circles. I want to calculate for each circle, what percent of the each of the blue polygons does it cover. For example, the circle closest to the top right of the image covers 100% of that small dark square polygon, and about 1% of the huge lighter blue polygon on top. Each circle would need potentially multiple attributes since each circle can cover multiple polygons.

The end goal is to estimate (assuming uniformity) how many locations fall into each circle. If a polygon contains 100 locations and is equally covered by two circles, each circle would then have an estimated 50 locations each

enter image description here

  • The Output result should have a concatenated %-values or for each intersections must be a single value? – Taras Sep 21 at 8:48
  • 1
    Are your circles polylines or polygons? – Taras Sep 21 at 8:59
  • 4
    Whta have you tried and what are your ideas of how to tackle it? – Taras Sep 21 at 9:56
  • Very good and clear question. Don't mind the closers. – Jakob Sep 22 at 6:16
  • thank you. glad to have gotten some great answers before it closed – Ben Hendel Sep 22 at 7:38

Here is a solution based on Virtual Layers in QGIS. It is a mess in SQL to work with a dynamic number of columns, so here the different procentages are show in rows. In a spreadsheet you can pivot the rows to columns if needed.

Test data: Four colored land (myland) and three circles (mycircle):

enter image description here

Run in QGIS Virtual Layers of the Data Source Manager:

with circle_land_intersection as (
    select c.name circlename, l.name landname, st_area(l.geometry) total_land_area,
        st_intersection(c.geometry,l.geometry) geometry
    from mycircle c, myland l
    where st_intersects(c.geometry, l.geometry)
area_calc as (
    select *, st_area(i.geometry) intersect_area
    from circle_land_intersection i
select *, round(intersect_area/total_land_area*100) pct from area_calc;

You will need to replace mycircle and myland with your own table names in above SQL. Also the column name in both tables should be matching your data. Alternatively you can delete the part:

c.name circlename, l.name landname


enter image description here

| improve this answer | |
  • It gives me an error: Reason: virtual Query preparation error on PRAGMA table_info(_tview): no such column: c.name – Ben Hendel Sep 22 at 7:48
  • name is a column in both tables. Change it to your own column name. I added the name columns to test the outcome of the spatial join. Take a look at the three attribute tables. Have updated the answer. – Jakob Sep 22 at 7:53
  • Can't believe I missed that. It works now. Incredible job! – Ben Hendel Sep 22 at 9:10
  • For some reason recently this only generates attributes tables one row long. Do you have any idea what that is about? – Ben Hendel Sep 24 at 8:47
  • Not really, you can try to just run the intersecting SQL alone, to see if you get the intersect areas. Cut it from your code like: select c.name circlename, l.name landname, st_area(l.geometry) total_land_area, st_intersection(c.geometry,l.geometry) geometry from mycircle c, myland l where st_intersects(c.geometry, l.geometry) – Jakob Sep 24 at 12:19

As an alternative answer, this is how you would get QGIS to calculate this live and update automatically when you add or change features:

In the attribute table of the Black Circles layer open the Field Calculator. Tick Create virtual field and set it to Decimal number.

As the expression use the following:

(area(intersection($geometry, aggregate('Blue Polygon Layer', 'collect', $geometry))) / area($geometry)) * 100

This can be repeated then for other layers using another virtual field.

The breakdown of the above is as follows:

aggregate('Blue Polygon Layer', 'collect', $geometry) collects the geometries of all the features of Blue Polygon Layer to create one large multipart geometry of the whole layer

intersection($geometry, aggregate('Blue Polygon Layer', 'collect', $geometry)) creates a geometry of the intersecting area of the Black Circle feature and the now aggregated Blue Polygon Layer

(area(intersection($geometry, aggregate('Blue Polygon Layer', 'collect', $geometry))) / area($geometry)) * 100 calculates the area of that intersecting geometry and divides it by the area of the original Black Circle features and multiplies by 100 to get the percent

Some notes on this:

  • Both layers will need to be in the same projected coordinate system
  • You need to use area($geometry) and not $area (planimetric vs geographic calculation)
| improve this answer | |
  • I don't think this works. Aside from returning mostly null values, it returns one column of data. How can a circle that covers multiple blue polygons be represented with one number? It needs to return multiple percentages – Ben Hendel Sep 21 at 10:27

Calculate the area of each polygon ($area using the field calculator, assuming you are using a CRS based on m). Then use intersect in order to divide the circles using the polygons while adding the attribtues of the polygons to the divided circles. Now run $area again on the intersection. You now know, how large the original polygon is and how large the part is, which each circle covers. The rest is basic mathematics (area intersection/area polygon).

I don't know how the intersection tool handels overlapping polygons (in this case your circles), so evaluate your outcome carefully.

| improve this answer | |

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