Подтвердить что ты не робот

Как обрезать график 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

4b9b3361

Ответ 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()

Примечание. На этом снимке я добавил цвет фона, чтобы выделить прямоугольную форму графиков