I am wondering if there is a way to display coordinates for each vertex of a polygon by only using expressions, without creating a new layer. So this question is basically inspired by Displaying vertex coordinates of a polygon on a map in QGIS and enhancing it.

I thought about creating an array containing all vertices as geometry. So I have created this expression:

array_foreach( -- Go throuth every element of the following array
    string_to_array(geom_to_wkt(nodes_to_points($geometry)),','), -- Create the array of WKT information splitted by comma [ 'MultiPoint ((0.2974026 51.8987013)', '(0.00909091 51.50… ]
        make_point( -- Create a point geometry for every array content
                length(regexp_substr( -- Only create X coordinate if
                    regexp_substr(@element,'\\d.*\\d.[0-9]'),'([^ ]+)'))>0, -- everything between the Brackets of 'MultiPoint ((0.2974026 51.8987013)' before the whitespace '0.2974026' is not empty like ''
                    to_real(regexp_substr(regexp_substr(@element,'\\d.*\\d.[0-9]'),'([^ ]+)')), -- Extract the X coordinate of 'MultiPoint ((0.2974026 51.8987013)' --> 0.2974026
                    NULL -- If invalid coordinate use NULL, maybe replace with 0
                length(regexp_substr( -- Only create Y coordinate if
                    regexp_substr(@element,'\\d.*\\d.[0-9]'),'(?<=\\s).*'))>0, --  everything between the Brackets of 'MultiPoint ((0.2974026 51.8987013)' after the whitespace '51.8987013' is not empty like ''
                    to_real(regexp_substr(regexp_substr(@element,'\\d.*\\d.[0-9]'),'(?<=\\s).*')), -- Extract the Y coordinate of 'MultiPoint ((0.2974026 51.8987013)' --> 51.8987013
                    NULL -- If invalid coordinate use NULL, maybe replace with 0

Which returns an array like [ <geometry: Point>, <geometry: Point>, <geometry: Point>, <geometry: Point>, ... ], which represents all the vertex of the polygon. One can easily extract X and Y coordinates out of it by adding x() or y() in front of make_point(), or by just adding another array_foreach() like array_foreach(*expression above*,x(@element)).

How could I use such an array to label every vertex with its coordinates? I thought of extracting them from the array, but cant iterate over it. Would this be possible? Or something similar? I am kind of stuck now...

  • 1
    You have only one feature (a polygon) so one label for its geometry. You can place labels at each vertices (Labels > Position > Geometry Generator (Point / Multipoints) > nodes_to_points($geometry)) but can't have vertex coordinates. – J. Monticolo Dec 4 '20 at 17:47

There is a way to display the coordinates... though not as a label.

One can add style with geometry generator to extract the vertices, then add a font marker style that will be overridden to display the vertices coordinates..

  1. add the vertices

Add a style of type geometry generator, geometry type point computed with the expression nodes_to_points( $geometry)

enter image description here

  1. Style it as a Font Marker

enter image description here

  1. Instruct to display the coordinates

Click the epsilon beside character(s) to edit the data-defined override. Enter the following expression

round(x( geometry_n( $geometry, @geometry_part_num )),4) || ' - ' || round(y( geometry_n( $geometry, @geometry_part_num )),4)

Let's break it down a bit:

geometry_n( $geometry, @geometry_part_num )) --> get the nth geometry from the one being rendered. From step 1, the geometry being rendered is an array of point (each vertices). Because we use @geometry_part_num, it is applied on every part (= on every vertex).
x(..) and y(...) -> the x/y coordinates of the point
round(..) --> let's not display 18 decimals :-)
|| ' - ' || --> Concatenate the X and Y coordinates, separate them with a -

enter image description here

  • 2
    Bravo, works perfectly! I would add for future readers that at 3.16.1 I did not initially see the "... epsilon besides character(s).." Instead, I saw the default button (not sure what to call it!). However, clicking on that default button and selecting Edit... brought up the Expression String Builder window, into which the expression can be written. At that point the default button displays the epsilon symbol, as circled in the answer. – Stu Smith Dec 4 '20 at 19:46
  • Great @JGH However confusing that in QGIS, vertices are refered to differently depending on context: normally, they are called vertices. In the expression nodes_to_points they are refered to as nodes, whereas geometry_part_num names them geometry part - good to remember! – babel Dec 4 '20 at 20:46
  • @babel Indeed! Though the geometry_part is more generic as it could refer to polygons or else (like a generated multiple ring buffer) – JGH Dec 4 '20 at 20:55
  • OK, so indeed geometry_part is not exclusively for vertices. Still, there is another name: in the expression point_n(geometry,index) vertices are refered to as points. – babel Dec 4 '20 at 21:11
  • Now thats one clever trick! And works with lines as well :) – MrXsquared Dec 4 '20 at 22:31

There is still something to copy from OpenJUMP (and improve). In OpenJUMP vertex XY is available as a decoration. Unfortunately the font or the numbers is tiny and there is no user interface for changing it.

enter image description here

enter image description here


I was reading the question too fast and used wrong decorations first.

enter image description here

enter image description here

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.