Skip to content

Commit 9763b60

Browse files
authored
Merge pull request #4936 from nyalldawson/algs
Restore more processing algs
2 parents fbff452 + e829092 commit 9763b60

19 files changed

+621
-536
lines changed

doc/api_break.dox

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,7 @@ empty geometry collection)
12421242
- avoidIntersections() got an extra argument: list of layers to include in the operation (previously read from active QgsProject)
12431243
- isGeosEmpty() was removed. Use isEmpty() instead.
12441244
- reshapeGeometry() expects QgsLineString as a parameter instead of a list of 2D points (so that it can support 3D geometries)
1245+
- vertexAt() now returns a QgsPoint (previously QgsPointV2) instead of a QgsPointXY (previously QgsPoint)
12451246

12461247

12471248
QgsGeometryAnalyzer {#qgis_api_break_3_0_QgsGeometryAnalyzer}

python/core/geometry/qgsgeometry.sip

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,12 +326,12 @@ Returns true if WKB of the geometry is of WKBMulti* type
326326
:rtype: bool
327327
%End
328328

329-
QgsPointXY vertexAt( int atVertex ) const;
329+
QgsPoint vertexAt( int atVertex ) const;
330330
%Docstring
331331
Returns coordinates of a vertex.
332332
\param atVertex index of the vertex
333-
:return: Coordinates of the vertex or QgsPointXY(0,0) on error
334-
:rtype: QgsPointXY
333+
:return: Coordinates of the vertex or QgsPoint(0,0) on error
334+
:rtype: QgsPoint
335335
%End
336336

337337
double sqrDistToVertexAt( QgsPointXY &point /In/, int atVertex ) const;

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

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,35 @@
2525

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

28-
from qgis.core import QgsFeature, QgsGeometry, QgsProcessingUtils
28+
from qgis.core import (QgsFeature,
29+
QgsGeometry,
30+
QgsFeatureRequest,
31+
QgsFeatureSink)
2932

3033

31-
def buffering(feedback, context, writer, distance, field, useField, layer, dissolve, segments, endCapStyle=1,
34+
def buffering(feedback, context, sink, distance, field, useField, source, dissolve, segments, endCapStyle=1,
3235
joinStyle=1, mitreLimit=2):
3336

3437
if useField:
35-
field = layer.fields().lookupField(field)
38+
field = source.fields().lookupField(field)
3639

3740
outFeat = QgsFeature()
3841

3942
current = 0
40-
features = QgsProcessingUtils.getFeatures(layer, context)
41-
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
43+
total = 100.0 / source.featureCount() if source.featureCount() else 0
4244

4345
# With dissolve
4446
if dissolve:
47+
attributes_to_fetch = []
48+
if useField:
49+
attributes_to_fetch.append(field)
50+
51+
features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(attributes_to_fetch))
4552
buffered_geometries = []
4653
for inFeat in features:
54+
if feedback.isCanceled():
55+
break
56+
4757
attrs = inFeat.attributes()
4858
if useField:
4959
value = attrs[field]
@@ -60,10 +70,15 @@ def buffering(feedback, context, writer, distance, field, useField, layer, disso
6070
final_geometry = QgsGeometry.unaryUnion(buffered_geometries)
6171
outFeat.setGeometry(final_geometry)
6272
outFeat.setAttributes(attrs)
63-
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
73+
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
6474
else:
75+
76+
features = source.getFeatures()
77+
6578
# Without dissolve
6679
for inFeat in features:
80+
if feedback.isCanceled():
81+
break
6782
attrs = inFeat.attributes()
6883
if useField:
6984
value = attrs[field]
@@ -74,8 +89,6 @@ def buffering(feedback, context, writer, distance, field, useField, layer, disso
7489
outGeom = inGeom.buffer(float(value), segments, endCapStyle, joinStyle, mitreLimit)
7590
outFeat.setGeometry(outGeom)
7691
outFeat.setAttributes(attrs)
77-
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
92+
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
7893
current += 1
7994
feedback.setProgress(int(current * total))
80-
81-
del writer

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

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@
3636
QgsFeatureSink,
3737
QgsGeometry,
3838
QgsWkbTypes,
39-
QgsProcessingUtils,
39+
QgsFeatureRequest,
4040
QgsFields,
41-
NULL)
41+
NULL,
42+
QgsProcessingParameterFeatureSource,
43+
QgsProcessingParameterField,
44+
QgsProcessingParameterFeatureSink,
45+
QgsProcessing,
46+
QgsProcessingException)
4247

4348
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
44-
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
45-
from processing.core.parameters import ParameterVector
46-
from processing.core.parameters import ParameterTableField
47-
from processing.core.parameters import ParameterSelection
48-
from processing.core.outputs import OutputVector
4949
from processing.tools import dataobjects, vector
5050

5151
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
@@ -56,7 +56,6 @@ class ConvexHull(QgisAlgorithm):
5656
INPUT = 'INPUT'
5757
OUTPUT = 'OUTPUT'
5858
FIELD = 'FIELD'
59-
METHOD = 'METHOD'
6059

6160
def icon(self):
6261
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'convex_hull.png'))
@@ -68,17 +67,12 @@ def __init__(self):
6867
super().__init__()
6968

7069
def initAlgorithm(self, config=None):
71-
self.methods = [self.tr('Create single minimum convex hull'),
72-
self.tr('Create convex hulls based on field')]
73-
74-
self.addParameter(ParameterVector(self.INPUT,
75-
self.tr('Input layer')))
76-
self.addParameter(ParameterTableField(self.FIELD,
77-
self.tr('Field (optional, only used if creating convex hulls by classes)'),
78-
self.INPUT, optional=True))
79-
self.addParameter(ParameterSelection(self.METHOD,
80-
self.tr('Method'), self.methods))
81-
self.addOutput(OutputVector(self.OUTPUT, self.tr('Convex hull'), datatype=[dataobjects.TYPE_VECTOR_POLYGON]))
70+
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
71+
self.tr('Input layer')))
72+
self.addParameter(QgsProcessingParameterField(self.FIELD,
73+
self.tr('Field (optional, set if creating convex hulls by classes)'),
74+
parentLayerParameterName=self.INPUT, optional=True))
75+
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Convex hull'), QgsProcessing.TypeVectorPolygon))
8276

8377
def name(self):
8478
return 'convexhull'
@@ -87,14 +81,15 @@ def displayName(self):
8781
return self.tr('Convex hull')
8882

8983
def processAlgorithm(self, parameters, context, feedback):
90-
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
91-
useField = self.getParameterValue(self.METHOD) == 1
92-
fieldName = self.getParameterValue(self.FIELD)
84+
source = self.parameterAsSource(parameters, self.INPUT, context)
85+
fieldName = self.parameterAsString(parameters, self.FIELD, context)
86+
useField = bool(fieldName)
9387

88+
field_index = None
9489
f = QgsField('value', QVariant.String, '', 255)
9590
if useField:
96-
index = layer.fields().lookupField(fieldName)
97-
fType = layer.fields()[index].type()
91+
field_index = source.fields().lookupField(fieldName)
92+
fType = source.fields()[field_index].type()
9893
if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]:
9994
f.setType(fType)
10095
f.setLength(20)
@@ -112,25 +107,30 @@ def processAlgorithm(self, parameters, context, feedback):
112107
fields.append(QgsField('area', QVariant.Double, '', 20, 6))
113108
fields.append(QgsField('perim', QVariant.Double, '', 20, 6))
114109

115-
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Polygon, layer.crs(), context)
110+
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
111+
fields, QgsWkbTypes.Polygon, source.sourceCrs())
116112

117113
outFeat = QgsFeature()
118-
inGeom = QgsGeometry()
119114
outGeom = QgsGeometry()
120115

121116
fid = 0
122117
val = None
123-
features = QgsProcessingUtils.getFeatures(layer, context)
124118
if useField:
125-
unique = layer.uniqueValues(index)
119+
unique = source.uniqueValues(field_index)
126120
current = 0
127-
total = 100.0 / (layer.featureCount() * len(unique)) if layer.featureCount() else 1
121+
total = 100.0 / (source.featureCount() * len(unique)) if source.featureCount() else 1
128122
for i in unique:
123+
if feedback.isCanceled():
124+
break
125+
129126
first = True
130127
hull = []
131-
features = QgsProcessingUtils.getFeatures(layer, context)
128+
features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([field_index]))
132129
for f in features:
133-
idVar = f[fieldName]
130+
if feedback.isCanceled():
131+
break
132+
133+
idVar = f.attributes()[field_index]
134134
if str(idVar).strip() == str(i).strip():
135135
if first:
136136
val = idVar
@@ -154,16 +154,19 @@ def processAlgorithm(self, parameters, context, feedback):
154154
perim = NULL
155155
outFeat.setGeometry(outGeom)
156156
outFeat.setAttributes([fid, val, area, perim])
157-
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
157+
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
158158
except:
159-
raise GeoAlgorithmExecutionException(
159+
raise QgsProcessingException(
160160
self.tr('Exception while computing convex hull'))
161161
fid += 1
162162
else:
163163
hull = []
164-
total = 100.0 / layer.featureCount() if layer.featureCount() else 1
165-
features = QgsProcessingUtils.getFeatures(layer, context)
164+
total = 100.0 / source.featureCount() if source.featureCount() else 1
165+
features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]))
166166
for current, f in enumerate(features):
167+
if feedback.isCanceled():
168+
break
169+
167170
inGeom = f.geometry()
168171
points = vector.extractPoints(inGeom)
169172
hull.extend(points)
@@ -180,9 +183,9 @@ def processAlgorithm(self, parameters, context, feedback):
180183
perim = NULL
181184
outFeat.setGeometry(outGeom)
182185
outFeat.setAttributes([0, 'all', area, perim])
183-
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
186+
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
184187
except:
185-
raise GeoAlgorithmExecutionException(
188+
raise QgsProcessingException(
186189
self.tr('Exception while computing convex hull'))
187190

188-
del writer
191+
return {self.OUTPUT: dest_id}

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

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,10 @@
2626
__revision__ = '$Format:%H$'
2727

2828
from qgis.core import (QgsFeatureRequest,
29-
QgsApplication,
3029
QgsFeatureSink,
31-
QgsProcessingUtils)
30+
QgsProcessingParameterFeatureSource,
31+
QgsProcessingParameterFeatureSink)
3232
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
33-
from processing.core.parameters import ParameterVector
34-
from processing.core.outputs import OutputVector
3533

3634

3735
class DeleteDuplicateGeometries(QgisAlgorithm):
@@ -46,9 +44,9 @@ def __init__(self):
4644
super().__init__()
4745

4846
def initAlgorithm(self, config=None):
49-
self.addParameter(ParameterVector(self.INPUT,
50-
self.tr('Input layer')))
51-
self.addOutput(OutputVector(self.OUTPUT, self.tr('Cleaned')))
47+
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
48+
self.tr('Input layer')))
49+
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Cleaned')))
5250

5351
def name(self):
5452
return 'deleteduplicategeometries'
@@ -57,23 +55,26 @@ def displayName(self):
5755
return self.tr('Delete duplicate geometries')
5856

5957
def processAlgorithm(self, parameters, context, feedback):
60-
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
58+
source = self.parameterAsSource(parameters, self.INPUT, context)
59+
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
60+
source.fields(), source.wkbType(), source.sourceCrs())
6161

62-
fields = layer.fields()
63-
64-
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, layer.wkbType(), layer.crs(), context)
65-
66-
features = QgsProcessingUtils.getFeatures(layer, context)
67-
68-
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
62+
features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]))
63+
total = 100.0 / source.featureCount() if source.featureCount() else 0
6964
geoms = dict()
7065
for current, f in enumerate(features):
66+
if feedback.isCanceled():
67+
break
68+
7169
geoms[f.id()] = f.geometry()
7270
feedback.setProgress(int(current * total))
7371

7472
cleaned = dict(geoms)
7573

7674
for i, g in list(geoms.items()):
75+
if feedback.isCanceled():
76+
break
77+
7778
for j in list(cleaned.keys()):
7879
if i == j or i not in cleaned:
7980
continue
@@ -82,8 +83,11 @@ def processAlgorithm(self, parameters, context, feedback):
8283

8384
total = 100.0 / len(cleaned) if cleaned else 1
8485
request = QgsFeatureRequest().setFilterFids(list(cleaned.keys()))
85-
for current, f in enumerate(layer.getFeatures(request)):
86-
writer.addFeature(f, QgsFeatureSink.FastInsert)
86+
for current, f in enumerate(source.getFeatures(request)):
87+
if feedback.isCanceled():
88+
break
89+
90+
sink.addFeature(f, QgsFeatureSink.FastInsert)
8791
feedback.setProgress(int(current * total))
8892

89-
del writer
93+
return {self.OUTPUT: dest_id}

0 commit comments

Comments
 (0)