2

I have three orthonormal vectors

(-0.460021, -0.241295, -0.854493), 
(-0.641846, 0.755344, 0.132244),
(-0.613526, -0.609288, 0.502348) 

and a magntitude value along each of these direction 1.44, 3.45 and 2.02.

How can I plot an ellipsoid (3D surface) representing the axis directions along the orthonormal vectors and the axis lengths given by their magnitude ?

1 Answers1

3

If I understand your question correctly, you want to create an ellipsoid and rotate it so that its major axis are aligned with the orthonormal vectors.

Note: since Matplotlib's 3D capability are rather limited, I'm going to use Plotly: it will make our life a lot easier since it provides an "equal" aspect ratio for 3D plots. You can easily change the plotting library to Matplotlib.

The parametric equations for an ellipsoid can be found here.

import numpy as np
import matplotlib.pyplot as plt
import plotly.graph_objects as go

# compute ellipsoid coordinates on standard basis
# e1=(1, 0, 0), e2=(0, 1, 0), e3=(0, 0, 1)
a, b, c = 1.44, 3.45, 2.02
u, v = np.mgrid[0:2*np.pi:40j, 0:np.pi:20j]
x1 = a * np.cos(u) * np.sin(v)
y1 = b * np.sin(u) * np.sin(v)
z1 = c * np.cos(v)
# points on the ellipsoid
points = np.stack([t.flatten() for t in [x1, y1, z1]])

v1 = np.array([-0.460021, -0.241295, -0.854493])
v2 = np.array([-0.641846, 0.755344, 0.132244])
v3 = np.array([-0.613526, -0.609288, 0.502348])
# 3x3 transformation matrix
T = np.array([v1, v2, v3]).T

# transform coordinates to the new orthonormal basis
new_points = T @ points
x2 = new_points[0, :]
y2 = new_points[1, :]
z2 = new_points[2, :]
x2, y2, z2 = [t.reshape(x1.shape) for t in [x2, y2, z2]]

# scale vector for better visualization
scale = 5
v1, v2, v3 = [scale * t for t in [v1, v2, v3]]

fig = go.Figure([
    # axis on the standard base
    go.Scatter3d(x=[0, 5], y=[0, 0], z=[0, 0], mode="lines", name="x1", line=dict(width=5, color="red")),
    go.Scatter3d(x=[0, 0], y=[0, 5], z=[0, 0], mode="lines", name="y1", line=dict(width=5, color="green")),
    go.Scatter3d(x=[0, 0], y=[0, 0], z=[0, 5], mode="lines", name="z1", line=dict(width=5, color="blue")),
    # axis on the new orthonormal base
    go.Scatter3d(x=[0, v1[0]], y=[0, v1[1]], z=[0, v1[2]], mode="lines", name="x2", line=dict(width=2, color="red")),
    go.Scatter3d(x=[0, v2[0]], y=[0, v2[1]], z=[0, v2[2]], mode="lines", name="y2", line=dict(width=2, color="green")),
    go.Scatter3d(x=[0, v3[0]], y=[0, v3[1]], z=[0, v3[2]], mode="lines", name="z2", line=dict(width=2, color="blue")),
    # original ellipsoid aligned to the standard base
    go.Surface(x=x1, y=y1, z=z1, opacity=0.35, colorscale="plotly3", surfacecolor=y1, cmin=y1.min(), cmax=y1.max(), colorbar=dict(len=0.6, yanchor="bottom", y=0)),
    # final ellipsoid aligned to the new orthonormal base
    go.Surface(x=x2, y=y2, z=z2, opacity=1, colorscale="aggrnyl", surfacecolor=y1, cmin=y1.min(), cmax=y1.max(), colorbar=dict(len=0.6, yanchor="bottom", y=0, x=0.95))
])
fig.update_layout({"scene": {"aspectmode": "auto"}})
fig

enter image description here

Davide_sd
  • 10,578
  • 3
  • 18
  • 30