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

如何用Cubic Spline创建赛道?解决x非严格递增报错问题

解决三次样条绘制赛道时x非严格递增的问题

核心思路

三次样条要求自变量严格递增是因为它默认遵循“x为自变量、y为单值因变量”的逻辑,但赛道的x坐标必然存在非单调(比如弯道、回环)的情况,所以绕开x作为自变量,改用独立的参数化插值是最优解,完全满足仅用两组(x,y)数组的要求。


方案1:参数化三次样条(推荐)

将x和y都视为严格递增参数t的函数,t可以直接用原始坐标的索引值(天然严格递增),彻底避开x的单调性限制,还能保证赛道曲线的平滑性。

示例代码:

import numpy as np
from scipy.interpolate import make_interp_spline
import matplotlib.pyplot as plt

# 你的原始赛道坐标数组
x = np.array([1, 3, 2, 4, 5, 3])
y = np.array([2, 5, 3, 6, 4, 7])

# 创建严格递增的参数t(用索引即可)
t = np.arange(len(x))

# 分别生成x(t)和y(t)的三次样条插值函数
spl_x = make_interp_spline(t, x, k=3)
spl_y = make_interp_spline(t, y, k=3)

# 生成密集的t值,得到平滑的赛道坐标
t_dense = np.linspace(t.min(), t.max(), 1000)
x_smooth = spl_x(t_dense)
y_smooth = spl_y(t_dense)

# 绘制结果
plt.plot(x_smooth, y_smooth, label='平滑赛道')
plt.scatter(x, y, color='red', label='原始控制点')
plt.legend()
plt.show()

这个方法支持任意形状的赛道(包括回环、交叉),无需修改原始坐标数组,完全符合需求。


方案2:分段处理非单调区间

如果不想用参数化,可以将原始坐标按x的单调性拆分成多个子段,每个子段保证x严格递增(递减段反转即可),分别做三次样条后拼接结果。但这个方法需要手动判断分段,且衔接处的平滑性可能需要额外处理,适合简单赛道场景。

示例代码:

import numpy as np
from scipy.interpolate import CubicSpline
import matplotlib.pyplot as plt

x = np.array([1, 3, 2, 4, 5, 3])
y = np.array([2, 5, 3, 6, 4, 7])

# 手动拆分x单调的子段(示例按索引拆分)
segments = [(0, 2), (2, 5), (5, 6)]
x_smooth_all = []
y_smooth_all = []

for start, end in segments:
    x_seg = x[start:end]
    y_seg = y[start:end]
    # 确保当前段x严格递增,否则反转
    if not np.all(np.diff(x_seg) > 0):
        x_seg = x_seg[::-1]
        y_seg = y_seg[::-1]
    # 生成当前段的样条
    cs = CubicSpline(x_seg, y_seg)
    x_dense = np.linspace(x_seg.min(), x_seg.max(), 200)
    y_dense = cs(x_dense)
    x_smooth_all.extend(x_dense)
    y_smooth_all.extend(y_dense)

plt.plot(x_smooth_all, y_smooth_all, label='平滑赛道')
plt.scatter(x, y, color='red', label='原始控制点')
plt.legend()
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 05:22:32