脚本中的输出符号系统

使用脚本工具参数的符号系统属性可将单个图层文件 (.lyrx) 与某个输出参数关联起来。运行脚本工具时,会使用在图层文件的符号系统将输出添加到显示画面中。您还可以使用 Parameter 对象的 symbology 属性在脚本的代码中设置符号系统属性,如下所示。

import arcpy
# Use the GetParameterInfo function to access tool parameters
params = arcpy.GetParameterInfo()
infc = params[0]
outfc = params[1]
# Copy features
arcpy.management.CopyFeatures(infc.valueAsText, outfc.valueAsText)
# Apply symbology to the copied features
outfc.symbology = "C:/Tools/Extractor/ToolData/polygon.lyrx"

通过定义字符串 JSON 制图信息模型 (CIM)Esri Web 地图规范对象并将其传递到 SetParameterSymbology 函数的符号系统参数中,可以将符号系统保留在脚本代码中。这使得用户无需在工具箱中包含 .lyrx 文件。JSON 字符串必须以 JSONRENDERER=JSONCIMDEF=JSONCLASSDEF= 开头,具体取决于对象和方案的类型。可通过多个选项来获取对象的 JSON 字符串。

CIM 方案符号系统

图层 (.lyrx) 文件将以 JSON 格式存储 CIM 内容信息,并且可以使用文本编辑器将其打开。以下示例显示了包含 4 个图层的图层文件的经修改 JSON 表示,其中带有表示省略部分的椭圆形 (...)。

注:

请注意,.lyrx 文件可以存储多个图层和图层组的符号系统,因此无法在 SetParameterSymbology 中直接使用整个 JSON 对象。各个图层对象将在 JSON CIMLayerDocumentlayerDefinitions 键下方列出。

{
  "type" : "CIMLayerDocument",
  "version" : "2.6.0",
  "build" : 23961,
  "layers" : [
    "CIMPATH=map/samplepoly.xml",
    "CIMPATH=map/samplepoint.xml",
    "CIMPATH=map/sampleline.xml",
    "CIMPATH=map/sampleraster.xml"
  ],
  "layerDefinitions" : [
    {
      "type" : "CIMFeatureLayer",
      "name" : "SamplePolygon",
      ...
      "renderer" : {
        ...
      }
    },
    {
      "type" : "CIMFeatureLayer",
      "name" : "SampleLine",
      ...
      "renderer" : {
        ...
      }
    },
    {
      "type" : "CIMFeatureLayer",
      "name" : "SamplePoint",
      ...
      "renderer" : {
        ...
      }
    },
    {
      "type" : "CIMRasterLayer",
      "name" : "SampleRaster",
      ...
      "colorizer" : {

        ...
      }
    }
  ],
  ...
}

单个图层的 JSON CIM 定义是该图层类型的包含括号内的所有内容,例如 CIMFeatureLayerCIMRasterLayer(包括省略部分)。每个图层对象都包含多个其他根级别属性以及多个嵌套对象,其中包括描述该图层符号系统的 CIM "renderer" 对象。请注意,对于栅格图层,相应的对象为 colorizer。以下示例显示了一个简单线图层的完整 JSON CIM 渲染器对象。

{
  "type" : "CIMSimpleRenderer",
  "patch" : "Default",
  "symbol" : {
    "type" : "CIMSymbolReference",
    "symbol" : {
      "type" : "CIMLineSymbol",
      "symbolLayers" : [
        {
          "type" : "CIMSolidStroke",
          "enable" : true,
          "capStyle" : "Round",
          "joinStyle" : "Round",
          "lineStyle3D" : "Strip",
          "miterLimit" : 10,
          "width" : 1,
          "color" : {
            "type" : "CIMRGBColor",
            "values" : [
              255,
              0,
              0,
              100
            ]
          }
        }
      ]
    }
  }
}

向量或栅格图层的 JSON CIM 对象可以通过 JSONCIMDEF= 全部与 SetParameterSymbology 一起使用,或者通过 JSONRENDERER= 仅传递 renderer 对象。有关 CIM 对象规范的完整列表可在 CIM 规范的类型页面下方找到。

注:

colorizer 对象不能通过 JSONRENDERER= 进行传递。

Web 地图方案符号系统

注:
请注意,CIM 规范适用于 ArcGIS Pro,而 Web 地图规范适用于 ArcGIS Online。CIM 和 Web 地图规范均为跨平台规范,但两者之间的转换可能会产生损耗。因此,建议使用 CIM 规范以在 ArcGIS Pro 中获得最佳效果。

Web 地图将根据 Web 地图规范以 JSON 格式存储内容信息。可以使用 ArcGIS Online 通过以下方式从托管在 ArcGIS REST API 上的要素服务中获取 Web 地图渲染器对象,有关详细信息请参阅 ArcGIS REST API 要素服务

import json import requests
# endpoint URL queried to expect a JSON formatted response html = "https://services.arcgis.com/vHwtjnCAEWmDBZo5/arcgis/rest/services/My_Hosted_Feature/FeatureServer/0?f=json"
# Obtain JSON response object with requests.get() response = requests.get(html, verify=False).json()
# Retrieve the renderer object nested within the response JSON jsonren = response["drawingInfo"]["renderer"]
# Dump renderer JSON to a string using json.dumps()
renderer = json.dumps(jsonren)

响应对象为 JSON Web 地图 layerDefinition。下面的示例显示了整个响应对象的简化表示。

注:

layerDefinition 不能全部用于 SetParameterSymbology。在以上示例中,将从响应 JSON 中检索 renderer 对象。

{
  "currentVersion": 10.7,
  "id": 0,
  "name": "TestPoly",
  "type": "Feature Layer",
  ...
  "drawingInfo": {
    "renderer": {
      ...
    },
    ...
  },
  ...
}

layerDefinition 对象包含多个其他根级别属性以及多个嵌套在其中的对象,其中包括含有 Web 地图 drawingInfo 对象的 Web 地图 renderer 对象。以下是用于简单面图层的完整 JSON Web 地图渲染器对象的示例。

{
  "type": "simple",  "symbol": {
    "type": "esriSFS",    "style": "esriSFSSolid",    "color": [      255,      0,      0,      255    ],    "outline": {
      "type": "esriSLS",      "style": "esriSLSSolid",      "color": [        110,        110,        110,        255      ],      "width": 0.7    }
  }
}

可将 Web 地图 renderer 对象传入具有 JSONRENDERER=SetParameterSymbology。有关 Web 地图渲染器规范的完整列表可在渲染器对象的 Web 地图规范页面上找到。

分类定义

Web 地图规范还支持使用 JSON 分类定义对象动态生成分类或唯一值渲染器。可将其传入具有 JSONCLASSDEF=SetParameterSymbology

设置输出符号系统

通过 symbology 属性或 SetParameterSymbology 函数设置符号系统时,只能将一个图层文件或 JSON 对象字符串与输出参数相关联。如果明确定义了输出,则只能有一个符号系统正常工作。但如果未明确定义输出结果会如何呢? 例如,您知道输出是一个要素类,但在运行工具之前您不知道它是包含点、折线还是面要素。图层文件和 JSON 对象依赖于几何类型,这意味着要符号化多种要素类型时不能只有一个符号系统。在本例中,需要具有三个图层文件或 JSON 对象,一种几何类型一个,并基于输出几何类型关联正确的符号系统。以下代码片段使用 symbology 属性对此进行了演示。

# Set the symbology of the output. 
output = self.params[1].value
if output:
    desc = arcpy.Describe(output)
    
    if desc.shapeType == "Polygon":
        self.params[2].symbology = "C:/Tools/Extractor/ToolData/polygon.lyrx"
    elif desc.shapeType == "Polyline":
        self.params[2].symbology = "C:/Tools/Extractor/ToolData/polyline.lyrx"
    else:
        self.params[2].symbology = "C:/Tools/Extractor/ToolData/point.lyrx"

上述脚本中的逻辑相对比较简单:测试几何(形状)类型并相应设置符号系统。即使具有更复杂的逻辑,模式也保持不变:

  • 创建一个将对各个可能的输出进行符号化的图层文件或 JSON 对象字符串。
  • 基于脚本中的逻辑,确定应使用的图层文件或 JSON 对象并使用参数的符号系统属性对其进行设置。

在脚本与 ToolValidator 类中设置符号系统

如果您熟悉 ToolValidator 类中的编程工具验证逻辑,则会发现上述代码片段可能会被重新编写以供在 updateParameters 方法中使用。事实上,如果只需引用一个图层文件或 JSON 对象,则应在脚本工具的属性中或在 initializeParameters 方法中执行此操作。但是如果需要为多个图层文件或 JSON 对象中的任意一个设置符号系统,则应在脚本工具中执行此操作。将此类逻辑置于 ToolValidator 类中会使您的代码由于具有与工具验证无关的逻辑而变得冗长,且在某些情况下,在执行工具之前您可能不知道要使用哪个图层文件。

脚本示例

下面的脚本将基于要素距波特兰市的公园的距离来创建要素。共有三个参数:输入要素、距离和输出要素。输出要素将被符号化以便在地图上可将其与其他要素(非默认符号系统内的对象,很难区分)区分开。由于输入要素可以是点、折线或面,因此需要三个图层文件。

此脚本还演示了多个可移植性的编码技巧。可移植性技巧用法如下:

  • 使用 __file__ 来检索脚本文件的完整路径
  • 使用 Python os 模块来创建数据的路径
  • 使用 CreateScratchName 函数来创建临时要素类

# ExtractData.py
# Description: Script that will extract features from an input layer within a 
#              specified distance from a park.
# Parameters:
#  0 - input features
#  1 - distance from parks (linear units)
#  2 - output feature class
import arcpy
import os
arcpy.env.overwriteOutput = True
# This tool uses a system folder with a Scripts and ToolData subfolder. 
# You can discover the pathname of this folder using the Python __file__
# attribute, which is the pathname to the script 
# (example: 'E:\examples\symbology\scripts\ExtractData.py'.)  You
# then use the toolSharePath variable to create paths to your 
# shapefile data and layer files ('E:\examples\symbology\ToolData\points.lyrx').
scriptPath = __file__
toolSharePath = os.path.dirname(os.path.dirname(scriptPath))
dataPath = os.path.join(toolSharePath, 'ToolData')
parkPath = os.path.join(dataPath, 'PortlandParks.shp')
pointLyrPath = os.path.join(dataPath, 'point.lyrx')
polygonLyrPath = os.path.join(dataPath, 'polygon.lyrx')
polylineLyrPath = os.path.join(dataPath, 'polyline.lyrx')
    
# Buffer the parks by the specified distance.  The output is a scratch
#  feature class in the same workspace as the output feature class
arcpy.SetProgressorLabel('Buffering parks ...')
scrname = arcpy.CreateScratchName('xxx', '', 'featureclass', 
                                  os.path.dirname(arcpy.GetParameterAsText(2)))
arcpy.Buffer_analysis(parkPath, scrname, arcpy.GetParameterAsText(1))
# Clip the defined layer with the buffered parks
arcpy.SetProgressorLabel('Clipping {} ...'.format(arcpy.GetParameterAsText(0)))
output = arcpy.Clip_analysis(arcpy.GetParameterAsText(0), scrname, 
                             arcpy.GetParameterAsText(2))
# Delete the intermediate dataset
try:
    arcpy.Delete_management(scrname)
except:
    pass
# Set the symbology of the output. 
params = arcpy.GetParameterInfo()
desc = arcpy.Describe(output)
if desc.shapeType == 'Polygon':
    params[2].symbology = polygonLyrPath
elif desc.shapeType == 'Polyline':
    params[2].symbology = polylineLyrPath
else:
    params[2].symbology = pointLyrPath