mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Algorithms don't have to be split to prepare/process/postProcess
Since it's safe to evaluate parameters in background threads now, it's usually going to be ok to evaluate everything in the processAlgorithm step. This keeps the algorithm code as simple as possible, and will make porting faster. Note that the prepare/postProcess virtual methods still exist and can be used when an algorithm MUST do setup/cleanup work in the main thread.
This commit is contained in:
parent
f39b7a0c4c
commit
8a84e134cc
@ -259,7 +259,7 @@ class QgsProcessingAlgorithm
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
bool runPrepared( QgsProcessingContext &context, QgsProcessingFeedback *feedback );
|
||||
QVariantMap runPrepared( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback );
|
||||
%Docstring
|
||||
Runs the algorithm, which has been prepared by an earlier call to prepare().
|
||||
This method is safe to call from any thread. Returns true if the algorithm was successfully executed.
|
||||
@ -272,7 +272,7 @@ class QgsProcessingAlgorithm
|
||||
This method modifies the algorithm instance, so it is not safe to call
|
||||
on algorithms directly retrieved from QgsProcessingRegistry and QgsProcessingProvider. Instead, a copy
|
||||
of the algorithm should be created with clone() and prepare()/runPrepared() called on the copy.
|
||||
:rtype: bool
|
||||
:rtype: QVariantMap
|
||||
%End
|
||||
|
||||
QVariantMap postProcess( QgsProcessingContext &context, QgsProcessingFeedback *feedback );
|
||||
@ -374,7 +374,7 @@ class QgsProcessingAlgorithm
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
virtual bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) = 0 /VirtualErrorHandler=processing_exception_handler/;
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) = 0 /VirtualErrorHandler=processing_exception_handler/;
|
||||
%Docstring
|
||||
Runs the algorithm using the specified ``parameters``. Algorithms should implement
|
||||
their custom processing logic here.
|
||||
@ -389,10 +389,10 @@ class QgsProcessingAlgorithm
|
||||
values such as statistical calculations.
|
||||
.. seealso:: prepareAlgorithm()
|
||||
.. seealso:: postProcessAlgorithm()
|
||||
:rtype: bool
|
||||
:rtype: QVariantMap
|
||||
%End
|
||||
|
||||
virtual QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) = 0 /VirtualErrorHandler=processing_exception_handler/;
|
||||
virtual QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) /VirtualErrorHandler=processing_exception_handler/;
|
||||
%Docstring
|
||||
Allows the algorithm to perform any required cleanup tasks. The returned variant map
|
||||
includes the results evaluated by the algorithm. These may be output layer references, or calculated
|
||||
|
@ -835,11 +835,7 @@ Copies are protected to avoid slicing
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool prepareAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback );
|
||||
virtual bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback );
|
||||
|
||||
virtual QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback );
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback );
|
||||
|
||||
|
||||
};
|
||||
|
@ -74,38 +74,28 @@ class AddTableField(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT_LAYER, self.tr('Added')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT_LAYER, self.tr('Added')))
|
||||
|
||||
self.source = None
|
||||
self.fieldType = None
|
||||
self.fieldLength = None
|
||||
self.fieldName = None
|
||||
self.fieldPrecision = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'addfieldtoattributestable'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Add field to attributes table')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
|
||||
self.fieldType = self.parameterAsEnum(parameters, self.FIELD_TYPE, context)
|
||||
self.fieldName = self.parameterAsString(parameters, self.FIELD_NAME, context)
|
||||
self.fieldLength = self.parameterAsInt(parameters, self.FIELD_LENGTH, context)
|
||||
self.fieldPrecision = self.parameterAsInt(parameters, self.FIELD_PRECISION, context)
|
||||
fieldType = self.parameterAsEnum(parameters, self.FIELD_TYPE, context)
|
||||
fieldName = self.parameterAsString(parameters, self.FIELD_NAME, context)
|
||||
fieldLength = self.parameterAsInt(parameters, self.FIELD_LENGTH, context)
|
||||
fieldPrecision = self.parameterAsInt(parameters, self.FIELD_PRECISION, context)
|
||||
|
||||
fields = self.source.fields()
|
||||
fields.append(QgsField(self.fieldName, self.TYPES[self.fieldType], '',
|
||||
self.fieldLength, self.fieldPrecision))
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
fields, self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
fields = source.fields()
|
||||
fields.append(QgsField(fieldName, self.TYPES[fieldType], '',
|
||||
fieldLength, fieldPrecision))
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
fields, source.wkbType(), source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
@ -116,10 +106,7 @@ class AddTableField(QgisAlgorithm):
|
||||
attributes.append(None)
|
||||
output_feature.setAttributes(attributes)
|
||||
|
||||
self.sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT_LAYER: self.dest_id}
|
||||
return {self.OUTPUT_LAYER: dest_id}
|
||||
|
@ -68,30 +68,22 @@ class Aspect(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterRasterOutput(self.OUTPUT, self.tr('Aspect')))
|
||||
self.addOutput(QgsProcessingOutputRasterLayer(self.OUTPUT, self.tr('Aspect')))
|
||||
|
||||
self.inputFile = None
|
||||
self.outputFile = None
|
||||
self.outputFormat = None
|
||||
self.zFactor = None
|
||||
|
||||
def name(self):
|
||||
return 'aspect'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Aspect')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.inputFile = exportRasterLayer(self.parameterAsRasterLayer(parameters, self.INPUT, context))
|
||||
self.zFactor = self.parameterAsDouble(parameters, self.Z_FACTOR, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
inputFile = exportRasterLayer(self.parameterAsRasterLayer(parameters, self.INPUT, context))
|
||||
zFactor = self.parameterAsDouble(parameters, self.Z_FACTOR, context)
|
||||
|
||||
self.outputFile = self.parameterAsRasterOutputLayer(parameters, self.OUTPUT, context)
|
||||
outputFile = self.parameterAsRasterOutputLayer(parameters, self.OUTPUT, context)
|
||||
|
||||
self.outputFormat = raster.formatShortNameFromFileName(self.outputFile)
|
||||
return True
|
||||
outputFormat = raster.formatShortNameFromFileName(outputFile)
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
aspect = QgsAspectFilter(self.inputFile, self.outputFile, self.outputFormat)
|
||||
aspect.setZFactor(self.zFactor)
|
||||
return aspect.processRaster(feedback) == 0
|
||||
aspect = QgsAspectFilter(inputFile, outputFile, outputFormat)
|
||||
aspect.setZFactor(zFactor)
|
||||
aspect.processRaster(feedback)
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.outputFile}
|
||||
return {self.OUTPUT: outputFile}
|
||||
|
@ -51,10 +51,6 @@ class AutoincrementalField(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Incremented')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Incremented')))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def group(self):
|
||||
return self.tr('Vector table tools')
|
||||
|
||||
@ -64,18 +60,16 @@ class AutoincrementalField(QgisAlgorithm):
|
||||
def displayName(self):
|
||||
return self.tr('Add autoincremental field')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
fields = self.source.fields()
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
fields = source.fields()
|
||||
fields.append(QgsField('AUTO', QVariant.Int))
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, source.wkbType(), source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
@ -85,9 +79,7 @@ class AutoincrementalField(QgisAlgorithm):
|
||||
attributes.append(current)
|
||||
output_feature.setAttributes(attributes)
|
||||
|
||||
self.sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -119,52 +119,42 @@ class BasicStatisticsForField(QgisAlgorithm):
|
||||
self.addOutput(QgsProcessingOutputNumber(self.THIRDQUARTILE, self.tr('Third quartile')))
|
||||
self.addOutput(QgsProcessingOutputNumber(self.IQR, self.tr('Interquartile Range (IQR)')))
|
||||
|
||||
self.source = None
|
||||
self.field = None
|
||||
self.field_name = None
|
||||
self.output_file = None
|
||||
self.results = {}
|
||||
|
||||
def name(self):
|
||||
return 'basicstatisticsforfields'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Basic statistics for fields')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
self.field_name = self.parameterAsString(parameters, self.FIELD_NAME, context)
|
||||
self.field = self.source.fields().at(self.source.fields().lookupField(self.field_name))
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
field_name = self.parameterAsString(parameters, self.FIELD_NAME, context)
|
||||
field = source.fields().at(source.fields().lookupField(field_name))
|
||||
|
||||
self.output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context)
|
||||
return True
|
||||
output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context)
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry).setSubsetOfAttributes([self.field_name], self.source.fields())
|
||||
features = self.source.getFeatures(request)
|
||||
count = self.source.featureCount()
|
||||
request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry).setSubsetOfAttributes([field_name], source.fields())
|
||||
features = source.getFeatures(request)
|
||||
count = source.featureCount()
|
||||
|
||||
data = []
|
||||
data.append(self.tr('Analyzed field: {}').format(self.field_name))
|
||||
data.append(self.tr('Analyzed field: {}').format(field_name))
|
||||
results = {}
|
||||
|
||||
if self.field.isNumeric():
|
||||
d, self.results = self.calcNumericStats(features, feedback, self.field, count)
|
||||
if field.isNumeric():
|
||||
d, results = self.calcNumericStats(features, feedback, field, count)
|
||||
data.extend(d)
|
||||
elif self.field.type() in (QVariant.Date, QVariant.Time, QVariant.DateTime):
|
||||
d, self.results = self.calcDateTimeStats(features, feedback, self.field, count)
|
||||
elif field.type() in (QVariant.Date, QVariant.Time, QVariant.DateTime):
|
||||
d, results = self.calcDateTimeStats(features, feedback, field, count)
|
||||
data.extend(d)
|
||||
else:
|
||||
d, self.results = self.calcStringStats(features, feedback, self.field, count)
|
||||
d, results = self.calcStringStats(features, feedback, field, count)
|
||||
data.extend(d)
|
||||
|
||||
if self.output_file:
|
||||
self.createHTML(self.output_file, data)
|
||||
self.results[self.OUTPUT_HTML_FILE] = self.output_file
|
||||
if output_file:
|
||||
self.createHTML(output_file, data)
|
||||
results[self.OUTPUT_HTML_FILE] = output_file
|
||||
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return self.results
|
||||
return results
|
||||
|
||||
def calcNumericStats(self, features, feedback, field, count):
|
||||
total = 100.0 / count if count else 0
|
||||
|
@ -58,10 +58,6 @@ class Boundary(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT_LAYER, self.tr('Boundary')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT_LAYER, self.tr("Boundaries")))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def icon(self):
|
||||
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'convex_hull.png'))
|
||||
|
||||
@ -74,11 +70,10 @@ class Boundary(QgisAlgorithm):
|
||||
def displayName(self):
|
||||
return self.tr('Boundary')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
|
||||
input_wkb = self.source.wkbType()
|
||||
output_wkb = None
|
||||
input_wkb = source.wkbType()
|
||||
if QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.LineGeometry:
|
||||
output_wkb = QgsWkbTypes.MultiPoint
|
||||
elif QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.PolygonGeometry:
|
||||
@ -88,13 +83,11 @@ class Boundary(QgisAlgorithm):
|
||||
if QgsWkbTypes.hasM(input_wkb):
|
||||
output_wkb = QgsWkbTypes.addM(output_wkb)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
self.source.fields(), output_wkb, self.source.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
source.fields(), output_wkb, source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
@ -109,9 +102,7 @@ class Boundary(QgisAlgorithm):
|
||||
|
||||
output_feature.setGeometry(output_geometry)
|
||||
|
||||
self.sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT_LAYER: self.dest_id}
|
||||
return {self.OUTPUT_LAYER: dest_id}
|
||||
|
@ -66,26 +66,20 @@ class BoundingBox(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT_LAYER, self.tr('Bounds'), QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT_LAYER, self.tr("Bounds")))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'boundingboxes'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Bounding boxes')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
self.source.fields(), QgsWkbTypes.Polygon, self.source.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
source.fields(), QgsWkbTypes.Polygon, source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
@ -100,9 +94,7 @@ class BoundingBox(QgisAlgorithm):
|
||||
|
||||
output_feature.setGeometry(output_geometry)
|
||||
|
||||
self.sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT_LAYER: self.dest_id}
|
||||
return {self.OUTPUT_LAYER: dest_id}
|
||||
|
@ -93,60 +93,46 @@ class CheckValidity(QgisAlgorithm):
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.ERROR_OUTPUT, self.tr('Error output')))
|
||||
self.addOutput(QgsProcessingOutputNumber(self.ERROR_COUNT, self.tr('Count of errors')))
|
||||
|
||||
self.method = None
|
||||
self.source = None
|
||||
self.valid_output_sink = None
|
||||
self.valid_output_dest_id = None
|
||||
self.valid_count = 0
|
||||
self.invalid_output_sink = None
|
||||
self.invalid_output_dest_id = None
|
||||
self.invalid_count = 0
|
||||
self.error_output_sink = None
|
||||
self.error_output_dest_id = None
|
||||
self.error_count = 0
|
||||
|
||||
def name(self):
|
||||
return 'checkvalidity'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Check validity')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
method_param = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
if method_param == 0:
|
||||
settings = QgsSettings()
|
||||
self.method = int(settings.value(settings_method_key, 0)) - 1
|
||||
if self.method < 0:
|
||||
self.method = 0
|
||||
method = int(settings.value(settings_method_key, 0)) - 1
|
||||
if method < 0:
|
||||
method = 0
|
||||
else:
|
||||
self.method = method_param - 1
|
||||
method = method_param - 1
|
||||
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
results = self.doCheck(method, parameters, context, feedback)
|
||||
return results
|
||||
|
||||
(self.valid_output_sink, self.valid_output_dest_id) = self.parameterAsSink(parameters, self.VALID_OUTPUT,
|
||||
context,
|
||||
self.source.fields(),
|
||||
self.source.wkbType(),
|
||||
self.source.sourceCrs())
|
||||
def doCheck(self, method, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
|
||||
invalid_fields = self.source.fields()
|
||||
(valid_output_sink, valid_output_dest_id) = self.parameterAsSink(parameters, self.VALID_OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
valid_count = 0
|
||||
|
||||
invalid_fields = source.fields()
|
||||
invalid_fields.append(QgsField('_errors', QVariant.String, 'string', 255))
|
||||
(self.invalid_output_sink, self.invalid_output_dest_id) = self.parameterAsSink(parameters, self.INVALID_OUTPUT,
|
||||
context,
|
||||
invalid_fields,
|
||||
self.source.wkbType(),
|
||||
self.source.sourceCrs())
|
||||
(invalid_output_sink, invalid_output_dest_id) = self.parameterAsSink(parameters, self.INVALID_OUTPUT, context,
|
||||
invalid_fields, source.wkbType(), source.sourceCrs())
|
||||
invalid_count = 0
|
||||
|
||||
error_fields = QgsFields()
|
||||
error_fields.append(QgsField('message', QVariant.String, 'string', 255))
|
||||
(self.error_output_sink, self.error_output_dest_id) = self.parameterAsSink(parameters, self.ERROR_OUTPUT, context,
|
||||
error_fields, QgsWkbTypes.Point,
|
||||
self.source.sourceCrs())
|
||||
return True
|
||||
(error_output_sink, error_output_dest_id) = self.parameterAsSink(parameters, self.ERROR_OUTPUT, context,
|
||||
error_fields, QgsWkbTypes.Point, source.sourceCrs())
|
||||
error_count = 0
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures(QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures(QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
for current, inFeat in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
@ -155,10 +141,10 @@ class CheckValidity(QgisAlgorithm):
|
||||
|
||||
valid = True
|
||||
if not geom.isNull() and not geom.isEmpty():
|
||||
errors = list(geom.validateGeometry(self.method))
|
||||
errors = list(geom.validateGeometry(method))
|
||||
if errors:
|
||||
# QGIS method return a summary at the end
|
||||
if self.method == 1:
|
||||
if method == 1:
|
||||
errors.pop()
|
||||
valid = False
|
||||
reasons = []
|
||||
@ -167,9 +153,9 @@ class CheckValidity(QgisAlgorithm):
|
||||
error_geom = QgsGeometry.fromPoint(error.where())
|
||||
errFeat.setGeometry(error_geom)
|
||||
errFeat.setAttributes([error.what()])
|
||||
if self.error_output_sink:
|
||||
self.error_output_sink.addFeature(errFeat, QgsFeatureSink.FastInsert)
|
||||
self.error_count += 1
|
||||
if error_output_sink:
|
||||
error_output_sink.addFeature(errFeat, QgsFeatureSink.FastInsert)
|
||||
error_count += 1
|
||||
|
||||
reasons.append(error.what())
|
||||
|
||||
@ -183,28 +169,26 @@ class CheckValidity(QgisAlgorithm):
|
||||
outFeat.setAttributes(attrs)
|
||||
|
||||
if valid:
|
||||
if self.valid_output_sink:
|
||||
self.valid_output_sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
self.valid_count += 1
|
||||
if valid_output_sink:
|
||||
valid_output_sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
valid_count += 1
|
||||
|
||||
else:
|
||||
if self.invalid_output_sink:
|
||||
self.invalid_output_sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
self.invalid_count += 1
|
||||
if invalid_output_sink:
|
||||
invalid_output_sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
invalid_count += 1
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
results = {
|
||||
self.VALID_COUNT: self.valid_count,
|
||||
self.INVALID_COUNT: self.invalid_count,
|
||||
self.ERROR_COUNT: self.error_count
|
||||
self.VALID_COUNT: valid_count,
|
||||
self.INVALID_COUNT: invalid_count,
|
||||
self.ERROR_COUNT: error_count
|
||||
}
|
||||
if self.valid_output_sink:
|
||||
results[self.VALID_OUTPUT] = self.valid_output_dest_id
|
||||
if self.invalid_output_sink:
|
||||
results[self.INVALID_OUTPUT] = self.invalid_output_dest_id
|
||||
if self.error_output_sink:
|
||||
results[self.ERROR_OUTPUT] = self.error_output_dest_id
|
||||
if valid_output_sink:
|
||||
results[self.VALID_OUTPUT] = valid_output_dest_id
|
||||
if invalid_output_sink:
|
||||
results[self.INVALID_OUTPUT] = invalid_output_dest_id
|
||||
if error_output_sink:
|
||||
results[self.ERROR_OUTPUT] = error_output_dest_id
|
||||
return results
|
||||
|
@ -53,35 +53,27 @@ class CreateAttributeIndex(QgisAlgorithm):
|
||||
self.tr('Attribute to index'), None, self.INPUT))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Indexed layer')))
|
||||
|
||||
self.layer = None
|
||||
self.field = None
|
||||
|
||||
def name(self):
|
||||
return 'createattributeindex'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Create attribute index')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
self.field = self.parameterAsString(parameters, self.FIELD, context)
|
||||
return True
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
field = self.parameterAsString(parameters, self.FIELD, context)
|
||||
provider = layer.dataProvider()
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
provider = self.layer.dataProvider()
|
||||
|
||||
field_index = self.layer.fields().lookupField(self.field)
|
||||
if field_index < 0 or self.layer.fields().fieldOrigin(field_index) != QgsFields.OriginProvider:
|
||||
feedback.pushInfo(self.tr('Can not create attribute index on "{}"').format(self.field))
|
||||
field_index = layer.fields().lookupField(field)
|
||||
if field_index < 0 or layer.fields().fieldOrigin(field_index) != QgsFields.OriginProvider:
|
||||
feedback.pushInfo(self.tr('Can not create attribute index on "{}"').format(field))
|
||||
else:
|
||||
provider_index = self.layer.fields().fieldOriginIndex(field_index)
|
||||
provider_index = layer.fields().fieldOriginIndex(field_index)
|
||||
if provider.capabilities() & QgsVectorDataProvider.CreateAttributeIndex:
|
||||
if not provider.createAttributeIndex(provider_index):
|
||||
feedback.pushInfo(self.tr('Could not create attribute index'))
|
||||
else:
|
||||
feedback.pushInfo(self.tr("Layer's data provider does not support "
|
||||
"creating attribute indexes"))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.layer.id()}
|
||||
return {self.OUTPUT: layer.id()}
|
||||
|
@ -58,56 +58,46 @@ class DeleteColumn(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Output layer')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Output layer")))
|
||||
|
||||
self.source = None
|
||||
self.fields_to_delete = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
self.field_indices = []
|
||||
|
||||
def name(self):
|
||||
return 'deletecolumn'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Drop field(s)')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.fields_to_delete = self.parameterAsFields(parameters, self.COLUMNS, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
fields_to_delete = self.parameterAsFields(parameters, self.COLUMNS, context)
|
||||
|
||||
fields = self.source.fields()
|
||||
fields = source.fields()
|
||||
field_indices = []
|
||||
# loop through twice - first we need to build up a list of original attribute indices
|
||||
for f in self.fields_to_delete:
|
||||
for f in fields_to_delete:
|
||||
index = fields.lookupField(f)
|
||||
self.field_indices.append(index)
|
||||
field_indices.append(index)
|
||||
|
||||
# important - make sure we remove from the end so we aren't changing used indices as we go
|
||||
self.field_indices.sort(reverse=True)
|
||||
field_indices.sort(reverse=True)
|
||||
|
||||
# this second time we make a cleaned version of the fields
|
||||
for index in self.field_indices:
|
||||
for index in field_indices:
|
||||
fields.remove(index)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, source.wkbType(), source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
attributes = f.attributes()
|
||||
for index in self.field_indices:
|
||||
for index in field_indices:
|
||||
del attributes[index]
|
||||
f.setAttributes(attributes)
|
||||
self.sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -58,40 +58,31 @@ class DeleteHoles(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Cleaned'), QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Cleaned'), QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||
|
||||
self.source = None
|
||||
self.min_area = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'deleteholes'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Delete holes')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.min_area = self.parameterAsDouble(parameters, self.MIN_AREA, context)
|
||||
if self.min_area == 0.0:
|
||||
self.min_area = -1.0
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
min_area = self.parameterAsDouble(parameters, self.MIN_AREA, context)
|
||||
if min_area == 0.0:
|
||||
min_area = -1.0
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
if f.hasGeometry():
|
||||
f.setGeometry(f.geometry().removeInteriorRings(self.min_area))
|
||||
self.sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
f.setGeometry(f.geometry().removeInteriorRings(min_area))
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -63,28 +63,21 @@ class DensifyGeometries(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Densified')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Densified')))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.vertices = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'densifygeometries'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Densify geometries')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.vertices = self.parameterAsInt(parameters, self.VERTICES, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
vertices = self.parameterAsInt(parameters, self.VERTICES, context)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
@ -92,11 +85,9 @@ class DensifyGeometries(QgisAlgorithm):
|
||||
|
||||
feature = f
|
||||
if feature.hasGeometry():
|
||||
new_geometry = feature.geometry().densifyByCount(self.vertices)
|
||||
new_geometry = feature.geometry().densifyByCount(vertices)
|
||||
feature.setGeometry(new_geometry)
|
||||
self.sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -61,40 +61,31 @@ class DensifyGeometriesInterval(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Densified')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Densified')))
|
||||
|
||||
self.source = None
|
||||
self.interval = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'densifygeometriesgivenaninterval'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Densify geometries given an interval')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.interval = self.parameterAsDouble(parameters, self.INTERVAL, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
interval = self.parameterAsDouble(parameters, self.INTERVAL, context)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
feature = f
|
||||
if feature.hasGeometry():
|
||||
new_geometry = feature.geometry().densifyByDistance(float(self.interval))
|
||||
new_geometry = feature.geometry().densifyByDistance(float(interval))
|
||||
feature.setGeometry(new_geometry)
|
||||
self.sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -55,36 +55,27 @@ class DropGeometry(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Dropped geometry')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Dropped geometry")))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'dropgeometries'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Drop geometries')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())
|
||||
return True
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
|
||||
features = self.source.getFeatures(request)
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures(request)
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
input_feature.clearGeometry()
|
||||
self.sink.addFeature(input_feature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(input_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -79,20 +79,15 @@ class ExtentFromLayer(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Extent')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Extent"), QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||
|
||||
self.source = None
|
||||
self.byFeature = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'polygonfromlayerextent'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Polygon from layer extent')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
self.byFeature = self.parameterAsBool(parameters, self.BY_FEATURE, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
byFeature = self.parameterAsBool(parameters, self.BY_FEATURE, context)
|
||||
|
||||
fields = QgsFields()
|
||||
fields.append(QgsField('MINX', QVariant.Double))
|
||||
@ -106,19 +101,15 @@ class ExtentFromLayer(QgisAlgorithm):
|
||||
fields.append(QgsField('HEIGHT', QVariant.Double))
|
||||
fields.append(QgsField('WIDTH', QVariant.Double))
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.Polygon, self.source.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.Polygon, source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
if self.byFeature:
|
||||
self.featureExtent(self.source, context, self.sink, feedback)
|
||||
if byFeature:
|
||||
self.featureExtent(source, context, sink, feedback)
|
||||
else:
|
||||
self.layerExtent(self.source, self.sink, feedback)
|
||||
return True
|
||||
self.layerExtent(source, sink, feedback)
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
||||
def layerExtent(self, source, sink, feedback):
|
||||
rect = source.sourceExtent()
|
||||
|
@ -55,26 +55,20 @@ class FixGeometry(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Fixed geometries')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Fixed geometries")))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'fixgeometries'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Fix geometries')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), QgsWkbTypes.multiType(self.source.wkbType()), self.source.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures(QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures(QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
for current, inputFeature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
@ -92,7 +86,7 @@ class FixGeometry(QgisAlgorithm):
|
||||
try:
|
||||
g.convertToMultiType()
|
||||
outputFeature.setGeometry(QgsGeometry(g))
|
||||
self.sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
|
||||
except:
|
||||
pass
|
||||
feedback.setProgress(int(current * total))
|
||||
@ -101,9 +95,7 @@ class FixGeometry(QgisAlgorithm):
|
||||
outputGeometry.convertToMultiType()
|
||||
outputFeature.setGeometry(outputGeometry)
|
||||
|
||||
self.sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -102,52 +102,41 @@ class GridPolygon(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Grid')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Grid'), QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||
|
||||
self.idx = None
|
||||
self.hSpacing = None
|
||||
self.vSpacing = None
|
||||
self.hOverlay = None
|
||||
self.vOverlay = None
|
||||
self.width = None
|
||||
self.height = None
|
||||
self.originX = None
|
||||
self.originY = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'creategridpolygon'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Create grid (polygon)')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.idx = self.parameterAsEnum(parameters, self.TYPE, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
idx = self.parameterAsEnum(parameters, self.TYPE, context)
|
||||
|
||||
self.hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context)
|
||||
self.vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context)
|
||||
self.hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context)
|
||||
self.vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context)
|
||||
hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context)
|
||||
vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context)
|
||||
hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context)
|
||||
vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context)
|
||||
|
||||
bbox = self.parameterAsExtent(parameters, self.EXTENT, context)
|
||||
crs = self.parameterAsCrs(parameters, self.CRS, context)
|
||||
self.width = bbox.width()
|
||||
self.height = bbox.height()
|
||||
self.originX = bbox.xMinimum()
|
||||
self.originY = bbox.yMaximum()
|
||||
|
||||
if self.hSpacing <= 0 or self.vSpacing <= 0:
|
||||
width = bbox.width()
|
||||
height = bbox.height()
|
||||
originX = bbox.xMinimum()
|
||||
originY = bbox.yMaximum()
|
||||
|
||||
if hSpacing <= 0 or vSpacing <= 0:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Invalid grid spacing: {0}/{1}').format(self.hSpacing, self.vSpacing))
|
||||
self.tr('Invalid grid spacing: {0}/{1}').format(hSpacing, vSpacing))
|
||||
|
||||
if self.width < self.hSpacing:
|
||||
if width < hSpacing:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Horizontal spacing is too small for the covered area'))
|
||||
|
||||
if self.hSpacing <= self.hOverlay or self.vSpacing <= self.vOverlay:
|
||||
if hSpacing <= hOverlay or vSpacing <= vOverlay:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Invalid overlay: {0}/{1}').format(self.hOverlay, self.vOverlay))
|
||||
self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay))
|
||||
|
||||
if self.height < self.vSpacing:
|
||||
if height < vSpacing:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Vertical spacing is too small for the covered area'))
|
||||
|
||||
@ -158,24 +147,20 @@ class GridPolygon(QgisAlgorithm):
|
||||
fields.append(QgsField('bottom', QVariant.Double, '', 24, 16))
|
||||
fields.append(QgsField('id', QVariant.Int, '', 10, 0))
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.Polygon, crs)
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.Polygon, crs)
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
if self.idx == 0:
|
||||
if idx == 0:
|
||||
self._rectangleGrid(
|
||||
self.sink, self.width, self.height, self.originX, self.originY, self.hSpacing, self.vSpacing, self.hOverlay, self.vOverlay, feedback)
|
||||
elif self.idx == 1:
|
||||
sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
|
||||
elif idx == 1:
|
||||
self._diamondGrid(
|
||||
self.sink, self.width, self.height, self.originX, self.originY, self.hSpacing, self.vSpacing, self.hOverlay, self.vOverlay, feedback)
|
||||
elif self.idx == 2:
|
||||
sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
|
||||
elif idx == 2:
|
||||
self._hexagonGrid(
|
||||
self.sink, self.width, self.height, self.originX, self.originY, self.hSpacing, self.vSpacing, self.hOverlay, self.vOverlay, feedback)
|
||||
return True
|
||||
sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
||||
def _rectangleGrid(self, sink, width, height, originX, originY,
|
||||
hSpacing, vSpacing, hOverlay, vOverlay, feedback):
|
||||
|
@ -27,7 +27,9 @@ __revision__ = '$Format:%H$'
|
||||
|
||||
from qgis.core import (QgsVectorLayerExporter,
|
||||
QgsSettings,
|
||||
QgsApplication,
|
||||
QgsFeatureSink,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterString,
|
||||
QgsProcessingParameterField,
|
||||
@ -106,86 +108,70 @@ class ImportIntoPostGIS(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterBoolean(self.FORCE_SINGLEPART,
|
||||
self.tr('Create single-part geometries instead of multi-part'), False))
|
||||
|
||||
self.db = None
|
||||
self.schema = None
|
||||
self.overwrite = None
|
||||
self.createIndex = None
|
||||
self.convertLowerCase = None
|
||||
self.dropStringLength = None
|
||||
self.forceSinglePart = None
|
||||
self.primaryKeyField = None
|
||||
self.encoding = None
|
||||
self.source = None
|
||||
self.table = None
|
||||
self.providerName = None
|
||||
self.geomColumn = None
|
||||
|
||||
def name(self):
|
||||
return 'importintopostgis'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Import into PostGIS')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
connection = self.parameterAsString(parameters, self.DATABASE, context)
|
||||
self.db = postgis.GeoDB.from_name(connection)
|
||||
db = postgis.GeoDB.from_name(connection)
|
||||
|
||||
self.schema = self.parameterAsString(parameters, self.SCHEMA, context)
|
||||
self.overwrite = self.parameterAsBool(parameters, self.OVERWRITE, context)
|
||||
self.createIndex = self.parameterAsBool(parameters, self.CREATEINDEX, context)
|
||||
self.convertLowerCase = self.parameterAsBool(parameters, self.LOWERCASE_NAMES, context)
|
||||
self.dropStringLength = self.parameterAsBool(parameters, self.DROP_STRING_LENGTH, context)
|
||||
self.forceSinglePart = self.parameterAsBool(parameters, self.FORCE_SINGLEPART, context)
|
||||
self.primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id'
|
||||
self.encoding = self.parameterAsString(parameters, self.ENCODING, context)
|
||||
schema = self.parameterAsString(parameters, self.SCHEMA, context)
|
||||
overwrite = self.parameterAsBool(parameters, self.OVERWRITE, context)
|
||||
createIndex = self.parameterAsBool(parameters, self.CREATEINDEX, context)
|
||||
convertLowerCase = self.parameterAsBool(parameters, self.LOWERCASE_NAMES, context)
|
||||
dropStringLength = self.parameterAsBool(parameters, self.DROP_STRING_LENGTH, context)
|
||||
forceSinglePart = self.parameterAsBool(parameters, self.FORCE_SINGLEPART, context)
|
||||
primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id'
|
||||
encoding = self.parameterAsString(parameters, self.ENCODING, context)
|
||||
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
|
||||
self.table = self.parameterAsString(parameters, self.TABLENAME, context)
|
||||
if self.table:
|
||||
self.table.strip()
|
||||
if not self.table or self.table == '':
|
||||
self.table = self.source.sourceName()
|
||||
self.table = self.table.replace('.', '_')
|
||||
self.table = self.table.replace(' ', '').lower()[0:62]
|
||||
self.providerName = 'postgres'
|
||||
table = self.parameterAsString(parameters, self.TABLENAME, context)
|
||||
if table:
|
||||
table.strip()
|
||||
if not table or table == '':
|
||||
table = source.sourceName()
|
||||
table = table.replace('.', '_')
|
||||
table = table.replace(' ', '').lower()[0:62]
|
||||
providerName = 'postgres'
|
||||
|
||||
self.geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context)
|
||||
if not self.geomColumn:
|
||||
self.geomColumn = 'geom'
|
||||
return True
|
||||
geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context)
|
||||
if not geomColumn:
|
||||
geomColumn = 'geom'
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
options = {}
|
||||
if self.overwrite:
|
||||
if overwrite:
|
||||
options['overwrite'] = True
|
||||
if self.convertLowerCase:
|
||||
if convertLowerCase:
|
||||
options['lowercaseFieldNames'] = True
|
||||
self.geomColumn = self.geomColumn.lower()
|
||||
if self.dropStringLength:
|
||||
geomColumn = geomColumn.lower()
|
||||
if dropStringLength:
|
||||
options['dropStringConstraints'] = True
|
||||
if self.forceSinglePart:
|
||||
if forceSinglePart:
|
||||
options['forceSinglePartGeometryType'] = True
|
||||
|
||||
# Clear geometry column for non-geometry tables
|
||||
if self.source.wkbType() == QgsWkbTypes.NoGeometry:
|
||||
self.geomColumn = None
|
||||
if source.wkbType() == QgsWkbTypes.NoGeometry:
|
||||
geomColumn = None
|
||||
|
||||
uri = self.db.uri
|
||||
uri.setDataSource(self.schema, self.table, self.geomColumn, '', self.primaryKeyField)
|
||||
uri = db.uri
|
||||
uri.setDataSource(schema, table, geomColumn, '', primaryKeyField)
|
||||
|
||||
if self.encoding:
|
||||
options['fileEncoding'] = self.encoding
|
||||
if encoding:
|
||||
options['fileEncoding'] = encoding
|
||||
|
||||
exporter = QgsVectorLayerExporter(uri.uri(), self.providerName, self.source.fields(),
|
||||
self.source.wkbType(), self.source.sourceCrs(), self.overwrite, options)
|
||||
exporter = QgsVectorLayerExporter(uri.uri(), providerName, source.fields(),
|
||||
source.wkbType(), source.sourceCrs(), overwrite, options)
|
||||
|
||||
if exporter.errorCode() != QgsVectorLayerExporter.NoError:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error importing to PostGIS\n{0}').format(exporter.errorMessage()))
|
||||
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
@ -200,13 +186,11 @@ class ImportIntoPostGIS(QgisAlgorithm):
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error importing to PostGIS\n{0}').format(exporter.errorMessage()))
|
||||
|
||||
if self.geomColumn and self.createIndex:
|
||||
self.db.create_spatial_index(self.table, self.schema, self.geomColumn)
|
||||
if geomColumn and createIndex:
|
||||
db.create_spatial_index(table, schema, geomColumn)
|
||||
|
||||
self.db.vacuum_analyze(self.table, self.schema)
|
||||
return True
|
||||
db.vacuum_analyze(table, schema)
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {}
|
||||
|
||||
def dbConnectionNames(self):
|
||||
|
@ -71,26 +71,13 @@ class ImportIntoSpatialite(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterBoolean(self.DROP_STRING_LENGTH, self.tr('Drop length constraints on character fields'), False))
|
||||
self.addParameter(QgsProcessingParameterBoolean(self.FORCE_SINGLEPART, self.tr('Create single-part geometries instead of multi-part'), False))
|
||||
|
||||
self.db = None
|
||||
self.overwrite = None
|
||||
self.createIndex = None
|
||||
self.dropStringLength = None
|
||||
self.convertLowerCase = None
|
||||
self.forceSinglePart = None
|
||||
self.primaryKeyField = None
|
||||
self.encoding = None
|
||||
self.source = None
|
||||
self.table = None
|
||||
self.providerName = None
|
||||
self.geomColumn = None
|
||||
|
||||
def name(self):
|
||||
return 'importintospatialite'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Import into Spatialite')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
database = self.parameterAsVectorLayer(parameters, self.DATABASE, context)
|
||||
databaseuri = database.dataProvider().dataSourceUri()
|
||||
uri = QgsDataSourceUri(databaseuri)
|
||||
@ -98,64 +85,61 @@ class ImportIntoSpatialite(QgisAlgorithm):
|
||||
if '|layerid' in databaseuri:
|
||||
databaseuri = databaseuri[:databaseuri.find('|layerid')]
|
||||
uri = QgsDataSourceUri('dbname=\'%s\'' % (databaseuri))
|
||||
self.db = spatialite.GeoDB(uri)
|
||||
db = spatialite.GeoDB(uri)
|
||||
|
||||
self.overwrite = self.parameterAsBool(parameters, self.OVERWRITE, context)
|
||||
self.createIndex = self.parameterAsBool(parameters, self.CREATEINDEX, context)
|
||||
self.convertLowerCase = self.parameterAsBool(parameters, self.LOWERCASE_NAMES, context)
|
||||
self.dropStringLength = self.parameterAsBool(parameters, self.DROP_STRING_LENGTH, context)
|
||||
self.forceSinglePart = self.parameterAsBool(parameters, self.FORCE_SINGLEPART, context)
|
||||
self.primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id'
|
||||
self.encoding = self.parameterAsString(parameters, self.ENCODING, context)
|
||||
overwrite = self.parameterAsBool(parameters, self.OVERWRITE, context)
|
||||
createIndex = self.parameterAsBool(parameters, self.CREATEINDEX, context)
|
||||
convertLowerCase = self.parameterAsBool(parameters, self.LOWERCASE_NAMES, context)
|
||||
dropStringLength = self.parameterAsBool(parameters, self.DROP_STRING_LENGTH, context)
|
||||
forceSinglePart = self.parameterAsBool(parameters, self.FORCE_SINGLEPART, context)
|
||||
primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id'
|
||||
encoding = self.parameterAsString(parameters, self.ENCODING, context)
|
||||
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
|
||||
self.table = self.parameterAsString(parameters, self.TABLENAME, context)
|
||||
if self.table:
|
||||
self.table.strip()
|
||||
if not self.table or self.table == '':
|
||||
self.table = self.source.sourceName()
|
||||
self.table = self.table.replace('.', '_')
|
||||
self.table = self.table.replace(' ', '').lower()
|
||||
self.providerName = 'spatialite'
|
||||
table = self.parameterAsString(parameters, self.TABLENAME, context)
|
||||
if table:
|
||||
table.strip()
|
||||
if not table or table == '':
|
||||
table = source.sourceName()
|
||||
table = table.replace('.', '_')
|
||||
table = table.replace(' ', '').lower()
|
||||
providerName = 'spatialite'
|
||||
|
||||
self.geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context)
|
||||
if not self.geomColumn:
|
||||
self.geomColumn = 'geom'
|
||||
geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context)
|
||||
if not geomColumn:
|
||||
geomColumn = 'geom'
|
||||
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
options = {}
|
||||
if self.overwrite:
|
||||
if overwrite:
|
||||
options['overwrite'] = True
|
||||
if self.convertLowerCase:
|
||||
if convertLowerCase:
|
||||
options['lowercaseFieldNames'] = True
|
||||
self.geomColumn = self.geomColumn.lower()
|
||||
if self.dropStringLength:
|
||||
geomColumn = geomColumn.lower()
|
||||
if dropStringLength:
|
||||
options['dropStringConstraints'] = True
|
||||
if self.forceSinglePart:
|
||||
if forceSinglePart:
|
||||
options['forceSinglePartGeometryType'] = True
|
||||
|
||||
# Clear geometry column for non-geometry tables
|
||||
if self.source.wkbType() == QgsWkbTypes.NoGeometry:
|
||||
self.geomColumn = None
|
||||
if source.wkbType() == QgsWkbTypes.NoGeometry:
|
||||
geomColumn = None
|
||||
|
||||
uri = self.db.uri
|
||||
uri.setDataSource('', self.table, self.geomColumn, '', self.primaryKeyField)
|
||||
uri = db.uri
|
||||
uri.setDataSource('', table, geomColumn, '', primaryKeyField)
|
||||
|
||||
if self.encoding:
|
||||
options['fileEncoding'] = self.encoding
|
||||
if encoding:
|
||||
options['fileEncoding'] = encoding
|
||||
|
||||
exporter = QgsVectorLayerExporter(uri.uri(), self.providerName, self.source.fields(),
|
||||
self.source.wkbType(), self.source.sourceCrs(), self.overwrite, options)
|
||||
exporter = QgsVectorLayerExporter(uri.uri(), providerName, source.fields(),
|
||||
source.wkbType(), source.sourceCrs(), overwrite, options)
|
||||
|
||||
if exporter.errorCode() != QgsVectorLayerExporter.NoError:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error importing to Spatialite\n{0}').format(exporter.errorMessage()))
|
||||
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
@ -170,9 +154,7 @@ class ImportIntoSpatialite(QgisAlgorithm):
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error importing to Spatialite\n{0}').format(exporter.errorMessage()))
|
||||
|
||||
if self.geomColumn and self.createIndex:
|
||||
self.db.create_spatial_index(self.table, self.geomColumn)
|
||||
return True
|
||||
if geomColumn and createIndex:
|
||||
db.create_spatial_index(table, geomColumn)
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {}
|
||||
|
@ -68,26 +68,19 @@ class Merge(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Merged')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Merged')))
|
||||
|
||||
self.input_layers = []
|
||||
self.fields = None
|
||||
self.add_layer_field = None
|
||||
self.add_path_field = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
self.dest_crs = None
|
||||
|
||||
def name(self):
|
||||
return 'mergevectorlayers'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Merge vector layers')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.input_layers = self.parameterAsLayerList(parameters, self.LAYERS, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
input_layers = self.parameterAsLayerList(parameters, self.LAYERS, context)
|
||||
|
||||
layers = []
|
||||
self.fields = QgsFields()
|
||||
fields = QgsFields()
|
||||
totalFeatureCount = 0
|
||||
for layer in self.input_layers:
|
||||
for layer in input_layers:
|
||||
if layer.type() != QgsMapLayer.VectorLayer:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('All layers must be vector layers!'))
|
||||
@ -102,7 +95,7 @@ class Merge(QgisAlgorithm):
|
||||
|
||||
for sindex, sfield in enumerate(layer.fields()):
|
||||
found = None
|
||||
for dfield in self.fields:
|
||||
for dfield in fields:
|
||||
if (dfield.name().upper() == sfield.name().upper()):
|
||||
found = dfield
|
||||
if (dfield.type() != sfield.type()):
|
||||
@ -111,38 +104,35 @@ class Merge(QgisAlgorithm):
|
||||
'data type than in other layers.'.format(sfield.name(), layerSource)))
|
||||
|
||||
if not found:
|
||||
self.fields.append(sfield)
|
||||
fields.append(sfield)
|
||||
|
||||
self.add_layer_field = False
|
||||
if self.fields.lookupField('layer') < 0:
|
||||
self.fields.append(QgsField('layer', QVariant.String, '', 100))
|
||||
self.add_layer_field = True
|
||||
self.add_path_field = False
|
||||
if self.fields.lookupField('path') < 0:
|
||||
self.fields.append(QgsField('path', QVariant.String, '', 200))
|
||||
self.add_path_field = True
|
||||
add_layer_field = False
|
||||
if fields.lookupField('layer') < 0:
|
||||
fields.append(QgsField('layer', QVariant.String, '', 100))
|
||||
add_layer_field = True
|
||||
add_path_field = False
|
||||
if fields.lookupField('path') < 0:
|
||||
fields.append(QgsField('path', QVariant.String, '', 200))
|
||||
add_path_field = True
|
||||
|
||||
total = 100.0 / totalFeatureCount if totalFeatureCount else 1
|
||||
self.dest_crs = layers[0].crs()
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.fields, layers[0].wkbType(), self.dest_crs)
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
dest_crs = layers[0].crs()
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, layers[0].wkbType(), dest_crs)
|
||||
|
||||
featureCount = 0
|
||||
for layer in self.layers:
|
||||
for feature in layer.getFeatures(QgsFeatureRequest().setDestinationCrs(self.dest_crs)):
|
||||
for layer in layers:
|
||||
for feature in layer.getFeatures(QgsFeatureRequest().setDestinationCrs(dest_crs)):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
sattributes = feature.attributes()
|
||||
dattributes = []
|
||||
for dindex, dfield in enumerate(self.fields):
|
||||
if self.add_layer_field and dfield.name() == 'layer':
|
||||
for dindex, dfield in enumerate(fields):
|
||||
if add_layer_field and dfield.name() == 'layer':
|
||||
dattributes.append(layer.name())
|
||||
continue
|
||||
if self.add_path_field and dfield.name() == 'path':
|
||||
if add_path_field and dfield.name() == 'path':
|
||||
dattributes.append(layer.publicSource())
|
||||
continue
|
||||
|
||||
@ -164,10 +154,8 @@ class Merge(QgisAlgorithm):
|
||||
dattributes.append(dattribute)
|
||||
|
||||
feature.setAttributes(dattributes)
|
||||
self.sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
featureCount += 1
|
||||
feedback.setProgress(int(featureCount * self.total))
|
||||
return True
|
||||
feedback.setProgress(int(featureCount * total))
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -80,49 +80,39 @@ class PointsLayerFromTable(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Points from table'), type=QgsProcessingParameterDefinition.TypeVectorPoint))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Points from table'), type=QgsProcessingParameterDefinition.TypeVectorPoint))
|
||||
|
||||
self.source = None
|
||||
self.x_field_index = None
|
||||
self.y_field_index = None
|
||||
self.z_field_index = None
|
||||
self.m_field_index = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'createpointslayerfromtable'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Create points layer from table')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
|
||||
fields = self.source.fields()
|
||||
self.x_field_index = fields.lookupField(self.parameterAsString(parameters, self.XFIELD, context))
|
||||
self.y_field_index = fields.lookupField(self.parameterAsString(parameters, self.YFIELD, context))
|
||||
self.z_field_index = -1
|
||||
fields = source.fields()
|
||||
x_field_index = fields.lookupField(self.parameterAsString(parameters, self.XFIELD, context))
|
||||
y_field_index = fields.lookupField(self.parameterAsString(parameters, self.YFIELD, context))
|
||||
z_field_index = -1
|
||||
if self.parameterAsString(parameters, self.ZFIELD, context):
|
||||
self.z_field_index = fields.lookupField(self.parameterAsString(parameters, self.ZFIELD, context))
|
||||
self.m_field_index = -1
|
||||
z_field_index = fields.lookupField(self.parameterAsString(parameters, self.ZFIELD, context))
|
||||
m_field_index = -1
|
||||
if self.parameterAsString(parameters, self.MFIELD, context):
|
||||
self.m_field_index = fields.lookupField(self.parameterAsString(parameters, self.MFIELD, context))
|
||||
m_field_index = fields.lookupField(self.parameterAsString(parameters, self.MFIELD, context))
|
||||
|
||||
wkb_type = QgsWkbTypes.Point
|
||||
if self.z_field_index >= 0:
|
||||
if z_field_index >= 0:
|
||||
wkb_type = QgsWkbTypes.addZ(wkb_type)
|
||||
if self.m_field_index >= 0:
|
||||
if m_field_index >= 0:
|
||||
wkb_type = QgsWkbTypes.addM(wkb_type)
|
||||
|
||||
target_crs = self.parameterAsCrs(parameters, self.TARGET_CRS, context)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, wkb_type, target_crs)
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, wkb_type, target_crs)
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
|
||||
features = self.source.getFeatures(request)
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
|
||||
for current, feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
@ -132,20 +122,20 @@ class PointsLayerFromTable(QgisAlgorithm):
|
||||
attrs = feature.attributes()
|
||||
|
||||
try:
|
||||
x = float(attrs[self.x_field_index])
|
||||
y = float(attrs[self.y_field_index])
|
||||
x = float(attrs[x_field_index])
|
||||
y = float(attrs[y_field_index])
|
||||
|
||||
point = QgsPoint(x, y)
|
||||
|
||||
if self.z_field_index >= 0:
|
||||
if z_field_index >= 0:
|
||||
try:
|
||||
point.addZValue(float(attrs[self.z_field_index]))
|
||||
point.addZValue(float(attrs[z_field_index]))
|
||||
except:
|
||||
point.addZValue(0.0)
|
||||
|
||||
if self.m_field_index >= 0:
|
||||
if m_field_index >= 0:
|
||||
try:
|
||||
point.addMValue(float(attrs[self.m_field_index]))
|
||||
point.addMValue(float(attrs[m_field_index]))
|
||||
except:
|
||||
point.addMValue(0.0)
|
||||
|
||||
@ -153,8 +143,6 @@ class PointsLayerFromTable(QgisAlgorithm):
|
||||
except:
|
||||
pass # no geometry
|
||||
|
||||
self.sink.addFeature(feature)
|
||||
return True
|
||||
sink.addFeature(feature)
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -53,28 +53,20 @@ class PostGISExecuteSQL(QgisAlgorithm):
|
||||
self.addParameter(db_param)
|
||||
self.addParameter(QgsProcessingParameterString(self.SQL, self.tr('SQL query')))
|
||||
|
||||
self.connection = None
|
||||
self.sql = None
|
||||
|
||||
def name(self):
|
||||
return 'postgisexecutesql'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('PostGIS execute SQL')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.connection = self.parameterAsString(parameters, self.DATABASE, context)
|
||||
self.sql = self.parameterAsString(parameters, self.SQL, context).replace('\n', ' ')
|
||||
return True
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
connection = self.parameterAsString(parameters, self.DATABASE, context)
|
||||
db = postgis.GeoDB.from_name(connection)
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
db = postgis.GeoDB.from_name(self.connection)
|
||||
sql = self.parameterAsString(parameters, self.SQL, context).replace('\n', ' ')
|
||||
try:
|
||||
db._exec_sql_and_commit(str(self.sql))
|
||||
db._exec_sql_and_commit(str(sql))
|
||||
except postgis.DbError as e:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error executing SQL:\n{0}').format(str(e)))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {}
|
||||
|
@ -66,54 +66,42 @@ class RandomExtract(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Extracted (random)')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Extracted (random)')))
|
||||
|
||||
self.source = None
|
||||
self.method = None
|
||||
self.value = None
|
||||
self.featureCount = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'randomextract'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Random extract')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
self.value = self.parameterAsInt(parameters, self.NUMBER, context)
|
||||
self.featureCount = self.source.featureCount()
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
|
||||
if self.method == 0:
|
||||
if self.value > self.featureCount:
|
||||
features = source.getFeatures()
|
||||
featureCount = source.featureCount()
|
||||
value = self.parameterAsInt(parameters, self.NUMBER, context)
|
||||
|
||||
if method == 0:
|
||||
if value > featureCount:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Selected number is greater than feature count. '
|
||||
'Choose a lower value and try again.'))
|
||||
else:
|
||||
if self.value > 100:
|
||||
if value > 100:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr("Percentage can't be greater than 100. Set a "
|
||||
"different value and try again."))
|
||||
self.value = int(round(self.value / 100.0000, 4) * self.featureCount)
|
||||
value = int(round(value / 100.0000, 4) * featureCount)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
selran = random.sample(list(range(featureCount)), value)
|
||||
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
selran = random.sample(list(range(self.featureCount)), self.value)
|
||||
features = self.source.getFeatures()
|
||||
|
||||
total = 100.0 / self.featureCount if self.featureCount else 1
|
||||
total = 100.0 / featureCount if featureCount else 1
|
||||
for i, feat in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
if i in selran:
|
||||
self.sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(i * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -74,46 +74,38 @@ class RandomExtractWithinSubsets(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Extracted (random stratified)')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Extracted (random stratified)')))
|
||||
|
||||
self.source = None
|
||||
self.method = None
|
||||
self.field = None
|
||||
self.value = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'randomextractwithinsubsets'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Random extract within subsets')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
|
||||
self.field = self.parameterAsString(parameters, self.FIELD, context)
|
||||
self.value = self.parameterAsInt(parameters, self.NUMBER, context)
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
field = self.parameterAsString(parameters, self.FIELD, context)
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
index = self.source.fields().lookupField(self.field)
|
||||
index = source.fields().lookupField(field)
|
||||
|
||||
features = self.source.getFeatures()
|
||||
featureCount = self.source.featureCount()
|
||||
unique = self.source.uniqueValues(index)
|
||||
if self.method == 0:
|
||||
if self.value > featureCount:
|
||||
features = source.getFeatures()
|
||||
featureCount = source.featureCount()
|
||||
unique = source.uniqueValues(index)
|
||||
value = self.parameterAsInt(parameters, self.NUMBER, context)
|
||||
if method == 0:
|
||||
if value > featureCount:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Selected number is greater that feature count. '
|
||||
'Choose lesser value and try again.'))
|
||||
else:
|
||||
if self.value > 100:
|
||||
if value > 100:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr("Percentage can't be greater than 100. Set "
|
||||
"correct value and try again."))
|
||||
self.value = self.value / 100.0
|
||||
value = value / 100.0
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
|
||||
selran = []
|
||||
total = 100.0 / (featureCount * len(unique)) if featureCount else 1
|
||||
@ -127,17 +119,13 @@ class RandomExtractWithinSubsets(QgisAlgorithm):
|
||||
feedback.setProgress(int(i * total))
|
||||
|
||||
for subset in classes.values():
|
||||
selValue = self.value if self.method != 1 else int(round(self.value * len(subset), 0))
|
||||
selValue = value if method != 1 else int(round(value * len(subset), 0))
|
||||
selran.extend(random.sample(subset, selValue))
|
||||
|
||||
total = 100.0 / featureCount if featureCount else 1
|
||||
for (i, feat) in enumerate(selran):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
self.sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(i * total))
|
||||
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -81,66 +81,55 @@ class RegularPoints(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Regular points'), QgsProcessingParameterDefinition.TypeVectorPoint))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Regular points'), QgsProcessingParameterDefinition.TypeVectorPoint))
|
||||
|
||||
self.extent = None
|
||||
self.spacing = None
|
||||
self.inset = None
|
||||
self.randomize = None
|
||||
self.isSpacing = None
|
||||
self.fields = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'regularpoints'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Regular points')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.extent = self.parameterAsExtent(parameters, self.EXTENT, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
extent = self.parameterAsExtent(parameters, self.EXTENT, context)
|
||||
|
||||
self.spacing = self.parameterAsDouble(parameters, self.SPACING, context)
|
||||
self.inset = self.parameterAsDouble(parameters, self.INSET, context)
|
||||
self.randomize = self.parameterAsBool(parameters, self.RANDOMIZE, context)
|
||||
self.isSpacing = self.parameterAsBool(parameters, self.IS_SPACING, context)
|
||||
spacing = self.parameterAsDouble(parameters, self.SPACING, context)
|
||||
inset = self.parameterAsDouble(parameters, self.INSET, context)
|
||||
randomize = self.parameterAsBool(parameters, self.RANDOMIZE, context)
|
||||
isSpacing = self.parameterAsBool(parameters, self.IS_SPACING, context)
|
||||
crs = self.parameterAsCrs(parameters, self.CRS, context)
|
||||
|
||||
self.fields = QgsFields()
|
||||
self.fields.append(QgsField('id', QVariant.Int, '', 10, 0))
|
||||
fields = QgsFields()
|
||||
fields.append(QgsField('id', QVariant.Int, '', 10, 0))
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.fields, QgsWkbTypes.Point, crs)
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.Point, crs)
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
if self.randomize:
|
||||
if randomize:
|
||||
seed()
|
||||
|
||||
area = self.extent.width() * self.extent.height()
|
||||
if self.isSpacing:
|
||||
pSpacing = self.spacing
|
||||
area = extent.width() * extent.height()
|
||||
if isSpacing:
|
||||
pSpacing = spacing
|
||||
else:
|
||||
pSpacing = sqrt(area / self.spacing)
|
||||
pSpacing = sqrt(area / spacing)
|
||||
|
||||
f = QgsFeature()
|
||||
f.initAttributes(1)
|
||||
f.setFields(self.fields)
|
||||
f.setFields(fields)
|
||||
|
||||
count = 0
|
||||
total = 100.0 / (area / pSpacing)
|
||||
y = self.extent.yMaximum() - self.inset
|
||||
y = extent.yMaximum() - inset
|
||||
|
||||
extent_geom = QgsGeometry.fromRect(self.extent)
|
||||
extent_geom = QgsGeometry.fromRect(extent)
|
||||
extent_engine = QgsGeometry.createGeometryEngine(extent_geom.geometry())
|
||||
extent_engine.prepareGeometry()
|
||||
|
||||
while y >= self.extent.yMinimum():
|
||||
x = self.extent.xMinimum() + self.inset
|
||||
while x <= self.extent.xMaximum():
|
||||
while y >= extent.yMinimum():
|
||||
x = extent.xMinimum() + inset
|
||||
while x <= extent.xMaximum():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
if self.randomize:
|
||||
if randomize:
|
||||
geom = QgsGeometry().fromPoint(QgsPointXY(
|
||||
uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)),
|
||||
uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0))))
|
||||
@ -150,13 +139,10 @@ class RegularPoints(QgisAlgorithm):
|
||||
if extent_engine.intersects(geom.geometry()):
|
||||
f.setAttribute('id', count)
|
||||
f.setGeometry(geom)
|
||||
self.sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
x += pSpacing
|
||||
count += 1
|
||||
feedback.setProgress(int(count * total))
|
||||
y = y - pSpacing
|
||||
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -47,35 +47,27 @@ class SaveSelectedFeatures(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Selection')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Selection")))
|
||||
|
||||
self.vectorLayer = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'saveselectedfeatures'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Save selected features')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.vectorLayer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
vectorLayer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.vectorLayer.fields(), self.vectorLayer.wkbType(), self.vectorLayer.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
vectorLayer.fields(), vectorLayer.wkbType(), vectorLayer.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.vectorLayer.getSelectedFeatures()
|
||||
count = int(self.vectorLayer.selectedFeatureCount())
|
||||
features = vectorLayer.getSelectedFeatures()
|
||||
count = int(vectorLayer.selectedFeatureCount())
|
||||
|
||||
total = 100.0 / count if count else 1
|
||||
for current, feat in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
self.sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -92,60 +92,47 @@ class SelectByAttribute(QgisAlgorithm):
|
||||
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Selected (attribute)')))
|
||||
|
||||
self.layer = None
|
||||
self.fieldName = None
|
||||
self.operator = None
|
||||
self.value = None
|
||||
self.input = None
|
||||
|
||||
def name(self):
|
||||
return 'selectbyattribute'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Select by attribute')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
|
||||
self.fieldName = self.parameterAsString(parameters, self.FIELD, context)
|
||||
self.operator = self.OPERATORS[self.parameterAsEnum(parameters, self.OPERATOR, context)]
|
||||
self.value = self.parameterAsString(parameters, self.VALUE, context)
|
||||
fieldName = self.parameterAsString(parameters, self.FIELD, context)
|
||||
operator = self.OPERATORS[self.parameterAsEnum(parameters, self.OPERATOR, context)]
|
||||
value = self.parameterAsString(parameters, self.VALUE, context)
|
||||
|
||||
self.input = parameters[self.INPUT]
|
||||
return True
|
||||
fields = layer.fields()
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
fields = self.layer.fields()
|
||||
|
||||
idx = self.layer.fields().lookupField(self.fieldName)
|
||||
idx = layer.fields().lookupField(fieldName)
|
||||
fieldType = fields[idx].type()
|
||||
|
||||
if fieldType != QVariant.String and self.operator in self.STRING_OPERATORS:
|
||||
if fieldType != QVariant.String and operator in self.STRING_OPERATORS:
|
||||
op = ''.join(['"%s", ' % o for o in self.STRING_OPERATORS])
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Operators {0} can be used only with string fields.').format(op))
|
||||
|
||||
field_ref = QgsExpression.quotedColumnRef(self.fieldName)
|
||||
quoted_val = QgsExpression.quotedValue(self.value)
|
||||
if self.operator == 'is null':
|
||||
field_ref = QgsExpression.quotedColumnRef(fieldName)
|
||||
quoted_val = QgsExpression.quotedValue(value)
|
||||
if operator == 'is null':
|
||||
expression_string = '{} IS NULL'.format(field_ref)
|
||||
elif self.operator == 'is not null':
|
||||
elif operator == 'is not null':
|
||||
expression_string = '{} IS NOT NULL'.format(field_ref)
|
||||
elif self.operator == 'begins with':
|
||||
expression_string = """%s LIKE '%s%%'""" % (field_ref, self.value)
|
||||
elif self.operator == 'contains':
|
||||
expression_string = """%s LIKE '%%%s%%'""" % (field_ref, self.value)
|
||||
elif self.operator == 'does not contain':
|
||||
expression_string = """%s NOT LIKE '%%%s%%'""" % (field_ref, self.value)
|
||||
elif operator == 'begins with':
|
||||
expression_string = """%s LIKE '%s%%'""" % (field_ref, value)
|
||||
elif operator == 'contains':
|
||||
expression_string = """%s LIKE '%%%s%%'""" % (field_ref, value)
|
||||
elif operator == 'does not contain':
|
||||
expression_string = """%s NOT LIKE '%%%s%%'""" % (field_ref, value)
|
||||
else:
|
||||
expression_string = '{} {} {}'.format(field_ref, self.operator, quoted_val)
|
||||
expression_string = '{} {} {}'.format(field_ref, operator, quoted_val)
|
||||
|
||||
expression = QgsExpression(expression_string)
|
||||
if expression.hasParserError():
|
||||
raise GeoAlgorithmExecutionException(expression.parserErrorString())
|
||||
|
||||
self.layer.selectByExpression(expression_string)
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.input}
|
||||
layer.selectByExpression(expression_string)
|
||||
return {self.OUTPUT: parameters[self.INPUT]}
|
||||
|
@ -60,42 +60,30 @@ class SelectByExpression(QgisAlgorithm):
|
||||
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Selected (attribute)')))
|
||||
|
||||
self.layer = None
|
||||
self.behavior = None
|
||||
self.input = None
|
||||
self.expression = None
|
||||
|
||||
def name(self):
|
||||
return 'selectbyexpression'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Select by expression')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
|
||||
method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
|
||||
if method == 0:
|
||||
self.behavior = QgsVectorLayer.SetSelection
|
||||
behavior = QgsVectorLayer.SetSelection
|
||||
elif method == 1:
|
||||
self.behavior = QgsVectorLayer.AddToSelection
|
||||
behavior = QgsVectorLayer.AddToSelection
|
||||
elif method == 2:
|
||||
self.behavior = QgsVectorLayer.RemoveFromSelection
|
||||
behavior = QgsVectorLayer.RemoveFromSelection
|
||||
elif method == 3:
|
||||
self.behavior = QgsVectorLayer.IntersectSelection
|
||||
behavior = QgsVectorLayer.IntersectSelection
|
||||
|
||||
self.expression = self.parameterAsString(parameters, self.EXPRESSION, context)
|
||||
qExp = QgsExpression(self.expression)
|
||||
expression = self.parameterAsString(parameters, self.EXPRESSION, context)
|
||||
qExp = QgsExpression(expression)
|
||||
if qExp.hasParserError():
|
||||
raise GeoAlgorithmExecutionException(qExp.parserErrorString())
|
||||
|
||||
self.input = parameters[self.INPUT]
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
self.layer.selectByExpression(self.expression, self.behavior)
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.input}
|
||||
layer.selectByExpression(expression, behavior)
|
||||
return {self.OUTPUT: parameters[self.INPUT]}
|
||||
|
@ -76,37 +76,28 @@ class SimplifyGeometries(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Simplified')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Simplified')))
|
||||
|
||||
self.source = None
|
||||
self.tolerance = None
|
||||
self.method = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'simplifygeometries'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Simplify geometries')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)
|
||||
self.method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)
|
||||
method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
pointsBefore = 0
|
||||
pointsAfter = 0
|
||||
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
|
||||
simplifier = None
|
||||
if self.method != 0:
|
||||
simplifier = QgsMapToPixelSimplifier(QgsMapToPixelSimplifier.SimplifyGeometry, self.tolerance, self.method)
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
|
||||
if method != 0:
|
||||
simplifier = QgsMapToPixelSimplifier(QgsMapToPixelSimplifier.SimplifyGeometry, tolerance, method)
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
@ -116,20 +107,18 @@ class SimplifyGeometries(QgisAlgorithm):
|
||||
input_geometry = input_feature.geometry()
|
||||
pointsBefore += input_geometry.geometry().nCoordinates()
|
||||
|
||||
if self.method == 0: # distance
|
||||
output_geometry = input_geometry.simplify(self.tolerance)
|
||||
if method == 0: # distance
|
||||
output_geometry = input_geometry.simplify(tolerance)
|
||||
else:
|
||||
output_geometry = simplifier.simplify(input_geometry)
|
||||
|
||||
pointsAfter += output_geometry.geometry().nCoordinates()
|
||||
out_feature.setGeometry(output_geometry)
|
||||
|
||||
self.sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
QgsMessageLog.logMessage(self.tr('Simplify: Input geometries have been simplified from {0} to {1} points').format(pointsBefore, pointsAfter),
|
||||
self.tr('Processing'), QgsMessageLog.INFO)
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -66,48 +66,37 @@ class Smooth(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Smoothed')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Smoothed')))
|
||||
|
||||
self.source = None
|
||||
self.iterations = None
|
||||
self.offset = None
|
||||
self.max_angle = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'smoothgeometry'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Smooth geometry')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.iterations = self.parameterAsInt(parameters, self.ITERATIONS, context)
|
||||
self.offset = self.parameterAsDouble(parameters, self.OFFSET, context)
|
||||
self.max_angle = self.parameterAsDouble(parameters, self.MAX_ANGLE, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
iterations = self.parameterAsInt(parameters, self.ITERATIONS, context)
|
||||
offset = self.parameterAsDouble(parameters, self.OFFSET, context)
|
||||
max_angle = self.parameterAsDouble(parameters, self.MAX_ANGLE, context)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
output_feature = input_feature
|
||||
if input_feature.geometry():
|
||||
output_geometry = input_feature.geometry().smooth(self.iterations, self.offset, -1, self.max_angle)
|
||||
output_geometry = input_feature.geometry().smooth(iterations, offset, -1, max_angle)
|
||||
if not output_geometry:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error smoothing geometry'))
|
||||
|
||||
output_feature.setGeometry(output_geometry)
|
||||
|
||||
self.sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -49,34 +49,26 @@ class SpatialiteExecuteSQL(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterVectorLayer(self.DATABASE, self.tr('File Database'), False, False))
|
||||
self.addParameter(QgsProcessingParameterString(self.SQL, self.tr('SQL query'), '', True))
|
||||
|
||||
self.database = None
|
||||
self.sql = None
|
||||
|
||||
def name(self):
|
||||
return 'spatialiteexecutesql'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Spatialite execute SQL')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.database = self.parameterAsVectorLayer(parameters, self.DATABASE, context)
|
||||
self.sql = self.parameterAsString(parameters, self.SQL, context).replace('\n', ' ')
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
databaseuri = self.database.dataProvider().dataSourceUri()
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
database = self.parameterAsVectorLayer(parameters, self.DATABASE, context)
|
||||
databaseuri = database.dataProvider().dataSourceUri()
|
||||
uri = QgsDataSourceUri(databaseuri)
|
||||
if uri.database() is '':
|
||||
if '|layerid' in databaseuri:
|
||||
databaseuri = databaseuri[:databaseuri.find('|layerid')]
|
||||
uri = QgsDataSourceUri('dbname=\'%s\'' % (databaseuri))
|
||||
db = spatialite.GeoDB(uri)
|
||||
sql = self.parameterAsString(parameters, self.SQL, context).replace('\n', ' ')
|
||||
try:
|
||||
db._exec_sql_and_commit(str(self.sql))
|
||||
db._exec_sql_and_commit(str(sql))
|
||||
except spatialite.DbError as e:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error executing SQL:\n{0}').format(str(e)))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {}
|
||||
|
@ -70,39 +70,32 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Symmetrical difference')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Symmetrical difference')))
|
||||
|
||||
self.sourceA = None
|
||||
self.sourceB = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'symmetricaldifference'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Symmetrical difference')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.sourceA = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
sourceA = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
|
||||
|
||||
geomType = QgsWkbTypes.multiType(self.sourceA.wkbType())
|
||||
fields = vector.combineFields(self.sourceA.fields(), self.sourceB.fields())
|
||||
geomType = QgsWkbTypes.multiType(sourceA.wkbType())
|
||||
fields = vector.combineFields(sourceA.fields(), sourceB.fields())
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, geomType, self.sourceA.sourceCrs())
|
||||
return True
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, geomType, sourceA.sourceCrs())
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
featB = QgsFeature()
|
||||
outFeat = QgsFeature()
|
||||
|
||||
indexA = QgsSpatialIndex(self.sourceA)
|
||||
indexB = QgsSpatialIndex(self.sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(self.sourceA.sourceCrs())))
|
||||
indexA = QgsSpatialIndex(sourceA)
|
||||
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
|
||||
|
||||
total = 100.0 / (self.sourceA.featureCount() * self.sourceB.featureCount()) if self.sourceA.featureCount() and self.sourceB.featureCount() else 1
|
||||
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
|
||||
count = 0
|
||||
|
||||
for featA in self.sourceA.getFeatures():
|
||||
for featA in sourceA.getFeatures():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
@ -111,8 +104,8 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
attrs = featA.attributes()
|
||||
intersects = indexB.intersects(geom.boundingBox())
|
||||
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
|
||||
request.setDestinationCrs(self.sourceA.sourceCrs())
|
||||
for featB in self.sourceB.getFeatures(request):
|
||||
request.setDestinationCrs(sourceA.sourceCrs())
|
||||
for featB in sourceB.getFeatures(request):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
tmpGeom = featB.geometry()
|
||||
@ -122,7 +115,7 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
try:
|
||||
outFeat.setGeometry(diffGeom)
|
||||
outFeat.setAttributes(attrs)
|
||||
self.sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
except:
|
||||
QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
|
||||
self.tr('Processing'), QgsMessageLog.WARNING)
|
||||
@ -131,9 +124,9 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
count += 1
|
||||
feedback.setProgress(int(count * total))
|
||||
|
||||
length = len(self.sourceA.fields())
|
||||
length = len(sourceA.fields())
|
||||
|
||||
for featA in self.sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(self.sourceA.sourceCrs())):
|
||||
for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs())):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
@ -143,7 +136,7 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
attrs = [NULL] * length + attrs
|
||||
intersects = indexA.intersects(geom.boundingBox())
|
||||
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
|
||||
for featB in self.sourceA.getFeatures(request):
|
||||
for featB in sourceA.getFeatures(request):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
@ -154,7 +147,7 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
try:
|
||||
outFeat.setGeometry(diffGeom)
|
||||
outFeat.setAttributes(attrs)
|
||||
self.sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
except:
|
||||
QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
|
||||
self.tr('Processing'), QgsMessageLog.WARNING)
|
||||
@ -162,7 +155,5 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
|
||||
count += 1
|
||||
feedback.setProgress(int(count * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -66,51 +66,42 @@ class VectorSplit(QgisAlgorithm):
|
||||
|
||||
self.addOutput(QgsProcessingOutputFolder(self.OUTPUT, self.tr('Output directory')))
|
||||
|
||||
self.source = None
|
||||
self.fieldName = None
|
||||
self.directory = None
|
||||
self.uniqueValues = None
|
||||
self.sinks = {}
|
||||
|
||||
def name(self):
|
||||
return 'splitvectorlayer'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Split vector layer')
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.fieldName = self.parameterAsString(parameters, self.FIELD, context)
|
||||
self.directory = self.parameterAsString(parameters, self.OUTPUT, context)
|
||||
mkdir(self.directory)
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
fieldName = self.parameterAsString(parameters, self.FIELD, context)
|
||||
directory = self.parameterAsString(parameters, self.OUTPUT, context)
|
||||
|
||||
fieldIndex = self.source.fields().lookupField(self.fieldName)
|
||||
self.uniqueValues = self.source.uniqueValues(fieldIndex)
|
||||
mkdir(directory)
|
||||
|
||||
baseName = os.path.join(self.directory, '{0}'.format(self.fieldName))
|
||||
self.sinks = {}
|
||||
for current, i in enumerate(self.uniqueValues):
|
||||
fieldIndex = source.fields().lookupField(fieldName)
|
||||
uniqueValues = source.uniqueValues(fieldIndex)
|
||||
baseName = os.path.join(directory, '{0}'.format(fieldName))
|
||||
|
||||
fields = source.fields()
|
||||
crs = source.sourceCrs()
|
||||
geomType = source.wkbType()
|
||||
|
||||
total = 100.0 / len(uniqueValues) if uniqueValues else 1
|
||||
|
||||
for current, i in enumerate(uniqueValues):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
fName = u'{0}_{1}.shp'.format(baseName, str(i).strip())
|
||||
feedback.pushInfo(self.tr('Creating layer: {}').format(fName))
|
||||
sink, dest = QgsProcessingUtils.createFeatureSink(fName, context, self.source.fields, self.source.wkbType(), self.source.sourceCrs())
|
||||
self.sinks[i] = sink
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
total = 100.0 / len(self.uniqueValues) if self.uniqueValues else 1
|
||||
for current, i in enumerate(self.uniqueValues):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
sink, dest = QgsProcessingUtils.createFeatureSink(fName, context, fields, geomType, crs)
|
||||
|
||||
sink = self.sinks[i]
|
||||
|
||||
filter = '{} = {}'.format(QgsExpression.quotedColumnRef(self.fieldName), QgsExpression.quotedValue(i))
|
||||
filter = '{} = {}'.format(QgsExpression.quotedColumnRef(fieldName), QgsExpression.quotedValue(i))
|
||||
req = QgsFeatureRequest().setFilterExpression(filter)
|
||||
|
||||
count = 0
|
||||
for f in self.source.getFeatures(req):
|
||||
for f in source.getFeatures(req):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
@ -119,7 +110,5 @@ class VectorSplit(QgisAlgorithm):
|
||||
del sink
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.directory}
|
||||
return {self.OUTPUT: directory}
|
||||
|
@ -121,14 +121,11 @@ class ZonalStatistics(QgisAlgorithm):
|
||||
self.rasterLayer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context)
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
zs = QgsZonalStatistics(self.vectorLayer,
|
||||
self.rasterLayer,
|
||||
self.columnPrefix,
|
||||
self.bandNumber,
|
||||
QgsZonalStatistics.Statistics(self.selectedStats))
|
||||
zs.calculateStatistics(feedback)
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.INPUT_VECTOR: self.vectorLayer}
|
||||
|
@ -248,7 +248,7 @@ class ScriptAlgorithm(QgsProcessingAlgorithm):
|
||||
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
self.ns['feedback'] = feedback
|
||||
self.ns['context'] = context
|
||||
|
||||
@ -257,9 +257,6 @@ class ScriptAlgorithm(QgsProcessingAlgorithm):
|
||||
for out in self.outputDefinitions():
|
||||
self.results[out.name()] = self.ns[out.name()]
|
||||
del self.ns
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return self.results
|
||||
|
||||
def helpUrl(self):
|
||||
|
@ -138,7 +138,7 @@ class AlgorithmsTest(object):
|
||||
pass
|
||||
else:
|
||||
results, ok = alg.run(parameters, context, feedback)
|
||||
self.assertTrue(ok, parameters)
|
||||
self.assertTrue(ok, 'params: {}, results: {}'.format(parameters, results))
|
||||
self.check_results(results, context, defs['params'], defs['results'])
|
||||
|
||||
def load_params(self, params):
|
||||
|
@ -89,27 +89,23 @@ QgsCentroidAlgorithm *QgsCentroidAlgorithm::create() const
|
||||
return new QgsCentroidAlgorithm();
|
||||
}
|
||||
|
||||
bool QgsCentroidAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
QVariantMap QgsCentroidAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
mSource.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !mSource )
|
||||
return false;
|
||||
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !source )
|
||||
return QVariantMap();
|
||||
|
||||
mSink.reset( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, mSinkId, mSource->fields(), QgsWkbTypes::Point, mSource->sourceCrs() ) );
|
||||
if ( !mSink )
|
||||
return false;
|
||||
QString dest;
|
||||
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(), QgsWkbTypes::Point, source->sourceCrs() ) );
|
||||
if ( !sink )
|
||||
return QVariantMap();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsCentroidAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
long count = mSource->featureCount();
|
||||
if ( count == 0 )
|
||||
return true;
|
||||
long count = source->featureCount();
|
||||
if ( count <= 0 )
|
||||
return QVariantMap();
|
||||
|
||||
QgsFeature f;
|
||||
QgsFeatureIterator it = mSource->getFeatures();
|
||||
QgsFeatureIterator it = source->getFeatures();
|
||||
|
||||
double step = 100.0 / count;
|
||||
int current = 0;
|
||||
@ -129,19 +125,14 @@ bool QgsCentroidAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessi
|
||||
QgsMessageLog::logMessage( QObject::tr( "Error calculating centroid for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), QgsMessageLog::WARNING );
|
||||
}
|
||||
}
|
||||
mSink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
sink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
|
||||
feedback->setProgress( current * step );
|
||||
current++;
|
||||
}
|
||||
mSink->flushBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsCentroidAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), mSinkId );
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
@ -178,47 +169,37 @@ QgsBufferAlgorithm *QgsBufferAlgorithm::create() const
|
||||
return new QgsBufferAlgorithm();
|
||||
}
|
||||
|
||||
bool QgsBufferAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
QVariantMap QgsBufferAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
mSource.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !mSource )
|
||||
return false;
|
||||
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !source )
|
||||
return QVariantMap();
|
||||
|
||||
mSink.reset( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, mSinkId, mSource->fields(), QgsWkbTypes::Polygon, mSource->sourceCrs() ) );
|
||||
if ( !mSink )
|
||||
return false;
|
||||
QString dest;
|
||||
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(), QgsWkbTypes::Polygon, source->sourceCrs() ) );
|
||||
if ( !sink )
|
||||
return QVariantMap();
|
||||
|
||||
// fixed parameters
|
||||
mDissolve = parameterAsBool( parameters, QStringLiteral( "DISSOLVE" ), context );
|
||||
mSegments = parameterAsInt( parameters, QStringLiteral( "SEGMENTS" ), context );
|
||||
mEndCapStyle = static_cast< QgsGeometry::EndCapStyle >( 1 + parameterAsInt( parameters, QStringLiteral( "END_CAP_STYLE" ), context ) );
|
||||
mJoinStyle = static_cast< QgsGeometry::JoinStyle>( 1 + parameterAsInt( parameters, QStringLiteral( "JOIN_STYLE" ), context ) );
|
||||
mMiterLimit = parameterAsDouble( parameters, QStringLiteral( "MITRE_LIMIT" ), context );
|
||||
mBufferDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context );
|
||||
mDynamicBuffer = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) );
|
||||
if ( mDynamicBuffer )
|
||||
{
|
||||
mDynamicBufferProperty = parameters.value( QStringLiteral( "DISTANCE" ) ).value< QgsProperty >();
|
||||
mExpContext = context.expressionContext();
|
||||
mDefaultBuffer = parameterDefinition( QStringLiteral( "DISTANCE" ) )->defaultValue().toDouble();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool dissolve = parameterAsBool( parameters, QStringLiteral( "DISSOLVE" ), context );
|
||||
int segments = parameterAsInt( parameters, QStringLiteral( "SEGMENTS" ), context );
|
||||
QgsGeometry::EndCapStyle endCapStyle = static_cast< QgsGeometry::EndCapStyle >( 1 + parameterAsInt( parameters, QStringLiteral( "END_CAP_STYLE" ), context ) );
|
||||
QgsGeometry::JoinStyle joinStyle = static_cast< QgsGeometry::JoinStyle>( 1 + parameterAsInt( parameters, QStringLiteral( "JOIN_STYLE" ), context ) );
|
||||
double miterLimit = parameterAsDouble( parameters, QStringLiteral( "MITRE_LIMIT" ), context );
|
||||
double bufferDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context );
|
||||
bool dynamicBuffer = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) );
|
||||
const QgsProcessingParameterDefinition *distanceParamDef = parameterDefinition( QStringLiteral( "DISTANCE" ) );
|
||||
|
||||
bool QgsBufferAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
long count = mSource->featureCount();
|
||||
if ( count == 0 )
|
||||
return false;
|
||||
long count = source->featureCount();
|
||||
if ( count <= 0 )
|
||||
return QVariantMap();
|
||||
|
||||
QgsFeature f;
|
||||
QgsFeatureIterator it = mSource->getFeatures();
|
||||
QgsFeatureIterator it = source->getFeatures();
|
||||
|
||||
double step = 100.0 / count;
|
||||
int current = 0;
|
||||
|
||||
double bufferDistance = mBufferDistance;
|
||||
|
||||
QList< QgsGeometry > bufferedGeometriesForDissolve;
|
||||
QgsAttributes dissolveAttrs;
|
||||
|
||||
@ -234,50 +215,45 @@ bool QgsBufferAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessing
|
||||
QgsFeature out = f;
|
||||
if ( out.hasGeometry() )
|
||||
{
|
||||
if ( mDynamicBuffer )
|
||||
if ( dynamicBuffer )
|
||||
{
|
||||
mExpContext.setFeature( f );
|
||||
bufferDistance = mDynamicBufferProperty.valueAsDouble( mExpContext, mDefaultBuffer );
|
||||
context.expressionContext().setFeature( f );
|
||||
bufferDistance = QgsProcessingParameters::parameterAsDouble( distanceParamDef, parameters, context );
|
||||
}
|
||||
|
||||
QgsGeometry outputGeometry = f.geometry().buffer( bufferDistance, mSegments, mEndCapStyle, mJoinStyle, mMiterLimit );
|
||||
QgsGeometry outputGeometry = f.geometry().buffer( bufferDistance, segments, endCapStyle, joinStyle, miterLimit );
|
||||
if ( !outputGeometry )
|
||||
{
|
||||
QgsMessageLog::logMessage( QObject::tr( "Error calculating buffer for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), QgsMessageLog::WARNING );
|
||||
}
|
||||
if ( mDissolve )
|
||||
if ( dissolve )
|
||||
bufferedGeometriesForDissolve << outputGeometry;
|
||||
else
|
||||
out.setGeometry( outputGeometry );
|
||||
}
|
||||
|
||||
if ( !mDissolve )
|
||||
mSink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
if ( !dissolve )
|
||||
sink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
|
||||
feedback->setProgress( current * step );
|
||||
current++;
|
||||
}
|
||||
|
||||
if ( mDissolve )
|
||||
if ( dissolve )
|
||||
{
|
||||
QgsGeometry finalGeometry = QgsGeometry::unaryUnion( bufferedGeometriesForDissolve );
|
||||
QgsFeature f;
|
||||
f.setGeometry( finalGeometry );
|
||||
f.setAttributes( dissolveAttrs );
|
||||
mSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
sink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
}
|
||||
|
||||
mSink->flushBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsBufferAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), mSinkId );
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
||||
QgsDissolveAlgorithm::QgsDissolveAlgorithm()
|
||||
{
|
||||
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
|
||||
@ -302,34 +278,31 @@ QgsDissolveAlgorithm *QgsDissolveAlgorithm::create() const
|
||||
return new QgsDissolveAlgorithm();
|
||||
}
|
||||
|
||||
bool QgsDissolveAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
mSource.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !mSource )
|
||||
return false;
|
||||
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !source )
|
||||
return QVariantMap();
|
||||
|
||||
mSink.reset( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, mSinkId, mSource->fields(), QgsWkbTypes::multiType( mSource->wkbType() ), mSource->sourceCrs() ) );
|
||||
QString dest;
|
||||
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(), QgsWkbTypes::multiType( source->wkbType() ), source->sourceCrs() ) );
|
||||
|
||||
if ( !mSink )
|
||||
return false;
|
||||
if ( !sink )
|
||||
return QVariantMap();
|
||||
|
||||
mFields = parameterAsFields( parameters, QStringLiteral( "FIELD" ), context );
|
||||
return true;
|
||||
}
|
||||
QStringList fields = parameterAsFields( parameters, QStringLiteral( "FIELD" ), context );
|
||||
|
||||
bool QgsDissolveAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
long count = mSource->featureCount();
|
||||
if ( count == 0 )
|
||||
return true;
|
||||
long count = source->featureCount();
|
||||
if ( count <= 0 )
|
||||
return QVariantMap();
|
||||
|
||||
QgsFeature f;
|
||||
QgsFeatureIterator it = mSource->getFeatures();
|
||||
QgsFeatureIterator it = source->getFeatures();
|
||||
|
||||
double step = 100.0 / count;
|
||||
int current = 0;
|
||||
|
||||
if ( mFields.isEmpty() )
|
||||
if ( fields.isEmpty() )
|
||||
{
|
||||
// dissolve all - not using fields
|
||||
bool firstFeature = true;
|
||||
@ -367,14 +340,14 @@ bool QgsDissolveAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessi
|
||||
}
|
||||
|
||||
outputFeature.setGeometry( QgsGeometry::unaryUnion( geomQueue ) );
|
||||
mSink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
|
||||
sink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
|
||||
}
|
||||
else
|
||||
{
|
||||
QList< int > fieldIndexes;
|
||||
Q_FOREACH ( const QString &field, mFields )
|
||||
Q_FOREACH ( const QString &field, fields )
|
||||
{
|
||||
int index = mSource->fields().lookupField( field );
|
||||
int index = source->fields().lookupField( field );
|
||||
if ( index >= 0 )
|
||||
fieldIndexes << index;
|
||||
}
|
||||
@ -418,21 +391,15 @@ bool QgsDissolveAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessi
|
||||
QgsFeature outputFeature;
|
||||
outputFeature.setGeometry( QgsGeometry::unaryUnion( geomIt.value() ) );
|
||||
outputFeature.setAttributes( attributeHash.value( geomIt.key() ) );
|
||||
mSink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
|
||||
sink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
|
||||
|
||||
feedback->setProgress( current * 100.0 / numberFeatures );
|
||||
current++;
|
||||
}
|
||||
}
|
||||
|
||||
mSink->flushBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsDissolveAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), mSinkId );
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
@ -459,29 +426,25 @@ QgsClipAlgorithm *QgsClipAlgorithm::create() const
|
||||
return new QgsClipAlgorithm();
|
||||
}
|
||||
|
||||
bool QgsClipAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
QVariantMap QgsClipAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
mFeatureSource.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !mFeatureSource )
|
||||
return false;
|
||||
std::unique_ptr< QgsFeatureSource > featureSource( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !featureSource )
|
||||
return QVariantMap();
|
||||
|
||||
mMaskSource.reset( parameterAsSource( parameters, QStringLiteral( "OVERLAY" ), context ) );
|
||||
if ( !mMaskSource )
|
||||
return false;
|
||||
std::unique_ptr< QgsFeatureSource > maskSource( parameterAsSource( parameters, QStringLiteral( "OVERLAY" ), context ) );
|
||||
if ( !maskSource )
|
||||
return QVariantMap();
|
||||
|
||||
mSink.reset( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, mSinkId, mFeatureSource->fields(), QgsWkbTypes::multiType( mFeatureSource->wkbType() ), mFeatureSource->sourceCrs() ) );
|
||||
QString dest;
|
||||
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, featureSource->fields(), QgsWkbTypes::multiType( featureSource->wkbType() ), featureSource->sourceCrs() ) );
|
||||
|
||||
if ( !mSink )
|
||||
return false;
|
||||
if ( !sink )
|
||||
return QVariantMap();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsClipAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
// first build up a list of clip geometries
|
||||
QList< QgsGeometry > clipGeoms;
|
||||
QgsFeatureIterator it = mMaskSource->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QList< int >() ).setDestinationCrs( mFeatureSource->sourceCrs() ) );
|
||||
QgsFeatureIterator it = maskSource->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QList< int >() ).setDestinationCrs( featureSource->sourceCrs() ) );
|
||||
QgsFeature f;
|
||||
while ( it.nextFeature( f ) )
|
||||
{
|
||||
@ -490,7 +453,7 @@ bool QgsClipAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFe
|
||||
}
|
||||
|
||||
if ( clipGeoms.isEmpty() )
|
||||
return true;
|
||||
return QVariantMap();
|
||||
|
||||
// are we clipping against a single feature? if so, we can show finer progress reports
|
||||
bool singleClipFeature = false;
|
||||
@ -521,7 +484,7 @@ bool QgsClipAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFe
|
||||
break;
|
||||
}
|
||||
|
||||
QgsFeatureIterator inputIt = mFeatureSource->getFeatures( QgsFeatureRequest().setFilterRect( clipGeom.boundingBox() ) );
|
||||
QgsFeatureIterator inputIt = featureSource->getFeatures( QgsFeatureRequest().setFilterRect( clipGeom.boundingBox() ) );
|
||||
QgsFeatureList inputFeatures;
|
||||
QgsFeature f;
|
||||
while ( inputIt.nextFeature( f ) )
|
||||
@ -576,7 +539,8 @@ bool QgsClipAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFe
|
||||
QgsFeature outputFeature;
|
||||
outputFeature.setGeometry( newGeometry );
|
||||
outputFeature.setAttributes( inputFeature.attributes() );
|
||||
mSink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
|
||||
sink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
|
||||
|
||||
|
||||
if ( singleClipFeature )
|
||||
feedback->setProgress( current * step );
|
||||
@ -588,17 +552,13 @@ bool QgsClipAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFe
|
||||
feedback->setProgress( 100.0 * static_cast< double >( i ) / clipGeoms.length() );
|
||||
}
|
||||
}
|
||||
mSink->flushBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsClipAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), mSinkId );
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
||||
QgsTransformAlgorithm::QgsTransformAlgorithm()
|
||||
{
|
||||
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
|
||||
@ -619,41 +579,29 @@ QgsTransformAlgorithm *QgsTransformAlgorithm::create() const
|
||||
return new QgsTransformAlgorithm();
|
||||
}
|
||||
|
||||
bool QgsTransformAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
QVariantMap QgsTransformAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
mSource.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !mSource )
|
||||
return false;
|
||||
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !source )
|
||||
return QVariantMap();
|
||||
|
||||
mCrs = parameterAsCrs( parameters, QStringLiteral( "TARGET_CRS" ), context );
|
||||
QgsCoordinateReferenceSystem targetCrs = parameterAsCrs( parameters, QStringLiteral( "TARGET_CRS" ), context );
|
||||
|
||||
mSink.reset( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, mSinkId, mSource->fields(), mSource->wkbType(), mCrs ) );
|
||||
if ( !mSink )
|
||||
return false;
|
||||
QString dest;
|
||||
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(), source->wkbType(), targetCrs ) );
|
||||
if ( !sink )
|
||||
return QVariantMap();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsTransformAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), mSinkId );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
bool QgsTransformAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
long count = mSource->featureCount();
|
||||
if ( count == 0 )
|
||||
return true;
|
||||
long count = source->featureCount();
|
||||
if ( count <= 0 )
|
||||
return QVariantMap();
|
||||
|
||||
QgsFeature f;
|
||||
QgsFeatureRequest req;
|
||||
// perform reprojection in the iterators...
|
||||
req.setDestinationCrs( mCrs );
|
||||
req.setDestinationCrs( targetCrs );
|
||||
|
||||
QgsFeatureIterator it = mSource->getFeatures( req );
|
||||
QgsFeatureIterator it = source->getFeatures( req );
|
||||
|
||||
double step = 100.0 / count;
|
||||
int current = 0;
|
||||
@ -664,12 +612,14 @@ bool QgsTransformAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcess
|
||||
break;
|
||||
}
|
||||
|
||||
mSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
sink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
feedback->setProgress( current * step );
|
||||
current++;
|
||||
}
|
||||
|
||||
return true;
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
||||
@ -698,29 +648,25 @@ QgsSubdivideAlgorithm *QgsSubdivideAlgorithm::create() const
|
||||
return new QgsSubdivideAlgorithm();
|
||||
}
|
||||
|
||||
bool QgsSubdivideAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
QVariantMap QgsSubdivideAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
mSource.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !mSource )
|
||||
return false;
|
||||
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !source )
|
||||
return QVariantMap();
|
||||
|
||||
mMaxNodes = parameterAsInt( parameters, QStringLiteral( "MAX_NODES" ), context );
|
||||
mSink.reset( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, mSinkId, mSource->fields(),
|
||||
QgsWkbTypes::multiType( mSource->wkbType() ), mSource->sourceCrs() ) );
|
||||
if ( !mSink )
|
||||
return false;
|
||||
int maxNodes = parameterAsInt( parameters, QStringLiteral( "MAX_NODES" ), context );
|
||||
QString dest;
|
||||
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(),
|
||||
QgsWkbTypes::multiType( source->wkbType() ), source->sourceCrs() ) );
|
||||
if ( !sink )
|
||||
return QVariantMap();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsSubdivideAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
long count = mSource->featureCount();
|
||||
if ( count == 0 )
|
||||
return true;
|
||||
long count = source->featureCount();
|
||||
if ( count <= 0 )
|
||||
return QVariantMap();
|
||||
|
||||
QgsFeature f;
|
||||
QgsFeatureIterator it = mSource->getFeatures();
|
||||
QgsFeatureIterator it = source->getFeatures();
|
||||
|
||||
double step = 100.0 / count;
|
||||
int current = 0;
|
||||
@ -734,29 +680,25 @@ bool QgsSubdivideAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcess
|
||||
QgsFeature out = f;
|
||||
if ( out.hasGeometry() )
|
||||
{
|
||||
out.setGeometry( f.geometry().subdivide( mMaxNodes ) );
|
||||
out.setGeometry( f.geometry().subdivide( maxNodes ) );
|
||||
if ( !out.geometry() )
|
||||
{
|
||||
QgsMessageLog::logMessage( QObject::tr( "Error calculating subdivision for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), QgsMessageLog::WARNING );
|
||||
}
|
||||
}
|
||||
mSink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
sink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
|
||||
feedback->setProgress( current * step );
|
||||
current++;
|
||||
}
|
||||
mSink->flushBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsSubdivideAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), mSinkId );
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QgsMultipartToSinglepartAlgorithm::QgsMultipartToSinglepartAlgorithm()
|
||||
{
|
||||
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
|
||||
@ -777,30 +719,26 @@ QgsMultipartToSinglepartAlgorithm *QgsMultipartToSinglepartAlgorithm::create() c
|
||||
return new QgsMultipartToSinglepartAlgorithm();
|
||||
}
|
||||
|
||||
bool QgsMultipartToSinglepartAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
QVariantMap QgsMultipartToSinglepartAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
mSource.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !mSource )
|
||||
return false;
|
||||
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !source )
|
||||
return QVariantMap();
|
||||
|
||||
QgsWkbTypes::Type sinkType = QgsWkbTypes::singleType( mSource->wkbType() );
|
||||
QgsWkbTypes::Type sinkType = QgsWkbTypes::singleType( source->wkbType() );
|
||||
|
||||
mSink.reset( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, mSinkId, mSource->fields(),
|
||||
sinkType, mSource->sourceCrs() ) );
|
||||
if ( !mSink )
|
||||
return false;
|
||||
QString dest;
|
||||
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(),
|
||||
sinkType, source->sourceCrs() ) );
|
||||
if ( !sink )
|
||||
return QVariantMap();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsMultipartToSinglepartAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
long count = mSource->featureCount();
|
||||
if ( count == 0 )
|
||||
return true;
|
||||
long count = source->featureCount();
|
||||
if ( count <= 0 )
|
||||
return QVariantMap();
|
||||
|
||||
QgsFeature f;
|
||||
QgsFeatureIterator it = mSource->getFeatures();
|
||||
QgsFeatureIterator it = source->getFeatures();
|
||||
|
||||
double step = 100.0 / count;
|
||||
int current = 0;
|
||||
@ -820,34 +758,30 @@ bool QgsMultipartToSinglepartAlgorithm::processAlgorithm( QgsProcessingContext &
|
||||
Q_FOREACH ( const QgsGeometry &g, inputGeometry.asGeometryCollection() )
|
||||
{
|
||||
out.setGeometry( g );
|
||||
mSink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
sink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mSink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
sink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// feature with null geometry
|
||||
mSink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
sink->addFeature( out, QgsFeatureSink::FastInsert );
|
||||
}
|
||||
|
||||
feedback->setProgress( current * step );
|
||||
current++;
|
||||
}
|
||||
mSink->flushBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsMultipartToSinglepartAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), mSinkId );
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
||||
QgsExtractByExpressionAlgorithm::QgsExtractByExpressionAlgorithm()
|
||||
{
|
||||
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
|
||||
@ -872,50 +806,47 @@ QgsExtractByExpressionAlgorithm *QgsExtractByExpressionAlgorithm::create() const
|
||||
return new QgsExtractByExpressionAlgorithm();
|
||||
}
|
||||
|
||||
bool QgsExtractByExpressionAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
QVariantMap QgsExtractByExpressionAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
mSource.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !mSource )
|
||||
return false;
|
||||
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !source )
|
||||
return QVariantMap();
|
||||
|
||||
mExpressionString = parameterAsExpression( parameters, QStringLiteral( "EXPRESSION" ), context );
|
||||
QString expressionString = parameterAsExpression( parameters, QStringLiteral( "EXPRESSION" ), context );
|
||||
|
||||
mMatchingSink.reset( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, mMatchingSinkId, mSource->fields(),
|
||||
mSource->wkbType(), mSource->sourceCrs() ) );
|
||||
if ( !mMatchingSink )
|
||||
return false;
|
||||
QString matchingSinkId;
|
||||
std::unique_ptr< QgsFeatureSink > matchingSink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, matchingSinkId, source->fields(),
|
||||
source->wkbType(), source->sourceCrs() ) );
|
||||
if ( !matchingSink )
|
||||
return QVariantMap();
|
||||
|
||||
mNonMatchingSink.reset( parameterAsSink( parameters, QStringLiteral( "FAIL_OUTPUT" ), context, mNonMatchingSinkId, mSource->fields(),
|
||||
mSource->wkbType(), mSource->sourceCrs() ) );
|
||||
QString nonMatchingSinkId;
|
||||
std::unique_ptr< QgsFeatureSink > nonMatchingSink( parameterAsSink( parameters, QStringLiteral( "FAIL_OUTPUT" ), context, nonMatchingSinkId, source->fields(),
|
||||
source->wkbType(), source->sourceCrs() ) );
|
||||
|
||||
mExpressionContext = createExpressionContext( parameters, context );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsExtractByExpressionAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
QgsExpression expression( mExpressionString );
|
||||
QgsExpression expression( expressionString );
|
||||
if ( expression.hasParserError() )
|
||||
{
|
||||
throw QgsProcessingException( expression.parserErrorString() );
|
||||
}
|
||||
|
||||
QgsExpressionContext expressionContext = createExpressionContext( parameters, context );
|
||||
|
||||
long count = mSource->featureCount();
|
||||
if ( count == 0 )
|
||||
return true;
|
||||
long count = source->featureCount();
|
||||
if ( count <= 0 )
|
||||
return QVariantMap();
|
||||
|
||||
double step = 100.0 / count;
|
||||
int current = 0;
|
||||
|
||||
if ( !mNonMatchingSink )
|
||||
if ( !nonMatchingSink )
|
||||
{
|
||||
// not saving failing features - so only fetch good features
|
||||
QgsFeatureRequest req;
|
||||
req.setFilterExpression( mExpressionString );
|
||||
req.setExpressionContext( mExpressionContext );
|
||||
req.setFilterExpression( expressionString );
|
||||
req.setExpressionContext( expressionContext );
|
||||
|
||||
QgsFeatureIterator it = mSource->getFeatures( req );
|
||||
QgsFeatureIterator it = source->getFeatures( req );
|
||||
QgsFeature f;
|
||||
while ( it.nextFeature( f ) )
|
||||
{
|
||||
@ -924,7 +855,7 @@ bool QgsExtractByExpressionAlgorithm::processAlgorithm( QgsProcessingContext &,
|
||||
break;
|
||||
}
|
||||
|
||||
mMatchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
matchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
|
||||
feedback->setProgress( current * step );
|
||||
current++;
|
||||
@ -933,10 +864,10 @@ bool QgsExtractByExpressionAlgorithm::processAlgorithm( QgsProcessingContext &,
|
||||
else
|
||||
{
|
||||
// saving non-matching features, so we need EVERYTHING
|
||||
mExpressionContext.setFields( mSource->fields() );
|
||||
expression.prepare( &mExpressionContext );
|
||||
expressionContext.setFields( source->fields() );
|
||||
expression.prepare( &expressionContext );
|
||||
|
||||
QgsFeatureIterator it = mSource->getFeatures();
|
||||
QgsFeatureIterator it = source->getFeatures();
|
||||
QgsFeature f;
|
||||
while ( it.nextFeature( f ) )
|
||||
{
|
||||
@ -945,37 +876,30 @@ bool QgsExtractByExpressionAlgorithm::processAlgorithm( QgsProcessingContext &,
|
||||
break;
|
||||
}
|
||||
|
||||
mExpressionContext.setFeature( f );
|
||||
if ( expression.evaluate( &mExpressionContext ).toBool() )
|
||||
expressionContext.setFeature( f );
|
||||
if ( expression.evaluate( &expressionContext ).toBool() )
|
||||
{
|
||||
mMatchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
matchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
}
|
||||
else
|
||||
{
|
||||
mNonMatchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
nonMatchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
}
|
||||
|
||||
feedback->setProgress( current * step );
|
||||
current++;
|
||||
}
|
||||
}
|
||||
if ( mMatchingSink )
|
||||
mMatchingSink->flushBuffer();
|
||||
if ( mNonMatchingSink )
|
||||
mNonMatchingSink->flushBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QVariantMap QgsExtractByExpressionAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), mMatchingSinkId );
|
||||
if ( !mNonMatchingSinkId.isEmpty() )
|
||||
outputs.insert( QStringLiteral( "FAIL_OUTPUT" ), mNonMatchingSinkId );
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), matchingSinkId );
|
||||
if ( nonMatchingSink )
|
||||
outputs.insert( QStringLiteral( "FAIL_OUTPUT" ), nonMatchingSinkId );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
||||
QgsExtractByAttributeAlgorithm::QgsExtractByAttributeAlgorithm()
|
||||
{
|
||||
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
|
||||
@ -1013,38 +937,34 @@ QgsExtractByAttributeAlgorithm *QgsExtractByAttributeAlgorithm::create() const
|
||||
return new QgsExtractByAttributeAlgorithm();
|
||||
}
|
||||
|
||||
bool QgsExtractByAttributeAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
QVariantMap QgsExtractByAttributeAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
mSource.reset( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !mSource )
|
||||
return false;
|
||||
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
||||
if ( !source )
|
||||
return QVariantMap();
|
||||
|
||||
mFieldName = parameterAsString( parameters, QStringLiteral( "FIELD" ), context );
|
||||
mOp = static_cast< Operation >( parameterAsEnum( parameters, QStringLiteral( "OPERATOR" ), context ) );
|
||||
mValue = parameterAsString( parameters, QStringLiteral( "VALUE" ), context );
|
||||
QString fieldName = parameterAsString( parameters, QStringLiteral( "FIELD" ), context );
|
||||
Operation op = static_cast< Operation >( parameterAsEnum( parameters, QStringLiteral( "OPERATOR" ), context ) );
|
||||
QString value = parameterAsString( parameters, QStringLiteral( "VALUE" ), context );
|
||||
|
||||
mMatchingSink.reset( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, mMatchingSinkId, mSource->fields(),
|
||||
mSource->wkbType(), mSource->sourceCrs() ) );
|
||||
if ( !mMatchingSink )
|
||||
return false;
|
||||
QString matchingSinkId;
|
||||
std::unique_ptr< QgsFeatureSink > matchingSink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, matchingSinkId, source->fields(),
|
||||
source->wkbType(), source->sourceCrs() ) );
|
||||
if ( !matchingSink )
|
||||
return QVariantMap();
|
||||
|
||||
mNonMatchingSink.reset( parameterAsSink( parameters, QStringLiteral( "FAIL_OUTPUT" ), context, mNonMatchingSinkId, mSource->fields(),
|
||||
mSource->wkbType(), mSource->sourceCrs() ) );
|
||||
QString nonMatchingSinkId;
|
||||
std::unique_ptr< QgsFeatureSink > nonMatchingSink( parameterAsSink( parameters, QStringLiteral( "FAIL_OUTPUT" ), context, nonMatchingSinkId, source->fields(),
|
||||
source->wkbType(), source->sourceCrs() ) );
|
||||
|
||||
|
||||
mExpressionContext = createExpressionContext( parameters, context );
|
||||
return true;
|
||||
}
|
||||
int idx = source->fields().lookupField( fieldName );
|
||||
QVariant::Type fieldType = source->fields().at( idx ).type();
|
||||
|
||||
bool QgsExtractByAttributeAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
int idx = mSource->fields().lookupField( mFieldName );
|
||||
QVariant::Type fieldType = mSource->fields().at( idx ).type();
|
||||
|
||||
if ( fieldType != QVariant::String && ( mOp == BeginsWith || mOp == Contains || mOp == DoesNotContain ) )
|
||||
if ( fieldType != QVariant::String && ( op == BeginsWith || op == Contains || op == DoesNotContain ) )
|
||||
{
|
||||
QString method;
|
||||
switch ( mOp )
|
||||
switch ( op )
|
||||
{
|
||||
case BeginsWith:
|
||||
method = QObject::tr( "begins with" );
|
||||
@ -1063,10 +983,10 @@ bool QgsExtractByAttributeAlgorithm::processAlgorithm( QgsProcessingContext &, Q
|
||||
throw QgsProcessingException( QObject::tr( "Operator '%1' can be used only with string fields." ).arg( method ) );
|
||||
}
|
||||
|
||||
QString fieldRef = QgsExpression::quotedColumnRef( mFieldName );
|
||||
QString quotedVal = QgsExpression::quotedValue( mValue );
|
||||
QString fieldRef = QgsExpression::quotedColumnRef( fieldName );
|
||||
QString quotedVal = QgsExpression::quotedValue( value );
|
||||
QString expr;
|
||||
switch ( mOp )
|
||||
switch ( op )
|
||||
{
|
||||
case Equals:
|
||||
expr = QStringLiteral( "%1 = %3" ).arg( fieldRef, quotedVal );
|
||||
@ -1087,10 +1007,10 @@ bool QgsExtractByAttributeAlgorithm::processAlgorithm( QgsProcessingContext &, Q
|
||||
expr = QStringLiteral( "%1 <= %3" ).arg( fieldRef, quotedVal );
|
||||
break;
|
||||
case BeginsWith:
|
||||
expr = QStringLiteral( "%1 LIKE '%2%'" ).arg( fieldRef, mValue );
|
||||
expr = QStringLiteral( "%1 LIKE '%2%'" ).arg( fieldRef, value );
|
||||
break;
|
||||
case Contains:
|
||||
expr = QStringLiteral( "%1 LIKE '%%2%'" ).arg( fieldRef, mValue );
|
||||
expr = QStringLiteral( "%1 LIKE '%%2%'" ).arg( fieldRef, value );
|
||||
break;
|
||||
case IsNull:
|
||||
expr = QStringLiteral( "%1 IS NULL" ).arg( fieldRef );
|
||||
@ -1099,31 +1019,34 @@ bool QgsExtractByAttributeAlgorithm::processAlgorithm( QgsProcessingContext &, Q
|
||||
expr = QStringLiteral( "%1 IS NOT NULL" ).arg( fieldRef );
|
||||
break;
|
||||
case DoesNotContain:
|
||||
expr = QStringLiteral( "%1 NOT LIKE '%%2%'" ).arg( fieldRef, mValue );
|
||||
expr = QStringLiteral( "%1 NOT LIKE '%%2%'" ).arg( fieldRef, value );
|
||||
break;
|
||||
}
|
||||
|
||||
QgsExpression expression( expr );
|
||||
if ( expression.hasParserError() )
|
||||
{
|
||||
throw QgsProcessingException( expression.parserErrorString() );
|
||||
// raise GeoAlgorithmExecutionException(expression.parserErrorString())
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
long count = mSource->featureCount();
|
||||
if ( count == 0 )
|
||||
return true;
|
||||
QgsExpressionContext expressionContext = createExpressionContext( parameters, context );
|
||||
|
||||
long count = source->featureCount();
|
||||
if ( count <= 0 )
|
||||
return QVariantMap();
|
||||
|
||||
double step = 100.0 / count;
|
||||
int current = 0;
|
||||
|
||||
if ( !mNonMatchingSink )
|
||||
if ( !nonMatchingSink )
|
||||
{
|
||||
// not saving failing features - so only fetch good features
|
||||
QgsFeatureRequest req;
|
||||
req.setFilterExpression( expr );
|
||||
req.setExpressionContext( mExpressionContext );
|
||||
req.setExpressionContext( expressionContext );
|
||||
|
||||
QgsFeatureIterator it = mSource->getFeatures( req );
|
||||
QgsFeatureIterator it = source->getFeatures( req );
|
||||
QgsFeature f;
|
||||
while ( it.nextFeature( f ) )
|
||||
{
|
||||
@ -1132,7 +1055,7 @@ bool QgsExtractByAttributeAlgorithm::processAlgorithm( QgsProcessingContext &, Q
|
||||
break;
|
||||
}
|
||||
|
||||
mMatchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
matchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
|
||||
feedback->setProgress( current * step );
|
||||
current++;
|
||||
@ -1141,10 +1064,10 @@ bool QgsExtractByAttributeAlgorithm::processAlgorithm( QgsProcessingContext &, Q
|
||||
else
|
||||
{
|
||||
// saving non-matching features, so we need EVERYTHING
|
||||
mExpressionContext.setFields( mSource->fields() );
|
||||
expression.prepare( &mExpressionContext );
|
||||
expressionContext.setFields( source->fields() );
|
||||
expression.prepare( &expressionContext );
|
||||
|
||||
QgsFeatureIterator it = mSource->getFeatures();
|
||||
QgsFeatureIterator it = source->getFeatures();
|
||||
QgsFeature f;
|
||||
while ( it.nextFeature( f ) )
|
||||
{
|
||||
@ -1153,14 +1076,14 @@ bool QgsExtractByAttributeAlgorithm::processAlgorithm( QgsProcessingContext &, Q
|
||||
break;
|
||||
}
|
||||
|
||||
mExpressionContext.setFeature( f );
|
||||
if ( expression.evaluate( &mExpressionContext ).toBool() )
|
||||
expressionContext.setFeature( f );
|
||||
if ( expression.evaluate( &expressionContext ).toBool() )
|
||||
{
|
||||
mMatchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
matchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
}
|
||||
else
|
||||
{
|
||||
mNonMatchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
nonMatchingSink->addFeature( f, QgsFeatureSink::FastInsert );
|
||||
}
|
||||
|
||||
feedback->setProgress( current * step );
|
||||
@ -1168,21 +1091,12 @@ bool QgsExtractByAttributeAlgorithm::processAlgorithm( QgsProcessingContext &, Q
|
||||
}
|
||||
}
|
||||
|
||||
if ( mMatchingSink )
|
||||
mMatchingSink->flushBuffer();
|
||||
if ( mNonMatchingSink )
|
||||
mNonMatchingSink->flushBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsExtractByAttributeAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), mMatchingSinkId );
|
||||
if ( !mNonMatchingSinkId.isEmpty() )
|
||||
outputs.insert( QStringLiteral( "FAIL_OUTPUT" ), mNonMatchingSinkId );
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), matchingSinkId );
|
||||
if ( nonMatchingSink )
|
||||
outputs.insert( QStringLiteral( "FAIL_OUTPUT" ), nonMatchingSinkId );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
||||
///@endcond
|
||||
|
@ -64,16 +64,9 @@ class QgsCentroidAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
protected:
|
||||
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr< QgsFeatureSource > mSource;
|
||||
std::unique_ptr< QgsFeatureSink > mSink;
|
||||
QString mSinkId;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -95,17 +88,9 @@ class QgsTransformAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
protected:
|
||||
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr< QgsFeatureSource > mSource;
|
||||
std::unique_ptr< QgsFeatureSink > mSink;
|
||||
QString mSinkId;
|
||||
QgsCoordinateReferenceSystem mCrs;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -127,27 +112,9 @@ class QgsBufferAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
protected:
|
||||
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr< QgsFeatureSource > mSource;
|
||||
std::unique_ptr< QgsFeatureSink > mSink;
|
||||
QString mSinkId;
|
||||
bool mDissolve = false;
|
||||
int mSegments = 8;
|
||||
QgsGeometry::EndCapStyle mEndCapStyle = QgsGeometry::CapRound;
|
||||
QgsGeometry::JoinStyle mJoinStyle = QgsGeometry::JoinStyleRound;
|
||||
double mMiterLimit = 1;
|
||||
double mBufferDistance = 1;
|
||||
bool mDynamicBuffer = false;
|
||||
QgsProperty mDynamicBufferProperty;
|
||||
QVariantMap mDynamicParams;
|
||||
double mDefaultBuffer;
|
||||
QgsExpressionContext mExpContext;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -169,17 +136,8 @@ class QgsDissolveAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
protected:
|
||||
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr< QgsFeatureSource > mSource;
|
||||
std::unique_ptr< QgsFeatureSink > mSink;
|
||||
QString mSinkId;
|
||||
QStringList mFields;
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
};
|
||||
|
||||
@ -217,22 +175,9 @@ class QgsExtractByAttributeAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
protected:
|
||||
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr< QgsFeatureSource > mSource;
|
||||
std::unique_ptr< QgsFeatureSink > mMatchingSink;
|
||||
QString mMatchingSinkId;
|
||||
std::unique_ptr< QgsFeatureSink > mNonMatchingSink;
|
||||
QString mNonMatchingSinkId;
|
||||
QString mFieldName;
|
||||
Operation mOp;
|
||||
QString mValue;
|
||||
QgsExpressionContext mExpressionContext;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -254,20 +199,9 @@ class QgsExtractByExpressionAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
protected:
|
||||
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr< QgsFeatureSource > mSource;
|
||||
std::unique_ptr< QgsFeatureSink > mMatchingSink;
|
||||
QString mMatchingSinkId;
|
||||
std::unique_ptr< QgsFeatureSink > mNonMatchingSink;
|
||||
QString mNonMatchingSinkId;
|
||||
QString mExpressionString;
|
||||
QgsExpressionContext mExpressionContext;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -289,18 +223,8 @@ class QgsClipAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
protected:
|
||||
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr< QgsFeatureSource > mFeatureSource;
|
||||
std::unique_ptr< QgsFeatureSource > mMaskSource;
|
||||
std::unique_ptr< QgsFeatureSink > mSink;
|
||||
QString mSinkId;
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
};
|
||||
|
||||
@ -324,17 +248,8 @@ class QgsSubdivideAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
protected:
|
||||
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr< QgsFeatureSource > mSource;
|
||||
std::unique_ptr< QgsFeatureSink > mSink;
|
||||
QString mSinkId;
|
||||
int mMaxNodes = 64;
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
};
|
||||
|
||||
@ -357,16 +272,9 @@ class QgsMultipartToSinglepartAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
protected:
|
||||
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr< QgsFeatureSource > mSource;
|
||||
std::unique_ptr< QgsFeatureSink > mSink;
|
||||
QString mSinkId;
|
||||
};
|
||||
|
||||
///@endcond PRIVATE
|
||||
|
@ -265,6 +265,11 @@ bool QgsProcessingAlgorithm::prepareAlgorithm( const QVariantMap &, QgsProcessin
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsProcessingAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
const QgsProcessingParameterDefinition *QgsProcessingAlgorithm::parameterDefinition( const QString &name ) const
|
||||
{
|
||||
Q_FOREACH ( const QgsProcessingParameterDefinition *def, mParameters )
|
||||
@ -329,14 +334,19 @@ QVariantMap QgsProcessingAlgorithm::run( const QVariantMap ¶meters, QgsProce
|
||||
if ( !res )
|
||||
return QVariantMap();
|
||||
|
||||
res = alg->runPrepared( context, feedback );
|
||||
if ( !res )
|
||||
QVariantMap runRes = alg->runPrepared( parameters, context, feedback );
|
||||
|
||||
if ( !alg->mHasExecuted )
|
||||
return QVariantMap();
|
||||
|
||||
if ( ok )
|
||||
*ok = true;
|
||||
|
||||
return alg->postProcess( context, feedback );
|
||||
QVariantMap ppRes = alg->postProcess( context, feedback );
|
||||
if ( !ppRes.isEmpty() )
|
||||
return ppRes;
|
||||
else
|
||||
return runRes;
|
||||
}
|
||||
|
||||
bool QgsProcessingAlgorithm::prepare( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
@ -356,9 +366,9 @@ bool QgsProcessingAlgorithm::prepare( const QVariantMap ¶meters, QgsProcessi
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsProcessingAlgorithm::runPrepared( QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
QVariantMap QgsProcessingAlgorithm::runPrepared( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
Q_ASSERT_X( mHasPrepared, "QgsProcessingAlgorithm::runPrepared", "prepare() was not called for the algorithm instance" );
|
||||
Q_ASSERT_X( mHasPrepared, "QgsProcessingAlgorithm::runPrepared", QString( "prepare() was not called for the algorithm instance %1" ).arg( name() ).toLatin1() );
|
||||
Q_ASSERT_X( !mHasExecuted, "QgsProcessingAlgorithm::runPrepared", "runPrepared() was already called for this algorithm instance" );
|
||||
|
||||
// Hey kids, let's all be thread safe! It's the fun thing to do!
|
||||
@ -388,8 +398,9 @@ bool QgsProcessingAlgorithm::runPrepared( QgsProcessingContext &context, QgsProc
|
||||
|
||||
try
|
||||
{
|
||||
mHasExecuted = processAlgorithm( *runContext, feedback );
|
||||
QVariantMap runResults = processAlgorithm( parameters, *runContext, feedback );
|
||||
|
||||
mHasExecuted = true;
|
||||
if ( mLocalContext )
|
||||
{
|
||||
// ok, time to clean things up. We need to push the temporary context back into
|
||||
@ -397,7 +408,7 @@ bool QgsProcessingAlgorithm::runPrepared( QgsProcessingContext &context, QgsProc
|
||||
// current thread, so we HAVE to do this here)
|
||||
mLocalContext->pushToThread( context.thread() );
|
||||
}
|
||||
return mHasExecuted;
|
||||
return runResults;
|
||||
}
|
||||
catch ( QgsProcessingException &e )
|
||||
{
|
||||
@ -409,14 +420,14 @@ bool QgsProcessingAlgorithm::runPrepared( QgsProcessingContext &context, QgsProc
|
||||
// see above!
|
||||
mLocalContext->pushToThread( context.thread() );
|
||||
}
|
||||
return false;
|
||||
return QVariantMap();
|
||||
}
|
||||
}
|
||||
|
||||
QVariantMap QgsProcessingAlgorithm::postProcess( QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
Q_ASSERT_X( QThread::currentThread() == context.temporaryLayerStore()->thread(), "QgsProcessingAlgorithm::postProcess", "postProcess() must be called from the same thread the context was created in" );
|
||||
Q_ASSERT_X( mHasExecuted, "QgsProcessingAlgorithm::postProcess", "runPrepared() was not called for the algorithm instance" );
|
||||
Q_ASSERT_X( mHasExecuted, "QgsProcessingAlgorithm::postProcess", QString( "algorithm instance %1 was not executed" ).arg( name() ).toLatin1() );
|
||||
Q_ASSERT_X( !mHasPostProcessed, "QgsProcessingAlgorithm::postProcess", "postProcess() was already called for this algorithm instance" );
|
||||
|
||||
if ( mLocalContext )
|
||||
|
@ -265,7 +265,7 @@ class CORE_EXPORT QgsProcessingAlgorithm
|
||||
* on algorithms directly retrieved from QgsProcessingRegistry and QgsProcessingProvider. Instead, a copy
|
||||
* of the algorithm should be created with clone() and prepare()/runPrepared() called on the copy.
|
||||
*/
|
||||
bool runPrepared( QgsProcessingContext &context, QgsProcessingFeedback *feedback );
|
||||
QVariantMap runPrepared( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback );
|
||||
|
||||
/**
|
||||
* Should be called in the main thread following the completion of runPrepared(). This method
|
||||
@ -371,7 +371,7 @@ class CORE_EXPORT QgsProcessingAlgorithm
|
||||
* \see prepareAlgorithm()
|
||||
* \see postProcessAlgorithm()
|
||||
*/
|
||||
virtual bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) = 0 SIP_VIRTUALERRORHANDLER( processing_exception_handler );
|
||||
virtual QVariantMap processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) = 0 SIP_VIRTUALERRORHANDLER( processing_exception_handler );
|
||||
|
||||
/**
|
||||
* Allows the algorithm to perform any required cleanup tasks. The returned variant map
|
||||
@ -389,7 +389,7 @@ class CORE_EXPORT QgsProcessingAlgorithm
|
||||
* \see prepareAlgorithm()
|
||||
* \see processAlgorithm()
|
||||
*/
|
||||
virtual QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) = 0 SIP_VIRTUALERRORHANDLER( processing_exception_handler );
|
||||
virtual QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) SIP_VIRTUALERRORHANDLER( processing_exception_handler );
|
||||
|
||||
/**
|
||||
* Evaluates the parameter with matching \a name to a static string value.
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
QgsProcessingAlgRunnerTask::QgsProcessingAlgRunnerTask( const QgsProcessingAlgorithm *algorithm, const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
: QgsTask( tr( "Running %1" ).arg( algorithm->name() ), QgsTask::CanCancel )
|
||||
, mParameters( parameters )
|
||||
, mContext( context )
|
||||
, mFeedback( feedback )
|
||||
, mAlgorithm( algorithm->create() )
|
||||
@ -33,7 +34,7 @@ QgsProcessingAlgRunnerTask::QgsProcessingAlgRunnerTask( const QgsProcessingAlgor
|
||||
mOwnedFeedback.reset( new QgsProcessingFeedback() );
|
||||
mFeedback = mOwnedFeedback.get();
|
||||
}
|
||||
if ( !mAlgorithm->prepare( parameters, context, mFeedback ) )
|
||||
if ( !mAlgorithm->prepare( mParameters, context, mFeedback ) )
|
||||
cancel();
|
||||
}
|
||||
|
||||
@ -48,7 +49,8 @@ bool QgsProcessingAlgRunnerTask::run()
|
||||
bool ok = false;
|
||||
try
|
||||
{
|
||||
ok = mAlgorithm->runPrepared( mContext, mFeedback );
|
||||
mResults = mAlgorithm->runPrepared( mParameters, mContext, mFeedback );
|
||||
ok = true;
|
||||
}
|
||||
catch ( QgsProcessingException & )
|
||||
{
|
||||
@ -60,9 +62,10 @@ bool QgsProcessingAlgRunnerTask::run()
|
||||
void QgsProcessingAlgRunnerTask::finished( bool result )
|
||||
{
|
||||
Q_UNUSED( result );
|
||||
QVariantMap ppResults;
|
||||
if ( result )
|
||||
{
|
||||
mResults = mAlgorithm->postProcess( mContext, mFeedback );
|
||||
ppResults = mAlgorithm->postProcess( mContext, mFeedback );
|
||||
}
|
||||
emit executed( result, mResults );
|
||||
emit executed( result, !ppResults.isEmpty() ? ppResults : mResults );
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ class CORE_EXPORT QgsProcessingAlgRunnerTask : public QgsTask
|
||||
|
||||
private:
|
||||
|
||||
QVariantMap mParameters;
|
||||
QVariantMap mResults;
|
||||
QgsProcessingContext &mContext;
|
||||
QgsProcessingFeedback *mFeedback = nullptr;
|
||||
|
@ -472,7 +472,7 @@ bool QgsProcessingModelAlgorithm::childOutputIsRequired( const QString &childId,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsProcessingModelAlgorithm::processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
|
||||
{
|
||||
QSet< QString > toExecute;
|
||||
QMap< QString, ChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
|
||||
@ -515,7 +515,7 @@ bool QgsProcessingModelAlgorithm::processAlgorithm( QgsProcessingContext &contex
|
||||
|
||||
const ChildAlgorithm &child = mChildAlgorithms[ childId ];
|
||||
|
||||
QVariantMap childParams = parametersForChildAlgorithm( child, mInputParameters, childResults );
|
||||
QVariantMap childParams = parametersForChildAlgorithm( child, parameters, childResults );
|
||||
feedback->setProgressText( QObject::tr( "Running %1 [%2/%3]" ).arg( child.description() ).arg( executed.count() + 1 ).arg( toExecute.count() ) );
|
||||
//feedback->pushDebugInfo( "Parameters: " + ', '.join( [str( p ).strip() +
|
||||
// '=' + str( p.value ) for p in alg.algorithm.parameters] ) )
|
||||
@ -551,11 +551,6 @@ bool QgsProcessingModelAlgorithm::processAlgorithm( QgsProcessingContext &contex
|
||||
feedback->pushDebugInfo( QObject::tr( "Model processed OK. Executed %1 algorithms total in %2 s." ).arg( executed.count() ).arg( totalTime.elapsed() / 1000.0 ) );
|
||||
|
||||
mResults = finalResults;
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsProcessingModelAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
return mResults;
|
||||
}
|
||||
|
||||
@ -655,12 +650,6 @@ QString QgsProcessingModelAlgorithm::asPythonCode() const
|
||||
return lines.join( '\n' );
|
||||
}
|
||||
|
||||
bool QgsProcessingModelAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
mInputParameters = parameters;
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariantMap QgsProcessingModelAlgorithm::helpContent() const
|
||||
{
|
||||
return mHelpContent;
|
||||
|
@ -826,10 +826,7 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
protected:
|
||||
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters,
|
||||
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
bool processAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QVariantMap processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
@ -846,8 +843,6 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
|
||||
//! Model source file
|
||||
QString mSourceFile;
|
||||
|
||||
QVariantMap mInputParameters;
|
||||
|
||||
QVariantMap mResults;
|
||||
|
||||
void dependsOnChildAlgorithmsRecursive( const QString &childId, QSet<QString> &depends ) const;
|
||||
|
@ -42,9 +42,7 @@ class DummyAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
QString name() const override { return mName; }
|
||||
QString displayName() const override { return mName; }
|
||||
bool processAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * ) override { return true; }
|
||||
bool prepareAlgorithm( const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * ) override { return true; }
|
||||
QVariantMap postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * ) override { return QVariantMap(); }
|
||||
QVariantMap processAlgorithm( const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * ) override { return QVariantMap(); }
|
||||
|
||||
virtual Flags flags() const override { return mFlags; }
|
||||
DummyAlgorithm *create() const override { return new DummyAlgorithm( name() ); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user