I have multiple WFS that show the same features (streets) in different regions. I would like to write a model that extracts the features from the current map extent.
How do I let the model know, which layer has features in the current map extend, so I don't end up with a lot of empty layers?
Can the QGIS modeler check, if a layer has features in the current map extent?
2 Answers 2
You could use the "Extract/clip by extent" algorithm from the "Vector overlay" Toolbox on every layer (select the option "Use Current Map Canvas Extent" as Extent) and than count the features in the resulting output layer (If count > 0: Layer is in current map extent).
Another way to do it, is using a python script: Just iterate over your map layers and then check if they intersect with your current map extent:
canvas = iface.mapCanvas()
current_extent = canvas.extent()
layers = QgsProject.instance().mapLayers().values()
visible_layers = []
for layer in layers:
if layer.type() == QgsMapLayer.VectorLayer:
if any(feature.geometry().intersects(current_extent) for feature in layer.getFeatures()):
visible_layers.append(layer.name())
print(visible_layers)
I would also think in terms of PyQGIS combined with editing the model by hand. There is a useful method variantToSource()
from the QgsProcessingUtils
class. After its implementation, one gets a pure QgsProcessingFeatureSource
-object that possesses a hasFeatures
method.
On the other side, one could handle the empty QgsProcessingFeatureSource
as an empty dictionary i.e. {}
, however, the temporary output will still be added. Therefore I am suggesting adding the QgsProcessingException
in this case to ignore empty temporary outputs.
So, in the end, your model may look as follows:
"""
Model exported as python.
Name : filterwfs
Group : Models
With QGIS : 33408
"""
from qgis.core import (QgsProcessing,
QgsProcessingAlgorithm,
QgsProcessingMultiStepFeedback,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterFeatureSink,
QgsProcessingException,
QgsProcessingUtils)
from qgis.utils import iface
import processing
class Filterwfs(QgsProcessingAlgorithm):
def name(self):
return 'filterwfs'
def displayName(self):
return 'filterwfs'
def group(self):
return 'Models'
def groupId(self):
return 'Models'
def createInstance(self):
return Filterwfs()
def initAlgorithm(self, config=None):
self.addParameter(QgsProcessingParameterVectorLayer('input', 'INPUT', defaultValue=None))
self.addParameter(QgsProcessingParameterFeatureSink('output', 'OUTPUT', type=QgsProcessing.TypeVectorPolygon,
createByDefault=False, defaultValue=None))
def processAlgorithm(self, parameters, context, model_feedback):
# Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
# overall progress through the model
feedback = QgsProcessingMultiStepFeedback(1, model_feedback)
results = {}
outputs = {}
# Extract/clip by extent
alg_params = {
'INPUT': parameters['input'],
'EXTENT': iface.mapCanvas().extent(),
'CLIP': False,
'OUTPUT': parameters['output']
}
outputs['extract'] = processing.run("native:extractbyextent", alg_params, context=context, feedback=feedback,
is_child_algorithm=True)
results['Output'] = outputs['extract']['OUTPUT']
source = QgsProcessingUtils.variantToSource(results['Output'], context=context, fallbackValue=feedback)
if source.hasFeatures() > 0:
return results
else:
raise QgsProcessingException('Empty layer was not added.')
References:
- QGIS User Guide | Writing new Processing algorithms as Python scripts
- Input string value in QGIS 3 Processing Scripts
- Getting canvas' extent coordinates using PyQGIS
- Disable option "open output file after running algorithm"
- Ignoring empty output in QGIS Graphical modeler
- PyQGIS - Save processing output to temporary file which is discarded when QGIS is closed (on Windows)
- Unable to load layers created with Processing Toolbox PyQGIS 3
- QGIS 3 - Error "Field name is not set" after exporting graphical modeler to PyQGIS script
Explore related questions
See similar questions with these tags.