matplotlib
Трехмерные графики
Поиск…
замечания
Трехмерное построение в matplotlib исторически было немного клочья, поскольку движок рендеринга по своей сути 2d. Тот факт, что 3D-установки визуализируются путем построения одного 2-го блока после другого, подразумевает, что часто возникают проблемы, связанные с кажущейся глубиной объектов. Ядро проблемы состоит в том, что два несвязанных объекта могут либо полностью отстать, либо полностью друг над другом, что приводит к артефактам, как показано на рисунке ниже двух взаимосвязанных колец (щелкните для анимированного gif):
Однако это может быть исправлено. Этот артефакт существует только при построении нескольких поверхностей на одном и том же участке - каждый из них отображается как плоская двумерная фигура с одним параметром, определяющим расстояние обзора. Вы заметите, что одна сложная поверхность не испытывает такой же проблемы.
Способ исправить это - объединить объекты сюжета вместе с использованием прозрачных мостов:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from scipy.special import erf
fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(0, 6, 0.25)
Y = np.arange(0, 6, 0.25)
X, Y = np.meshgrid(X, Y)
Z1 = np.empty_like(X)
Z2 = np.empty_like(X)
C1 = np.empty_like(X, dtype=object)
C2 = np.empty_like(X, dtype=object)
for i in range(len(X)):
for j in range(len(X[0])):
z1 = 0.5*(erf((X[i,j]+Y[i,j]-4.5)*0.5)+1)
z2 = 0.5*(erf((-X[i,j]-Y[i,j]+4.5)*0.5)+1)
Z1[i,j] = z1
Z2[i,j] = z2
# If you want to grab a colour from a matplotlib cmap function,
# you need to give it a number between 0 and 1. z1 and z2 are
# already in this range, so it just works as is.
C1[i,j] = plt.get_cmap("Oranges")(z1)
C2[i,j] = plt.get_cmap("Blues")(z2)
# Create a transparent bridge region
X_bridge = np.vstack([X[-1,:],X[-1,:]])
Y_bridge = np.vstack([Y[-1,:],Y[-1,:]])
Z_bridge = np.vstack([Z1[-1,:],Z2[-1,:]])
color_bridge = np.empty_like(Z_bridge, dtype=object)
color_bridge.fill((1,1,1,0)) # RGBA colour, onlt the last component matters - it represents the alpha / opacity.
# Join the two surfaces flipping one of them (using also the bridge)
X_full = np.vstack([X, X_bridge, np.flipud(X)])
Y_full = np.vstack([Y, Y_bridge, np.flipud(Y)])
Z_full = np.vstack([Z1, Z_bridge, np.flipud(Z2)])
color_full = np.vstack([C1, color_bridge, np.flipud(C2)])
surf_full = ax.plot_surface(X_full, Y_full, Z_full, rstride=1, cstride=1,
facecolors=color_full, linewidth=0,
antialiased=False)
plt.show()
Создание трехмерных осей
По умолчанию оси Matplotlib являются двумерными. Чтобы создать трехмерные графики, нам нужно импортировать класс Axes3D
из инструментария mplot3d , который позволит использовать новый вид проекции для осей, а именно '3d'
:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
Помимо прямых обобщений двумерных графиков (таких как линейные графики , диаграммы рассеяния , штриховые графики , контурные графики ), доступны несколько методов построения поверхности , например ax.plot_surface
:
# generate example data
import numpy as np
x,y = np.meshgrid(np.linspace(-1,1,15),np.linspace(-1,1,15))
z = np.cos(x*np.pi)*np.sin(y*np.pi)
# actual plotting example
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# rstride and cstride are row and column stride (step size)
ax.plot_surface(x,y,z,rstride=1,cstride=1,cmap='hot')
ax.set_xlabel(r'$x$')
ax.set_ylabel(r'$y$')
ax.set_zlabel(r'$\cos(\pi x) \sin(\pi y)$')
plt.show()