importarcpyimportnumpyimportmathdefAddGeometryAttributes(fc, geomProperties, lUnit, aUnit, cs):"""-------------------------------------------------------------------------
Tool: Add Geometry Attributes (Data Management Tools)
Source Name: AddGeometryAttributes.py
Version: ArcGIS 10.2.1
Author: Esri, Inc.
Usage: arcpy.AddGeometryAttributes_management(
Input_Features,
Geometry_Properties,
{Length_Unit},
{Area_Unit},
{Coordinate_System})
Required Arguments: Input Features
Geometry Properties
Optional Arguments: Length Unit
Area Unit
Coordinate System
Description: Adds attribute fields to the input features containing
measurements and coordinate properties of the feature
geometries (for example, length or area).
Updated: Not yet.
------------------------------------------------------------------------"""desc=arcpy.Describe(fc)
hasZ, hasM=desc.hasZ, desc.hasMifcs:
sr=arcpy.SpatialReference()
sr.loadFromString(cs)try:
srMetersPerUnit=sr.metersPerUnitexcept:
srMetersPerUnit= 1
else:try:
srMetersPerUnit=desc.spatialReference.metersPerUnitexcept:
srMetersPerUnit= 1shapeDict= {"POINT":1,"MULTIPOINT":1.5,"POLYLINE":2,"POLYGON":3,}
shapeDim=shapeDict[str(desc.shapeType).upper()]deldesc
fields=CreateOutputFields(fc, geomProperties, hasZ, hasM)
arcpy.SetProgressor("STEP", arcpy.GetIDMessage(86174), 0,
int(arcpy.GetCount_management(fc).getOutput(0)),1)
hasNulls=False#Calculate geometry properties into new fields
with arcpy.da.UpdateCursor(fc,fields + ["SHAPE@"],"",cs) as ucur:
ucurFields=ucur.fieldsglobalucurFieldsfor row inucur:globalrow
geom= row[ucurFields.index("SHAPE@")]ifgeom:if shapeDim == 1:if "POINT_X_Y_Z_M" ingeomProperties:
Update("POINT_X", geom.firstPoint.X)
Update("POINT_Y", geom.firstPoint.Y)ifhasZ:
Update("POINT_Z", geom.firstPoint.Z)ifhasM:
Update("POINT_M", geom.firstPoint.M)if shapeDim>1:if "PART_COUNT" ingeomProperties:
Update("PART_COUNT", geom.partCount)if "CENTROID" ingeomProperties:
Update("CENTROID_X", geom.trueCentroid.X)
Update("CENTROID_Y", geom.trueCentroid.Y)ifhasZ:
Update("CENTROID_Z", geom.trueCentroid.Z)ifhasM:
Update("CENTROID_M", geom.trueCentroid.M)if "EXTENT" ingeomProperties:
Update("EXT_MIN_X", geom.extent.XMin)
Update("EXT_MIN_Y", geom.extent.YMin)
Update("EXT_MAX_X", geom.extent.XMax)
Update("EXT_MAX_Y", geom.extent.YMax)if shapeDim>=2:if "POINT_COUNT" ingeomProperties:
Update("PNT_COUNT", geom.pointCount)if "LINE_START_MID_END" ingeomProperties:
Update("START_X", geom.firstPoint.X)
Update("START_Y", geom.firstPoint.Y)if shapeDim ==2:
midPoint= geom.positionAlongLine(0.5,
True).firstPointelse:
line= arcpy.Polyline(geom.getPart(0), "#",
hasZ, hasM)if line.length >0:
midPoint= line.positionAlongLine(0.5,
True).firstPointelse:
hasNulls=Truedelline
Update("MID_X", midPoint.X)
Update("MID_Y", midPoint.Y)
Update("END_X", geom.lastPoint.X)
Update("END_Y", geom.lastPoint.Y)ifhasZ:
Update("START_Z", geom.firstPoint.Z)
Update("MID_Z", midPoint.Z)
Update("END_Z", geom.lastPoint.Z)ifhasM:
Update("START_M", geom.firstPoint.M)
Update("MID_M", midPoint.M)
Update("END_M", geom.lastPoint.M)delmidPointif "CENTROID_INSIDE" ingeomProperties:
Update("INSIDE_X", geom.centroid.X)
Update("INSIDE_Y", geom.centroid.Y)ifhasZ:
Update("INSIDE_Z", geom.centroid.Z)ifhasM:
Update("INSIDE_M", geom.centroid.M)if shapeDim==2:if "LINE_BEARING" ingeomProperties:
lat1=geom.firstPoint.Y
lon1=geom.firstPoint.X
lat2=geom.lastPoint.Y
lon2=geom.lastPoint.X
Update("BEARING", (90 - math.degrees(math.atan2(lat2-lat1, lon2-lon1))) % 360)dellat1, lon1, lat2, lon2if "LENGTH" ingeomProperties:
Update("LENGTH", ConvertFromMeters("LINEAR",
geom.length,
lUnit,
srMetersPerUnit))if "LENGTH_3D" ingeomProperties:
Update("LENGTH_3D", ConvertFromMeters("LINEAR",
geom.length3D,
lUnit,
srMetersPerUnit))if "LENGTH_GEODESIC" ingeomProperties:
Update("LENGTH_GEO", ConvertFromMeters("LINEAR",
geom.getLength("PRESERVE_SHAPE"),
lUnit,
srMetersPerUnit))if shapeDim==3:if "PERIMETER_LENGTH" ingeomProperties:
Update("PERIMETER", ConvertFromMeters("LINEAR",
geom.length,
lUnit,
srMetersPerUnit))if "AREA" ingeomProperties:
Update("POLY_AREA", ConvertFromMeters("AREA",
geom.area,
aUnit,
srMetersPerUnit))if "AREA_GEODESIC" ingeomProperties:
Update("AREA_GEO", ConvertFromMeters("AREA",
geom.getArea("PRESERVE_SHAPE"),
aUnit,
srMetersPerUnit))if "PERIMETER_LENGTH_GEODESIC" ingeomProperties:
Update("PERIM_GEO", ConvertFromMeters("LINEAR",
geom.getLength("PRESERVE_SHAPE"),
lUnit,
srMetersPerUnit))
ucur.updateRow(row)else:
hasNulls=True
arcpy.SetProgressorPosition()ifhasNulls:
arcpy.AddIDMessage("WARNING", 957)defCreateOutputFields(fc, geomProperties, hasZ, hasM):
propDict= {"POINT_X_Y_Z_M": ["POINT_X","POINT_Y","POINT_Z","POINT_M"],"PART_COUNT": ["PART_COUNT"],"CENTROID": ["CENTROID_X","CENTROID_Y","CENTROID_Z","CENTROID_M"],"EXTENT": ["EXT_MIN_X","EXT_MIN_Y","EXT_MAX_X","EXT_MAX_Y"],"POINT_COUNT": ["PNT_COUNT"],"LINE_START_MID_END": ["START_X","START_Y","START_Z","START_M","MID_X","MID_Y","MID_Z","MID_M","END_X","END_Y","END_Z","END_M"],"LINE_BEARING": ["BEARING"],"CENTROID_INSIDE": ["INSIDE_X","INSIDE_Y","INSIDE_Z","INSIDE_M"],"LENGTH": ["LENGTH"],"PERIMETER_LENGTH": ["PERIMETER"],"AREA": ["POLY_AREA"],"LENGTH_GEODESIC": ["LENGTH_GEO"],"AREA_GEODESIC": ["AREA_GEO"],"LENGTH_3D": ["LENGTH_3D"],"PERIMETER_LENGTH_GEODESIC":["PERIM_GEO"],
}if nothasZ:
propDict["POINT_X_Y_Z_M"].remove("POINT_Z")
propDict["CENTROID"].remove("CENTROID_Z")
propDict["CENTROID_INSIDE"].remove("INSIDE_Z")
propDict["LINE_START_MID_END"].remove("START_Z")
propDict["LINE_START_MID_END"].remove("MID_Z")
propDict["LINE_START_MID_END"].remove("END_Z")if nothasM:
propDict["POINT_X_Y_Z_M"].remove("POINT_M")
propDict["CENTROID"].remove("CENTROID_M")
propDict["CENTROID_INSIDE"].remove("INSIDE_M")
propDict["LINE_START_MID_END"].remove("START_M")
propDict["LINE_START_MID_END"].remove("MID_M")
propDict["LINE_START_MID_END"].remove("END_M")
addList=[]
geomPropertiesList=[]
currentFields= [field.name for field inarcpy.ListFields(fc)]for prop ingeomProperties:for field inpropDict[prop.upper()]:
geomPropertiesList.append(field)if field not incurrentFields:
addList.append(field)else:
arcpy.AddIDMessage("WARNING", 1097, field)ifaddList:
narray= numpy.array([], numpy.dtype([("_ID", numpy.int)] +[(n, numpy.float)for n inaddList]))
arcpy.da.ExtendTable(fc,"OID@", narray, "_ID")returngeomPropertiesListdefConvertFromMeters(type, value, unit, metersPerUnit):if notunit:returnvalueelse:
distanceUnitInfo= {"METERS": 1.0,"FEET_US": 0.304800609601219,"NAUTICAL_MILES": 1852.0,"MILES_US": 1609.34721869444,"KILOMETERS": 1000.0,"YARDS": 0.914401828803658,}
areaUnitInfo= {"ACRES": 4046.86,"HECTARES": 10000.0,"SQUARE_METERS": 1.0,"SQUARE_FEET_US": 0.09290341161327473,"SQUARE_NAUTICAL_MILES": 3429904.0,"SQUARE_MILES_US": 2589998.4703195295,"SQUARE_KILOMETERS": 1000000.0,"SQUARE_YARDS": 0.8361307045194741,}if type == "LINEAR":return (value*metersPerUnit)/distanceUnitInfo[unit]if type == "AREA":return (value*math.pow(metersPerUnit,2))/areaUnitInfo[unit]defUpdate(field, value):ifvalue:if notmath.isnan(value):
row[ucurFields.index(field)]=value#run the script
if __name__ == '__main__':#Get Parameters
fc =arcpy.GetParameterAsText(0)if arcpy.GetParameterAsText(1).find(";") > -1:
geomProperties= arcpy.GetParameterAsText(1).upper().split(";")else:
geomProperties= [arcpy.GetParameterAsText(1).upper()]
lUnit= arcpy.GetParameterAsText(2)
aUnit= arcpy.GetParameterAsText(3)
cs= arcpy.GetParameterAsText(4)if notcs:
cs=arcpy.env.outputCoordinateSystem#Run the main script
AddGeometryAttributes(fc, geomProperties, lUnit, aUnit, cs)