Consider a regular matrix that represents nodes numbered as shown in the figure:
I want to make a list with all the triangles represented in the figure. Which would result in the following 2 dimensional list:[[0,1,4],[1,5,4],[1,2,5],[2,6,5],...,[11,15,14]]
Assuming that the dimensions of the matrix are (Nr
XNc
) ((4X4) in this case), I was able to achieve this result with the following code:
def MakeFaces(Nr,Nc):Nfaces=(Nr-1)*(Nc-1)*2Faces=np.zeros((Nfaces,3),dtype=np.int32)for r in range(Nr-1):for c in range(Nc-1):fi=(r*(Nc-1)+c)*2l1=r*Nc+cl2=l1+1l3=l1+Ncl4=l3+1Faces[fi]=[l1,l2,l3]Faces[fi+1]=[l2,l4,l3]return Faces
However, the double loop operations make this approach quite slow. Is there a way of using numpy in a smart way to do this faster?
We could play a multi-dimensional
game based on slicing
and multi-dim assignment
that are perfect in NumPy environment on efficiency -
def MakeFacesVectorized1(Nr,Nc):out = np.empty((Nr-1,Nc-1,2,3),dtype=int)r = np.arange(Nr*Nc).reshape(Nr,Nc)out[:,:, 0,0] = r[:-1,:-1]out[:,:, 1,0] = r[:-1,1:]out[:,:, 0,1] = r[:-1,1:]out[:,:, 1,1] = r[1:,1:]out[:,:, :,2] = r[1:,:-1,None]out.shape =(-1,3)return out
Runtime test and verification -
In [226]: Nr,Nc = 100, 100In [227]: np.allclose(MakeFaces(Nr, Nc), MakeFacesVectorized1(Nr, Nc))
Out[227]: TrueIn [228]: %timeit MakeFaces(Nr, Nc)
100 loops, best of 3: 11.9 ms per loopIn [229]: %timeit MakeFacesVectorized1(Nr, Nc)
10000 loops, best of 3: 133 µs per loopIn [230]: 11900/133.0
Out[230]: 89.47368421052632
Around 90x
speedup for Nr, Nc = 100, 100
!