ドーナツとマグカップの位相同型動画
By K.Yoshimi
はじめに
数学には位相同型、あるいは同相という概念があります。
よくある例として、マグカップを連続的に変形していくとドーナツにできるので、 位相幾何学的には両者を区別することができません、のような説明を聞いたことがある人は多いかもしれません。
本記事では、このマグカップを連続的に変形していってドーナツにする動画を 数学的な動画を作成するための、PythonライブラリであるManimを使用して、勉強がてらに作成してみます。
Manim
Youtubeに、美しい動画と音楽とともに、数学や物理学、はてはブロックチェーン、ニューラルネットワークまで説明する 3Blue1Brownという有名チャンネルがあります。 (日本語版の3Blue1BrownJapanもありますので、ぜひのぞいてみてください。)
3Blue1BrownはGrant Sandersonさんが運営していて、配信に使われた動画を作成するためのPythonライブラリ Manimも公開されています。 (ちなみに、3Blue1Brownという名称は、グラントの右目が青色と茶色の虹彩異色症であることに由来するとのこと)
しかし、このライブラリはメンテナンスが十分でなく不安定なので、有志が集まって、2020年に Manimのコミュニティ版 が開発されました。
これにより、Manimという同じ名称の2つのライブラリが存在することになり、 初学者が混乱する状況となっています。
今回は、より安定しているManimのコミュニティ版を 使用します。
❗ インストール方法については、Manimのホームページを参考ください
マグカップを連続的に変形してドーナツにする動画
マグカップを連続的に変形してドーナツにする動画のPythonスクリプトが、Grant Sandersonさんの方のGithubに存在します。
しかし、これをManimのコミュニティ版で実行しようとすると、エラーがでます。 ここで、Manimの実行コマンドは以下で行います。
manim -ql -p mug_to_torus.py
Manimのコミュニティ版で動くようにするために、以下のように変更してみました。
❗ Manimのコミュニティ版には、TorusやCylinderなどが用意されていますが、これらで形状を置き換えると上手くいきませんでした。 習熟と調整が必要そうです。
from manim import *
import math
class MugToTorus(ThreeDScene):
def __init__(self):
super().__init__()
def construct(self):
self.set_camera_orientation(phi=45 * DEGREES, theta=-90 * DEGREES)
R1, R2 = (2, 0.75)
def torus_func(u, v):
v1 = np.array([-math.sin(u), 0, math.cos(u)])
v2 = math.cos(v) * v1 + math.sin(v) * UP
return R1 * v1 + R2 * v2
def cylinder_func(u, v):
return (math.cos(v), math.sin(v), u)
left_half_torus = Surface(
torus_func,
u_range=(-PI / 2, PI + PI / 2),
v_range=(0, TAU),
)
right_half_torus = Surface(
torus_func,
u_range=(PI, TAU),
v_range=(0, TAU),
)
cylinder = Surface(
cylinder_func,
u_range=(PI, TAU),
v_range=(0, TAU),
)
cylinder.set_width(3)
cylinder.set_depth(5)
cylinder.move_to(ORIGIN, LEFT)
disk = Circle(radius=cylinder.get_width()*0.5, fill_opacity=1)
disk.move_to(cylinder, IN)
disk.scale(1.001)
low_disk = disk.copy()
for mob in (left_half_torus, right_half_torus, cylinder, low_disk, disk):
mob.set_color(GREY)
mob.set_gloss(0.7)
left_half_torus.save_state()
left_half_torus.set_depth(3)
self.add(left_half_torus)
self.add(low_disk, disk)
self.add(cylinder)
self.play(disk.animate.move_to(cylinder, OUT), run_time=2)
for mob in (disk, low_disk):
mob.generate_target()
mob.target.rotate(90 * DEGREES, DOWN)
mob.target.set_depth(2 * R2)
disk.target.move_to(right_half_torus, OUT + LEFT)
low_disk.target.rotate(PI, UP)
low_disk.target.move_to(right_half_torus, IN + LEFT)
self.move_camera(phi=75 * DEGREES, theta=-90 * DEGREES),
self.play(
MoveToTarget(disk),
MoveToTarget(low_disk),
Transform(cylinder, right_half_torus),
Restore(left_half_torus, rate_func=squish_rate_func(smooth, 0, 0.75)),
run_time=5,
)
self.wait()
このプログラムを実行して、作成された動画は以下のようになりました。
おわりに
本記事では、Manimを使用して、よくあるマグカップを連続的に変形してドーナツにする動画を作成しました。
このような動画があると直感的に数学や物理などの概念を理解しやすくなりますし、 教育コンテンツを作成するのにもとても有用に感じました。
ただ、Manimで動画を作成するには、習熟が必要そうで、コード数も多くなりがちだし、骨が折れると感じました。 もっと簡単に作成するには、商用ソフトが必要かもしれませんね。