You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Python参数化代码以自动完成几何图形对齐?

几何图形对齐功能优化:修复除零错误并实现自动判断

需求说明

  • 实现几何图形对齐功能:当图形存在旋转时,将其主坐标轴与参考系XY轴平行(旋转角度归零);无旋转则不执行操作。
  • 现有代码可处理旋转后的图形,但在处理无旋转的坐标集时出现division by zero错误。

测试坐标集

旋转坐标集

X2_coordinate = [0.0, 0.87, 1.37, 1.87, 2.73, 3.6, 4.46, 4.96, 5.46, 4.6, 3.73, 2.87, 2.0, 1.5, 1.0, 0.5, 2.37, 3.23, 4.1]
Y2_coordinate = [0.0, 0.5, -0.37, -1.23, -0.73, -0.23, 0.27, -0.6, -1.46, -1.96, -2.46, -2.96, -3.46, -2.6, -1.73, -0.87, -2.1, -1.6, -1.1]

无旋转坐标集

X2_coordinate = [0, 0, 1, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 3, 2, 1, 3, 3, 3]
Y2_coordinate = [0, 1, 1, 1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0, 0, 0, 1, 2, 3]

现有代码核心问题

  1. 除零错误:计算线段角度时使用arctan((p1.x - p2.x)/(p1.y - p2.y)),当两点Y坐标相等时,分母为0触发异常。
  2. 无自动判断:无论图形是否旋转,都会执行旋转操作,无意义且可能引入误差。
  3. 耦合度高:代码未封装为可复用的函数,无法灵活调用。

优化后的代码

from sbNative.debugtools import log, cleanRepr
import math
import matplotlib.pyplot as plt

def rotate(origin, point, angle):
    """将点绕原点逆时针旋转指定弧度角度"""
    qx = origin.x + math.cos(angle) * (point.x - origin.x) - math.sin(angle) * (point.y - origin.y)
    qy = origin.y + math.sin(angle) * (point.x - origin.x) + math.cos(angle) * (point.y - origin.y)
    return qx, qy

@cleanRepr()
class Point:
    def __init__(self, *pts):
        pt_names = "xyzw"
        for n, v in zip(pt_names[:len(pts)], pts):
            self.__setattr__(n, v)

def align_geometry(X_coords, Y_coords, angle_tolerance=0.1):
    """
    对齐几何图形:自动判断是否需要旋转,将主坐标轴与XY轴平行
    参数:
        X_coords: X坐标列表
        Y_coords: Y坐标列表
        angle_tolerance: 角度容差(弧度),判断是否接近坐标轴方向
    返回:
        对齐后的X、Y坐标列表
    """
    coordinates = list(zip(X_coords, Y_coords))
    points = [Point(*coors) for coors in coordinates]
    point_pairs = [(points[i], points[i+1]) for i in range(len(points)-1)] + [(points[-1], points[0])]

    # 使用arctan2避免除零错误,计算每条线段的绝对角度(归一化到[0, π/2])
    angles = []
    for p1, p2 in point_pairs:
        dx = p2.x - p1.x
        dy = p2.y - p1.y
        angle = abs(math.atan2(dy, dx))
        # 将角度归一到0到π/2区间,统一处理水平/垂直方向的等价性
        if angle > math.pi/2:
            angle = math.pi - angle
        angles.append(angle)

    # 按容差分组统计角度频率,避免浮点精度干扰
    angle_counts = {}
    for angle in angles:
        rounded_angle = round(angle / angle_tolerance) * angle_tolerance
        angle_counts[rounded_angle] = angle_counts.get(rounded_angle, 0) + 1

    if not angle_counts:
        return X_coords, Y_coords

    # 获取出现频率最高的主方向角度
    main_angle = max(angle_counts, key=angle_counts.get)

    # 判断是否需要旋转:主角度是否远离坐标轴方向
    need_rotation = not (
        abs(main_angle) < angle_tolerance or 
        abs(main_angle - math.pi/2) < angle_tolerance
    )

    if not need_rotation:
        log("图形已对齐,无需旋转")
        return X_coords, Y_coords

    # 计算最优旋转角度:选择最小幅度将主方向对齐到坐标轴
    rotation_angle = -main_angle if main_angle < math.pi/4 else math.pi/2 - main_angle

    # 执行旋转操作
    origin = Point(0, 0)
    new_points = [rotate(origin, p, rotation_angle) for p in points]
    X_aligned, Y_aligned = zip(*new_points)

    # 保留一位小数,统一输出精度
    X_aligned = [round(num, 1) for num in X_aligned]
    Y_aligned = [round(num, 1) for num in Y_aligned]

    log(f"完成图形对齐,旋转角度:{math.degrees(rotation_angle):.1f}度")
    return X_aligned, Y_aligned

# 示例调用
if __name__ == "__main__":
    # 测试旋转坐标集
    X_rot = [0.0, 0.87, 1.37, 1.87, 2.73, 3.6, 4.46, 4.96, 5.46, 4.6, 3.73, 2.87, 2.0, 1.5, 1.0, 0.5, 2.37, 3.23, 4.1]
    Y_rot = [0.0, 0.5, -0.37, -1.23, -0.73, -0.23, 0.27, -0.6, -1.46, -1.96, -2.46, -2.96, -3.46, -2.6, -1.73, -0.87, -2.1, -1.6, -1.1]
    X_rot_aligned, Y_rot_aligned = align_geometry(X_rot, Y_rot)
    
    plt.scatter(X_rot_aligned, Y_rot_aligned)
    plt.title("旋转图形对齐结果")
    plt.show()

    # 测试无旋转坐标集
    X_no_rot = [0, 0, 1, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 3, 2, 1, 3, 3, 3]
    Y_no_rot = [0, 1, 1, 1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0, 0, 0, 1, 2, 3]
    X_no_rot_aligned, Y_no_rot_aligned = align_geometry(X_no_rot, Y_no_rot)
    
    plt.scatter(X_no_rot_aligned, Y_no_rot_aligned)
    plt.title("无旋转图形结果")
    plt.show()

关键优化细节

  1. 修复除零错误:用math.atan2(dy, dx)替代除法式的角度计算,直接支持水平/垂直线段的角度求解。
  2. 自动旋转判断:通过对比主方向角度与坐标轴的偏差,自动跳过无需旋转的场景。
  3. 参数化封装:将对齐逻辑封装为独立函数,支持自定义角度容差,提升复用性。
  4. 浮点精度处理:按容差对角度分组统计,避免因浮点误差导致角度统计偏差。
  5. 最优旋转策略:选择最小旋转幅度将主方向对齐到坐标轴,减少不必要的计算误差。

内容的提问来源于stack exchange,提问作者Urvesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:21:58