scipy.spatial.
geometric_slerp#
- scipy.spatial.geometric_slerp(start, end, t, tol=1e-07)[源代码]#
几何球面线性插值。
插值在任意维空间中沿单位半径大圆弧进行。
- 参数:
- start(n_dimensions, ) 数组类
一维数组类对象中的单个 n 维输入坐标。 n 必须大于 1。
- end(n_dimensions, ) 数组类
一维数组类对象中的单个 n 维输入坐标。 n 必须大于 1。
- t浮点数或 (n_points,) 一维数组类
表示插值参数的浮点数或一维双精度数组类,值必须在 0 到 1 的闭区间内。一种常见方法是使用
np.linspace(0, 1, n_pts)
生成线性间隔点的数组。允许升序、降序和乱序。- tol浮点数
用于确定起始和结束坐标是否为对跖点的绝对容差。
- 返回:
- result(t.size, D)
包含插值球面路径的双精度数组,当使用 0 和 1 t 时包含起始和结束点。插值值应与 t 数组中提供的排序顺序一致。如果
t
是浮点数,则结果可能是一维的。
- 引发:
- ValueError
如果
start
和end
是对跖点,不在单位 n 球面上,或存在各种退化条件。
另请参阅
scipy.spatial.transform.Slerp
适用于四元数的 3D Slerp
注释
该实现基于 [1] 中提供的数学公式,而该算法的首次已知呈现(源自对 4 维几何的研究)则归功于 Ken Shoemake 原始四元数 Slerp 出版物 [2] 的脚注中的 Glenn Davis。
在版本 1.5.0 中添加。
参考文献
[2]Ken Shoemake (1985) 用四元数曲线动画旋转。ACM SIGGRAPH 计算机图形学,19(3): 245-254。
示例
在跨度为 90 度的圆周上插值四个线性间隔的值
>>> import numpy as np >>> from scipy.spatial import geometric_slerp >>> import matplotlib.pyplot as plt >>> fig = plt.figure() >>> ax = fig.add_subplot(111) >>> start = np.array([1, 0]) >>> end = np.array([0, 1]) >>> t_vals = np.linspace(0, 1, 4) >>> result = geometric_slerp(start, ... end, ... t_vals)
插值结果应在单位圆上以 30 度间隔可识别
>>> ax.scatter(result[...,0], result[...,1], c='k') >>> circle = plt.Circle((0, 0), 1, color='grey') >>> ax.add_artist(circle) >>> ax.set_aspect('equal') >>> plt.show()
尝试在圆的对跖点之间进行插值是模糊的,因为存在两条可能的路径;而在球面上,测地表面上存在无限条可能的路径。尽管如此,仍会返回其中一条模糊路径并附带警告。
>>> opposite_pole = np.array([-1, 0]) >>> with np.testing.suppress_warnings() as sup: ... sup.filter(UserWarning) ... geometric_slerp(start, ... opposite_pole, ... t_vals) array([[ 1.00000000e+00, 0.00000000e+00], [ 5.00000000e-01, 8.66025404e-01], [-5.00000000e-01, 8.66025404e-01], [-1.00000000e+00, 1.22464680e-16]])
将原始示例扩展到球体并在 3D 中绘制插值点
>>> from mpl_toolkits.mplot3d import proj3d >>> fig = plt.figure() >>> ax = fig.add_subplot(111, projection='3d')
绘制单位球体作为参考(可选)
>>> u = np.linspace(0, 2 * np.pi, 100) >>> v = np.linspace(0, np.pi, 100) >>> x = np.outer(np.cos(u), np.sin(v)) >>> y = np.outer(np.sin(u), np.sin(v)) >>> z = np.outer(np.ones(np.size(u)), np.cos(v)) >>> ax.plot_surface(x, y, z, color='y', alpha=0.1)
对更多点进行插值可能会在球体表面呈现平滑曲线,这对于球体表面上的离散积分计算也很有用
>>> start = np.array([1, 0, 0]) >>> end = np.array([0, 0, 1]) >>> t_vals = np.linspace(0, 1, 200) >>> result = geometric_slerp(start, ... end, ... t_vals) >>> ax.plot(result[...,0], ... result[...,1], ... result[...,2], ... c='k') >>> plt.show()