0
1

Manim チュートリアル

Last updated at Posted at 2024-08-16

はじめに

この記事はPythonで数学の映像を作ることができる「Manim」について、簡単な使い方を説明したものです。
日本語での記事はあまりないので、作ってみました。

前提

  • Pythonの基礎文法が分かる
  • オブジェクト指向の基本がわかる
  • Manimとその依存関係がインストール済み

環境

  • Windows 11 Home
  • Ubuntu 22.04 on WSL2
  • Python 3.10
  • Manim 0.18.1
  • VScode (拡張機能:Manim Sideview)

目次

1.四角形を描画する
シンプルなコードを通して、Manimの大まかな流れを掴む

2.Manimの構成要素
Scene, Mobject, Animation というManimの基本構造を理解する

3.簡単なサンプルプログラム
今までの知識を実践し、より深い理解を得る

4.Manim独自の型と定数
自分でメソッドとプロパティを使えるようになるための準備

5.メソッド&プロパティ紹介
より高度で複雑な映像を作れるようになる

四角形を描画する

まず最初に、簡単なプログラムを動かしてみましょう。

from manim import *

class CreateSquare(Scene):
    def construct(self):
        square = Square()
        createAnim = Create(square)
        self.play(createAnim)

実行する方法

VScodeでManim Sideviewを入れている方であれば、このようなマーク(赤い四角で囲ったもの)が表示されていると思います。

image.png

このマークを押すと画面上部に「▷CreateSquare」が表示されるので押してください。
すると画面が分割されて、右側で四角形が描画されるアニメーションを見ることができたと思います。

結果

コードの説明

- 1行目 -

Manimモジュールを読み込む。

from manim import *

- 3行目 -

Sceneを継承したCreateSquareという名前のクラスを作る。
そうすることで、オブジェクトを表示するためのキャンバスを用意している。

class CreateSquare(Scene):

- 4行目 -

Sceneクラスのconstructメソッドをオーバーライドする。
Manimのプログラムのほとんどはこのメソッドの中に書く。

def construct(self):

- 5行目 -

Squareクラスをインスタンス化して、変数squareに入れる。
そうすることで四角形を生成している。

square = Square()

- 6行目 -

Createクラスをインスタンス化して、変数createAnimに入れる。
そのとき、コンストラクタに mobject = square を渡す。
そうすることで、5行目で作った四角形を描画するアニメーションを作っている。

createAnim = Create(square)

- 7行目 -

Sceneクラスのplayメソッドを実行している。
そのときの引数にcreateAnimを渡している。
そうすることで、6行目で作ったアニメーションを実行している。

self.play(createAnim)

一回一回変数に代入せず、このようにまとめて書いてもよいです。
from manim import *

class CreateSquare(Scene):
    def construct(self):
        self.play(Create(Square()))

Manimの構成要素

Manimは主に以下の3つの機能から成り立っています。

1.Scene機能
Mobjectを表示するキャンバスのことをSceneという。
Scene機能:映像の制御全般を行う。
Mobjectを表示したり、Animationを実行したりする。

2.Mobject機能
画面に表示するオブジェクト全てをMobject(mathematical object)という。
Mobject機能:Mobjectを生成したり、静的に回転・移動・変形させる。
※生成するだけで表示はしない

3.Animation機能
Mobjectのある決まった一連の動きをAnimationという。
その動きは、Mobjectを動的に回転・移動・変形させるものである。
Animation機能:Animationを生成する。
※生成するだけで実行はしない

Scene機能

Scene機能は全てSceneクラスツリーに属します。
Sceneクラスツリーには純粋なSceneクラスと、それを継承した6つのクラスがあります。

それぞれのSceneクラスの特徴

1. Sceneクラス
最も基本的なSceneクラス。
シンプルな2Dアニメーションや描画、テキストの表示、図形の操作などに使用。

2. VectorSceneクラス
ベクトルや座標平面を扱うためのSceneクラス。
ベクトルの可視化、座標軸の描画、数学的なベクトル操作を表現するアニメーションに使用。

3. LinearTransformationSceneクラス
線形変換を可視化するためのSceneクラス。
線形代数の概念(行列変換、固有ベクトル、固有値など)を視覚的に示す際に使用。

4. MovingCameraSceneクラス
カメラを動かすためのSceneクラス。
特定の部分にフォーカスを当てたり、広い範囲をカバーするアニメーションを作成したりする場合に使用。

5. ZoomedSceneクラス
シーン内の特定の領域をズームインして強調表示することができるSceneクラス。
詳細な部分に焦点を当てたいときや、全体と部分を同時に表示するアニメーションを作成したいときに使用。

6. ThreeDSceneクラス
3Dシーンを扱うための基本的なSceneクラス。
3Dグラフィックスやアニメーション、立体的な図形やグラフの表示に使用。

7. SpecialThreeDSceneクラス
ThreeDSceneにさらに特殊なカメラ操作やシェーディング機能を追加したSceneクラス。
特殊な3D効果や、より高度な3Dカメラ操作を必要とするアニメーションに使用。

Scene機能の使い方

まず初めに、Sceneクラスを継承したクラスを作成する。
このプログラムのSceneの部分をVectorSceneやThreeDSceneに変更することで、
それぞれのSceneを使うことができる。

class SceneName(Scene):

次に、SceneクラスのConstructメソッドをオーバーライドする。
Manimで作る映像本体に関わるコードは全てこのメソッド内に記述する。
Mobject生成・Animation生成・Mobject表示・Animation実行 など

def construct(self):

Sceneクラスのメソッドを使用することで、以下のことができる。

self.add(Mobject)           # Mobjectを表示する(シーンに追加する)
self.play(Animation)        # Animationを実行する

Mobject機能

Mobject機能は全てMobjectクラスツリーに属します。
Mobjectクラスツリーには非常にたくさんの具体的なクラスがあります。
(Square, Circle, Triangle, Line, Text など)
Mobjectクラスには主に3つの子クラスがあり、
そこから上記のような具体的なクラスが派生します。

Mobjectクラスとその子クラスは抽象度が高く、
そのままインスタンス化されて使われることはありません。
そこから何度か継承を繰り返して具体的になったクラスが、
インスタンス化されて使われます。

それぞれのMobject子クラスの特徴

1. PMobjectクラス
Point Cloud Mobject の略であり、点の集合を扱うためのMobjectクラス。

2. VMobjectクラス
Vectorized Mobject の略であり、ベクトルグラフィックスを扱うためのMobjectクラス。
Manimで扱うMobjectのほとんどはVMobjectに属する。

3. AbstractImageMobjectクラス
画像を扱うためのMobjectクラス。

Mobject機能の使い方

SquareクラスやCircleクラスなどの具体的なクラスをインスタンス化することで、それぞれの図形を生成することができる。

square()                    # 正方形を生成する
Circle()                    # 円を生成する

インスタンス化するときに特定のプロパティを渡すことで、
図形の大きさや色などの特徴の初期設定をすることができる。

square(side_length = 4.0)   # 一辺の長さがside_lengthである正方形を生成する
Circle(color = BLUE)        # 色が青である円を生成する

Mobjectクラスのメソッドを使用することで、
Mobjectを静的に回転・移動・変形させることができる。

mobject.move_to([2, 2, 0])  # Mobjectの位置を[2, 2, 0]に変更する
mobject.set_color(GREEN)    # Mobjectの色をGREENに変更する

Animation機能

Animation機能を持つものは主に2つあります。

1. Animationクラスツリー
事前に定義されたAnimationを使用できる。
Animationの内容が明確。

2. Mobjectクラスのanimateプロパティ
MobjectクラスのメソッドをAnimation化できる。

先ほどMobjectクラスのメソッドを使用することで、
Mobjectを静的に回転・移動・変形させることができる
といったが、それを動的に行えるようになる。

Animation機能の使い方

Animationクラスツリーを使う場合

CreateクラスやFadeOutクラスなどの具体的なクラスをインスタンス化することで、それぞれのアニメーションを生成することができる。
プロパティには対象のMobjectを入れる

Create(Mobject)             # Mobjectを描画するAnimationを生成する
FadeOut(Mobject)            # MobjectをフェードアウトするAnimationを生成する
Mobjectクラスのanimateプロパティを使う場合

先ほどMobjectクラスのメソッドの使い方を説明したが、
そのときのmobjectとメソッドの間に .animate を挿入する

# Mobjectを[2, 2, 0]に移動するアニメーションを生成する
mobject.animate.move_to([2, 2, 0])

# Mobjectの色をGREENに変更するアニメーションを生成する
mobject.animate.set_color(GREEN)            

まとめ

1.Scene機能
Mobjectの表示、Animationの実行など
全てSceneクラスツリーに属する

2.Mobject機能
Mobjectを生成したり、静的に回転・移動・変形させる
全てMobjectクラスツリーに属する

3.Animation機能
Mobjectを動的に回転・移動・変形させるAnimationを生成する
Animationクラスツリーに属するものと
Mobjectクラスのanimateプロパティに属するものがある

初めのプログラムを改めて確認

from manim import *

class CreateSquare(Scene):
    def construct(self):
        square = Square()             # Mobject機能
        createAnim = Create(square)   # Animation機能
        self.play(createAnim)         # Scene機能

簡単なサンプルプログラム

細かいメソッドやプロパティの説明に移る前に、
今までの知識で作ることができる簡単なプログラムを見てみましょう。

Sample1.py
from manim import *

class CircleAndSquare(Scene):
    def construct(self):
        circle = Circle(color = RED)                       # Mobject機能
        circle.move_to([2, 2, 0])                          # Mobject機能

        square = Square(color = GREEN, side_length = 4.0)  # Mobject機能
        self.add(square)                                   # Scene機能

        circleAnim = circle.animate.move_to([-2, -2, 0])   # Animation機能
        self.play(circleAnim)                              # Scene機能

結果



Sample2.py
from manim import *

class CircleMove(Scene):
    def construct(self):
        circle = Circle(color = BLUE)  # Mobject機能
        circle.move_to([-2, 2, 0])     # Mobject機能

        animFirst = Create(circle)     # Animation機能
        animMiddle = circle.animate.move_to([-2, -2, 0]).set_color(GREEN)
        animEnd = FadeOut(circle)      # Animation機能

        self.play(animFirst)           # Scene機能
        self.play(animMiddle)          # Scene機能
        self.play(animEnd)             # Scene機能

結果



Sample3.py
from manim import *

class DoubleSquare(Scene):
    def construct(self):
        square1 = Square(color = BLUE)                # Mobject機能
        square2 = Square(color = RED)                 # Mobject機能
        circle = Circle(color = GREEN)                # Mobject機能

        square1.move_to([2, 2, 0])                    # Mobject機能
        square2.move_to([-2, 2, 0])                   # Mobject機能

        anim1 = square1.animate.move_to([-2, -2, 0])  # Animation機能
        anim2 = square2.animate.move_to([2, -2, 0])   # Animation機能
        animEnd = FadeOut(square1, square2)           # Animation機能

        self.add(circle)                              # Scene機能
        self.play(anim1, anim2)                       # Scene機能
        self.play(animEnd)                            # Scene機能

結果

Manim独自の型と定数

Manimには独自の型と定数があります。
これからその一部を紹介します。

独自の型

# 正確には違いますが、簡略化して書いています
Point3D = tuple[float, float, float]
Vector3D = np.ndarray[float, float, float]
ManimColor = str           # 16進数カラーコード

Pythonには数値計算を効率的に行うための NumPy ライブラリがあります。
2行目の np.ndarray は、NumPyによって提供される配列の型です。
from manim import *  をするときに、内部では
import numpy as np  が同時に実行されています。

独自の定数

PI = np.pi                         # PIには円周率が入っている

Vector3D型の定数

UP = np.array([0.0, 1.0, 0.0])
DOWN = np.array([0.0, -1.0, 0.0])
RIGHT = np.array([1.0, 0.0, 0.0])
LEFT = np.array([-1.0, 0.0, 0.0])
UL = np.array([-1.0, 1.0, 0.0])
UR = np.array([1.0, 1.0, 0.0])
DL = np.array([-1.0, -1.0, 0.0])
DR = np.array([1.0, -1.0, 0.0])

ManimColor型の定数

image.png
この画像のように、
定数 BLUE_A には、#C7E9F1 が、
定数 GREEN_C には、#83C167 が、
定数 RED_E には、#CF5044 が、
定数 LIGHT_PINK には、#DC75CD が入っている
定数名がすべて大文字であることに注意。

メソッド&プロパティ紹介

ここからは、私がよく使うと思うメソッドとプロパティを紹介します。
色を指定するプロパティについては、str型の場合もParsableManimColor型の場合も簡略化してManimColor型と表示しています。

Sceneクラス

メソッド

# 見やすくするために、一部仮引数名を変更しています
add(*mobjects: Mobject)            # Mobjectsをシーンに追加する
remove(*mobjects: Mobject)         # Mobjectsをシーンから削除する
play(*animations: Animation)       # Animationsを実行する
wait(duration: float)              # duration秒間何もしない

Mobjectクラス

プロパティ

color(ManimColor)                  # Mobjectの色

メソッド

# 見やすくするために、一部仮引数名を変更しています
move_to(point: Point3D)                        # pointの場所に移動する
next_to(mobject: Mobject, direction: Vector3D) # mobjectの場所からdirectionだけ離れた場所に移動する
shift(vector: Vector3D)                        # vectorだけ移動する
set_x(x: float)                                # 指定されたx座標に移動する
set_y(y: float)                                # 指定されたy座標に移動する
to_corner(corner: Vector3D)                    # cornerに移動する
to_edge(edge: Vector3D)                        # edgeに移動する
rotate(angle: float)                           # angle(radian)だけ反時計回りに回転する
set_color(color: ManimColor)                   # 色をcolorに変更する
scale(scale_factor: float)                     # 大きさをscale_factor倍に変更する

VMobjectクラスのプロパティ

fill_color(ManimColor)             # 塗りつぶす色
fill_opacity(float)                # 塗りつぶす色の透明度(0.0 ~ 1.0)
stroke_color(ManimColor)           # 枠の色
stroke_opacity(float)              # 枠の色の透明度(0.0 ~ 1.0)
stroke_width(float)                # 枠の幅

VMobjectから派生したクラス

Rectangle()                        # 長方形を生成する
Square()                           # 正方形を生成する
RegularPolygon()                   # 正多角形を生成する
Circle()                           # 円を生成する
Line()                             # 直線を生成する
Arrow()                            # 矢印を生成する
NumberLine()                       # 数直線を生成する
Axes()                             # x軸とy軸を生成する
NumberPlane()                      # 座標平面を生成する
Text()                             # 文章を生成する
MathTex()                          # 数式を生成する
Rectangleクラスのプロパティ
height(float)                      # 高さ
width(float)                       # 横幅
Squareクラスのプロパティ
side_length(float)                 # 1辺の長さ
RegularPolygonクラスのプロパティ
n(int)                             # 頂点の数
radius(float)                      # 頂点が通る円の半径
Circleクラスのプロパティ
radius(float)                      # 半径
Lineクラスのプロパティ
start(Point3D)                     # 始点(Point3D)
end(Point3D)                       # 終点(Point3D)
ArrowはLineを継承している
NumberLineクラスのプロパティ
x_range([float, float, float])     # [xの最小値, xの最大値, 目盛りを降る間隔]
length(float)                      # 数直線の長さ
include_numbers(bool)              # 目盛りを降るかどうか
include_tip(bool)                  # 矢印を含むかどうか
Axesクラスのプロパティ
x_range([float, float, float])     # [xの最小値, xの最大値, 目盛りを降る間隔]
y_range([float, float, float])     # [yの最小値, yの最大値, 目盛りを降る間隔]
x_length(float)                    # x軸の長さ
y_length(float)                    # y軸の長さ
tips(bool)                         # 両軸に矢印を含むかどうか
axis_config({str, any})            # {NumberLineクラスの変数, 値} 両軸に影響を与える
x_axis_config({str, any})          # {NumberLineクラスの変数, 値} x軸に影響を与える
y_axis_config({str, any})          # {NumberLineクラスの変数, 値} y軸に影響を与える
NumberPlaneはAxesを継承している(ただし矢印は表示できない)
Textクラスのプロパティ
text(str)                          # 文字
font_size(float)                   # 文字サイズ
MathTexクラスのプロパティ
tex_strings(str)                   # LaTeX記法で書かれた数式
font_size(float)                   # 文字サイズ

Axis・NumberPlaneで使えるメソッド

# functionに基づいて生成した曲線を返す
plot(function: Callable[[float], float])   # 引数・返り値ともに1つで、floatである関数が引数


# graphとx軸がなす領域を塗る
get_area(graph: ParametricFunction,                  # plot関数の返り値
         x_range: [float, float],                    # [xの最小値, xの最大値]
         color: ManimColor,                          # 領域を塗る色
         opacity: float)                             # 領域を塗る色の透明度


# graphとx軸がなす領域を細長い長方形で埋める
get_riemann_rectangles(graph: ParametricFunction,    # plot関数の返り値
                       x_range: [float, float],      # [xの最小値, xの最大値]
                       dx: float,                    # 長方形の幅
                       color: ManimColor,            # 長方形を塗る色
                       fill_opacity: float)          # 長方形を塗る色の透明度

Animationクラス

プロパティ

mobject(Mobject)                   # Animationの対象となるMobject
run_time(float)                    # アニメーションの継続時間(秒)

Animationから派生したクラス

FadeIn()                           # Mobjectをフェードインする
FadeOut()                          # Mobjectをフェードアウトする
Create()                           # Mobjectを描画する(端から)
Write()                            # Mobjectを描画する(外側から手書きするイメージ)
Transform(target_mobject: Mobject) # あるMobjectをtarget_mobjectに変形させる
FadeToColor(color: ManimColor)     # 色をcolorに変化させる
Indicate(color: ManimColor)        # color色に点灯させる、目立たせる

さいごに

私自身、Manimを使う際に日本語の説明があまり無く大変だったので、
備忘録もかねてこれから学ぶ人のために作ってみました。
最後の メソッド&プロパティ紹介 は読むだけでは分からないと思いますので、
気になったものがあったら自分で試してみるのが良いと思います。
今後、複雑なサンプルプログラムも追加するかもしれません。

参考

Manim Community 公式ページ

Manim Community 公式GitHubリポジトリ

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1