使用Python Scipy的splprep生成3D样条后提取分段系数及绘图问题
解决方法
你通过splprep得到的tck元组包含三个核心元素:
t:节点向量c:B样条系数,三维场景下是包含x/y/z三个维度系数的列表k:样条阶数,你设置的k=3即为三次样条
方法1:单独绘制某一段样条
如果仅需要提取并绘制单段样条,不需要显式获取多项式系数,直接截取对应参数u的区间采样即可:
import numpy as np import scipy as sc from scipy.interpolate import splev import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 你的原有构建样条代码 x_points = np.linspace(0, 2*np.pi, 10) y_points = np.sin(x_points) z_points = np.cos(x_points) path = np.vstack([x_points, y_points, z_points]) tck, u = sc.interpolate.splprep(path, k=3, s=0) # 以提取最后一段样条为例,第i段对应的u区间为[u[i], u[i+1]] u_start = u[-2] u_end = u[-1] # 区间内采样100个点计算坐标 u_segment = np.linspace(u_start, u_end, 100) x_seg, y_seg, z_seg = splev(u_segment, tck) # 绘图 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # 可选:绘制原始点和完整样条做对比 ax.plot(x_points, y_points, z_points, 'ro', label='原始点') x_full, y_full, z_full = splev(np.linspace(0,1,200), tck) ax.plot(x_full, y_full, z_full, 'gray', alpha=0.3, label='完整样条') # 绘制提取的单段样条 ax.plot(x_seg, y_seg, z_seg, 'b', linewidth=2, label='最后一段样条') ax.legend() plt.show()
方法2:提取每段样条的幂基多项式系数
如果需要显式获取a + b*(x - xi) + c*(x - xi)^2 + d*(x - xi)^3形式的系数,可以通过BSpline转PPoly的方式实现:
from scipy.interpolate import BSpline, PPoly t, c, k = tck # 分别为x/y/z三个维度生成分段多项式对象 pp_x = PPoly.from_bspline(BSpline(t, c[0], k)) pp_y = PPoly.from_bspline(BSpline(t, c[1], k)) pp_z = PPoly.from_bspline(BSpline(t, c[2], k))
PPoly对象的c属性即为多项式系数,结构为(阶数, 分段数),三次样条每列对应一段的系数,顺序为[d, c, b, a],对应多项式:d*(u - xi)^3 + c*(u - xi)^2 + b*(u - xi) + a,其中xi为该段参数区间的左端点,可通过PPoly.x属性获取。
示例:获取x维度最后一段的系数
# 最后一段索引为-1 coef_x_last = pp_x.c[:, -1] xi_last = pp_x.x[-2] print("x维度最后一段系数[d, c, b, a]:", coef_x_last) print("该段参数区间左端点:", xi_last)
注意:splprep生成的是参数B样条,x/y/z都是独立的关于参数u的函数,因此上述多项式的自变量是参数u,不是x坐标。
内容的提问来源于stack exchange,提问作者Shmulik Edelman
相关产品推荐
相关产品推荐

