3

I'm developing a plugin where I would like to get some features from one layer (a), do a difference on them with the entirety of a second layer (b), and put the results into a layer I've created in memory (c). If at all possible, I'd also like to copy a specific field from (a) to (c) when doing the difference.

To do this, I've got the following code set up:

layer_A = None
for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
    if lyr.name() == "A":
        layer_A = lyr
        break

it = layer_A.getFeatures( QgsFeatureRequest().setFilterExpression ( u'"CAT" = 27') )
layer_A.setSelectedFeatures( [ f.id() for f in it ] )

box = layer_A.boundingBoxOfSelected()
iface.mapCanvas().setExtent(box)
iface.mapCanvas().refresh()

layer_B = None
for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
    if lyr.name() == "B":
        layer_B = lyr
        break

l1 = QgsVectorLayer("Polygon?field=CAT:integer", "C", "memory")
QgsMapLayerRegistry.instance().addMapLayer(l1)

As you can see, we select various features in A based on a query.

I'd like to perform a difference between these selected features, and the entirety of B, which is unfiltered and to put the resulting shapes into C (with the CAT, if at all possible, but not necessary).

2

To get the answer on your question I recommend you to use QGIS Python API:

  1. To iterate over all features in the layer use qgis.core.QgsVectorLayer.getFeatures

  2. To iterate over selected features use qgis.core.QgsVectorLayer.getSelectedFeatures

  3. Then get features geometry with qgis.core.QgsFeature.geometry

  4. And finally use qgis.core.QgsGeometry.difference

1

Managed it with this code, with explanation:

    fields = difflayer.fields()
    features_A = layer_A.selectedFeatures()
    features_B = layer_B.getFeatures()
    outgoingFeatureList = []
    for f in features_A:
        compFeature = QgsGeometry()
        localFeature = QgsGeometry()
        outgoingFeature = QgsFeature()
        localFeature = f.geometry()
        for h in features_B:
            compFeature = h.geometry()
            if localFeature.intersects(compFeature):
                localFeature = localFeature.difference(compFeature)
        outgoingFeature.setFields(fields)
        outgoingFeature.setGeometry(localFeature)
        outgoingFeature['ID'] = f['ID']
        outgoingFeatureList.append(outgoingFeature)
    difflayer.dataProvider().addFeatures(outgoingFeatureList)
    difflayer.commitChanges()

Using this, we cycle through layer A and get each of our selected features, storing this as a feature locally. Then we cycle through layer B and compare the current (A) feature with the (B) features for intersects.

If we intersect, then we diff the stored feature with the intersecting one. This way, we don't have to merge, as each intersecting feature will take a chunk off the local one.

When we've reached the end of the (B) features, we'll write this to a list and, when we reach the end of the (A) features, write this list to the layer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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