import arcpy
import os
import collections
class Toolbox(object):
def __init__(self):
"""定义工具箱名称"""
self.label = "界址点线提取工具"
self.alias = ""
self.tools = [ExtractBoundaryPointsAndLines]
class ExtractBoundaryPointsAndLines(object):
def __init__(self):
"""初始化工具"""
self.label = "提取界址点和界址线"
self.description = "从输入面要素中提取所有界址点(不重复)和界址线(考虑空洞)"
self.canRunInBackground = False
def getParameterInfo(self):
"""定义参数"""
params = []
# 输入面要素参数
input_polygon = arcpy.Parameter(
name="input_polygon",
displayName="输入面要素",
datatype="DEFeatureClass",
parameterType="Required",
direction="Input")
input_polygon.filter.list = ["Polygon"]
params.append(input_polygon)
# 输出点要素参数
output_points = arcpy.Parameter(
name="output_points",
displayName="输出界址点要素",
datatype="DEFeatureClass",
parameterType="Required",
direction="Output")
params.append(output_points)
# 输出线要素参数
output_lines = arcpy.Parameter(
name="output_lines",
displayName="输出界址线要素",
datatype="DEFeatureClass",
parameterType="Required",
direction="Output")
params.append(output_lines)
# 唯一ID字段参数(可选)
id_field = arcpy.Parameter(
name="id_field",
displayName="唯一标识字段(可选)",
datatype="Field",
parameterType="Optional",
direction="Input")
id_field.parameterDependencies = [input_polygon.name]
params.append(id_field)
return params
def isLicensed(self):
"""设置工具是否可用"""
return True
def updateParameters(self, parameters):
"""根据用户输入动态修改参数"""
return
def updateMessages(self, parameters):
"""自定义消息"""
return
def execute(self, parameters, messages):
"""执行工具"""
try:
# 获取参数
input_polygon = parameters[0].valueAsText
output_points = parameters[1].valueAsText
output_lines = parameters[2].valueAsText
id_field = parameters[3].valueAsText if parameters[3].value else None
# 创建输出要素类
spatial_ref = arcpy.Describe(input_polygon).spatialReference
# 创建界址点要素类
arcpy.CreateFeatureclass_management(
out_path=os.path.dirname(output_points),
out_name=os.path.basename(output_points),
geometry_type="POINT",
spatial_reference=spatial_ref)
# 创建界址线要素类
arcpy.CreateFeatureclass_management(
out_path=os.path.dirname(output_lines),
out_name=os.path.basename(output_lines),
geometry_type="POLYLINE",
spatial_reference=spatial_ref)
# 添加字段到界址点要素类
arcpy.AddField_management(output_points, "JID", "TEXT", field_length=20) # 界址点编号
arcpy.AddField_management(output_points, "X", "DOUBLE") # X坐标
arcpy.AddField_management(output_points, "Y", "DOUBLE") # Y坐标
if id_field:
arcpy.AddField_management(output_points, "POLY_ID", "TEXT", field_length=50) # 面要素ID
# 添加字段到界址线要素类
arcpy.AddField_management(output_lines, "LINE_ID", "TEXT", field_length=20) # 界址线编号
if id_field:
arcpy.AddField_management(output_lines, "POLY_ID", "TEXT", field_length=50) # 面要素ID
arcpy.AddField_management(output_lines, "IS_HOLE", "SHORT") # 是否为空洞边界
# 定义字段列表
point_fields = ["SHAPE@", "JID", "X", "Y"]
line_fields = ["SHAPE@", "LINE_ID"]
if id_field:
point_fields.append("POLY_ID")
line_fields.append("POLY_ID")
line_fields.append("IS_HOLE")
# 使用字典存储所有点,确保不重复
all_points = collections.OrderedDict()
point_counter = 1
# 创建插入游标
with arcpy.da.InsertCursor(output_points, point_fields) as point_cursor, \
arcpy.da.InsertCursor(output_lines, line_fields) as line_cursor:
# 使用搜索游标遍历输入面要素
with arcpy.da.SearchCursor(input_polygon, ["SHAPE@", id_field] if id_field else ["SHAPE@"]) as poly_cursor:
for row in poly_cursor:
polygon = row[0]
fid = row[1] if id_field else None
# 处理外边界和空洞
part_index = 0
for part in polygon:
# 创建线要素的顶点数组
line_array = arcpy.Array()
part_points = []
# 遍历当前部分的每个点
for pnt in part:
if pnt:
# 检查点是否已存在
point_key = (round(pnt.X, 6), round(pnt.Y, 6))
if point_key not in all_points:
all_points[point_key] = {
"point": pnt,
"jid": f"J{point_counter}",
"x": pnt.X,
"y": pnt.Y
}
point_counter += 1
# 添加点到线数组
line_array.add(pnt)
part_points.append(pnt)
# 创建线几何对象
if len(part_points) > 1:
line = arcpy.Polyline(line_array)
# 准备线要素记录
line_record = [line, f"L{part_index+1}"]
if id_field:
line_record.append(fid)
line_record.append(1 if part_index > 0 else 0) # 0=外边界, 1=空洞
# 插入线要素
line_cursor.insertRow(line_record)
part_index += 1
# 插入所有不重复的点
for point_data in all_points.values():
point_record = [
arcpy.PointGeometry(point_data["point"]),
point_data["jid"],
point_data["x"],
point_data["y"]
]
if id_field:
point_record.append(None) # 面要素ID在点要素中不适用
point_cursor.insertRow(point_record)
arcpy.AddMessage("界址点和界址线提取完成!")
except Exception as e:
arcpy.AddError(f"处理过程中出错: {str(e)}")
raise e
if __name__ == "__main__":
# 测试代码
tool = ExtractBoundaryPointsAndLines()
tool.execute(tool.getParameterInfo(), None)
优化错误
最新发布