2015-09-14 35 views
4

任意的旋轉角度的列表(可以說繞X軸):什麼是正確的方式來創建轉型的numpy的陣列矩陣

import numpy as np 
x_axis_rotations = np.radians([0,10,32,44,165]) 

我可以創建這樣做符合這些角矩陣陣列所以:

matrices = [] 
for angle in x_axis_rotations: 
    matrices.append(np.asarray([[1 , 0 , 0],[0, np.cos(angle), -np.sin(angle)], [0, np.sin(angle), np.cos(angle)]])) 
matrices = np.array(matrices) 

這會工作,但它並沒有利用numpy的的優勢在應對大陣......所以,如果我的角度陣列以百萬計,做這種方式會不會很快速。

是否有更好(更快)的方法來從輸入數組中創建變換矩陣的數組?

+0

所以,如果我理解正確的話,你要以3D陣列?輸入來自哪裏?一個文件或者你在運行時產生的東西? – ventsyv

+1

您能否解釋一下爲什麼要存儲這些矩陣而不是在使用時計算它們的原因? – Simpom

+0

@Simpom我想實現[本文]中概述的點對三角技術(http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.479.8237&rep=rep1&type=pdf)。這個想法是,通過爲網格的每個三角形預先計算一個變換矩陣,可以減少從點到三角形問題的3D距離,變成更簡單的2D圖形,可以比重心計算更快地計算出來。如果我只想要一個點查詢,那麼是沒有必要計算矩陣。但是,如果我有一百萬點查詢,那麼這應該證明是有用的。 – Fnord

回答

3

這裏有一個直接而簡單的方法:

c = np.cos(x_axis_rotations) 
s = np.sin(x_axis_rotations) 
matrices = np.zeros((len(x_axis_rotations), 3, 3)) 
matrices[:, 0, 0] = 1 
matrices[:, 1, 1] = c 
matrices[:, 1, 2] = -s 
matrices[:, 2, 1] = s 
matrices[:, 2, 2] = c 

時間,好奇:

In [30]: angles = 2 * np.pi * np.random.rand(1000) 

In [31]: timeit OP(angles) 
100 loops, best of 3: 5.46 ms per loop 

In [32]: timeit askewchan(angles) 
10000 loops, best of 3: 39.6 µs per loop 

In [33]: timeit divakar(angles) 
10000 loops, best of 3: 93.8 µs per loop 

In [34]: timeit divakar_oneline(angles) 
10000 loops, best of 3: 56.1 µs per loop 

In [35]: timeit divakar_combine(angles) 
10000 loops, best of 3: 43.9 µs per loop 

所有比你的循環更快,所以使用哪個你最喜歡:)

+0

確實很簡單,很好! – Divakar

+0

不錯,簡潔!謝謝! – Fnord

2

您可以使用linear indexing助陣,像這樣 -

# Get cosine and sine values in one-go 
cosv = np.cos(x_axis_rotations) 
sinv = np.sin(x_axis_rotations) 

# Get size parameter 
N = x_axis_rotations.size 

# Initialize output array 
out = np.zeros((N,3,3)) 

# Set the first element in each 3D slice as 1 
out[:,0,0] = 1 

# Calculate the first of positions where cosine valued elements are to be put 
idx1 = 4 + 9*np.arange(N)[:,None] 

# One by one put those 4 values in 2x2 blocks across all 3D slices 
out.ravel()[idx1] = cosv 
out.ravel()[idx1+1] = -sinv 

out.ravel()[idx1+3] = sinv 
out.ravel()[idx1+4] = cosv 

或者,你可以設置中的元素一去,你有zeros初始化輸出數組後,並在每個切片組的第一個元素爲1,像這樣 -

out.reshape(N,-1)[:,[4,5,7,8]] = np.column_stack((cosv,-sinv,sinv,cosv)) 

上述兩種方法之間,兩個中景方法可能演變,再初始化後W擺正第i個零和設置在每個3D片的第一個元素爲1,像這樣 -

out.reshape(N,-1)[:,[4,8]] = cosv[:,None] 
out.reshape(N,-1)[:,[5,7]] = np.column_stack((-sinv[:,None],sinv[:,None])) 

最後一個是 -

out.reshape(N,-1)[:,[4,8]] = cosv[:,None] 
out.reshape(N,-1)[:,5] = -sinv 
out.reshape(N,-1)[:,7] = sinv 
+0

我喜歡這些答案的優雅,但我認爲索引最終只會放慢速度。 – askewchan

+0

@askewchan那麼,我很害怕column_stacks,因爲他們被認爲是緩慢的。這將是很好,我想花時間所有這些。 – Divakar

+0

因爲LHS上的切片只有一個維度,所以最後一個解決方案不應該有最後兩行的新軸。 – askewchan