首頁 > 軟體

python manim實現排序演演算法動畫範例

2022-08-12 18:00:04

什麼是 manim

Manim 是一個用於精確程式設計動畫的引擎,專為建立解釋性數學視訊而設計。

注意,有兩個主要版本的 manim。該儲存庫最初是 3Blue1Brown 的作者的個人專案,目的是為這些視訊製作動畫,此處提供了視訊專用程式碼。2020 年,一群開發人員將其分叉成現在的社群版,目標是更穩定、更好地測試、更快地響應社群貢獻,以及更友好地開始使用。

主要版本如下:

氣泡排序介紹

本文就使用 manim 來實現一個氣泡排序的動畫,首先來了解下什麼是氣泡排序

氣泡排序(Bubble Sort)也是一種簡單直觀的排序演演算法。它重複地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個演演算法的名字由來是因為越小的元素會經由交換慢慢"浮"到數列的頂端。

演演算法步驟

  • 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
  • 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。這步做完後,最後的元素會是最大的數。
  • 針對所有的元素重複以上的步驟,除了最後一個。
  • 持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數位需要比較。

初始化元素

比如我們需要排序陣列為: [4,2,3,1,5]

首先,需要在 manim 場景上初始化我們的需要排序的所有元素,這裡用矩形來表示。

在 manim 中,可以用 Rectangle 來初始化矩形,然後我們通過設定元素不同的高度來表示不同的元素大小。

  • main.py
from manimlib import *
class Test(Scene):
    def construct(self):
        COLOR = [BLUE, GREEN, RED, PINK, ORANGE, MAROON_B, TEAL, PURPLE_B, GREY_BROWN]
        arr = [4,2,3,1,5]
        g = VGroup()
        for i in range(len(arr)):
            r1=Rectangle(width=1,height=arr[i],fill_color=COLOR[i%len(COLOR)],fill_opacity=1)
            t1=Text(str(arr[i])).scale(0.5)
            rec = VGroup(r1,t1)
            g.add(rec)
        g.arrange(RIGHT,aligned_edge=DOWN)
        self.add(g)
        self.wait()

使用下面的命令執行上面的程式碼:

manimgl main.py BubbleSort

ManimGL v1.6.1
[11:27:18] INFO     Using the default configuration file, which you can modify in `/Users/zheng/anaconda3/envs/manim/lib/python3.10/site-packages/manimlib/default_config.yml`                                                                                         config.py:265
           INFO     If you want to create a local configuration file, you can create a file named `custom_config.yml`, or run `manimgl --config`                                                                                                                       config.py:266
[11:27:20] INFO     Tips: You are now in the interactive mode. Now you can use the keyboard and the mouse to interact with the scene. Just press `q` if you want to quit.

執行後,就會出現一個視窗顯示如下畫面。

程式碼說明

上面程式碼中,通過繼承父類別 Scene 然後重新父類別的 construct 來構建一個場景。

然後在場景中新增了矩形(Rectangle)和文字(Text),並且將這兩個元素新增到了 VGroup 類中。

再用一個 VGroup 來包含所有的 VGroup,通過呼叫 arrange 方法來排列這些元素。第一個 RIGHT 參數列示所有元素向右依次排列,aligned_edge 表示對齊的邊,這裡我們傳入 DOWN 將底邊對齊。

最後使用 self.add() 方法把 VGroup 新增到場景中。

Rectangle 類定義了矩形的建立,更多圖形可以檢視 docs.manim.org.cn/documentati…

元素交換動畫

通過演演算法步驟的第一步:比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。就涉及到了交換的動畫。

一開始,我用 manim 提供的 CyclicReplace 方法來交換兩個元素。效果如下:

self.play(CyclicReplace(g[0], g[1]))
self.wait()

交換是交換了,但是交換後對齊的邊變成了頂部對齊了,不符合預期。於是繼續檢視檔案,最終決定使用元素的 target 屬性來進行交換動畫的製作。

上面我們要交換 g(0)g(1) 兩個元素,所以我們定義這兩個交換元素的 target

g[0].generate_target()
g[0].target.next_to(g[1],ORIGIN,aligned_edge=DOWN)
g[1].generate_target()
g[1].target.next_to(g[0],ORIGIN,aligned_edge=DOWN)

generate_target() 表示生成元素的 target, next_to() 表示將元素移動到指定的位置。

比如 g[0],我們先生成元素的 target,然後操作 target 將元素通過 next_to 方法移動到 g[1] 的位置。其中 ORIGIN 表示 g[1] 的所在位置。 我們對 g[1] 的元素也做類似的操作。

然後使用 MoveToTarget 來將元素轉換到定義的 target 上,通過呼叫 self.play() 方法來播放動畫。

self.play(MoveToTarget(g[0]),MoveToTarget(g[1]))

嗯~完美符合預期。

實現程式碼

根據上面的知識點,接下來就可以編寫一個氣泡排序的動畫了。

這裡在初始化場景元素時,額外新增了一個陣列來存放所有場景元素,因為在交換元素位置後,也要交換對應索引下的元素,如果直接用 VGroup 來交換時,會出現問題。

    self.g[j],self.g[j+1] = self.g[j+1],self.g[j]
TypeError: 'VGroup' object does not support item assignment

所以用額外的陣列去接收。

還新增了一個 Indicate 方法,當涉及到對應交換的元素時,會做一個類似對焦的動作。

from manimlib import *
class BubbleSort(Scene):
    def construct(self):
        self.COLOR = [BLUE, GREEN, RED, PINK, ORANGE, MAROON_B, TEAL, PURPLE_B, GREY_BROWN]
        self.bubbleSort([4,2,3,1,5])
    def init_vmobj(self,arr):
        '''
            初始化場景元素
        '''
        self.vmArr = []
        g = VGroup()
        for i in range(len(arr)):
            r1=Rectangle(width=1,height=arr[i]/2,fill_color=self.COLOR[i%len(self.COLOR)],fill_opacity=1)
            t1=Text(str(arr[i])).scale(0.5)
            rec = VGroup(r1,t1)
            self.vmArr.append(rec)
            g.add(rec)
        g.arrange(RIGHT,aligned_edge=DOWN)
        self.add(g)
        self.wait()
    def bubbleSort(self,arr):
        '''
            氣泡排序
        '''
        self.init_vmobj(arr)
        for i in range(1, len(arr)):
            for j in range(0, len(arr)-i):
                self.play(Indicate(self.vmArr[j]))
                self.play(Indicate(self.vmArr[j+1],color=RED))
                if arr[j] > arr[j+1]:
                    arr[j], arr[j + 1] = arr[j + 1], arr[j]
                    self.cyc_move(self.vmArr[j],self.vmArr[j+1])
                    self.vmArr[j],self.vmArr[j+1] = self.vmArr[j+1],self.vmArr[j]
        return arr
    def cyc_move(self,vm1,vm2):
        '''
            交換兩個元素位置
        '''
        vm1.generate_target()
        vm1.target.next_to(vm2,ORIGIN,aligned_edge=DOWN)
        vm2.generate_target()
        vm2.target.next_to(vm1,ORIGIN,aligned_edge=DOWN)
        self.play(MoveToTarget(vm1),MoveToTarget(vm2))
        self.wait()

以上就是python manim實現排序演演算法動畫範例的詳細內容

本文不介紹 manim 的安裝教學,需要安裝教學的請參考:docs.manim.org.cn/getting_sta

更多關於python manim排序演演算法動畫的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com