上一篇中,我介绍如何通过ArcPy调用自定义或第三方工具,本节将介绍如果从利用ArcPy创建一个自定义的工具。

工具参数

在ArcGIS中,我们使用工具,这些工具都有参数,比如选择处理的数据,处理结果的保存路径等。ArcPy中使用arcpy.GetParameter(parameterIndex)来获取指定索引parameterIndex处的参数的信息,该方法返回的是一个object对象。此外还有一个函数arcpy.GetParameterAsText(parameterIndex),也是用来获取指定索引parameterIndex处的参数,但是从函数名可以看出,这个函数会将获取的参数以字符串的形式进行返回。

这两个函数都具有一个形参parameterIndex,这个形参是指参数的索引,从0开始。

编写脚本

下面我们来写一个工具,该工具用来将对点进行一个缓冲区分析,但是与ArcGIS中自带的不同,该缓冲的结果是正方形,即以点为中心,向四周做两个半径长度的正方形。工具中有三个参数:输入要素类,距离半径,输入位置。

首先接受参数:

  1. # 输入要素
  2. input_fs = arcpy.GetParameterAsText(0)
  3. # distance convert string to number
  4. distance_str = arcpy.GetParameterAsText(1)
  5. distance = float(distance_str)
  6. # output
  7. output_fs = arcpy.GetParameterAsText(2)

然后创建输出shapefile:

  1. output_dir = os.path.dirname(output_fs)
  2. output_name = os.path.basename(output_fs)
  3. arcpy.CreateFeatureclass_management(output_dir, output_name, "Polygon", spatial_reference=input_fs)

接着遍历原来的点图层,输出缓冲结果:

  1. with arcpy.da.InsertCursor(output_fs, ['SHAPE@']) as i_cur:
  2. with arcpy.da.SearchCursor(input_fs, ['SHAPE@']) as s_cur:
  3. for row in s_cur:
  4. point = row[0].firstPoint
  5. # buffer for the point, and return a polygon geometry
  6. point_buffer = buffer_point(point, distance)
  7. insert_row = [point_buffer]
  8. i_cur.insertRow(insert_row)

注意,里面的注释我都是使用的英文,而使用中文的地方,注释与代码间是相隔了一个空行。这是因为,如果声明文件编码为utf8,如果没有空行的存在,在运行工具的时候,可能会得到“Name xxx is not defined”的错误;如果声明编码为cp936(即:GB2312),则不需要如此。

现在,核心代码已经全部完成了,接下来需要将其变为工具。

创建工具

ArcGIS中每个工具都是存在于工具箱之中,为了将该脚本变为工具使用,需要先选择一个工具箱,这里选择上一节中定义的MyTools.tbx工具箱。在工具箱上右键,选择添加|脚本(如图 1所示),打开脚本的添加界面(如图2所示),这里我们为该脚本工具命名为RectBuffer。
add-script.png
图 1 工具箱右键菜单
add-script-1.png
图 2 添加脚本(第一步)

点击下一步进入添加脚本第二步,这里我们需要选择脚本的路径(如图 3所示)。
add-script-2.png
图 3 添加脚本(第二步)
点击下一步,接下来,我们需要为该脚本工具设置参数了。该脚本工具有三个参数,分别为输入数据(限制为点图层),缓冲的半径距离(这里做的比较简单,将单位设置为与输入数据的坐标单位一样即可,数字)以及输出文件。

现在我们先将三个参数输入进去,其数据类型依次为:要素图层、双精度和要素类。为什么第一个参数类型选择的是要素图层呢?因为如果这个图层已经在ArcGIS中打开了,我们可以通过下来菜单选择,而不必再选择去路径了。

接下来,我们选择输入数据,在下方的过滤器中选择要素类,然后将其限制为点图层(如图 4所示)。
config-parameter1.png
图 4 添加脚本(第三步,限制输入要素类型)
由于输出结果是向我们的磁盘上写入文件,而不是读取文件,因此我们还需要将出输出位置的方向设置为Output(如图 5所示)。
config-parameter2.png
图 5 添加脚本(第四步,更改输出要素的方向)
接下来点击完成,即可将该脚本封装为工具,双击RectBuffer工具,其界面如图 6所示。
script-tool.png
图 6 RectBuffer工具
分别进行5度,10度的缓冲(元素数据是WGS84坐标系,因此缓冲单位为度),结果如图 7所示。
rect-buffer-result.png
图 7 RectBuffer结果

进阶

添加消息输出

ArcPy脚本中的print函数的执行结果并不会显示在工具运行时的对话框中,但我们想在知道程序运行到了哪一步怎么办呢?ArcPy提供了一些函数来实现这些功能,其中常用的是下面三个:

  1. AddMessage:向工具对话框、历史记录和 Python 窗口显示一条消息;
  2. AddWarning:向工具对话框、历史记录和 Python 窗口显示一条警告;
  3. AddError:向工具对话框、历史记录和 Python 窗口显示一条错误;

现在向脚本中添加以下三行代码,结果如图 8所示。在图7中,我们可以看到工具对话框中显示了这三条信息,并且还有了颜色进行区分。

  1. arcpy.AddMessage(u"这是一条普通消息")
  2. arcpy.AddWarning(u"这是一条警告消息")
  3. arcpy.AddError(u"这是一条错误消息")

arcpy-addmsg.png
图 8 输出消息示例

添加进度条

另一个用于显示处理进度的是进度条,进度条的使用要复杂些,先看Demo:

  1. arcpy.SetProgressor("step", "Title", 0, 100, 1)
  2. time.sleep(5)
  3. for i in range(1, 100):
  4. arcpy.SetProgressorLabel("Loading {0}...".format(i))
  5. time.sleep(1)
  6. arcpy.SetProgressorPosition()
  7. arcpy.ResetProgressor()

这是使用的time.sleep函数来模拟数据的处理,其效果如图9所示:
进度条1.png
a 初始化显示标注
进度条效果.png
b 处理过程中
图 9 进度条

使用过程

  1. 设置进度条

使用进度条前要先使用arcpy.SetProgressor声明一个进度条,arcpy.SetProgressor的定义如下:

  1. SetProgressor(type, {message}, {min_range}, {max_range}, {step_value})
参数 说明 数据类型
type 进度条类型(默认或步骤)。default —进度条连续向后或向前移动;step —进度条显示完成百分比。(默认值为 default) String
message 进度条标注。默认情况下没有标注。 String
min_range 进度条的开始值。默认值为 0。(默认值为 0) Integer
max_range 进度条的结束值。默认值为 100。(默认值为 100) Integer
step_value 用于更新进度条的进度条步长间隔。(默认值为 1) Integer

引用自:https://desktop.arcgis.com/zh-cn/arcmap/10.3/analyze/arcpy-functions/setprogressor.htm

  1. 更新进度条

更新进度条则需要使用arcpy.SetProgressorPosition函数,其定义如下:

  1. SetProgressorPosition({position})

参数position用来设置进度条的进度,其不是百分比,百分比是根据(position-min_range)/max_range计算的。如果不指定position,则会在上次的position(初始为min_range)基础上递增step_value

  1. 重置进度条

当进度条达到100%后,我们可能想为下一个操作设置进度条,这时候,我们需要使用arcpy.ResetProgressor函数。如果是最后处理完成, 我们也可以不用重置进度条。