6

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?

asked Dec 4, 2014 at 4:51
11
  • How's your .net? Access to the IColor from the UniqueValuesRenderer is available from .net (vb.net, c#). There are ways of wrapping these objects for python but that's way advanced python! Commented Dec 4, 2014 at 4:53
  • My .net is dodgy. But it is food for thought. Thank you for the key words, I will look into it. Commented Dec 4, 2014 at 5:34
  • If you've got a VBA license it might be easier. Should this be the case I could put a little bit of code together. Commented Dec 4, 2014 at 5:35
  • Alas, no we don't have a licence. But, it was very kind of you to offer. Thank you. Commented Dec 4, 2014 at 5:43
  • This is a good question but I think it is a duplicate of gis.stackexchange.com/questions/71352/… and that you appear to be asking it to meet requirements similar to these gis.stackexchange.com/questions/27807/… Commented Dec 4, 2014 at 5:50

1 Answer 1

6

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:

  1. 0: A Folder (used for temp files including new file gdb & layer files)
  2. 1: A layer (from an open mxd)
  3. 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()

Example: enter image description here

answered Dec 12, 2014 at 6:25
2
  • 1
    I wrote the above py to be a script tool. The 3 exposed parameters plug into the toolbox tool nicely. Here's how you make a script tool: help.arcgis.com/EN/arcgisdesktop/10.0/help/index.html#/… Commented Aug 28, 2015 at 7:22
  • Can you write down some information what types of parameters did you use for Symbology field when creating a script tool. Commented Feb 6, 2017 at 17:27

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.