2. 圆弧插补基础实现

任务目标

实现二维平面圆弧插补算法,支持顺/逆时针方向,给定圆心、半径、起始角与终止角后,按固定步距角输出插补点序列,并验证所有插补点到圆心的距离与理论半径的误差在允许范围内。

实现方案

采用角度增量法:从起始角开始,按固定步距角逐步累加至终止角,每个角度对应一个插补点。顺逆时针通过角度增减方向区分。核心数据结构为圆弧参数结构体,核心函数为圆弧插补生成器与半径误差验证函数。

关键完整代码


#include <stdio.h>
#include <math.h>

#define PI 3.14159265358979323846

typedef struct {
    double cx, cy;      // 圆心坐标
    double r;           // 半径
    double start_angle; // 起始角(弧度)
    double end_angle;   // 终止角(弧度)
    int clockwise;      // 1=顺时针, 0=逆时针
} ArcParams;

// 圆弧插补:输出插补点,返回点数
int arc_interpolate(ArcParams arc, double step_angle, 
                    double *out_x, double *out_y, int max_points) {
    int n = 0;
    double angle = arc.start_angle;
    double total_angle;
    
    // 计算总角度(考虑跨0°情况)
    if (arc.clockwise) {
        total_angle = arc.start_angle - arc.end_angle;
        if (total_angle < 0) total_angle += 2 * PI;
    } else {
        total_angle = arc.end_angle - arc.start_angle;
        if (total_angle < 0) total_angle += 2 * PI;
    }
    
    int steps = (int)ceil(total_angle / step_angle);
    if (steps > max_points) steps = max_points;
    
    for (int i = 0; i <= steps && n < max_points; i++) {
        double current_angle = angle + (arc.clockwise ? -1 : 1) * i * step_angle;
        // 确保不超过终止角
        if (arc.clockwise) {
            if (current_angle < arc.end_angle - 1e-9) break;
        } else {
            if (current_angle > arc.end_angle + 1e-9) break;
        }
        out_x[n] = arc.cx + arc.r * cos(current_angle);
        out_y[n] = arc.cy + arc.r * sin(current_angle);
        n++;
    }
    return n;
}

// 验证半径误差:返回最大误差
double verify_radius_error(double *x, double *y, int n, 
                           double cx, double cy, double r) {
    double max_err = 0.0;
    for (int i = 0; i < n; i++) {
        double dist = sqrt((x[i]-cx)*(x[i]-cx) + (y[i]-cy)*(y[i]-cy));
        double err = fabs(dist - r);
        if (err > max_err) max_err = err;
    }
    return max_err;
}

int main() {
    // 示例:圆心(0,0),半径10,从0°到90°,逆时针,步距角5°
    ArcParams arc = {0, 0, 10, 0, PI/2, 0};
    double step_angle = 5.0 * PI / 180.0;  // 5°
    double x[100], y[100];
    
    int n = arc_interpolate(arc, step_angle, x, y, 100);
    
    printf("插补点数: %d\n", n);
    for (int i = 0; i < n; i++) {
        printf("P%d: (%.4f, %.4f)\n", i, x[i], y[i]);
    }
    
    double max_err = verify_radius_error(x, y, n, arc.cx, arc.cy, arc.r);
    printf("最大半径误差: %.6f\n", max_err);
    
    // 验证通过条件
    if (max_err < 1e-6) {
        printf("验证通过:所有插补点半径误差在允许范围内\n");
    } else {
        printf("验证失败:存在超差插补点\n");
    }
    return 0;
}

编译与运行


gcc -o arc_interp arc_interp.c -lm
./arc_interp

验证方法

程序输出每个插补点坐标及最大半径误差。判定通过条件:最大半径误差小于1e-6(即浮点计算精度范围内),且插补点数与理论计算一致(90°/5°+1=19个点)。可修改圆弧参数测试顺逆时针、跨0°边界、整圆等场景。

预期输出(示例)


插补点数: 19
P0: (10.0000, 0.0000)
P1: (9.9619, 0.8716)
...
P18: (0.0000, 10.0000)
最大半径误差: 0.000000
验证通过:所有插补点半径误差在允许范围内

说明:上述输出为基于代码逻辑的确定性预期结果,非实测数据。实际运行时浮点舍入可能导致最后一位微小差异,但不影响误差判定。