1、问题驱动:
日常工作时常需要统计某县乡镇级三调各地类面积统计汇总,而国家下发的统计报表只到县市区级。乡镇级三调各地类面积只能自己手工统计。
调查监测三调地类面积统计往往需基于国家三调统计口径来统计,这是一个较复杂的规则,目前很多程序未能完全适用这一面积统计规则,地类面积统计要考虑城镇村用地范围(调查数据库中的“CZCDYD”层)而不是简单的对乡镇范围(调查数据库"XZQ"层)内进行地类统计。
基于上述原因,在学习arcpy两个月后,着手开发完成“三调地类面积统计(按行政区划)”工具。
2、工具功能描述:
Arcmap 10.2.2, 编程IDE环境 pycham 2023.3.3
为了便于调试,该工具核心程序放在*.py文件,工具的定义,参数获取在*.pyt文件中,通过from Statistics_By_Xzq import StatisticsForXZQ来调用*.py文件中的函数。
def execute(self, parameters, messages):
#该工具的源代码。
WkspaceS=parameters[0].values # parameters[0]:统计汇总的对象数据库文件集
Unit = parameters[1].valueAsText # parameters[1]:统计汇总单位
exlfolder = parameters[2].valueAsText # parameters[2]:统计汇总生产的文件存放文件夹路径
statistics_type = parameters[3].valueAsText # parameters[3]:统计汇总方式 如三调统计口径(城镇村不打开)
statistics_Names = []
for SatName in parameters[4].values: # parameters[4]:统计汇总的一级地类清单
statistics_Names.append(SatName[1:])
# arcpy.AddMessage(SatName[1:])
for wkspace in WkspaceS:
from Statistics_By_Xzq import StatisticsForXZQ
StatisticsForXZQ(wkspace, Unit, exlfolder, statistics_type, statistics_Names)
return
几个心得共享:
一是通过该工具的开发基本掌握了arcmap自定义工具基于程序的开发,特别是根据统计方式的改变,在统计地类列表的联动变化,使用了.hasBeenValidated属性,而不是网上资料里提到
的.altered 属性来联动(导致联动混乱,试试就知道了)。
def updateParameters(self, parameters):
# 在执行内部验证之前,请修改参数的值和属性。只要参数已更改,就会调用此方法。
stat_type=parameters[3]
stat_Names=parameters[4]
if parameters[3].hasBeenValidated==False:
if stat_type.value==u'按年末库三调土地利用现状分类统计(不按三调统计口径,13大类)':
stat_Names.values=['A湿地','B耕地','C园地','D林地','E草地','F商业服务业用地','G工矿用地','H住宅用地',
'I公共管理与公共服务用地','J特殊用地','K交通运输用地','L水利及水利设施用地','M其他']
elif stat_type.value ==u'按国标GT/T21010-2017土地利用现状分类统计(不按三调统计口径,12大类)':
stat_Names.values= ['A耕地','B园地','C林地','D草地','E商服用地','F工矿用地','G住宅用地',
'H公共管理与公共服务用地','I特殊用地','J交通运输用地','K水利及水利设施用地','L其他']
elif stat_type.value == u'按三调统计口径,仅统计城镇村内部(13大类)':
stat_Names.values = ['A湿地','B耕地','C园地','D林地','E草地','F商业服务业用地','G工矿用地','H住宅用地',
'I公共管理与公共服务用地','J特殊用地','K交通运输用地','L水利及水利设施用地','M其他']
elif stat_type.value ==u'按三调统计口径(城镇村不打开)' or stat_type.value ==u'按三调统计口径(城镇村打开)':
stat_Names.values = ['A湿地','B耕地','C园地','D林地','E草地','F城镇村工矿用地','G交通运输用地','H水工建筑','I水利及水利设施用地','J其他']
return
二是程序中文编码问题。较好的解决方式,在py程序文件第一行声明utf-8 编码,程序中重新加载sys,并再次设置sys.setdefaultencoding('utf8'),能够较好地解决。
# -*- coding:utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf8')
较好的解决方式在*.pyt文件中第一行声明必须为# -*- coding:GBK -*- 的GBK 编码,因为arcmap内不识别utf8编码,只能用GBK编码,但pyt文件和py文件两者中可以用不同编码来运行。另外,一个教训,在pyt文件中尽量不用转字符串 str函数,在开发过程中就因为在pyt文件中不经意间把一个参数用str()转了下,导致程序报编码错误,调试了一天才发现,问题在str()转换后编码不一定就是GBK编码。
UnicodeEncodeError: 'ascii' codec can't encode characters in position 14-16: ordinal not in range(128)
三是字段计算器的操作,特别是椭球面积!shape.geodesicArea!重新计算速度较慢,一个字段计算器语句中无法对两个字段同时操作。期间 用字段计算器函数编程提高运行速度,实测后发现没有明显提升,最终放弃。后续升级会考虑编程统计图斑面的椭球面积,抛弃字段计算器,看看能不能提升速度。
expression = "getClass(!DLBM!,!TBDLMJ!,!shape.geodesicArea!)"
codeblock = """
def getClass(bm,tbmj,shp_mj):
if bm in ['0303','0304','0306','0402','1105','1106','1108','0101','0102','0103','0201','0202','0203','0204',
'0301','0302','0305','0307','0401','0403','0404','1101','1102','1103