Add outline color field; headings can be regrouped now
This commit is contained in:
parent
dee854e5c1
commit
1582317c59
1 changed files with 170 additions and 81 deletions
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
import arcpy # type: ignore
|
import arcpy # type: ignore
|
||||||
|
|
||||||
|
DEFAULT_LINE_WIDTH = 0.7
|
||||||
|
|
||||||
|
|
||||||
class Toolbox:
|
class Toolbox:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -45,7 +47,7 @@ class FeatureRenderer:
|
||||||
table_param = arcpy.Parameter(
|
table_param = arcpy.Parameter(
|
||||||
displayName="Select Legend Table",
|
displayName="Select Legend Table",
|
||||||
name="table",
|
name="table",
|
||||||
datatype="DETable",
|
datatype="GPTableView",
|
||||||
parameterType="Required",
|
parameterType="Required",
|
||||||
direction="Input",
|
direction="Input",
|
||||||
)
|
)
|
||||||
|
@ -74,9 +76,9 @@ class FeatureRenderer:
|
||||||
|
|
||||||
field_param_2.parameterDependencies = [table_param.name]
|
field_param_2.parameterDependencies = [table_param.name]
|
||||||
|
|
||||||
# Define parameter for selecting a stroke symbol code field
|
# Define parameter for selecting a line symbol code field
|
||||||
field_param_3 = arcpy.Parameter(
|
field_param_3 = arcpy.Parameter(
|
||||||
displayName="Select Stroke Symbol Code Field",
|
displayName="Select Line Symbol Code Field",
|
||||||
name="line_symbol",
|
name="line_symbol",
|
||||||
datatype="Field",
|
datatype="Field",
|
||||||
parameterType="Required",
|
parameterType="Required",
|
||||||
|
@ -169,18 +171,31 @@ class FeatureRenderer:
|
||||||
|
|
||||||
heading_field.parameterDependencies = [table_param.name]
|
heading_field.parameterDependencies = [table_param.name]
|
||||||
|
|
||||||
# Define Boolean parameter
|
# Define parameter to choose to draw outlines
|
||||||
draw_outlines = arcpy.Parameter(
|
draw_outlines = arcpy.Parameter(
|
||||||
displayName="Draw outlines",
|
displayName="Draw outlines",
|
||||||
name="draw_outlines",
|
name="draw_outlines",
|
||||||
datatype="GPBoolean",
|
datatype="GPBoolean",
|
||||||
parameterType="Required",
|
parameterType="Required",
|
||||||
direction="Input",
|
direction="Input",
|
||||||
|
category="Define Outlines",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Default value
|
# Default value
|
||||||
draw_outlines.value = True
|
draw_outlines.value = True
|
||||||
|
|
||||||
|
# Define parameter for outline field
|
||||||
|
outline_field = arcpy.Parameter(
|
||||||
|
name="outline_field",
|
||||||
|
displayName="Select Outline Field",
|
||||||
|
datatype="Field",
|
||||||
|
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,
|
||||||
|
@ -195,6 +210,7 @@ class FeatureRenderer:
|
||||||
label_field_2,
|
label_field_2,
|
||||||
heading_field,
|
heading_field,
|
||||||
draw_outlines,
|
draw_outlines,
|
||||||
|
outline_field,
|
||||||
]
|
]
|
||||||
|
|
||||||
def isLicensed(self):
|
def isLicensed(self):
|
||||||
|
@ -223,6 +239,7 @@ class FeatureRenderer:
|
||||||
label_field_2 = parameters[9].valueAsText
|
label_field_2 = parameters[9].valueAsText
|
||||||
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
|
||||||
|
|
||||||
# Retrieve currently active map
|
# Retrieve currently active map
|
||||||
active_map = project.activeMap
|
active_map = project.activeMap
|
||||||
|
@ -296,9 +313,10 @@ class FeatureRenderer:
|
||||||
for row in search_cursor:
|
for row in search_cursor:
|
||||||
custom_labels[row[0]] = f"{row[1]}{label_delimieter}{row[2]}"
|
custom_labels[row[0]] = f"{row[1]}{label_delimieter}{row[2]}"
|
||||||
|
|
||||||
|
# Retrieve headings
|
||||||
|
headings = {}
|
||||||
if heading_field:
|
if heading_field:
|
||||||
labels = [primary_key_field, heading_field]
|
labels = [primary_key_field, heading_field]
|
||||||
headings = {}
|
|
||||||
with arcpy.da.SearchCursor(
|
with arcpy.da.SearchCursor(
|
||||||
table,
|
table,
|
||||||
labels,
|
labels,
|
||||||
|
@ -306,6 +324,16 @@ class FeatureRenderer:
|
||||||
for row in search_cursor:
|
for row in search_cursor:
|
||||||
headings[str(row[0])] = row[1]
|
headings[str(row[0])] = row[1]
|
||||||
|
|
||||||
|
# Retrieve outline color codes
|
||||||
|
outline_codes = {}
|
||||||
|
if outline_field:
|
||||||
|
with arcpy.da.SearchCursor(
|
||||||
|
table,
|
||||||
|
[primary_key_field, outline_field],
|
||||||
|
) as search_cursor:
|
||||||
|
for row in search_cursor:
|
||||||
|
outline_codes[str(row[0])] = row[1]
|
||||||
|
|
||||||
# Start rendering process
|
# Start rendering process
|
||||||
for layer in map_layers:
|
for layer in map_layers:
|
||||||
if layer.name in layers_to_render:
|
if layer.name in layers_to_render:
|
||||||
|
@ -317,42 +345,6 @@ class FeatureRenderer:
|
||||||
|
|
||||||
# Check if UniqueValueRenderer is defined
|
# Check if UniqueValueRenderer is defined
|
||||||
if sym.renderer == "UniqueValueRenderer":
|
if sym.renderer == "UniqueValueRenderer":
|
||||||
|
|
||||||
# Regroup items according to heading field
|
|
||||||
if heading_field:
|
|
||||||
new_item_groups = {}
|
|
||||||
old_item_groups = {}
|
|
||||||
|
|
||||||
for group in sym.renderer.groups:
|
|
||||||
old_item_groups[group.heading] = group.items
|
|
||||||
|
|
||||||
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 headings:
|
|
||||||
heading = headings[leg_id]
|
|
||||||
if not heading:
|
|
||||||
heading = "Other"
|
|
||||||
else:
|
|
||||||
heading = "Other"
|
|
||||||
|
|
||||||
if heading in new_item_groups:
|
|
||||||
new_item_groups[heading].append(item)
|
|
||||||
else:
|
|
||||||
new_item_groups[heading] = [item]
|
|
||||||
|
|
||||||
# Remove old item groups
|
|
||||||
sym.renderer.removeValues(old_item_groups)
|
|
||||||
layer.symbology = sym
|
|
||||||
|
|
||||||
# Add new item groups
|
|
||||||
sym.renderer.addValues(new_item_groups)
|
|
||||||
layer.symbology = sym
|
|
||||||
|
|
||||||
# Apply symbols from gallery
|
# Apply symbols from gallery
|
||||||
for group in sym.renderer.groups:
|
for group in sym.renderer.groups:
|
||||||
for item in group.items:
|
for item in group.items:
|
||||||
|
@ -376,11 +368,19 @@ class FeatureRenderer:
|
||||||
symbols_from_gallery = (
|
symbols_from_gallery = (
|
||||||
item.symbol.listSymbolsFromGallery(symbol_key)
|
item.symbol.listSymbolsFromGallery(symbol_key)
|
||||||
)
|
)
|
||||||
|
symbol_found = False
|
||||||
for symbol_from_gallery in symbols_from_gallery:
|
for symbol_from_gallery in symbols_from_gallery:
|
||||||
if symbol_from_gallery.name == symbol_key:
|
if symbol_from_gallery.name == symbol_key:
|
||||||
|
symbol_found = True
|
||||||
item.symbol = symbol_from_gallery
|
item.symbol = symbol_from_gallery
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# Print message if symbol could not be found
|
||||||
|
if not symbol_found:
|
||||||
|
messages.AddMessage(
|
||||||
|
f"Could not find symbol in gallery {symbol_key}"
|
||||||
|
)
|
||||||
|
|
||||||
# Add user defined labels
|
# Add user defined labels
|
||||||
if add_labels:
|
if add_labels:
|
||||||
if leg_id in custom_labels:
|
if leg_id in custom_labels:
|
||||||
|
@ -392,39 +392,98 @@ class FeatureRenderer:
|
||||||
cim_lyr = layer.getDefinition("V3")
|
cim_lyr = layer.getDefinition("V3")
|
||||||
|
|
||||||
# Retrieve stroke symbol properties
|
# Retrieve stroke symbol properties
|
||||||
stroke_symbol_props = {"color": {}, "width": 0}
|
stroke_symbol_props = {}
|
||||||
if draw_outlines:
|
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 unique_value_class.values[0].fieldValues[0] != "<Null>":
|
||||||
for (
|
leg_id = str(
|
||||||
symbol_layer
|
unique_value_class.values[0].fieldValues[0]
|
||||||
) in unique_value_class.symbol.symbol.symbolLayers:
|
)
|
||||||
if isinstance(
|
else:
|
||||||
symbol_layer,
|
leg_id = None
|
||||||
arcpy.cim.CIMSymbols.CIMSolidStroke,
|
|
||||||
):
|
stroke_symbol_props[leg_id] = {
|
||||||
stroke_symbol_props["color"] = (
|
"color": None,
|
||||||
symbol_layer.color
|
"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]
|
||||||
|
color_value = get_symbol_color(outline_code)
|
||||||
|
color = arcpy.cim.CreateCIMObjectFromClassName(
|
||||||
|
"CIMCMYKColor", "V3"
|
||||||
)
|
)
|
||||||
stroke_symbol_props["width"] = (
|
color.values = color_value["CMYK"]
|
||||||
symbol_layer.width
|
stroke_symbol_props[leg_id]["color"] = color
|
||||||
)
|
else:
|
||||||
break
|
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 = [40, 40, 40, 10, 100]
|
||||||
|
stroke_symbol_props[leg_id]["color"] = color
|
||||||
|
|
||||||
if stroke_symbol_props["color"]:
|
if draw_outlines:
|
||||||
break
|
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
|
||||||
|
|
||||||
# Set default stroke width and color if unset
|
break
|
||||||
if draw_outlines and stroke_symbol_props["width"] == 0:
|
|
||||||
stroke_symbol_props["width"] = 0.7
|
|
||||||
|
|
||||||
if not stroke_symbol_props["color"]:
|
# In case the layer did not have a stroke symbol layer or outline color
|
||||||
color = arcpy.cim.CreateCIMObjectFromClassName(
|
if not stroke_symbol_props[leg_id]["color"]:
|
||||||
"CIMCMYKColor", "V3"
|
if leg_id in outline_codes:
|
||||||
)
|
messages.AddMessage("Add color")
|
||||||
color.values = [40, 40, 40, 10, 100]
|
# Set user defined outline color
|
||||||
stroke_symbol_props["color"] = color
|
outline_code = outline_codes[leg_id]
|
||||||
|
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 = [40, 40, 40, 10, 100]
|
||||||
|
stroke_symbol_props[leg_id]["color"] = color
|
||||||
|
|
||||||
|
if not stroke_symbol_props[leg_id]["width"]:
|
||||||
|
if draw_outlines:
|
||||||
|
stroke_symbol_props[leg_id][
|
||||||
|
"width"
|
||||||
|
] = DEFAULT_LINE_WIDTH
|
||||||
|
else:
|
||||||
|
stroke_symbol_props[leg_id]["width"] = 0
|
||||||
|
|
||||||
|
new_groups = []
|
||||||
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:
|
||||||
|
|
||||||
|
@ -471,10 +530,10 @@ class FeatureRenderer:
|
||||||
arcpy.cim.CIMSymbols.CIMSolidStroke,
|
arcpy.cim.CIMSymbols.CIMSolidStroke,
|
||||||
):
|
):
|
||||||
symbol_layer.width = (
|
symbol_layer.width = (
|
||||||
stroke_symbol_props["width"]
|
stroke_symbol_props[leg_id]["width"]
|
||||||
)
|
)
|
||||||
symbol_layer.color = (
|
symbol_layer.color = (
|
||||||
stroke_symbol_props["color"]
|
stroke_symbol_props[leg_id]["color"]
|
||||||
)
|
)
|
||||||
|
|
||||||
elif layer_shape_type == "Polyline":
|
elif layer_shape_type == "Polyline":
|
||||||
|
@ -495,7 +554,7 @@ class FeatureRenderer:
|
||||||
# Draw symbol background colors
|
# Draw symbol background colors
|
||||||
if not has_color and color_value:
|
if not has_color and color_value:
|
||||||
if layer_shape_type == "Polygon":
|
if layer_shape_type == "Polygon":
|
||||||
# Add fill and stroke symbol layers
|
# Add fill symbol layer
|
||||||
fill_symbol = arcpy.cim.CIMSolidFill()
|
fill_symbol = arcpy.cim.CIMSolidFill()
|
||||||
update_color(fill_symbol, color_value)
|
update_color(fill_symbol, color_value)
|
||||||
|
|
||||||
|
@ -504,17 +563,14 @@ class FeatureRenderer:
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add stroke symbol layer
|
# Add stroke symbol layer
|
||||||
if (
|
if stroke_symbol_props[leg_id]:
|
||||||
draw_outlines
|
|
||||||
and stroke_symbol_props["color"]
|
|
||||||
):
|
|
||||||
stroke_symbol = arcpy.cim.CIMSolidStroke()
|
stroke_symbol = arcpy.cim.CIMSolidStroke()
|
||||||
stroke_symbol.color = stroke_symbol_props[
|
stroke_symbol.color = stroke_symbol_props[
|
||||||
"color"
|
leg_id
|
||||||
]
|
]["color"]
|
||||||
stroke_symbol.width = stroke_symbol_props[
|
stroke_symbol.width = stroke_symbol_props[
|
||||||
"width"
|
leg_id
|
||||||
]
|
]["width"]
|
||||||
unique_value_class.symbol.symbol.symbolLayers.append(
|
unique_value_class.symbol.symbol.symbolLayers.append(
|
||||||
stroke_symbol
|
stroke_symbol
|
||||||
)
|
)
|
||||||
|
@ -533,6 +589,36 @@ class FeatureRenderer:
|
||||||
marker_symbol
|
marker_symbol
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 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
|
# Push changes back to layer object
|
||||||
layer.setDefinition(cim_lyr)
|
layer.setDefinition(cim_lyr)
|
||||||
|
|
||||||
|
@ -633,7 +719,10 @@ def get_percentage_from_letter(letter):
|
||||||
elif letter == "X":
|
elif letter == "X":
|
||||||
return 0
|
return 0
|
||||||
else:
|
else:
|
||||||
return int(letter) * 10
|
try:
|
||||||
|
return int(letter) * 10
|
||||||
|
except ValueError as _:
|
||||||
|
raise ValueError(f"Execution aborted: unknown color code {letter}")
|
||||||
|
|
||||||
|
|
||||||
def get_symbol_color(color_string):
|
def get_symbol_color(color_string):
|
||||||
|
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue