I have a MultiPoint layer in QGIS 3.18 that I wanted to add x and y coordinates to in its attribute table. Normally, I can just use field calculator and calculate the new field to be $x
or $y
.
How do I achieve the same thing in PyQGIS?
My current workflow:
pr = multiPointLayer.dataProvider()
pr.addAttributes([QgsField("x_coord", QVariant.Double), QgsField("y_coord", QVariant.Double)])
multiPointLayer.updateFields()
with edit(multiPointLayer):
for feature in multiPointLayer.getFeatures():
feature['x_coord'] = ???
feature['y_coord'] = ???
multiPointLayer.updateFeature(feature)
QgsProject.instance().addMapLayer(multiPointLayer)
PyQGIS is unwilling to handle MultiPoint layers, seems like — and when I use the Add X/Y coordinates algorithm provided by QGIS it wanted me to use single points, but I'd much rather keep it a MultiPoint layer since they can be relatively large.
Turns out, all I had to do is to convert my multipoint layer to singlepoint. When Clipping a point layer, the output point layer gets automatically converted to a multipoint one, which caused the issue. The commenting about a multipoint layer made me aware of the properties of the multipoint type.
Best Answer
Here are three solutions. You can either
If not using the centroid, you need to loop through the vertices of each MultiPoint-Feature just as you would do it with a MultiLineString or a MultiPolygon.
A side note on your expressions, not PyQGIS related:
If you type
$x
or$y
in fieldcaluclator on a MultiPoint-layer, you will always get the coordinate of the "first" point. This is mentioned in the function description.If you use
x($geometry)
ory($geometry)
, you will get the centroid for each MultiPoint.If you want another coordinate than the one from the first point, you can use
x_at()
ory_at()
, e.g.x_at(2)
to return the x coordinate of the 3rd point of a MultiPoint.You can also use
x_at()
andy_at()
to return an array of all x and y coordinates of a MultiPoint by combining it withnum_points()
,generate_series()
andarray_foreach()
, e.g. by usingarray_foreach(generate_series(0,num_points($geometry)-1),x_at(@element))
to get an array of all x coordinates of each MultiPoint orarray_foreach(generate_series(0,num_points($geometry)-1),y_at(@element))
to get an array of all y coordinates of each MultiPoint.