乐于分享
好东西不私藏

openclaw把GIS的直线边弧段

openclaw把GIS的直线边弧段
# -*- coding: utf-8 -*-"""线段转曲线工具 2 点直线转换为曲线(圆弧)"""import arcpyimport mathimport os输入输出input_fc = r"C:\Users\yl\Documents\ArcGIS\Projects\MyProject17\MyProject17.gdb\line"output_fc = r"C:\Users\yl\Documents\ArcGIS\Projects\MyProject17\MyProject17.gdb\k"曲线参数CURVE_HEIGHT = 200  曲线拱高(米),正值向上拱,负值向下拱print("=" 60)print("线段转曲线工具")print("=" 60)print("输入:%s" % input_fc)print("输出:%s" % output_fc)print("曲线拱高:%.1f % CURVE_HEIGHT)print()设置环境arcpy.env.overwriteOutput = True获取输入要素类信息desc = arcpy.Describe(input_fc)spatial_ref = desc.spatialReferenceprint("坐标系:%s" % spatial_ref.name)创建输出要素类print("\n创建输出要素类...")arcpy.management.CreateFeatureclass(    os.path.dirname(output_fc),    os.path.basename(output_fc),"POLYLINE",    spatial_reference=spatial_ref,    has_m="DISABLED",    has_z="DISABLED")print("[OK] 输出要素类已创建")复制字段print("\n复制字段结构...")input_fields = [f for in arcpy.ListFields(input_fc) if f.name not in ['Shape''OID''FID']]for field in input_fields:if field.type not in ['OID''Geometry']:        arcpy.management.AddField(output_fc, field.name, field.type, field.precision, field.scale, field.length)print("[OK] 字段已复制")转换线段到曲线def line_to_curve(start_pt, end_pt, height=CURVE_HEIGHT):"""将直线转换为圆弧曲线    参数:        start_pt: 起点 (arcpy.Point)        end_pt: 终点 (arcpy.Point)        height: 拱高(米)    返回:        arcpy.Polyline: 曲线几何    """    # 计算中点mid_x = (start_pt.X + end_pt.X) / 2mid_y = (start_pt.Y + end_pt.Y) / 2计算线段长度和方向dx = end_pt.X - start_pt.X    dy = end_pt.Y - start_pt.Y    length = math.sqrt(dx * dx + dy * dy)if length == 0:return None计算垂直方向的单位向量perp_x = -dy / length    perp_y = dx / length计算控制点(中点垂直偏移)control_x = mid_x + perp_x * height    control_y = mid_y + perp_y * height创建圆弧(使用三个点:起点、控制点、终点)# ArcGIS 中使用 densify  true curve    # 这里使用多段线近似圆弧生成圆弧上的点(使用二次贝塞尔曲线公式)num_points = 20  圆弧分段数points = arcpy.Array()for in range(num_points + 1):        t = i / num_points二次贝塞尔曲线公式# B(t) = (1-t)²*P0 + 2(1-t)*t*P1 + t²*P2x = (1-t)*** start_pt.X + 2*(1-t)*t * control_x + t*** end_pt.X        y = (1-t)*** start_pt.Y + 2*(1-t)*t * control_y + t*** end_pt.Y        pt = arcpy.Point(x, y)        points.add(pt)创建折线polyline = arcpy.Polyline(points, spatial_ref)return polyline处理要素print("\n开始转换...")insert_cursor = arcpy.da.InsertCursor(output_fc, ["SHAPE@"] + [f.name for in input_fields])count_total = 0count_success = 0with arcpy.da.SearchCursor(input_fc, ["SHAPE@""OID@"] + [f.name for in input_fields]) as search_cursor:for row in search_cursor:        count_total += 1geometry = row[0]        oid = row[1]        attributes = row[2:]try:处理每个部分new_parts = []for part in geometry:                points = [pt for pt in part if pt]if len(points) < 2:continue将每对相邻点转换为曲线curve_points = arcpy.Array()for in range(len(points) - 1):                    start_pt = points[i]                    end_pt = points[i + 1]转换为曲线curve = line_to_curve(start_pt, end_pt)if curve:添加曲线上的点(排除第一个点,避免重复)for j, pt in enumerate(curve.getPart(0)):if j > or i == 0:  第一段包含起点curve_points.add(pt)if curve_points.count > 1:                    new_parts.append(curve_points)if new_parts:创建新的折线if len(new_parts) == 1:                    new_geometry = arcpy.Polyline(new_parts[0], spatial_ref)else:                    new_geometry = arcpy.Polyline(arcpy.Array(new_parts), spatial_ref)插入新要素insert_cursor.insertRow([new_geometry] + list(attributes))                count_success += 1if count_success % 10 == 0:                    print("  已处理 %d 个要素..." % count_success)except Exception as e:            print("[警告要素 %d 处理失败:%s" % (oid, str(e)))del insert_cursorprint()print("=" 60)print("处理完成!")print("共处理 %d 个要素,成功 %d % (count_total, count_success))print("输出:%s" % output_fc)print("=" 60)