2

I have a problem with my first QGIS 3 plugin. I want to calculate lenght each segment in my polyline and next creating buffer equal 1/2 length of line.

The first 13 lines code have to do calculating the length of the selected layer and it works. But I have a problem with the buffer. I tried many ways that I found on the internet and it still doesn't work. Now I have no errors, but the plugin does not return anything.

Can you solve this problem?

if result:
    for layer in QgsProject.instance().mapLayers().values():
        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)
        result = processing.run("native:buffer",
            {'INPUT': layer, 
            'DISTANCE' : 100,
            'SEGMENTS' : 10,
            'DISSOLVE': True,
            'END_CAP_STYLE' : 1,
            'JOIN_STYLE': 0,
            'MITER_LIMIT': 10,
            'OUTPUT': 'memory:buffer'})
        layer.commitChanges()
        layer.updateFields()

1 Answer 1

2

After erasing some repeated lines in your code and changing 'run' processing method by 'runAndLoadResults' (also modifying 'DISTANCE' : 100 with 'DISTANCE' : leng/2), I tried your code out and it worked.

for layer in QgsProject.instance().mapLayers().values():
    features = layer.getFeatures()
    coluna = QgsField('Length', QVariant.Double)
    res = layer.dataProvider().addAttributes([coluna])
    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)
    result = processing.runAndLoadResults("native:buffer",
                                          {'INPUT': layer, 
                                           'DISTANCE' : leng/2,
                                           'SEGMENTS' : 10,
                                           'DISSOLVE': True,
                                           'END_CAP_STYLE' : 1,
                                           'JOIN_STYLE': 0,
                                           'MITER_LIMIT': 10,
                                           'OUTPUT': 'memory:buffer'})
    layer.commitChanges()

Result can be observed in following image with a only one feature line layer:

enter image description here

However, in a plugin you need to trigger an action in some button (e.g. OK button). So, I created a test plugin capable to recreate this behavior with 'creating_buffer' function. For working in a plugin, these were the modifications in following code snippet:

.
.
.
from PyQt5.QtCore import QSettings, QTranslator, qVersion, QCoreApplication, QVariant
.
.
.
from qgis.core import QgsProject, QgsField
import processing
.
.
.
    def add_action(
.
.
.
        okBtn = self.dlg.okButton
        okBtn.clicked.connect(self.creating_buffer)

        return action
.
.
.
    def creating_buffer(self):

        for layer in QgsProject.instance().mapLayers().values():
            features = layer.getFeatures()
            coluna = QgsField('Length', QVariant.Double)
            res = layer.dataProvider().addAttributes([coluna])
            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)
            result = processing.runAndLoadResults("native:buffer",
                                                  {'INPUT': layer, 
                                                   'DISTANCE' : leng/2,
                                                   'SEGMENTS' : 10,
                                                   'DISSOLVE': True,
                                                   'END_CAP_STYLE' : 1,
                                                   'JOIN_STYLE': 0,
                                                   'MITER_LIMIT': 10,
                                                   'OUTPUT': 'memory:buffer'})
            layer.commitChanges()

    def run(self):
        """Run method that performs all the real work"""
        # show the dialog
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()
        # See if OK was pressed
        if result:
            # Do something useful here - delete the line containing pass and
            # substitute with your code.
            pass

After clicking in OK button plugin, result was identical to above image.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.