Как обрезать график Axes3D с квадратным соотношением сторон?
Вот пример barebones:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
f = fig.add_subplot(2, 1, 1, projection='3d')
t = fig.add_subplot(2, 1, 2, projection='3d')
# axes
for d in {f, t}:
d.plot([-1, 1], [0, 0], [0, 0], color='k', alpha=0.8, lw=2)
d.plot([0, 0], [-1, 1], [0, 0], color='k', alpha=0.8, lw=2)
d.plot([0, 0], [0, 0], [-1, 1], color='k', alpha=0.8, lw=2)
f.dist = t.dist = 5.2 # 10 is default
plt.tight_layout()
f.set_aspect('equal')
t.set_aspect('equal')
r = 6
f.set_xlim3d([-r, r])
f.set_ylim3d([-r, r])
f.set_zlim3d([-r, r])
t.set_xlim3d([-r, r])
t.set_ylim3d([-r, r])
t.set_zlim3d([-r, r])
f.set_axis_off()
t.set_axis_off()
plt.draw()
plt.show()
Это то, что я получаю:
![квадратные видовые экраны]()
Это то, что я хочу:
![прямоугольные видовые экраны]()
Другими словами, я хочу, чтобы сами сюжеты имели квадратное соотношение сторон, а не все растягивались следующим образом:
![растянутый]()
и я получил эту часть благодаря qaru.site/info/106600/...
но я хочу, чтобы окна смотрели на эти сюжеты, чтобы они были прямоугольными, а верх и низ обрезаны (так как там будет только пустое место сверху и снизу, и я создаю несколько анимированных GIF файлов, поэтому я не могу легко опубликовать -процесс его в форму, которую я хочу).
В основном я делаю эту анимацию, и я хочу то же самое, но без всех пробелов:
![animation]()
Ответы
Ответ 1
Чтобы отслеживать мои комментарии и показывать примеры, установив меньший r
и удаляя поля подзаголовка с помощью subplots_adjust
:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
f = fig.add_subplot(2, 1, 1, projection='3d')
t = fig.add_subplot(2, 1, 2, projection='3d')
# axes
for d in {f, t}:
d.plot([-1, 1], [0, 0], [0, 0], color='k', alpha=0.8, lw=2)
d.plot([0, 0], [-1, 1], [0, 0], color='k', alpha=0.8, lw=2)
d.plot([0, 0], [0, 0], [-1, 1], color='k', alpha=0.8, lw=2)
f.dist = t.dist = 5.2 # 10 is default
plt.tight_layout()
f.set_aspect('equal')
t.set_aspect('equal')
r = 1
f.set_xlim3d([-r, r])
f.set_ylim3d([-r, r])
f.set_zlim3d([-r, r])
t.set_xlim3d([-r, r])
t.set_ylim3d([-r, r])
t.set_zlim3d([-r, r])
f.set_axis_off()
t.set_axis_off()
fig.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0,
hspace = 0, wspace = 0)
plt.draw()
plt.show()
Это даст более плотные подзаголовки, поскольку значения по умолчанию для SubplotParams выглядят следующим образом:
слева: 0,125
справа: 0,9
внизу: 0,1
top: 0,9
wspace: 0.2
hspace: 0.2
не уверен, что это OP ищет, хотя...
![введите описание изображения здесь]()
Ответ 2
Поскольку вам нужен прямоугольный график, вы не можете использовать set_aspect('equal')
, вместо этого вы должны настроить пределы своих сюжетов, чтобы учесть разницу в соотношении сторон.
В попытке ниже я использовал ось bbox
для получения осей height
и width
осей и использовал соотношение сторон для масштабирования осей X
и Y
. (Я предположил, что оба графика имеют одинаковое измерение, но у вас также могут быть графики с разными размерами, вам просто нужно самостоятельно отрегулировать пределы осей для каждого).
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
f = fig.add_subplot(2, 1, 1, projection='3d')
t = fig.add_subplot(2, 1, 2, projection='3d')
# axes
for d in {f, t}:
d.plot([-1, 1], [0, 0], [0, 0], color='k', alpha=0.8, lw=2)
d.plot([0, 0], [-1, 1], [0, 0], color='k', alpha=0.8, lw=2)
d.plot([0, 0], [0, 0], [-1, 1], color='k', alpha=0.8, lw=2)
f.dist = t.dist = 5.2 # 10 is default
plt.tight_layout()
# Cannot use 'equal' aspect for a rectangular plot
# f.set_aspect('equal')
# t.set_aspect('equal')
# get the dimensions of the axes from its bbox
f_bbox = f.get_position()
f_height = f_bbox.height
f_width = f_bbox.width
r = 6
f.set_xlim3d([-1 * f_width/f_height * r, f_width/f_height * r])
f.set_ylim3d([-1 * f_width/f_height * r, f_width/f_height * r])
f.set_zlim3d([-r, r])
t.set_xlim3d([-1 * f_width/f_height * r, f_width/f_height * r])
t.set_ylim3d([-1 * f_width/f_height * r, f_width/f_height * r])
t.set_zlim3d([-r, r])
f.set_axis_off()
t.set_axis_off()
plt.draw()
plt.show()
![]()
Примечание. На этом снимке я добавил цвет фона, чтобы выделить прямоугольную форму графиков