1

I have an app that occasionally generates zero length polylines with identical start and end vertices. I need to modify the geometry for these features so that the end vertex is slightly different than the origin vertex. I am using an arcpy.da.UpdateCursor to replace the geometry of the features, but am getting an AttributeError: 'Polyline' object has no attribute 'setValue' on the second to last line. Any thoughts on how to resolve?

import arcpy

oilZoneFC = "T:\\Temp\\processing.gdb\\TEST"

cursor = arcpy.da.UpdateCursor(oilZoneFC, ["SHAPE@"]) 
for row in cursor:

    length = row[0].getLength('PLANAR', 'METERS')
    arcpy.AddMessage("Length = " + str(length) + " meters")
    if length == 0.0:
       arcpy.AddMessage("ZERO LENGTH FEATURE TO BE MODIFIED")
       for part in row[0]:
           origX = part[0].X
           origY = part[0].Y
           newX = origX + 0.0001
           newY = origY + 0.0001

           newCoord = arcpy.Array([arcpy.Point(origX, origY), arcpy.Point(newX, newY)])

           newLine = arcpy.Polyline(newCoord)
           row[0].setValue("SHAPE", newLine)
           cursor.updateRow(row)
  • 3
    setValue is a method of the old Cursor. You are using the newer DA cursor. – klewis Nov 1 '16 at 17:28
  • Row[0]=newLine will do – FelixIP Nov 1 '16 at 17:29
  • Thank you, I had tried the Row[0]=newLine and that also failed. I turned out that the problem (in addition to trying setValue) is complicated by the fact that in a geographic coordinate system, adding a second only vertex 0.0001 degrees results in arcpy considering the coordinates as identical. However, by changing that to 0.0002, enough of a difference was perceived for the script to work. – spaine Nov 1 '16 at 19:57
1

Sounds like you have got an answer but I wanted to point out that you should adopt the following code standards as it should guarantee the release of the cursor which, if not, can cause you all sorts of problems if there was more code. So get into the habitat of this best practise:

import arcpy
myTable = r"C:\temp\test.dbf"
with arcpy.da.SearchCursor(myTable,["Somefield1","somefield2"]) as cursor:
    for row in cursor:
        # get field values
        val1 = row[0]
        val2 = row[1]

        # Do more stuff

You can replace the "SearchCursor" with update or insert cursor. Note the with statement is what releases the cursor if you code in this style.

0

Here is the working script.

After replacing "row[0].setValue("SHAPE", newLine)" with "row[0] = newLine" (to be consistent with the arcpy.da.UpdateCursor format), the original script still failed because the original data is in a geographic coordinate system and offsetting a second polyline vertex only 0.0001 decimal degrees from the origin vertex resulted in ArcPy snapping the vertices together, back into a zero-length polyline. I attempted to add a projected spatial reference to my update cursor, but then ArcPy, apparently recognizing a zero-length polyline, deleted ALL vertices from the feature, so that it no longer had any origin vertex from which to build.

I overcame this problem by running the update cursor in 2 iterations. The first iteration identifies zero-length features, and adds a second vertex 0.001 decimal degrees from the origin (this being far enough away that ArcPy doesn't snap them back together). It also tags a new "FLAG" attribute so that the second iteration knows which features to alter.

Now that there is a legitimate polyline, the second iteration runs the cursor on flagged records in a projected coordinate system, allowing the script to create a polyline that begins at the origin and ends 1 meter away in both X and Y directions.

import arcpy

oilZoneFC = "T:\\Temp\\processing.gdb\\TEST"

arcpy.AddField_management(oilZoneFC, "FLAG", "SHORT")

with arcpy.da.UpdateCursor(oilZoneFC, ["SHAPE@", "FLAG"]) as cursor:
    arcpy.AddMessage("\nFirst Iteration - Identify Zero-Length Features and Add Vertex")
    for row in cursor:

        length = row[0].getLength('GEODESIC', 'METERS')
        arcpy.AddMessage("Length = " + str(length) + " meters")
        if length == 0.0:
            arcpy.AddMessage("ZERO LENGTH FEATURE MODIFIED")
            for part in row[0]:
                origX = part[0].X
                origY = part[0].Y
                newX = origX + 0.001
                newY = origY + 0.001

                newCoord = arcpy.Array([arcpy.Point(origX, origY), arcpy.Point(newX, newY)])

                newLine = arcpy.Polyline(newCoord)
                row[0] = newLine
                row[1] = 1
            cursor.updateRow(row)
    del cursor

with arcpy.da.UpdateCursor(oilZoneFC, ["SHAPE@", "FLAG"], spatial_reference = arcpy.SpatialReference(3310)) as cursor2:      #change spatial ref of cursor to Teale Albers NAD83      
    arcpy.AddMessage("\nSecond Iteration - Adjust Zero-Length Features to 1 Meter Length")
    for row2 in cursor2:

        length = row2[0].getLength('GEODESIC', 'METERS')
        arcpy.AddMessage("Length2 = " + str(length) + " meters")

        if row2[1] == 1:
            arcpy.AddMessage("FEATURE ADJUSTED TO 1 METER LENGTH")
            for part2 in row2[0]:
                origX2 = part2[0].X
                origY2 = part2[0].Y
                newX2 = origX2 + 1
                newY2 = origY2 + 1

                newCoord2 = arcpy.Array([arcpy.Point(origX2, origY2), arcpy.Point(newX2, newY2)])

                newLine2 = arcpy.Polyline(newCoord2)
                row2[0] = newLine2
            cursor2.updateRow(row2)
    del cursor2

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.