<jupyter_start><jupyter_text>Manim (optional) **CS1302 Introduction to Computer Programming**___<jupyter_code>import math

from manim import *

%reload_ext mytutor<jupyter_output><empty_output><jupyter_text>[Manim](https://github.com/3b1b/manim) is a powerful **anim**ation engine for **ma**themetics developed by [3Blue1Brown](https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw). We will use manim to domenstrate how object-oriented programming uses classes and objects to make it create complex animation.  Creating a scene **How to create an animation with `manim`?** In jupyter notebook, we can use `%%manim` cell magic:<jupyter_code>%%manim -qm --progress_bar=none --disable_caching --flush_cache -v ERROR HelloWorld
class HelloWorld(Scene):
    def construct(self):
        self.play(Write(Text("Hello, World!")))<jupyter_output><empty_output><jupyter_text>In the line starting with `%%`:- `-qm` is the alias for `--quality=m`, which means the video is rendered in medium quality. Change it to `-ql` (`-qh`) for low (high) quality.- `--progress_bar=none --disable_caching --flush_cache -v ERROR` are [additional configurations](https://docs.manim.community/en/stable/tutorials/configuration.html) to turn off some features. - `HelloWorld` is the class to render, which is defined in the body:    ```Python     class HelloWorld(Scene):        def construct(self):            ...    ``` **How to define a class?** As a toy example, the following [defines a class](https://docs.python.org/3/tutorial/classes.html?highlight=inheritanceclass-definition-syntax) `Pet` and its [subclasses](https://docs.python.org/3/tutorial/classes.html?highlight=inheritanceinheritance) `Cat` and `Dog`:<jupyter_code>%%mytutor -h 700
class Pet:
    kind = "Pet"

    def __init__(self, name):
        self.name = name

    def __str__(self):
        return f"{self.kind} {self.name}"


class Cat(Pet):
    kind = "Cat"


class Dog(Pet):
    kind = "Dog"


p1 = Pet("Alfie")
p2 = Dog("Bobbie")
p3, p4 = Cat("Bella"), Cat("Kelly")
print(p1, p2, p3, p4, sep=", ")<jupyter_output><empty_output><jupyter_text>- Each pet has its own `name` but they share `kind` from their class without duplicating it.- Subclasses can reuse (inherit) code from their superclass but produce different results:    - Line 19-21 calls `Pet.__init__` implicitly to create pets with different `name`s.    - Line 22 calls `Pet.__str__` implicitly to return a string containing pets' specific `kind` in addition to its `name`.  Animating an Object **How to add objects to a `Scene`?** We can create a square and add it to the scene as follows:<jupyter_code>%%manim -qm --progress_bar=none --disable_caching --flush_cache -v ERROR BlueSquare1
class BlueSquare1(Scene):
    def construct(self):
        s = Square(fill_color=BLUE, color=WHITE)
        self.add(s)<jupyter_output><empty_output><jupyter_text>- The square object is create using `Square`, `BLUE` and `WHITE` imported from `manim`.- It is then placed to to the scene using `self.add` inherited from `Scene`. **How to animate an object?** The following shows the creation of a square:<jupyter_code>%%manim -qm --progress_bar=none --disable_caching --flush_cache -v ERROR BlueSquare2
class BlueSquare2(Scene):
    def construct(self):
        s = Square(color=WHITE, fill_color=BLUE, fill_opacity=0.8)
        self.play(Create(s))
        self.wait()<jupyter_output><empty_output><jupyter_text>- `self.play` plays the animation `Create(s)`.- `self.wait()` creates a pause "animation". **How to transform an object?** To scale, move, or rotate the shape:<jupyter_code>%%manim -qm --progress_bar=none --disable_caching --flush_cache -v ERROR BlueSquare3
class BlueSquare3(Scene):
    def construct(self):
        s = Square(color=WHITE, fill_color=BLUE, fill_opacity=0.8)
        self.play(Create(s))
        self.play(s.animate.scale(1.5).rotate(PI / 4))
        self.play(s.animate.move_to([-3, 0, 0]))
        self.play(s.animate.move_to([3, 0, 0]))
        self.play(s.animate.scale(0.5).move_to(ORIGIN).rotate(-PI / 4))
        self.wait()<jupyter_output><empty_output><jupyter_text>**Exercise** (Optional) The attribute `s.animate` is an object that provides the methods `scale`, `move_to`, and `rotate`. Note that the methods can be called successively as in `s.animate.scale(0.5).move_to(ORIGIN).rotate(-PI/4)`. Why?  Animating multiple objects **Tessellation with regular polygons** Consider tiling a 12-by-6 plane using squares:<jupyter_code>%%manim -qm --progress_bar=none --disable_caching --flush_cache -v ERROR SquareTiling1
class SquareTiling1(Scene):
    WIDTH = 12
    HEIGHT = 6
    EDGE = 1

    def construct(self):
        plane = Rectangle(width=self.WIDTH, height=self.HEIGHT)
        unit = Square(color=WHITE, fill_color=BLUE, fill_opacity=0.8).scale(
            self.EDGE / 2
        )
        self.add(plane, unit)<jupyter_output><empty_output><jupyter_text>The first line of squares can be animated as follows:<jupyter_code>%%manim -qm --progress_bar=none --disable_caching --flush_cache -v ERROR SquareTiling2
class SquareTiling2(Scene):
    WIDTH = 12
    HEIGHT = 6
    EDGE = 1

    def construct(self):

        plane = Rectangle(width=self.WIDTH, height=self.HEIGHT)
        self.add(plane)

        unit = Square(color=WHITE, fill_color=BLUE, fill_opacity=0.8).scale(
            self.EDGE / 2
        )
        self.play(Create(unit))
        self.play(
            unit.animate.move_to(
                [-self.WIDTH / 2 + self.EDGE / 2, self.HEIGHT / 2 - self.EDGE / 2, 0]
            )
        )

        for i in range(1, self.WIDTH // self.EDGE):
            self.play(unit.copy().animate.shift([i, 0, 0]), run_time=1 / i)
        self.wait()<jupyter_output><empty_output><jupyter_text>We can use `VGroup` method to create a group of shapes.<jupyter_code>%%manim -qm --progress_bar=none --disable_caching --flush_cache -v ERROR SquareTiling3
class SquareTiling3(Scene):
    WIDTH = 12
    HEIGHT = 6
    EDGE = 1

    def construct(self):

        plane = Rectangle(width=self.WIDTH, height=self.HEIGHT)
        self.add(plane)

        unit = Square(color=WHITE, fill_color=BLUE, fill_opacity=0.8).scale(
            self.EDGE / 2
        )
        self.play(Create(unit))
        self.play(
            unit.animate.move_to(
                [-self.WIDTH / 2 + self.EDGE / 2, self.HEIGHT / 2 - self.EDGE / 2, 0]
            )
        )

        for i in range(1, math.floor(self.WIDTH / self.EDGE)):
            self.play(unit.copy().animate.shift([i * self.EDGE, 0, 0]), run_time=1 / i)

        line = VGroup(
            *[
                unit.copy().shift([i * self.EDGE, 0, 0])
                for i in range(math.floor(self.WIDTH / self.EDGE))
            ]
        )
        for i in range(1, math.floor(self.HEIGHT / self.EDGE)):
            self.play(line.copy().animate.shift([0, -i * self.EDGE, 0]), run_time=1 / i)

        self.wait()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13305463456825717, 'fraction_numerical': 0.015712844168949112, 'mean_word_length': 3.288009888751545, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 5, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '299402', 'license': 'MIT', 'n_tokens_mistral': 2395, 'n_tokens_neox': 2259, 'n_words': 605, 'path': 'Lab5/Manim.ipynb', 'repo_name': 'ccha23/CS1302', 'size': '6937'}