2. 圆弧插补基础实现

任务目标

实现二维平面圆弧插补算法,支持顺时针(CW)与逆时针(CCW)方向,输入圆心、半径、起始角与终止角,输出离散插补点,并验证所有插补点到圆心的距离(半径)保持恒定。

实现思路

采用角度增量法:将圆弧按固定角度步长Δθ离散化,从起始角逐步累加至终止角,每个角度对应一个插补点。方向由direction参数控制(1为CCW,-1为CW)。核心公式为:

x = cx + r·cos(θ)
y = cy + r·sin(θ)

完整代码

import math

def arc_interpolate(cx, cy, r, start_angle, end_angle, direction=1, step_angle=0.05):
    """
    圆弧插补:角度增量法
    :param cx, cy: 圆心坐标
    :param r: 圆弧半径
    :param start_angle: 起始角(弧度)
    :param end_angle: 终止角(弧度)
    :param direction: 1=逆时针(CCW), -1=顺时针(CW)
    :param step_angle: 插补步长(弧度)
    :return: 插补点列表 [(x1,y1), (x2,y2), ...]
    """
    # 计算总角度增量(带方向)
    delta = (end_angle - start_angle) * direction
    # 归一化到 [-2π, 2π],取最短路径
    delta = math.fmod(delta, 2 * math.pi)
    if delta == 0:
        delta = 2 * math.pi * direction  # 整圆

    # 确定步数(向上取整保证覆盖终点)
    steps = max(1, int(math.ceil(abs(delta) / step_angle)))
    actual_step = delta / steps  # 实际步长(带方向)

    points = []
    for i in range(steps + 1):
        theta = start_angle + i * actual_step
        x = cx + r * math.cos(theta)
        y = cy + r * math.sin(theta)
        points.append((round(x, 6), round(y, 6)))
    return points

def verify_radius(points, cx, cy, r, tolerance=1e-4):
    """验证所有插补点到圆心距离是否恒等于半径"""
    max_dev = 0.0
    for (x, y) in points:
        dist = math.sqrt((x - cx) ** 2 + (y - cy) ** 2)
        dev = abs(dist - r)
        max_dev = max(max_dev, dev)
    return max_dev < tolerance, max_dev

# ========== 最小验证闭环 ==========
if __name__ == "__main__":
    # 测试1:逆时针90°圆弧(从0°到90°)
    cx, cy, r = 0.0, 0.0, 10.0
    pts_ccw = arc_interpolate(cx, cy, r, 0, math.pi / 2, direction=1)
    ok1, dev1 = verify_radius(pts_ccw, cx, cy, r)
    print(f"CCW 90°: 点数={len(pts_ccw)}, 半径最大偏差={dev1:.2e}, 通过={ok1}")

    # 测试2:顺时针90°圆弧(从90°到0°)
    pts_cw = arc_interpolate(cx, cy, r, math.pi / 2, 0, direction=-1)
    ok2, dev2 = verify_radius(pts_cw, cx, cy, r)
    print(f"CW 90°: 点数={len(pts_cw)}, 半径最大偏差={dev2:.2e}, 通过={ok2}")

    # 测试3:整圆(起点=终点)
    pts_full = arc_interpolate(cx, cy, r, 0, 0, direction=1)
    ok3, dev3 = verify_radius(pts_full, cx, cy, r)
    print(f"整圆CCW: 点数={len(pts_full)}, 半径最大偏差={dev3:.2e}, 通过={ok3}")

    # 打印前5个CCW插补点供观察
    print("\nCCW前5个插补点:")
    for p in pts_ccw[:5]:
        print(f"  ({p[0]:.4f}, {p[1]:.4f})")

运行与验证

运行方式:直接执行python arc_interp.py(将上述代码保存为该文件名)。

通过条件:控制台输出中三个测试的通过=True,且半径最大偏差均小于1e-4。该偏差仅来源于浮点舍入与round(x,6)的截断误差,证明插补点严格落在目标圆弧上。

关键说明

  • 方向处理:direction=1时角度递增(CCW),-1时角度递减(CW)。delta的计算方式保证无论起止角大小,始终沿指定方向走最短弧。
  • 整圆支持:当起止角相同时,delta被设为2π·direction,实现完整圆周插补。
  • 步长自适应:实际步长actual_step由总角度除以步数得到,确保终点被精确覆盖,避免累积误差。
X Y O(0,0) CCW CW r=10 θ

上图展示了圆心在原点、半径10的圆弧插补示意:红色为逆时针(0°→90°),蓝色为顺时针(90°→0°),绿色虚线标注半径恒定。插补点(红点)均匀分布在圆弧上,验证了角度增量法的正确性。