Skip to content

Commit 8c73bcb

Browse files
committed
[FEATURE] Port CheckValidity alg to new API
Also make outputs optional from the alg - now you can select which outputs you need for your model!
1 parent 6b55300 commit 8c73bcb

File tree

3 files changed

+69
-70
lines changed

3 files changed

+69
-70
lines changed

python/plugins/processing/algs/qgis/BasicStatistics.py

+6
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ def calcNumericStats(self, features, feedback, field, count):
158158
total = 100.0 / float(count)
159159
stat = QgsStatisticalSummary()
160160
for current, ft in enumerate(features):
161+
if feedback.isCanceled():
162+
break
161163
stat.addVariant(ft[field.name()])
162164
feedback.setProgress(int(current * total))
163165
stat.finalize()
@@ -205,6 +207,8 @@ def calcStringStats(self, features, feedback, field, count):
205207
total = 100.0 / float(count)
206208
stat = QgsStringStatisticalSummary()
207209
for current, ft in enumerate(features):
210+
if feedback.isCanceled():
211+
break
208212
stat.addValue(ft[field.name()])
209213
feedback.setProgress(int(current * total))
210214
stat.finalize()
@@ -235,6 +239,8 @@ def calcDateTimeStats(self, features, feedback, field, count):
235239
total = 100.0 / float(count)
236240
stat = QgsDateTimeStatisticalSummary()
237241
for current, ft in enumerate(features):
242+
if feedback.isCanceled():
243+
break
238244
stat.addValue(ft[field.name()])
239245
feedback.setProgress(int(current * total))
240246
stat.finalize()

python/plugins/processing/algs/qgis/CheckValidity.py

+60-68
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,14 @@
3636
QgsField,
3737
QgsWkbTypes,
3838
QgsProcessingUtils,
39-
QgsFields)
39+
QgsFields,
40+
QgsProcessingParameterFeatureSource,
41+
QgsProcessingParameterEnum,
42+
QgsProcessingParameterFeatureSink,
43+
QgsProcessingOutputVectorLayer,
44+
QgsProcessingParameterDefinition
45+
)
4046
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
41-
from processing.core.parameters import ParameterVector
42-
from processing.core.parameters import ParameterSelection
43-
from processing.core.outputs import OutputVector
4447

4548
settings_method_key = "/qgis/digitizing/validate_geometries"
4649
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
@@ -66,26 +69,17 @@ def __init__(self):
6669
'QGIS',
6770
'GEOS']
6871

69-
self.addParameter(ParameterVector(
70-
self.INPUT_LAYER,
71-
self.tr('Input layer')))
72+
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT_LAYER,
73+
self.tr('Input layer')))
74+
self.addParameter(QgsProcessingParameterEnum(self.METHOD,
75+
self.tr('Method'), self.methods))
7276

73-
self.addParameter(ParameterSelection(
74-
self.METHOD,
75-
self.tr('Method'),
76-
self.methods))
77-
78-
self.addOutput(OutputVector(
79-
self.VALID_OUTPUT,
80-
self.tr('Valid output')))
81-
82-
self.addOutput(OutputVector(
83-
self.INVALID_OUTPUT,
84-
self.tr('Invalid output')))
85-
86-
self.addOutput(OutputVector(
87-
self.ERROR_OUTPUT,
88-
self.tr('Error output')))
77+
self.addParameter(QgsProcessingParameterFeatureSink(self.VALID_OUTPUT, self.tr('Valid output'), QgsProcessingParameterDefinition.TypeVectorAny, '', True))
78+
self.addOutput(QgsProcessingOutputVectorLayer(self.VALID_OUTPUT, self.tr('Valid output')))
79+
self.addParameter(QgsProcessingParameterFeatureSink(self.INVALID_OUTPUT, self.tr('Invalid output'), QgsProcessingParameterDefinition.TypeVectorAny, '', True))
80+
self.addOutput(QgsProcessingOutputVectorLayer(self.INVALID_OUTPUT, self.tr('Invalid output')))
81+
self.addParameter(QgsProcessingParameterFeatureSink(self.ERROR_OUTPUT, self.tr('Error output'), QgsProcessingParameterDefinition.TypeVectorAny, '', True))
82+
self.addOutput(QgsProcessingOutputVectorLayer(self.ERROR_OUTPUT, self.tr('Error output')))
8983

9084
def name(self):
9185
return 'checkvalidity'
@@ -94,51 +88,48 @@ def displayName(self):
9488
return self.tr('Check validity')
9589

9690
def processAlgorithm(self, parameters, context, feedback):
97-
settings = QgsSettings()
98-
initial_method_setting = settings.value(settings_method_key, 1)
99-
100-
method = self.getParameterValue(self.METHOD)
101-
if method != 0:
102-
settings.setValue(settings_method_key, method)
103-
try:
104-
self.doCheck(context, feedback)
105-
finally:
106-
settings.setValue(settings_method_key, initial_method_setting)
107-
108-
def doCheck(self, context, feedback):
109-
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
110-
111-
settings = QgsSettings()
112-
method = int(settings.value(settings_method_key, 1))
113-
114-
valid_output = self.getOutputFromName(self.VALID_OUTPUT)
115-
valid_fields = layer.fields()
116-
valid_writer = valid_output.getVectorWriter(valid_fields, layer.wkbType(), layer.crs(), context)
91+
method_param = self.parameterAsEnum(parameters, self.METHOD, context)
92+
if method_param == 0:
93+
settings = QgsSettings()
94+
method = int(settings.value(settings_method_key, 0)) - 1
95+
if method < 0:
96+
method = 0
97+
else:
98+
method = method_param - 1
99+
100+
results = self.doCheck(method, parameters, context, feedback)
101+
return results
102+
103+
def doCheck(self, method, parameters, context, feedback):
104+
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
105+
106+
(valid_output_sink, valid_output_dest_id) = self.parameterAsSink(parameters, self.VALID_OUTPUT, context,
107+
source.fields(), source.wkbType(), source.sourceCrs())
117108
valid_count = 0
118109

119-
invalid_output = self.getOutputFromName(self.INVALID_OUTPUT)
120-
invalid_fields = layer.fields()
121-
invalid_fields.append(QgsField('_errors',
122-
QVariant.String,
123-
255))
124-
invalid_writer = invalid_output.getVectorWriter(invalid_fields, layer.wkbType(), layer.crs(), context)
110+
invalid_fields = source.fields()
111+
invalid_fields.append(QgsField('_errors', QVariant.String, 'string', 255))
112+
(invalid_output_sink, invalid_output_dest_id) = self.parameterAsSink(parameters, self.INVALID_OUTPUT, context,
113+
invalid_fields, source.wkbType(), source.sourceCrs())
125114
invalid_count = 0
126115

127-
error_output = self.getOutputFromName(self.ERROR_OUTPUT)
128116
error_fields = QgsFields()
129-
error_fields.append(QgsField('message', QVariant.String, 255))
130-
error_writer = error_output.getVectorWriter(error_fields, QgsWkbTypes.Point, layer.crs(), context)
117+
error_fields.append(QgsField('message', QVariant.String, 'string', 255))
118+
(error_output_sink, error_output_dest_id) = self.parameterAsSink(parameters, self.ERROR_OUTPUT, context,
119+
error_fields, QgsWkbTypes.Point, source.sourceCrs())
131120
error_count = 0
132121

133-
features = QgsProcessingUtils.getFeatures(layer, context)
134-
total = 100.0 / QgsProcessingUtils.featureCount(layer, context)
122+
features = source.getFeatures()
123+
total = 100.0 / source.featureCount()
135124
for current, inFeat in enumerate(features):
125+
if feedback.isCanceled():
126+
break
136127
geom = inFeat.geometry()
137128
attrs = inFeat.attributes()
138129

139130
valid = True
140131
if not geom.isNull() and not geom.isEmpty():
141-
errors = list(geom.validateGeometry())
132+
errors = list(geom.validateGeometry(method))
142133
if errors:
143134
# QGIS method return a summary at the end
144135
if method == 1:
@@ -150,7 +141,8 @@ def doCheck(self, context, feedback):
150141
error_geom = QgsGeometry.fromPoint(error.where())
151142
errFeat.setGeometry(error_geom)
152143
errFeat.setAttributes([error.what()])
153-
error_writer.addFeature(errFeat)
144+
if error_output_sink:
145+
error_output_sink.addFeature(errFeat)
154146
error_count += 1
155147

156148
reasons.append(error.what())
@@ -165,22 +157,22 @@ def doCheck(self, context, feedback):
165157
outFeat.setAttributes(attrs)
166158

167159
if valid:
168-
valid_writer.addFeature(outFeat)
160+
if valid_output_sink:
161+
valid_output_sink.addFeature(outFeat)
169162
valid_count += 1
170163

171164
else:
172-
invalid_writer.addFeature(outFeat)
165+
if invalid_output_sink:
166+
invalid_output_sink.addFeature(outFeat)
173167
invalid_count += 1
174168

175169
feedback.setProgress(int(current * total))
176170

177-
del valid_writer
178-
del invalid_writer
179-
del error_writer
180-
181-
if valid_count != 0:
182-
context.addLayerToLoadOnCompletion(valid_output.value)
183-
if invalid_count != 0:
184-
context.addLayerToLoadOnCompletion(invalid_output.value)
185-
if error_count != 0:
186-
context.addLayerToLoadOnCompletion(error_output.value)
171+
results = {}
172+
if valid_output_sink:
173+
results[self.VALID_OUTPUT] = valid_output_dest_id
174+
if invalid_output_sink:
175+
results[self.INVALID_OUTPUT] = invalid_output_dest_id
176+
if error_output_sink:
177+
results[self.ERROR_OUTPUT] = error_output_dest_id
178+
return results

python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
# from .SplitLinesWithLines import SplitLinesWithLines
137137
# from .FieldsMapper import FieldsMapper
138138
# from .Datasources2Vrt import Datasources2Vrt
139-
# from .CheckValidity import CheckValidity
139+
from .CheckValidity import CheckValidity
140140
# from .OrientedMinimumBoundingBox import OrientedMinimumBoundingBox
141141
# from .Smooth import Smooth
142142
# from .ReverseLineDirection import ReverseLineDirection
@@ -237,7 +237,7 @@ def getAlgs(self):
237237
# SelectByExpression(), HypsometricCurves(),
238238
# SplitWithLines(), SplitLinesWithLines(), CreateConstantRaster(),
239239
# FieldsMapper(), SelectByAttributeSum(), Datasources2Vrt(),
240-
# CheckValidity(), OrientedMinimumBoundingBox(), Smooth(),
240+
# OrientedMinimumBoundingBox(), Smooth(),
241241
# ReverseLineDirection(), SpatialIndex(), DefineProjection(),
242242
# RectanglesOvalsDiamondsVariable(),
243243
# RectanglesOvalsDiamondsFixed(), MergeLines(),
@@ -265,6 +265,7 @@ def getAlgs(self):
265265
BasicStatisticsForField(),
266266
Boundary(),
267267
BoundingBox(),
268+
CheckValidity(),
268269
Clip(),
269270
DeleteColumn(),
270271
ExtentFromLayer()

0 commit comments

Comments
 (0)