数式のグラフ化プログラム(4)

コメントでいただいた通りに”刻み幅”を指定できるようにした。そんなにたいしたプログラムではないけれども、だいぶ使いやすくなったと思う。

  • 使い方
    • 描きたいグラフのxとyの関数形を入力する。tを媒介変数とする。Pythonでの数式記法で。
    • yをxの関数としたいときは、xの関数形をtとし、yをtの関数として与えればよい。
    • tの範囲(最大、最小値)を決め、刻み幅も指定する。
    • すべて入力したらボタンを押す。

いろいろやってみる。まず、y=exp(-t/10)*cos(t), x=exp(-t/10)*sin(t)のとき。刻み幅を決められるので滑らかに表示できうようになった。

次に、リサージュ図形。x=cos(t), y=sin(2*t)のとき。

また、x=cos(2*t), y=sin(3*t)のとき。

また、x=cos(2*t), y=sin(5*t)のとき。

また、x=cos(5*t), y=sin(6*t)のとき。

また、x=cos(sqrt(2)*t), y=sin(sqrt(3)*t)のとき。

ソースコード

# coding: utf-8
# -------------------------------------------------------------------
# PlotTool2                               ver.1.0 (2008/12/07)
#                                               
# -------------------------------------------------------------------
import wx
import os
from pylab import *

class MainFrame(wx.Frame):
    def __init__(self, id, title):
        width, height = 600, 700
        wx.Frame.__init__(self, id, title=u"Plot Tool",
                          size=wx.Size(width, height))
        
        self.current = "  "
        self.sb = self.CreateStatusBar(2)
        self.sb.SetStatusWidths([-1, 150])
        self.sb.SetStatusText(self.current)

        Sizer0 = wx.BoxSizer(wx.VERTICAL)
        Sizer1 = wx.BoxSizer(wx.HORIZONTAL)
        Sizer2 = wx.BoxSizer(wx.HORIZONTAL)
        Sizer4 = wx.BoxSizer(wx.HORIZONTAL)
        
        Pan = wx.Panel(self, -1)
        StTxt1 = wx.StaticText(Pan, -1, u"xの数式 x=f(t):")
        StTxt6 = wx.StaticText(Pan, -1, u"yの数式 y=g(t):")
        self.TxtCtl1 = wx.TextCtrl(Pan, -1, "", size=(300,-1))
        self.TxtCtl6 = wx.TextCtrl(Pan, -1, "", size=(300,-1))
        self.TxtCtl2 = wx.TextCtrl(Pan, -1, "", size=(60,-1))
        self.TxtCtl3 = wx.TextCtrl(Pan, -1, "", size=(60,-1))
        self.TxtCtl7 = wx.TextCtrl(Pan, -1, "", size=(60,-1))
        StTxt2 = wx.StaticText(Pan, -1, u"【数式の入力はPythonでの記法に従ってください】")
        BtnPlt = wx.Button(Pan, -1, u"で数式をプロットする")
        StTxt3 = wx.StaticText(Pan, -1, u"tの表示範囲:")
        StTxt4 = wx.StaticText(Pan, -1, u"から")
        StTxt5 = wx.StaticText(Pan, -1, u"までを刻み幅")

        bmp = wx.EmptyBitmap(500,500)
        self.bmpFlag = wx.StaticBitmap(Pan, -1, bmp)
        self.bmpFlag.SetBitmap(bmp)   
        
        BtnPlt.Bind(wx.EVT_BUTTON, self.OnPlot)

        Sizer1.Add(StTxt1, 0, wx.ALL, 2)
        Sizer1.Add(self.TxtCtl1, 0, wx.ALL, 2)
        Sizer4.Add(StTxt6, 0, wx.ALL, 2)
        Sizer4.Add(self.TxtCtl6, 0, wx.ALL, 2)
        Sizer2.Add(StTxt3, 0, wx.ALL, 2)
        Sizer2.Add(self.TxtCtl2, 0, wx.ALL, 2)
        Sizer2.Add(StTxt4, 0, wx.ALL, 2)
        Sizer2.Add(self.TxtCtl3, 0, wx.ALL, 2)
        Sizer2.Add(StTxt5, 0, wx.ALL, 2)
        Sizer2.Add(self.TxtCtl7, 0, wx.ALL, 2)
        Sizer2.Add(BtnPlt, 0, wx.RIGHT, 2)
        
        Sizer0.Add(StTxt2,  0, wx.ALL, 2)
        Sizer0.Add(Sizer1, 0, wx.ALL, 2)
        Sizer0.Add(Sizer4, 0, wx.ALL, 2)
        Sizer0.Add(Sizer2,  0, wx.ALL, 2)
        Sizer0.Add(self.bmpFlag,  0, wx.ALL, 5)

        Pan.SetSizer(Sizer0)
        Sizer0.Fit(self)
        
    def OnPlot(self, event):
        susikix = self.TxtCtl1.GetValue()
        susikiy = self.TxtCtl6.GetValue()
        tmin = self.TxtCtl2.GetValue()
        tmax = self.TxtCtl3.GetValue()
        dt = float(self.TxtCtl7.GetValue())
        if len(susikix) == 0 or len(susikiy) == 0:   # input error
            self.sb.SetStatusText(u"ERR: 数式が入力されていません.")        
        else:
            xlist = []
            ylist = []
            vtmin = float(tmin)
            vtmax = float(tmax)
            ndt = int((vtmax-vtmin)/float(dt))
            fig = figure()
            ax = fig.add_subplot(111)
            for i in xrange(ndt+1):
                t = vtmin + dt*i
                f = eval(susikix)
                g = eval(susikiy)
                xlist.append(f)
                ylist.append(g)
            ax.plot(xlist, ylist, 'k', color='r', linewidth=2.0)
            ax.autoscale_view()
            xlabel('x')
            ylabel('y')
            tname = susikix + ", "+susikiy
            title(tname)
            filen = os.path.join(os.getcwd(), "tempfig")
            fig.savefig(filen, dpi=60)                              
            bmp = wx.Bitmap("tempfig.png")      #ここも修正したらきれいな表示になった
            self.bmpFlag.SetBitmap(bmp)
            self.sb.SetStatusText(u"%sと%sが読み込まれました."
                                  % (susikix, susikiy))
        
class Application(wx.App):
    def OnInit(self):
        frame = MainFrame(None, -1)
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

def main():
    import time
    
    app = Application(0)
    print u"info> 起動時刻: %s." % time.ctime(time.time())
    appl_boot_path = os.getcwd()
    print u"info> 起動ディレクトリ: %s." % appl_boot_path
    app.MainLoop()

if __name__ == '__main__':
    main()
#eof