4

I have a layer of contiguous (pink) polygons (UK Parliamentary constitutencies) and a separate layer containing (blue) polygons representing protected nature areas (Natura 2000 areas):

enter image description here

Each constituency consists of a single polygon. Each Natura 2000 area can consist of one or more polygons.

For each constituency I need a combined total for the number of Natura 2000 areas that are:

  1. contained in
  2. touched by
  3. overlapping

that constituency.

I've added both as vector layers in QGIS and tried using Spatial Query and Topology Checker plugins and Geoprocessing tools (Clip, Intersect). But I don't really know what I'm doing. Although I was able to select constituencies where there is an intersect I couldn't see the number of intersects per constituency and this didn't solve my need to include touching and contained polygons in the totals.

And just to be clear about Natura 2000 areas consisting of one or more polygons. In this screenshot (contained in a box) is an example of a single Natura 2000 site consisting of multiple polygons. Because all of these polygons are contained in a single constituency we'd only want to count them once as a single Natura 2000 area. But if they were spread across the boundaries of constituencies we'd count them for each constituency any part of them touched/overlapped/was contained by. In the same way we'd count the single polygon Natura 2000 site that overlaps two constituencies (circled) twice - once for each constituency it covers.

enter image description here

(For background, I'm campaigning to protect Natura 2000 areas and my aim is to develop a target list of UK Members of Parliament prioritised by those who have the highest number of these areas in their constituency.

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
  • related: http://gis.stackexchange.com/questions/60045/find-and-list-all-polygons-that-overlap-with-another-polygon – Mapperz Jan 15 '16 at 18:19
  • Are you open to python scripting? I'm not sure you can achieve what you want with a simple combination of QGIS functions. – ArMoraer Jan 15 '16 at 18:37
  • I'm just starting to write a simple script, but I need more info. The most important being : how do you know when multiple polygons are part of the same Natura 2000 area? Does the Natura 2000 layer have an attribute such as "area id" shared by polygons of a same area, for example? – ArMoraer Jan 15 '16 at 19:41

1 Answers1

2

EDIT: there is actually a simpler answer. Compute the intersection between your two layers (Vector > Geoprocessing tools > Intersect), then use the Group Stats plugin to compute statistics on the constituencies. You can even compute the total area of Natura 2000 sites per constituency.

Minor issue: it will only take into account Natura 2000 sites that intersect (overlap + contained) the constituencies.

Original answer:

As stated in my last comment I wrote a small Python script to do the job. It is probably the most simple way to answer your question.

Following the comment of mgc, I assume your Natura 2000 layer is made of MultiPolygons. If it is not the case (i.e. if the layer is made of simple polygons), just use Vector > Geometry Tools > Singleparts to Multipart... to get a new MultiPolygon layer from your Natura 2000 layer. You will have to specify the field that identifies unique areas (cf. my last comment).

The simplest way to execute the script is to install the Script Runner plugin in QGIS. Then, copy the following text in a file that you will call e.g. script.py:

from qgis.core import *

def run_script(iface):

    lyr_n2000 = QgsVectorLayer("PATH/TO/YOUR/NATURA2000/SHAPEFILE", "", "ogr")
    lyr_constit = QgsVectorLayer("PATH/TO/YOUR/CONSTITUENCIES/SHAPEFILE", "", "ogr")

    list_n2000 = list(lyr_n2000.getFeatures())
    list_constit = list(lyr_constit.getFeatures())

    print "Constituency | contained | touched | overlapped | TOTAL"

    for constit in list_constit:

        n2000_contained = 0
        n2000_touched = 0
        n2000_overlapping = 0
        constit_geom = constit.geometry()

        for n2000 in list_n2000:

            try:
                n2000_geom = n2000.geometry()

                if constit_geom.contains( n2000_geom ):
                    n2000_contained = n2000_contained + 1

                if constit_geom.touches( n2000_geom ):
                    n2000_touched = n2000_touched + 1

                if constit_geom.intersects( n2000_geom ):
                    n2000_overlapping = n2000_overlapping + 1

            except Exception:
                print "Error with n2000 #{0} and constit #{1}".format(n2000.id(), constit.id())
                pass

        print "{0} | {1} | {2} | {3} | {4}".format(constit.attribute("id"), n2000_contained, n2000_touched, n2000_overlapping-n2000_contained-n2000_touched, n2000_overlapping)

Change the paths to your shapefiles, and replace the "id" in constit.attribute("id") (last line) by the name of the field of the constituency layer you want to see appear.

Open the script with the Script Runner plugin (launch the plugin and click on the green "+"). To run the script, click on the green arrow. The results will appear in the bottom panel, they look like that (I used homemade test layers) :

Constituency | contained | touched | overlapped | TOTAL
1 | 0 | 0 | 0 | 0
2 | 0 | 0 | 0 | 0
3 | 0 | 0 | 1 | 1
4 | 0 | 0 | 0 | 0
5 | 0 | 0 | 1 | 1
6 | 1 | 1 | 1 | 3
7 | 0 | 0 | 1 | 1

The first column represents the constituency. The second, third and fourth columns are respectively the number of N2000 areas completely contained, adjacent or simply overlapping (not intersecting!) the constituency. As you can guess, the last column is the sum of the previous three.

This script may need some adjustments depending on the precise nature of your data. Don't hesitate to post a comment if anything goes wrong (bad results, script not running, etc).

Test layer (N2000 in blue, constit. in orange): Test layer with natura 2000 areas in blue

ArMoraer
  • 5,649
  • 2
  • 26
  • 48
  • Thanks so much for this! I tried running the script as suggested but got the following error: Traceback (most recent call last): File "C:/Users/sion elis.williams/.qgis2/python/plugins\scriptrunner\scriptrunner.py", line 553, in run_script user_script.run_script(self.iface) AttributeError: 'module' object has no attribute 'run_script' – Sion Williams Jan 18 '16 at 13:58
  • Well, apparently you can't name your script script.py, for some reason... Can you try naming it myscript.py? – ArMoraer Jan 18 '16 at 14:29
  • Hello, thanks again. Renamed but this time got this: Traceback (most recent call last): File "C:/Users/sion elis.williams/.qgis2/python/plugins\scriptrunner\scriptrunner.py", line 553, in run_script user_script.run_script(self.iface) File "C:/Users/sion elis.williams/Desktop\myscript.py", line 24, in run_script if constit_geom.contains( n2000_geom ): Exception: unknown – Sion Williams Jan 18 '16 at 18:31
  • Hi, sorry for being late. It's difficult to identify the issue from the message you got. It's possible that one of your polygons has a "wrong" geometry. I updated the script in order to ignore this kind of message, can you give it a try? – ArMoraer Jan 20 '16 at 15:17
  • Hey, no worries! Tried again but it was "Crash dumped" to C:\Users\SIONEL~1.WIL\AppData\Local\Temp\qgis-20160125-113527-5632-992-e2a51df.dmp which I'm struggling to find a way of opening. Will reply again once I've found a way. Thanks for your patience and persistence. – Sion Williams Jan 25 '16 at 12:55
  • Hey, managed to open that .dmp file in notepad and saved to google drive as a zipped .txt file: [https://drive.google.com/file/d/0BxTmUMstpZKwYWwzbTVpOUhUOU0/view?usp=sharing] Here are the two .shp files I'm using too: [https://drive.google.com/file/d/0BxTmUMstpZKwZFEzSUNSMTVFTk0/view?usp=sharing] and this one zipped [https://drive.google.com/file/d/0BxTmUMstpZKwMDJNb1B0QkIxZVE/view?usp=sharing]. Hope that helps and is proper etiquette! (I'm new here.) – Sion Williams Jan 26 '16 at 12:58
  • I think that will be simpler that way ;) Give me a few days and I should be able to give you the result based on the shapefiles you gave me. – ArMoraer Jan 27 '16 at 14:44
  • Hi, could you also send me the .dbf and .shx files that come with the .shp files? I need them to open the layers. You can put them in a single zip file, it will be simpler. – ArMoraer Jan 28 '16 at 13:27
  • Thanks so much. I've deleted the zips mentioned above to make room for the single zips you suggest (containing .shp .dbf and .shx files). Here are the UK constituency boundaries: https://drive.google.com/file/d/0BxTmUMstpZKwNm9QUmFVM3dxOEU/view?usp=sharing and all EU Natura 2000 sites: https://drive.google.com/file/d/0BxTmUMstpZKweXhWOFN6MlphRTg/view?usp=sharing The latter hasn't been filtered to only the UK sites we're interested in because I don't know how to do that and export anything other than the .shp file sorry. Thanks again for all your kind help! – Sion Williams Jan 29 '16 at 14:46
  • Finally did it! Results here. Important note : the results are not completely accurate because the N2000 sites don't always follow constituency boundaries when they should. Example: the Natura 2000 Kenfig/Cynffig site should (I guess) only touch the Aberavon constituency; instead, there is a tiny overlap between them. As a consequence, no "touching" sites are listed in the results file: real touching sites are either listed as overlapping sites, or not listed at all. Given your final goal, I guess this is not a serious issue. – ArMoraer Jan 30 '16 at 18:49
  • Sorry for going quiet. You are an absolute superhero! Thanks so much for your help. – Sion Williams Mar 17 '16 at 13:22