gpt4 book ai didi

python - Matplotlib - 强制 3D 图使用可用的 figsize

转载 作者:行者123 更新时间:2023-12-04 14:52:09 27 4
gpt4 key购买 nike

我想创建一个具有指定图形大小的图,其中 3D 轴尝试使用整个可用空间,同时在所有轴上保持相等的纵横比。

我目前的尝试显示了一个隐藏了部分网格的剪切矩形。

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

fig = plt.figure(figsize=(5, 2.5))
ax = fig.add_subplot(projection='3d')
ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), np.diag([1, 1, 1, 0.5]))

u = v = np.linspace(0, 2 * np.pi, 50)
u, v = np.meshgrid(u, v)
X = np.cos(v) * (6 - (5/4 + np.sin(3 * u)) * np.sin(u - 3 * v))
Y = (6 - (5/4 + np.sin(3 * u)) * np.sin(u - 3 * v)) * np.sin(v)
Z = -np.cos(u - 3 * v) * (5/4 + np.sin(3 * u))

ax.plot_surface(X, Y, Z, rstride=1, cstride=1, color=[0.7] * 3, linewidth=0.25, edgecolor="k")
ax.set_box_aspect([ub - lb for lb, ub in (getattr(ax, f'get_{a}lim')() for a in 'xyz')])

plt.show()

current plot

我能做什么?

最佳答案

我复制了你提供的代码,只是在最后添加了 4 行。

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
plt.close()
fig = plt.figure(figsize=(5, 2.5))
ax = fig.add_subplot(projection='3d')
ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), np.diag([1, 1, 1, 0.5]))

u = v = np.linspace(0, 2 * np.pi, 50)
u, v = np.meshgrid(u, v)
X = np.cos(v) * (6 - (5/4 + np.sin(3 * u)) * np.sin(u - 3 * v))
Y = (6 - (5/4 + np.sin(3 * u)) * np.sin(u - 3 * v)) * np.sin(v)
Z = -np.cos(u - 3 * v) * (5/4 + np.sin(3 * u))

ax.plot_surface(X, Y, Z, rstride=1, cstride=1, color=[0.7] * 3, linewidth=0.25, edgecolor="k")
# ax.set_box_aspect([ub - lb for lb, ub in (getattr(ax, f'get_{a}lim')() for a in 'xyz')])


left, right = plt.xlim()
ax.set_zlim(left, right)
ax.set_ylim(left, right)
plt.tight_layout()

我注释掉 ax.set_box_aspect 行,因为它给我一个错误。上面的输出是:

enter image description here

--- 编辑---

我有一个解决方法,可以让它在 matplotlib v3.4.2 中工作:

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

plt.close()

# your code starts here, with a little modification
fig = plt.figure(figsize=(5,5))
ax = fig.add_subplot(projection='3d')

u = v = np.linspace(0, 2 * np.pi, 50)
u, v = np.meshgrid(u, v)
X = np.cos(v) * (6 - (5/4 + np.sin(3 * u)) * np.sin(u - 3 * v))
Y = (6 - (5/4 + np.sin(3 * u)) * np.sin(u - 3 * v)) * np.sin(v)
Z = -np.cos(u - 3 * v) * (5/4 + np.sin(3 * u))
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, color=[0.7] * 3, linewidth=0.25, edgecolor="k")

# set the axes limits
left, right = plt.xlim()
ax.set_zlim(left, right)
ax.set_ylim(left, right)

# zoom in to the plot
ax.dist = 6

# make everything other than the plot itself transparent
fig.patch.set_alpha(0)
ax.patch.set_alpha(0)
ax.axis('off')
plt.tight_layout()

# save plot as image
plt.savefig('plotted.png')

# remove the axes where the image was plotted
ax.remove()

# resize figsize
fig = matplotlib.pyplot.gcf()
fig.set_size_inches(5, 2.5)

# add fake axes for gridlines as in 3d plot to make it look like a real plot
# skip this part if the gridlines are unnecessary
ax_bg = fig.add_subplot(111, projection='3d')
ax_bg.dist = 3

# add axes in cartesian coordinates (xy-plane) for the image
ax = fig.add_subplot(111)
fig.patch.set_alpha(1)
fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
im = plt.imread('plotted.png')

h, w, dc = im.shape # (height=500, width=500, depth/color=4)
im_cropped = im[120:390, :, :] # this is manually adjusted
ax.axis('off')
ax.imshow(im_cropped)

# delete the saved image
os.remove('plotted.png')

输出是:

enter image description here

我不知道它是否适用于您的特定上下文,但它仅适用于解决您的问题。

如果有什么不清楚的地方,请告诉我。

关于python - Matplotlib - 强制 3D 图使用可用的 figsize,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68905632/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com