Skip to content

Commit d4af761

Browse files
committedJul 20, 2017
Flip some more algorithms to feature based algorithms
1 parent 6e49403 commit d4af761

15 files changed

+278
-565
lines changed
 

‎python/plugins/processing/algs/qgis/Boundary.py

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -28,31 +28,20 @@
2828
import os
2929

3030
from qgis.core import (QgsGeometry,
31-
QgsWkbTypes,
32-
QgsFeatureSink,
33-
QgsProcessing,
34-
QgsProcessingParameterFeatureSource,
35-
QgsProcessingParameterFeatureSink)
31+
QgsWkbTypes)
3632

3733
from qgis.PyQt.QtGui import QIcon
3834

39-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
35+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
4036

4137
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
4238

4339

44-
class Boundary(QgisAlgorithm):
45-
46-
INPUT_LAYER = 'INPUT_LAYER'
47-
OUTPUT_LAYER = 'OUTPUT_LAYER'
40+
class Boundary(QgisFeatureBasedAlgorithm):
4841

4942
def __init__(self):
5043
super().__init__()
5144

52-
def initAlgorithm(self, config=None):
53-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT_LAYER, self.tr('Input layer'), [QgsProcessing.TypeVectorLine, QgsProcessing.TypeVectorPolygon]))
54-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT_LAYER, self.tr('Boundary')))
55-
5645
def icon(self):
5746
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'convex_hull.png'))
5847

@@ -65,10 +54,10 @@ def name(self):
6554
def displayName(self):
6655
return self.tr('Boundary')
6756

68-
def processAlgorithm(self, parameters, context, feedback):
69-
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
57+
def outputName(self):
58+
return self.tr('Boundary')
7059

71-
input_wkb = source.wkbType()
60+
def outputWkbType(self, input_wkb):
7261
if QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.LineGeometry:
7362
output_wkb = QgsWkbTypes.MultiPoint
7463
elif QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.PolygonGeometry:
@@ -78,26 +67,15 @@ def processAlgorithm(self, parameters, context, feedback):
7867
if QgsWkbTypes.hasM(input_wkb):
7968
output_wkb = QgsWkbTypes.addM(output_wkb)
8069

81-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context,
82-
source.fields(), output_wkb, source.sourceCrs())
83-
84-
features = source.getFeatures()
85-
total = 100.0 / source.featureCount() if source.featureCount() else 0
86-
87-
for current, input_feature in enumerate(features):
88-
if feedback.isCanceled():
89-
break
90-
output_feature = input_feature
91-
input_geometry = input_feature.geometry()
92-
if input_geometry:
93-
output_geometry = QgsGeometry(input_geometry.geometry().boundary())
94-
if not output_geometry:
95-
feedback.reportError(self.tr('No boundary for feature {} (possibly a closed linestring?)').format(input_feature.id()))
96-
output_feature.clearGeometry()
97-
else:
98-
output_feature.setGeometry(output_geometry)
99-
100-
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
101-
feedback.setProgress(int(current * total))
102-
103-
return {self.OUTPUT_LAYER: dest_id}
70+
return output_wkb
71+
72+
def processFeature(self, feature, feedback):
73+
input_geometry = feature.geometry()
74+
if input_geometry:
75+
output_geometry = QgsGeometry(input_geometry.geometry().boundary())
76+
if not output_geometry:
77+
feedback.reportError(self.tr('No boundary for feature {} (possibly a closed linestring?)').format(feature.id()))
78+
feature.clearGeometry()
79+
else:
80+
feature.setGeometry(output_geometry)
81+
return feature

‎python/plugins/processing/algs/qgis/DeleteColumn.py

Lines changed: 28 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,13 @@
2525

2626
__revision__ = '$Format:%H$'
2727

28-
from qgis.core import (QgsFeatureSink,
29-
QgsProcessingParameterFeatureSource,
30-
QgsProcessingParameterFeatureSink,
31-
QgsProcessingParameterField)
32-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
28+
from qgis.core import (QgsProcessingParameterField)
29+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
3330

3431

35-
class DeleteColumn(QgisAlgorithm):
32+
class DeleteColumn(QgisFeatureBasedAlgorithm):
3633

37-
INPUT = 'INPUT'
3834
COLUMNS = 'COLUMN'
39-
OUTPUT = 'OUTPUT'
4035

4136
def tags(self):
4237
return self.tr('drop,delete,remove,fields,columns,attributes').split(',')
@@ -46,55 +41,44 @@ def group(self):
4641

4742
def __init__(self):
4843
super().__init__()
44+
self.fields_to_delete = []
45+
self.field_indices = []
4946

50-
def initAlgorithm(self, config=None):
51-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer')))
47+
def initParameters(self, config=None):
5248
self.addParameter(QgsProcessingParameterField(self.COLUMNS,
5349
self.tr('Fields to drop'),
54-
None, self.INPUT, QgsProcessingParameterField.Any, True))
55-
56-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Output layer')))
50+
None, 'INPUT', QgsProcessingParameterField.Any, True))
5751

5852
def name(self):
5953
return 'deletecolumn'
6054

6155
def displayName(self):
6256
return self.tr('Drop field(s)')
6357

64-
def processAlgorithm(self, parameters, context, feedback):
65-
source = self.parameterAsSource(parameters, self.INPUT, context)
66-
fields_to_delete = self.parameterAsFields(parameters, self.COLUMNS, context)
58+
def outputName(self):
59+
return self.tr('Fields dropped')
60+
61+
def prepareAlgorithm(self, parameters, context, feedback):
62+
self.fields_to_delete = self.parameterAsFields(parameters, self.COLUMNS, context)
63+
return True
6764

68-
fields = source.fields()
69-
field_indices = []
65+
def outputFields(self, input_fields):
7066
# loop through twice - first we need to build up a list of original attribute indices
71-
for f in fields_to_delete:
72-
index = fields.lookupField(f)
73-
field_indices.append(index)
67+
for f in self.fields_to_delete:
68+
index = input_fields.lookupField(f)
69+
self.field_indices.append(index)
7470

7571
# important - make sure we remove from the end so we aren't changing used indices as we go
76-
field_indices.sort(reverse=True)
72+
self.field_indices.sort(reverse=True)
7773

7874
# this second time we make a cleaned version of the fields
79-
for index in field_indices:
80-
fields.remove(index)
81-
82-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
83-
fields, source.wkbType(), source.sourceCrs())
84-
85-
features = source.getFeatures()
86-
total = 100.0 / source.featureCount() if source.featureCount() else 0
87-
88-
for current, f in enumerate(features):
89-
if feedback.isCanceled():
90-
break
91-
92-
attributes = f.attributes()
93-
for index in field_indices:
94-
del attributes[index]
95-
f.setAttributes(attributes)
96-
sink.addFeature(f, QgsFeatureSink.FastInsert)
97-
98-
feedback.setProgress(int(current * total))
99-
100-
return {self.OUTPUT: dest_id}
75+
for index in self.field_indices:
76+
input_fields.remove(index)
77+
return input_fields
78+
79+
def processFeature(self, feature, feedback):
80+
attributes = feature.attributes()
81+
for index in self.field_indices:
82+
del attributes[index]
83+
feature.setAttributes(attributes)
84+
return feature

‎python/plugins/processing/algs/qgis/DeleteHoles.py

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,23 @@
2424

2525
__revision__ = '$Format:%H$'
2626

27-
from qgis.core import (QgsFeatureSink,
28-
QgsProcessing,
29-
QgsProcessingParameterFeatureSource,
30-
QgsProcessingParameterNumber,
31-
QgsProcessingParameterFeatureSink)
32-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
27+
from qgis.core import (QgsProcessingParameterNumber)
28+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
3329

3430

35-
class DeleteHoles(QgisAlgorithm):
31+
class DeleteHoles(QgisFeatureBasedAlgorithm):
3632

37-
INPUT = 'INPUT'
3833
MIN_AREA = 'MIN_AREA'
39-
OUTPUT = 'OUTPUT'
4034

4135
def __init__(self):
4236
super().__init__()
37+
self.min_area = None
4338

44-
def initAlgorithm(self, config=None):
45-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
46-
self.tr('Input layer'), [QgsProcessing.TypeVectorPolygon]))
39+
def initParameters(self, config=None):
4740
self.addParameter(QgsProcessingParameterNumber(self.MIN_AREA,
4841
self.tr('Remove holes with area less than'), QgsProcessingParameterNumber.Double,
4942
0, True, 0.0, 10000000.0))
5043

51-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Cleaned'), QgsProcessing.TypeVectorPolygon))
52-
5344
def tags(self):
5445
return self.tr('remove,delete,drop,holes,rings,fill').split(',')
5546

@@ -62,25 +53,16 @@ def name(self):
6253
def displayName(self):
6354
return self.tr('Delete holes')
6455

65-
def processAlgorithm(self, parameters, context, feedback):
66-
source = self.parameterAsSource(parameters, self.INPUT, context)
67-
min_area = self.parameterAsDouble(parameters, self.MIN_AREA, context)
68-
if min_area == 0.0:
69-
min_area = -1.0
70-
71-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
72-
source.fields(), source.wkbType(), source.sourceCrs())
73-
74-
features = source.getFeatures()
75-
total = 100.0 / source.featureCount() if source.featureCount() else 0
76-
77-
for current, f in enumerate(features):
78-
if feedback.isCanceled():
79-
break
56+
def outputName(self):
57+
return self.tr('Cleaned')
8058

81-
if f.hasGeometry():
82-
f.setGeometry(f.geometry().removeInteriorRings(min_area))
83-
sink.addFeature(f, QgsFeatureSink.FastInsert)
84-
feedback.setProgress(int(current * total))
59+
def prepareAlgorithm(self, parameters, context, feedback):
60+
self.min_area = self.parameterAsDouble(parameters, self.MIN_AREA, context)
61+
if self.min_area == 0.0:
62+
self.min_area = -1.0
63+
return True
8564

86-
return {self.OUTPUT: dest_id}
65+
def processFeature(self, feature, feedback):
66+
if feature.hasGeometry():
67+
feature.setGeometry(feature.geometry().removeInteriorRings(self.min_area))
68+
return feature

‎python/plugins/processing/algs/qgis/DensifyGeometries.py

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,14 @@
2828

2929
import os
3030

31-
from qgis.core import (QgsFeatureSink,
32-
QgsProcessing,
33-
QgsProcessingParameterFeatureSource,
34-
QgsProcessingParameterNumber,
35-
QgsProcessingParameterFeatureSink)
36-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
31+
from qgis.core import (QgsProcessingParameterNumber)
3732

33+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
3834

39-
class DensifyGeometries(QgisAlgorithm):
4035

41-
INPUT = 'INPUT'
36+
class DensifyGeometries(QgisFeatureBasedAlgorithm):
37+
4238
VERTICES = 'VERTICES'
43-
OUTPUT = 'OUTPUT'
4439

4540
def tags(self):
4641
return self.tr('add,vertices,points').split(',')
@@ -50,41 +45,28 @@ def group(self):
5045

5146
def __init__(self):
5247
super().__init__()
48+
self.vertices = None
5349

54-
def initAlgorithm(self, config=None):
55-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
56-
self.tr('Input layer'), [QgsProcessing.TypeVectorPolygon, QgsProcessing.TypeVectorLine]))
50+
def initParameters(self, config=None):
5751
self.addParameter(QgsProcessingParameterNumber(self.VERTICES,
5852
self.tr('Vertices to add'), QgsProcessingParameterNumber.Integer,
5953
1, False, 1, 10000000))
6054

61-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Densified')))
62-
6355
def name(self):
6456
return 'densifygeometries'
6557

6658
def displayName(self):
6759
return self.tr('Densify geometries')
6860

69-
def processAlgorithm(self, parameters, context, feedback):
70-
source = self.parameterAsSource(parameters, self.INPUT, context)
71-
vertices = self.parameterAsInt(parameters, self.VERTICES, context)
72-
73-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
74-
source.fields(), source.wkbType(), source.sourceCrs())
75-
76-
features = source.getFeatures()
77-
total = 100.0 / source.featureCount() if source.featureCount() else 0
78-
79-
for current, f in enumerate(features):
80-
if feedback.isCanceled():
81-
break
61+
def outputName(self):
62+
return self.tr('Densified')
8263

83-
feature = f
84-
if feature.hasGeometry():
85-
new_geometry = feature.geometry().densifyByCount(vertices)
86-
feature.setGeometry(new_geometry)
87-
sink.addFeature(feature, QgsFeatureSink.FastInsert)
88-
feedback.setProgress(int(current * total))
64+
def prepareAlgorithm(self, parameters, context, feedback):
65+
self.vertices = self.parameterAsInt(parameters, self.VERTICES, context)
66+
return True
8967

90-
return {self.OUTPUT: dest_id}
68+
def processFeature(self, feature, feedback):
69+
if feature.hasGeometry():
70+
new_geometry = feature.geometry().densifyByCount(self.vertices)
71+
feature.setGeometry(new_geometry)
72+
return feature

‎python/plugins/processing/algs/qgis/DensifyGeometriesInterval.py

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -27,60 +27,42 @@
2727

2828
__revision__ = '$Format:%H$'
2929

30-
from qgis.core import (QgsFeatureSink,
31-
QgsProcessing,
32-
QgsProcessingParameterFeatureSource,
33-
QgsProcessingParameterNumber,
34-
QgsProcessingParameterFeatureSink)
35-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
30+
from qgis.core import (QgsProcessingParameterNumber)
3631

32+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
3733

38-
class DensifyGeometriesInterval(QgisAlgorithm):
3934

40-
INPUT = 'INPUT'
35+
class DensifyGeometriesInterval(QgisFeatureBasedAlgorithm):
36+
4137
INTERVAL = 'INTERVAL'
42-
OUTPUT = 'OUTPUT'
4338

4439
def group(self):
4540
return self.tr('Vector geometry tools')
4641

4742
def __init__(self):
4843
super().__init__()
44+
self.interval = None
4945

50-
def initAlgorithm(self, config=None):
51-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
52-
self.tr('Input layer'), [QgsProcessing.TypeVectorPolygon, QgsProcessing.TypeVectorLine]))
46+
def initParameters(self, config=None):
5347
self.addParameter(QgsProcessingParameterNumber(self.INTERVAL,
5448
self.tr('Interval between vertices to add'), QgsProcessingParameterNumber.Double,
5549
1, False, 0, 10000000))
5650

57-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Densified')))
58-
5951
def name(self):
6052
return 'densifygeometriesgivenaninterval'
6153

6254
def displayName(self):
6355
return self.tr('Densify geometries given an interval')
6456

65-
def processAlgorithm(self, parameters, context, feedback):
66-
source = self.parameterAsSource(parameters, self.INPUT, context)
67-
interval = self.parameterAsDouble(parameters, self.INTERVAL, context)
68-
69-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
70-
source.fields(), source.wkbType(), source.sourceCrs())
57+
def outputName(self):
58+
return self.tr('Densified')
7159

72-
features = source.getFeatures()
73-
total = 100.0 / source.featureCount() if source.featureCount() else 0
74-
for current, f in enumerate(features):
75-
if feedback.isCanceled():
76-
break
77-
78-
feature = f
79-
if feature.hasGeometry():
80-
new_geometry = feature.geometry().densifyByDistance(float(interval))
81-
feature.setGeometry(new_geometry)
82-
sink.addFeature(feature, QgsFeatureSink.FastInsert)
83-
84-
feedback.setProgress(int(current * total))
60+
def prepareAlgorithm(self, parameters, context, feedback):
61+
interval = self.parameterAsDouble(parameters, self.INTERVAL, context)
62+
return True
8563

86-
return {self.OUTPUT: dest_id}
64+
def processFeature(self, feature, feedback):
65+
if feature.hasGeometry():
66+
new_geometry = feature.geometry().densifyByDistance(float(interval))
67+
feature.setGeometry(new_geometry)
68+
return feature

‎python/plugins/processing/algs/qgis/DropGeometry.py

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,13 @@
2525

2626
__revision__ = '$Format:%H$'
2727

28-
from qgis.core import (QgsFeatureRequest,
29-
QgsWkbTypes,
30-
QgsFeatureSink,
31-
QgsCoordinateReferenceSystem,
32-
QgsProcessing,
33-
QgsProcessingParameterFeatureSource,
34-
QgsProcessingParameterFeatureSink)
35-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
28+
from qgis.core import (QgsWkbTypes,
29+
QgsCoordinateReferenceSystem)
3630

31+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
3732

38-
class DropGeometry(QgisAlgorithm):
3933

40-
INPUT = 'INPUT'
41-
OUTPUT = 'OUTPUT'
34+
class DropGeometry(QgisFeatureBasedAlgorithm):
4235

4336
def tags(self):
4437
return self.tr('remove,drop,delete,geometry,objects').split(',')
@@ -49,31 +42,21 @@ def group(self):
4942
def __init__(self):
5043
super().__init__()
5144

52-
def initAlgorithm(self, config=None):
53-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer'), [QgsProcessing.TypeVectorPoint, QgsProcessing.TypeVectorLine, QgsProcessing.TypeVectorPolygon]))
54-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Dropped geometry')))
55-
5645
def name(self):
5746
return 'dropgeometries'
5847

5948
def displayName(self):
6049
return self.tr('Drop geometries')
6150

62-
def processAlgorithm(self, parameters, context, feedback):
63-
source = self.parameterAsSource(parameters, self.INPUT, context)
64-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
65-
source.fields(), QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())
66-
67-
request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
68-
features = source.getFeatures(request)
69-
total = 100.0 / source.featureCount() if source.featureCount() else 0
51+
def outputName(self):
52+
return self.tr('Dropped geometries')
7053

71-
for current, input_feature in enumerate(features):
72-
if feedback.isCanceled():
73-
break
54+
def outputCrs(self, input_crs):
55+
return QgsCoordinateReferenceSystem()
7456

75-
input_feature.clearGeometry()
76-
sink.addFeature(input_feature, QgsFeatureSink.FastInsert)
77-
feedback.setProgress(int(current * total))
57+
def outputWkbType(self, input_wkb_type):
58+
return QgsWkbTypes.NoGeometry
7859

79-
return {self.OUTPUT: dest_id}
60+
def processFeature(self, feature, feedback):
61+
feature.clearGeometry()
62+
return feature

‎python/plugins/processing/algs/qgis/LinesToPolygons.py

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,13 @@
4242
QgsProcessingParameterFeatureSink,
4343
QgsProcessingUtils)
4444

45-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
45+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
4646
from processing.tools import dataobjects, vector
4747

4848
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
4949

5050

51-
class LinesToPolygons(QgisAlgorithm):
52-
53-
INPUT = 'INPUT'
54-
OUTPUT = 'OUTPUT'
51+
class LinesToPolygons(QgisFeatureBasedAlgorithm):
5552

5653
def icon(self):
5754
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'to_lines.png'))
@@ -65,52 +62,27 @@ def group(self):
6562
def __init__(self):
6663
super().__init__()
6764

68-
def initAlgorithm(self, config=None):
69-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
70-
self.tr('Input layer'),
71-
[QgsProcessing.TypeVectorLine]))
72-
73-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT,
74-
self.tr('Lines to polygons'),
75-
QgsProcessing.TypeVectorPolygon))
76-
7765
def name(self):
7866
return 'linestopolygons'
7967

8068
def displayName(self):
8169
return self.tr('Lines to polygons')
8270

83-
def processAlgorithm(self, parameters, context, feedback):
84-
source = self.parameterAsSource(parameters, self.INPUT, context)
85-
86-
geomType = self.convertWkbToPolygons(source.wkbType())
87-
88-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
89-
source.fields(), geomType, source.sourceCrs())
90-
91-
outFeat = QgsFeature()
92-
93-
total = 100.0 / source.featureCount() if source.featureCount() else 0
94-
count = 0
95-
96-
for feat in source.getFeatures():
97-
if feedback.isCanceled():
98-
break
71+
def outputName(self):
72+
return self.tr('Polygons')
9973

100-
if feat.hasGeometry():
101-
outFeat.setGeometry(QgsGeometry(self.convertToPolygons(feat.geometry())))
102-
attrs = feat.attributes()
103-
outFeat.setAttributes(attrs)
104-
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
105-
if outFeat.geometry().isEmpty():
106-
feedback.reportError(self.tr("One or more line ignored due to geometry not having a minimum of three vertices."))
107-
else:
108-
sink.addFeature(feat, QgsFeatureSink.FastInsert)
74+
def outputType(self):
75+
return QgsProcessing.TypeVectorPolygon
10976

110-
count += 1
111-
feedback.setProgress(int(count * total))
77+
def outputWkbType(self, input_wkb_type):
78+
return self.convertWkbToPolygons(input_wkb_type)
11279

113-
return {self.OUTPUT: dest_id}
80+
def processFeature(self, feature, feedback):
81+
if feature.hasGeometry():
82+
feature.setGeometry(QgsGeometry(self.convertToPolygons(feature.geometry())))
83+
if feature.geometry().isEmpty():
84+
feedback.reportError(self.tr("One or more line ignored due to geometry not having a minimum of three vertices."))
85+
return feature
11486

11587
def convertWkbToPolygons(self, wkb):
11688
multi_wkb = None

‎python/plugins/processing/algs/qgis/OffsetLine.py

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,13 @@
3535
QgsProcessingParameterEnum,
3636
QgsProcessingParameterFeatureSink)
3737

38-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
38+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
3939

4040
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
4141

4242

43-
class OffsetLine(QgisAlgorithm):
44-
INPUT = 'INPUT'
45-
OUTPUT = 'OUTPUT'
43+
class OffsetLine(QgisFeatureBasedAlgorithm):
44+
4645
DISTANCE = 'DISTANCE'
4746
SEGMENTS = 'SEGMENTS'
4847
JOIN_STYLE = 'JOIN_STYLE'
@@ -54,9 +53,12 @@ def group(self):
5453
def __init__(self):
5554
super().__init__()
5655

57-
def initAlgorithm(self, config=None):
58-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer'),
59-
[QgsProcessing.TypeVectorLine]))
56+
self.distance = None
57+
self.segments = None
58+
self.join_style = None
59+
self.miter_limit = None
60+
61+
def initParameters(self, config=None):
6062
self.addParameter(QgsProcessingParameterNumber(self.DISTANCE,
6163
self.tr('Distance'),
6264
type=QgsProcessingParameterNumber.Double,
@@ -76,43 +78,33 @@ def initAlgorithm(self, config=None):
7678
self.tr('Mitre limit'), type=QgsProcessingParameterNumber.Double,
7779
minValue=1, defaultValue=2))
7880

79-
self.addParameter(
80-
QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Offset'), QgsProcessing.TypeVectorLine))
81-
8281
def name(self):
8382
return 'offsetline'
8483

8584
def displayName(self):
8685
return self.tr('Offset line')
8786

88-
def processAlgorithm(self, parameters, context, feedback):
89-
source = self.parameterAsSource(parameters, self.INPUT, context)
90-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
91-
source.fields(), source.wkbType(), source.sourceCrs())
92-
93-
distance = self.parameterAsDouble(parameters, self.DISTANCE, context)
94-
segments = self.parameterAsInt(parameters, self.SEGMENTS, context)
95-
join_style = self.parameterAsEnum(parameters, self.JOIN_STYLE, context) + 1
96-
miter_limit = self.parameterAsDouble(parameters, self.MITRE_LIMIT, context)
97-
98-
features = source.getFeatures()
99-
total = 100.0 / source.featureCount() if source.featureCount() else 0
87+
def outputName(self):
88+
return self.tr('Offset')
10089

101-
for current, input_feature in enumerate(features):
102-
if feedback.isCanceled():
103-
break
90+
def outputType(self):
91+
return QgsProcessing.TypeVectorLine
10492

105-
output_feature = input_feature
106-
input_geometry = input_feature.geometry()
107-
if input_geometry:
108-
output_geometry = input_geometry.offsetCurve(distance, segments, join_style, miter_limit)
109-
if not output_geometry:
110-
raise QgsProcessingException(
111-
self.tr('Error calculating line offset'))
93+
def prepareAlgorithm(self, parameters, context, feedback):
94+
self.distance = self.parameterAsDouble(parameters, self.DISTANCE, context)
95+
self.segments = self.parameterAsInt(parameters, self.SEGMENTS, context)
96+
self.join_style = self.parameterAsEnum(parameters, self.JOIN_STYLE, context) + 1
97+
self.miter_limit = self.parameterAsDouble(parameters, self.MITRE_LIMIT, context)
98+
return True
11299

113-
output_feature.setGeometry(output_geometry)
100+
def processFeature(self, feature, feedback):
101+
input_geometry = feature.geometry()
102+
if input_geometry:
103+
output_geometry = input_geometry.offsetCurve(self.distance, self.segments, self.join_style, self.miter_limit)
104+
if not output_geometry:
105+
raise QgsProcessingException(
106+
self.tr('Error calculating line offset'))
114107

115-
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
116-
feedback.setProgress(int(current * total))
108+
feature.setGeometry(output_geometry)
117109

118-
return {self.OUTPUT: dest_id}
110+
return feature

‎python/plugins/processing/algs/qgis/Orthogonalize.py

Lines changed: 23 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,14 @@
2525

2626
__revision__ = '$Format:%H$'
2727

28-
from qgis.core import (QgsFeatureSink,
29-
QgsProcessingException,
30-
QgsProcessing,
28+
from qgis.core import (QgsProcessingException,
3129
QgsProcessingParameterDefinition,
32-
QgsProcessingParameterFeatureSource,
33-
QgsProcessingParameterNumber,
34-
QgsProcessingParameterFeatureSink)
35-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
30+
QgsProcessingParameterNumber)
31+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
3632

3733

38-
class Orthogonalize(QgisAlgorithm):
39-
INPUT = 'INPUT'
40-
OUTPUT = 'OUTPUT'
34+
class Orthogonalize(QgisFeatureBasedAlgorithm):
35+
4136
MAX_ITERATIONS = 'MAX_ITERATIONS'
4237
DISTANCE_THRESHOLD = 'DISTANCE_THRESHOLD'
4338
ANGLE_TOLERANCE = 'ANGLE_TOLERANCE'
@@ -50,12 +45,10 @@ def group(self):
5045

5146
def __init__(self):
5247
super().__init__()
48+
self.max_iterations = None
49+
self.angle_tolerance = None
5350

54-
def initAlgorithm(self, config=None):
55-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer'),
56-
[QgsProcessing.TypeVectorLine,
57-
QgsProcessing.TypeVectorPolygon]))
58-
51+
def initParameters(self, config=None):
5952
self.addParameter(QgsProcessingParameterNumber(self.ANGLE_TOLERANCE,
6053
self.tr('Maximum angle tolerance (degrees)'),
6154
type=QgsProcessingParameterNumber.Double,
@@ -68,41 +61,27 @@ def initAlgorithm(self, config=None):
6861
max_iterations.setFlags(max_iterations.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
6962
self.addParameter(max_iterations)
7063

71-
self.addParameter(
72-
QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Orthogonalized')))
73-
7464
def name(self):
7565
return 'orthogonalize'
7666

7767
def displayName(self):
7868
return self.tr('Orthogonalize')
7969

80-
def processAlgorithm(self, parameters, context, feedback):
81-
source = self.parameterAsSource(parameters, self.INPUT, context)
82-
max_iterations = self.parameterAsInt(parameters, self.MAX_ITERATIONS, context)
83-
angle_tolerance = self.parameterAsDouble(parameters, self.ANGLE_TOLERANCE, context)
84-
85-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
86-
source.fields(), source.wkbType(), source.sourceCrs())
87-
88-
features = source.getFeatures()
89-
total = 100.0 / source.featureCount() if source.featureCount() else 0
90-
91-
for current, input_feature in enumerate(features):
92-
if feedback.isCanceled():
93-
break
94-
95-
output_feature = input_feature
96-
input_geometry = input_feature.geometry()
97-
if input_geometry:
98-
output_geometry = input_geometry.orthogonalize(1.0e-8, max_iterations, angle_tolerance)
99-
if not output_geometry:
100-
raise QgsProcessingException(
101-
self.tr('Error orthogonalizing geometry'))
70+
def outputName(self):
71+
return self.tr('Orthogonalized')
10272

103-
output_feature.setGeometry(output_geometry)
73+
def prepareAlgorithm(self, parameters, context, feedback):
74+
self.max_iterations = self.parameterAsInt(parameters, self.MAX_ITERATIONS, context)
75+
self.angle_tolerance = self.parameterAsDouble(parameters, self.ANGLE_TOLERANCE, context)
76+
return True
10477

105-
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
106-
feedback.setProgress(int(current * total))
78+
def processFeature(self, feature, feedback):
79+
input_geometry = feature.geometry()
80+
if input_geometry:
81+
output_geometry = input_geometry.orthogonalize(1.0e-8, self.max_iterations, self.angle_tolerance)
82+
if not output_geometry:
83+
raise QgsProcessingException(
84+
self.tr('Error orthogonalizing geometry'))
10785

108-
return {self.OUTPUT: dest_id}
86+
feature.setGeometry(output_geometry)
87+
return feature

‎python/plugins/processing/algs/qgis/PointOnSurface.py

Lines changed: 19 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,18 @@
2727

2828
import os
2929

30-
from qgis.core import (QgsWkbTypes,
31-
QgsFeatureSink,
32-
QgsProcessing,
33-
QgsProcessingParameterFeatureSource,
34-
QgsProcessingParameterFeatureSink)
30+
from qgis.core import (QgsProcessing,
31+
QgsProcessingException,
32+
QgsWkbTypes)
3533

3634
from qgis.PyQt.QtGui import QIcon
3735

38-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
39-
from processing.tools import dataobjects
36+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
4037

4138
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
4239

4340

44-
class PointOnSurface(QgisAlgorithm):
45-
46-
INPUT_LAYER = 'INPUT_LAYER'
47-
OUTPUT_LAYER = 'OUTPUT_LAYER'
41+
class PointOnSurface(QgisFeatureBasedAlgorithm):
4842

4943
def icon(self):
5044
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'centroids.png'))
@@ -55,39 +49,27 @@ def group(self):
5549
def __init__(self):
5650
super().__init__()
5751

58-
def initAlgorithm(self, config=None):
59-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT_LAYER,
60-
self.tr('Input layer')))
61-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT_LAYER, self.tr('Point'), QgsProcessing.TypeVectorPoint))
62-
6352
def name(self):
6453
return 'pointonsurface'
6554

6655
def displayName(self):
6756
return self.tr('Point on surface')
6857

69-
def processAlgorithm(self, parameters, context, feedback):
70-
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)
71-
72-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context, source.fields(), QgsWkbTypes.Point, source.sourceCrs())
73-
74-
features = source.getFeatures()
75-
total = 100.0 / source.featureCount() if source.featureCount() else 0
76-
77-
for current, input_feature in enumerate(features):
78-
if feedback.isCanceled():
79-
break
58+
def outputName(self):
59+
return self.tr('Point')
8060

81-
output_feature = input_feature
82-
input_geometry = input_feature.geometry()
83-
if input_geometry:
84-
output_geometry = input_geometry.pointOnSurface()
85-
if not output_geometry:
86-
raise QgsProcessingException(self.tr('Error calculating point on surface: `{error_message}`'.format(error_message=output_geometry.error())))
61+
def outputType(self):
62+
return QgsProcessing.TypeVectorPoint
8763

88-
output_feature.setGeometry(output_geometry)
64+
def outputWkbType(self, input_wkb_type):
65+
return QgsWkbTypes.Point
8966

90-
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
91-
feedback.setProgress(int(current * total))
67+
def processFeature(self, feature, feedback):
68+
input_geometry = feature.geometry()
69+
if input_geometry:
70+
output_geometry = input_geometry.pointOnSurface()
71+
if not output_geometry:
72+
raise QgsProcessingException(self.tr('Error calculating point on surface: `{error_message}`'.format(error_message=output_geometry.error())))
9273

93-
return {self.OUTPUT_LAYER: dest_id}
74+
feature.setGeometry(output_geometry)
75+
return feature

‎python/plugins/processing/algs/qgis/PolygonsToLines.py

Lines changed: 14 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,19 @@
2929

3030
from qgis.PyQt.QtGui import QIcon
3131

32-
from qgis.core import (QgsFeature,
33-
QgsGeometry,
32+
from qgis.core import (QgsGeometry,
3433
QgsGeometryCollection,
3534
QgsMultiLineString,
3635
QgsMultiCurve,
3736
QgsWkbTypes,
38-
QgsFeatureSink,
39-
QgsProcessing,
40-
QgsProcessingParameterFeatureSource,
41-
QgsProcessingParameterFeatureSink,
42-
QgsProcessingUtils)
37+
QgsProcessing)
4338

44-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
45-
from processing.tools import dataobjects
39+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
4640

4741
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
4842

4943

50-
class PolygonsToLines(QgisAlgorithm):
51-
52-
INPUT = 'INPUT'
53-
OUTPUT = 'OUTPUT'
44+
class PolygonsToLines(QgisFeatureBasedAlgorithm):
5445

5546
def icon(self):
5647
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'to_lines.png'))
@@ -64,50 +55,25 @@ def group(self):
6455
def __init__(self):
6556
super().__init__()
6657

67-
def initAlgorithm(self, config=None):
68-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
69-
self.tr('Input layer'),
70-
[QgsProcessing.TypeVectorPolygon]))
71-
72-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT,
73-
self.tr('Polygons to lines'),
74-
QgsProcessing.TypeVectorLine))
75-
7658
def name(self):
7759
return 'polygonstolines'
7860

7961
def displayName(self):
8062
return self.tr('Polygons to lines')
8163

82-
def processAlgorithm(self, parameters, context, feedback):
83-
source = self.parameterAsSource(parameters, self.INPUT, context)
84-
85-
geomType = self.convertWkbToLines(source.wkbType())
86-
87-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
88-
source.fields(), geomType, source.sourceCrs())
89-
90-
outFeat = QgsFeature()
91-
92-
total = 100.0 / source.featureCount() if source.featureCount() else 0
93-
count = 0
94-
95-
for feat in source.getFeatures():
96-
if feedback.isCanceled():
97-
break
64+
def outputName(self):
65+
return self.tr('Lines')
9866

99-
if feat.hasGeometry():
100-
outFeat.setGeometry(QgsGeometry(self.convertToLines(feat.geometry())))
101-
attrs = feat.attributes()
102-
outFeat.setAttributes(attrs)
103-
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
104-
else:
105-
sink.addFeature(feat, QgsFeatureSink.FastInsert)
67+
def outputType(self):
68+
return QgsProcessing.TypeVectorLine
10669

107-
count += 1
108-
feedback.setProgress(int(count * total))
70+
def outputWkbType(self, input_wkb_type):
71+
return self.convertWkbToLines(input_wkb_type)
10972

110-
return {self.OUTPUT: dest_id}
73+
def processFeature(self, feature, feedback):
74+
if feature.hasGeometry():
75+
feature.setGeometry(QgsGeometry(self.convertToLines(feature.geometry())))
76+
return feature
11177

11278
def convertWkbToLines(self, wkb):
11379
multi_wkb = None

‎python/plugins/processing/algs/qgis/ReverseLineDirection.py

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,61 +26,39 @@
2626
__revision__ = '$Format:%H$'
2727

2828
from qgis.core import (QgsGeometry,
29-
QgsFeature,
30-
QgsFeatureSink,
3129
QgsProcessingException,
32-
QgsProcessing,
33-
QgsProcessingParameterFeatureSource,
34-
QgsProcessingParameterFeatureSink)
35-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
30+
QgsProcessing)
31+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
3632

3733

38-
class ReverseLineDirection(QgisAlgorithm):
39-
40-
INPUT = 'INPUT'
41-
OUTPUT = 'OUTPUT'
34+
class ReverseLineDirection(QgisFeatureBasedAlgorithm):
4235

4336
def group(self):
4437
return self.tr('Vector geometry tools')
4538

4639
def __init__(self):
4740
super().__init__()
4841

49-
def initAlgorithm(self, config=None):
50-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer'),
51-
[QgsProcessing.TypeVectorLine]))
52-
self.addParameter(
53-
QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Reversed'), QgsProcessing.TypeVectorLine))
54-
5542
def name(self):
5643
return 'reverselinedirection'
5744

5845
def displayName(self):
5946
return self.tr('Reverse line direction')
6047

61-
def processAlgorithm(self, parameters, context, feedback):
62-
source = self.parameterAsSource(parameters, self.INPUT, context)
63-
64-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
65-
source.fields(), source.wkbType(), source.sourceCrs())
66-
67-
features = source.getFeatures()
68-
total = 100.0 / source.featureCount() if source.featureCount() else 0
69-
for current, inFeat in enumerate(features):
70-
if feedback.isCanceled():
71-
break
48+
def outputName(self):
49+
return self.tr('Reversed')
7250

73-
outFeat = inFeat
74-
if inFeat.geometry():
75-
inGeom = inFeat.geometry()
76-
reversedLine = inGeom.geometry().reversed()
77-
if not reversedLine:
78-
raise QgsProcessingException(
79-
self.tr('Error reversing line'))
80-
outGeom = QgsGeometry(reversedLine)
51+
def outputType(self):
52+
return QgsProcessing.TypeVectorLine
8153

82-
outFeat.setGeometry(outGeom)
83-
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
84-
feedback.setProgress(int(current * total))
54+
def processFeature(self, feature, feedback):
55+
if feature.geometry():
56+
inGeom = feature.geometry()
57+
reversedLine = inGeom.geometry().reversed()
58+
if not reversedLine:
59+
raise QgsProcessingException(
60+
self.tr('Error reversing line'))
61+
outGeom = QgsGeometry(reversedLine)
8562

86-
return {self.OUTPUT: dest_id}
63+
feature.setGeometry(outGeom)
64+
return feature

‎python/plugins/processing/algs/qgis/SimplifyGeometries.py

Lines changed: 23 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,17 @@
3030
from qgis.PyQt.QtGui import QIcon
3131

3232
from qgis.core import (QgsMapToPixelSimplifier,
33-
QgsMessageLog,
34-
QgsFeatureSink,
35-
QgsProcessing,
36-
QgsProcessingParameterFeatureSource,
37-
QgsProcessingParameterFeatureSink,
3833
QgsProcessingParameterEnum,
3934
QgsProcessingParameterNumber)
4035

41-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
36+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
4237

4338
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
4439

4540

46-
class SimplifyGeometries(QgisAlgorithm):
41+
class SimplifyGeometries(QgisFeatureBasedAlgorithm):
4742

48-
INPUT = 'INPUT'
4943
TOLERANCE = 'TOLERANCE'
50-
OUTPUT = 'OUTPUT'
5144
METHOD = 'METHOD'
5245

5346
def icon(self):
@@ -58,11 +51,11 @@ def group(self):
5851

5952
def __init__(self):
6053
super().__init__()
54+
self.tolerance = None
55+
self.method = None
56+
self.simplifier = None
6157

62-
def initAlgorithm(self, config=None):
63-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
64-
self.tr('Input layer'),
65-
[QgsProcessing.TypeVectorPolygon, QgsProcessing.TypeVectorLine]))
58+
def initParameters(self, config=None):
6659
self.methods = [self.tr('Distance (Douglas-Peucker)'),
6760
'Snap to grid',
6861
'Area (Visvalingam)']
@@ -73,51 +66,31 @@ def initAlgorithm(self, config=None):
7366
self.addParameter(QgsProcessingParameterNumber(self.TOLERANCE,
7467
self.tr('Tolerance'), minValue=0.0, maxValue=10000000.0, defaultValue=1.0))
7568

76-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Simplified')))
77-
7869
def name(self):
7970
return 'simplifygeometries'
8071

8172
def displayName(self):
8273
return self.tr('Simplify geometries')
8374

84-
def processAlgorithm(self, parameters, context, feedback):
85-
source = self.parameterAsSource(parameters, self.INPUT, context)
86-
tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)
87-
method = self.parameterAsEnum(parameters, self.METHOD, context)
88-
89-
pointsBefore = 0
90-
pointsAfter = 0
91-
92-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
93-
source.fields(), source.wkbType(), source.sourceCrs())
94-
95-
features = source.getFeatures()
96-
total = 100.0 / source.featureCount() if source.featureCount() else 0
97-
98-
if method != 0:
99-
simplifier = QgsMapToPixelSimplifier(QgsMapToPixelSimplifier.SimplifyGeometry, tolerance, method)
100-
101-
for current, input_feature in enumerate(features):
102-
if feedback.isCanceled():
103-
break
104-
out_feature = input_feature
105-
if input_feature.geometry():
106-
input_geometry = input_feature.geometry()
107-
pointsBefore += input_geometry.geometry().nCoordinates()
75+
def outputName(self):
76+
return self.tr('Simplified')
10877

109-
if method == 0: # distance
110-
output_geometry = input_geometry.simplify(tolerance)
111-
else:
112-
output_geometry = simplifier.simplify(input_geometry)
78+
def prepareAlgorithm(self, parameters, context, feedback):
79+
self.tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)
80+
self.method = self.parameterAsEnum(parameters, self.METHOD, context)
81+
if self.method != 0:
82+
self.simplifier = QgsMapToPixelSimplifier(QgsMapToPixelSimplifier.SimplifyGeometry, self.tolerance, self.method)
11383

114-
pointsAfter += output_geometry.geometry().nCoordinates()
115-
out_feature.setGeometry(output_geometry)
84+
return True
11685

117-
sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
118-
feedback.setProgress(int(current * total))
86+
def processFeature(self, feature, feedback):
87+
if feature.hasGeometry():
88+
input_geometry = feature.geometry()
11989

120-
QgsMessageLog.logMessage(self.tr('Simplify: Input geometries have been simplified from {0} to {1} points').format(pointsBefore, pointsAfter),
121-
self.tr('Processing'), QgsMessageLog.INFO)
90+
if self.method == 0: # distance
91+
output_geometry = input_geometry.simplify(self.tolerance)
92+
else:
93+
output_geometry = self.simplifier.simplify(input_geometry)
12294

123-
return {self.OUTPUT: dest_id}
95+
feature.setGeometry(output_geometry)
96+
return feature

‎python/plugins/processing/algs/qgis/Smooth.py

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,14 @@
2525

2626
__revision__ = '$Format:%H$'
2727

28-
from qgis.core import (QgsFeatureSink,
29-
QgsProcessing,
30-
QgsProcessingException,
31-
QgsProcessingParameterFeatureSource,
32-
QgsProcessingParameterFeatureSink,
28+
from qgis.core import (QgsProcessingException,
3329
QgsProcessingParameterNumber)
3430

35-
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
31+
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
3632

3733

38-
class Smooth(QgisAlgorithm):
34+
class Smooth(QgisFeatureBasedAlgorithm):
3935

40-
INPUT = 'INPUT'
41-
OUTPUT = 'OUTPUT'
4236
ITERATIONS = 'ITERATIONS'
4337
MAX_ANGLE = 'MAX_ANGLE'
4438
OFFSET = 'OFFSET'
@@ -49,9 +43,7 @@ def group(self):
4943
def __init__(self):
5044
super().__init__()
5145

52-
def initAlgorithm(self, config=None):
53-
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
54-
self.tr('Input layer'), [QgsProcessing.TypeVectorPolygon, QgsProcessing.TypeVectorLine]))
46+
def initParameters(self, config=None):
5547
self.addParameter(QgsProcessingParameterNumber(self.ITERATIONS,
5648
self.tr('Iterations'),
5749
defaultValue=1, minValue=1, maxValue=10))
@@ -62,39 +54,27 @@ def initAlgorithm(self, config=None):
6254
self.tr('Maximum node angle to smooth'), QgsProcessingParameterNumber.Double,
6355
defaultValue=180.0, minValue=0.0, maxValue=180.0))
6456

65-
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Smoothed')))
66-
6757
def name(self):
6858
return 'smoothgeometry'
6959

7060
def displayName(self):
7161
return self.tr('Smooth geometry')
7262

73-
def processAlgorithm(self, parameters, context, feedback):
74-
source = self.parameterAsSource(parameters, self.INPUT, context)
75-
iterations = self.parameterAsInt(parameters, self.ITERATIONS, context)
76-
offset = self.parameterAsDouble(parameters, self.OFFSET, context)
77-
max_angle = self.parameterAsDouble(parameters, self.MAX_ANGLE, context)
78-
79-
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
80-
source.fields(), source.wkbType(), source.sourceCrs())
81-
82-
features = source.getFeatures()
83-
total = 100.0 / source.featureCount() if source.featureCount() else 0
84-
85-
for current, input_feature in enumerate(features):
86-
if feedback.isCanceled():
87-
break
88-
output_feature = input_feature
89-
if input_feature.geometry():
90-
output_geometry = input_feature.geometry().smooth(iterations, offset, -1, max_angle)
91-
if not output_geometry:
92-
raise QgsProcessingException(
93-
self.tr('Error smoothing geometry'))
63+
def outputName(self):
64+
return self.tr('Smoothed')
9465

95-
output_feature.setGeometry(output_geometry)
66+
def prepareAlgorithm(self, parameters, context, feedback):
67+
self.iterations = self.parameterAsInt(parameters, self.ITERATIONS, context)
68+
self.offset = self.parameterAsDouble(parameters, self.OFFSET, context)
69+
self.max_angle = self.parameterAsDouble(parameters, self.MAX_ANGLE, context)
70+
return True
9671

97-
sink.addFeature(output_feature, QgsFeatureSink.FastInsert)
98-
feedback.setProgress(int(current * total))
72+
def processFeature(self, feature, feedback):
73+
if feature.hasGeometry():
74+
output_geometry = feature.geometry().smooth(self.iterations, self.offset, -1, self.max_angle)
75+
if not output_geometry:
76+
raise QgsProcessingException(
77+
self.tr('Error smoothing geometry'))
9978

100-
return {self.OUTPUT: dest_id}
79+
feature.setGeometry(output_geometry)
80+
return feature

‎python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -481,44 +481,44 @@ tests:
481481
- algorithm: qgis:boundary
482482
name: Polygon boundary
483483
params:
484-
INPUT_LAYER:
484+
INPUT:
485485
name: polys.gml
486486
type: vector
487487
results:
488-
OUTPUT_LAYER:
488+
OUTPUT:
489489
name: expected/poly_boundary.gml
490490
type: vector
491491

492492
- algorithm: qgis:boundary
493493
name: Multipoly boundary
494494
params:
495-
INPUT_LAYER:
495+
INPUT:
496496
name: multipolys.gml
497497
type: vector
498498
results:
499-
OUTPUT_LAYER:
499+
OUTPUT:
500500
name: expected/multipoly_boundary.gml
501501
type: vector
502502

503503
- algorithm: qgis:boundary
504504
name: Line boundary
505505
params:
506-
INPUT_LAYER:
506+
INPUT:
507507
name: lines.gml
508508
type: vector
509509
results:
510-
OUTPUT_LAYER:
510+
OUTPUT:
511511
name: expected/lines_boundary.gml
512512
type: vector
513513

514514
- algorithm: qgis:boundary
515515
name: Multiline boundary
516516
params:
517-
INPUT_LAYER:
517+
INPUT:
518518
name: multilines.gml
519519
type: vector
520520
results:
521-
OUTPUT_LAYER:
521+
OUTPUT:
522522
name: expected/multiline_boundary.gml
523523
type: vector
524524

@@ -588,33 +588,33 @@ tests:
588588
- algorithm: qgis:pointonsurface
589589
name: Point on polygon surface
590590
params:
591-
INPUT_LAYER:
591+
INPUT:
592592
name: polys.gml
593593
type: vector
594594
results:
595-
OUTPUT_LAYER:
595+
OUTPUT:
596596
name: expected/point_on_poly.gml
597597
type: vector
598598

599599
- algorithm: qgis:pointonsurface
600600
name: Point on multipoint surface
601601
params:
602-
INPUT_LAYER:
602+
INPUT:
603603
name: multipoints.gml
604604
type: vector
605605
results:
606-
OUTPUT_LAYER:
606+
OUTPUT:
607607
name: expected/point_on_multipoint.gml
608608
type: vector
609609

610610
- algorithm: qgis:pointonsurface
611611
name: Point on line surface
612612
params:
613-
INPUT_LAYER:
613+
INPUT:
614614
name: lines.gml
615615
type: vector
616616
results:
617-
OUTPUT_LAYER:
617+
OUTPUT:
618618
name: expected/point_on_line.gml
619619
type: vector
620620

0 commit comments

Comments
 (0)
Please sign in to comment.