Loading... # 前言 最近需要用ArcGIS统计面内点的数量,搜索了一下,官方提供的工具为空间连接,挺好用,但是有一个缺点,一次只能计算一个点要素类,多个点要素类需要重复操作,比较繁琐。搜索一番网上没有较完美的解决方案,刚好最近在研究**Arcpy**,开始手搓轮子。 # 实现思路 Arcpy实现判定相交我想到的有两个方法,一个是官方的按位置选择图层,一个是遍历图层用Arcpy的Geometry类中的contains判定相交,此处使用的是前者,Arcpy调用官方工具也十分简单,在具体工具的运行键右边有个向下拉的部分,点击后选择复制成Python代码即可。 # 踩过的坑 ## 新添加的图层无法使用SelectLayerByLocation 根据官方介绍,需要使用**MakeFeatureLayer**创建要素图层  ## MakeFeatureLayer后编辑字段会影响源要素属性 先**CopyFeatures_management**将要素类复制到数据库,再使用**MakeFeatureLayer**创建要素图层,操作完成之后不需要重新导出 ## 组内要素的处理问题 `.split("\\")[-1]`从路径提取中的文件名 ## 要素类行数获取 `int(arcpy.management.GetCount("目标要素")[0])` # 成品代码 注释很详细,看不懂翻翻官方手册就行 ``` # -*- coding: utf-8 -*- """ Tool: 统计 Source Name: <File name> Version: Arcgis Pro 2.8 Author: Chao Usage: <Command syntax> Required Arguments: <point_parameter> <surface_parameter> Optional Arguments: <point_parameter2> <point_parameter3> Description: 统计面内多个点要素类的点数量 """ import arcpy def ScriptTool(point_parameter, surface_parameter, result_parameter): true_result_parameter = result_parameter # 根据绝对路径提取文件名 result_parameter = result_parameter.split("\\")[-1] # 复制图层并添加到图层列表,不使用MakeFeatureLayer将无法使用SelectLayerByLocation,不copy直接创建图层要素修改时源要素会变化 arcpy.CopyFeatures_management(surface_parameter, true_result_parameter) arcpy.management.MakeFeatureLayer(true_result_parameter, result_parameter) # 获取面文件行数,用于计算进度 task_total_num = int(arcpy.management.GetCount(surface_parameter)[0]) # 添加进度条 arcpy.SetProgressor("step", f"即将开始任务,共计{task_total_num}个面",0, task_total_num , 1) # 将点文件文本切割为列表 point_list = point_parameter.split(";") # 获取面要素已有字段 fieldList = arcpy.ListFields(result_parameter) field_name_List = [] for field in fieldList: field_name_List.append(field.name) for point_name in point_list: # 处理需要添加的字段 if "\\" in point_name: point_name_str = point_name.split("\\")[-1] else: point_name_str = point_name # 判断是否包含该字段,没有则添加 if point_name_str not in field_name_List: # 添加字段 arcpy.management.AddField(result_parameter, point_name_str, "LONG", None, None, None, point_name_str, "NULLABLE","NON_REQUIRED",'') # 添加游标,用于遍历面要素 updateCursor = arcpy.UpdateCursor(result_parameter) task_num = 1 for row in updateCursor: OBJECTID = row.getValue("OBJECTID") # 选择面要素的一个面,通过按位置选择工具选出与其相交的点要素 arcpy.management.SelectLayerByAttribute(result_parameter, "NEW_SELECTION", f"OBJECTID = {OBJECTID}", None) arcpy.management.SelectLayerByLocation(point_parameter, "INTERSECT", result_parameter, None, "NEW_SELECTION", "NOT_INVERT") # 修改进度条显示文字 arcpy.SetProgressorLabel(f"开始统计面,当前第{task_num}/{task_total_num}个面") # 修改进度条进度,向后跳动一个间隔数 arcpy.SetProgressorPosition() for point_name in point_list: num = int(arcpy.management.GetCount(point_name)[0]) if "\\" in point_name: point_name_str = point_name.split("\\")[-1] else: point_name_str = point_name # 为所选字段赋值 arcpy.management.CalculateField(result_parameter, point_name_str, str(num), "PYTHON3", '', "TEXT", "NO_ENFORCE_DOMAINS") task_num = task_num + 1 # 清除选择的要素 arcpy.management.SelectLayerByAttribute(result_parameter, "CLEAR_SELECTION") for point_name in point_list: arcpy.management.SelectLayerByAttribute(point_name, "CLEAR_SELECTION") arcpy.SetProgressorLabel(f"统计完成") return if __name__ == '__main__': # 获取脚本输入信息 # Getpoint_parameterAsText-将输入要素转换为文本,多选要素中间";"相隔 surface_parameter = arcpy.GetParameterAsText(0) point_parameter = arcpy.GetParameterAsText(1) result_parameter = arcpy.GetParameterAsText(2) ScriptTool(point_parameter, surface_parameter,result_parameter) ``` 脚本参数设置,如图  # 最后 工具实现的面内多点要素类的统计,统计信息以字段的形式储存在输出要素类中,另外实现了进度条信息的可视化。第二种实现方法在面和点的数量较少的时候运行估计会快些,~~暂时还没造轮子,留个坑~~。 # 补充第二种(contains)方法 脚本属性设置同第一种方法 ``` # -*- coding: utf-8 -*- """ Tool: 统计 Source Name: <File name> Version: Arcgis Pro 2.8 Author: Chao Usage: <Command syntax> Required Arguments: <point_parameter> <surface_parameter> Optional Arguments: <point_parameter2> <point_parameter3> Description: 统计面内多个点要素类的点数量 """ import arcpy def ScriptTool(point_parameter, surface_parameter, result_parameter): true_result_parameter = result_parameter # 根据绝对路径提取文件名 result_parameter = result_parameter.split("\\")[-1] # 复制图层并添加到图层列表,不使用MakeFeatureLayer将无法使用SelectLayerByLocation,不copy直接创建图层要素修改时源要素会变化 arcpy.CopyFeatures_management(surface_parameter, true_result_parameter) arcpy.management.MakeFeatureLayer(true_result_parameter, result_parameter) # 获取面文件行数,用于计算进度 task_total_num = int(arcpy.management.GetCount(surface_parameter)[0]) # 添加进度条 arcpy.SetProgressor("step", f"即将开始任务,共计{task_total_num}个面",0, task_total_num , 1) # 将点文件文本切割为列表 point_list = point_parameter.split(";") # 获取面要素已有字段 fieldList = arcpy.ListFields(result_parameter) field_name_List = [] for field in fieldList: field_name_List.append(field.name) for point_name in point_list: # 处理需要添加的字段 if "\\" in point_name: point_name_str = point_name.split("\\")[-1] else: point_name_str = point_name # 判断是否包含该字段,没有则添加 if point_name_str not in field_name_List: # 添加字段 arcpy.management.AddField(result_parameter, point_name_str, "LONG", None, None, None, point_name_str, "NULLABLE","NON_REQUIRED",'') # 添加游标,用于遍历面要素 updateCursor = arcpy.UpdateCursor(result_parameter) task_num = 1 for row in updateCursor: surface_geometry = row.shape # 修改进度条显示文字 arcpy.SetProgressorLabel(f"开始统计面,当前第{task_num}/{task_total_num}个面") # 修改进度条进度,向后跳动一个间隔数 arcpy.SetProgressorPosition() for point_name in point_list: pointCursor = arcpy.UpdateCursor(point_name) num = 0 for point_row in pointCursor: point_geometry =point_row.shape ## 判断点是否在面内 if (surface_geometry.contains(point_geometry)): num = num + 1 if "\\" in point_name: point_name_str = point_name.split("\\")[-1] else: point_name_str = point_name # 为所选字段赋值 row.setValue(point_name_str, str(num)) updateCursor.updateRow(row) del pointCursor task_num = task_num + 1 arcpy.SetProgressorLabel(f"统计完成") return if __name__ == '__main__': # 获取脚本输入信息 # Getpoint_parameterAsText-将输入要素转换为文本,多选要素中间";"相隔 surface_parameter = arcpy.GetParameterAsText(0) point_parameter = arcpy.GetParameterAsText(1) result_parameter = arcpy.GetParameterAsText(2) ScriptTool(point_parameter, surface_parameter,result_parameter) ``` 最后修改:2022 年 08 月 30 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,请随意赞赏