# Matplotlib 立體圖

``````import numpy as np
import matplotlib.pyplot as plt

start = 0
end = np.pi * 20
step = np.pi / 180

x = np.arange(start, end, step)
y = np.sin(x)
z = np.cos(x)

# 取得 mpl_toolkits.mplot3d.axes3d.Axes3D 實例
ax = plt.axes(projection='3d')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.plot(x, y, z)
plt.title('Axes3D Plot')
plt.show()
``````

``````import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D

fig = plt.gcf()
ax = Axes3D(fig)
``````

``````import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm

def f(x, y):
n = np.sqrt(np.power(x, 2) + np.power(y, 2)) / 180 * np.pi
return np.cos(n) + np.cos(3 * n)

width = 200
step = 10

x = np.arange(-width, width, step)
y = np.arange(-width, width, step)

X, Y = np.meshgrid(x, y)
Z = f(X, Y)

ax = plt.axes(projection='3d')
ax.plot_surface(X, Y, Z, cmap = cm.coolwarm)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.set_box_aspect((1, 1, 0.5))
plt.title('Axes3D Plot Surface')
plt.show()
``````

`plot_surface` 預設並不分層著色，這邊指定了 `cm.coolwarm`，值高的部份會是代表熱度的紅色，值低的部份會是藍色，預設的圖形在三個軸是 1:1:1，也就是會以正立方體來繪製，這會讓這個函式圖的 z 軸顯得過於突冗，可以透過 `set_box_aspect` 來調整比例，執行後的圖形如下：

``````from math import floor
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm

def blending(t):
return 6 * (t ** 5) - 15 * (t ** 4) + 10 * (t ** 3)

def lerp(g1, g2, t):
return g1 + t * (g2 - g1)

return [dy, dx + dy, dx, dx - dy, -dy, -dx - dy, -dx, -dx + dy][hashvalue % 8];

rand_table = np.random.randint(255, size = 256).tolist()
def _perlin2(x, y):
xi = floor(x)
yi = floor(y)

aa = rand_table[
(rand_table[xi % 256] + yi) % 256
]
ba = rand_table[
(rand_table[(xi + 1) % 256] + yi) % 256
]
ab = rand_table[
(rand_table[xi % 256] + yi + 1) % 256
]
bb = rand_table[
(rand_table[(xi + 1) % 256] + yi + 1) % 256
]

dx = x - xi
dy = y - yi

u = blending(dx)
v = blending(dy)

g2 = lerp(grad2(ab, dx, dy - 1), grad2(bb, dx - 1, dy - 1), u)

return lerp(g1, g2, v)
_perlin2 = np.frompyfunc(_perlin2, 2, 1)

def perlin2(x, y):
cx, cy = np.meshgrid(x, y)
return _perlin2(cx, cy).astype(np.float)

width = 100
x = np.arange(width)
y = np.arange(width)

X, Y = np.meshgrid(x, y)
Z = perlin2(x / 25, y / 25)

ax = plt.axes(projection='3d')
ax.plot_surface(X, Y, Z, cmap = cm.gist_earth) # 用地形高度顏色來著色
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.set_box_aspect((1, 1, 25 / width))
plt.title('Perlin noise')
plt.show()
``````