{ "cells": [ { "cell_type": "markdown", "id": "36cee816", "metadata": {}, "source": [ "# Řešení 2. série" ] }, { "cell_type": "code", "execution_count": null, "id": "efe16561", "metadata": {}, "outputs": [], "source": [ "from manim import *" ] }, { "cell_type": "markdown", "id": "36ec08cc", "metadata": {}, "source": [ "## Trojúhelník" ] }, { "cell_type": "code", "execution_count": null, "id": "e7a3da39", "metadata": {}, "outputs": [], "source": [ "%%manim -v WARNING -qh Triangle\n", "\n", "from random import *\n", "\n", "\n", "class Triangle(Scene):\n", " def construct(self):\n", " seed(0xDEADBEEF)\n", "\n", " # vše trochu zvětšíme\n", " c = 2\n", "\n", " p1 = Dot().scale(c).shift(UP * c)\n", " p2 = Dot().scale(c).shift(DOWN * c + LEFT * c)\n", " p3 = Dot().scale(c).shift(DOWN * c + RIGHT * c)\n", "\n", " points = VGroup(p1, p2, p3)\n", " \n", " self.play(Write(points, lag_ratio=0.5), run_time=1.5)\n", "\n", " l1 = Line()\n", " l2 = Line()\n", " l3 = Line()\n", "\n", " lines = VGroup(l1, l2, l3)\n", "\n", " def create_line_updater(a, b):\n", " \"\"\"Vrátí funkci, která se chová jako updater nějaké úsečky.\"\"\"\n", " return lambda x: x.become(Line(start=a.get_center(), end=b.get_center()))\n", "\n", " l1.add_updater(create_line_updater(p1, p2))\n", " l2.add_updater(create_line_updater(p2, p3))\n", " l3.add_updater(create_line_updater(p3, p1))\n", "\n", " self.play(Write(lines, lag_ratio=0.5), run_time=1.5)\n", "\n", " x = Tex(\"x\")\n", " y = Tex(\"y\")\n", " z = Tex(\"z\")\n", "\n", " x.add_updater(lambda x: x.next_to(p1, UP))\n", " y.add_updater(lambda x: x.next_to(p2, DOWN + LEFT))\n", " z.add_updater(lambda x: x.next_to(p3, DOWN + RIGHT))\n", "\n", " labels = VGroup(x, y, z).scale(c * 0.8)\n", "\n", " self.play(FadeIn(labels, shift=UP * 0.2))\n", "\n", " circle = Circle()\n", " circle.add_updater(\n", " lambda c: c.become(\n", " Circle.from_three_points(\n", " p1.get_center(), p2.get_center(), p3.get_center()\n", " )\n", " )\n", " )\n", "\n", " self.play(Write(circle))\n", "\n", " self.play(\n", " p2.animate.shift(LEFT + UP),\n", " p1.animate.shift(RIGHT),\n", " )" ] }, { "cell_type": "markdown", "id": "171e8840", "metadata": {}, "source": [ "## Vlna" ] }, { "cell_type": "code", "execution_count": null, "id": "252d64a3", "metadata": {}, "outputs": [], "source": [ "%%manim -v WARNING -qh Wave\n", "\n", "from random import *\n", "\n", "\n", "class Wave(Scene):\n", " def construct(self):\n", " seed(0xDEADBEEF)\n", "\n", " maze_string = \"\"\"\n", "#######################################################\n", "# ################# ## #\n", "# ################## #### #\n", "# ################# #### #\n", "# ############### ##### # ##\n", "# ######### ##### ####\n", "# ### ###### ######\n", "# ### ## ##### ### #####\n", "# #### ######## #### ##### ## #\n", "# ##### ########## ### ######## # #\n", "# ##### ########### ######## #\n", "# #### ########### ########## #\n", "# ## ########### ########## #\n", "# #### ############ ############# #\n", "# ###### ############ ############# #\n", "# ######### ## ########### ######### # #\n", "# ############### ######### ####### #\n", "# ############### ###### ###### #\n", "# ############### ##### #### #\n", "# ############# # ## #\n", "# # ####### ########### ####\n", "# ### # #################\n", "# ## #### #################\n", "##### ###### ##################\n", "###### ###### ##################\n", "# ### ### ####### ### ############### #\n", "# #### ############ #### ####### #\n", "# ##### ############ ### #\n", "# ### ########## #\n", "#######################################################\n", "\"\"\"\n", "\n", " maze = [] # 2D pole čtverců tak, jak ho vidíme\n", " maze_bool = [] # 2D pole True/False\n", " all_squares = VGroup()\n", "\n", " # parsujeme vstup, řádek po řádku\n", " for row in maze_string.strip().splitlines():\n", " maze.append([])\n", " maze_bool.append([])\n", "\n", " for char in row:\n", " square = Square(\n", " side_length=0.23,\n", " stroke_width=1,\n", " fill_color=WHITE if char == \"#\" else BLACK,\n", " fill_opacity=1,\n", " )\n", "\n", " maze[-1].append(square)\n", " maze_bool[-1].append(char == \" \")\n", " all_squares.add(square)\n", "\n", " # rozměry bludiště\n", " w = len(maze[0])\n", " h = len(maze)\n", "\n", " # rozmístění do gridu\n", " all_squares.arrange_in_grid(rows=h, buff=0)\n", "\n", " self.play(FadeIn(all_squares), run_time=2)\n", "\n", " # startovní pozice\n", " x, y = 1, 1\n", "\n", " colors = [\"#ef476f\", \"#ffd166\", \"#06d6a0\", \"#118ab2\"]\n", "\n", " # vytvoříme si slovník se vzdálenostmi od startu\n", " distances = {(x, y): 0}\n", " stack = [(x, y, 0)]\n", "\n", " while len(stack) != 0:\n", " x, y, d = stack.pop(0)\n", "\n", " for dx, dy in ((0, 1), (1, 0), (-1, 0), (0, -1)):\n", " nx, ny = dx + x, dy + y\n", "\n", " # není potřeba, jelikož vstup je ohraničený a nikde nevyběhneme :)\n", " #if nx < 0 or nx >= w or ny < 0 or ny >= h:\n", " # continue\n", "\n", " if maze_bool[ny][nx] and (nx, ny) not in distances:\n", " stack.append((nx, ny, d + 1))\n", " distances[(nx, ny)] = d + 1\n", "\n", " max_distance = max([d for d in distances.values()])\n", "\n", " all_colors = color_gradient(colors, max_distance + 1)\n", "\n", " # vytvoříme skupiny podle vzdálenosti od startu\n", " groups = []\n", " for d in range(max_distance + 1):\n", " groups.append(\n", " AnimationGroup(\n", " *[\n", " maze[y][x].animate.set_fill(all_colors[d])\n", " for x, y in distances\n", " if distances[x, y] == d\n", " ]\n", " )\n", " )\n", "\n", " self.play(AnimationGroup(*groups, lag_ratio=0.08))\n" ] }, { "cell_type": "markdown", "id": "e6f13b54", "metadata": {}, "source": [ "## Hilbert" ] }, { "cell_type": "code", "execution_count": null, "id": "06ed2d5c", "metadata": {}, "outputs": [], "source": [ "%%manim -v WARNING -qh Hilbert\n", "\n", "\n", "class Path(VMobject):\n", " def __init__(self, points, *args, **kwargs):\n", " super().__init__(self, *args, **kwargs)\n", " self.set_points_as_corners(points)\n", "\n", " def get_important_points(self):\n", " \"\"\"Vrátí důležité body křivky.\"\"\"\n", " return list(self.get_start_anchors()) + [self.get_end_anchors()[-1]]\n", "\n", "\n", "class Hilbert(Scene):\n", " def construct(self):\n", " directions = [LEFT + DOWN, LEFT + UP, RIGHT + UP, RIGHT + DOWN]\n", "\n", " hilbert = Path(directions).scale(3)\n", "\n", " self.play(Write(hilbert, lag_ratio=0.5))\n", "\n", " for i in range(1, 4):\n", " # délka jedné úsečky\n", " new_segment_length = 1 / (2 ** (i + 1) - 1)\n", "\n", " # škálování částí křivky tak, aby byla vycentrovaná\n", " new_scale = (1 - new_segment_length) / 2\n", "\n", " # chceme si uchovat původní křivku, abychom pomocí ní vyrovnávali ostatní\n", " lu = hilbert.copy()\n", " lu, hilbert = hilbert, lu\n", "\n", " self.play(\n", " lu.animate.scale(new_scale)\n", " .set_color(DARK_GRAY)\n", " .align_to(hilbert, directions[1])\n", " )\n", "\n", " ru = lu.copy()\n", " self.play(ru.animate.align_to(hilbert, directions[2]))\n", "\n", " ld, rd = lu.copy(), ru.copy()\n", " self.play(\n", " ld.animate.align_to(hilbert, directions[0]).rotate(-PI / 2),\n", " rd.animate.align_to(hilbert, directions[3]).rotate(PI / 2),\n", " )\n", "\n", " new_hilbert = Path(\n", " list(ld.flip(LEFT).get_important_points())\n", " + list(lu.get_important_points())\n", " + list(ru.get_important_points())\n", " + list(rd.flip(LEFT).get_important_points())\n", " )\n", "\n", " self.play(Write(new_hilbert, run_time=2 ** i))\n", "\n", " self.remove(lu, ru, ld, rd)\n", "\n", " hilbert = new_hilbert" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.1" } }, "nbformat": 4, "nbformat_minor": 5 }