Skip to content

Commit 17000a4

Browse files
committed
use combineField and handle exceptions better
1 parent aa2aed9 commit 17000a4

File tree

2 files changed

+33
-53
lines changed

2 files changed

+33
-53
lines changed

python/plugins/processing/algs/help/qgis.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ qgis:checkvalidity: >
5656
qgis:climbalongline: >
5757
This algorithm calculates the total climb and descent along line geometries.
5858

59-
It works only if the geometries have Z values. If it does not, and you have a DEM, you can use the Drape (set z-value from raster) algorithm to add Z values.
59+
Input layers must have Z values present. If Z values are not available, the "Drape" (set Z value from raster) algorithm may be used to add Z values from a DEM layer.
6060

6161
The output layer is a copy of the input layer with additional fields that contain the total climb, total descent, the minimum elevation and the maximum elevation for each line geometry. If the input layer contains fields with the same names as these added fields, they will be overwritten.
6262

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

Lines changed: 32 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
QgsProcessingParameterFeatureSource,
3939
QgsProcessingParameterFeatureSink,
4040
QgsProcessingOutputNumber,
41+
QgsProcessingException,
42+
QgsProcessingUtils,
4143
QgsWkbTypes,
4244
QgsFields,
4345
QgsField)
@@ -127,12 +129,13 @@ def processAlgorithm(self, parameters, context, feedback):
127129
)
128130

129131
fcount = source.featureCount()
132+
source_fields = source.fields()
130133

131134
hasZ = QgsWkbTypes.hasZ(source.wkbType())
132135

133136
if not hasZ:
134-
feedback.reportError(self.tr('The layer does not have Z values. If you have a DEM, use the Drape algorithm to extract Z values.'))
135-
return
137+
raise QgsProcessingException(self.tr('The layer does not have Z values. If you have a DEM, use the Drape algorithm to extract Z values.'))
138+
return {}
136139

137140
thefields = QgsFields()
138141
climbindex = -1
@@ -141,51 +144,21 @@ def processAlgorithm(self, parameters, context, feedback):
141144
maxelevindex = -1
142145
fieldnumber = 0
143146

144-
# Skip fields with names that are equal to the generated ones
145-
for field in source.fields():
146-
if field.name() == self.CLIMBATTRIBUTE:
147-
feedback.pushInfo(self.tr(
148-
'{attr_name} attribute found and removed'.format(
149-
attr_name=self.CLIMBATTRIBUTE)
150-
)
151-
)
152-
climbindex = fieldnumber
153-
elif field.name() == self.DESCENTATTRIBUTE:
154-
feedback.pushInfo(self.tr(
155-
'{attr_name} attribute found and removed'.format(
156-
attr_name=self.DESCENTATTRIBUTE)
157-
)
158-
)
159-
descentindex = fieldnumber
160-
elif field.name() == self.MINELEVATTRIBUTE:
161-
feedback.pushInfo(self.tr(
162-
'{attr_name} attribute found and removed'.format(
163-
attr_name=self.MINELEVATTRIBUTE)
164-
)
165-
)
166-
minelevindex = fieldnumber
167-
elif field.name() == self.MAXELEVATTRIBUTE:
168-
feedback.pushInfo(self.tr(
169-
'{attr_name} attribute found and removed'.format(
170-
attr_name=self.MAXELEVATTRIBUTE)
171-
)
172-
)
173-
maxelevindex = fieldnumber
174-
else:
175-
thefields.append(field)
176-
fieldnumber = fieldnumber + 1
177-
178147
# Create new fields for climb and descent
179148
thefields.append(QgsField(self.CLIMBATTRIBUTE, QVariant.Double))
180149
thefields.append(QgsField(self.DESCENTATTRIBUTE, QVariant.Double))
181150
thefields.append(QgsField(self.MINELEVATTRIBUTE, QVariant.Double))
182151
thefields.append(QgsField(self.MAXELEVATTRIBUTE, QVariant.Double))
183152

153+
# combine all the vector fields
154+
out_fields = QgsProcessingUtils.combineFields(source_fields, thefields)
155+
184156
layerwithz = source
185157

186158
(sink, dest_id) = self.parameterAsSink(parameters,
187159
self.OUTPUT,
188-
context, thefields,
160+
context,
161+
out_fields,
189162
layerwithz.wkbType(),
190163
source.sourceCrs())
191164

@@ -197,6 +170,7 @@ def processAlgorithm(self, parameters, context, feedback):
197170
maxelevation = float('-Infinity')
198171

199172
no_z_nodes = []
173+
no_geometry = []
200174

201175
for current, feature in enumerate(features):
202176
if feedback.isCanceled():
@@ -208,6 +182,12 @@ def processAlgorithm(self, parameters, context, feedback):
208182
# In case of multigeometries we need to do the parts
209183
parts = feature.geometry().constParts()
210184
partnumber = 0
185+
if not feature.hasGeometry():
186+
no_geometry.append(self.tr(
187+
'Feature: {feature_id}'.format(
188+
feature_id=feature.id())
189+
)
190+
)
211191
for part in parts:
212192
# Calculate the climb
213193
first = True
@@ -244,20 +224,14 @@ def processAlgorithm(self, parameters, context, feedback):
244224
partnumber += 1
245225
# Set the attribute values
246226
attrs = feature.attributes()
247-
outattrs = []
248-
attrindex = 0
249-
for attr in attrs:
250-
# Skip attributes from the input layer that had names
251-
# that were equal to the generated ones
252-
if not (attrindex == climbindex or
253-
attrindex == descentindex or
254-
attrindex == minelevindex or
255-
attrindex == maxelevindex):
256-
outattrs.append(attr)
257-
attrindex = attrindex + 1
258-
# feature.setAttributes(outattrs + [climb, descent])
259-
feature.setAttributes(outattrs +
260-
[climb, descent, minelev, maxelev])
227+
# Append the attributes to the end of the existing ones
228+
attrs.append(climb)
229+
attrs.append(descent)
230+
attrs.append(minelev)
231+
attrs.append(maxelev)
232+
233+
# Set the final attribute list
234+
feature.setAttributes(attrs)
261235
# Add a feature to the sink
262236
sink.addFeature(feature, QgsFeatureSink.FastInsert)
263237
if minelevation > minelev:
@@ -269,7 +243,13 @@ def processAlgorithm(self, parameters, context, feedback):
269243
feedback.setProgress(int(100 * current / fcount))
270244

271245
feedback.pushInfo(self.tr(
272-
'The following points to not have Z values: {no_z_report}'.format(
246+
'The following features do not have geometry: {no_geometry_report}'.format(
247+
no_geometry_report=str(no_geometry))
248+
)
249+
)
250+
251+
feedback.pushInfo(self.tr(
252+
'The following points do not have Z values: {no_z_report}'.format(
273253
no_z_report=str(no_z_nodes))
274254
)
275255
)

0 commit comments

Comments
 (0)