[GIS] One to many intersection of polygons

intersectionpolygonqgis

using QGIS 2.18.16 I am trying to figure out how to find out what polygons in layer one (blue) intersects the polygons in layer 2 (red\pink). I know that there will be more than one intersection for most of the polygons in layer 1 (blue) but not sure how to calc it. In a perfect world I would like to add it as a attribute to the polygon in layer 1.

enter image description here

Best Answer

I found the following to work well on my small sample, though it involves repeated iteration through the layer1 features, so it might be slow on a large dataset. Also, I used QGIS 3.0.0. I am not sure how much it differs from 2.18.16.

First, load data (pardon my crooked quarter sections):

quarter sections and layer 1

Second, use "Vector > Data Management Tools > Join Attributes By Location" to join the two layers. I selected "contains" in addition to "intersects" under geometric predicates to cover cases like polygon 2, where it doesn't cross the border of a quarter section. Use layer 1 (blue) as the input and the quarter sections as the join layer. Use the create separate feature for each located feature option under "join type".

settings for join by location

This will create duplicate polygons wherever a layer1 polygon intersects with more than quarter section.

duplicated polygons

Lastly, we use the new joined layer to write the correct quarter section names into the original layer1 file with a bit of python.

# add layers and add new attribute to layer1
joined = QgsVectorLayer("...some path/joined.shp", "Joined layer", "ogr")
layer1 = QgsVectorLayer("...some path/layer1.shp", "layer1", "ogr")
res = layer1.dataProvider().addAttributes([QgsField("QS_list", QVariant.String)])
joined.updateFields()
layer1.updateFields()

# iterate through the layer1 features and for each,
# iterate through the joined features and for each,
# if the layer1 and joined IDs match, add the QS name to a list
# finally sort the list and write it into the new layer1 attribute
for feature in layer1.getFeatures():
    ID = feature.id()
    QS_list = []
    for feature_joined in joined.getFeatures():
        attrs = feature.attributes()
        attrs_joined = feature_joined.attributes()
        if attrs_joined[0] == attrs[0]:
            QS_list.append(str(attrs_joined[1]))
    layer1.startEditing()
    layer1.changeAttributeValue(ID, 1, str(sorted(QS_list)))
    layer1.updateFields()
    layer1.commitChanges()

results after python code

There appears to be a trick to doing this in ArcGIS also (and it looks way easier). Spatial Join’s hidden trick or how to transfer attribute values in a One to Many relationship

Here are the steps (the post on Esri Australia Technical Blog also has screen captures). I didn't test this.

In the Spatial Join tool’s dialog navigate to the Zoning field in the dataset that is being joined and Right-click on it. Choose Properties.

Set the following:

Length: set the value which will be capable of storing the appropriate number of characters

Merge Rule: use Join

Delimiter: use any delimiter you like

Set the cardinality in the Spatial Join tool to “One to One” Run the tool. The resulting dataset should display zones that each of the property boundary polygons intersect, stored as text values separated by the delimiter of your choice.

Related Question