geometric_slerp#
- scipy.spatial.geometric_slerp(start, end, t, tol=1e-07)[source]#
幾何球面線性內插。
內插發生在任意維度空間中單位半徑大圓弧上。
- 參數:
- start(n_dimensions, ) 類陣列
單一 n 維輸入座標,以 1 維類陣列物件表示。n 必須大於 1。
- end(n_dimensions, ) 類陣列
單一 n 維輸入座標,以 1 維類陣列物件表示。n 必須大於 1。
- tfloat 或 (n_points,) 1D 類陣列
浮點數或雙精度浮點數的 1 維類陣列,表示內插參數,值必須在 0 到 1 的包含區間內。常見的方法是使用
np.linspace(0, 1, n_pts)
產生線性間隔點的陣列。允許升序、降序和亂序。- tolfloat
用於判斷起始和結束座標是否為對跖點的絕對容差。
- 返回:
- result(t.size, D)
包含內插球面路徑的雙精度浮點數陣列,當使用 0 和 1 作為 t 時,包含起始和結束點。內插值應對應於 t 陣列中提供的相同排序順序。如果
t
是浮點數,則結果可能是一維的。
- 引發:
- ValueError
如果
start
和end
是對跖點、不在單位 n 球面上,或存在各種退化條件。
參見
scipy.spatial.transform.Slerp
使用四元數的 3-D Slerp
註解
此實作基於 [1] 中提供的數學公式,並且此演算法的首次已知呈現,源自對 4-D 幾何的研究,歸功於 Glenn Davis 在 Ken Shoemake [2] 的原始四元數 Slerp 出版物中的註腳。
在 1.5.0 版本中新增。
參考文獻
[2]Ken Shoemake (1985) Animating rotation with quaternion curves. ACM SIGGRAPH Computer Graphics, 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()