前言
最近需要用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)
4 条评论
2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
你好,之前网站的文章不同步过来吗
没备份