Pythonプログラミング(ステップ7・配列・線形代数・二次曲面)
このページでは、NumPyライブラリの線形演算機能を用いる例として、二次曲面とその描画について考えてみる。
球面の描画
三次元座標を
緯度(
matplotlibライブラリのplot_surface()関数は、 このように、メルカトル図法的に座標点を与えることで、三次元内の曲面を描画することができる。
# coding: utf-8 from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np import math ndiv = 100 phi = np.linspace(0, 2 * math.pi, ndiv) theta = np.linspace(0, math.pi, ndiv) r = 1 x = np.empty((ndiv,ndiv),dtype='float32') y = np.empty((ndiv,ndiv),dtype='float32') z = np.empty((ndiv,ndiv),dtype='float32') for i in range(ndiv): t = theta[i] for j in range(ndiv): p = phi[j] x[i,j] = r * math.sin(t) * math.cos(p) y[i,j] = r * math.sin(t) * math.sin(p) z[i,j] = r * math.cos(t) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot_surface(x, y, z, color='red', antialiased=True, shade=True) plt.show()
二次曲面の描画
以上を踏まえて、さらに一般的に
一般の二次曲面は上式に
上式は
ここで、線形代数の知識を思い出すと、
固有値が全て正の場合:楕円体の描画
固有値が全て正の場合は、 変数をスケール変換して
以上を踏まえると、
の固有値と固有ベクトルを求め、 を得る- 半径
球面の座標 を生成する。 - それぞれの座標軸を固有値の平方根倍だけスケールして、
を得る。 で得られたデータ点について(球と同様に)描画する。
# coding: utf-8 from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np import math ndiv = 30 phi = np.linspace(0, 2 * math.pi, ndiv) theta = np.linspace(0, math.pi, ndiv) u = np.empty((ndiv,ndiv),dtype='float32') v = np.empty((ndiv,ndiv),dtype='float32') w = np.empty((ndiv,ndiv),dtype='float32') x = np.empty((ndiv,ndiv),dtype='float32') y = np.empty((ndiv,ndiv),dtype='float32') z = np.empty((ndiv,ndiv),dtype='float32') A = np.array([ [ 1, 0.5,-0.5], [ 0.5, 0.7, 0.2], [-0.5, 0.2, 1.3] ], dtype='float32') C = 1 eig,P = np.linalg.eig(A) print('eigen values=',eig) print('P=\n',P) for i in range(ndiv): t = theta[i] for j in range(ndiv): p = phi[j] u[i,j] = math.sqrt(C/eig[0]) * math.sin(t) * math.cos(p) v[i,j] = math.sqrt(C/eig[1]) * math.sin(t) * math.sin(p) w[i,j] = math.sqrt(C/eig[2]) * math.cos(t) for i in range(ndiv): for j in range(ndiv): x[i,j] = P[0,0] * u[i,j] + P[0,1] * v[i,j] + P[0,2] * w[i,j] y[i,j] = P[1,0] * u[i,j] + P[1,1] * v[i,j] + P[1,2] * w[i,j] z[i,j] = P[2,0] * u[i,j] + P[2,1] * v[i,j] + P[2,2] * w[i,j] fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.view_init(elev=45, azim=45) ax.plot_surface(x, y, z, color='red', antialiased=True, shade=True) plt.show()
上のコードの出力結果の例を以下に示す。
ax.view_init(elev=45, azim=45)
の値(45)を変えることで、視点の向きを調整することができる。
双曲面の描画
z軸に沿った「高さ」を
# coding: utf-8 from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np import math ndiv = 50 phi = np.linspace(0, 2 * math.pi, ndiv) xi = np.linspace(-2, 2, ndiv) x = np.empty((ndiv,ndiv),dtype='float32') y = np.empty((ndiv,ndiv),dtype='float32') z = np.empty((ndiv,ndiv),dtype='float32') C = 1 for i in range(ndiv): t = xi[i] for j in range(ndiv): p = phi[j] r = math.sqrt(C + t**2) x[i,j] = r * math.cos(p) y[i,j] = r * math.sin(p) z[i,j] = t fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.view_init(elev=30, azim=45) ax.plot_surface(x, y, z, color='red', linewidth=1, antialiased=True, shade=True) plt.show()
練習:二葉双曲面
発展練習:二次曲面
三次元中の二次曲面のうち、
ヒント