Matplotlibで3次元空間に円を描画、透過、境界を描画、線を引く | USHITORA Lab.
スポンサーリンク

Matplotlibで3次元空間に円を描画、透過、境界を描画、線を引く

Python

この記事では、PythonのMatplotlibを使用して3次元空間に球や面、線などを描画する方法について解説する。なお、ここで作成した画像の一部は

標準正規分布の規格化条件から、M次元単位球の表面積を求める
正規分布$$\mathcal{N}(x|\mu,\sigma)=\frac{1}{\sqrt{2\pi\sigma^2}}\exp\{-\frac{1}{2\sigma^2}(x-\mu)\}$$は様々な特徴...

において利用されている。

球体の描画

基本

球を描画するには、極座標の考え方を利用する必要がある。直交座標 \(x,y,z\) を極座標 \(r,\theta_1,\theta_2\) に変換するときには

$$x_1 = r\cos{\theta_2}\sin{\theta_1}$$

$$x_2 = r\sin{\theta_2}\sin{\theta_1}$$

$$x_3 = r\cos{\theta_1}$$

の対応関係を用いる。

np.linspaceで \([0,\frac{\pi}{2}]\) の値をとる \(\theta_1,\theta_2\) の値を100個ずつ生成する。そして、球を3次元空間に描画するax.plot_surfaceは引数に2次元配列をとるので、np.meshgridを用いて \(\theta_1,\theta_2\) 配列の形状を変換する。これを用いて \(x,y,z\) を計算すると、 \(x,y,z\) も2次元配列として得られる。

最後に描画領域と3D軸を作成してax.plot_surfaceで描画すると、上図のような半径 \(r\) の \(\frac{1}{8}\) 円が得られる。

np.meshgridについての詳細は以下を参照のこと。

matplotlibで3次元空間に2次元ヒストグラムを表示する方法
この記事では、PythonのMatplotlibを用いて、XとYの2種類の値をとる2次元変数(X, Y)についての2次元ヒストグラムを、3次元空間に立体的に表示する方法を説明する。その方法を用いれば、この記事のアイキャッチ画像のようなグラフ...

以下、上記のコードと異なる部分のみを掲載する。

透過

ax.plot_surfaceを用いて描画する際に、alpha値を指定することで描画図形を透過することができる。このalpha値は0~1の間で指定することができ、1に近い値をとるほど濃く描画される。

領域と境界の描画

続いて、 \(r,\theta_1,\theta_2\) をそれぞれ \([r,r+dr], [\phi_1,\phi_1+d\phi_1], [\phi_2,\phi_2+d\phi_2]\) の範囲で動かしたときに得られる領域を描画する。このコードの例では、具体的な値として \(r=3, dr=0.3, \phi_1=\phi_2=\frac{\pi}{12}, d\phi_1=d\phi_2=\frac{\pi}{12}\) を代入している。

np.linspaceで \([\frac{\pi}{12},\frac{\pi}{6}]\) の範囲を動く \(\phi_1, \phi_2\) を新たに作成する。コードの第1・第2ブロックでは、この \(\phi_1, \phi_2\) を用いて、半径が \(r=3\) のときと \(r+dr=3.3\) のときの球の一部を描画している。

第1・第2ブロックの内容のみ表示

あとはこの2曲面を底面とした場合の4つの側面を描画すればよいのであるが、そのためには再びnp.linspaceを用いて、 \([3.0,3.3]\) の区間を動く \(r_b\) を作成する。これと \(\phi_1, \phi_2\) の組み合わせで境界面を描画する。第4ブロックでは \(\phi_2\) の値を \(\frac{\pi}{12}\) に固定し、 \(\phi_1\) と \(r_b\) のみを動かすことで境界を作成した。同様に、第6ブロックでは \(\phi_2\) の値を \(\frac{\pi}{6}\) に固定して \(\phi_1\) と \(r_b\) のみを動かし、第5・第7ブロックでは \(\phi_1\) の値を \(\frac{\pi}{12}\) または \(\frac{\pi}{6}\) に固定して \(\phi_2\) と \(r_b\) のみを動かした。

線を引く

軸を入れる(基本)

線を引くためにはax.plotを使用する。引数のリストはそれぞれ通る点の \(x,y,z\) 座標を示しており、1行目は点(0,0,0)と(3,0,0)、2行目は点(0,0,0)と(0,3,0)、3行目は点(0,0,0)と(0,0,3)を通る線分を描画している。

任意の線分を引く+透過

直交座標→極座標変換の関係式を用いて点の \(x,y,z\) 座標をしてやると、原点から先程の領域の線を引くことができる。また、ここでもalpha値を指定してやることで透過効果を加えることができる。

曲線を引く

先程描画した線のうち2本を消去し、今度は \(\theta_1\) の回転方向の曲線を描画する。球面や境界を描画するときには変数のうち1つを固定して2つを動かした(配列で指定した) が、線を描画するときにもそれと同じ考えで、変数のうち2つを固定し1つのみを動かす。今回は \(\theta_1\) 方向の回転曲線を描画するため、 \(r\) と \(\theta_2\) を固定し \(\theta_1\) のみを動かして得られた各点の座標を、ax.plotに渡して描画した。

まとめ

以上の技術をすべて合わせると、以下のような作図が可能になる。

コメント