4. 圆弧插补

任务目标

实现第一象限逆时针圆弧的逐点比较法插补。给定圆心、半径、起点与终点(均在第一象限且位于圆弧上),程序逐点计算插补坐标,输出全部插补点,并绘制圆弧轨迹与理想圆弧进行对比。

实现原理

逐点比较法每步通过偏差判别决定进给方向。对于第一象限逆圆,偏差函数为:

F = x² + y² − R²

  • F ≥ 0:向 −X 方向进给一步(x = x − 1),新偏差 F = F − 2x + 1
  • F < 0:向 +Y 方向进给一步(y = y + 1),新偏差 F = F + 2y + 1

从起点开始迭代,直到到达终点坐标为止。

完整代码

import matplotlib.pyplot as plt
import numpy as np

def bresenham_circle_interp(x0, y0, R, x_start, y_start, x_end, y_end):
    """
    第一象限逆圆逐点比较法插补
    输入:圆心(x0,y0),半径R,起点(x_start,y_start),终点(x_end,y_end)
    返回:插补点列表 [(x, y), ...]
    """
    # 将坐标平移到圆心坐标系
    x = x_start - x0
    y = y_start - y0
    xe = x_end - x0
    ye = y_end - y0

    points = [(x + x0, y + y0)]  # 保存原始坐标系下的点

    # 偏差初值
    F = x * x + y * y - R * R

    # 迭代直到到达终点
    while True:
        if F >= 0:
            # 向 -X 方向进给
            x -= 1
            F = F - 2 * x - 1  # 注意:x已更新,用新x计算
        else:
            # 向 +Y 方向进给
            y += 1
            F = F + 2 * y + 1  # 注意:y已更新,用新y计算

        points.append((x + x0, y + y0))

        # 到达终点判断
        if x == xe and y == ye:
            break

    return points

# ========== 参数设置 ==========
x0, y0 = 0, 0        # 圆心
R = 10               # 半径
x_start, y_start = 10, 0   # 起点 (R, 0)
x_end, y_end = 0, 10       # 终点 (0, R)

# ========== 执行插补 ==========
interp_points = bresenham_circle_interp(x0, y0, R, x_start, y_start, x_end, y_end)

# ========== 输出插补点 ==========
print("插补点坐标:")
for i, (px, py) in enumerate(interp_points):
    print(f"第{i:2d}步: ({px:3d}, {py:3d})")

# ========== 绘制结果 ==========
xs = [p[0] for p in interp_points]
ys = [p[1] for p in interp_points]

# 理想圆弧(用于对比)
theta = np.linspace(0, np.pi / 2, 100)
ideal_x = x0 + R * np.cos(theta)
ideal_y = y0 + R * np.sin(theta)

plt.figure(figsize=(6, 6))
plt.plot(ideal_x, ideal_y, 'b-', linewidth=1, label='理想圆弧')
plt.plot(xs, ys, 'r.-', markersize=4, linewidth=0.8, label='插补轨迹')
plt.plot(x0, y0, 'k+', markersize=10, label='圆心')
plt.plot(x_start, y_start, 'go', label='起点')
plt.plot(x_end, y_end, 'mo', label='终点')
plt.gca().set_aspect('equal')
plt.grid(True, linestyle='--', alpha=0.6)
plt.legend()
plt.title('第一象限逆圆逐点比较法插补')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()

运行方式

  1. 安装依赖:pip install matplotlib numpy
  2. 将代码保存为 circle_interp.py,运行 python circle_interp.py

验证方法

  • 程序输出从 (10, 0) 到 (0, 10) 的整数坐标点序列,首点为起点,末点为终点。
  • 每个输出点应满足 x² + y² 接近 100(偏差不超过进给步长带来的最大误差约 1.5)。
  • 图中红色插补轨迹应沿蓝色理想圆弧从起点逆时针走向终点,且轨迹点全部位于第一象限。
  • 可通过修改 x_start, y_start, x_end, y_end 验证其他第一象限逆圆弧(需保证起点终点在半径为 R 的圆上)。

预期输出(前5步)

第 0步: (10,  0)
第 1步: ( 9,  0)
第 2步: ( 9,  1)
第 3步: ( 8,  1)
第 4步: ( 8,  2)
第 5步: ( 7,  2)
...

常见问题

  • 偏差更新公式中的符号:代码中先更新坐标再计算新偏差,因此 F = F − 2x − 1 中的 x 是更新后的值,与理论推导中先算偏差再进给的写法等价。
  • 终点判断:使用精确坐标相等判断。若终点坐标非整数或不在圆上,需改用误差容限判断。
  • 适用范围:本实现仅针对第一象限逆圆。其他象限或顺圆需修改进给方向与偏差更新规则。