6

I'm following this tutorial on custom expressions and all goes well - my function shows up in the custom section and seems to work for the preview giving 21S for the first feature. When I extend the selection expression to GetUtmZone() = '21S' the output preview still says 1. But when I click on the select button no features are selected.

This works on 2.14.x but fails on 2.18.x.

The old style $GetUtmZone doesn't work in 2.14 or 2.18.

  • Did you try $GetUtmZone = '215' – artwork21 Mar 14 '17 at 12:29
  • yes that works in 2.8 but not later versions – Ian Turton Mar 14 '17 at 12:30
  • 1
    For what it's worth, I'm able to replicate this problem. In a possibly related bug, I created a "virtual" column (in QGIS 2.18.4) whose value is GetUtmZone() then tried to select features based on an expression using that column and it fails the same way (no features selected). Interestingly, the features are labeled with the value of that column and they display correctly. – csd Mar 14 '17 at 14:05
6

There are two things worth noting in this tutorial with respect to QGIS 2.18:

  • The code that is written in this exercise is a function (and not a variable). Functions are called with brackets (and parameters where applicable), so one needs to write GetUtmZone(). Do not reference it as a variable with a $ prefix.

  • This expression requires the geometry of the feature to calculate and return the result (it's hard to determine the correct UTM zone without a geometry, right ;) ). QGIS tries to reduce the amount of data it fetches (for performance reasons) and doesn't fetch the geometry if it's not explicitly required. Therefore you need to tell QGIS, that your function requires a geometry. How you do that?

-

@qgsfunction(args=0, group='Custom', usesgeometry=True)
6

Interesting, this also worked for me before (I used it several times) but it also fails for me on QGIS 2.18.2.

Anyway, an alternative is to instead create a field which contains the zones for each feature and then use this field in your select expression. You can do this by creating a script which you can add by going to:

Processing Toolbox > Scripts > Tools > Create new script

The following is code taken from your link but slightly modified to run from the processing toolbox:

##Example=name
##Layer=vector point
##Field_Name=string

from qgis.core import QgsField
from math import floor
from PyQt4.QtCore import QVariant

layer = processing.getObject(Layer)
layer.dataProvider().addAttributes([QgsField(str(Field_Name), QVariant.String)])
layer.updateFields()
idx = layer.fieldNameIndex(str(Field_Name))
layer.startEditing()

for feat in layer.getFeatures():
    pt = feat.geometry().centroid().asPoint()
    longitude = pt.x()
    latitude = pt.y()
    zone_number = floor(((longitude + 180) / 6) % 60) + 1
    if latitude >= 0:
        zone_letter = 'N'
    else:
        zone_letter = 'S'
    layer.changeAttributeValue(feat.id(), idx, '%d%s' % (int(zone_number), zone_letter))

layer.commitChanges()

Example:

  1. Populated dataset from your link:

    Populated dataset

  2. Script interface:

    Running script

  3. New attribute field added containing zones

    New attributes

  4. Result of selecting the zones by expression (highlighted in yellow):

    Result

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.