I have two input vector layers (one point and one line layer). I loop through every feature in the input-line-layer and calculate some things (with help of the point layer).
What I am trying to do now is to generate an output line layer for which I want to have the following six fields:
1. QgsField('id', QVariant.String)
2. QgsField('vto', QVariant.Double)
3. QgsField('vfrom', QVariant.Double)
4. QgsField('priority', QVariant.Int)
5. QgsField('node1', QVariant.String)
6. QgsField('node2', QVariant.String)
Based on those defined fields, I want to add some features to the output layer, but I do not know how to define the fields (of the output layer) and how to add features to the output layer in QGIS3.
Note: I am using the processing algorithm template for QGIS3 from underdark : see https://anitagraser.com/2018/03/25/processing-script-template-for-qgis3/
Based on her template, she writes this:
def processAlgorithm(self, parameters, context, feedback):
inEdges = self.parameterAsSource(parameters,
self.INPUT_VECTOR_LAYER_EDGES, context)
inNodes = self.parameterAsSource(parameters,
self.INPUT_VECTOR_LAYER_NODES, context)
(sink, dest_id) = self.parameterAsSink(parameters,
self.OUTPUT_VECTOR_LAYER_MERGED, context,
inEdges.fields(), inEdges.wkbType(), inEdges.sourceCrs())
In the line which starts with (sink, dest_id), underdark has declared an outputlayer which takes the same fields as the inputlayer. But how can I declare an outputlayer with my customized fields (which are not ident with the fields from the inputlayer)?
EDIT: As suggested from root676, I altered my code a little bit:
# 1. First of all, I defined a variable which holds the definition of my fields
outFields = QgsFields()
# 2. Then, I defined the fields
outFields.append(QgsField('id', QVariant.String))
outFields.append(QgsField('vto', QVariant.Double))
outFields.append(QgsField('vfrom', QVariant.Double))
outFields.append(QgsField('priority', QVariant.Int))
outFields.append(QgsField('node1', QVariant.String))
outFields.append(QgsField('node2', QVariant.String))
# 3. The I created the output sink with the previously defined fields
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_VECTOR_LAYER_MERGED, context,
outFields, inEdges.wkbType(), inEdges.sourceCrs())
# 4. I created a new Feature which will be added to the outputlayer after I set its attribute values.
newEdge = QgsFeature()
# 5. The ERROR happens when I try to set an attribute value like this:
newEdge['id'] = edgeIdTrimmed
The error I am getting is as followed:
Traceback (most recent call last): File "", line 143, in processAlgorithm KeyError: 'id'
EDIT: I solved the problem by initialising the new QgsFeature with my defined Fields variable. See below:
newEdge = QgsFeature(outFields)
Answer
Here is an example of a possible base-layout of your processAlgorithm()
method (just a quick wrap-up of the basic field related code you were asking about - has to be embedded into your context):
def processAlgorithm(self, parameters, context, feedback):
#get your input layers
inEdges = self.parameterAsSource(parameters,
self.INPUT_VECTOR_LAYER_EDGES, context)
inNodes = self.parameterAsSource(parameters,
self.INPUT_VECTOR_LAYER_NODES, context)
#define your fields
your_fields = QgsFields()
#append fields
your_fields.append(QgsField('id', QVariant.String))
your_fields.append(QgsField('vto', QVariant.Double))
your_fields.append(QgsField('vfrom', QVariant.Double))
your_fields.append(QgsField('priority', QVariant.Int))
your_fields.append(QgsField('node1', QVariant.String))
your_fields.append(QgsField('node2', QVariant.String))
#create the output sink
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_VECTOR_LAYER_MERGED, context, your_fields, inEdges.wkbType(), inEdges.sourceCrs())
#do some calculations with inEdges and inNodes
#somewhere in your while/for loops create a new feature object
feat = QgsFeature()
#set your fields of the feature
feat.setFields(your_fields)
#set the attribute values like this
feat['vto'] = #some_vto_value
#set geometry of feature
feat.setGeometry(geom)
#add feature to sink
sink.addFeature(feat, QgsFeatureSink.FastInsert)
#return feature sink
results = {}
results[self.OUTPUT_VECTOR_LAYER_MERGED] = dest_id
return results
The following steps are necessary to output a sink with custom fields (see corresponding code comments):
- get your input layers
- define your fields as
QgsFields
object - append the corresponding
QgsField
objects to theQgsFields
- create the output
QgsFeatureSink
using the fields from the variableyour_fields
- do your calculations with the
inEdges
andinNodes
layers - create features using
your_fields
, set their attributes and geometry in the calculation process - add the features to the
sink
- return the
sink
as new output layer.
No comments:
Post a Comment