5

I have a vector layer containing 3 rows (see image2). Each row is a polygon. The blue polygon is number3 and the magenta polygon is number2 (see image1)

image1

image2

I need to subtract the polygon that has the attribute "number"=3 to polygon that has the attribute "number"=2.

How can I do it in PyQGIS?

I have tried something like this:

import processing

layer = QgsProject.instance().mapLayersByName("Langham_SPZs_v1_diss")[0]

outfn2 = "Langham_SPZs_final.shp"

layer2=layer.selectByExpression('"number"=2')

layer3=layer.selectByExpression('"number"=3')

processing.run("native:difference", {layer3, layer2, 'OUTPUT':outfn2})
1
  • 1
    Blue is number 3, magenta is number 2 - I have edited the main post.
    – ec17403
    Mar 31, 2022 at 16:18

2 Answers 2

7

Field number is a string in your data. So you have to use "number='2'" as expression. And you should extract the selected polygon with number=2 since both polygons are in the same layer. Use this script:

import processing

layer = QgsProject.instance().mapLayersByName("Langham_SPZs_v1_diss")[0]

outfn2 = "Langham_SPZs_final.shp"    

layer.selectByExpression("number='2'")

layer2 = processing.run("native:saveselectedfeatures",
     {'INPUT':layer ,
      'OUTPUT':'TEMPORARY_OUTPUT'})["OUTPUT"]

layer.selectByExpression("number='3'")

processing.run("native:difference",
    {'INPUT':QgsProcessingFeatureSourceDefinition(layer.id(),
             selectedFeaturesOnly=True),
     'OVERLAY':layer2,
     'OUTPUT':outfn2})
1
  • Depending on the desired result, it can be done with shorter code: import processing layer = QgsProject.instance().mapLayersByName("Langham_SPZs_v1_diss")[0] layer.selectByExpression("number='3'") processing.runAndLoadResults("native:difference", { 'INPUT' : layer, 'OVERLAY': QgsProcessingFeatureSourceDefinition(layer.id(), selectedFeaturesOnly=True), 'OUTPUT': 'TEMPORARY_OUTPUT' })
    – ThiPa
    Mar 31, 2022 at 18:11
3

Another option is to use the materialize() method.

from qgis import processing

layer = QgsProject.instance().mapLayersByName('Langham_SPZs_v1_diss')[0]

outfn2 = "Langham_SPZs_final.shp"

layer.selectByExpression("number='2'")
layer2 = layer.materialize(QgsFeatureRequest().setFilterFids(layer.selectedFeatureIds()))

layer.selectByExpression("number='3'")
layer3 = layer.materialize(QgsFeatureRequest().setFilterFids(layer.selectedFeatureIds()))

processing.run("native:difference", {'INPUT' : layer3, 'OVERLAY' : layer2, 'OUTPUT': outfn2})

Note: this method is available since QGIS 3.0.


References:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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