wxPythonのwx.Panelを使ってマンデルブロ集合を描画

した。wx.PaintDCを使ってPanelの上に描画している。OpenGLのディスプレイリストのような機能がないので(よく探していないので実際はあるかもしれない)、1度の描画にしばらく時間がかかる。なので、計算結果がすぐにみられるようにピクセルの描画の順番を工夫した。ピクセルを左上から右下に順番に描画していくのではなくて、描画処理を2パスに分けて1パス目は

     
     
     
     
     

の■にあたるピクセルを描画して2パス目はそれ以外を描画、というふうにして結果がすぐにわかるようにした。

# coding: utf-8

import wx

class Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "mandelbrot", pos=(0,0),size=(450,450))
        self.panel = wx.Panel(self, size=(400,400))
        self.resol = self.panel.GetSize()
        self.panel.Bind(wx.EVT_PAINT, self.OnDraw)
        self.mandel()
    def mandel(self):
        # [(-2.5, -2.0), (+1.5,+2.0)]の矩形で計算
        w,h = self.resol
        self.points = [[0]*w for i in xrange(h)]
        coef = 30
        for i in xrange(h):
            for j in xrange(w):
                a = -2.5 + 4./w*j
                b = -2.0 + 4./h*i
                c = complex(a, b)
                z = 0j
                countup = 0
                for k in xrange(coef):
                    z = z*z + c
                    if abs(z) > 1e10:
                        break
                    countup += 1
                self.points[i][j] = int(255.0 * countup / coef)
    def OnDraw(self, event):
        dc = wx.PaintDC(self.panel)
        w,h = self.resol
        """
        for i in xrange(h):
            for j in xrange(w):
                c = self.points[i][j]
                dc.SetBrush(wx.Brush(wx.Colour(c, c, c)))
                dc.DrawPoint(i, j)
        """
        def draw(y, x):
            c = self.points[y][x]
            dc.SetPen(wx.Pen(wx.Colour(c,c,c)))
            dc.DrawPoint(x, y)
        # . . . .
        #  . . .
        # . . . .
        #  . . . 
        # -------
        #  . . .
        # . . . .
        #  . . .
        # . . . .
        # -------
        # と塗り分けることで情報の提示を高速化
        for i in xrange(h):
            for j in xrange([0,1][i%2], w, 2):
                draw(i, j)
        for i in xrange(h):
            for j in xrange([1,0][i%2], w, 2):
                draw(i, j)

if __name__ == '__main__':
    app = wx.PySimpleApp()
    Frame().Show()
    app.MainLoop()