Manimを使ったアニメーション表現


# Manimとは

Manim（Mathematical Animation Library）は、数学的概念やプロセスを視覚的にアニメーション化するために設計されたPythonライブラリです。3Blue1BrownというYouTubeチャンネルで有名になり、チャンネルの制作者であるGrant Sandersonが開発しました。このライブラリを使用すると、数学の教育や説明に役立つ高品質なビデオコンテンツを作成できます。

https://www.manim.community/

# サンプル解説

Manimは、グラフの描画、数式の表示、図形の操作など、数学的な情報を視覚化するための多彩な機能を提供します。コードを書いて特定のアニメーションを定義し、それをビデオとしてレンダリングすることで、複雑な数学的アイデアを直感的に理解しやすくします。

https://www.manim.community/examples/


```python

from manim import *

class ContinuousMotion(Scene):
    def construct(self):
        # ベクトル場を定義する関数。
        # この関数は、与えられた位置に基づいてベクトルを返します。
        # ここでは、sinとcos関数を使用して2D空間でのベクトル場を作成しています。
        func = lambda pos: np.sin(pos[0] / 2) * UR + np.cos(pos[1] / 2) * LEFT
        
        # StreamLinesオブジェクトを作成。
        # funcで定義されたベクトル場に沿った流線を生成します。
        stream_lines = StreamLines(func, stroke_width=2, max_anchors_per_line=30)
        
        # 生成された流線をシーンに追加します。
        self.add(stream_lines)
        
        # 流線のアニメーションを開始します。
        # warm_upをFalseに設定することで、アニメーションがすぐに開始されます。
        # flow_speedパラメータで流線の動きの速さを調整できます。
        stream_lines.start_animation(warm_up=False, flow_speed=1.5)
        
        # アニメーションが終了するまで待機します。
        # virtual_timeとflow_speedを使用してアニメーションの総時間を計算し、
        # その時間だけ待機することで、アニメーションが完了するのを確実にします。
        self.wait(stream_lines.virtual_time / stream_lines.flow_speed)

```

```python
from manim import *

class OpeningManim(Scene):
    def construct(self):
        # LaTeXテキストの表示
        title = Tex(r"This is some \LaTeX")
        # 数学の式をLaTeXで表示
        basel = MathTex(r"\sum_{n=1}^\infty \frac{1}{n^2} = \frac{\pi^2}{6}")
        # タイトルと式を縦に配置
        VGroup(title, basel).arrange(DOWN)
        # タイトルの書き込みと式のフェードインアニメーションを実行
        self.play(
            Write(title),
            FadeIn(basel, shift=DOWN),
        )
        self.wait()  # 少し待機

        # 新しいタイトルのテキスト
        transform_title = Tex("That was a transform")
        transform_title.to_corner(UP + LEFT)  # 左上に配置
        # タイトルの変形と式のフェードアウトアニメーションを実行
        self.play(
            Transform(title, transform_title),
            LaggedStart(*(FadeOut(obj, shift=DOWN) for obj in basel)),
        )
        self.wait()

        # 数値グリッドを表示
        grid = NumberPlane()
        grid_title = Tex("This is a grid", font_size=72)
        grid_title.move_to(transform_title)  # 新しいタイトルの位置に移動

        self.add(grid, grid_title)  # グリッドとタイトルを追加
        # タイトルのフェードアウトとグリッドの作成アニメーションを実行
        self.play(
            FadeOut(title),
            FadeIn(grid_title, shift=UP),
            Create(grid, run_time=3, lag_ratio=0.1),
        )
        self.wait()

        # グリッドに適用される非線形変換の説明テキスト
        grid_transform_title = Tex(
            r"That was a non-linear function \\ applied to the grid",
        )
        grid_transform_title.move_to(grid_title, UL)  # タイトルの位置に移動
        grid.prepare_for_nonlinear_transform()  # 非線形変換の準備
        # グリッドに非線形変換を適用するアニメーションを実行
        self.play(
            grid.animate.apply_function(
                lambda p: p
                + np.array(
                    [
                        np.sin(p[1]),
                        np.sin(p[0]),
                        0,
                    ],
                ),
            ),
            run_time=3,
        )
        self.wait()
        # グリッドタイトルを変更するアニメーションを実行
        self.play(Transform(grid_title, grid_transform_title))
        self.wait()  # 少し待機

```

```python

from manim import *

class SquareToCircle(Scene):
    def construct(self):
        # Circleオブジェクトを作成
        circle = Circle()  # 円を定義
        # Squareオブジェクトを作成
        square = Square()  # 四角形を定義
        square.flip(RIGHT)  # 四角形を右方向に反転
        square.rotate(-3 * TAU / 8)  # 四角形を回転させる（TAUは2πに等しい）
        # 円にピンクの塗りつぶしを設定し、不透明度を0.5に設定
        circle.set_fill(PINK, opacity=0.5)

        # 四角形の作成アニメーションを実行
        self.play(Create(square))
        # 四角形を円に変形させるアニメーションを実行
        self.play(Transform(square, circle))
        # 変形後のオブジェクト（四角形が変形した円）をフェードアウトさせる
        self.play(FadeOut(square))


```