Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
# -*- coding: utf-8 -*-
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessing,
QgsGeometry,
QgsProject,
QgsField,
QgsFields,
QgsFeature,
QgsPointXY,
QgsFeatureSink,
QgsProcessingException,
QgsProcessingAlgorithm,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink)
from qgis import processing
class CheckPointsAgainstAllVectorLayers(QgsProcessingAlgorithm):
POINT_INPUT = 'POINT_INPUT'
OUTPUT = 'OUTPUT'
def tr(self, string):
return QCoreApplication.translate('Processing', string)
def createInstance(self):
return CheckPointsAgainstAllVectorLayers()
def name(self):
return 'check_layer_membership'
def displayName(self):
return self.tr('Check Layer Membership')
def group(self):
return self.tr('Example scripts')
def groupId(self):
return 'examplescripts'
def shortHelpString(self):
return self.tr("Checks membership of an input point layer against all existing vector layers.")
def initAlgorithm(self, config=None):
self.addParameter(
QgsProcessingParameterFeatureSource(
self.POINT_INPUT,
self.tr('Input point layer'),
[QgsProcessing.TypeVectorPoint]
)
)
self.addParameter(
QgsProcessingParameterFeatureSink(
self.OUTPUT,
self.tr('Output layer')
)
)
def processAlgorithm(self, parameters, context, feedback):
# Get the input from the script parameters, and validate that it exists
point_source = self.parameterAsSource(
parameters,
self.POINT_INPUT,
context
)
if point_source is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.POINT_INPUT))
# We want to set up our output layer with a combination of fields:
# - all the fields from the point input source
# - one column for each vector layer in the project, so we can mark presence
vector_layers = []
# We want to get the vector layers out of the project, except for the point input layer
# (there's no point in checking whether the points contain themselves)
for key,layer in QgsProject.instance().mapLayers().items():
if(layer.__class__.__name__ == 'QgsVectorLayer'):
if(layer.name() != point_source.sourceName()):
vector_layers.append(layer)
else:
feedback.pushInfo('Skipping identity point layer: %s:' %point_source.sourceName())
# Combine these together into a QgsFields object
output_fields = QgsFields(point_source.fields())
for layer in vector_layers:
feedback.pushInfo('layer name: %s:' %layer.name())
field = QgsField(layer.name())
output_fields.append(field)
# Get the output from the parameters, and validate that it exists
(sink, dest_id) = self.parameterAsSink(
parameters,
self.OUTPUT,
context,
output_fields,
point_source.wkbType(),
point_source.sourceCrs()
)
if sink is None:
raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))
# Get and count the total number of points, so we can update progress as we go
points = point_source.getFeatures()
total = 100.0 / point_source.featureCount() if point_source.featureCount() else 0
for current, point in enumerate(points):
# This is super important. There is no good way to kill a QGIS script unless
# it stops itself.
if feedback.isCanceled():
break
feedback.setProgress(int(current * total))
# We want to start with the attributes from the original point, and add to it
attr_copy = point.attributes().copy()
# For each vector layer, check every feature. If any of them contain the point,
# break, mark it as present, and move on to the next layer.
for layer in vector_layers:
features = layer.getFeatures()
feature_match = False
geometry = point.geometry()
for feature in features:
if (feature.geometry().contains(geometry)):
feature_match = True
break
if(feature_match):
attr_copy.append(1)
else:
attr_copy.append(0)
# Copy the feature and throw it into the output layer.
output_feature = QgsFeature(point)
output_feature.setAttributes(attr_copy)
feedback.pushInfo('Point attributes: %s' % output_feature.attributes())
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
return {self.OUTPUT: dest_id}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.