Изображение на плоскости в Matplotlib mplot3d

У меня есть 3D-сцена, созданная с помощью Matplotlib, и я хотел бы применить рисунок в виде шахматной доски на нижней плоскости на изображении ниже. У вас есть идеи, как этого добиться?

введите здесь описание изображения

Вот код для создания этого изображения:

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

# Create figure
plt.style.use('dark_background') # Dark theme
fig = plt.figure(frameon=False)
ax = fig.add_subplot(111, projection='3d')

# Make panes transparent
ax.xaxis.pane.fill = False # Left pane
ax.yaxis.pane.fill = False # Right pane
# ax.zaxis.pane.fill = False # Bottom pane

# Remove grid lines
ax.grid(False)

# Remove tick labels
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.set_zticklabels([])

# Random data to illustrate
zdata = 15 * np.random.random(100)
xdata = np.sin(zdata) + 0.1 * np.random.randn(100)
ydata = np.cos(zdata) + 0.1 * np.random.randn(100)
ax.scatter3D(xdata, ydata, zdata, c=zdata, cmap='Greens')

# Print chart
file_path = 'charts/3d.png'
fig.savefig(file_path, bbox_inches='tight', pad_inches=0.05, transparent=True)

person Alexis.Rolland    schedule 22.01.2020    source источник


Ответы (1)


Вы можете создать сетку прямоугольников и использовать функцию pathpatch_2d_to_3d из mpl_toolkits.mplot3d.art3d для вставки в 3D-сцену:

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

from matplotlib.patches import Rectangle
import mpl_toolkits.mplot3d.art3d as art3d

# Create figure
plt.style.use('dark_background') # Dark theme
fig = plt.figure(frameon=False)
ax = fig.add_subplot(111, projection='3d')

# Make planes transparent
ax.xaxis.pane.fill = False # Left plane
ax.yaxis.pane.fill = False # Right plane
# ax.zaxis.pane.fill = False # Horizontal plane

# Remove grid lines
ax.grid(False)

# Remove tick labels
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.set_zticklabels([])

# Draw chessboard on hortizontal plane
for x_index, x in enumerate(np.arange(-1, 1.1, 0.2)):
    for y_index, y in enumerate(np.arange(-1, 1.1, 0.2)):
        if (x_index+y_index)%2:
            p = Rectangle([x,y], 0.2, 0.2)
            ax.add_patch(p)
            art3d.pathpatch_2d_to_3d(p, z=0, zdir="z")

ax.set(xlim=(-1,1.1), ylim=(-1,1.2), zlim=(0,15))

# Random data to illustrate
zdata = 15 * np.random.random(100)
xdata = np.sin(zdata) + 0.1 * np.random.randn(100)
ydata = np.cos(zdata) + 0.1 * np.random.randn(100)
ax.scatter3D(xdata, ydata, zdata, c=zdata, cmap='Greens')

# Print chart
file_path = 'charts/3d.png'
fig.savefig(file_path, bbox_inches='tight', pad_inches=0.05, transparent=True)

введите здесь описание изображения


РЕДАКТИРОВАТЬ: более чистая версия

RECT_SIZE_X = 0.2
RECT_SIZE_Y = 0.2
xlims = (-1, 1)
ylims = (-1, 1)

for x_index, x_pos in enumerate(np.arange(xlims[0], xlims[1], RECT_SIZE_X)):
    for y_index, y_pos in enumerate(np.arange(ylims[0], ylims[1], RECT_SIZE_Y)):
        if (x_index+y_index)%2:
            p = Rectangle([x_pos, y_pos], RECT_SIZE_X, RECT_SIZE_Y, color='orange')
        else:
            p = Rectangle([x_pos, y_pos], RECT_SIZE_X, RECT_SIZE_Y, color='gray')
        ax.add_patch(p)
        art3d.pathpatch_2d_to_3d(p, z=0, zdir="z")

ax.set(xlim=xlims, ylim=ylims, zlim=(0,15))
# Transparent spines
ax.w_xaxis.line.set_color((1.0, 1.0, 1.0, 0.0))
ax.w_yaxis.line.set_color((1.0, 1.0, 1.0, 0.0))
ax.w_zaxis.line.set_color((1.0, 1.0, 1.0, 0.0))

# Transparent panes
ax.w_xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
ax.w_yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
ax.w_zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))

# No ticks
ax.set_xticks([]) 
ax.set_yticks([]) 
ax.set_zticks([])

введите здесь описание изображения

person Andrea    schedule 22.01.2020
comment
Красивый! Большое спасибо, я попробую это! - person Alexis.Rolland; 22.01.2020
comment
кажется, что последняя строка вызывает ошибку в вашем фрагменте кода ax.set(xlim=(-1,1.1), ylim=(-1,1.2), zlim=(0,15)) возвращает SyntaxError: invalid syntax - person Alexis.Rolland; 22.01.2020
comment
Я нашел проблему, добавив одну дополнительную строку после того, как цикл for исправляет ее на моей стороне. - person Alexis.Rolland; 22.01.2020
comment
так как вы, кажется, одарены matplotlib, не могли бы вы представить, как это сделать? stackoverflow.com/questions/59857203/ - person Alexis.Rolland; 22.01.2020
comment
Конечно, вот оно:) - person Andrea; 22.01.2020
comment
Еще один вопрос, если не слишком сложно... не могли бы вы объяснить вложенные циклы for? Я понимаю, что они используются для вычисления прямоугольников и их координат, но мне не совсем понятен выбор используемых вами жестко закодированных значений. - person Alexis.Rolland; 22.01.2020
comment
Признаюсь, я не особо об этом думал, я просто сделал контрольную доску, а затем отрегулировал границы x и y, чтобы все заработало. Я добавил более чистую версию кода, она должна быть более понятной, но спросите, если у вас есть сомнения. пс. Если вы оставите там плоскость, будет небольшое несоответствие в пределах осей, которое я не совсем понимаю, и могут потребоваться специальные настройки вручную. - person Andrea; 22.01.2020
comment
Вот возможный обходной путь для несоответствия, но я бы не стал его использовать. Это похоже на проблему с matplotlib, и они могут захотеть исправить это поведение в будущем. - person Andrea; 22.01.2020
comment
Именно из-за небольшого несоответствия/смещения в предыдущей версии, которую я и просил уточнить. Ваш обходной путь выглядит достаточно хорошо для меня. Спасибо!! - person Alexis.Rolland; 23.01.2020