Select to view content in your preferred language

Python code error

1919
3
Jump to solution
10-31-2012 03:35 AM
by Anonymous User
Not applicable
Original User: luke.kaim

Hi Everyone,

Let me start by thanking you in advance.

The problem I am encountering is that line features do not close on themselves. I need to go through every line feature, select the first point X,Y coordinate store that point X,Y coordinate and add it to the end of the line Array. This will then close the line feature which is the desired goal of the code. I am trying to do this using the insert and search cursor. The code is not working though. My first issue is that the code will not create a feature class and then output it to the correct directory. I am not sure if I have the correct logic as well. Would you be able to look at the below code? I can also add a feature class which is a selection of the data.


# Luke Kaim 10/26/12 # The goal of this code is to close all line features such that the first coordinate and the last coordinate of a feature match.  # Import arcpy module import arcpy, sys, os, re import arcpy from arcpy import env  env.overwriteOutput = True env.workspace = "C:\\Users\\Luke Kaim\\Documents\\University of Maine\\Fall_2012\\Volunteer Geographic Information\\Data\\test"   # Get the output feature class infile = r"C:\Users\Luke Kaim\Documents\University of Maine\Fall_2012\Volunteer Geographic Information\Data\test\selectedlines.gdb\line"  outfile = (r"C:\Users\Luke Kaim\Documents\University of Maine\Fall_2012\Volunteer Geographic Information\Data\test\selectedlines.gdb\testline", 'w')    # Identify the geometry field desc = arcpy.Describe(infile) shapefieldname = desc.ShapeFieldName OIDFieldName = desc.OIDFieldName    try:    # Create the output feature class    #    #arcpy.CreateFeatureclass(path,name,"POLYLINE", infile)    arcpy.CreateFeatureclass_management(os.path.dirname(outfile),                                        os.path.basename(outfile),                                         "Polyline", infile)      rows = arcpy.SearchCursor(infile)    cur = arcpy.InsertCursor(outfile)     # Create an array and point object needed to create features    lineArray = arcpy.Array()    pnt = arcpy.Point()     # Iterate through the rows in the cursor     for row in rows:        # Create the geometry object              feat = row.getValue(shapefieldname)        # Print the current multipoint's ID              print "Feature %i:" % row.getValue(desc.OIDFieldName)        partnum = 0         # Step through each part of the feature               for part in feat:            # Print the part number                        print "Part %i:" % partnum             # Step through each vertex in the feature                        for pnt in feat.getPart(partnum):                if pnt:                     Print x,y coordinates of current point                                        print pnt.X, pnt.Y                    if partnum==1:                        firstpnt.X=pnt.X                        firstpnt.Y=pnt.Y                     lineArray.add(pnt)            feat = cur.newRow()             # Set the geometry of the new feature to the array of points            #            lineArray.add(firstpnt)            feat.shape = lineArray             # Insert the feature             cur.insertRow(feat)    lineArray.removeAll()          partnum += 1      del cur, rows except Exception as e:    print e.message
0 Kudos
1 Solution

Accepted Solutions
by Anonymous User
Not applicable
Original User: Wayne_Whitley

Ah, that's right, getPart will return an array of point objects, sufficient to pass to the 'new' geometry instead of dealing with coords (which aren't themselves being manipulated).

Good observation, thanks Marcin.

View solution in original post

0 Kudos
3 Replies
by Anonymous User
Not applicable
Original User: Wayne_Whitley

Your desired end product is to produce lines that loop on themselves?  Without looking at your data, are you sure this will produce the shapes intended, legitimate geometry?

I see you're establishing the workspace which you are both reading and writing from with:
env.workspace = "C:\\Users\\Luke Kaim\\Documents\\University of Maine\\Fall_2012\\Volunteer Geographic Information\\Data\\test"

But you're reading/writing to/from a gdb, so set your workspace directly to that with:
env.workspace = "C:\\Users\\Luke Kaim\\Documents\\University of Maine\\Fall_2012\\Volunteer Geographic Information\\Data\\test\\selectedlines.gdb"

Then your variables, infile and outfile (which are really feature classes), can be defined simply as:
infile = "line"
outfile = "testline"

This line (below, with the 'w' parameter [which means 'write' mode]) doesn't make sense - looks like you were trying to adapt code for writing to a text file (use the line above for defining the variable outfile)--
outfile = (r"C:\Users\Luke Kaim\Documents\University of Maine\Fall_2012\Volunteer Geographic Information\Data\test\selectedlines.gdb\testline", 'w')

Also, you'll need to change your parameters for Create Feature Class to accept the way you've defined infile and outfile - this more direct approach should work:
arcpy.CreateFeatureclass_management(env.workspace, outfile,"Polyline", infile)

For running this script on a selected set, you can run your search cursor initially set up with a query to define a selected set.

Hope that helps.  Also, next time you post, it would be helpful to include any error messages that may result.
0 Kudos
MarcinGasior
Frequent Contributor
The following code work on your sample data. In short - you don't need to loop through every point in part's point Array. It's enough to take first point (Array.getObject(0)) and add it to the end of array.
I didn't introduce Wayne's remarks, so polishing the code is your job;)
You may also need to copy attributes' values from input layer to output.

# Import arcpy module
import arcpy, sys, os, traceback
from arcpy import env

env.overwriteOutput = True
env.workspace = r"C:\tmp\selectedlines.gdb"


# Get the output feature class
infile = r"C:\tmp\selectedlines.gdb\line"
outfile = r"C:\tmp\selectedlines.gdb\testline"

# Identify the geometry field
desc = arcpy.Describe(infile)
shapefieldname = desc.ShapeFieldName
OIDFieldName = desc.OIDFieldName

# Create the output feature class
#arcpy.CreateFeatureclass(path,name,"POLYLINE", infile)
arcpy.CreateFeatureclass_management(os.path.dirname(outfile), os.path.basename(outfile), "Polyline", infile,
                                    "SAME_AS_TEMPLATE","SAME_AS_TEMPLATE",infile)

rows = arcpy.SearchCursor(infile)
cur = arcpy.InsertCursor(outfile)

# Iterate through the rows in the cursor
for row in rows:
    # Create the geometry object
    feat = row.getValue(shapefieldname)
    # Print the current multipoint's ID
    print "Feature %i:" % row.getValue(desc.OIDFieldName)
    partnum = 0

    # Step through each part of the feature
    for part in feat:
        # Print the part number
        #print "Part %i:" % partnum

        # Create an array of points from part
        pointsArray = feat.getPart(partnum)
        # Get the first point from Array
        firstPoint = pointsArray.getObject(0)
        # Add first point to the end of array to close a line
        pointsArray.add(firstPoint)

        feat = cur.newRow()
        feat.shape = pointsArray

        # Insert the feature
        cur.insertRow(feat)

pointsArray.removeAll()
del cur, rows
0 Kudos
by Anonymous User
Not applicable
Original User: Wayne_Whitley

Ah, that's right, getPart will return an array of point objects, sufficient to pass to the 'new' geometry instead of dealing with coords (which aren't themselves being manipulated).

Good observation, thanks Marcin.
0 Kudos