Last active
September 2, 2019 06:37
-
-
Save bpodgursky/e81b591d39870506dc13da1d5d24c0eb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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