PyQGIS – Add LineString from Points

pointpolyline-creationpyqgisqgis-3

I want to create a LineString using points/coordinates in QGIS 3.26 using Python/PyQGIS.

Here is my code :

points = []

x = QgsPointXY(783648,1397243)
points.append(x)

y = QgsPointXY(788883,1396853)
points.append(y)

layer = iface.activeLayer()

fields = layer.dataProvider().fields()

feature = QgsFeature()
feature.setGeometry(QgsGeometry.fromPolylineXY(points))
feature.setFields(fields)
feature.setAttribute(0,12)

layer.addFeature(feature)

QgsProject.instance().addMapLayer(layer)

I am facing no error but I can't see any LineString in QGIS from the given points.

Best Answer

The fundamental reason why your code is not working is that you are trying to add a feature to your layer without making it editable. If you want to immediately commit the changes to the layer's underlying data store, you should work with layer.dataProvider() instead. Also, you should remove the last line from your code snippet, since the active layer is already added to the project, and replace it with a few lines to reflect the changes to the layer.

points = []
x = QgsPointXY(783648,1397243)
points.append(x)
y = QgsPointXY(788883,1396853)
points.append(y)

layer = iface.activeLayer()

if layer.dataProvider().capabilities() & QgsVectorDataProvider.AddFeatures:
    feature = QgsFeature(layer.fields())
    feature.setGeometry(QgsGeometry.fromPolylineXY(points))
    feature.setAttributes([0, 12])
    layer.dataProvider().addFeatures([feature])
    layer.updateExtents()
    layer.triggerRepaint()
    iface.mapCanvas().refresh()
    # Optional...
    iface.zoomToActiveLayer()

On the other hand, if you want the opportunity to undo/ redo then save the edits via the GUI, you can just call layer.startEditing() before adding the feature to the layer:

points = []
x = QgsPointXY(783648,1397243)
points.append(x)
y = QgsPointXY(788883,1396853)
points.append(y)

layer = iface.activeLayer()

if layer.type() == QgsMapLayerType.VectorLayer:
    feature = QgsFeature(layer.fields())
    feature.setGeometry(QgsGeometry.fromPolylineXY(points))
    feature.setAttributes([0, 12])

    if not layer.isEditable():
        layer.startEditing()
        
    layer.addFeature(feature)
    layer.updateExtents()
    layer.triggerRepaint()
    iface.mapCanvas().refresh()
    # Optional...
    iface.zoomToActiveLayer()

I strongly recommend reading the PyQGIS Cookbook section on Modifying Vector Layers.