2

I wrote a processing scrip for QGIS 2.18 to create a multi-distance buffer rings using the haversine formula. Unfortunately, it no longer works after I updated to QGIS 3.4.5. I've tried updating the script wherever I can but I can't figure out how to fix the part of the code where it writes the buffers to a shapefile.

Here's my code:

from math import *
from qgis.core import *
from qgis.utils import iface
from PyQt5.QtCore import *
from PyQt5.QtGui import *

layer = iface.activeLayer()
for feat in layer.selectedFeatures():
    geom = feat.geometry()

start_x = geom.asPoint().x()
start_y = geom.asPoint().y()
sides = 64
radius = 6378137.0  # meters

# create layer
vl = QgsVectorLayer("Polygon", "Distance Buffers", "memory")
pr = vl.dataProvider()

# changes are only possible when editing the layer
vl.startEditing()

# add fields
pr.addAttributes([QgsField("Distance", QVariant.Int), QgsField("Label", QVariant.String)])

distance = [250, 500, 1000, 2000, 3000, 4000, 5000, 10000, 15000, 20000, 25000, 30000, 40000, 50000]
for i in range(len(distance)):
    points = []
    dist = distance[i]
    degrees = 0
    while degrees <= 360:
        degrees = degrees + 360 / sides

        start_lon = start_x * pi / 180
        start_lat = start_y * pi / 180
        bearing = degrees * pi / 180

        end_lat = asin((sin(start_lat) * cos(dist / radius)) + (cos(start_lat) * sin(dist / radius) * cos(bearing)))
        end_lon = start_lon + atan2(sin(bearing) * sin(dist / radius) * cos(start_lat),
                                    cos(dist / radius) - (sin(start_lat) * sin(end_lat)))

        points.append(QgsPointXY(end_lon * 180 / pi, end_lat * 180 / pi))

        fet_name = str(distance[i])
        if distance[i] < 1000:
            label = str(distance[i]) + "m"
        else:
            label = str(distance[i]/1000) + "km"

    # add a feature
    fet = QgsFeature()
    geometry = QgsGeometry.fromPolygonXY([points])
    fet.setGeometry(geometry)
    fet.setAttributes([fet_name,label])
    pr.addFeatures([fet])

# commit to stop editing the layer
vl.commitChanges()

# update layer's extent when new features have been added
# because change of extent in provider is not propagated to the layer
vl.updateExtents()

myDir = QgsProject.instance().readPath("./")
file_name = 'Distance Buffers' + '.shp'
ShapefileDir = myDir + "/Shapefiles/" + file_name

_writer = QgsVectorFileWriter.writeAsVectorFormat(vl, ShapefileDir, "utf-8", None, "ESRI Shapefile")

At the last line of the code I get this error:

Traceback (most recent call last): File "C:/PROGRA~1/QGIS3~1.4/apps/qgis-ltr/./python/plugins\processing\script\ScriptEditorDialog.py", line 227, in runAlgorithm exec(self.editor.text(), d) File "", line 68, in TypeError: QgsVectorFileWriter.writeAsVectorFormat(): arguments did not match any overloaded call: overload 1: argument 4 has unexpected type 'NoneType' overload 2: argument 4 has unexpected type 'NoneType' overload 3: argument 3 has unexpected type 'str'

Based on the QGIS 3.0 documentation, I think writeAsVectorFormat now takes the following arguments: writeAsVectorFormat(layer: QgsVectorLayer, fileName: str, options: QgsVectorFileWriter.SaveVectorOptions, newFilename: str = ‘’) but I can't figure out how to set the SaveVectorOptions.

Can someone show me how this is done with this script, or with any other working examples?

  • Related to your comment "# changes are only possible when editing the layer", this is not true. You are using the dataProvider, so you don't need to use startEditing and commitChanges. – etrimaille Feb 26 at 13:28
1

As it happens, I have just finished updating the documentation on vector layers. The big change is that you can't pass in None as the CRS any longer, so either use an explicit one or leave it out altogether.

You now need something like:

writer = QgsVectorFileWriter("my_shapes", "UTF-8", driverName="ESRI Shapefile")

The latest docs are available which give the full list of parameters.

Your Answer

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

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