Compare commits
10 commits
e8d04ada05
...
6c562d15ea
Author | SHA1 | Date | |
---|---|---|---|
6c562d15ea | |||
34df797d96 | |||
2211eb92de | |||
19ed988760 | |||
5bdad0ea44 | |||
387c891134 | |||
6c5f9a6ca0 | |||
ff8c99cd8d | |||
f9d165da67 | |||
4a769a41a8 |
2 changed files with 301 additions and 273 deletions
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
import arcpy # type: ignore
|
import arcpy # type: ignore
|
||||||
|
|
||||||
DEFAULT_LINE_WIDTH = 0.7
|
# Define constants
|
||||||
|
# 1 point = 1/72 inch
|
||||||
|
# 1 inch = 25.4 mm
|
||||||
|
DEFAULT_LINE_WIDTH = 0.23
|
||||||
DEFAULT_COLOR = [
|
DEFAULT_COLOR = [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -62,7 +65,7 @@ class FeatureRenderer:
|
||||||
|
|
||||||
# Define parameter for selecting a primary key
|
# Define parameter for selecting a primary key
|
||||||
field_param_1 = arcpy.Parameter(
|
field_param_1 = arcpy.Parameter(
|
||||||
displayName="Select Primary Key Field (LEG_ID)",
|
displayName="Select Primary Key Field",
|
||||||
name="primary_key",
|
name="primary_key",
|
||||||
datatype="Field",
|
datatype="Field",
|
||||||
parameterType="Required",
|
parameterType="Required",
|
||||||
|
@ -204,6 +207,18 @@ class FeatureRenderer:
|
||||||
|
|
||||||
outline_field.parameterDependencies = [table_param.name]
|
outline_field.parameterDependencies = [table_param.name]
|
||||||
|
|
||||||
|
# Define parameter for outline width
|
||||||
|
outline_width = arcpy.Parameter(
|
||||||
|
name="outline_width",
|
||||||
|
displayName="Set outline width in pt",
|
||||||
|
datatype="GPDouble",
|
||||||
|
direction="Input",
|
||||||
|
parameterType="Optional",
|
||||||
|
category="Define Outlines",
|
||||||
|
)
|
||||||
|
|
||||||
|
outline_field.parameterDependencies = [table_param.name]
|
||||||
|
|
||||||
# Return parameter definitions as a list
|
# Return parameter definitions as a list
|
||||||
return [
|
return [
|
||||||
style_files,
|
style_files,
|
||||||
|
@ -219,6 +234,7 @@ class FeatureRenderer:
|
||||||
heading_field,
|
heading_field,
|
||||||
draw_outlines,
|
draw_outlines,
|
||||||
outline_field,
|
outline_field,
|
||||||
|
outline_width,
|
||||||
]
|
]
|
||||||
|
|
||||||
def isLicensed(self):
|
def isLicensed(self):
|
||||||
|
@ -248,6 +264,7 @@ class FeatureRenderer:
|
||||||
heading_field = parameters[10].valueAsText
|
heading_field = parameters[10].valueAsText
|
||||||
draw_outlines = parameters[11].value
|
draw_outlines = parameters[11].value
|
||||||
outline_field = parameters[12].valueAsText
|
outline_field = parameters[12].valueAsText
|
||||||
|
outline_width = parameters[13].value
|
||||||
|
|
||||||
# Retrieve currently active map
|
# Retrieve currently active map
|
||||||
active_map = project.activeMap
|
active_map = project.activeMap
|
||||||
|
@ -264,15 +281,20 @@ class FeatureRenderer:
|
||||||
layers_to_render = []
|
layers_to_render = []
|
||||||
for input_layer in input_layers_list:
|
for input_layer in input_layers_list:
|
||||||
present = False
|
present = False
|
||||||
|
|
||||||
|
# Test if layer is a group layer and extract layer name from path
|
||||||
|
if "\\" in input_layer:
|
||||||
|
input_layer = input_layer.split("\\")[-1]
|
||||||
|
|
||||||
for layer in map_layers:
|
for layer in map_layers:
|
||||||
if layer.name == input_layer:
|
if layer.name == input_layer:
|
||||||
layers_to_render.append(layer.name)
|
layers_to_render.append(layer)
|
||||||
present = True
|
present = True
|
||||||
break
|
break
|
||||||
|
|
||||||
if not present:
|
if not present:
|
||||||
added_layer = active_map.addDataFromPath(input_layer)
|
added_layer = active_map.addDataFromPath(input_layer)
|
||||||
layers_to_render.append(added_layer.name)
|
layers_to_render.append(added_layer)
|
||||||
|
|
||||||
# Retrieve styles that are currently in the project
|
# Retrieve styles that are currently in the project
|
||||||
project_styles = project.styles
|
project_styles = project.styles
|
||||||
|
@ -305,32 +327,49 @@ class FeatureRenderer:
|
||||||
|
|
||||||
# Retrieve label texts for custom labels
|
# Retrieve label texts for custom labels
|
||||||
add_labels = False
|
add_labels = False
|
||||||
|
custom_labels = {}
|
||||||
if label_field_1 or label_field_2:
|
if label_field_1 or label_field_2:
|
||||||
add_labels = True
|
add_labels = True
|
||||||
custom_labels = {}
|
fields = [primary_key_field]
|
||||||
labels = [primary_key_field]
|
if label_field_1 and label_field_1 not in fields:
|
||||||
if label_field_1:
|
fields.append(label_field_1)
|
||||||
labels.append(label_field_1)
|
if label_field_2 and label_field_2 not in fields:
|
||||||
if label_field_2:
|
fields.append(label_field_2)
|
||||||
labels.append(label_field_2)
|
|
||||||
|
|
||||||
with arcpy.da.SearchCursor(
|
with arcpy.da.SearchCursor(
|
||||||
table,
|
table,
|
||||||
labels,
|
fields,
|
||||||
) as search_cursor:
|
) as search_cursor:
|
||||||
for row in search_cursor:
|
for row in search_cursor:
|
||||||
custom_labels[row[0]] = f"{row[1]}{label_delimieter}{row[2]}"
|
id = str(row[0])
|
||||||
|
if id not in custom_labels:
|
||||||
|
if len(fields) == 3:
|
||||||
|
custom_labels[id] = f"{row[1]}{label_delimieter}{row[2]}"
|
||||||
|
elif len(fields) == 2:
|
||||||
|
if label_field_1 == primary_key_field:
|
||||||
|
custom_labels[id] = (
|
||||||
|
f"{row[0]}{label_delimieter}{row[1]}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
custom_labels[id] = f"{row[1]}"
|
||||||
|
elif len(fields) == 1:
|
||||||
|
custom_labels[id] = f"{row[0]}"
|
||||||
|
|
||||||
# Retrieve headings
|
# Retrieve headings
|
||||||
headings = {}
|
headings = {}
|
||||||
if heading_field:
|
if heading_field:
|
||||||
labels = [primary_key_field, heading_field]
|
fields = [primary_key_field]
|
||||||
|
if heading_field not in fields:
|
||||||
|
fields.append(heading_field)
|
||||||
with arcpy.da.SearchCursor(
|
with arcpy.da.SearchCursor(
|
||||||
table,
|
table,
|
||||||
labels,
|
fields,
|
||||||
) as search_cursor:
|
) as search_cursor:
|
||||||
for row in search_cursor:
|
for row in search_cursor:
|
||||||
|
if len(fields) == 2:
|
||||||
headings[str(row[0])] = row[1]
|
headings[str(row[0])] = row[1]
|
||||||
|
elif len(fields) == 1:
|
||||||
|
headings[str(row[0])] = row[0]
|
||||||
|
|
||||||
# Retrieve outline color codes
|
# Retrieve outline color codes
|
||||||
outline_codes = {}
|
outline_codes = {}
|
||||||
|
@ -343,8 +382,7 @@ class FeatureRenderer:
|
||||||
outline_codes[str(row[0])] = row[1]
|
outline_codes[str(row[0])] = row[1]
|
||||||
|
|
||||||
# Start rendering process
|
# Start rendering process
|
||||||
for layer in map_layers:
|
for layer in layers_to_render:
|
||||||
if layer.name in layers_to_render:
|
|
||||||
messages.AddMessage(f"Rendering layer: {layer.name}")
|
messages.AddMessage(f"Rendering layer: {layer.name}")
|
||||||
|
|
||||||
sym = layer.symbology
|
sym = layer.symbology
|
||||||
|
@ -369,7 +407,7 @@ class FeatureRenderer:
|
||||||
if symbol_code == "#":
|
if symbol_code == "#":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
code_components = get_code_components(symbol_code)
|
code_components = get_code_components(symbol_code, leg_id)
|
||||||
symbol_key = code_components["symbol_key"]
|
symbol_key = code_components["symbol_key"]
|
||||||
|
|
||||||
if symbol_key:
|
if symbol_key:
|
||||||
|
@ -385,13 +423,11 @@ class FeatureRenderer:
|
||||||
|
|
||||||
# Print message if symbol could not be found
|
# Print message if symbol could not be found
|
||||||
if not symbol_found:
|
if not symbol_found:
|
||||||
messages.AddMessage(
|
arcpy.AddWarning(
|
||||||
f"Could not find symbol in gallery {symbol_key}"
|
f"Could not find symbol in gallery {symbol_key}"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
messages.AddMessage(
|
arcpy.AddWarning(f"{leg_id} is not in legend table")
|
||||||
f"{leg_id} is not in legend table yet"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Add user defined labels
|
# Add user defined labels
|
||||||
if add_labels:
|
if add_labels:
|
||||||
|
@ -408,10 +444,7 @@ class FeatureRenderer:
|
||||||
if layer_shape_type == "Polygon":
|
if layer_shape_type == "Polygon":
|
||||||
for group in cim_lyr.renderer.groups:
|
for group in cim_lyr.renderer.groups:
|
||||||
for unique_value_class in group.classes:
|
for unique_value_class in group.classes:
|
||||||
if (
|
if unique_value_class.values[0].fieldValues[0] != "<Null>":
|
||||||
unique_value_class.values[0].fieldValues[0]
|
|
||||||
!= "<Null>"
|
|
||||||
):
|
|
||||||
leg_id = str(
|
leg_id = str(
|
||||||
unique_value_class.values[0].fieldValues[0]
|
unique_value_class.values[0].fieldValues[0]
|
||||||
)
|
)
|
||||||
|
@ -433,63 +466,36 @@ class FeatureRenderer:
|
||||||
if leg_id in outline_codes:
|
if leg_id in outline_codes:
|
||||||
# Set user defined outline color
|
# Set user defined outline color
|
||||||
outline_code = outline_codes[leg_id]
|
outline_code = outline_codes[leg_id]
|
||||||
|
if outline_code and outline_code != "#":
|
||||||
if (
|
|
||||||
not outline_code
|
|
||||||
) or outline_code == "#":
|
|
||||||
outline_code = CODE_BLK
|
|
||||||
|
|
||||||
color_value = get_symbol_color(outline_code)
|
color_value = get_symbol_color(outline_code)
|
||||||
|
else:
|
||||||
|
color_value = {"CMYK": DEFAULT_COLOR}
|
||||||
|
|
||||||
color = (
|
color = arcpy.cim.CreateCIMObjectFromClassName(
|
||||||
arcpy.cim.CreateCIMObjectFromClassName(
|
|
||||||
"CIMCMYKColor", "V3"
|
"CIMCMYKColor", "V3"
|
||||||
)
|
)
|
||||||
)
|
|
||||||
color.values = color_value["CMYK"]
|
color.values = color_value["CMYK"]
|
||||||
stroke_symbol_props[leg_id]["color"] = color
|
stroke_symbol_props[leg_id]["color"] = color
|
||||||
else:
|
|
||||||
if symbol_layer.color:
|
|
||||||
# Set color as it was before
|
|
||||||
stroke_symbol_props[leg_id][
|
|
||||||
"color"
|
|
||||||
] = symbol_layer.color
|
|
||||||
else:
|
else:
|
||||||
# Set default color
|
# Set default color
|
||||||
color = arcpy.cim.CreateCIMObjectFromClassName(
|
color = arcpy.cim.CreateCIMObjectFromClassName(
|
||||||
"CIMCMYKColor", "V3"
|
"CIMCMYKColor", "V3"
|
||||||
)
|
)
|
||||||
color.values = DEFAULT_COLOR
|
color.values = DEFAULT_COLOR
|
||||||
stroke_symbol_props[leg_id][
|
stroke_symbol_props[leg_id]["color"] = color
|
||||||
"color"
|
|
||||||
] = color
|
|
||||||
|
|
||||||
if draw_outlines:
|
|
||||||
if symbol_layer.width:
|
|
||||||
# Set width as it was before
|
|
||||||
stroke_symbol_props[leg_id][
|
|
||||||
"width"
|
|
||||||
] = symbol_layer.width
|
|
||||||
else:
|
|
||||||
# Set default width
|
|
||||||
stroke_symbol_props[leg_id][
|
|
||||||
"width"
|
|
||||||
] = DEFAULT_LINE_WIDTH
|
|
||||||
else:
|
|
||||||
stroke_symbol_props[leg_id]["width"] = 0
|
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
# In case the layer did not have a stroke symbol layer or outline color
|
# In case the layer did not have a stroke symbol layer
|
||||||
if not stroke_symbol_props[leg_id]["color"]:
|
if not stroke_symbol_props[leg_id]["color"]:
|
||||||
if leg_id in outline_codes:
|
if leg_id in outline_codes:
|
||||||
# Set user defined outline color
|
# Set user defined outline color
|
||||||
outline_code = outline_codes[leg_id]
|
outline_code = outline_codes[leg_id]
|
||||||
|
if outline_code and outline_code != "#":
|
||||||
if (not outline_code) or outline_code == "#":
|
|
||||||
outline_code = CODE_BLK
|
|
||||||
|
|
||||||
color_value = get_symbol_color(outline_code)
|
color_value = get_symbol_color(outline_code)
|
||||||
|
else:
|
||||||
|
color_value = {"CMYK": DEFAULT_COLOR}
|
||||||
|
|
||||||
color = arcpy.cim.CreateCIMObjectFromClassName(
|
color = arcpy.cim.CreateCIMObjectFromClassName(
|
||||||
"CIMCMYKColor", "V3"
|
"CIMCMYKColor", "V3"
|
||||||
)
|
)
|
||||||
|
@ -503,8 +509,12 @@ class FeatureRenderer:
|
||||||
color.values = DEFAULT_COLOR
|
color.values = DEFAULT_COLOR
|
||||||
stroke_symbol_props[leg_id]["color"] = color
|
stroke_symbol_props[leg_id]["color"] = color
|
||||||
|
|
||||||
if not stroke_symbol_props[leg_id]["width"]:
|
# Set outline width
|
||||||
if draw_outlines:
|
if draw_outlines:
|
||||||
|
if outline_width:
|
||||||
|
stroke_symbol_props[leg_id]["width"] = outline_width
|
||||||
|
else:
|
||||||
|
if not stroke_symbol_props[leg_id]["width"]:
|
||||||
stroke_symbol_props[leg_id][
|
stroke_symbol_props[leg_id][
|
||||||
"width"
|
"width"
|
||||||
] = DEFAULT_LINE_WIDTH
|
] = DEFAULT_LINE_WIDTH
|
||||||
|
@ -516,9 +526,7 @@ class FeatureRenderer:
|
||||||
for unique_value_class in group.classes:
|
for unique_value_class in group.classes:
|
||||||
|
|
||||||
if unique_value_class.values[0].fieldValues[0] != "<Null>":
|
if unique_value_class.values[0].fieldValues[0] != "<Null>":
|
||||||
leg_id = str(
|
leg_id = str(unique_value_class.values[0].fieldValues[0])
|
||||||
unique_value_class.values[0].fieldValues[0]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
leg_id = None
|
leg_id = None
|
||||||
|
|
||||||
|
@ -529,7 +537,7 @@ class FeatureRenderer:
|
||||||
if symbol_code == "#":
|
if symbol_code == "#":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
code_components = get_code_components(symbol_code)
|
code_components = get_code_components(symbol_code, leg_id)
|
||||||
color_value = code_components["color"]
|
color_value = code_components["color"]
|
||||||
symbol_color_value = code_components["symbol_color"]
|
symbol_color_value = code_components["symbol_color"]
|
||||||
|
|
||||||
|
@ -537,7 +545,6 @@ class FeatureRenderer:
|
||||||
for (
|
for (
|
||||||
symbol_layer
|
symbol_layer
|
||||||
) in unique_value_class.symbol.symbol.symbolLayers:
|
) in unique_value_class.symbol.symbol.symbolLayers:
|
||||||
|
|
||||||
if symbol_color_value:
|
if symbol_color_value:
|
||||||
update_symbol_layer_colors(
|
update_symbol_layer_colors(
|
||||||
symbol_layer, symbol_color_value
|
symbol_layer, symbol_color_value
|
||||||
|
@ -557,12 +564,12 @@ class FeatureRenderer:
|
||||||
symbol_layer,
|
symbol_layer,
|
||||||
arcpy.cim.CIMSymbols.CIMSolidStroke,
|
arcpy.cim.CIMSymbols.CIMSolidStroke,
|
||||||
):
|
):
|
||||||
symbol_layer.width = (
|
symbol_layer.width = stroke_symbol_props[
|
||||||
stroke_symbol_props[leg_id]["width"]
|
leg_id
|
||||||
)
|
]["width"]
|
||||||
symbol_layer.color = (
|
symbol_layer.color = stroke_symbol_props[
|
||||||
stroke_symbol_props[leg_id]["color"]
|
leg_id
|
||||||
)
|
]["color"]
|
||||||
|
|
||||||
# Draw symbol background colors
|
# Draw symbol background colors
|
||||||
if not has_background_color and color_value:
|
if not has_background_color and color_value:
|
||||||
|
@ -642,6 +649,12 @@ def update_symbol_layer_colors(symbol_layer, symbol_color_value):
|
||||||
if isinstance(symbol_layer, arcpy.cim.CIMSymbols.CIMSolidStroke):
|
if isinstance(symbol_layer, arcpy.cim.CIMSymbols.CIMSolidStroke):
|
||||||
update_color(symbol_layer, symbol_color_value)
|
update_color(symbol_layer, symbol_color_value)
|
||||||
|
|
||||||
|
if isinstance(symbol_layer, arcpy.cim.CIMSymbols.CIMHatchFill) and hasattr(
|
||||||
|
symbol_layer, "lineSymbol"
|
||||||
|
):
|
||||||
|
for sub_symbol_layer in symbol_layer.lineSymbol.symbolLayers:
|
||||||
|
update_color(sub_symbol_layer, symbol_color_value)
|
||||||
|
|
||||||
if isinstance(
|
if isinstance(
|
||||||
symbol_layer,
|
symbol_layer,
|
||||||
arcpy.cim.CIMSymbols.CIMCharacterMarker,
|
arcpy.cim.CIMSymbols.CIMCharacterMarker,
|
||||||
|
@ -671,11 +684,12 @@ def get_symbol_code_for_shape(shape_type, symbol_codes):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_code_components(code):
|
# code has three components: fill color, symbol key, symbol color
|
||||||
|
def get_code_components(code, leg_id):
|
||||||
code_len = len(code)
|
code_len = len(code)
|
||||||
if code_len == 4:
|
if code_len == 4:
|
||||||
return {
|
return {
|
||||||
"color": decode_color(code),
|
"color": decode_color(code, leg_id),
|
||||||
"symbol_key": "",
|
"symbol_key": "",
|
||||||
"symbol_color": {},
|
"symbol_color": {},
|
||||||
}
|
}
|
||||||
|
@ -695,13 +709,13 @@ def get_code_components(code):
|
||||||
}
|
}
|
||||||
elif code_len == 11:
|
elif code_len == 11:
|
||||||
return {
|
return {
|
||||||
"color": decode_color(code[:4]),
|
"color": decode_color(code[:4], leg_id),
|
||||||
"symbol_key": code[4:12],
|
"symbol_key": code[4:12],
|
||||||
"symbol_color": {},
|
"symbol_color": {},
|
||||||
}
|
}
|
||||||
elif code_len == 14:
|
elif code_len == 14:
|
||||||
return {
|
return {
|
||||||
"color": decode_color(code[:4]),
|
"color": decode_color(code[:4], leg_id),
|
||||||
"symbol_key": code[4:11],
|
"symbol_key": code[4:11],
|
||||||
"symbol_color": get_symbol_color(code[11:]),
|
"symbol_color": get_symbol_color(code[11:]),
|
||||||
}
|
}
|
||||||
|
@ -709,19 +723,29 @@ def get_code_components(code):
|
||||||
raise ValueError(f"Execution aborted: unknown symbol code {code}")
|
raise ValueError(f"Execution aborted: unknown symbol code {code}")
|
||||||
|
|
||||||
|
|
||||||
def decode_color(color_string):
|
def decode_color(color_string, leg_id):
|
||||||
|
if color_string[3] == "X":
|
||||||
return {
|
return {
|
||||||
"CMYK": [
|
"CMYK": [
|
||||||
get_percentage_from_letter(color_string[0]),
|
0,
|
||||||
get_percentage_from_letter(color_string[1]),
|
0,
|
||||||
get_percentage_from_letter(color_string[2]),
|
0,
|
||||||
get_percentage_from_letter(color_string[3]),
|
0,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return {
|
||||||
|
"CMYK": [
|
||||||
|
get_percentage_from_letter(color_string[0], leg_id),
|
||||||
|
get_percentage_from_letter(color_string[1], leg_id),
|
||||||
|
get_percentage_from_letter(color_string[2], leg_id),
|
||||||
|
get_percentage_from_letter(color_string[3], leg_id),
|
||||||
100,
|
100,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_percentage_from_letter(letter):
|
def get_percentage_from_letter(letter, leg_id):
|
||||||
if letter == "F":
|
if letter == "F":
|
||||||
return 15
|
return 15
|
||||||
elif letter == "V":
|
elif letter == "V":
|
||||||
|
@ -733,8 +757,10 @@ def get_percentage_from_letter(letter):
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
return int(letter) * 10
|
return int(letter) * 10
|
||||||
except ValueError as _:
|
except Exception as _:
|
||||||
raise ValueError(f"Execution aborted: unknown color code {letter}")
|
raise ValueError(
|
||||||
|
f"Execution aborted: unknown color code {letter} for {leg_id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_symbol_color(color_string):
|
def get_symbol_color(color_string):
|
||||||
|
@ -778,5 +804,7 @@ def get_symbol_color(color_string):
|
||||||
return {
|
return {
|
||||||
"CMYK": [100, 100, 100, 0, 100],
|
"CMYK": [100, 100, 100, 0, 100],
|
||||||
}
|
}
|
||||||
|
elif color_string == "GRA":
|
||||||
|
return {"CMYK": [10, 10, 10, 21, 100]}
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Execution aborted: unknown color code {color_string}")
|
raise ValueError(f"Execution aborted: unknown color code {color_string}")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Feature Renderer
|
# Feature Renderer
|
||||||
|
|
||||||
This is a Python toolbox for rendering geologic features in ArcGIS Pro. The toolbox is based on [ArcPy](https://pro.arcgis.com/en/pro-app/latest/arcpy/main/arcgis-pro-arcpy-reference.htm) modules. Specifically, it is based on the Cartographic Information Model [CIM](https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/python-cim-access.htm) to manipulate symbol layers and their properties.
|
This is a Python toolbox for rendering of geologic features in ArcGIS Pro. The toolbox is based on [ArcPy](https://pro.arcgis.com/en/pro-app/latest/arcpy/main/arcgis-pro-arcpy-reference.htm). Specifically, it uses the Cartographic Information Model [CIM](https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/python-cim-access.htm) to manipulate symbol layers and their properties.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue