Here are three solutions. You can either
- Get a list, array or concatenated string of all x and y coordinates of each MultiPoint
- Get the x and y coordinate of the centroid of each MultiPoint
- Get the x and y coordinates of the first point of each MultiPoint
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.
#multiPointLayer = QgsProject.instance().mapLayersByName('Dissolved')[0] # get a layer
pr = multiPointLayer.dataProvider()
# Note the change of fieldtypes:
pr.addAttributes([
# Will store the concatenated string of all x and y coordinates of each MultiPoint:
QgsField("x_coords", QVariant.String),
QgsField("y_coords", QVariant.String),
# Will store the x and y coordinate of the centroid of each MultiPoint:
QgsField("x_coord_centroid", QVariant.Double),
QgsField("y_coord_centroid", QVariant.Double),
# Will store the x and y coordinates of the first point of each MultiPoint:
QgsField("x_coord_firstpoint", QVariant.Double),
QgsField("y_coord_firstpoint", QVariant.Double)
])
multiPointLayer.updateFields()
with edit(multiPointLayer):
for feature in multiPointLayer.getFeatures():
geom = feature.geometry() # get the geometry of the current feature
x_arr = [] # create an empty list
y_arr = [] # create an empty list
for part in geom.parts(): # loop through the parts of each multipoint feature
for p in part.vertices(): # now "loop through" each vertex of each part (actually a loop isnt really needed but easier to implement, since each part always has exact one vertex)
x_arr.append(p.x()) # get the x coordinate of that vertex (p.x()) and append it to the list
y_arr.append(p.y()) # get the y coordinate of that vertex (p.y()) and append it to the list
# Same as array_to_string(array_foreach(generate_series(0,num_points($geometry)-1),x_at(@element)),','):
feature['x_coords'] = ','.join(str(x) for x in x_arr) # turn the list of x coordinates into a comma spearated string. Therefore we need to iterate over the list and convert each double value to a string
feature['y_coords'] = ','.join(str(y) for y in y_arr) # turn the list of y coordinates into a comma spearated string. Therefore we need to iterate over the list and convert each double value to a string
# Same as x($geometry) and y($geometry):
feature['x_coord_centroid'] = geom.centroid().asPoint().x() # get the x coordinate of the multipoint features centroid
feature['y_coord_centroid'] = geom.centroid().asPoint().y() # get the y coordinate of the multipoint features centroid
# Same as $x and $y:
feature['x_coord_firstpoint'] = x_arr[0] # get the x coordinate of the first point of each MultiPoint
feature['y_coord_firstpoint'] = y_arr[0] # get the y coordinate of the first point of each MultiPoint
multiPointLayer.updateFeature(feature)
QgsProject.instance().addMapLayer(multiPointLayer)
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)
or y($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()
or y_at()
, e.g. x_at(2)
to return the x coordinate of the 3rd point of a MultiPoint.
You can also use x_at()
and y_at()
to return an array of all x and y coordinates of a MultiPoint by combining it with num_points()
, generate_series()
and array_foreach()
, e.g. by using array_foreach(generate_series(0,num_points($geometry)-1),x_at(@element))
to get an array of all x coordinates of each MultiPoint or array_foreach(generate_series(0,num_points($geometry)-1),y_at(@element))
to get an array of all y coordinates of each MultiPoint.