Skip to content
Permalink
Browse files

use combineField and handle exceptions better

  • Loading branch information
ghtmtt committed May 17, 2019
1 parent aa2aed9 commit 17000a4b36aef401b8c60e22fa99b0cb881d3678
Showing with 33 additions and 53 deletions.
  1. +1 −1 python/plugins/processing/algs/help/qgis.yaml
  2. +32 −52 python/plugins/processing/algs/qgis/Climb.py
@@ -56,7 +56,7 @@ qgis:checkvalidity: >
qgis:climbalongline: >
This algorithm calculates the total climb and descent along line geometries.

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.
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.

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.

@@ -38,6 +38,8 @@
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink,
QgsProcessingOutputNumber,
QgsProcessingException,
QgsProcessingUtils,
QgsWkbTypes,
QgsFields,
QgsField)
@@ -127,12 +129,13 @@ def processAlgorithm(self, parameters, context, feedback):
)

fcount = source.featureCount()
source_fields = source.fields()

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

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

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

# Skip fields with names that are equal to the generated ones
for field in source.fields():
if field.name() == self.CLIMBATTRIBUTE:
feedback.pushInfo(self.tr(
'{attr_name} attribute found and removed'.format(
attr_name=self.CLIMBATTRIBUTE)
)
)
climbindex = fieldnumber
elif field.name() == self.DESCENTATTRIBUTE:
feedback.pushInfo(self.tr(
'{attr_name} attribute found and removed'.format(
attr_name=self.DESCENTATTRIBUTE)
)
)
descentindex = fieldnumber
elif field.name() == self.MINELEVATTRIBUTE:
feedback.pushInfo(self.tr(
'{attr_name} attribute found and removed'.format(
attr_name=self.MINELEVATTRIBUTE)
)
)
minelevindex = fieldnumber
elif field.name() == self.MAXELEVATTRIBUTE:
feedback.pushInfo(self.tr(
'{attr_name} attribute found and removed'.format(
attr_name=self.MAXELEVATTRIBUTE)
)
)
maxelevindex = fieldnumber
else:
thefields.append(field)
fieldnumber = fieldnumber + 1

# Create new fields for climb and descent
thefields.append(QgsField(self.CLIMBATTRIBUTE, QVariant.Double))
thefields.append(QgsField(self.DESCENTATTRIBUTE, QVariant.Double))
thefields.append(QgsField(self.MINELEVATTRIBUTE, QVariant.Double))
thefields.append(QgsField(self.MAXELEVATTRIBUTE, QVariant.Double))

# combine all the vector fields
out_fields = QgsProcessingUtils.combineFields(source_fields, thefields)

layerwithz = source

(sink, dest_id) = self.parameterAsSink(parameters,
self.OUTPUT,
context, thefields,
context,
out_fields,
layerwithz.wkbType(),
source.sourceCrs())

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

no_z_nodes = []
no_geometry = []

for current, feature in enumerate(features):
if feedback.isCanceled():
@@ -208,6 +182,12 @@ def processAlgorithm(self, parameters, context, feedback):
# In case of multigeometries we need to do the parts
parts = feature.geometry().constParts()
partnumber = 0
if not feature.hasGeometry():
no_geometry.append(self.tr(
'Feature: {feature_id}'.format(
feature_id=feature.id())
)
)
for part in parts:
# Calculate the climb
first = True
@@ -244,20 +224,14 @@ def processAlgorithm(self, parameters, context, feedback):
partnumber += 1
# Set the attribute values
attrs = feature.attributes()
outattrs = []
attrindex = 0
for attr in attrs:
# Skip attributes from the input layer that had names
# that were equal to the generated ones
if not (attrindex == climbindex or
attrindex == descentindex or
attrindex == minelevindex or
attrindex == maxelevindex):
outattrs.append(attr)
attrindex = attrindex + 1
# feature.setAttributes(outattrs + [climb, descent])
feature.setAttributes(outattrs +
[climb, descent, minelev, maxelev])
# Append the attributes to the end of the existing ones
attrs.append(climb)
attrs.append(descent)
attrs.append(minelev)
attrs.append(maxelev)

# Set the final attribute list
feature.setAttributes(attrs)
# Add a feature to the sink
sink.addFeature(feature, QgsFeatureSink.FastInsert)
if minelevation > minelev:
@@ -269,7 +243,13 @@ def processAlgorithm(self, parameters, context, feedback):
feedback.setProgress(int(100 * current / fcount))

feedback.pushInfo(self.tr(
'The following points to not have Z values: {no_z_report}'.format(
'The following features do not have geometry: {no_geometry_report}'.format(
no_geometry_report=str(no_geometry))
)
)

feedback.pushInfo(self.tr(
'The following points do not have Z values: {no_z_report}'.format(
no_z_report=str(no_z_nodes))
)
)

0 comments on commit 17000a4

Please sign in to comment.
You can’t perform that action at this time.