3

Several similar questions have already been made, but none of the is helping me.

I have a layer of polygons and I want to known the length of each line of each polygon. And based on the length I want to create another layer. So I convert polygons > line and apply the explode lines tool. But then when I try to get the length, this is the error: AttributeError: QgsVectorLayer object has no attribute geometry.

My code is this:

def run(self):
   # show the dialog
    self.dlg.show()
    self.dlg.layerCombo.clear()
    layers = QgsMapLayerRegistry.instance().mapLayers().values()

    for layer in layers:
        if layer.type() == QgsMapLayer.VectorLayer:
            self.dlg.layerCombo.addItem( layer.name(), layer )
    result = self.dlg.exec_()
    # See if OK was pressed
    if result == 1:
        index = self.dlg.layerCombo.currentIndex()
        layer = self.dlg.layerCombo.itemData(index)
        #polygons to lines
        processing.runalg ('saga:convertpolygonstolines',layer,layer_line)

I know I need to use somenthing like this to have a new field with length values:

for f in features:
        geom = f.geometry()
        leng = geom.length()
        res = layer.dataProvider().addAttributes([QgsField("Length", QVariant.Int)])
        layer.updateFields()
        fieldIndex = layer.dataProvider().fieldNameIndex( "Length" )

I know that my problem is using QgsMapLayer.VectorLayer...But I don't know whatelse to use. I already read PyQGIS Developer Cookbook, the answer to this question (Calculate length of selected features in PyQGIS), this question (Adding new field with expression in pyqgis) ...

What should I use instead of QgsVectorLayer?

Ok. I made the changes suggested by Michael. My code is now like this:

            res = layer.dataProvider().addAttributes([QgsField("Length", QVariant.Int)])
            layer_output3.updateFields()
            fieldIndex = layer.dataProvider().fieldNameIndex( "Length" )
            features = layer.getFeatures()
            layer.startEditing()
            for f in features:
                geom = f.geometry()
                leng = geom.length()
                layer.changeAttributeValue(f.id())
                layer.commitChanges()

I am missing something..

So I corrected the itens mentioned by Michael and David. The part where the new field is add and the length is calculated looks like this:

            features = layer.getFeatures()
            coluna = QgsField('Length', QVariant.Double)
            res = layer.dataProvider().addAttributes([coluna])
            leng = layer.dataProvider().fieldNameIndex
            layer.updateFields()
            fieldIndex = layer.dataProvider().fieldNameIndex( "Length" )
            layer.startEditing()
            for f in features:
                geom = f.geometry()
                leng = geom.length()
                layer.changeAttributeValue(f.id(),fieldIndex, leng)
            layer.commitChanges()
            layer.updateFields()
  • 1
    You should use the last three lines in the for f in features: loop before the loop or you will get an error on the 2nd iteration as the field already exists. Update your new field attributes like in the accepted answer gis.stackexchange.com/questions/102119/… – Michael Stimson Jun 13 at 0:15
  • Can you please update your code in your question, I can't see getitem in there anywhere. – Michael Stimson Jun 13 at 1:08
  • Yeah, that was my mistake. Another plugin I am using...sorry – monica Jun 13 at 1:23
  • 1
    layer.changeAttributeValue(f.id()) should be layer.changeAttributeValue(f.id(),fieldIndex , leng) to update the newly added field by its index to the value of the length. As it stands you're changing no field to no value with your chageAttributeValue statement as the parameters are missing. – Michael Stimson Jun 13 at 1:28
  • 1
    You have to move layer.commitChanges() outside of the for loop (commit changes after all features are updated). Commit ends edit session, therefore changes are applied only to the first feature in your code. You should spot messages about trying to edit layer outside of edit session somewhere in the log. – DavidP Jun 14 at 11:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.