Geometry Operations with ArcMap Field Calculator

Field Calculator is one of the most frequently used tools within ArcMap: taught as part of nearly every introductory GIS course, it offers spreadsheet-like features to the normally static attribute table. Starting in ArcGIS 10.0, the attribute table also exposes the raw Geometry object of each feature to Field Calculator. This underutilized feature allows for rapid access to data that normally requires running a separate geoprocessing tool and joining the result to the attribute table. Building on my previous post about geodesic areas, I’ve compiled some of the more useful one-line geometry field calculations.

The doozy of an expression that inspired this cheat sheet.
The doozy of an expression that inspired me to post this cheat sheet.

These examples assume that the name of the shape field is SHAPE. Also, don’t forget that the Python parser must be used. If you immediately see an ERROR 999999 message, then it is likely that the parser is inadvertently set to VB Script.

Centroids and Midpoints
  • !SHAPE!.trueCentroid.X and !SHAPE!.trueCentroid.Y return the longitude and latitude coordinates of the true centroid of the feature as floating point numbers. For concave shapes (e.g. a horseshoe) this point can lie outside of the feature.
  • !SHAPE!.labelPoint.X and !SHAPE!.labelPoint.Y return the longitude and latitude coordinates of the label point of the feature as floating point numbers. The label point always lies within the feature, even when concave.
  • !SHAPE!.centroid.X and !SHAPE!.centroid.Y return the longitude and latitude coordinates of the centroid of the feature as floating point numbers. This is identical to the true centroid above, unless that point is outside of the feature in which case the label point is returned.
  • !SHAPE!.positionAlongLine(0.5,True).firstPoint.X and !SHAPE!.positionAlongLine(0.5,True).firstPoint.Y return the longitude and latitude coordinates of the midpoint of the feature as floating point numbers. To get the coordinates for the point at another fraction along the line, replace 0.5 with a value between 0.0 and 1.0. For example,  !SHAPE!.positionAlongLine(0.2, True) returns the point one-fifth of the length from the start of the feature to the end of the feature. Passing in False for the boolean parameter will return the point at a horizontal distance along the line rather than a fraction of the line.
Length, Perimieter, and Area
    • !SHAPE!.length returns the planar length of a line feature or the planar perimeter of a polygon feature. The units are the feature’s coordinate system’s linear units. This is identical to the SHAPE_Length field automatically added in geodatabase feature classes.
    • !SHAPE!.getLength("PLANAR","KILOMETERS") returns the planar length of a line feature or the planar perimieter of a polygon feature in kilometers. The area can be calculated in other units, identical to the Calculate Geometry tool in the attribute table.
    • !SHAPE!.getLength("GEODESIC","KILOMETERS") returns the geodesic length of a line feature or the geodesic perimeter of a polygon feature in kilometers. This accurate length calculation can be performed on feature classes in geographic coordinate systems (i.e. “unprojected”). The length can be calculated in other units and with other measurement types, as discussed in my detailed post about geodesic areas.
    • !SHAPE!.area returns the planar area of a polygon feature in the feature’s coordinate system as a floating point number. The units are the square of the feature’s coordinate system’s linear units. This is identical to the SHAPE_Area field automatically added in geodatabase feature classes.
    • !SHAPE!.getArea("PLANAR","SQUAREKILOMETERS") returns the area of a polygon feature projected onto a two-dimensional plane in square kilometers. The area can be calculated in other units, identical to the Calculate Geometry tool in the attribute table.
    • !SHAPE!.getArea("GEODESIC","SQUAREKILOMETERS") returns the geodesic area of a polygon feature in square kilometers. This accurate area calculation can be performed on feature classes in geographic coordinate systems (i.e. “unprojected”). The area can be calculated in other units and with other measurement types, as discussed in the in my detailed post about geodesic areas.
    • sorted([arcpy.Polygon(!SHAPE!.getPart(i), !SHAPE!.spatialReference).area for i in range( !SHAPE!.partCount)])[-1] returns the area of the largest part within a polygon. If the polygon has only one part, it returns the area of that part. This complex expression gets the individual parts of a multipart polygon, retrieves their areas, stores them in a Python list via a list comprehension, sorts the list, then takes the last (i.e. largest) value.
Extents, Convex Hulls, and Compactness
    • !SHAPE!.extent.YMax, !SHAPE!.extent.XMax, !SHAPE!.extent.YMin, and !SHAPE!.extent.XMin return the coordinate for the north, east, south, and western bounds of the feature, respectively.
    • !SHAPE!.extent.polygon returns a polygonal representation of the extent that can then be the target of other operations, e.g. !SHAPE!.extent.polygon.centroid for the centroid of the extent, !SHAPE!.extent.polygon.area for the area of the extent, !SHAPE!.extent.polygon.length, for the perimeter of the extent.
    • !SHAPE!.convexHull() returns a polygonal convex hull of an input point or line feature. This polygon can then be the target of other operations, e.g. !SHAPE!.convexHull().centroid for the centroid of the convex hull, !SHAPE!.convexHull().extent for the extent of the convex hull, !SHAPE!.convexHull().area for the area of the convex hull, !SHAPE!.convexHull().length, for the perimeter of the convex hull-.
    • !SHAPE!.area/!SHAPE!.convexHull().area returns the area of the feature divided by the area of the convex hull. This is a useful quick measure of compactness of concave polygons, where values closer to 1 denote more compact polygons without large concavities.
Part and Vertex Counts
  • !SHAPE!.partCount returns the number of parts in the feature as an integer number. Features with more than one part as considered multipart, and consist of distinct, non-contiguous polygons linked to a single row in the attribute table.
  • !Shape!.pointCount returns the number of vertices in a line or polygon feature feature as an integer number. Remember that there is an additional last vertex in a polygon that is a duplicate of the first vertex to “close” the shape, so a square will return a value of 5, a hexagon will return a value of 7, etc.
  • !Shape!.pointCount-!Shape!.partCount returns the number of unique vertices in a valid polygon feature as an integer number. The subtraction of !Shape!.partCount is necessary to avoid double counting the first vertex (of each part), which is repeated in order to “close” the part.
Densified and Simplified Geometry
  • !SHAPE!.densify("DISTANCE",1000,100) returns a densified line or polygon with additional vertices every 1000 horizontal units and a maximum deviation from the original line of 100 horizontal units. Outputting this value to the SHAPE field itself is equivalent to the Densify tool, except that it can be performed with only an ArcGIS for Desktop Basic license rather than a Standard license.
  • !SHAPE!.generalize(150) returns a simplified line with vertices removed within a tolerance of 150 horizontal units using the Douglas-Peucker algorithm. Outputting this value to the SHAPE field itself is equivalent to the Simplify Line tool/Simplify Polygon tool, except that it can be performed with only an ArcGIS for Desktop Basic license rather than a Standard license.
Projected Geometries
  • It is possible to project geometries to a new coordinate system defined by a SpatialReference object. The constructor for this object uses the “well-known identifier” (WKID) for different coordinate systems, as listed in this PDF of geographic coordinate systems and this PDF of projected coordinate systems.
  • arcpy.PointGeometry(!SHAPE!.centroid, !SHAPE!.spatialReference ).projectAs(arcpy.SpatialReference(26986)).firstPoint.X returns the longitude of the centroid projected from its native coordinate system to the NAD83 Massachusetts State Plane coordinate system (WKID 26986). To get the latitude, replace the final X with Y; to use different centroid types, replace centroid with labelPoint or trueCentroid; to output a different coordinate system, replace 26986 with the output coordinate system’s WKID.
  • !SHAPE!.projectAs(arcpy.SpatialReference(26986).exportToString()).area returns the area of a polygon projected from its native coordinate system to the NAD83 Massachusetts State Plane coordinate system (WKID 26986). To output a different coordinate system, replace 26986 with the output coordinate system’s WKID.
  • The previous example converts the SpatialReference object to a string using the exportToString() method, while the preceding example does not. This is necessary because !SHAPE! returns a <type 'geoprocessing describe geometry object'> rather than a true <class 'arcpy.arcobjects.geometries.PointGeometry'> or <class 'arcpy.arcobjects.geometries.Polyline'> or  <class 'arcpy.arcobjects.geometries.Polygon'> object. As such, all method parameters are converted to strings via gp_fixargs(). This works fine for the getLength(), getArea(), conexHull(), densify(), and simplify() methods whose parameters are all easily stringified str, int, and float primitives. However, this stringification does not handle SpatialReference objects. So if you encounter RuntimeError: Object: CreateObject error creating spatial reference, try using the exportToString() method on the SpatialReference object.

One thought on “Geometry Operations with ArcMap Field Calculator”

Leave a Reply

Your email address will not be published. Required fields are marked *