使用 Matplotlib 绘制椭球体

发布于 2024-12-10 11:30:11 字数 294 浏览 0 评论 0原文

有人有绘制椭球体的示例代码吗? matplotlib 网站上有一个关于球体的信息,但没有关于椭球体的信息。我试图绘制

x**2 + 2*y**2 + 2*z**2 = c

其中 c 是定义椭球体的常量(如 10)。我尝试了 meshgrid(x,y) 路线,重新设计了方程,使 z 位于一侧,但 sqrt 是一个问题。 matplotlib 球体示例适用于角度,u,v,但我不确定如何将其应用于椭球体。

Does anyone have sample code for plotting ellipsoids? There is one for sphere on matplotlib site, but nothing for ellipsoids. I am trying to plot

x**2 + 2*y**2 + 2*z**2 = c

where c is a constant (like 10) that defines an ellipsoid. I tried the meshgrid(x,y) route, reworked the equation so z is on one side, but the sqrt is a problem. The matplotlib sphere example works with angles, u,v, but I am not sure how to work that for ellipsoid.

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

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

发布评论

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

评论(3

诗化ㄋ丶相逢 2024-12-17 11:30:11

以下是通过球面坐标来完成此操作的方法:

# from mpl_toolkits.mplot3d import Axes3D  # Not needed with Matplotlib 3.6.3
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=plt.figaspect(1))  # Square figure
ax = fig.add_subplot(111, projection='3d')

coefs = (1, 2, 2)  # Coefficients in a0/c x**2 + a1/c y**2 + a2/c z**2 = 1 
# Radii corresponding to the coefficients:
rx, ry, rz = 1/np.sqrt(coefs)

# Set of all spherical angles:
u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)

# Cartesian coordinates that correspond to the spherical angles:
# (this is the equation of an ellipsoid):
x = rx * np.outer(np.cos(u), np.sin(v))
y = ry * np.outer(np.sin(u), np.sin(v))
z = rz * np.outer(np.ones_like(u), np.cos(v))

# Plot:
ax.plot_surface(x, y, z,  rstride=4, cstride=4, color='b')

# Adjustment of the axes, so that they all have the same span:
max_radius = max(rx, ry, rz)
for axis in 'xyz':
    getattr(ax, 'set_{}lim'.format(axis))((-max_radius, max_radius))

plt.show()

生成的图类似于

在此处输入图像描述

上面的程序实际上生成看起来更好看的“方形”图形。

该解决方案深受 示例 的启发//matplotlib.sourceforge.net/gallery.html" rel="nofollow noreferrer">Matplotlib 的画廊。

Here is how you can do it via spherical coordinates:

# from mpl_toolkits.mplot3d import Axes3D  # Not needed with Matplotlib 3.6.3
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=plt.figaspect(1))  # Square figure
ax = fig.add_subplot(111, projection='3d')

coefs = (1, 2, 2)  # Coefficients in a0/c x**2 + a1/c y**2 + a2/c z**2 = 1 
# Radii corresponding to the coefficients:
rx, ry, rz = 1/np.sqrt(coefs)

# Set of all spherical angles:
u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)

# Cartesian coordinates that correspond to the spherical angles:
# (this is the equation of an ellipsoid):
x = rx * np.outer(np.cos(u), np.sin(v))
y = ry * np.outer(np.sin(u), np.sin(v))
z = rz * np.outer(np.ones_like(u), np.cos(v))

# Plot:
ax.plot_surface(x, y, z,  rstride=4, cstride=4, color='b')

# Adjustment of the axes, so that they all have the same span:
max_radius = max(rx, ry, rz)
for axis in 'xyz':
    getattr(ax, 'set_{}lim'.format(axis))((-max_radius, max_radius))

plt.show()

The resulting plot is similar to

enter image description here

The program above actually produces a nicer looking "square" graphics.

This solution is strongly inspired from the example in Matplotlib's gallery.

潦草背影 2024-12-17 11:30:11

以 EOL 的答案为基础。有时您有一个矩阵格式的椭球:

A 和 c 其中 A 是椭球矩阵,c 是表示椭球中心的向量。

import numpy as np
import numpy.linalg as linalg
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# your ellispsoid and center in matrix form
A = np.array([[1,0,0],[0,2,0],[0,0,2]])
center = [0,0,0]

# find the rotation matrix and radii of the axes
U, s, rotation = linalg.svd(A)
radii = 1.0/np.sqrt(s)

# now carry on with EOL's answer
u = np.linspace(0.0, 2.0 * np.pi, 100)
v = np.linspace(0.0, np.pi, 100)
x = radii[0] * np.outer(np.cos(u), np.sin(v))
y = radii[1] * np.outer(np.sin(u), np.sin(v))
z = radii[2] * np.outer(np.ones_like(u), np.cos(v))
for i in range(len(x)):
    for j in range(len(x)):
        [x[i,j],y[i,j],z[i,j]] = np.dot([x[i,j],y[i,j],z[i,j]], rotation) + center

# plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(x, y, z,  rstride=4, cstride=4, color='b', alpha=0.2)
plt.show()
plt.close(fig)
del fig

因此,这里并没有太多新内容,但是如果您有一个矩阵形式的椭球体,该椭球体经过旋转并且可能不以 0,0,0 为中心并且想要绘制它,那么它会很有帮助。

Building on EOL's answer. Sometimes you have an ellipsoid in matrix format:

A and c Where A is the ellipsoid matrix and c is a vector representing the centre of the ellipsoid.

import numpy as np
import numpy.linalg as linalg
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# your ellispsoid and center in matrix form
A = np.array([[1,0,0],[0,2,0],[0,0,2]])
center = [0,0,0]

# find the rotation matrix and radii of the axes
U, s, rotation = linalg.svd(A)
radii = 1.0/np.sqrt(s)

# now carry on with EOL's answer
u = np.linspace(0.0, 2.0 * np.pi, 100)
v = np.linspace(0.0, np.pi, 100)
x = radii[0] * np.outer(np.cos(u), np.sin(v))
y = radii[1] * np.outer(np.sin(u), np.sin(v))
z = radii[2] * np.outer(np.ones_like(u), np.cos(v))
for i in range(len(x)):
    for j in range(len(x)):
        [x[i,j],y[i,j],z[i,j]] = np.dot([x[i,j],y[i,j],z[i,j]], rotation) + center

# plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(x, y, z,  rstride=4, cstride=4, color='b', alpha=0.2)
plt.show()
plt.close(fig)
del fig

So, not too much new here, but helpful if you've got an ellipsoid in matrix form which is rotated and perhaps not centered at 0,0,0 and want to plot it.

我最亲爱的 2024-12-17 11:30:11

如果您有一个由任意协方差矩阵 cov 和偏移量 bias 指定的椭球体,则可以执行更简单的 @minillinim 的答案 通过向量化操作。

u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)

制作单位球体

x = np.outer(np.cos(u), np.sin(v))
y = np.outer(np.sin(u), np.sin(v))
z = np.outer(np.ones_like(u), np.cos(v))
sphere = np.stack((x, y, z), axis=-1)[..., None]

开始计算标准差矩阵,该矩阵具有与协方差相同的旋转,但按特征值的平方根缩放:

e, v = np.linalg.eig(cov)
s = v @ np.diag(np.sqrt(e)) @ v.T

现在变换球体:

ellipsoid = (s @ sphere).squeeze(-1) + bias

您可以像以前一样绘制结果:

ax.plot_surface(*ellipsoid.transpose(2, 0, 1), rstride=4, cstride=4, color='b', alpha=0.75)

作为参考,< code>u、v 具有形状 (100,),这使得 xyz 进入(100, 100) 数组。 sphere(100, 100, 3, 1),这使得它成为一个由 3x1 向量组成的 100x100 数组,就广播 @ 运算符而言担心的。 s @sphere 具有相同的大小,因此挤压最后一个单位轴使其适合使用 bias 进行加法广播。最后,ellipsoid.transpose(2, 0, 1) 的形状为 (3, 100, 100),它可以星展开为三个独立的 x- 数组, y 和 z 值传入对 plot_surface 的调用。

If you have an ellipsoid specified by an arbitrary covariance matrix cov and offset bias, you perform a simpler version of @minillinim's answer by vectorizing the operations.

Starting with

u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)

Make a unit sphere

x = np.outer(np.cos(u), np.sin(v))
y = np.outer(np.sin(u), np.sin(v))
z = np.outer(np.ones_like(u), np.cos(v))
sphere = np.stack((x, y, z), axis=-1)[..., None]

Compute the standard deviation matrix, which has the same rotation as the covariance, but scales by the square root of the eigenvalues:

e, v = np.linalg.eig(cov)
s = v @ np.diag(np.sqrt(e)) @ v.T

Now transform the sphere:

ellipsoid = (s @ sphere).squeeze(-1) + bias

You can plot the result pretty much as before:

ax.plot_surface(*ellipsoid.transpose(2, 0, 1), rstride=4, cstride=4, color='b', alpha=0.75)

For reference, u, v have shape (100,), which makes x, y, z into (100, 100) arrays. sphere is (100, 100, 3, 1), which makes it a 100x100 array of 3x1 vectors as far as the broadcasting @ operator is concerned. s @ sphere has the same size, so squeezing out the last unit axis makes it suitable for broadcasting for addition with bias. Finally, ellipsoid.transpose(2, 0, 1) has shape (3, 100, 100), which can be star-expanded as three separate arrays of x-, y- and z-values into the call to plot_surface.

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