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