8

In ArcPy, you can pass a geometry object as parameter to geoprocessing tool:

import arcpy

coordinates = [[20, 30], [30, 30], [30, 20], [20, 20]]
array = arcpy.Array([arcpy.Point(x, y) for x, y in coordinates])

# Create a polygon geometry object using the array object
boundary = arcpy.Polygon(array, arcpy.SpatialReference(4326))

arcpy.Clip_analysis('c:/data/rivers.shp', 
                     boundary, # <- GEOMETRY OBJECT
                    'c:/data/rivers_clipped.shp')

I have a polygon geometry and a layer. I want to clip the layer by the polygon geometry using PyQGIS. Normally, I make a new layer, add the geometry to the layer and use it in processing.run as follows:

coordinates = [QgsPointXY(20, 30), QgsPointXY(30, 30),
               QgsPointXY(30, 20), QgsPointXY(20, 20)]
geometry = QgsGeometry.fromPolygonXY([coordinates ])

temp_layer = QgsVectorLayer(f"Polygon?crs=EPSG:4326", "TEST", "memory")

feature = QgsFeature()
feature.setGeometry(geometry)
temp_layer.dataProvider().addFeatures([feature])
temp_layer.updateExtents()

LayerA = iface.activeLayer()

result = processing.run("native:difference",
                        {'INPUT': LayerA,       # <- QgsVectorLayer
                         'OVERLAY': temp_layer, # <- QgsVectorLayer
                         'OUTPUT':'TEMPORARY_OUTPUT'})

But I would like to avoid making a new layer for one geometry. I tried passing a geometry to processing.run, but it obviously didn't work:

result = processing.run("native:difference",
                        {'INPUT': LayerA,       # <- QgsVectorLayer
                         'OVERLAY': geometry,   # <- QgsGeometry ?
                         'OUTPUT':'TEMPORARY_OUTPUT'})

How can I pass a geometry object to a processing tool without making a new layer for the geometry? Is that possible in PyQGIS?

1
  • 1
    This something I have wondered too. Currently I have a function, geom2lyr to convert a geometry or list of geometries into a layer, in a library that I import into most of my scripts. Using the geometry directly would be very handy.
    – Matt
    Jan 25 at 14:18

1 Answer 1

4

When I check the help for the "native:difference"/"qgis:difference" algorithm with processing.algorithmHelp("native:difference") it declares that:

INPUT: Input layer

    Parameter type: QgsProcessingParameterFeatureSource

    Accepted data types:
        - str: layer ID
        - str: layer name
        - str: layer source
        - QgsProcessingFeatureSourceDefinition
        - QgsProperty
        - QgsVectorLayer

where:

  • QgsProcessingFeatureSourceDefinition : a constructor for QgsProcessingFeatureSourceDefinition, accepting a static string source.
  • QgsProperty : a constructor for a QgsAbstractProperty. The property will be set to an InvalidProperty type.
  • QgsVectorLayer : represents a vector layer which manages a vector based data sets.

So, it seems there is no possibility to pass directly the geometry object to processing algorithm.

However, I can suggest an alternative that uses a "Virtual Layer":

coordinates1 = [QgsPointXY(20, 30), QgsPointXY(30, 30), QgsPointXY(30, 20), QgsPointXY(20, 20)]
coordinates2 = [QgsPointXY(25, 35), QgsPointXY(35, 35), QgsPointXY(35, 25), QgsPointXY(25, 25)]

geometry1 = QgsGeometry.fromPolygonXY([coordinates1])
geometry2 = QgsGeometry.fromPolygonXY([coordinates2])

layer1 = QgsVectorLayer( f"?query=SELECT ST_GeomFromText('{geometry1.asWkt()}')", "vlayer1", "virtual" )
layer2 = QgsVectorLayer( f"?query=SELECT ST_GeomFromText('{geometry2.asWkt()}')", "vlayer2", "virtual" )

result = processing.runAndLoadResults("native:difference",
                        {'INPUT': layer1, # <- QgsVectorLayer
                         'OVERLAY': layer2, # <- QgsVectorLayer
                         'OUTPUT':'memory:'})

If it is not mandatory to use the "Difference" tool one can also try this:

coordinates1 = [QgsPointXY(20, 30), QgsPointXY(30, 30), QgsPointXY(30, 20), QgsPointXY(20, 20)]
coordinates2 = [QgsPointXY(25, 35), QgsPointXY(35, 35), QgsPointXY(35, 25), QgsPointXY(25, 25)]

geometry1 = QgsGeometry.fromPolygonXY([coordinates1])
geometry2 = QgsGeometry.fromPolygonXY([coordinates2])
                
difference_geometry = geometry1.difference(geometry2)

result = QgsVectorLayer( f"?query=SELECT ST_GeomFromText('{difference_geometry.asWkt()}')", "result", "virtual" )

QgsProject.instance().addMapLayer(result)

References:

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.