简体   繁体   中英

Is there an easy way to rotate a 3d mesh by 90 degree in plotly?

I've created a 3d mesh in plotly using the plotly.graph_objects.Mesh3d function. Please see the next picture.

在此处输入图像描述

Is there an easy way to rotate this 3d mesh by 90 degree? Please see the next picture as an indication how I want to rotate.

在此处输入图像描述

Although I don't know how exactly you created the 3d mesh rectangular surface, I can recreate it by passing the x,y,z coordinates of the four corners of your surface, as well as the Delaunay axis to go.Mesh3d . The Delaunay axis tells Plotly the direction perpendicular to your surface in order to construct the mesh. You could specify the Delaunay axis to be either 'x' or 'y' and the surface will be render correctly:

import plotly.graph_objects as go

x = [11.5,11.5,14.5,14.5]
y = [19,19,13,13]
z = [436,441,436,441]

fig = go.Figure(data=[
    go.Mesh3d(
        x=x,
        y=y,
        z=z,
        delaunayaxis='y'
    )
])
    
fig.show()

在此处输入图像描述

When you rotate your plane so that lies parallel to the xy plane, the two original z-coordinates at the bottom of the plane will remain fixed, but the coordinates of the two new planes can be calculated using properties of perpendicular vectors.

Consider the below diagram (vectors not drawn accurately but hopefully the following explanation makes sense). When you rotate your 3d mesh plane down to z=436, the new blue vector must be perpendicular to the green vector and have a length of 5 (the same distance from 436 to 441 in the original 3d mesh plane you drew). The green vector can be decomposed into x and y components represented in red. If the green vector has direction (v_x, v_y) , then the blue vector will have direction (-v_y, v_x) . Then we can normalize this vector (divide by its length) and multiply it by 5 to get the final vector. Add this vector to points a and b and we get our new coordinates c and d .

![在此处输入图像描述

Using some basic numpy operations to help us, we can translate the above into code ( a and b are the bottom coordinates of the mesh that will stay the same after rotation, and c and d are the new coordinates). Also when you add the rotated 3d mesh, you'll want to change the Delaunay axis to z since the z-axis is perpendicular to our new surface:

import numpy as np

## make points a and b the bottom two points
a = np.array((x[0], y[0], z[0]))
b = np.array((x[2], y[2], z[2]))
v = b-a

## create a perpendicular unit vector
v_perp_unit = np.array([-1*v[1], v[0], v[2]]) / np.linalg.norm(v)
v_length = max(z) - min(z)

v_perp = v_length*v_perp_unit

## calculate the coordinates of the final two points
c = a+v_perp
d = b+v_perp

x_new = [a[0],b[0],c[0],d[0]]
y_new = [a[1],b[1],c[1],d[1]]
z_new = [a[2],b[2],c[2],d[2]]

fig = go.Figure(data=[
    go.Mesh3d(
        x=x_new,
        y=y_new,
        z=z_new,
        delaunayaxis='z'
    )
])
    
fig.show()

在此处输入图像描述

If you add the newly rotated 3d mesh plane as a trace, you can see that the original and check that the two planes are indeed perpendicular:

fig.add_trace(
    go.Mesh3d(
        x=x_new,
        y=y_new,
        z=z_new,
        delaunayaxis='z'
    )
)
    
fig.show()

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM