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

昨日のプログラムについてコメントをいただいたので修正というか、別のものというか、プログラムを変えてみました。x,yの両方の関数形をtの関数として与えるようにしました。

  • 起動画面:x、yをtの関数として与えます。tの範囲も指定します。

  • 実行例1:こんな感じの図が描けます。

  • 実行例2:tの範囲によっては曲線がガタガタです。今はtの最小値と最大値の間を100分割して点を置いてますが、少なすぎるようです。分割点数か刻み幅を指定できるようにした方がよさそうです。


しかし図がきれいでないので、画像ファイルの貼り付け方を変えた。savefigでファイルに落すときにdpi=で解像度を指定する。するときれいな表示になった。

  • 画像貼り付け方修正後

とりあえずのソースPlotTool2.pywは以下の通り。

# coding: utf-8
# -------------------------------------------------------------------
# PlotTool2                               ver.1.0 (2008/12/05)
#                                               
# -------------------------------------------------------------------
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=(100,-1))
        self.TxtCtl3 = wx.TextCtrl(Pan, -1, "", size=(100,-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(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()
        if len(susikix) == 0 or len(susikiy) == 0:   # input error
            self.sb.SetStatusText(u"ERR: 数式が入力されていません.")        
        else:
            xlist = []
            ylist = []
            vtmin = float(tmin)
            vtmax = float(tmax)
            dt = (vtmax-vtmin)/100.
            fig = figure()
            ax = fig.add_subplot(111)
            for i in xrange(101):
                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