2

I am trying to delete first and the last vertex of each line.

I created code to delete first and last vertex but it shows me error on line 18:

Traceback (most recent call last): File "D:\UKPN\ukpn_CAD\tet\Delete_first_last.py", line 18, in insert = arcpy.da.InsertCursor(outFC, "SHAPE@") RuntimeError: cannot open 'D:\UKPN\ukpn_CAD\ukpn_CAD.gdb\right_no_diss_sample_diss_Sp4' Failed to execute (Deletefirstlast).

My code:

import arcpy

arcpy.env.overwriteOutput = True

# set input/output parameters
inFC = arcpy.GetParameterAsText(0)      
outFC = arcpy.GetParameterAsText(1)    

#output path
fcPath = outFC.rpartition("\\")[0]
fcName = outFC.rpartition("\\")[2]

if arcpy.Exists(outFC):
    arcpy.Delete_management(outFC)


search = arcpy.da.SearchCursor(inFC, "SHAPE@")
insert = arcpy.da.InsertCursor(outFC, "SHAPE@")

for row in search:
    points = [arcpy.Point(point.X, point.Y) for shape in row[0] for point in shape]

    del points[0]
    del points[-1]
    points.append(points[0])

    array = arcpy.Array(points)
    polyline = arcpy.Polyline(array)

    insert.insertRow([polyline])

I am using ArcGIS Pro Basic license 1.3. Can anyone tell me what am I doing wrong?

1
  • You should use u_cur.updateRow(row). updateRow is a method of UpdateCursor not of the row object! – fatih_dur Jan 31 '17 at 16:32
2

I think the problem lies in your attempt to "explode" your geometry into a list of point objects. I personally find list comprehension extremely confusing and generally unreadable. The following code does the same and is much easier to read.

# Code assumes the following: all polylines are single part & that a minimum number of vertices is 4
import arcpy
flayer = "fcLines" # Layer in TOC
with arcpy.da.UpdateCursor(flayer,["shape@","OID@"]) as cursor:
    for row in cursor:
        geom = row[0]
        oid = row[1]
        if geom.length > 0:
            # Create an array of point
            arr = geom.getPart(0) 

            print "Processing OID: " + str(oid)
            print "before: " + str(arr.count)

            # remove first
            arr.remove(0)

            # remove end
            arr.remove(arr.count - 1)

            print "after: " + str(arr.count)

            # Create new polyline and update row
            newLine = arcpy.Polyline(arr)
            row[0] = newLine
            cursor.updateRow(row)

Looking at your initial attempt there is no error trapping, what about lines that are composed of only two vertices, what about null geometries, what about stacked points? You need to deal with all those situations, you cannot assume your dataset is perfect.

1
  • 1
    Thanks for help :) Is just part of my full process, during it i got many tool that makes me sure what my output is so is not just an assumption. – Losbaltica Feb 1 '17 at 7:02
2

I have had similar problems with data where we had multiple vertices "stacked" at close to the same x,y pt in polylines and polygons. If you are using ArcGIS Arcmap (32 bit) ESRI products with python 2.7, I wrote a script to identify and clean those issues. In my script, I'm always saving the beginning and ending vertex of a polyline.

import arcpy
import math
#path

fc = arcpy.mapping.Layer('D:/Folder/Errors/HIGHWAYS.shp')
#UpdateCursor up, then down
with arcpy.da.UpdateCursor(fc,["shape@", "OID@"]) as cursor:
  for row in cursor:
    # loop through parts
    for part in row[0]:
      counter = 0
      compX = 000000.1
      compY = 000000.1
      #print "Beginning OID = " + str(row[1])
      for pnt in part:
        #--NOTE--if you want 2 places with ceil, multi and divide by 100
        if (math.ceil(pnt.X*10)/10 < compX + 0.2 and math.ceil(pnt.X*10)/10 > 
        compX - 0.2) and (math.ceil(pnt.Y*10)/10 < compY + 0.2 and 
        math.ceil(pnt.Y*10)/10 > compY - 0.2):
          print "##########################################################"
          #print str(compX) + "," + str(compY)
          print "OID = " + str(row[1])
          arr = row[0].getPart(0)
          if arr.count == 3:
            print "arr.count = 3"
            arr.remove(1)
            newLine = arcpy.Polyline(arr)
            row[0] = newLine
            print("Removing Malcolm in the Middle vertex " + "{0}, 
            {1}".format(pnt.X, pnt.Y))
            cursor.updateRow(row)
            print "-----------------------------------------"
          elif arr.count <= 2:
            print "no beuno---very small line---probably a sliver"
          else:
            print "arrcount = " + str(arr.count)
            print "counter = " + str(counter)
            if arr.count == (counter + 1):
                arr.remove(arr.count - 2)
                newLine = arcpy.Polyline(arr)
                row[0] = newLine
                print("Removing vertex " + "{0}, {1}".format(pnt.X, pnt.Y))
                print "Saved Original Endpoint"
                cursor.updateRow(row)
                print "----------->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
            else:
                arr.remove(counter - 1)
                newLine = arcpy.Polyline(arr)
                row[0] = newLine
                print("Removing vertex " + "{0}, {1}".format(pnt.X, pnt.Y))
                cursor.updateRow(row)
            print "-----------------------------------------"

        else:
          compX = math.ceil(pnt.X*10)/10
          compY = math.ceil(pnt.Y*10)/10
          counter = counter + 1
print ("Done")

If you are using something like Oracle Spatial.....

select * from (
SELECT id_number, id_2, SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(c.geometry, 
0.2) val
   FROM highway c  )
   where val <> 'TRUE';

Fixed the data using:

 update highway set geometry = sdo_util.rectify_geometry(GEOMETRY,0.2) where  
 id_number = 'somenumber1' ;
0

You are asking your model's user to enter an output feature class location/name as a parameter and deleting it if it exists. The problem is arcpy.da.InsertCursor works only with existing feature classes, so you need to create one (since you want to make sure it is an empty feature class).

Try adding Create Feature Class tool just before your insert cursor with relevant out path, name and geometry arguments.

Also the rest of your code may not work as expected if you have multipartite polylines!

5
  • if i could delete it on just one line it will be fine, i can loop through my feature for every single line. I added outFC = arcpy.CopyFeatures_management(inFC, outFC) But still it shows error that point is not recognise so i guess is something wrong with my row search but i don't know how to fix it – Losbaltica Jan 31 '17 at 15:23
  • 1
    Have a look at da.UpdateCursor instead of InsertCursor. You also need to check if the line feature that you are processing has at least four points, once the first and the last points are deleted, you will have only two points making one line. – fatih_dur Jan 31 '17 at 15:26
  • All my lines have 4 and more points. When i change it to UpdateCursor i got error: AttributeError: 'da.UpdateCursor' object has no attribute 'insertRow' – Losbaltica Jan 31 '17 at 15:30
  • Additionally, when you use update cursor, you won't need a search cursor to borrow the update shapes. All will be replaced in place! – fatih_dur Jan 31 '17 at 15:30
  • 1
    Since the correct record submission method is updateRow (row) for UpdateCursor... See the help page. – fatih_dur Jan 31 '17 at 15:32

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.