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.
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):
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".
This will create duplicate polygons wherever a layer1 polygon intersects with more than quarter section.
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 == attrs: QS_list.append(str(attrs_joined)) layer1.startEditing() layer1.changeAttributeValue(ID, 1, str(sorted(QS_list))) layer1.updateFields() layer1.commitChanges()
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.
I´d go for a Virtual Layer using the natively supported SQLite/SpatiaLite SQL dialect:
Add/Edit Virtual Layer...
Add(from file) /
Import(from project) | select both polygon layers
Assuming their names are
idcolumn each and an attribute
layer2that you are interested in, running
SELECT a.*, GROUP_CONCAT(b.val) AS vals FROM layer1 AS a JOIN layer2 AS b ON ST_Intersects(a.geometry, b.geometry) GROUP BY a.id
Queryfield will copy all attributes/geometries from
layer1plus a concatenated string field
vals, with the
layer2that intersect each polygon in
layer1, into the Virtual Layer.
Addand save to file (e.g. layer context |
The more versatile way would be to use the DB Manager (as @DPSSpatial also mentioned in his comment I only just read...); this is a full scale DB client, capable of also runnning queries against the project layers (you'll find all currently loaded layers under
Virtual Layers |
QGIS Layers on the left) using the SQLite/SpatiaLite SQL dialect;
- E.g. when executing the same query, you will be presented a result table including a geometry field to check against.
Load as new layerand save the created layer to file (don´t forget to specify a geometry column if not already set).
If you are not familiar with or just not willing to use SQL in any way, you can also simply use the Field Calculator (the summary aggregate functions should be available from QGIS 2.16.x on):
- layer1 |
Open Field Calculator|
Output field type=
aggregate(layer:=<layer>, aggregate:='concatenate', concatenator:=',', expression:="<field>", filter:=intersects($geometry, geometry(@parent)))
<field>with fieldname of interest in
layer2(double quotes have to stay!)
<field>is not of type
OKshould add the above field to the attribute table of
layer1as a concatenated string
save/quit edit mode (has been auto enabled)