14

I want to create parcels (polygons/polyline) maps with the vertices labeled incrementally by vertex id using PyQGIS/QGIS. I normally do this by converting the polygon/polyline to point layer and adding point id attribute then overlay these points (with id labels) to the polygon layers. This is ok for one polygon, however, this becomes tedious and problematic if there are already lots of adjacent polygons.

I was wondering if there is a better way to do this using PyQGIS in QGIS?

I added a sample image for reference. sample image

Here's what I tried so far:

layer = iface.activeLayer()

featureId = 0

for feature in layer.getFeatures() :

    geom = feature.geometry()
    polygon = geom.asPolygon()
    outerRing = polygon[0]
    vertexId = 0

    # get the number of vertices of the outer ring
    numVertices = len(polygon[0])

    featureId = featureId + 1
  
    #get ring vertices
    # the -1 excludes the last vertex
    for steps in range(numVertices-1) :
        vertexId = vertexId + 1

        print featureId, ", ",vertexId, ", ", outerRing[steps] [0], ", ", outerRing[steps] [1]

This allows me to access the vertices and assign IDs and generate the list shown below:

1 ,  1 ,  -1.25423728814 ,  0.79472693032
1 ,  2 ,  -0.56120527307 ,  1.1450094162
1 ,  3 ,  0.158192090395 ,  0.606403013183
1 ,  4 ,  0.0118042738386 ,  0.30526236198
1 ,  5 ,  -0.105461393597 ,  0.0640301318267
1 ,  6 ,  -0.983050847458 ,  -0.00376647834275
1 ,  7 ,  -0.79472693032 ,  0.425612052731
2 ,  1 ,  -0.56120527307 ,  1.1450094162
2 ,  2 ,  0.020286539162 ,  1.59141143305
2 ,  3 ,  0.870711284112 ,  0.957931776096
2 ,  4 ,  0.384949214866 ,  0.718276001517
2 ,  5 ,  0.158192090395 ,  0.606403013183
3 ,  1 ,  0.384949214866 ,  0.718276001517
3 ,  2 ,  0.567873765457 ,  0.504288791391
3 ,  3 ,  0.212961505246 ,  0.230321432632
3 ,  4 ,  0.0118042738386 ,  0.30526236198
3 ,  5 ,  0.158192090395 ,  0.606403013183

I tried to combine labeling script below:

def vertexLabelling(posX, posY, vertexId) :
    palyr = QgsPalLayerSettings()
    palyr.enabled = True
    palyr.isExpression = True
    palyr.setDataDefinedProperty(QgsPalLayerSettings.Size,True,True,"8","")

    # set the placement position of the label
    palyr.setDataDefinedProperty(QgsPalLayerSettings.PositionX,True,True, posX,"")
    palyr.setDataDefinedProperty(QgsPalLayerSettings.PositionY,True,True, posY,"")

    palyr.fieldName = vertexId
    palyr.writeToLayer(layer)

    return()

vertexLabelling(str(outerRing[steps] [0]), str(outerRing[steps] [1]), str(vertexId))

However, QGIS only show one label with the last part of the loopResulting label.

If the labeling method (PAL) is applicable in this scenario, how do I modify my code?

Perhaps an alternative for me is to use the generated list as labels without having to convert it to points.

0

2 Answers 2

19

I know this is forever after you asked, but I found your question when I attempted to do the same thing.

At least in QGIS Version 3.8.0, this has been made incredibly easy.

Layer Properties -> Symbology
Fill
Add an Outline: Marker Line
Make sure the points are on every vertex. enter image description here

Add a Font Marker as a child of the Marker Line created above.
For the Character(s) field, add a data-defined override of @geometry_point_num
enter image description here

I also added a Simple marker colorized to the same color as the polygon fill, just to help visualize exactly where the vertices fall.

enter image description here

And below, I've added the X and Y locations, which can be very useful for confirming cadastral drawings or generating reports.

concat(@geometry_point_num,'\n', ' X: ',format_number($x_at(@geometry_point_num),3), '\n' , ' Y: ' ,format_number($y_at(@geometry_point_num),3))

Please note that newlines are being stripped currently. I have filed a Bug Report with QGIS about this behavior, however. enter image description here

0
0

This is really a comment on the excellent answer by Saijin_Naib:

I found that I had to subtract one from the value of @geometry_point_num with the function z_at() in order to access the correct point in the geometry. QGIS 3.34

z_at($geometry, (@geometry_point_num -1))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.