python manim實(shí)現(xiàn)排序算法動(dòng)畫示例
什么是 manim
Manim 是一個(gè)用于精確編程動(dòng)畫的引擎,專為創(chuàng)建解釋性數(shù)學(xué)視頻而設(shè)計(jì)。
注意,有兩個(gè)主要版本的 manim。該存儲(chǔ)庫最初是 3Blue1Brown 的作者的個(gè)人項(xiàng)目,目的是為這些視頻制作動(dòng)畫,此處提供了視頻專用代碼。2020 年,一群開發(fā)人員將其分叉成現(xiàn)在的社區(qū)版,目標(biāo)是更穩(wěn)定、更好地測(cè)試、更快地響應(yīng)社區(qū)貢獻(xiàn),以及更友好地開始使用。
主要版本如下:
- 3b1b/manim 【最新版】
- cairo-backend【舊版】
- ManimCommunity/manim 【社區(qū)版】
冒泡排序介紹
本文就使用 manim 來實(shí)現(xiàn)一個(gè)冒泡排序的動(dòng)畫,首先來了解下什么是冒泡排序
冒泡排序(Bubble Sort)也是一種簡(jiǎn)單直觀的排序算法。它重復(fù)地走訪過要排序的數(shù)列,一次比較兩個(gè)元素,如果他們的順序錯(cuò)誤就把他們交換過來。走訪數(shù)列的工作是重復(fù)地進(jìn)行直到?jīng)]有再需要交換,也就是說該數(shù)列已經(jīng)排序完成。這個(gè)算法的名字由來是因?yàn)樵叫〉脑貢?huì)經(jīng)由交換慢慢"浮"到數(shù)列的頂端。
算法步驟
- 比較相鄰的元素。如果第一個(gè)比第二個(gè)大,就交換他們兩個(gè)。
- 對(duì)每一對(duì)相鄰元素作同樣的工作,從開始第一對(duì)到結(jié)尾的最后一對(duì)。這步做完后,最后的元素會(huì)是最大的數(shù)。
- 針對(duì)所有的元素重復(fù)以上的步驟,除了最后一個(gè)。
- 持續(xù)每次對(duì)越來越少的元素重復(fù)上面的步驟,直到?jīng)]有任何一對(duì)數(shù)字需要比較。
初始化元素
比如我們需要排序數(shù)組為: [4,2,3,1,5]
首先,需要在 manim 場(chǎng)景上初始化我們的需要排序的所有元素,這里用矩形來表示。
在 manim 中,可以用 Rectangle
來初始化矩形,然后我們通過設(shè)置元素不同的高度來表示不同的元素大小。
- 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()
使用下面的命令運(yùn)行上面的代碼:
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.
運(yùn)行后,就會(huì)出現(xiàn)一個(gè)窗口顯示如下畫面。
代碼說明
上面代碼中,通過繼承父類 Scene
然后重新父類的 construct
來構(gòu)建一個(gè)場(chǎng)景。
然后在場(chǎng)景中添加了矩形(Rectangle
)和文本(Text
),并且將這兩個(gè)元素添加到了 VGroup
類中。
再用一個(gè) VGroup
來包含所有的 VGroup
,通過調(diào)用 arrange
方法來排列這些元素。第一個(gè) RIGHT
參數(shù)表示所有元素向右依次排列,aligned_edge
表示對(duì)齊的邊,這里我們傳入 DOWN
將底邊對(duì)齊。
最后使用 self.add()
方法把 VGroup
添加到場(chǎng)景中。
Rectangle
類定義了矩形的創(chuàng)建,更多圖形可以查看 docs.manim.org.cn/documentati…
元素交換動(dòng)畫
通過算法步驟的第一步:比較相鄰的元素。如果第一個(gè)比第二個(gè)大,就交換他們兩個(gè)。就涉及到了交換的動(dòng)畫。
一開始,我用 manim
提供的 CyclicReplace
方法來交換兩個(gè)元素。效果如下:
self.play(CyclicReplace(g[0], g[1])) self.wait()
交換是交換了,但是交換后對(duì)齊的邊變成了頂部對(duì)齊了,不符合預(yù)期。于是繼續(xù)查看文檔,最終決定使用元素的 target
屬性來進(jìn)行交換動(dòng)畫的制作。
上面我們要交換 g(0) 和 g(1) 兩個(gè)元素,所以我們定義這兩個(gè)交換元素的 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()
表示將元素移動(dòng)到指定的位置。
比如 g[0]
,我們先生成元素的 target
,然后操作 target
將元素通過 next_to
方法移動(dòng)到 g[1]
的位置。其中 ORIGIN
表示 g[1]
的所在位置。 我們對(duì) g[1]
的元素也做類似的操作。
然后使用 MoveToTarget
來將元素轉(zhuǎn)換到定義的 target
上,通過調(diào)用 self.play()
方法來播放動(dòng)畫。
self.play(MoveToTarget(g[0]),MoveToTarget(g[1]))
嗯~完美符合預(yù)期。
實(shí)現(xiàn)代碼
根據(jù)上面的知識(shí)點(diǎn),接下來就可以編寫一個(gè)冒泡排序的動(dòng)畫了。
這里在初始化場(chǎng)景元素時(shí),額外添加了一個(gè)數(shù)組來存放所有場(chǎng)景元素,因?yàn)樵诮粨Q元素位置后,也要交換對(duì)應(yīng)索引下的元素,如果直接用 VGroup
來交換時(shí),會(huì)出現(xiàn)問題。
self.g[j],self.g[j+1] = self.g[j+1],self.g[j] TypeError: 'VGroup' object does not support item assignment
所以用額外的數(shù)組去接收。
還添加了一個(gè) Indicate
方法,當(dāng)涉及到對(duì)應(yīng)交換的元素時(shí),會(huì)做一個(gè)類似對(duì)焦的動(dòng)作。
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): ''' 初始化場(chǎng)景元素 ''' 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): ''' 交換兩個(gè)元素位置 ''' 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實(shí)現(xiàn)排序算法動(dòng)畫示例的詳細(xì)內(nèi)容
本文不介紹 manim 的安裝教程,需要安裝教程的請(qǐng)參考:docs.manim.org.cn/getting_sta
更多關(guān)于python manim排序算法動(dòng)畫的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python3+PyQt5 數(shù)據(jù)庫編程--增刪改實(shí)例
今天小編就為大家分享一篇python3+PyQt5 數(shù)據(jù)庫編程--增刪改實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-06-06使用python把json文件轉(zhuǎn)換為csv文件
這篇文章主要介紹了使用python把json文件轉(zhuǎn)換為csv文件,幫助大家更好的利用python處理數(shù)據(jù),感興趣的朋友可以了解下2021-03-03Centos部署django服務(wù)nginx+uwsgi的方法
這篇文章主要介紹了Centos部署django服務(wù)nginx+uwsgi的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-01-01Python實(shí)現(xiàn)PS濾鏡中的USM銳化效果
這篇文章主要介紹了Python實(shí)現(xiàn)PS濾鏡中的USM銳化效果,幫助大家更好的利用python處理圖片,感興趣的朋友可以了解下2020-12-12Python視頻爬蟲實(shí)現(xiàn)下載頭條視頻功能示例
這篇文章主要介紹了Python視頻爬蟲實(shí)現(xiàn)下載頭條視頻功能,涉及Python正則匹配、網(wǎng)絡(luò)傳輸及文件讀寫等相關(guān)操作技巧,需要的朋友可以參考下2018-05-05Python讀取配置文件-ConfigParser的二次封裝方法
這篇文章主要介紹了Python讀取配置文件-ConfigParser的二次封裝方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02Python猴子補(bǔ)丁知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家分享的是關(guān)于Python猴子補(bǔ)丁知識(shí)點(diǎn)總結(jié),需要的朋友們學(xué)習(xí)下。2020-01-01