I am wanting to take a symbolized layer in an mxd, and save it's symbol color (like a polygon fill) into its attribute table as an RGB value. My goal is to use this value in MapInfo to symbolize it's features via Discover.
I can't see any obvious way of using the ArcPy mapping module to read the particular values. Has anyone had a hack at building a simple modern solution?
Answer
I only need to get RGB values for polygon features. In particular solid fill vegetation and geology. I made a rough as guts ArcPy tool that fits my purpose.
The tool gets the user to nominate their layer and symbology field in ArcMap. The tool then loops through groups of "like sybology" values exporting them as rasters and interrogating them for their RGB values. These are then placed in the attribute table.
3 parameters must be passed into a script tool, which is used in a current mxd:
- 0: A Folder (used for temp files including new file gdb & layer files)
- 1: A layer (from an open mxd)
- 2: The nominated layers symbolology field
Code Sample:
import arcpy
from arcpy import env
arcpy.gp.overwriteOutput = True
arcpy.AddMessage("STARTED")
arcpy.AddMessage(" ")
arcpy.AddMessage("======================================================================")
##############
Folder = arcpy.GetParameterAsText(0)
if Folder == '#' or not Folder:
Folder = "C:\\Data"
##############
GDB = Folder+"\\TempGDB.gdb"
if arcpy.Exists(GDB):
arcpy.AddMessage(GDB)
else:
arcpy.CreateFileGDB_management(Folder, "TempGDB")
arcpy.AddMessage("GDB MADE")
# MUST BE IN ARCMAP
##############
InPolyLayer = arcpy.GetParameterAsText(1)
desc = arcpy.Describe(InPolyLayer)
LayerPath = desc.catalogPath
arcpy.AddMessage("Path: "+ LayerPath)
spatial_ref = arcpy.Describe(LayerPath).spatialReference
arcpy.AddMessage("Spatial Reference: "+spatial_ref.name)
sr = arcpy.SpatialReference(spatial_ref.factoryCode)
# Must Be The Symbology Field From "InPolyLayer"
##############
FieldName = arcpy.GetParameterAsText(2)
arcpy.AddMessage(FieldName)
fields = arcpy.ListFields(LayerPath)
for field in fields:
if field.name == FieldName:
FType = (field.type)
FPrecision = (field.precision)
FScale = (field.scale)
FLength = (field.length)
FNull = (field.isNullable)
arcpy.AddMessage("Type: "+str(FType))
arcpy.AddMessage("Precision: "+str(FPrecision))
arcpy.AddMessage("Scale: "+str(FScale))
arcpy.AddMessage("Lenght: "+str(FLength))
arcpy.AddMessage("Null: "+ str(FNull))
TempTileFC = GDB+"\\TempTileFC"
if arcpy.Exists(TempTileFC):
arcpy.Delete_management(TempTileFC)
### Varibles
# Temps
TempFrequency = GDB+"\\TempFrequency"
if arcpy.Exists(TempFrequency):
arcpy.Delete_management(TempFrequency)
TempP = GDB+"\\TempP"
if arcpy.Exists(TempP):
arcpy.Delete_management(TempP)
TRaster = Folder+"\\TempRaster.tif"
arcpy.AddMessage("TEMPS SET")
# Layers
mxd = arcpy.mapping.MapDocument ("CURRENT")
df = arcpy.mapping.ListDataFrames(mxd)[0]
TempLayerName = "TempLayer"
FreqView = "FreqView"
TempLayerFile = Folder+"\\TempLayerFile.lyr"
TempLayerFileLayer = "TempLayerFileLayer"
TempLayerCloneName = "TempLayerClone"
#Lyr for raster
arcpy.SaveToLayerFile_management(InPolyLayer, TempLayerFile, "ABSOLUTE")
# Fields
FieldNameR = str(FieldName)+"_R" #Check for, and create RGB Field
FieldNameG = str(FieldName)+"_G" #Check for, and create RGB Field
FieldNameB = str(FieldName)+"_B" #Check for, and create RGB Field
if len(arcpy.ListFields(InPolyLayer,FieldNameR)) == 0:
arcpy.AddField_management (InPolyLayer, FieldNameR, "short")
arcpy.AddMessage(FieldNameR +" field created")
else:
arcpy.AddMessage(FieldNameR +" field exists")
if len(arcpy.ListFields(InPolyLayer,FieldNameG)) == 0:
arcpy.AddField_management (InPolyLayer, FieldNameG, "short")
arcpy.AddMessage(FieldNameG +" field created")
else:
arcpy.AddMessage(FieldNameG +" field exists")
if len(arcpy.ListFields(InPolyLayer,FieldNameB)) == 0:
arcpy.AddField_management (InPolyLayer, FieldNameB, "short")
arcpy.AddMessage(FieldNameB +" field created")
else:
arcpy.AddMessage(FieldNameB +" field exists")
arcpy.AddMessage(" ")
arcpy.AddMessage("======================================================================")
arcpy.AddMessage(" ")
arcpy.AddMessage(" * FREQUENCIES & TEMP CARTO TILES")
arcpy.Frequency_analysis(LayerPath, TempFrequency, FieldName, "")
arcpy.AddMessage(" - Symbology Frequency Analysis Completed")
# Make Polygon For Layer Symbol Export
xExtent = df.extent
pnt1 = arcpy.Point(xExtent.XMin , xExtent.YMin)
pnt2 = arcpy.Point(xExtent.XMax , xExtent.YMin)
pnt3 = arcpy.Point(xExtent.XMax , xExtent.YMax)
pnt4 = arcpy.Point(xExtent.XMin , xExtent.YMax)
array = arcpy.Array()
array.add(pnt1)
array.add(pnt2)
array.add(pnt3)
array.add(pnt4)
array.add(pnt1)
SYMExtent = arcpy.Polygon(array)
arcpy.FeatureClassToFeatureClass_conversion (SYMExtent, GDB, "TempTileFC", "", "", "")
arcpy.AddMessage(" - Temp Tile Feature Class: "+str(TempTileFC))
arcpy.AddField_management (TempTileFC, FieldName, FType, FPrecision, FScale, FLength, "", FNull, "", "")
arcpy.FeatureToPoint_management (SYMExtent, TempP, "CENTROID")
TempPCen = arcpy.Describe(TempP)
CentroidE = TempPCen.extent
CentroidX = CentroidE.XMin
CentroidY = CentroidE.YMin
arcpy.AddMessage(" - Temp Tile Feature Class Field Added:"+str(FieldName))
arcpy.AddMessage(" - Centroid Feature Class For Raster:"+str(CentroidX)+str(CentroidY))
sourceLayer = arcpy.mapping.Layer(TempLayerFile)
arcpy.AddMessage(" ")
arcpy.AddMessage("======================================================================")
arcpy.AddMessage(" ")
arcpy.AddMessage(" * LOOPING VALUES")
cursor = arcpy.SearchCursor(TempFrequency)
for row in cursor:
arcpy.AddMessage(" ")
arcpy.AddMessage(" --------------")
rec = row.getValue(FieldName)
arcpy.AddMessage(" - Frequency Field Name:"+str(FieldName))
arcpy.AddMessage(" - Frequency Record: "+str(rec))
TempLayerClone = TempLayerCloneName+str(rec)
arcpy.AddMessage(" - Temp Layer:"+str(TempLayerClone))
### We don't need to delete the geom. just write the new value.
FieldExp ="'"+str(rec)+"'"
arcpy.AddMessage(" - Calculate Tile Field Expression: "+str(FieldExp))
arcpy.AddMessage(" - Temp Tile: " +str(TempTileFC))
arcpy.CalculateField_management(TempTileFC, FieldName, FieldExp, "PYTHON_9.3","")
# Remove Layer Test
for df in arcpy.mapping.ListDataFrames(mxd):
for lyr in arcpy.mapping.ListLayers(mxd, "", df):
if str(lyr)==TempLayerClone:
arcpy.mapping.RemoveLayer(df, lyr)
if arcpy.Exists(TempLayerClone):
arcpy.Delete_management(TempLayerClone)
# Make Layer
arcpy.MakeFeatureLayer_management (TempTileFC, TempLayerClone, "", "", "") # Make Layer
FeatureClassLayerMapping = arcpy.mapping.Layer(TempLayerClone)
arcpy.mapping.AddLayer(df, FeatureClassLayerMapping, "TOP") # Layer At Top
arcpy.AddMessage(" - Layer Added")
# Update
df2 = arcpy.mapping.ListDataFrames(mxd)[0]
updateLayer2 = arcpy.mapping.ListLayers(mxd, TempLayerClone, df)[0]
arcpy.mapping.UpdateLayer(df2, updateLayer2, sourceLayer, "True") # Carto Matches
################ NUMERIC OR TEXT
if FType == "String":
arcpy.AddMessage(" - IS String")
## 10.1
DefQURY = (("""\"{0}"='{1}'""").format(FieldName,rec)) #TEXT FIELDS
elif FType == "Text":
arcpy.AddMessage(" - IS TEXT")
## 10.1
DefQURY = (("""\"{0}"='{1}'""").format(FieldName,rec)) #TEXT FIELDS
else:
arcpy.AddMessage(" - IS NOT TEXT")
DefQURY = (("""\"{0}"={1}""").format(FieldName,rec)) #NUMERIC FIELDS
arcpy.AddMessage(" - Layer Updated")
arcpy.AddMessage(" - Selection Qu:" +str(DefQURY))
arcpy.SelectLayerByAttribute_management (updateLayer2, "NEW_SELECTION", DefQURY ) # Select & Zoom
df.zoomToSelectedFeatures()
arcpy.SelectLayerByAttribute_management (updateLayer2, "CLEAR_SELECTION")
arcpy.RefreshActiveView()
arcpy.AddMessage(" - Zoomed")
#Raster
if arcpy.Exists(TRaster):
arcpy.Delete_management(TRaster)
arcpy.mapping.ExportToTIFF(mxd, TRaster, df2, df_export_width=600,df_export_height=600,geoTIFF_tags=True)
arcpy.AddMessage(" - RGB Raster Exported")
arcpy.AddMessage(" - RGB Raster: "+TRaster)
Centroidf = ("{0} {1}".format(CentroidX,CentroidY))
RValues = arcpy.GetCellValue_management(TRaster, Centroidf, "1")
GValues = arcpy.GetCellValue_management(TRaster, Centroidf, "2")
BValues = arcpy.GetCellValue_management(TRaster, Centroidf, "3")
arcpy.AddMessage(" - R: "+str(RValues))
arcpy.AddMessage(" - G: "+str(GValues))
arcpy.AddMessage(" - B: "+str(BValues))
#Selection
arcpy.SelectLayerByAttribute_management (InPolyLayer, "NEW_SELECTION", DefQURY )
arcpy.AddMessage(" - Selection: "+ InPolyLayer)
arcpy.AddMessage(" - Def: "+ DefQURY)
arcpy.CalculateField_management(InPolyLayer, FieldNameR, RValues, "PYTHON_9.3")
arcpy.CalculateField_management(InPolyLayer, FieldNameG, GValues, "PYTHON_9.3")
arcpy.CalculateField_management(InPolyLayer, FieldNameB, BValues, "PYTHON_9.3")
arcpy.SelectLayerByAttribute_management (InPolyLayer, "CLEAR_SELECTION", DefQURY )
arcpy.AddMessage(" - Calculated & Cleared")
# Remove Layer
for df3 in arcpy.mapping.ListDataFrames(mxd):
for lyr in arcpy.mapping.ListLayers(mxd, "", df3):
if str(lyr)==TempLayerClone:
arcpy.mapping.RemoveLayer(df3, lyr)
del TempLayerClone
del FeatureClassLayerMapping
del df2, df3
arcpy.AddMessage(" - Removed & Cleared")
## if current is not saved then the tool will fail
mxd.save()
No comments:
Post a Comment