Change color code X to transparent

This commit is contained in:
Fuhrmann 2025-02-21 10:07:53 +01:00
parent 5bdad0ea44
commit 19ed988760

View file

@ -288,13 +288,13 @@ class FeatureRenderer:
for layer in map_layers:
if layer.name == input_layer:
layers_to_render.append(layer.name)
layers_to_render.append(layer)
present = True
break
if not present:
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
project_styles = project.styles
@ -345,9 +345,11 @@ class FeatureRenderer:
custom_labels[row[0]] = f"{row[1]}{label_delimieter}{row[2]}"
elif len(fields) == 2:
if label_field_1 == primary_key_field:
custom_labels[row[0]] = f"{row[0]}{label_delimieter}{row[1]}"
custom_labels[row[0]] = (
f"{row[0]}{label_delimieter}{row[1]}"
)
else:
custom_labels[row[0]] = f"{row[1]}"
custom_labels[row[0]] = f"{row[1]}"
elif len(fields) == 1:
custom_labels[row[0]] = f"{row[0]}"
@ -378,138 +380,87 @@ class FeatureRenderer:
outline_codes[str(row[0])] = row[1]
# Start rendering process
for layer in map_layers:
if layer.name in layers_to_render:
messages.AddMessage(f"Rendering layer: {layer.name}")
for layer in layers_to_render:
messages.AddMessage(f"Rendering layer: {layer.name}")
sym = layer.symbology
layer_desc = arcpy.Describe(layer)
layer_shape_type = layer_desc.featureClass.shapeType
sym = layer.symbology
layer_desc = arcpy.Describe(layer)
layer_shape_type = layer_desc.featureClass.shapeType
# Check if UniqueValueRenderer is defined
if sym.renderer == "UniqueValueRenderer":
# Apply symbols from gallery
for group in sym.renderer.groups:
for item in group.items:
if item.values[0][0] != "<Null>":
leg_id = str(item.values[0][0])
# Check if UniqueValueRenderer is defined
if sym.renderer == "UniqueValueRenderer":
# Apply symbols from gallery
for group in sym.renderer.groups:
for item in group.items:
if item.values[0][0] != "<Null>":
leg_id = str(item.values[0][0])
else:
leg_id = None
if leg_id in symbol_codes:
symbol_code = get_symbol_code_for_shape(
layer_shape_type, symbol_codes[leg_id]
)
if symbol_code == "#":
continue
code_components = get_code_components(symbol_code, leg_id)
symbol_key = code_components["symbol_key"]
if symbol_key:
symbols_from_gallery = (
item.symbol.listSymbolsFromGallery(symbol_key)
)
symbol_found = False
for symbol_from_gallery in symbols_from_gallery:
if symbol_from_gallery.name == symbol_key:
symbol_found = True
item.symbol = symbol_from_gallery
break
# Print message if symbol could not be found
if not symbol_found:
arcpy.AddWarning(
f"Could not find symbol in gallery {symbol_key}"
)
else:
arcpy.AddWarning(f"{leg_id} is not in legend table")
# Add user defined labels
if add_labels:
if leg_id in custom_labels:
item.label = custom_labels[leg_id]
layer.symbology = sym
# Retrieve CIM to add colors
cim_lyr = layer.getDefinition("V3")
# Retrieve stroke symbol properties
stroke_symbol_props = {}
if layer_shape_type == "Polygon":
for group in cim_lyr.renderer.groups:
for unique_value_class in group.classes:
if unique_value_class.values[0].fieldValues[0] != "<Null>":
leg_id = str(
unique_value_class.values[0].fieldValues[0]
)
else:
leg_id = None
if leg_id in symbol_codes:
symbol_code = get_symbol_code_for_shape(
layer_shape_type, symbol_codes[leg_id]
)
stroke_symbol_props[leg_id] = {
"color": None,
"width": None,
}
if symbol_code == "#":
continue
code_components = get_code_components(
symbol_code, leg_id
)
symbol_key = code_components["symbol_key"]
if symbol_key:
symbols_from_gallery = (
item.symbol.listSymbolsFromGallery(symbol_key)
)
symbol_found = False
for symbol_from_gallery in symbols_from_gallery:
if symbol_from_gallery.name == symbol_key:
symbol_found = True
item.symbol = symbol_from_gallery
break
# Print message if symbol could not be found
if not symbol_found:
arcpy.AddWarning(
f"Could not find symbol in gallery {symbol_key}"
)
else:
arcpy.AddWarning(f"{leg_id} is not in legend table")
# Add user defined labels
if add_labels:
if leg_id in custom_labels:
item.label = custom_labels[leg_id]
layer.symbology = sym
# Retrieve CIM to add colors
cim_lyr = layer.getDefinition("V3")
# Retrieve stroke symbol properties
stroke_symbol_props = {}
if layer_shape_type == "Polygon":
for group in cim_lyr.renderer.groups:
for unique_value_class in group.classes:
if (
unique_value_class.values[0].fieldValues[0]
!= "<Null>"
for (
symbol_layer
) in unique_value_class.symbol.symbol.symbolLayers:
if isinstance(
symbol_layer,
arcpy.cim.CIMSymbols.CIMSolidStroke,
):
leg_id = str(
unique_value_class.values[0].fieldValues[0]
)
else:
leg_id = None
stroke_symbol_props[leg_id] = {
"color": None,
"width": None,
}
for (
symbol_layer
) in unique_value_class.symbol.symbol.symbolLayers:
if isinstance(
symbol_layer,
arcpy.cim.CIMSymbols.CIMSolidStroke,
):
if leg_id in outline_codes:
# Set user defined outline color
outline_code = outline_codes[leg_id]
if (
not outline_code
) or outline_code == "#":
outline_code = CODE_BLK
color_value = get_symbol_color(outline_code)
color = (
arcpy.cim.CreateCIMObjectFromClassName(
"CIMCMYKColor", "V3"
)
)
color.values = color_value["CMYK"]
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:
# Set default color
color = arcpy.cim.CreateCIMObjectFromClassName(
"CIMCMYKColor", "V3"
)
color.values = DEFAULT_COLOR
stroke_symbol_props[leg_id][
"color"
] = color
# Get symbol layer line width
if symbol_layer.width:
# Set width as it was before
stroke_symbol_props[leg_id][
"width"
] = symbol_layer.width
break
# In case the layer did not have a stroke symbol layer or outline color
if not stroke_symbol_props[leg_id]["color"]:
if leg_id in outline_codes:
# Set user defined outline color
outline_code = outline_codes[leg_id]
@ -518,150 +469,185 @@ class FeatureRenderer:
outline_code = CODE_BLK
color_value = get_symbol_color(outline_code)
color = arcpy.cim.CreateCIMObjectFromClassName(
"CIMCMYKColor", "V3"
)
color.values = color_value["CMYK"]
stroke_symbol_props[leg_id]["color"] = color
else:
# Set default color
color = arcpy.cim.CreateCIMObjectFromClassName(
"CIMCMYKColor", "V3"
)
color.values = DEFAULT_COLOR
stroke_symbol_props[leg_id]["color"] = color
if symbol_layer.color:
# Set color as it was before
stroke_symbol_props[leg_id][
"color"
] = symbol_layer.color
else:
# Set default color
color = (
arcpy.cim.CreateCIMObjectFromClassName(
"CIMCMYKColor", "V3"
)
)
color.values = DEFAULT_COLOR
stroke_symbol_props[leg_id]["color"] = color
# Set outline width
if draw_outlines:
if outline_width:
stroke_symbol_props[leg_id][
"width"
] = outline_width
else:
if not stroke_symbol_props[leg_id]["width"]:
# Get symbol layer line width
if symbol_layer.width:
# Set width as it was before
stroke_symbol_props[leg_id][
"width"
] = DEFAULT_LINE_WIDTH
] = symbol_layer.width
break
# In case the layer did not have a stroke symbol layer or outline color
if not stroke_symbol_props[leg_id]["color"]:
if leg_id in outline_codes:
# Set user defined outline color
outline_code = outline_codes[leg_id]
if (not outline_code) or outline_code == "#":
outline_code = CODE_BLK
color_value = get_symbol_color(outline_code)
color = arcpy.cim.CreateCIMObjectFromClassName(
"CIMCMYKColor", "V3"
)
color.values = color_value["CMYK"]
stroke_symbol_props[leg_id]["color"] = color
else:
stroke_symbol_props[leg_id]["width"] = 0
# Set default color
color = arcpy.cim.CreateCIMObjectFromClassName(
"CIMCMYKColor", "V3"
)
color.values = DEFAULT_COLOR
stroke_symbol_props[leg_id]["color"] = color
new_groups = []
for group in cim_lyr.renderer.groups:
for unique_value_class in group.classes:
if unique_value_class.values[0].fieldValues[0] != "<Null>":
leg_id = str(
unique_value_class.values[0].fieldValues[0]
)
# Set outline width
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][
"width"
] = DEFAULT_LINE_WIDTH
else:
leg_id = None
stroke_symbol_props[leg_id]["width"] = 0
if leg_id in symbol_codes:
symbol_code = get_symbol_code_for_shape(
layer_shape_type, symbol_codes[leg_id]
)
if symbol_code == "#":
continue
new_groups = []
for group in cim_lyr.renderer.groups:
for unique_value_class in group.classes:
code_components = get_code_components(
symbol_code, leg_id
)
color_value = code_components["color"]
symbol_color_value = code_components["symbol_color"]
if unique_value_class.values[0].fieldValues[0] != "<Null>":
leg_id = str(unique_value_class.values[0].fieldValues[0])
else:
leg_id = None
has_background_color = False
for (
symbol_layer
) in unique_value_class.symbol.symbol.symbolLayers:
if symbol_color_value:
update_symbol_layer_colors(
symbol_layer, symbol_color_value
)
if leg_id in symbol_codes:
symbol_code = get_symbol_code_for_shape(
layer_shape_type, symbol_codes[leg_id]
)
if symbol_code == "#":
continue
if color_value:
# Update background colors
if layer_shape_type == "Polygon":
if isinstance(
symbol_layer,
arcpy.cim.CIMSymbols.CIMSolidFill,
):
update_color(symbol_layer, color_value)
has_background_color = True
code_components = get_code_components(symbol_code, leg_id)
color_value = code_components["color"]
symbol_color_value = code_components["symbol_color"]
if isinstance(
symbol_layer,
arcpy.cim.CIMSymbols.CIMSolidStroke,
):
symbol_layer.width = (
stroke_symbol_props[leg_id]["width"]
)
symbol_layer.color = (
stroke_symbol_props[leg_id]["color"]
)
has_background_color = False
for (
symbol_layer
) in unique_value_class.symbol.symbol.symbolLayers:
if symbol_color_value:
update_symbol_layer_colors(
symbol_layer, symbol_color_value
)
# Draw symbol background colors
if not has_background_color and color_value:
if color_value:
# Update background colors
if layer_shape_type == "Polygon":
# Add fill symbol layer
fill_symbol = arcpy.cim.CIMSolidFill()
update_color(fill_symbol, color_value)
if isinstance(
symbol_layer,
arcpy.cim.CIMSymbols.CIMSolidFill,
):
update_color(symbol_layer, color_value)
has_background_color = True
unique_value_class.symbol.symbol.symbolLayers.append(
fill_symbol
)
# Add stroke symbol layer
if stroke_symbol_props[leg_id]:
stroke_symbol = arcpy.cim.CIMSolidStroke()
stroke_symbol.color = stroke_symbol_props[
leg_id
]["color"]
stroke_symbol.width = stroke_symbol_props[
if isinstance(
symbol_layer,
arcpy.cim.CIMSymbols.CIMSolidStroke,
):
symbol_layer.width = stroke_symbol_props[
leg_id
]["width"]
symbol_layer.color = stroke_symbol_props[
leg_id
]["color"]
# Insert at the beginning such that it appears on top of solid fill layer
unique_value_class.symbol.symbol.symbolLayers.insert(
0, stroke_symbol
)
# Draw symbol background colors
if not has_background_color and color_value:
if layer_shape_type == "Polygon":
# Add fill symbol layer
fill_symbol = arcpy.cim.CIMSolidFill()
update_color(fill_symbol, color_value)
# Regroup items
if heading_field:
if leg_id in headings:
heading = headings[leg_id]
if not heading:
heading = "Other"
else:
heading = "Other"
matched_group = next(
(
group
for group in new_groups
if group.heading == heading
),
None,
)
if matched_group:
matched_group.classes.append(unique_value_class)
else:
new_group = arcpy.cim.CreateCIMObjectFromClassName(
"CIMUniqueValueGroup", "V3"
unique_value_class.symbol.symbol.symbolLayers.append(
fill_symbol
)
new_group.heading = heading
new_group.classes.append(unique_value_class)
new_groups.append(new_group)
if heading_field:
cim_lyr.renderer.groups = new_groups
# Add stroke symbol layer
if stroke_symbol_props[leg_id]:
stroke_symbol = arcpy.cim.CIMSolidStroke()
stroke_symbol.color = stroke_symbol_props[
leg_id
]["color"]
stroke_symbol.width = stroke_symbol_props[
leg_id
]["width"]
# Push changes back to layer object
layer.setDefinition(cim_lyr)
# Insert at the beginning such that it appears on top of solid fill layer
unique_value_class.symbol.symbol.symbolLayers.insert(
0, stroke_symbol
)
else:
raise ValueError(
f"Execution aborted: please apply a Unique Value Renderer to layer {layer.name}"
)
# Regroup items
if heading_field:
if leg_id in headings:
heading = headings[leg_id]
if not heading:
heading = "Other"
else:
heading = "Other"
matched_group = next(
(
group
for group in new_groups
if group.heading == heading
),
None,
)
if matched_group:
matched_group.classes.append(unique_value_class)
else:
new_group = arcpy.cim.CreateCIMObjectFromClassName(
"CIMUniqueValueGroup", "V3"
)
new_group.heading = heading
new_group.classes.append(unique_value_class)
new_groups.append(new_group)
if heading_field:
cim_lyr.renderer.groups = new_groups
# Push changes back to layer object
layer.setDefinition(cim_lyr)
else:
raise ValueError(
f"Execution aborted: please apply a Unique Value Renderer to layer {layer.name}"
)
def postExecute(self, _):
return
@ -677,7 +663,9 @@ def update_symbol_layer_colors(symbol_layer, symbol_color_value):
if isinstance(symbol_layer, arcpy.cim.CIMSymbols.CIMSolidStroke):
update_color(symbol_layer, symbol_color_value)
if isinstance(symbol_layer, arcpy.cim.CIMSymbols.CIMHatchFill) and hasattr(symbol_layer, "lineSymbol"):
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)
@ -710,6 +698,7 @@ def get_symbol_code_for_shape(shape_type, symbol_codes):
)
# code has three components: fill color, symbol key, symbol color
def get_code_components(code, leg_id):
code_len = len(code)
if code_len == 4:
@ -749,15 +738,25 @@ def get_code_components(code, leg_id):
def decode_color(color_string, leg_id):
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,
],
}
if color_string[3] == "X":
return {
"CMYK": [
0,
0,
0,
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,
],
}
def get_percentage_from_letter(letter, leg_id):