使用matplotlib,python绘制三个正交矢量和大小的椭圆形

发布于 2025-01-26 19:07:50 字数 266 浏览 2 评论 0原文

我有三个正顺序向量

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

,并且沿着这些方向的每个方向1.44、3.452.02沿每个方向的亮度值。

我如何绘制代表沿正顺序向量的轴方向以及其大小给出的轴长的椭圆形(3D表面)?

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 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半葬歌 2025-02-02 19:07:50

如果我正确理解您的问题,您想创建一个椭圆形并旋转它,以使其主要轴与正统向量对齐。

注释:由于Matplotlib的3D功能相当有限,因此我将使用绘图:这将使我们的生活变得容易得多,因为它为3D图提供了“相等”的长宽比。您可以轻松地将绘图库更改为matplotlib。

椭圆形的参数方程可以在这里找到

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文