【はじめてのPython】マンデルブロ集合を動き回る②

ITスキル
  • マンデルブロ集合を自由に動き回るGUIを作成して、自由に遊ぶようにするための方法を解説します
スポンサーリンク

前回までのおさらい

前々回から前回にかけて、マンデルブロ集合を使って配列を動かす処理を実装してきました。

今回は自由に拡大縮小できるようにする実装をすることで、マンデルブロ集合の中にある美しい図形を探検できるようにします。

前回は、上下左右に動かした際に、新しく表示される部分だけを計算して表示させるという処理をすることで、処理の高速化を実現しました。

拡大と縮小

ボタンの設置

今回は拡大と縮小を行いますが、単純に2倍に拡大する、2分の1に縮小する、というボタンを設置するのだと、少し大変です。

というのも、どうしてもそのような計算の過程で小数点以下の桁数が多くなり、計算が重くなってしまうからです。

そこで今回は、下記の画像のように、一番最初に表示されている倍率を起点として、好きな倍率に変更できるように処理を行います。

ここは簡単で、前回作ったcreate_widgetsの関数の中に次のようなものを組み込むだけです。

        self.control_frame = tk.Frame(self.master)
        self.control_frame.pack(side=tk.BOTTOM) 
        self.button = tk.Button(self.control_frame, text = "x1.0", command = self.magnific_1, width = 16)
        self.button.pack(side = tk.LEFT)
        self.button = tk.Button(self.control_frame, text = "x2.0", command = self.magnific_2, width = 16)
        self.button.pack(side = tk.LEFT)
        self.button = tk.Button(self.control_frame, text = "x5.0", command = self.magnific_5, width = 16)
        self.button.pack(side = tk.LEFT)
        self.button = tk.Button(self.control_frame, text = "x10.0", command = self.magnific_10, width = 16)
        self.button.pack(side = tk.LEFT)
        self.button = tk.Button(self.control_frame, text = "x20.0", command = self.magnific_20, width = 16)
        self.button.pack(side = tk.LEFT)
        self.button = tk.Button(self.control_frame, text = "x50.0", command = self.magnific_50, width = 16)
        self.button.pack(side = tk.LEFT)
        self.button = tk.Button(self.control_frame, text = "x100.0", command = self.magnific_100, width = 16)
        self.button.pack(side = tk.LEFT)
        self.button = tk.Button(self.control_frame, text = "x200.0", command = self.magnific_200, width = 16)
        self.button.pack(side = tk.LEFT)
        self.button = tk.Button(self.control_frame, text = "x500.0", command = self.magnific_500, width = 16)
        self.button.pack(side = tk.LEFT)
        self.button = tk.Button(self.control_frame, text = "x1,000.0", command = self.magnific_1000, width = 16)
        self.button.pack(side = tk.LEFT)
        self.button = tk.Button(self.control_frame, text = "x2,000.0", command = self.magnific_2000, width = 16)
        self.button.pack(side = tk.LEFT)
        self.button = tk.Button(self.control_frame, text = "x5,000.0", command = self.magnific_5000, width = 16)
        self.button.pack(side = tk.LEFT)
        
        self.status_frame = tk.Frame(self.master)
        self.status_frame.pack(side=tk.BOTTOM)
        self.text = tk.StringVar()
        self.text.set('倍率:' + str(self.magnific) + '倍/' \
                      + 'top: ' + str(self.top) + ' / ' \
                      + 'bottom: ' + str(self.bottom) + ' / ' \
                      + 'left: ' + str(self.left) + ' / ' \
                      + 'right: ' + str(self.right) \
                     )
        self.label = tk.Label(self.status_frame, textvariable=self.text)
        self.label.pack()

倍率変更の処理

続いて実際に「magnific_xx」の関数の処理を入れていきます。
この時、コードの省略のため、magnific_xという関数を作成して、倍率だけを変更してそれぞれ呼び出せるように設定します。

    def magnific_x(self, next_magnific):
        self.top = round(self.ver_mid + (self.ver_lng) / 2 * self.magnific / next_magnific, self.round_digit)
        self.bottom = round(self.ver_mid - (self.ver_lng) / 2 * self.magnific / next_magnific, self.round_digit)
        self.right = round(self.hor_mid + (self.hor_lng) / 2 * self.magnific / next_magnific, self.round_digit)
        self.left = round(self.hor_mid - (self.hor_lng) / 2 * self.magnific / next_magnific, self.round_digit)
        self.ver_lng, self.hor_lng = round((self.top - self.bottom), self.round_digit), round((self.right - self.left), self.round_digit)
        self.magnific = next_magnific
        self.Mandelbrot = set_mandelbrot(self.left, self.right, self.bottom, self.top, self.resolution, self.max)
        plt.imshow(self.Mandelbrot, cmap="jet")
        self.canvas.draw()
        self.text.set('倍率:' + str(self.magnific) + '倍/' \
                      + 'top: ' + str(self.top) + ' / ' \
                      + 'bottom: ' + str(self.bottom) + ' / ' \
                      + 'left: ' + str(self.left) + ' / ' \
                      + 'right: ' + str(self.right) \
                     )

ちなみに、出てくる「倍率」から始まるテキストの部分は見やすさを考慮してつけているだけなので、必ずしも入れる必要はありません。
なお、入れる場合は、上下左右に動かす関数にも入れる必要があるので、その点は注意してください。

やっていることは非常に簡単で、変更後の倍率と中心線の場所を使って、適切な上下左右の位置を設定して、再度描写しているというだけです。

あとは、次のようなイメージで、それぞれの倍率に関数を設定すれば動きます。

    def magnific_1(self):
        self.magnific_x(1.0)

実際に動かしてみると…

試しに5倍にしてみると、次の画像の通り、きちんと拡大されました。

あとは自由に動き回って、美しい画像を楽しんでください!

コメント

タイトルとURLをコピーしました