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

如何实现无第三方依赖的n点B-spline曲线插值功能

三次均匀B样条曲线实现(无第三方依赖)

你需要的效果为三次均匀B样条插值效果,以下实现直接使用已推导完成的固定基函数系数,无需你掌握额外的微积分知识,直接调用即可。

Python版本实现

def spline(x_points, y_points, step=0.01):
    # 输入:x_points、y_points为控制点坐标列表,step为插值点密度,值越小曲线越平滑
    n = len(x_points)
    inter_points = []
    # 控制点少于3个直接返回原坐标
    if n < 3:
        return list(zip(x_points, y_points))
    
    # 三次B样条固定基函数,为已推导完成的系数,直接使用即可
    def calc_base(t):
        t2 = t * t
        t3 = t2 * t
        b0 = (-t3 + 3 * t2 - 3 * t + 1) / 6.0
        b1 = (3 * t3 - 6 * t2 + 4) / 6.0
        b2 = (-3 * t3 + 3 * t2 + 3 * t + 1) / 6.0
        b3 = t3 / 6.0
        return b0, b1, b2, b3

    # 扩展首尾虚拟控制点,保证曲线经过所有输入的控制点
    x_ext = [x_points[0]] * 2 + x_points + [x_points[-1]] * 2
    y_ext = [y_points[0]] * 2 + y_points + [y_points[-1]] * 2

    # 逐段计算插值点
    for i in range(len(x_ext) - 3):
        t = 0.0
        while t <= 1.0:
            b0, b1, b2, b3 = calc_base(t)
            x = b0 * x_ext[i] + b1 * x_ext[i+1] + b2 * x_ext[i+2] + b3 * x_ext[i+3]
            y = b0 * y_ext[i] + b1 * y_ext[i+1] + b2 * y_ext[i+2] + b3 * y_ext[i+3]
            inter_points.append((x, y))
            t += step
    return inter_points

# 调用示例
if __name__ == "__main__":
    # 替换为你自己的控制点坐标
    x_list = [10, 50, 100, 150, 200]
    y_list = [20, 80, 30, 90, 40]
    result_points = spline(x_list, y_list)
    # 调用你自己的绘制函数逐点绘制即可
    # for p in result_points:
    #     draw_ellipse(p[0], p[1], 2, 2)

Java版本实现

import java.util.ArrayList;
import java.util.List;

public class SplineGenerator {
    public static class Point {
        public float x;
        public float y;
        public Point(float x, float y) {
            this.x = x;
            this.y = y;
        }
    }

    public static List<Point> spline(float[] xPoints, float[] yPoints, float step) {
        int n = xPoints.length;
        List<Point> interPoints = new ArrayList<>();
        // 控制点少于3个直接返回原坐标
        if (n < 3) {
            for (int i = 0; i < n; i++) {
                interPoints.add(new Point(xPoints[i], yPoints[i]));
            }
            return interPoints;
        }

        // 扩展首尾虚拟控制点,保证曲线经过所有输入的控制点
        float[] xExt = new float[n + 4];
        float[] yExt = new float[n + 4];
        xExt[0] = xExt[1] = xPoints[0];
        yExt[0] = yExt[1] = yPoints[0];
        System.arraycopy(xPoints, 0, xExt, 2, n);
        System.arraycopy(yPoints, 0, yExt, 2, n);
        xExt[n+2] = xExt[n+3] = xPoints[n-1];
        yExt[n+2] = yExt[n+3] = yPoints[n-1];

        // 逐段计算插值点
        for (int i = 0; i < xExt.length - 3; i++) {
            float t = 0f;
            while (t <= 1f) {
                float t2 = t * t;
                float t3 = t2 * t;
                float b0 = (-t3 + 3*t2 - 3*t + 1) / 6f;
                float b1 = (3*t3 - 6*t2 + 4) / 6f;
                float b2 = (-3*t3 + 3*t2 + 3*t + 1) / 6f;
                float b3 = t3 / 6f;
                float x = b0 * xExt[i] + b1 * xExt[i+1] + b2 * xExt[i+2] + b3 * xExt[i+3];
                float y = b0 * yExt[i] + b1 * yExt[i+1] + b2 * yExt[i+2] + b3 * yExt[i+3];
                interPoints.add(new Point(x, y));
                t += step;
            }
        }
        return interPoints;
    }

    // 调用示例
    public static void main(String[] args) {
        float[] x = {10, 50, 100, 150, 200};
        float[] y = {20, 80, 30, 90, 40};
        List<Point> resultPoints = spline(x, y, 0.01f);
        // 调用你自己的绘制函数逐点绘制即可
        // for (Point p : resultPoints) {
        //     draw_ellipse(p.x, p.y, 2, 2);
        // }
    }
}

注意事项

  • 所有代码均使用基础语法实现,没有依赖任何第三方库或封装好的样条相关函数
  • step参数可根据需求调整:如果需要更高的绘制性能,可将step调大到0.05~0.1;如果需要更平滑的曲线效果,可调小到0.005
  • 生成的插值点列表直接遍历调用你已有的点绘制函数,即可得到和示例一致的效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 16:39:02