2

I have created two functions: one to add a field to a layer and one to calculate a field. I am having issues with the calculate field function when trying to calculate values for a numeric column. I do not get an error, but the column is blank after the code runs (it was blank to begin with). I've tried both OFTInteger and OFTReal as field types with the same result. Here are the functions:

def add_field(lyr, field_name, field_type):
    field = ogr.FieldDefn(field_name, field_type)
    field.SetWidth(50)
    lyr.CreateField(field)

def calc_field(calc_lyr, field, exp):
    for feature in calc_lyr:
        geom = feature.GetGeometryRef()
        area = geom.GetArea()
        feature.SetField(field, exp)
        calc_lyr.SetFeature(feature)

and here are the function calls to add and calculate a numeric field:

add_field(dxf_lyr, 'color', ogr.OFTInteger)
calc_field(dxf_lyr, 'color', 150)

The field gets added, but the values don't get caculated. What am I missing?

  • Do you close the dataset at the end using something like ds.Destroy()? It might also be necessary to repack it using ds.ExecuteSQL("REPACK " + lyr.GetName()) – s6hebern Mar 29 '18 at 7:49
  • thanks for your note. I don't close it, but can try that. But when I run the same dataset through both functions to add and calculate a string field, it works..but maybe I need to close it each time, the string field was the first one I added and calculated – kflaw Mar 29 '18 at 16:24
1

I have always used the layer.GetNextFeature() method with consistent success. i.e your function would look like this:

def calc_field(calc_lyr, field, exp):
    calc_lyr.ResetReading()    #reset the pointer
    feature= calc_lyr.GetNextFeature()    #prime the pump
    while feature:
        geom = feature.GetGeometryRef()
        area = geom.GetArea()
        feature.SetField(field, exp)
        calc_lyr.SetFeature(feature)
        feature= calc_lyr.GetNextFeature() #get the next feature, or None if at the end of the layer
  • Something else I am wondering and thought I would ask before starting a new post, how do you reference existing fields when calculating values for a new field? say I want to concatenate two fields as the value in the new field, i'm not sure how to do this here – kflaw Apr 5 '18 at 16:23
  • Start a new post so the question gets more visability – planetsandman Apr 6 '18 at 13:22
  • It is important to note (as explained in my answer) that the reason it failed was because you cannot iterate features with the chosen syntax: for feature in calc_lyr. It effectively did nothing. – Devin Cairns Apr 6 '18 at 16:41
1

The issue appears to be your use of iteration of the layer. The Layer class in the OGR Python API has an __iter__ method, but it will not work for you in this case. There are other ways of iterating features such as Layer.next and Layer.GetNextFeature, but these are challenging to use.

The simplest way to iterate features (in my experience) is to use one of the indexing methods, which are Layer.__getitem__ or Layer.GetFeature. These are usually used in conjunction with the Layer.GetFeatureCount method:

  • __getitem__ syntax:

    for i in range(calc_lyr.GetFeatureCount()):
        feature = calc_lyr[i]  # Note, only single integer slices are supported
        area = feature.GetGeometryRef().GetArea()
    
  • Using the Layer.GetFeature method:

    for i in range(calc_lyr.GetFeatureCount()):
        feature = calc_lyr.GetFeature(i)
        area = feature.GetGeometryRef().GetArea()
    

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.