Writing geometries

Using insert and update cursors, scripts can create new features in a feature class or update existing ones. A script can define a feature by creating a point object, populating its properties, and placing it in an array. That array can then be used to set a feature's geometry. A single geometry part is defined by an array of points, so a multipart feature can be created from multiple arrays of points.

Below is an example of a file to be processed by the script that follows. It contains a point ID and an x- and y-coordinate.


The following example shows how to read a text file containing a series of linear coordinates (as above) and use them to create a new feature class.

# Create a new line feature class using a text file of coordinates.
#   Each coordinate entry is semicolon delimited in the format of ID;X;Y

# Import ArcPy and other required modules
import arcpy
from arcpy import env
import fileinput
import string
import os

env.overwriteOutput = True

# Get the coordinate ASCII file
infile = arcpy.GetParameterAsText(0)

# Get the output feature class
fcname = arcpy.GetParameterAsText(1)

# Get the template feature class
template = arcpy.GetParameterAsText(2)

   # Create the output feature class
                                       "Polyline", template)

   # Open an insert cursor for the new feature class
   cur = arcpy.InsertCursor(fcname)

   # Create an array and point object needed to create features
   lineArray = arcpy.Array()
   pnt = arcpy.Point()

   # Initialize a variable for keeping track of a feature's ID.
   ID = -1 
   for line in fileinput.input(infile): # Open the input file
      # set the point's ID, X and Y properties
      pnt.ID, pnt.X, pnt.Y = string.split(line,";")
      print pnt.ID, pnt.X, pnt.Y
      if ID == -1:
         ID = pnt.ID

      # Add the point to the feature's array of points
      #   If the ID has changed, create a new feature
      if ID != pnt.ID:
         # Create a new row or feature, in the feature class
         feat = cur.newRow()

         # Set the geometry of the new feature to the array of points
         feat.shape = lineArray

         # Insert the feature
      ID = pnt.ID

   # Add the last feature
   feat = cur.newRow()
   feat.shape = lineArray
   del cur
except Exception as e:
   print e.message

An array of points is not necessary when writing point features. A single point object is used to set the geometry of a point feature.

All geometries are validated before they are written to a feature class. Issues such as incorrect ring orientation and self-intersecting polygons, among others, are corrected when the geometry is simplified before its insertion.

Example: Using SearchCursor and InsertCursor to create square buffers

In some cases, it is desirable to create new geometries based on the features of another feature class. This can be achieved by using SearchCursor and InsertCursor simultaneously.

In the following example, InsertCursor is used to identify x,y coordinates of an input point feature class. These point coordinates are used to calculate the corner locations for square buffer polygons that are entered into the output using InsertCursor.

import arcpy
from arcpy import env
import os

env.overwriteOutput = True

# Get arguments: 
#   Input point feature class
#   Output polygon feature class
#   Buffer distance
#   Boolean type: Maintain fields and field values of the input in the output 
inPoints   = arcpy.GetParameterAsText(0)
outPolys   = arcpy.GetParameterAsText(1)
bufDist    = arcpy.GetParameterAsText(2)
keepFields = arcpy.GetParameterAsText(3)

# Prepare the output based on whether field and field values are desired in the output
if keepFields:
    # Create empty output polygon feature class that includes fields of the input
    arcpy.CreateFeatureClass(os.path.dirname(outPolys), os.path.basename(outPolys), "POLYGON",
                             inPoints, "", "", inPoints)

    # Create a short list of fields to ignore when moving fields values from 
    #  input to output
    ignoreFields = []

    # Use Describe properties to identify the shapeFieldName and OIDFieldName
    desc = arcpy.Describe(inPoints)

    # Create a list of fields to use when moving field values from input to output
    fields = arcpy.ListFields(inPoints)
    fieldList = []
    for field in fields:
        if field.name not in ignoreFields:
    # Create empty output polygon feature class without fields of the input
    arcpy.CreateFeatureclass(os.path.dirname(outPolys), os.path.basename(outPolys), "POLYGON",
                             "", "", "", inPoints)

# Open searchcursor
inRows = arcpy.SearchCursor(inPoints)

# Open insertcursor
outRows = arcpy.InsertCursor(outPolys)

# Create point and array objects
pntObj = arcpy.Point()
arrayObj = arcpy.Array()

for inRow in inRows: # One output feature for each input point feature
    inShape = inRow.shape
    pnt = inShape.getPart(0)

    # Need 5 vertices for square buffer: upper right, upper left, lower left,
    #   lower right, upper right. Add and subtract distance from coordinates of
    #   input point as appropriate.
    for vertex in [0,1,2,3,4]:
        pntObj.ID = vertex
        if vertex in [0,3,4]:
            pntObj.X = pnt.X + bufDist
            pntObj.X = pnt.X - bufDist
        if vertex in [0,1,5]:
            pntObj.Y = pnt.Y + bufDist
            pntObj.Y = pnt.Y - bufDist

    # Create new row for output feature
    feat = outRows.newRow()

    # Shift attributes from input to output
    if keepFields == "true":
        for fieldName in fieldList:
            feat.setValue(fieldName, inRow.getValue(fieldName))
    # Assign array of points to output feature
    feat.shape = arrayObj

    # Insert the feature

    # Clear array of points

# Delete inputcursor
del outRows

Using only geoprocessing tools, a square buffer can also be calculated using the Buffer and FeatureEnvelopeToPolygon tools in succession.

Related Topics