mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Upgrade ported python algs to be thread ready
This commit is contained in:
parent
c2621b1275
commit
cd7776ca1c
@ -74,28 +74,38 @@ class AddTableField(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT_LAYER, self.tr('Added')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT_LAYER, self.tr('Added')))
|
||||
|
||||
self.source = None
|
||||
self.fieldType = None
|
||||
self.fieldLength = None
|
||||
self.fieldName = None
|
||||
self.fieldPrecision = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'addfieldtoattributestable'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Add field to attributes table')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
|
||||
fieldType = self.parameterAsEnum(parameters, self.FIELD_TYPE, context)
|
||||
fieldName = self.parameterAsString(parameters, self.FIELD_NAME, context)
|
||||
fieldLength = self.parameterAsInt(parameters, self.FIELD_LENGTH, context)
|
||||
fieldPrecision = self.parameterAsInt(parameters, self.FIELD_PRECISION, context)
|
||||
self.fieldType = self.parameterAsEnum(parameters, self.FIELD_TYPE, context)
|
||||
self.fieldName = self.parameterAsString(parameters, self.FIELD_NAME, context)
|
||||
self.fieldLength = self.parameterAsInt(parameters, self.FIELD_LENGTH, context)
|
||||
self.fieldPrecision = self.parameterAsInt(parameters, self.FIELD_PRECISION, context)
|
||||
|
||||
fields = source.fields()
|
||||
fields.append(QgsField(fieldName, self.TYPES[fieldType], '',
|
||||
fieldLength, fieldPrecision))
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
fields, source.wkbType(), source.sourceCrs())
|
||||
fields = self.source.fields()
|
||||
fields.append(QgsField(self.fieldName, self.TYPES[self.fieldType], '',
|
||||
self.fieldLength, self.fieldPrecision))
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
fields, self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
@ -106,7 +116,10 @@ class AddTableField(QgisAlgorithm):
|
||||
attributes.append(None)
|
||||
output_feature.setAttributes(attributes)
|
||||
|
||||
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
return {self.OUTPUT_LAYER: dest_id}
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT_LAYER: self.dest_id}
|
||||
|
@ -47,7 +47,7 @@ pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
|
||||
class Aspect(QgisAlgorithm):
|
||||
|
||||
INPUT_LAYER = 'INPUT_LAYER'
|
||||
INPUT = 'INPUT'
|
||||
Z_FACTOR = 'Z_FACTOR'
|
||||
OUTPUT_LAYER = 'OUTPUT_LAYER'
|
||||
|
||||
@ -60,13 +60,18 @@ class Aspect(QgisAlgorithm):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.addParameter(QgsProcessingParameterRasterLayer(self.INPUT_LAYER,
|
||||
self.addParameter(QgsProcessingParameterRasterLayer(self.INPUT,
|
||||
self.tr('Elevation layer')))
|
||||
self.addParameter(QgsProcessingParameterNumber(self.Z_FACTOR,
|
||||
self.tr('Z factor'), QgsProcessingParameterNumber.Double,
|
||||
1, False, 1, 999999.99))
|
||||
self.addParameter(QgsProcessingParameterRasterOutput(self.OUTPUT_LAYER, self.tr('Aspect')))
|
||||
self.addOutput(QgsProcessingOutputRasterLayer(self.OUTPUT_LAYER, self.tr('Aspect')))
|
||||
self.addParameter(QgsProcessingParameterRasterOutput(self.OUTPUT, self.tr('Aspect')))
|
||||
self.addOutput(QgsProcessingOutputRasterLayer(self.OUTPUT, self.tr('Aspect')))
|
||||
|
||||
self.inputFile = None
|
||||
self.outputFile = None
|
||||
self.outputFormat = None
|
||||
self.zFactor = None
|
||||
|
||||
def name(self):
|
||||
return 'aspect'
|
||||
@ -74,16 +79,19 @@ class Aspect(QgisAlgorithm):
|
||||
def displayName(self):
|
||||
return self.tr('Aspect')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
inputFile = exportRasterLayer(self.parameterAsRasterLayer(parameters, self.INPUT_LAYER, context))
|
||||
zFactor = self.parameterAsDouble(parameters, self.Z_FACTOR, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.inputFile = exportRasterLayer(self.parameterAsRasterLayer(parameters, self.INPUT, context))
|
||||
self.zFactor = self.parameterAsDouble(parameters, self.Z_FACTOR, context)
|
||||
|
||||
outputFile = self.parameterAsRasterOutputLayer(parameters, self.OUTPUT_LAYER, context)
|
||||
self.outputFile = self.parameterAsRasterOutputLayer(parameters, self.OUTPUT, context)
|
||||
|
||||
outputFormat = raster.formatShortNameFromFileName(outputFile)
|
||||
self.outputFormat = raster.formatShortNameFromFileName(self.outputFile)
|
||||
return True
|
||||
|
||||
aspect = QgsAspectFilter(inputFile, outputFile, outputFormat)
|
||||
aspect.setZFactor(zFactor)
|
||||
aspect.processRaster(feedback)
|
||||
def processAlgorithm(self, context, feedback):
|
||||
aspect = QgsAspectFilter(self.inputFile, self.outputFile, self.outputFormat)
|
||||
aspect.setZFactor(self.zFactor)
|
||||
return aspect.processRaster(feedback) == 0
|
||||
|
||||
return {self.OUTPUT_LAYER: outputFile}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.outputFile}
|
||||
|
@ -51,6 +51,10 @@ class AutoincrementalField(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Incremented')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Incremented')))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def group(self):
|
||||
return self.tr('Vector table tools')
|
||||
|
||||
@ -60,16 +64,18 @@ class AutoincrementalField(QgisAlgorithm):
|
||||
def displayName(self):
|
||||
return self.tr('Add autoincremental field')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
fields = source.fields()
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
fields = self.source.fields()
|
||||
fields.append(QgsField('AUTO', QVariant.Int))
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, source.wkbType(), source.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
@ -79,7 +85,9 @@ class AutoincrementalField(QgisAlgorithm):
|
||||
attributes.append(current)
|
||||
output_feature.setAttributes(attributes)
|
||||
|
||||
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -119,42 +119,52 @@ class BasicStatisticsForField(QgisAlgorithm):
|
||||
self.addOutput(QgsProcessingOutputNumber(self.THIRDQUARTILE, self.tr('Third quartile')))
|
||||
self.addOutput(QgsProcessingOutputNumber(self.IQR, self.tr('Interquartile Range (IQR)')))
|
||||
|
||||
self.source = None
|
||||
self.field = None
|
||||
self.field_name = None
|
||||
self.output_file = None
|
||||
self.results = {}
|
||||
|
||||
def name(self):
|
||||
return 'basicstatisticsforfields'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Basic statistics for fields')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
field_name = self.parameterAsString(parameters, self.FIELD_NAME, context)
|
||||
field = source.fields().at(source.fields().lookupField(field_name))
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
self.field_name = self.parameterAsString(parameters, self.FIELD_NAME, context)
|
||||
self.field = self.source.fields().at(self.source.fields().lookupField(self.field_name))
|
||||
|
||||
output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context)
|
||||
self.output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context)
|
||||
return True
|
||||
|
||||
request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry).setSubsetOfAttributes([field_name], source.fields())
|
||||
features = source.getFeatures(request)
|
||||
count = source.featureCount()
|
||||
def processAlgorithm(self, context, feedback):
|
||||
request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry).setSubsetOfAttributes([self.field_name], self.source.fields())
|
||||
features = self.source.getFeatures(request)
|
||||
count = self.source.featureCount()
|
||||
|
||||
data = []
|
||||
data.append(self.tr('Analyzed field: {}').format(field_name))
|
||||
results = {}
|
||||
data.append(self.tr('Analyzed field: {}').format(self.field_name))
|
||||
|
||||
if field.isNumeric():
|
||||
d, results = self.calcNumericStats(features, feedback, field, count)
|
||||
if self.field.isNumeric():
|
||||
d, self.results = self.calcNumericStats(features, feedback, self.field, count)
|
||||
data.extend(d)
|
||||
elif field.type() in (QVariant.Date, QVariant.Time, QVariant.DateTime):
|
||||
d, results = self.calcDateTimeStats(features, feedback, field, count)
|
||||
elif self.field.type() in (QVariant.Date, QVariant.Time, QVariant.DateTime):
|
||||
d, self.results = self.calcDateTimeStats(features, feedback, self.field, count)
|
||||
data.extend(d)
|
||||
else:
|
||||
d, results = self.calcStringStats(features, feedback, field, count)
|
||||
d, self.results = self.calcStringStats(features, feedback, self.field, count)
|
||||
data.extend(d)
|
||||
|
||||
if output_file:
|
||||
self.createHTML(output_file, data)
|
||||
results[self.OUTPUT_HTML_FILE] = output_file
|
||||
if self.output_file:
|
||||
self.createHTML(self.output_file, data)
|
||||
self.results[self.OUTPUT_HTML_FILE] = self.output_file
|
||||
|
||||
return results
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return self.results
|
||||
|
||||
def calcNumericStats(self, features, feedback, field, count):
|
||||
total = 100.0 / count if count else 0
|
||||
|
@ -58,6 +58,10 @@ class Boundary(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT_LAYER, self.tr('Boundary')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT_LAYER, self.tr("Boundaries")))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def icon(self):
|
||||
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'convex_hull.png'))
|
||||
|
||||
@ -70,10 +74,11 @@ class Boundary(QgisAlgorithm):
|
||||
def displayName(self):
|
||||
return self.tr('Boundary')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
|
||||
input_wkb = source.wkbType()
|
||||
input_wkb = self.source.wkbType()
|
||||
output_wkb = None
|
||||
if QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.LineGeometry:
|
||||
output_wkb = QgsWkbTypes.MultiPoint
|
||||
elif QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.PolygonGeometry:
|
||||
@ -83,11 +88,13 @@ class Boundary(QgisAlgorithm):
|
||||
if QgsWkbTypes.hasM(input_wkb):
|
||||
output_wkb = QgsWkbTypes.addM(output_wkb)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
source.fields(), output_wkb, source.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
self.source.fields(), output_wkb, self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
@ -102,7 +109,9 @@ class Boundary(QgisAlgorithm):
|
||||
|
||||
output_feature.setGeometry(output_geometry)
|
||||
|
||||
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
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}
|
||||
|
@ -66,20 +66,26 @@ class BoundingBox(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT_LAYER, self.tr('Bounds'), QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT_LAYER, self.tr("Bounds")))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'boundingboxes'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Bounding boxes')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
source.fields(), QgsWkbTypes.Polygon, source.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
|
||||
self.source.fields(), QgsWkbTypes.Polygon, self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
@ -94,7 +100,9 @@ class BoundingBox(QgisAlgorithm):
|
||||
|
||||
output_feature.setGeometry(output_geometry)
|
||||
|
||||
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
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}
|
||||
|
@ -93,46 +93,60 @@ class CheckValidity(QgisAlgorithm):
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.ERROR_OUTPUT, self.tr('Error output')))
|
||||
self.addOutput(QgsProcessingOutputNumber(self.ERROR_COUNT, self.tr('Count of errors')))
|
||||
|
||||
self.method = None
|
||||
self.source = None
|
||||
self.valid_output_sink = None
|
||||
self.valid_output_dest_id = None
|
||||
self.valid_count = 0
|
||||
self.invalid_output_sink = None
|
||||
self.invalid_output_dest_id = None
|
||||
self.invalid_count = 0
|
||||
self.error_output_sink = None
|
||||
self.error_output_dest_id = None
|
||||
self.error_count = 0
|
||||
|
||||
def name(self):
|
||||
return 'checkvalidity'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Check validity')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
method_param = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
if method_param == 0:
|
||||
settings = QgsSettings()
|
||||
method = int(settings.value(settings_method_key, 0)) - 1
|
||||
if method < 0:
|
||||
method = 0
|
||||
self.method = int(settings.value(settings_method_key, 0)) - 1
|
||||
if self.method < 0:
|
||||
self.method = 0
|
||||
else:
|
||||
method = method_param - 1
|
||||
self.method = method_param - 1
|
||||
|
||||
results = self.doCheck(method, parameters, context, feedback)
|
||||
return results
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
|
||||
def doCheck(self, method, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
(self.valid_output_sink, self.valid_output_dest_id) = self.parameterAsSink(parameters, self.VALID_OUTPUT,
|
||||
context,
|
||||
self.source.fields(),
|
||||
self.source.wkbType(),
|
||||
self.source.sourceCrs())
|
||||
|
||||
(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 = self.source.fields()
|
||||
invalid_fields.append(QgsField('_errors', QVariant.String, 'string', 255))
|
||||
(invalid_output_sink, invalid_output_dest_id) = self.parameterAsSink(parameters, self.INVALID_OUTPUT, context,
|
||||
invalid_fields, source.wkbType(), source.sourceCrs())
|
||||
invalid_count = 0
|
||||
(self.invalid_output_sink, self.invalid_output_dest_id) = self.parameterAsSink(parameters, self.INVALID_OUTPUT,
|
||||
context,
|
||||
invalid_fields,
|
||||
self.source.wkbType(),
|
||||
self.source.sourceCrs())
|
||||
|
||||
error_fields = QgsFields()
|
||||
error_fields.append(QgsField('message', QVariant.String, 'string', 255))
|
||||
(error_output_sink, error_output_dest_id) = self.parameterAsSink(parameters, self.ERROR_OUTPUT, context,
|
||||
error_fields, QgsWkbTypes.Point, source.sourceCrs())
|
||||
error_count = 0
|
||||
(self.error_output_sink, self.error_output_dest_id) = self.parameterAsSink(parameters, self.ERROR_OUTPUT, context,
|
||||
error_fields, QgsWkbTypes.Point,
|
||||
self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
features = source.getFeatures(QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures(QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
for current, inFeat in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
@ -141,10 +155,10 @@ class CheckValidity(QgisAlgorithm):
|
||||
|
||||
valid = True
|
||||
if not geom.isNull() and not geom.isEmpty():
|
||||
errors = list(geom.validateGeometry(method))
|
||||
errors = list(geom.validateGeometry(self.method))
|
||||
if errors:
|
||||
# QGIS method return a summary at the end
|
||||
if method == 1:
|
||||
if self.method == 1:
|
||||
errors.pop()
|
||||
valid = False
|
||||
reasons = []
|
||||
@ -153,9 +167,9 @@ class CheckValidity(QgisAlgorithm):
|
||||
error_geom = QgsGeometry.fromPoint(error.where())
|
||||
errFeat.setGeometry(error_geom)
|
||||
errFeat.setAttributes([error.what()])
|
||||
if error_output_sink:
|
||||
error_output_sink.addFeature(errFeat, QgsFeatureSink.FastInsert)
|
||||
error_count += 1
|
||||
if self.error_output_sink:
|
||||
self.error_output_sink.addFeature(errFeat, QgsFeatureSink.FastInsert)
|
||||
self.error_count += 1
|
||||
|
||||
reasons.append(error.what())
|
||||
|
||||
@ -169,26 +183,28 @@ class CheckValidity(QgisAlgorithm):
|
||||
outFeat.setAttributes(attrs)
|
||||
|
||||
if valid:
|
||||
if valid_output_sink:
|
||||
valid_output_sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
valid_count += 1
|
||||
if self.valid_output_sink:
|
||||
self.valid_output_sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
self.valid_count += 1
|
||||
|
||||
else:
|
||||
if invalid_output_sink:
|
||||
invalid_output_sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
invalid_count += 1
|
||||
if self.invalid_output_sink:
|
||||
self.invalid_output_sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
self.invalid_count += 1
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
results = {
|
||||
self.VALID_COUNT: valid_count,
|
||||
self.INVALID_COUNT: invalid_count,
|
||||
self.ERROR_COUNT: error_count
|
||||
self.VALID_COUNT: self.valid_count,
|
||||
self.INVALID_COUNT: self.invalid_count,
|
||||
self.ERROR_COUNT: self.error_count
|
||||
}
|
||||
if valid_output_sink:
|
||||
results[self.VALID_OUTPUT] = valid_output_dest_id
|
||||
if invalid_output_sink:
|
||||
results[self.INVALID_OUTPUT] = invalid_output_dest_id
|
||||
if error_output_sink:
|
||||
results[self.ERROR_OUTPUT] = error_output_dest_id
|
||||
if self.valid_output_sink:
|
||||
results[self.VALID_OUTPUT] = self.valid_output_dest_id
|
||||
if self.invalid_output_sink:
|
||||
results[self.INVALID_OUTPUT] = self.invalid_output_dest_id
|
||||
if self.error_output_sink:
|
||||
results[self.ERROR_OUTPUT] = self.error_output_dest_id
|
||||
return results
|
||||
|
@ -53,27 +53,35 @@ class CreateAttributeIndex(QgisAlgorithm):
|
||||
self.tr('Attribute to index'), None, self.INPUT))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Indexed layer')))
|
||||
|
||||
self.layer = None
|
||||
self.field = None
|
||||
|
||||
def name(self):
|
||||
return 'createattributeindex'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Create attribute index')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
field = self.parameterAsString(parameters, self.FIELD, context)
|
||||
provider = layer.dataProvider()
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
self.field = self.parameterAsString(parameters, self.FIELD, context)
|
||||
return True
|
||||
|
||||
field_index = layer.fields().lookupField(field)
|
||||
if field_index < 0 or layer.fields().fieldOrigin(field_index) != QgsFields.OriginProvider:
|
||||
feedback.pushInfo(self.tr('Can not create attribute index on "{}"').format(field))
|
||||
def processAlgorithm(self, context, feedback):
|
||||
provider = self.layer.dataProvider()
|
||||
|
||||
field_index = self.layer.fields().lookupField(self.field)
|
||||
if field_index < 0 or self.layer.fields().fieldOrigin(field_index) != QgsFields.OriginProvider:
|
||||
feedback.pushInfo(self.tr('Can not create attribute index on "{}"').format(self.field))
|
||||
else:
|
||||
provider_index = layer.fields().fieldOriginIndex(field_index)
|
||||
provider_index = self.layer.fields().fieldOriginIndex(field_index)
|
||||
if provider.capabilities() & QgsVectorDataProvider.CreateAttributeIndex:
|
||||
if not provider.createAttributeIndex(provider_index):
|
||||
feedback.pushInfo(self.tr('Could not create attribute index'))
|
||||
else:
|
||||
feedback.pushInfo(self.tr("Layer's data provider does not support "
|
||||
"creating attribute indexes"))
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: layer.id()}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.layer.id()}
|
||||
|
@ -58,46 +58,56 @@ class DeleteColumn(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Output layer')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Output layer")))
|
||||
|
||||
self.source = None
|
||||
self.fields_to_delete = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
self.field_indices = []
|
||||
|
||||
def name(self):
|
||||
return 'deletecolumn'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Drop field(s)')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
fields_to_delete = self.parameterAsFields(parameters, self.COLUMNS, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.fields_to_delete = self.parameterAsFields(parameters, self.COLUMNS, context)
|
||||
|
||||
fields = source.fields()
|
||||
field_indices = []
|
||||
fields = self.source.fields()
|
||||
# loop through twice - first we need to build up a list of original attribute indices
|
||||
for f in fields_to_delete:
|
||||
for f in self.fields_to_delete:
|
||||
index = fields.lookupField(f)
|
||||
field_indices.append(index)
|
||||
self.field_indices.append(index)
|
||||
|
||||
# important - make sure we remove from the end so we aren't changing used indices as we go
|
||||
field_indices.sort(reverse=True)
|
||||
self.field_indices.sort(reverse=True)
|
||||
|
||||
# this second time we make a cleaned version of the fields
|
||||
for index in field_indices:
|
||||
for index in self.field_indices:
|
||||
fields.remove(index)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, source.wkbType(), source.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
attributes = f.attributes()
|
||||
for index in field_indices:
|
||||
for index in self.field_indices:
|
||||
del attributes[index]
|
||||
f.setAttributes(attributes)
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -58,31 +58,40 @@ class DeleteHoles(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Cleaned'), QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Cleaned'), QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||
|
||||
self.source = None
|
||||
self.min_area = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'deleteholes'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Delete holes')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
min_area = self.parameterAsDouble(parameters, self.MIN_AREA, context)
|
||||
if min_area == 0.0:
|
||||
min_area = -1.0
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.min_area = self.parameterAsDouble(parameters, self.MIN_AREA, context)
|
||||
if self.min_area == 0.0:
|
||||
self.min_area = -1.0
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
if f.hasGeometry():
|
||||
f.setGeometry(f.geometry().removeInteriorRings(min_area))
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
f.setGeometry(f.geometry().removeInteriorRings(self.min_area))
|
||||
self.sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -63,21 +63,28 @@ class DensifyGeometries(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Densified')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Densified')))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.vertices = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'densifygeometries'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Densify geometries')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
vertices = self.parameterAsInt(parameters, self.VERTICES, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.vertices = self.parameterAsInt(parameters, self.VERTICES, context)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
@ -85,9 +92,11 @@ class DensifyGeometries(QgisAlgorithm):
|
||||
|
||||
feature = f
|
||||
if feature.hasGeometry():
|
||||
new_geometry = feature.geometry().densifyByCount(vertices)
|
||||
new_geometry = feature.geometry().densifyByCount(self.vertices)
|
||||
feature.setGeometry(new_geometry)
|
||||
sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -61,31 +61,40 @@ class DensifyGeometriesInterval(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Densified')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Densified')))
|
||||
|
||||
self.source = None
|
||||
self.interval = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'densifygeometriesgivenaninterval'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Densify geometries given an interval')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
interval = self.parameterAsDouble(parameters, self.INTERVAL, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.interval = self.parameterAsDouble(parameters, self.INTERVAL, context)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
feature = f
|
||||
if feature.hasGeometry():
|
||||
new_geometry = feature.geometry().densifyByDistance(float(interval))
|
||||
new_geometry = feature.geometry().densifyByDistance(float(self.interval))
|
||||
feature.setGeometry(new_geometry)
|
||||
sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -39,8 +39,8 @@ from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
|
||||
class DropGeometry(QgisAlgorithm):
|
||||
|
||||
INPUT_LAYER = 'INPUT_LAYER'
|
||||
OUTPUT_TABLE = 'OUTPUT_TABLE'
|
||||
INPUT = 'INPUT'
|
||||
OUTPUT = 'OUTPUT'
|
||||
|
||||
def tags(self):
|
||||
return self.tr('remove,drop,delete,geometry,objects').split(',')
|
||||
@ -51,9 +51,13 @@ class DropGeometry(QgisAlgorithm):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT_LAYER, self.tr('Input layer'), [QgsProcessingParameterDefinition.TypeVectorPoint, QgsProcessingParameterDefinition.TypeVectorLine, QgsProcessingParameterDefinition.TypeVectorPolygon]))
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT_TABLE, self.tr('Dropped geometry')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT_TABLE, self.tr("Dropped geometry")))
|
||||
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer'), [QgsProcessingParameterDefinition.TypeVectorPoint, QgsProcessingParameterDefinition.TypeVectorLine, QgsProcessingParameterDefinition.TypeVectorPolygon]))
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Dropped geometry')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Dropped geometry")))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'dropgeometries'
|
||||
@ -61,21 +65,26 @@ class DropGeometry(QgisAlgorithm):
|
||||
def displayName(self):
|
||||
return self.tr('Drop geometries')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_TABLE, context,
|
||||
source.fields(), QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
|
||||
features = source.getFeatures(request)
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
features = self.source.getFeatures(request)
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
input_feature.clearGeometry()
|
||||
sink.addFeature(input_feature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(input_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
return {self.OUTPUT_TABLE: dest_id}
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -79,15 +79,20 @@ class ExtentFromLayer(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Extent')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Extent"), QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||
|
||||
self.source = None
|
||||
self.byFeature = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'polygonfromlayerextent'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Polygon from layer extent')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
byFeature = self.parameterAsBool(parameters, self.BY_FEATURE, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
|
||||
self.byFeature = self.parameterAsBool(parameters, self.BY_FEATURE, context)
|
||||
|
||||
fields = QgsFields()
|
||||
fields.append(QgsField('MINX', QVariant.Double))
|
||||
@ -101,15 +106,19 @@ class ExtentFromLayer(QgisAlgorithm):
|
||||
fields.append(QgsField('HEIGHT', QVariant.Double))
|
||||
fields.append(QgsField('WIDTH', QVariant.Double))
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.Polygon, source.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.Polygon, self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
if byFeature:
|
||||
self.featureExtent(source, context, sink, feedback)
|
||||
def processAlgorithm(self, context, feedback):
|
||||
if self.byFeature:
|
||||
self.featureExtent(self.source, context, self.sink, feedback)
|
||||
else:
|
||||
self.layerExtent(source, sink, feedback)
|
||||
self.layerExtent(self.source, self.sink, feedback)
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
||||
def layerExtent(self, source, sink, feedback):
|
||||
rect = source.sourceExtent()
|
||||
|
@ -55,20 +55,26 @@ class FixGeometry(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Fixed geometries')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Fixed geometries")))
|
||||
|
||||
self.source = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'fixgeometries'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Fix geometries')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), QgsWkbTypes.multiType(self.source.wkbType()), self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
features = source.getFeatures(QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures(QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
for current, inputFeature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
@ -86,7 +92,7 @@ class FixGeometry(QgisAlgorithm):
|
||||
try:
|
||||
g.convertToMultiType()
|
||||
outputFeature.setGeometry(QgsGeometry(g))
|
||||
sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
|
||||
except:
|
||||
pass
|
||||
feedback.setProgress(int(current * total))
|
||||
@ -95,7 +101,9 @@ class FixGeometry(QgisAlgorithm):
|
||||
outputGeometry.convertToMultiType()
|
||||
outputFeature.setGeometry(outputGeometry)
|
||||
|
||||
sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -102,41 +102,52 @@ class GridPolygon(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Grid')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Grid'), QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||
|
||||
self.idx = None
|
||||
self.hSpacing = None
|
||||
self.vSpacing = None
|
||||
self.hOverlay = None
|
||||
self.vOverlay = None
|
||||
self.width = None
|
||||
self.height = None
|
||||
self.originX = None
|
||||
self.originY = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'creategridpolygon'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Create grid (polygon)')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
idx = self.parameterAsEnum(parameters, self.TYPE, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.idx = self.parameterAsEnum(parameters, self.TYPE, context)
|
||||
|
||||
hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context)
|
||||
vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context)
|
||||
hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context)
|
||||
vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context)
|
||||
self.hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context)
|
||||
self.vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context)
|
||||
self.hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context)
|
||||
self.vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context)
|
||||
|
||||
bbox = self.parameterAsExtent(parameters, self.EXTENT, context)
|
||||
crs = self.parameterAsCrs(parameters, self.CRS, context)
|
||||
self.width = bbox.width()
|
||||
self.height = bbox.height()
|
||||
self.originX = bbox.xMinimum()
|
||||
self.originY = bbox.yMaximum()
|
||||
|
||||
width = bbox.width()
|
||||
height = bbox.height()
|
||||
originX = bbox.xMinimum()
|
||||
originY = bbox.yMaximum()
|
||||
|
||||
if hSpacing <= 0 or vSpacing <= 0:
|
||||
if self.hSpacing <= 0 or self.vSpacing <= 0:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Invalid grid spacing: {0}/{1}').format(hSpacing, vSpacing))
|
||||
self.tr('Invalid grid spacing: {0}/{1}').format(self.hSpacing, self.vSpacing))
|
||||
|
||||
if width < hSpacing:
|
||||
if self.width < self.hSpacing:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Horizontal spacing is too small for the covered area'))
|
||||
|
||||
if hSpacing <= hOverlay or vSpacing <= vOverlay:
|
||||
if self.hSpacing <= self.hOverlay or self.vSpacing <= self.vOverlay:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay))
|
||||
self.tr('Invalid overlay: {0}/{1}').format(self.hOverlay, self.vOverlay))
|
||||
|
||||
if height < vSpacing:
|
||||
if self.height < self.vSpacing:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Vertical spacing is too small for the covered area'))
|
||||
|
||||
@ -147,20 +158,24 @@ class GridPolygon(QgisAlgorithm):
|
||||
fields.append(QgsField('bottom', QVariant.Double, '', 24, 16))
|
||||
fields.append(QgsField('id', QVariant.Int, '', 10, 0))
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.Polygon, crs)
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.Polygon, crs)
|
||||
return True
|
||||
|
||||
if idx == 0:
|
||||
def processAlgorithm(self, context, feedback):
|
||||
if self.idx == 0:
|
||||
self._rectangleGrid(
|
||||
sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
|
||||
elif idx == 1:
|
||||
self.sink, self.width, self.height, self.originX, self.originY, self.hSpacing, self.vSpacing, self.hOverlay, self.vOverlay, feedback)
|
||||
elif self.idx == 1:
|
||||
self._diamondGrid(
|
||||
sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
|
||||
elif idx == 2:
|
||||
self.sink, self.width, self.height, self.originX, self.originY, self.hSpacing, self.vSpacing, self.hOverlay, self.vOverlay, feedback)
|
||||
elif self.idx == 2:
|
||||
self._hexagonGrid(
|
||||
sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
|
||||
self.sink, self.width, self.height, self.originX, self.originY, self.hSpacing, self.vSpacing, self.hOverlay, self.vOverlay, feedback)
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
||||
def _rectangleGrid(self, sink, width, height, originX, originY,
|
||||
hSpacing, vSpacing, hOverlay, vOverlay, feedback):
|
||||
|
@ -27,9 +27,7 @@ __revision__ = '$Format:%H$'
|
||||
|
||||
from qgis.core import (QgsVectorLayerExporter,
|
||||
QgsSettings,
|
||||
QgsApplication,
|
||||
QgsFeatureSink,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterString,
|
||||
QgsProcessingParameterField,
|
||||
@ -38,10 +36,6 @@ from qgis.core import (QgsVectorLayerExporter,
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||
from processing.core.parameters import ParameterBoolean
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterString
|
||||
from processing.core.parameters import ParameterTableField
|
||||
from processing.tools import postgis
|
||||
|
||||
|
||||
@ -112,70 +106,86 @@ class ImportIntoPostGIS(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterBoolean(self.FORCE_SINGLEPART,
|
||||
self.tr('Create single-part geometries instead of multi-part'), False))
|
||||
|
||||
self.db = None
|
||||
self.schema = None
|
||||
self.overwrite = None
|
||||
self.createIndex = None
|
||||
self.convertLowerCase = None
|
||||
self.dropStringLength = None
|
||||
self.forceSinglePart = None
|
||||
self.primaryKeyField = None
|
||||
self.encoding = None
|
||||
self.source = None
|
||||
self.table = None
|
||||
self.providerName = None
|
||||
self.geomColumn = None
|
||||
|
||||
def name(self):
|
||||
return 'importintopostgis'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Import into PostGIS')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
connection = self.parameterAsString(parameters, self.DATABASE, context)
|
||||
db = postgis.GeoDB.from_name(connection)
|
||||
self.db = postgis.GeoDB.from_name(connection)
|
||||
|
||||
schema = self.parameterAsString(parameters, self.SCHEMA, context)
|
||||
overwrite = self.parameterAsBool(parameters, self.OVERWRITE, context)
|
||||
createIndex = self.parameterAsBool(parameters, self.CREATEINDEX, context)
|
||||
convertLowerCase = self.parameterAsBool(parameters, self.LOWERCASE_NAMES, context)
|
||||
dropStringLength = self.parameterAsBool(parameters, self.DROP_STRING_LENGTH, context)
|
||||
forceSinglePart = self.parameterAsBool(parameters, self.FORCE_SINGLEPART, context)
|
||||
primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id'
|
||||
encoding = self.parameterAsString(parameters, self.ENCODING, context)
|
||||
self.schema = self.parameterAsString(parameters, self.SCHEMA, context)
|
||||
self.overwrite = self.parameterAsBool(parameters, self.OVERWRITE, context)
|
||||
self.createIndex = self.parameterAsBool(parameters, self.CREATEINDEX, context)
|
||||
self.convertLowerCase = self.parameterAsBool(parameters, self.LOWERCASE_NAMES, context)
|
||||
self.dropStringLength = self.parameterAsBool(parameters, self.DROP_STRING_LENGTH, context)
|
||||
self.forceSinglePart = self.parameterAsBool(parameters, self.FORCE_SINGLEPART, context)
|
||||
self.primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id'
|
||||
self.encoding = self.parameterAsString(parameters, self.ENCODING, context)
|
||||
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
|
||||
table = self.parameterAsString(parameters, self.TABLENAME, context)
|
||||
if table:
|
||||
table.strip()
|
||||
if not table or table == '':
|
||||
table = source.sourceName()
|
||||
table = table.replace('.', '_')
|
||||
table = table.replace(' ', '').lower()[0:62]
|
||||
providerName = 'postgres'
|
||||
self.table = self.parameterAsString(parameters, self.TABLENAME, context)
|
||||
if self.table:
|
||||
self.table.strip()
|
||||
if not self.table or self.table == '':
|
||||
self.table = self.source.sourceName()
|
||||
self.table = self.table.replace('.', '_')
|
||||
self.table = self.table.replace(' ', '').lower()[0:62]
|
||||
self.providerName = 'postgres'
|
||||
|
||||
geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context)
|
||||
if not geomColumn:
|
||||
geomColumn = 'geom'
|
||||
self.geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context)
|
||||
if not self.geomColumn:
|
||||
self.geomColumn = 'geom'
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
options = {}
|
||||
if overwrite:
|
||||
if self.overwrite:
|
||||
options['overwrite'] = True
|
||||
if convertLowerCase:
|
||||
if self.convertLowerCase:
|
||||
options['lowercaseFieldNames'] = True
|
||||
geomColumn = geomColumn.lower()
|
||||
if dropStringLength:
|
||||
self.geomColumn = self.geomColumn.lower()
|
||||
if self.dropStringLength:
|
||||
options['dropStringConstraints'] = True
|
||||
if forceSinglePart:
|
||||
if self.forceSinglePart:
|
||||
options['forceSinglePartGeometryType'] = True
|
||||
|
||||
# Clear geometry column for non-geometry tables
|
||||
if source.wkbType() == QgsWkbTypes.NoGeometry:
|
||||
geomColumn = None
|
||||
if self.source.wkbType() == QgsWkbTypes.NoGeometry:
|
||||
self.geomColumn = None
|
||||
|
||||
uri = db.uri
|
||||
uri.setDataSource(schema, table, geomColumn, '', primaryKeyField)
|
||||
uri = self.db.uri
|
||||
uri.setDataSource(self.schema, self.table, self.geomColumn, '', self.primaryKeyField)
|
||||
|
||||
if encoding:
|
||||
options['fileEncoding'] = encoding
|
||||
if self.encoding:
|
||||
options['fileEncoding'] = self.encoding
|
||||
|
||||
exporter = QgsVectorLayerExporter(uri.uri(), providerName, source.fields(),
|
||||
source.wkbType(), source.sourceCrs(), overwrite, options)
|
||||
exporter = QgsVectorLayerExporter(uri.uri(), self.providerName, self.source.fields(),
|
||||
self.source.wkbType(), self.source.sourceCrs(), self.overwrite, options)
|
||||
|
||||
if exporter.errorCode() != QgsVectorLayerExporter.NoError:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error importing to PostGIS\n{0}').format(exporter.errorMessage()))
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
@ -190,11 +200,13 @@ class ImportIntoPostGIS(QgisAlgorithm):
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error importing to PostGIS\n{0}').format(exporter.errorMessage()))
|
||||
|
||||
if geomColumn and createIndex:
|
||||
db.create_spatial_index(table, schema, geomColumn)
|
||||
if self.geomColumn and self.createIndex:
|
||||
self.db.create_spatial_index(self.table, self.schema, self.geomColumn)
|
||||
|
||||
db.vacuum_analyze(table, schema)
|
||||
self.db.vacuum_analyze(self.table, self.schema)
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {}
|
||||
|
||||
def dbConnectionNames(self):
|
||||
|
@ -28,8 +28,6 @@ __revision__ = '$Format:%H$'
|
||||
from qgis.core import (QgsDataSourceUri,
|
||||
QgsFeatureSink,
|
||||
QgsVectorLayerExporter,
|
||||
QgsApplication,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterVectorLayer,
|
||||
QgsProcessingParameterField,
|
||||
@ -73,13 +71,26 @@ class ImportIntoSpatialite(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterBoolean(self.DROP_STRING_LENGTH, self.tr('Drop length constraints on character fields'), False))
|
||||
self.addParameter(QgsProcessingParameterBoolean(self.FORCE_SINGLEPART, self.tr('Create single-part geometries instead of multi-part'), False))
|
||||
|
||||
self.db = None
|
||||
self.overwrite = None
|
||||
self.createIndex = None
|
||||
self.dropStringLength = None
|
||||
self.convertLowerCase = None
|
||||
self.forceSinglePart = None
|
||||
self.primaryKeyField = None
|
||||
self.encoding = None
|
||||
self.source = None
|
||||
self.table = None
|
||||
self.providerName = None
|
||||
self.geomColumn = None
|
||||
|
||||
def name(self):
|
||||
return 'importintospatialite'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Import into Spatialite')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
database = self.parameterAsVectorLayer(parameters, self.DATABASE, context)
|
||||
databaseuri = database.dataProvider().dataSourceUri()
|
||||
uri = QgsDataSourceUri(databaseuri)
|
||||
@ -87,61 +98,64 @@ class ImportIntoSpatialite(QgisAlgorithm):
|
||||
if '|layerid' in databaseuri:
|
||||
databaseuri = databaseuri[:databaseuri.find('|layerid')]
|
||||
uri = QgsDataSourceUri('dbname=\'%s\'' % (databaseuri))
|
||||
db = spatialite.GeoDB(uri)
|
||||
self.db = spatialite.GeoDB(uri)
|
||||
|
||||
overwrite = self.parameterAsBool(parameters, self.OVERWRITE, context)
|
||||
createIndex = self.parameterAsBool(parameters, self.CREATEINDEX, context)
|
||||
convertLowerCase = self.parameterAsBool(parameters, self.LOWERCASE_NAMES, context)
|
||||
dropStringLength = self.parameterAsBool(parameters, self.DROP_STRING_LENGTH, context)
|
||||
forceSinglePart = self.parameterAsBool(parameters, self.FORCE_SINGLEPART, context)
|
||||
primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id'
|
||||
encoding = self.parameterAsString(parameters, self.ENCODING, context)
|
||||
self.overwrite = self.parameterAsBool(parameters, self.OVERWRITE, context)
|
||||
self.createIndex = self.parameterAsBool(parameters, self.CREATEINDEX, context)
|
||||
self.convertLowerCase = self.parameterAsBool(parameters, self.LOWERCASE_NAMES, context)
|
||||
self.dropStringLength = self.parameterAsBool(parameters, self.DROP_STRING_LENGTH, context)
|
||||
self.forceSinglePart = self.parameterAsBool(parameters, self.FORCE_SINGLEPART, context)
|
||||
self.primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY, context) or 'id'
|
||||
self.encoding = self.parameterAsString(parameters, self.ENCODING, context)
|
||||
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
|
||||
table = self.parameterAsString(parameters, self.TABLENAME, context)
|
||||
if table:
|
||||
table.strip()
|
||||
if not table or table == '':
|
||||
table = source.sourceName()
|
||||
table = table.replace('.', '_')
|
||||
table = table.replace(' ', '').lower()
|
||||
providerName = 'spatialite'
|
||||
self.table = self.parameterAsString(parameters, self.TABLENAME, context)
|
||||
if self.table:
|
||||
self.table.strip()
|
||||
if not self.table or self.table == '':
|
||||
self.table = self.source.sourceName()
|
||||
self.table = self.table.replace('.', '_')
|
||||
self.table = self.table.replace(' ', '').lower()
|
||||
self.providerName = 'spatialite'
|
||||
|
||||
geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context)
|
||||
if not geomColumn:
|
||||
geomColumn = 'geom'
|
||||
self.geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN, context)
|
||||
if not self.geomColumn:
|
||||
self.geomColumn = 'geom'
|
||||
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
options = {}
|
||||
if overwrite:
|
||||
if self.overwrite:
|
||||
options['overwrite'] = True
|
||||
if convertLowerCase:
|
||||
if self.convertLowerCase:
|
||||
options['lowercaseFieldNames'] = True
|
||||
geomColumn = geomColumn.lower()
|
||||
if dropStringLength:
|
||||
self.geomColumn = self.geomColumn.lower()
|
||||
if self.dropStringLength:
|
||||
options['dropStringConstraints'] = True
|
||||
if forceSinglePart:
|
||||
if self.forceSinglePart:
|
||||
options['forceSinglePartGeometryType'] = True
|
||||
|
||||
# Clear geometry column for non-geometry tables
|
||||
if source.wkbType() == QgsWkbTypes.NoGeometry:
|
||||
geomColumn = None
|
||||
if self.source.wkbType() == QgsWkbTypes.NoGeometry:
|
||||
self.geomColumn = None
|
||||
|
||||
uri = db.uri
|
||||
uri.setDataSource('', table, geomColumn, '', primaryKeyField)
|
||||
uri = self.db.uri
|
||||
uri.setDataSource('', self.table, self.geomColumn, '', self.primaryKeyField)
|
||||
|
||||
if encoding:
|
||||
options['fileEncoding'] = encoding
|
||||
if self.encoding:
|
||||
options['fileEncoding'] = self.encoding
|
||||
|
||||
exporter = QgsVectorLayerExporter(uri.uri(), providerName, source.fields(),
|
||||
source.wkbType(), source.sourceCrs(), overwrite, options)
|
||||
exporter = QgsVectorLayerExporter(uri.uri(), self.providerName, self.source.fields(),
|
||||
self.source.wkbType(), self.source.sourceCrs(), self.overwrite, options)
|
||||
|
||||
if exporter.errorCode() != QgsVectorLayerExporter.NoError:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error importing to Spatialite\n{0}').format(exporter.errorMessage()))
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
for current, f in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
@ -156,7 +170,9 @@ class ImportIntoSpatialite(QgisAlgorithm):
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error importing to Spatialite\n{0}').format(exporter.errorMessage()))
|
||||
|
||||
if geomColumn and createIndex:
|
||||
db.create_spatial_index(table, geomColumn)
|
||||
if self.geomColumn and self.createIndex:
|
||||
self.db.create_spatial_index(self.table, self.geomColumn)
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {}
|
||||
|
@ -68,19 +68,26 @@ class Merge(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Merged')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Merged')))
|
||||
|
||||
self.input_layers = []
|
||||
self.fields = None
|
||||
self.add_layer_field = None
|
||||
self.add_path_field = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
self.dest_crs = None
|
||||
|
||||
def name(self):
|
||||
return 'mergevectorlayers'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Merge vector layers')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
input_layers = self.parameterAsLayerList(parameters, self.LAYERS, context)
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.input_layers = self.parameterAsLayerList(parameters, self.LAYERS, context)
|
||||
layers = []
|
||||
fields = QgsFields()
|
||||
self.fields = QgsFields()
|
||||
totalFeatureCount = 0
|
||||
for layer in input_layers:
|
||||
for layer in self.input_layers:
|
||||
if layer.type() != QgsMapLayer.VectorLayer:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('All layers must be vector layers!'))
|
||||
@ -95,7 +102,7 @@ class Merge(QgisAlgorithm):
|
||||
|
||||
for sindex, sfield in enumerate(layer.fields()):
|
||||
found = None
|
||||
for dfield in fields:
|
||||
for dfield in self.fields:
|
||||
if (dfield.name().upper() == sfield.name().upper()):
|
||||
found = dfield
|
||||
if (dfield.type() != sfield.type()):
|
||||
@ -104,35 +111,38 @@ class Merge(QgisAlgorithm):
|
||||
'data type than in other layers.'.format(sfield.name(), layerSource)))
|
||||
|
||||
if not found:
|
||||
fields.append(sfield)
|
||||
self.fields.append(sfield)
|
||||
|
||||
add_layer_field = False
|
||||
if fields.lookupField('layer') < 0:
|
||||
fields.append(QgsField('layer', QVariant.String, '', 100))
|
||||
add_layer_field = True
|
||||
add_path_field = False
|
||||
if fields.lookupField('path') < 0:
|
||||
fields.append(QgsField('path', QVariant.String, '', 200))
|
||||
add_path_field = True
|
||||
self.add_layer_field = False
|
||||
if self.fields.lookupField('layer') < 0:
|
||||
self.fields.append(QgsField('layer', QVariant.String, '', 100))
|
||||
self.add_layer_field = True
|
||||
self.add_path_field = False
|
||||
if self.fields.lookupField('path') < 0:
|
||||
self.fields.append(QgsField('path', QVariant.String, '', 200))
|
||||
self.add_path_field = True
|
||||
|
||||
total = 100.0 / totalFeatureCount if totalFeatureCount else 1
|
||||
dest_crs = layers[0].crs()
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, layers[0].wkbType(), dest_crs)
|
||||
self.dest_crs = layers[0].crs()
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.fields, layers[0].wkbType(), self.dest_crs)
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
|
||||
featureCount = 0
|
||||
for layer in layers:
|
||||
for feature in layer.getFeatures(QgsFeatureRequest().setDestinationCrs(dest_crs)):
|
||||
for layer in self.layers:
|
||||
for feature in layer.getFeatures(QgsFeatureRequest().setDestinationCrs(self.dest_crs)):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
sattributes = feature.attributes()
|
||||
dattributes = []
|
||||
for dindex, dfield in enumerate(fields):
|
||||
if add_layer_field and dfield.name() == 'layer':
|
||||
for dindex, dfield in enumerate(self.fields):
|
||||
if self.add_layer_field and dfield.name() == 'layer':
|
||||
dattributes.append(layer.name())
|
||||
continue
|
||||
if add_path_field and dfield.name() == 'path':
|
||||
if self.add_path_field and dfield.name() == 'path':
|
||||
dattributes.append(layer.publicSource())
|
||||
continue
|
||||
|
||||
@ -154,8 +164,10 @@ class Merge(QgisAlgorithm):
|
||||
dattributes.append(dattribute)
|
||||
|
||||
feature.setAttributes(dattributes)
|
||||
sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(feature, QgsFeatureSink.FastInsert)
|
||||
featureCount += 1
|
||||
feedback.setProgress(int(featureCount * total))
|
||||
feedback.setProgress(int(featureCount * self.total))
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -53,20 +53,28 @@ class PostGISExecuteSQL(QgisAlgorithm):
|
||||
self.addParameter(db_param)
|
||||
self.addParameter(QgsProcessingParameterString(self.SQL, self.tr('SQL query')))
|
||||
|
||||
self.connection = None
|
||||
self.sql = None
|
||||
|
||||
def name(self):
|
||||
return 'postgisexecutesql'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('PostGIS execute SQL')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
connection = self.parameterAsString(parameters, self.DATABASE, context)
|
||||
db = postgis.GeoDB.from_name(connection)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.connection = self.parameterAsString(parameters, self.DATABASE, context)
|
||||
self.sql = self.parameterAsString(parameters, self.SQL, context).replace('\n', ' ')
|
||||
return True
|
||||
|
||||
sql = self.parameterAsString(parameters, self.SQL, context).replace('\n', ' ')
|
||||
def processAlgorithm(self, context, feedback):
|
||||
db = postgis.GeoDB.from_name(self.connection)
|
||||
try:
|
||||
db._exec_sql_and_commit(str(sql))
|
||||
db._exec_sql_and_commit(str(self.sql))
|
||||
except postgis.DbError as e:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error executing SQL:\n{0}').format(str(e)))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {}
|
||||
|
@ -28,9 +28,7 @@ __revision__ = '$Format:%H$'
|
||||
|
||||
import random
|
||||
|
||||
from qgis.core import (QgsApplication,
|
||||
QgsFeatureSink,
|
||||
QgsProcessingUtils,
|
||||
from qgis.core import (QgsFeatureSink,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessingParameterNumber,
|
||||
@ -38,7 +36,6 @@ from qgis.core import (QgsApplication,
|
||||
QgsProcessingOutputVectorLayer)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||
from processing.core.outputs import OutputVector
|
||||
|
||||
|
||||
class RandomExtract(QgisAlgorithm):
|
||||
@ -69,42 +66,54 @@ class RandomExtract(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Extracted (random)')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Extracted (random)')))
|
||||
|
||||
self.source = None
|
||||
self.method = None
|
||||
self.value = None
|
||||
self.featureCount = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'randomextract'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Random extract')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
self.value = self.parameterAsInt(parameters, self.NUMBER, context)
|
||||
self.featureCount = self.source.featureCount()
|
||||
|
||||
features = source.getFeatures()
|
||||
featureCount = source.featureCount()
|
||||
value = self.parameterAsInt(parameters, self.NUMBER, context)
|
||||
|
||||
if method == 0:
|
||||
if value > featureCount:
|
||||
if self.method == 0:
|
||||
if self.value > self.featureCount:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Selected number is greater than feature count. '
|
||||
'Choose a lower value and try again.'))
|
||||
else:
|
||||
if value > 100:
|
||||
if self.value > 100:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr("Percentage can't be greater than 100. Set a "
|
||||
"different value and try again."))
|
||||
value = int(round(value / 100.0000, 4) * featureCount)
|
||||
self.value = int(round(self.value / 100.0000, 4) * self.featureCount)
|
||||
|
||||
selran = random.sample(list(range(featureCount)), value)
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
return True
|
||||
|
||||
total = 100.0 / featureCount if featureCount else 1
|
||||
def processAlgorithm(self, context, feedback):
|
||||
selran = random.sample(list(range(self.featureCount)), self.value)
|
||||
features = self.source.getFeatures()
|
||||
|
||||
total = 100.0 / self.featureCount if self.featureCount else 1
|
||||
for i, feat in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
if i in selran:
|
||||
sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(i * total))
|
||||
return {self.OUTPUT: dest_id}
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -74,38 +74,46 @@ class RandomExtractWithinSubsets(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Extracted (random stratified)')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Extracted (random stratified)')))
|
||||
|
||||
self.source = None
|
||||
self.method = None
|
||||
self.field = None
|
||||
self.value = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'randomextractwithinsubsets'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Random extract within subsets')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
|
||||
field = self.parameterAsString(parameters, self.FIELD, context)
|
||||
self.field = self.parameterAsString(parameters, self.FIELD, context)
|
||||
self.value = self.parameterAsInt(parameters, self.NUMBER, context)
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
index = source.fields().lookupField(field)
|
||||
def processAlgorithm(self, context, feedback):
|
||||
index = self.source.fields().lookupField(self.field)
|
||||
|
||||
features = source.getFeatures()
|
||||
featureCount = source.featureCount()
|
||||
unique = source.uniqueValues(index)
|
||||
value = self.parameterAsInt(parameters, self.NUMBER, context)
|
||||
if method == 0:
|
||||
if value > featureCount:
|
||||
features = self.source.getFeatures()
|
||||
featureCount = self.source.featureCount()
|
||||
unique = self.source.uniqueValues(index)
|
||||
if self.method == 0:
|
||||
if self.value > featureCount:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Selected number is greater that feature count. '
|
||||
'Choose lesser value and try again.'))
|
||||
else:
|
||||
if value > 100:
|
||||
if self.value > 100:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr("Percentage can't be greater than 100. Set "
|
||||
"correct value and try again."))
|
||||
value = value / 100.0
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
self.value = self.value / 100.0
|
||||
|
||||
selran = []
|
||||
total = 100.0 / (featureCount * len(unique)) if featureCount else 1
|
||||
@ -119,13 +127,17 @@ class RandomExtractWithinSubsets(QgisAlgorithm):
|
||||
feedback.setProgress(int(i * total))
|
||||
|
||||
for subset in classes.values():
|
||||
selValue = value if method != 1 else int(round(value * len(subset), 0))
|
||||
selValue = self.value if self.method != 1 else int(round(self.value * len(subset), 0))
|
||||
selran.extend(random.sample(subset, selValue))
|
||||
|
||||
total = 100.0 / featureCount if featureCount else 1
|
||||
for (i, feat) in enumerate(selran):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(i * total))
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -81,55 +81,66 @@ class RegularPoints(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Regular points'), QgsProcessingParameterDefinition.TypeVectorPoint))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Regular points'), QgsProcessingParameterDefinition.TypeVectorPoint))
|
||||
|
||||
self.extent = None
|
||||
self.spacing = None
|
||||
self.inset = None
|
||||
self.randomize = None
|
||||
self.isSpacing = None
|
||||
self.fields = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'regularpoints'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Regular points')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
extent = self.parameterAsExtent(parameters, self.EXTENT, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.extent = self.parameterAsExtent(parameters, self.EXTENT, context)
|
||||
|
||||
spacing = self.parameterAsDouble(parameters, self.SPACING, context)
|
||||
inset = self.parameterAsDouble(parameters, self.INSET, context)
|
||||
randomize = self.parameterAsBool(parameters, self.RANDOMIZE, context)
|
||||
isSpacing = self.parameterAsBool(parameters, self.IS_SPACING, context)
|
||||
self.spacing = self.parameterAsDouble(parameters, self.SPACING, context)
|
||||
self.inset = self.parameterAsDouble(parameters, self.INSET, context)
|
||||
self.randomize = self.parameterAsBool(parameters, self.RANDOMIZE, context)
|
||||
self.isSpacing = self.parameterAsBool(parameters, self.IS_SPACING, context)
|
||||
crs = self.parameterAsCrs(parameters, self.CRS, context)
|
||||
|
||||
fields = QgsFields()
|
||||
fields.append(QgsField('id', QVariant.Int, '', 10, 0))
|
||||
self.fields = QgsFields()
|
||||
self.fields.append(QgsField('id', QVariant.Int, '', 10, 0))
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, QgsWkbTypes.Point, crs)
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.fields, QgsWkbTypes.Point, crs)
|
||||
return True
|
||||
|
||||
if randomize:
|
||||
def processAlgorithm(self, context, feedback):
|
||||
if self.randomize:
|
||||
seed()
|
||||
|
||||
area = extent.width() * extent.height()
|
||||
if isSpacing:
|
||||
pSpacing = spacing
|
||||
area = self.extent.width() * self.extent.height()
|
||||
if self.isSpacing:
|
||||
pSpacing = self.spacing
|
||||
else:
|
||||
pSpacing = sqrt(area / spacing)
|
||||
pSpacing = sqrt(area / self.spacing)
|
||||
|
||||
f = QgsFeature()
|
||||
f.initAttributes(1)
|
||||
f.setFields(fields)
|
||||
f.setFields(self.fields)
|
||||
|
||||
count = 0
|
||||
total = 100.0 / (area / pSpacing)
|
||||
y = extent.yMaximum() - inset
|
||||
y = self.extent.yMaximum() - self.inset
|
||||
|
||||
extent_geom = QgsGeometry.fromRect(extent)
|
||||
extent_geom = QgsGeometry.fromRect(self.extent)
|
||||
extent_engine = QgsGeometry.createGeometryEngine(extent_geom.geometry())
|
||||
extent_engine.prepareGeometry()
|
||||
|
||||
while y >= extent.yMinimum():
|
||||
x = extent.xMinimum() + inset
|
||||
while x <= extent.xMaximum():
|
||||
while y >= self.extent.yMinimum():
|
||||
x = self.extent.xMinimum() + self.inset
|
||||
while x <= self.extent.xMaximum():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
if randomize:
|
||||
if self.randomize:
|
||||
geom = QgsGeometry().fromPoint(QgsPointXY(
|
||||
uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)),
|
||||
uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0))))
|
||||
@ -139,10 +150,13 @@ class RegularPoints(QgisAlgorithm):
|
||||
if extent_engine.intersects(geom.geometry()):
|
||||
f.setAttribute('id', count)
|
||||
f.setGeometry(geom)
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
x += pSpacing
|
||||
count += 1
|
||||
feedback.setProgress(int(count * total))
|
||||
y = y - pSpacing
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -26,12 +26,10 @@ __copyright__ = '(C) 2012, Victor Olaya'
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
from qgis.core import (QgsFeatureSink,
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingParameterVectorLayer,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingOutputVectorLayer)
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
|
||||
|
||||
|
||||
class SaveSelectedFeatures(QgisAlgorithm):
|
||||
@ -49,27 +47,35 @@ class SaveSelectedFeatures(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Selection')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr("Selection")))
|
||||
|
||||
self.vectorLayer = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'saveselectedfeatures'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Save selected features')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
vectorLayer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.vectorLayer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
vectorLayer.fields(), vectorLayer.wkbType(), vectorLayer.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.vectorLayer.fields(), self.vectorLayer.wkbType(), self.vectorLayer.sourceCrs())
|
||||
return True
|
||||
|
||||
features = vectorLayer.getSelectedFeatures()
|
||||
count = int(vectorLayer.selectedFeatureCount())
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.vectorLayer.getSelectedFeatures()
|
||||
count = int(self.vectorLayer.selectedFeatureCount())
|
||||
|
||||
total = 100.0 / count if count else 1
|
||||
for current, feat in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(feat, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -92,47 +92,60 @@ class SelectByAttribute(QgisAlgorithm):
|
||||
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Selected (attribute)')))
|
||||
|
||||
self.layer = None
|
||||
self.fieldName = None
|
||||
self.operator = None
|
||||
self.value = None
|
||||
self.input = None
|
||||
|
||||
def name(self):
|
||||
return 'selectbyattribute'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Select by attribute')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
|
||||
fieldName = self.parameterAsString(parameters, self.FIELD, context)
|
||||
operator = self.OPERATORS[self.parameterAsEnum(parameters, self.OPERATOR, context)]
|
||||
value = self.parameterAsString(parameters, self.VALUE, context)
|
||||
self.fieldName = self.parameterAsString(parameters, self.FIELD, context)
|
||||
self.operator = self.OPERATORS[self.parameterAsEnum(parameters, self.OPERATOR, context)]
|
||||
self.value = self.parameterAsString(parameters, self.VALUE, context)
|
||||
|
||||
fields = layer.fields()
|
||||
self.input = parameters[self.INPUT]
|
||||
return True
|
||||
|
||||
idx = layer.fields().lookupField(fieldName)
|
||||
def processAlgorithm(self, context, feedback):
|
||||
fields = self.layer.fields()
|
||||
|
||||
idx = self.layer.fields().lookupField(self.fieldName)
|
||||
fieldType = fields[idx].type()
|
||||
|
||||
if fieldType != QVariant.String and operator in self.STRING_OPERATORS:
|
||||
if fieldType != QVariant.String and self.operator in self.STRING_OPERATORS:
|
||||
op = ''.join(['"%s", ' % o for o in self.STRING_OPERATORS])
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Operators {0} can be used only with string fields.').format(op))
|
||||
|
||||
field_ref = QgsExpression.quotedColumnRef(fieldName)
|
||||
quoted_val = QgsExpression.quotedValue(value)
|
||||
if operator == 'is null':
|
||||
field_ref = QgsExpression.quotedColumnRef(self.fieldName)
|
||||
quoted_val = QgsExpression.quotedValue(self.value)
|
||||
if self.operator == 'is null':
|
||||
expression_string = '{} IS NULL'.format(field_ref)
|
||||
elif operator == 'is not null':
|
||||
elif self.operator == 'is not null':
|
||||
expression_string = '{} IS NOT NULL'.format(field_ref)
|
||||
elif operator == 'begins with':
|
||||
expression_string = """%s LIKE '%s%%'""" % (field_ref, value)
|
||||
elif operator == 'contains':
|
||||
expression_string = """%s LIKE '%%%s%%'""" % (field_ref, value)
|
||||
elif operator == 'does not contain':
|
||||
expression_string = """%s NOT LIKE '%%%s%%'""" % (field_ref, value)
|
||||
elif self.operator == 'begins with':
|
||||
expression_string = """%s LIKE '%s%%'""" % (field_ref, self.value)
|
||||
elif self.operator == 'contains':
|
||||
expression_string = """%s LIKE '%%%s%%'""" % (field_ref, self.value)
|
||||
elif self.operator == 'does not contain':
|
||||
expression_string = """%s NOT LIKE '%%%s%%'""" % (field_ref, self.value)
|
||||
else:
|
||||
expression_string = '{} {} {}'.format(field_ref, operator, quoted_val)
|
||||
expression_string = '{} {} {}'.format(field_ref, self.operator, quoted_val)
|
||||
|
||||
expression = QgsExpression(expression_string)
|
||||
if expression.hasParserError():
|
||||
raise GeoAlgorithmExecutionException(expression.parserErrorString())
|
||||
|
||||
layer.selectByExpression(expression_string)
|
||||
return {self.OUTPUT: parameters[self.INPUT]}
|
||||
self.layer.selectByExpression(expression_string)
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.input}
|
||||
|
@ -60,30 +60,42 @@ class SelectByExpression(QgisAlgorithm):
|
||||
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Selected (attribute)')))
|
||||
|
||||
self.layer = None
|
||||
self.behavior = None
|
||||
self.input = None
|
||||
self.expression = None
|
||||
|
||||
def name(self):
|
||||
return 'selectbyexpression'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Select by expression')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
|
||||
|
||||
method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
|
||||
if method == 0:
|
||||
behavior = QgsVectorLayer.SetSelection
|
||||
self.behavior = QgsVectorLayer.SetSelection
|
||||
elif method == 1:
|
||||
behavior = QgsVectorLayer.AddToSelection
|
||||
self.behavior = QgsVectorLayer.AddToSelection
|
||||
elif method == 2:
|
||||
behavior = QgsVectorLayer.RemoveFromSelection
|
||||
self.behavior = QgsVectorLayer.RemoveFromSelection
|
||||
elif method == 3:
|
||||
behavior = QgsVectorLayer.IntersectSelection
|
||||
self.behavior = QgsVectorLayer.IntersectSelection
|
||||
|
||||
expression = self.parameterAsString(parameters, self.EXPRESSION, context)
|
||||
qExp = QgsExpression(expression)
|
||||
self.expression = self.parameterAsString(parameters, self.EXPRESSION, context)
|
||||
qExp = QgsExpression(self.expression)
|
||||
if qExp.hasParserError():
|
||||
raise GeoAlgorithmExecutionException(qExp.parserErrorString())
|
||||
|
||||
layer.selectByExpression(expression, behavior)
|
||||
return {self.OUTPUT: parameters[self.INPUT]}
|
||||
self.input = parameters[self.INPUT]
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
self.layer.selectByExpression(self.expression, self.behavior)
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.input}
|
||||
|
@ -76,28 +76,37 @@ class SimplifyGeometries(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Simplified')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Simplified')))
|
||||
|
||||
self.source = None
|
||||
self.tolerance = None
|
||||
self.method = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'simplifygeometries'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Simplify geometries')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)
|
||||
method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)
|
||||
self.method = self.parameterAsEnum(parameters, self.METHOD, context)
|
||||
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
pointsBefore = 0
|
||||
pointsAfter = 0
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
|
||||
if method != 0:
|
||||
simplifier = QgsMapToPixelSimplifier(QgsMapToPixelSimplifier.SimplifyGeometry, tolerance, method)
|
||||
simplifier = None
|
||||
if self.method != 0:
|
||||
simplifier = QgsMapToPixelSimplifier(QgsMapToPixelSimplifier.SimplifyGeometry, self.tolerance, self.method)
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
@ -107,18 +116,20 @@ class SimplifyGeometries(QgisAlgorithm):
|
||||
input_geometry = input_feature.geometry()
|
||||
pointsBefore += input_geometry.geometry().nCoordinates()
|
||||
|
||||
if method == 0: # distance
|
||||
output_geometry = input_geometry.simplify(tolerance)
|
||||
if self.method == 0: # distance
|
||||
output_geometry = input_geometry.simplify(self.tolerance)
|
||||
else:
|
||||
output_geometry = simplifier.simplify(input_geometry)
|
||||
|
||||
pointsAfter += output_geometry.geometry().nCoordinates()
|
||||
out_feature.setGeometry(output_geometry)
|
||||
|
||||
sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
|
||||
QgsMessageLog.logMessage(self.tr('Simplify: Input geometries have been simplified from {0} to {1} points').format(pointsBefore, pointsAfter),
|
||||
self.tr('Processing'), QgsMessageLog.INFO)
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -66,37 +66,48 @@ class Smooth(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Smoothed')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Smoothed')))
|
||||
|
||||
self.source = None
|
||||
self.iterations = None
|
||||
self.offset = None
|
||||
self.max_angle = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'smoothgeometry'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Smooth geometry')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
iterations = self.parameterAsInt(parameters, self.ITERATIONS, context)
|
||||
offset = self.parameterAsDouble(parameters, self.OFFSET, context)
|
||||
max_angle = self.parameterAsDouble(parameters, self.MAX_ANGLE, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.iterations = self.parameterAsInt(parameters, self.ITERATIONS, context)
|
||||
self.offset = self.parameterAsDouble(parameters, self.OFFSET, context)
|
||||
self.max_angle = self.parameterAsDouble(parameters, self.MAX_ANGLE, context)
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
source.fields(), source.wkbType(), source.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
self.source.fields(), self.source.wkbType(), self.source.sourceCrs())
|
||||
return True
|
||||
|
||||
features = source.getFeatures()
|
||||
total = 100.0 / source.featureCount() if source.featureCount() else 0
|
||||
def processAlgorithm(self, context, feedback):
|
||||
features = self.source.getFeatures()
|
||||
total = 100.0 / self.source.featureCount() if self.source.featureCount() else 0
|
||||
|
||||
for current, input_feature in enumerate(features):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
output_feature = input_feature
|
||||
if input_feature.geometry():
|
||||
output_geometry = input_feature.geometry().smooth(iterations, offset, -1, max_angle)
|
||||
output_geometry = input_feature.geometry().smooth(self.iterations, self.offset, -1, self.max_angle)
|
||||
if not output_geometry:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error smoothing geometry'))
|
||||
|
||||
output_feature.setGeometry(output_geometry)
|
||||
|
||||
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -49,26 +49,34 @@ class SpatialiteExecuteSQL(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterVectorLayer(self.DATABASE, self.tr('File Database'), False, False))
|
||||
self.addParameter(QgsProcessingParameterString(self.SQL, self.tr('SQL query'), '', True))
|
||||
|
||||
self.database = None
|
||||
self.sql = None
|
||||
|
||||
def name(self):
|
||||
return 'spatialiteexecutesql'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Spatialite execute SQL')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
database = self.parameterAsVectorLayer(parameters, self.DATABASE, context)
|
||||
databaseuri = database.dataProvider().dataSourceUri()
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.database = self.parameterAsVectorLayer(parameters, self.DATABASE, context)
|
||||
self.sql = self.parameterAsString(parameters, self.SQL, context).replace('\n', ' ')
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
databaseuri = self.database.dataProvider().dataSourceUri()
|
||||
uri = QgsDataSourceUri(databaseuri)
|
||||
if uri.database() is '':
|
||||
if '|layerid' in databaseuri:
|
||||
databaseuri = databaseuri[:databaseuri.find('|layerid')]
|
||||
uri = QgsDataSourceUri('dbname=\'%s\'' % (databaseuri))
|
||||
db = spatialite.GeoDB(uri)
|
||||
sql = self.parameterAsString(parameters, self.SQL, context).replace('\n', ' ')
|
||||
try:
|
||||
db._exec_sql_and_commit(str(sql))
|
||||
db._exec_sql_and_commit(str(self.sql))
|
||||
except spatialite.DbError as e:
|
||||
raise GeoAlgorithmExecutionException(
|
||||
self.tr('Error executing SQL:\n{0}').format(str(e)))
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {}
|
||||
|
@ -70,32 +70,39 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Symmetrical difference')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Symmetrical difference')))
|
||||
|
||||
self.sourceA = None
|
||||
self.sourceB = None
|
||||
self.sink = None
|
||||
self.dest_id = None
|
||||
|
||||
def name(self):
|
||||
return 'symmetricaldifference'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Symmetrical difference')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
sourceA = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.sourceA = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
|
||||
|
||||
geomType = QgsWkbTypes.multiType(sourceA.wkbType())
|
||||
fields = vector.combineFields(sourceA.fields(), sourceB.fields())
|
||||
geomType = QgsWkbTypes.multiType(self.sourceA.wkbType())
|
||||
fields = vector.combineFields(self.sourceA.fields(), self.sourceB.fields())
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, geomType, sourceA.sourceCrs())
|
||||
(self.sink, self.dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, geomType, self.sourceA.sourceCrs())
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
featB = QgsFeature()
|
||||
outFeat = QgsFeature()
|
||||
|
||||
indexA = QgsSpatialIndex(sourceA)
|
||||
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
|
||||
indexA = QgsSpatialIndex(self.sourceA)
|
||||
indexB = QgsSpatialIndex(self.sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(self.sourceA.sourceCrs())))
|
||||
|
||||
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
|
||||
total = 100.0 / (self.sourceA.featureCount() * self.sourceB.featureCount()) if self.sourceA.featureCount() and self.sourceB.featureCount() else 1
|
||||
count = 0
|
||||
|
||||
for featA in sourceA.getFeatures():
|
||||
for featA in self.sourceA.getFeatures():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
@ -104,8 +111,8 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
attrs = featA.attributes()
|
||||
intersects = indexB.intersects(geom.boundingBox())
|
||||
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
|
||||
request.setDestinationCrs(sourceA.sourceCrs())
|
||||
for featB in sourceB.getFeatures(request):
|
||||
request.setDestinationCrs(self.sourceA.sourceCrs())
|
||||
for featB in self.sourceB.getFeatures(request):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
tmpGeom = featB.geometry()
|
||||
@ -115,7 +122,7 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
try:
|
||||
outFeat.setGeometry(diffGeom)
|
||||
outFeat.setAttributes(attrs)
|
||||
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
except:
|
||||
QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
|
||||
self.tr('Processing'), QgsMessageLog.WARNING)
|
||||
@ -124,9 +131,9 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
count += 1
|
||||
feedback.setProgress(int(count * total))
|
||||
|
||||
length = len(sourceA.fields())
|
||||
length = len(self.sourceA.fields())
|
||||
|
||||
for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs())):
|
||||
for featA in self.sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(self.sourceA.sourceCrs())):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
@ -136,7 +143,7 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
attrs = [NULL] * length + attrs
|
||||
intersects = indexA.intersects(geom.boundingBox())
|
||||
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
|
||||
for featB in sourceA.getFeatures(request):
|
||||
for featB in self.sourceA.getFeatures(request):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
@ -147,7 +154,7 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
try:
|
||||
outFeat.setGeometry(diffGeom)
|
||||
outFeat.setAttributes(attrs)
|
||||
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
self.sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
|
||||
except:
|
||||
QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
|
||||
self.tr('Processing'), QgsMessageLog.WARNING)
|
||||
@ -155,5 +162,7 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
|
||||
count += 1
|
||||
feedback.setProgress(int(count * total))
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: dest_id}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.dest_id}
|
||||
|
@ -28,7 +28,6 @@ __revision__ = '$Format:%H$'
|
||||
|
||||
import os
|
||||
|
||||
from qgis.PyQt.QtGui import QIcon
|
||||
from qgis.core import (QgsProcessingUtils,
|
||||
QgsFeatureSink,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
@ -39,10 +38,6 @@ from qgis.core import (QgsProcessingUtils,
|
||||
QgsFeatureRequest)
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
|
||||
from processing.core.parameters import ParameterVector
|
||||
from processing.core.parameters import ParameterTableField
|
||||
from processing.core.outputs import OutputDirectory
|
||||
from processing.tools import vector
|
||||
from processing.tools.system import mkdir
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
@ -71,42 +66,51 @@ class VectorSplit(QgisAlgorithm):
|
||||
|
||||
self.addOutput(QgsProcessingOutputFolder(self.OUTPUT, self.tr('Output directory')))
|
||||
|
||||
self.source = None
|
||||
self.fieldName = None
|
||||
self.directory = None
|
||||
self.uniqueValues = None
|
||||
self.sinks = {}
|
||||
|
||||
def name(self):
|
||||
return 'splitvectorlayer'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Split vector layer')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
fieldName = self.parameterAsString(parameters, self.FIELD, context)
|
||||
directory = self.parameterAsString(parameters, self.OUTPUT, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.source = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
self.fieldName = self.parameterAsString(parameters, self.FIELD, context)
|
||||
self.directory = self.parameterAsString(parameters, self.OUTPUT, context)
|
||||
mkdir(self.directory)
|
||||
|
||||
mkdir(directory)
|
||||
fieldIndex = self.source.fields().lookupField(self.fieldName)
|
||||
self.uniqueValues = self.source.uniqueValues(fieldIndex)
|
||||
|
||||
fieldIndex = source.fields().lookupField(fieldName)
|
||||
uniqueValues = source.uniqueValues(fieldIndex)
|
||||
baseName = os.path.join(directory, '{0}'.format(fieldName))
|
||||
|
||||
fields = source.fields()
|
||||
crs = source.sourceCrs()
|
||||
geomType = source.wkbType()
|
||||
|
||||
total = 100.0 / len(uniqueValues) if uniqueValues else 1
|
||||
|
||||
for current, i in enumerate(uniqueValues):
|
||||
baseName = os.path.join(self.directory, '{0}'.format(self.fieldName))
|
||||
self.sinks = {}
|
||||
for current, i in enumerate(self.uniqueValues):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
fName = u'{0}_{1}.shp'.format(baseName, str(i).strip())
|
||||
feedback.pushInfo(self.tr('Creating layer: {}').format(fName))
|
||||
sink, dest = QgsProcessingUtils.createFeatureSink(fName, context, self.source.fields, self.source.wkbType(), self.source.sourceCrs())
|
||||
self.sinks[i] = sink
|
||||
return True
|
||||
|
||||
sink, dest = QgsProcessingUtils.createFeatureSink(fName, context, fields, geomType, crs)
|
||||
def processAlgorithm(self, context, feedback):
|
||||
total = 100.0 / len(self.uniqueValues) if self.uniqueValues else 1
|
||||
for current, i in enumerate(self.uniqueValues):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
filter = '{} = {}'.format(QgsExpression.quotedColumnRef(fieldName), QgsExpression.quotedValue(i))
|
||||
sink = self.sinks[i]
|
||||
|
||||
filter = '{} = {}'.format(QgsExpression.quotedColumnRef(self.fieldName), QgsExpression.quotedValue(i))
|
||||
req = QgsFeatureRequest().setFilterExpression(filter)
|
||||
|
||||
count = 0
|
||||
for f in source.getFeatures(req):
|
||||
for f in self.source.getFeatures(req):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
sink.addFeature(f, QgsFeatureSink.FastInsert)
|
||||
@ -115,5 +119,7 @@ class VectorSplit(QgisAlgorithm):
|
||||
del sink
|
||||
|
||||
feedback.setProgress(int(current * total))
|
||||
return True
|
||||
|
||||
return {self.OUTPUT: directory}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.OUTPUT: self.directory}
|
||||
|
@ -94,30 +94,40 @@ class ZonalStatistics(QgisAlgorithm):
|
||||
self.tr('Zonal statistics'),
|
||||
QgsProcessingParameterDefinition.TypeVectorPolygon))
|
||||
|
||||
self.bandNumber = None
|
||||
self.columnPrefix = None
|
||||
self.selectedStats = None
|
||||
self.vectorLayer = None
|
||||
self.rasterLayer = None
|
||||
|
||||
def name(self):
|
||||
return 'zonalstatistics'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Zonal Statistics')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
bandNumber = self.parameterAsInt(parameters, self.RASTER_BAND, context)
|
||||
columnPrefix = self.parameterAsString(parameters, self.COLUMN_PREFIX, context)
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.bandNumber = self.parameterAsInt(parameters, self.RASTER_BAND, context)
|
||||
self.columnPrefix = self.parameterAsString(parameters, self.COLUMN_PREFIX, context)
|
||||
st = self.parameterAsEnums(parameters, self.STATISTICS, context)
|
||||
|
||||
vectorLayer = self.parameterAsVectorLayer(parameters, self.INPUT_VECTOR, context)
|
||||
rasterLayer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context)
|
||||
|
||||
keys = list(self.STATS.keys())
|
||||
selectedStats = 0
|
||||
self.selectedStats = 0
|
||||
for i in st:
|
||||
selectedStats |= self.STATS[keys[i]]
|
||||
self.selectedStats |= self.STATS[keys[i]]
|
||||
|
||||
zs = QgsZonalStatistics(vectorLayer,
|
||||
rasterLayer,
|
||||
columnPrefix,
|
||||
bandNumber,
|
||||
selectedStats)
|
||||
self.vectorLayer = self.parameterAsVectorLayer(parameters, self.INPUT_VECTOR, context)
|
||||
self.rasterLayer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context)
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
zs = QgsZonalStatistics(self.vectorLayer,
|
||||
self.rasterLayer,
|
||||
self.columnPrefix,
|
||||
self.bandNumber,
|
||||
self.selectedStats)
|
||||
zs.calculateStatistics(feedback)
|
||||
return True
|
||||
|
||||
return {self.INPUT_VECTOR: vectorLayer}
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return {self.INPUT_VECTOR: self.vectorLayer}
|
||||
|
@ -75,6 +75,10 @@ class ScriptAlgorithm(QgsProcessingAlgorithm):
|
||||
if descriptionFile is not None:
|
||||
self.defineCharacteristicsFromFile()
|
||||
|
||||
self.ns = {}
|
||||
self.cleaned_script = None
|
||||
self.results = {}
|
||||
|
||||
def clone(self):
|
||||
return ScriptAlgorithm(self.descriptionFile)
|
||||
|
||||
@ -178,11 +182,7 @@ class ScriptAlgorithm(QgsProcessingAlgorithm):
|
||||
self.tr('Could not load script: {0}.\n'
|
||||
'Problem with line "{1}"', 'ScriptAlgorithm').format(self.descriptionFile or '', line))
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
ns = {}
|
||||
|
||||
ns['scriptDescriptionFile'] = self.descriptionFile
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
for param in self.parameterDefinitions():
|
||||
method = None
|
||||
if param.type() == "boolean":
|
||||
@ -224,20 +224,19 @@ class ScriptAlgorithm(QgsProcessingAlgorithm):
|
||||
method = self.parameterAsSource
|
||||
|
||||
if method:
|
||||
ns[param.name()] = method(parameters, param.name(), context)
|
||||
self.ns[param.name()] = method(parameters, param.name(), context)
|
||||
|
||||
self.ns['scriptDescriptionFile'] = self.descriptionFile
|
||||
for out in self.outputDefinitions():
|
||||
ns[out.name()] = None
|
||||
self.ns[out.name()] = None
|
||||
|
||||
ns['self'] = self
|
||||
ns['parameters'] = parameters
|
||||
ns['feedback'] = feedback
|
||||
ns['context'] = context
|
||||
self.ns['self'] = self
|
||||
self.ns['parameters'] = parameters
|
||||
|
||||
expression_context = self.createExpressionContext(parameters, context)
|
||||
variables = re.findall('@[a-zA-Z0-9_]*', self.script)
|
||||
script = 'import processing\n'
|
||||
script += self.script
|
||||
context = self.createExpressionContext(parameters, context)
|
||||
for var in variables:
|
||||
varname = var[1:]
|
||||
if context.hasVariable(varname):
|
||||
@ -245,12 +244,22 @@ class ScriptAlgorithm(QgsProcessingAlgorithm):
|
||||
else:
|
||||
# messy - it's probably NOT a variable, and instead an email address or some other string containing '@'
|
||||
QgsMessageLog.logMessage(self.tr('Cannot find variable: {0}').format(varname), self.tr('Processing'), QgsMessageLog.WARNING)
|
||||
self.cleaned_script = script
|
||||
|
||||
exec((script), ns)
|
||||
results = {}
|
||||
return True
|
||||
|
||||
def processAlgorithm(self, context, feedback):
|
||||
self.ns['feedback'] = feedback
|
||||
self.ns['context'] = context
|
||||
|
||||
exec((self.cleaned_script), self.ns)
|
||||
self.results = {}
|
||||
for out in self.outputDefinitions():
|
||||
results[out.name()] = ns[out.name()]
|
||||
return results
|
||||
self.results[out.name()] = self.ns[out.name()]
|
||||
return True
|
||||
|
||||
def postProcessAlgorithm(self, context, feedback):
|
||||
return self.results
|
||||
|
||||
def helpUrl(self):
|
||||
if self.descriptionFile is None:
|
||||
|
@ -9,7 +9,7 @@ tests:
|
||||
type: vector # Param is a vector layer
|
||||
name: polys.gml # file name
|
||||
results: # A map of results (only one here)
|
||||
OUTPUT_LAYER:
|
||||
OUTPUT:
|
||||
type: vector # Expected result is a vector layer
|
||||
name: expected/polys_centroid.gml # The relative filepath from the processing testdata directory
|
||||
compare:
|
||||
@ -735,7 +735,7 @@ tests:
|
||||
name: lines.gml
|
||||
type: vector
|
||||
results:
|
||||
OUTPUT_LAYER:
|
||||
OUTPUT:
|
||||
name: expected/centroid_lines.gml
|
||||
type: vector
|
||||
compare:
|
||||
@ -749,7 +749,7 @@ tests:
|
||||
name: multilines.gml
|
||||
type: vector
|
||||
results:
|
||||
OUTPUT_LAYER:
|
||||
OUTPUT:
|
||||
name: expected/centroid_multilines.gml
|
||||
type: vector
|
||||
compare:
|
||||
@ -763,7 +763,7 @@ tests:
|
||||
name: multipoints.gml
|
||||
type: vector
|
||||
results:
|
||||
OUTPUT_LAYER:
|
||||
OUTPUT:
|
||||
name: expected/centroid_multipoint.gml
|
||||
type: vector
|
||||
compare:
|
||||
@ -777,7 +777,7 @@ tests:
|
||||
name: multipolys.gml
|
||||
type: vector
|
||||
results:
|
||||
OUTPUT_LAYER:
|
||||
OUTPUT:
|
||||
name: expected/centroid_multipolys.gml
|
||||
type: vector
|
||||
compare:
|
||||
@ -791,7 +791,7 @@ tests:
|
||||
name: points.gml
|
||||
type: vector
|
||||
results:
|
||||
OUTPUT_LAYER:
|
||||
OUTPUT:
|
||||
name: expected/centroid_points.gml
|
||||
type: vector
|
||||
compare:
|
||||
@ -805,7 +805,7 @@ tests:
|
||||
name: polys.gml
|
||||
type: vector
|
||||
results:
|
||||
OUTPUT_LAYER:
|
||||
OUTPUT:
|
||||
name: expected/centroid_polys.gml
|
||||
type: vector
|
||||
compare:
|
||||
@ -1037,12 +1037,12 @@ tests:
|
||||
- algorithm: qgis:aspect
|
||||
name: Aspect from QGIS analysis library
|
||||
params:
|
||||
INPUT_LAYER:
|
||||
INPUT:
|
||||
name: dem.tif
|
||||
type: raster
|
||||
Z_FACTOR: 1.0
|
||||
results:
|
||||
OUTPUT_LAYER:
|
||||
OUTPUT:
|
||||
hash: 762865ee485a6736d188402aa10e6fd38a812a9e45a7dd2d4885a63a
|
||||
type: rasterhash
|
||||
|
||||
@ -1670,11 +1670,11 @@ tests:
|
||||
- algorithm: qgis:dropgeometries
|
||||
name: Drop geometries
|
||||
params:
|
||||
INPUT_LAYER:
|
||||
INPUT:
|
||||
name: polys.gml
|
||||
type: vector
|
||||
results:
|
||||
OUTPUT_TABLE:
|
||||
OUTPUT:
|
||||
name: expected/dropped_geometry.csv
|
||||
type: vector
|
||||
|
||||
|
@ -142,7 +142,7 @@ bool QgsCentroidAlgorithm::processAlgorithm( QgsProcessingContext &, QgsProcessi
|
||||
QVariantMap QgsCentroidAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
QVariantMap outputs;
|
||||
outputs.insert( QStringLiteral( "OUTPUT_LAYER" ), mSinkId );
|
||||
outputs.insert( QStringLiteral( "OUTPUT" ), mSinkId );
|
||||
return outputs;
|
||||
}
|
||||
|
||||
|
@ -4610,7 +4610,7 @@ void TestQgsProcessing::modelerAlgorithm()
|
||||
QMap<QString, QgsProcessingModelAlgorithm::ModelOutput> alg7c1outputs;
|
||||
QgsProcessingModelAlgorithm::ModelOutput alg7c1out1( QStringLiteral( "my_output" ) );
|
||||
alg7c1out1.setChildId( "cx1" );
|
||||
alg7c1out1.setChildOutputName( "OUTPUT_LAYER" );
|
||||
alg7c1out1.setChildOutputName( "OUTPUT" );
|
||||
alg7c1out1.setDescription( QStringLiteral( "my output" ) );
|
||||
alg7c1outputs.insert( QStringLiteral( "my_output" ), alg7c1out1 );
|
||||
alg7c1.setModelOutputs( alg7c1outputs );
|
||||
@ -4630,7 +4630,7 @@ void TestQgsProcessing::modelerAlgorithm()
|
||||
QMap<QString, QgsProcessingModelAlgorithm::ModelOutput> alg7c2outputs;
|
||||
QgsProcessingModelAlgorithm::ModelOutput alg7c2out1( QStringLiteral( "my_output2" ) );
|
||||
alg7c2out1.setChildId( "cx2" );
|
||||
alg7c2out1.setChildOutputName( "OUTPUT_LAYER" );
|
||||
alg7c2out1.setChildOutputName( "OUTPUT" );
|
||||
alg7c2out1.setDescription( QStringLiteral( "my output2" ) );
|
||||
alg7c2outputs.insert( QStringLiteral( "my_output2" ), alg7c2out1 );
|
||||
alg7c2.setModelOutputs( alg7c2outputs );
|
||||
@ -4700,7 +4700,7 @@ void TestQgsProcessing::modelExecution()
|
||||
alg2c1.addParameterSources( "DISSOLVE", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromStaticValue( false ) );
|
||||
QMap<QString, QgsProcessingModelAlgorithm::ModelOutput> outputs1;
|
||||
QgsProcessingModelAlgorithm::ModelOutput out1( "MODEL_OUT_LAYER" );
|
||||
out1.setChildOutputName( "OUTPUT_LAYER" );
|
||||
out1.setChildOutputName( "OUTPUT" );
|
||||
outputs1.insert( QStringLiteral( "MODEL_OUT_LAYER" ), out1 );
|
||||
alg2c1.setModelOutputs( outputs1 );
|
||||
model2.addChildAlgorithm( alg2c1 );
|
||||
@ -4720,7 +4720,7 @@ void TestQgsProcessing::modelExecution()
|
||||
QCOMPARE( params.value( "END_CAP_STYLE" ).toInt(), 1 );
|
||||
QCOMPARE( params.value( "JOIN_STYLE" ).toInt(), 2 );
|
||||
QCOMPARE( params.value( "INPUT" ).toString(), QStringLiteral( "my_layer_id" ) );
|
||||
QCOMPARE( params.value( "OUTPUT_LAYER" ).toString(), QStringLiteral( "dest.shp" ) );
|
||||
QCOMPARE( params.value( "OUTPUT" ).toString(), QStringLiteral( "dest.shp" ) );
|
||||
QCOMPARE( params.count(), 7 );
|
||||
|
||||
QVariantMap results;
|
||||
@ -4735,7 +4735,7 @@ void TestQgsProcessing::modelExecution()
|
||||
model2.addChildAlgorithm( alg2c2 );
|
||||
params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx2" ), modelInputs, childResults );
|
||||
QCOMPARE( params.value( "INPUT" ).toString(), QStringLiteral( "dest.shp" ) );
|
||||
QCOMPARE( params.value( "OUTPUT_LAYER" ).toString(), QStringLiteral( "memory:" ) );
|
||||
QCOMPARE( params.value( "OUTPUT" ).toString(), QStringLiteral( "memory:" ) );
|
||||
QCOMPARE( params.count(), 2 );
|
||||
|
||||
// a child with an optional output
|
||||
@ -4770,8 +4770,8 @@ void TestQgsProcessing::modelExecution()
|
||||
"##my_out=output outputVector\n"
|
||||
"results={}\n"
|
||||
"outputs['cx1']=processing.run('native:buffer', {'DISSOLVE':false,'DISTANCE':parameters['DIST'],'END_CAP_STYLE':1,'INPUT':parameters['SOURCE_LAYER'],'JOIN_STYLE':2,'SEGMENTS':16}, context=context, feedback=feedback)\n"
|
||||
"results['MODEL_OUT_LAYER']=outputs['cx1']['OUTPUT_LAYER']\n"
|
||||
"outputs['cx2']=processing.run('native:centroids', {'INPUT':outputs['cx1']['OUTPUT_LAYER']}, context=context, feedback=feedback)\n"
|
||||
"results['MODEL_OUT_LAYER']=outputs['cx1']['OUTPUT']\n"
|
||||
"outputs['cx2']=processing.run('native:centroids', {'INPUT':outputs['cx1']['OUTPUT']}, context=context, feedback=feedback)\n"
|
||||
"outputs['cx3']=processing.run('native:extractbyexpression', {'EXPRESSION':true,'INPUT':outputs['cx1']['OUTPUT_LAYER'],'OUTPUT':parameters['MY_OUT']}, context=context, feedback=feedback)\n"
|
||||
"results['MY_OUT']=outputs['cx3']['OUTPUT']\n"
|
||||
"return results" ).split( '\n' );
|
||||
|
Loading…
x
Reference in New Issue
Block a user