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?
Best Answer
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:
The latest docs are available which give the full list of parameters.