『Python数値計算ノート』ではアフィリエイトプログラムを利用して商品を紹介しています。

【Matplotlib】視点の変更 (仰角と方位角の設定)

Axes3D.view_init(elev, azim)

 Matplotlib では、Axes3D.view_init(elev, azim) を使って、三次元グラフを「どの方向から見るか」を指定できます (下図の矢印が視線の方向)。
 方位角(azimuth)と仰角(elevation)の説明図
引数の elev, azim は、それぞれ elevation angle (仰角)azimuth (方位角) の略で、上図の θ, φ に相当するパラメータです(”azimuth” は「アジマス」と発音します)。
 
Matplotlib をインポートして、適当な三次元グラフをプロットしてみます。

# MATPLOTLIB_AXES3D_INIT_VIEW

# In[1]

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

fig = plt.figure(figsize = (8, 6))
ax = fig.add_subplot(111, projection='3d')

# 軸ラベルを設定
ax.set_xlabel("x", size=16)
ax.set_ylabel("y", size=16)
ax.set_zlabel("z", size=16)

# 分割数
n = 256

# x-y格子点を生成
x = np.linspace(-4 * np.pi, 4 * np.pi, n)
y = np.linspace(-4 * np.pi, 4 * np.pi, n)
X, Y = np.meshgrid(x, y)

# 格子点の高度Zを計算
Z = X**2 - Y**2

# 曲面を描画
ax.plot_surface(X, Y, Z, cmap = "gnuplot")

Matplotlib view_initをデフォルト設定で描いた三次元グラフ
elev, azim のデフォルト値は、それぞれ 30, -60 です。つまり、デフォルト設定では、仰角 30°、方位角 – 60°の方角からグラフを見ていることになります。
elev = 0 (仰角 0°) に設定してみましょう。

# In[2]

# 視点を仰角 0°、方位角 -60°に設定
ax.view_init(elev=0)

display(fig)

仰角を0°に設定(elevation angle=0)
x-y 平面と平行な視点となっていますね。
次は方位角を 0°にしてみます。

# In[3]

# 視点を仰角30°、方位角0°に設定
ax.view_init(azim=0)

display(fig)

方位角を0°に設定(azimuth=0)
視線の方向は x 軸の正から負の方向となっています。この記事の一番上に掲載した図を見て、方位角を 0°にした時の視線方向をイメージしてください。
 
グラフを真上から見る時は仰角を 90°に設定します。

# In[4]

# 真上からの視点に設定
ax.view_init(elev=90)

display(fig)

Matplotlib 3Dグラフを上から見た図
次のコードを実行すると、仰角を 30°に固定して、方位角を 0°から 45°刻みに変化させながら三次元プロットエリア (Axes3D オブジェクト) を表示します。

# In[5]

# 8個のAxes3Dを2列に並べる
fig, ax = plt.subplots(4, 2, figsize=(10,18), subplot_kw=dict(projection='3d'))

ct = 0

# 仰角を30°に固定し、方位角を0°から45°刻みに変化させながらプロットエリアを表示
for k in ax.ravel():
    k.view_init(azim=ct*45)
    k.set_title("elev=30, azim={}".format(ct*45))
    k.set_xlabel("x", size=16)
    k.set_ylabel("y", size=16)
    k.set_zlabel("z", size=16)
    ct += 1

plt.show()

Matplotlib 3D 視点の変更(方位角を小刻みに変化させる)
次のコードを実行すると、方位角を -60°に固定して、仰角を 0°から 15°刻みに変化させながら三次元プロットエリア (Axes3D オブジェクト) を表示します。

# In[6]

# 3×2個の3DAxesオブジェクトを作成
fig, ax = plt.subplots(3, 2, figsize=(10,16), subplot_kw=dict(projection='3d'))

ct = 0

# 方位角を-60°に固定し、仰角を0°から15°刻みに変化させる
for k in ax.ravel():
    k.view_init(elev=ct*15)
    k.set_title("elev={}, azim=-60".format(ct*15))
    k.set_xlabel("x", size=16)
    k.set_ylabel("y", size=16)
    k.set_zlabel("z", size=16)
    ct += 1

plt.show()

Matplotlib 3D 視点の変更(仰角を小刻みに変化させる)
仰角と方位角は、Axes3D のコンストラクタで予め設定しておくことも可能です。

# In[7]

fig = plt.figure(figsize = (8, 6))

# 仰角と方位角を45°に設定して三次元プロットエリアを作成
ax = fig.add_subplot(111, projection='3d', elev=45, azim=45)

# 格子点の高度Zを計算
W = X - Y

# 曲面を描画
ax.plot_surface(X, Y, W, cmap="Greens")

plt.show()

Matplotlib コンストラクタでelev, azimを設定する

コメント

  1. HNaito より:

    一枚の fig に In[5] や In[6] プログラムのように多数のプロットを描くことはあまりないので弊害は小さいのですが、Google Colab で実行すると下辺と右辺が欠けます ( 実際には 目盛の数値や軸ラベルの一部 ) 。簡単に回避できる方法があるようでしたら教えてください。

    • あとりえこばと より:

      Matplotlib では Figure の中に Axes や Axes3D を収めるので、Figure のサイズにゆとりをもたせるのが一番手っ取り早いと思います。Google Colab で試してみると、figsize=(14,24) ぐらいに設定すると大丈夫でした。なお、本文中の設定でも savefig などで PNG ファイルなどに書き出せば、きちんと収まると思います(記事本文中に掲載した図)。

      • HNaito より:

        私のPCの Google Colab では、z軸のラベルまで表示できるサイズは、figsize=(14, 36) でした。plt.savefig(“view.png”) では figsize=(10, 18) できちんと収まりました。ご回答ありがとうございました。

  2. HNaito より:

    新しく本記事を追加していただき、ありがとうございました。仰角と方位角を変化させたときの一覧を載せていただいたので、これ以上はないくらいの明解さでした。