2014年1月27日月曜日

matplotlibでorthogonal projectionの3D plot

グラフを作るのに、gnuplotもよいけど、pythonからmatplotlibを使うのももよいですよね。
下の図は、matplotlibで3次元プロットした例ですが、遠近感(perspective effect)が観られます。



しばしば、そのような遠近感の効果をなくして3次元プロットしてみたいという要求があります。
言い換えると、透視投影(perspective projection)から平行投影(orthogonal projection)に変更したいわけです。調べてみたところ、mpl_toolkits.mplot3dの中のproj3dにあるpersp_transformation関数を書き換えればよいということです。

ということで、以下のようにしてみました。

#!/usr/bin/env python

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

#--------- Patch for Orthogonal Projection of 3Dplot ------
from mpl_toolkits.mplot3d import proj3d
def orthogonal_transformation(zfront, zback):
    a = 2/(zfront-zback)
    b = -1*(zfront+zback)/(zfront-zback)
    c = zback
    return numpy.array([[1,0,0,0],
                        [0,1,0,0],
                        [0,0,a,b],
                        [0,0,0,c]])
proj3d.persp_transformation = orthogonal_transformation
#-----------------------------------------------------

#---------- make canvas for figure -------------
fig = plt.figure(figsize=(6, 6), facecolor='w')

#---------- 3D Plot ----------------
ax = fig.add_subplot(111, projection='3d', axisbg='w')

# making sample data
x = numpy.arange(-3, 3, 0.25)
y = numpy.arange(-3, 3, 0.25)
xm, ym = numpy.meshgrid(x, y)
z = numpy.exp(-1*xm**2) * numpy.exp(-1*ym**2)

# draw x, y, z labels
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')

# plot 3d
surf = ax.plot_surface(xm, ym, z, rstride=1, cstride=1,
        linewidth=1, antialiased=True)

# set view point
ax.view_init(elev=30, azim=-45)

# display the figures
plt.show()
このスクリプトでプロットすると、下のようになりました。





0 件のコメント: