Applying linear transformation to whole surface of weird shape

Question:

So, I have this torus that is moved from its usual position given by the function

def toro(u,v,R,r,t):
    
    n = unitary_normal_t(t)
    n0, n1, n2  = [n[k][0] for k in [0,1,2]]
    b  = binormal_t(t)
    b0, b1, b2 = [b[k][0] for k in [0,1,2]]
    tang  = tangente(t)
    t0, t1, t2 = [tang[k][0] for k in [0,1,2]]
    
    x = n0*np.cos(u)*(R + r*np.cos(v)) + b0*(R + r*np.cos(v))*np.sin(u) + r*t0*np.sin(v) + n0*R
    y = n1*np.cos(u)*(R + r*np.cos(v)) + b1*(R + r*np.cos(v))*np.sin(u) + r*t1*np.sin(v) + n1*R
    z = n2*np.cos(u)*(R + r*np.cos(v)) + b2*(R + r*np.cos(v))*np.sin(u) + r*t2*np.sin(v) + n2*R
    return np.array([x,y,z])

The actual expression of this tori is not relevant. Since I wish to plot this tori, I do the following:

fig = go.Figure()                                                                                                                   # this creates the figure object
d = 1            # we add the torus
r = 0.1
R = 0.5

colorscales = ['plotly3','bluered','magma','blugrn','blues','gray']
u = np.linspace(0, 2*np.pi, 240)                                                # discretization of the u parameter
v = np.linspace(0, 2*np.pi, 240)                                                # discretization of the v parameter
uplot,vplot = np.meshgrid(u,v)

t = 0.1
torito = toro(uplot,vplot,R,r,t)
X = torito[0]
Y = torito[1]
Z = torito[2]
colorscale = 'plotly3'
fig.add_surface(x=X, y=Y, z=Z, colorscale = colorscale)                         # we add a surfaceplot to it

fig.update_traces(showscale=False) 

Recall I am using numpy and Plotly. In the code above, torito is the torus and it is an array of shape (3,240,240). Now, I have this 3×3 matrix, let’s call it M, that I would like to apply to torito, something like transformed_tori = np.matmul(M,torito) so that I could apply the same code as above to transformed_tori, yet I cannot do so because shapes do not match.

Does anyone know how I could do such a thing? Tryouts can be made with the following matrix: M = np.array([[ 0.00348674, -0.2282992 , 0.97358478], [ 0.07565293, 0.97086078, 0.2273895 ], [-0.99712811, 0.07286169, 0.02065664]])

Thank you in advance!!!

Asked By: juan zaragoza

||

Answers:

You can use np.einsum() to do the appropriate matrix multiplication along the wanted axis.

transformed_tori  = np.einsum("ij,jkl->ikl", M, torito)

Where transformed_tori is a (3, 240, 240) array where transformed_tori[:, i,j] = np.matmul(M, tori[:, i,j]

Answered By: PlainRavioli