Zdrojové kódy k příkladům a úlohám 34. série KSP (Manim).
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

675 lines
20 KiB

{
"cells": [
{
"cell_type": "markdown",
"id": "substantial-impact",
"metadata": {},
"source": [
"# Vítej!"
]
},
{
"cell_type": "markdown",
"id": "first-armenia",
"metadata": {},
"source": [
"Tento dokument obsahuje zdrojové kódy animací ke čtvrté sérii seriálu KSP. Před spouštěním opět nezapomeň Manim importovat spuštěním následujícího řádku!"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e03b150c",
"metadata": {},
"outputs": [],
"source": [
"from manim import *"
]
},
{
"cell_type": "markdown",
"id": "45897e9c",
"metadata": {},
"source": [
"## Booleovské operace"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6aa5ba0f",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh BooleanOperations\n",
"\n",
"\n",
"class BooleanOperations(Scene):\n",
" def construct(self):\n",
"\n",
" circle = Circle(fill_opacity=0.75, color=RED).scale(2).shift(LEFT * 1.5)\n",
" square = Square(fill_opacity=0.75, color=GREEN).scale(2).shift(RIGHT * 1.5)\n",
"\n",
" group = VGroup(circle, square)\n",
"\n",
" self.play(Write(group))\n",
"\n",
" self.play(group.animate.scale(0.5).shift(UP * 1.6))\n",
"\n",
" union = Union(circle, square, fill_opacity=1, color=BLUE)\n",
"\n",
" # postupně voláme Union(), Intersection() a Difference()\n",
" for operation, position, name in zip(\n",
" [Intersection, Union, Difference],\n",
" [LEFT * 3.3, ORIGIN, RIGHT * 4.5],\n",
" [\"Průnik\", \"Sjednocení\", \"Rozdíl\"],\n",
" ):\n",
" result = operation(circle, square, fill_opacity=1, color=DARK_BLUE)\n",
" result_position = DOWN * 1.3 + position\n",
" \n",
" label = Tex(name).move_to(result_position).scale(0.8)\n",
" \n",
" self.play(\n",
" AnimationGroup(\n",
" FadeIn(result),\n",
" result.animate.move_to(result_position),\n",
" FadeIn(label),\n",
" lag_ratio=0.5,\n",
" )\n",
" )"
]
},
{
"cell_type": "markdown",
"id": "3da40017",
"metadata": {},
"source": [
"## Vlastní objekty"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cf1fb3b5",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh StackExample\n",
"\n",
"\n",
"class Stack(VMobject):\n",
" def __init__(self, size, *args, **kwargs):\n",
" # inicializace VGroup objektu\n",
" super().__init__(**kwargs)\n",
"\n",
" self.squares = VGroup()\n",
" self.labels = VGroup()\n",
" self.index = 0\n",
" self.pointer = Arrow(ORIGIN, UP * 1.2)\n",
"\n",
" for _ in range(size):\n",
" self.squares.add(Square(side_length=0.8))\n",
"\n",
" self.squares.arrange(buff=0.15)\n",
"\n",
" self.pointer.next_to(self.squares[0], DOWN)\n",
" self.add()\n",
"\n",
" # DŮLEŽITÉ - přidáme do objektu všechny podobjekty!\n",
" self.add(self.squares, self.labels, self.pointer)\n",
"\n",
" def __get_index_rectangle_color(self):\n",
" \"\"\"Vrátí barvu aktuálního obdelníků stacku.\"\"\"\n",
" return self.squares[self.index].get_color()\n",
"\n",
" def __create_label(self, element):\n",
" \"\"\"Vytvoření labelu daného prvku (podle barvy a rozměrů čtverců stacku).\"\"\"\n",
" return (\n",
" Tex(str(element))\n",
" .scale(self.squares[0].height)\n",
" .set_color(self.__get_index_rectangle_color())\n",
" )\n",
"\n",
" def push(self, element):\n",
" \"\"\"Přidá prvek do zásobníku. Vrátí odpovídající animace.\"\"\"\n",
" self.labels.add(self.__create_label(element).move_to(self.squares[self.index]))\n",
" self.index += 1\n",
"\n",
" return AnimationGroup(\n",
" FadeIn(self.labels[-1]),\n",
" self.pointer.animate.next_to(self.squares[self.index], DOWN),\n",
" Indicate(\n",
" self.squares[self.index - 1], color=self.__get_index_rectangle_color()\n",
" ),\n",
" )\n",
"\n",
" def pop(self):\n",
" \"\"\"Odebere prvek ze zásobníku. Vrátí odpovídající animace.\"\"\"\n",
" label = self.labels[-1]\n",
" self.labels.remove(label)\n",
" self.index -= 1\n",
"\n",
" return AnimationGroup(\n",
" FadeOut(label),\n",
" self.pointer.animate.next_to(self.squares[self.index], DOWN),\n",
" Indicate(\n",
" self.squares[self.index],\n",
" color=self.__get_index_rectangle_color(),\n",
" scale_factor=1 / 1.2,\n",
" ),\n",
" )\n",
"\n",
" def clear(self):\n",
" \"\"\"Vyčistí zásobník. Vrátí odpovídající animaci.\"\"\"\n",
" result = AnimationGroup(*[self.pop() for _ in range(self.index)], lag_ratio=0)\n",
"\n",
" self.index = 0\n",
"\n",
" return result\n",
"\n",
"\n",
"class StackExample(Scene):\n",
" def construct(self):\n",
" stack = Stack(10)\n",
"\n",
" # na objekt fungují správně libovolné animace\n",
" self.play(Write(stack))\n",
"\n",
" self.wait(0.5)\n",
"\n",
" for i in range(5):\n",
" self.play(stack.push(i))\n",
"\n",
" self.play(stack.pop())\n",
"\n",
" self.wait(0.5)\n",
"\n",
" # můžeme používat i animate syntax!\n",
" # měnění barvy se rekurzivně aplikuje na všechny podobjekty\n",
" self.play(stack.animate.scale(1.3).set_color(BLUE))\n",
"\n",
" self.wait(0.5)\n",
"\n",
" for i in range(2):\n",
" self.play(stack.push(i))\n",
"\n",
" self.play(stack.pop())\n",
"\n",
" self.play(stack.clear())\n",
"\n",
" self.play(FadeOut(stack))"
]
},
{
"cell_type": "markdown",
"id": "88f6f285",
"metadata": {},
"source": [
"## Jiné grafy"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0906f798",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh GraphExample\n",
"\n",
"from math import sin\n",
"\n",
"\n",
"class GraphExample(Scene):\n",
" def construct(self):\n",
" # osy - rozmezí a značení os x, y\n",
" axes = Axes(x_range=[-5, 5], y_range=[-3, 7])\n",
" labels = axes.get_axis_labels(x_label=\"x\", y_label=\"y\")\n",
"\n",
" def f1(x):\n",
" return x ** 2\n",
"\n",
" def f2(x):\n",
" return sin(x)\n",
"\n",
" # objekty vykreslených funkcí\n",
" g1 = axes.plot(f1, color=RED)\n",
" g2 = axes.plot(f2, color=BLUE)\n",
"\n",
" self.play(Write(axes), Write(labels))\n",
"\n",
" self.play(AnimationGroup(Write(g1), Write(g2), lag_ratio=0.5))\n",
"\n",
" self.play(Unwrite(axes), Unwrite(labels), Unwrite(g1), Unwrite(g2))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "84978263",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh DiscontinuousGraphExample\n",
"\n",
"from math import sin\n",
"\n",
"\n",
"class DiscontinuousGraphExample(Scene):\n",
" def construct(self):\n",
" axes = Axes(x_range=[-5, 5], y_range=[-3, 7])\n",
" labels = axes.get_axis_labels(x_label=\"x\", y_label=\"y\")\n",
"\n",
" def f(x):\n",
" return 1 / x\n",
"\n",
" g_bad = axes.plot(f, color=RED)\n",
"\n",
" # rozdělení na dvě části podle hodnot x\n",
" g_left = axes.plot(f, x_range=[-5, -0.1], color=GREEN)\n",
" g_right = axes.plot(f, x_range=[0.1, 5], color=GREEN)\n",
"\n",
" self.play(Write(axes), Write(labels))\n",
"\n",
" self.play(Write(g_bad))\n",
" self.play(FadeOut(g_bad))\n",
"\n",
" self.play(AnimationGroup(Write(g_left), Write(g_right), lag_ratio=0.5))\n",
"\n",
" self.play(Unwrite(axes), Unwrite(labels), Unwrite(g_left), Unwrite(g_right))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "521d3286",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh ParametricGraphExample\n",
"\n",
"from math import sin, cos\n",
"\n",
"\n",
"class ParametricGraphExample(Scene):\n",
" def construct(self):\n",
" axes = Axes(x_range=[-10, 10], y_range=[-5, 5])\n",
" labels = axes.get_axis_labels(x_label=\"x\", y_label=\"y\")\n",
"\n",
" def f1(t):\n",
" \"\"\"Parametrická funkce kružnice.\"\"\"\n",
" return (cos(t) * 3 - 4.5, sin(t) * 3)\n",
"\n",
" def f2(t):\n",
" \"\"\"Parametrická funkce <3.\"\"\"\n",
" return (\n",
" 0.2 * (16 * (sin(t)) ** 3) + 4.5,\n",
" 0.2 * (13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t)),\n",
" )\n",
"\n",
" # objekty vykreslených funkcí\n",
" # místo axes.plot používáme axes.plot_parametric_curve\n",
" # parametr t_range určuje, jaké je rozmezí parametru t\n",
" g1 = axes.plot_parametric_curve(f1, color=RED, t_range=[0, 2 * PI])\n",
" g2 = axes.plot_parametric_curve(f2, color=BLUE, t_range=[-PI, PI])\n",
"\n",
" self.play(Write(axes), Write(labels))\n",
"\n",
" self.play(AnimationGroup(Write(g1), Write(g2), lag_ratio=0.5))\n",
"\n",
" self.play(Unwrite(axes), Unwrite(labels), Unwrite(g1), Unwrite(g2))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c0e61a1b",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh LineGraphExample\n",
"\n",
"from random import random, seed\n",
"\n",
"\n",
"class LineGraphExample(Scene):\n",
" def construct(self):\n",
" seed(0xDEADBEEF2) # hezčí hodnoty :P\n",
"\n",
" # hodnoty ke grafování (x a y)\n",
" # u np.arange(l, r, step) vrátí pole hodnot od l do r (nevčetně) s kroky velikosti step\n",
" x_values = np.arange(-1, 1 + 0.25, 0.25)\n",
" y_values = [random() for _ in x_values]\n",
"\n",
" # osy (tentokrát s čísly)\n",
" axes = Axes(\n",
" x_range=[-1, 1, 0.25],\n",
" y_range=[-0.1, 1, 0.25],\n",
" # nastavení čísel - hodnoty a počet desetinných míst\n",
" x_axis_config={\"numbers_to_include\": x_values},\n",
" y_axis_config={\"numbers_to_include\": np.arange(0, 1, 0.25)},\n",
" axis_config={\"decimal_number_config\": {\"num_decimal_places\": 2}},\n",
" )\n",
"\n",
" labels = axes.get_axis_labels(x_label=\"x\", y_label=\"y\")\n",
"\n",
" # místo axes.plot používáme axes.plot_line_graph\n",
" graph = axes.plot_line_graph(x_values=x_values, y_values=y_values)\n",
"\n",
" self.play(Write(axes), Write(labels))\n",
"\n",
" self.play(Write(graph), run_time=2)\n",
"\n",
" self.play(Unwrite(axes), Unwrite(labels), Unwrite(graph))"
]
},
{
"cell_type": "markdown",
"id": "bb5423f4",
"metadata": {},
"source": [
"## 3D operace"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ab85ca2d",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh Axes3DExample\n",
"\n",
"\n",
"class Axes3DExample(ThreeDScene):\n",
" def construct(self):\n",
" # 3D osy\n",
" axes = ThreeDAxes()\n",
"\n",
" x_label = axes.get_x_axis_label(Tex(\"x\"))\n",
" y_label = axes.get_y_axis_label(Tex(\"y\")).shift(UP * 1.8)\n",
"\n",
" # 3D varianta Dot() objektu\n",
" dot = Dot3D()\n",
"\n",
" # zmenšení zoomu, abychom viděli osy\n",
" self.set_camera_orientation(zoom=0.5)\n",
"\n",
" self.play(FadeIn(axes), FadeIn(dot), FadeIn(x_label), FadeIn(y_label))\n",
"\n",
" self.wait(0.5)\n",
"\n",
" # animace posunutí kamery tak, aby byly osy dobře vidět\n",
" self.move_camera(phi=75 * DEGREES, theta=30 * DEGREES, zoom=1, run_time=1.5)\n",
"\n",
" # vestavěný updater, který kameru začne rotovat (aby na scénu bylo lépe vidět)\n",
" self.begin_ambient_camera_rotation(rate=0.15)\n",
"\n",
" # jedna tečka za každý směr\n",
" upDot = dot.copy().set_color(RED)\n",
" rightDot = dot.copy().set_color(BLUE)\n",
" outDot = dot.copy().set_color(GREEN)\n",
"\n",
" self.wait(1)\n",
"\n",
" self.play(\n",
" upDot.animate.shift(UP),\n",
" rightDot.animate.shift(RIGHT),\n",
" outDot.animate.shift(OUT),\n",
" )\n",
"\n",
" self.wait(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "efc147d5",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh Rotation3DExample\n",
"\n",
"\n",
"class Rotation3DExample(ThreeDScene):\n",
" def construct(self):\n",
" # přidání jednoduché základní krychle\n",
" cube = Cube(side_length=3, fill_opacity=1)\n",
"\n",
" self.begin_ambient_camera_rotation(rate=0.3)\n",
"\n",
" # posunutí orientace kamery bez animace\n",
" self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)\n",
"\n",
" self.play(Write(cube), run_time=2)\n",
"\n",
" self.wait(3)\n",
"\n",
" self.play(Unwrite(cube), run_time=2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "127ccd71",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh Basic3DExample\n",
"\n",
"\n",
"class Basic3DExample(ThreeDScene):\n",
" def construct(self):\n",
" # přidání jednoduché základní krychle\n",
" cube = Cube(side_length=3, fill_opacity=0.5)\n",
"\n",
" self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)\n",
"\n",
" self.play(FadeIn(cube))\n",
"\n",
" for axis in [RIGHT, UP, OUT]:\n",
" self.play(Rotate(cube, PI / 2, about_point=ORIGIN, axis=axis))\n",
"\n",
" self.play(FadeOut(cube))"
]
},
{
"cell_type": "markdown",
"id": "98daca2b",
"metadata": {},
"source": [
"## Kostry úloh"
]
},
{
"cell_type": "markdown",
"id": "8746ae11",
"metadata": {},
"source": [
"### Simulace binomického rozložení [6b]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "18fb5e35",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh BinomialDistributionSimulation\n",
"\n",
"\n",
"class BinomialDistributionSimulation(Scene):\n",
" def construct(self):\n",
" pass"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b7139b0d",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh BezierExample\n",
"\n",
"from random import choice, seed\n",
"\n",
"\n",
"class MoveAndFade(Animation):\n",
" def __init__(self, mobject: Mobject, path: VMobject, **kwargs):\n",
" self.path = path\n",
" self.original = mobject.copy()\n",
" super().__init__(mobject, **kwargs)\n",
"\n",
" def interpolate_mobject(self, alpha: float) -> None:\n",
" point = self.path.point_from_proportion(self.rate_func(alpha))\n",
"\n",
" # tohle není úplně čisté, jelikož pokaždé vytváříme nový objekt\n",
" # je to kvůli tomu, že obj.fade() nenastavuje průhlednost ale přidává jí\n",
" self.mobject.become(self.original.copy()).move_to(point).fade(alpha)\n",
"\n",
"\n",
"class BezierExample(Scene):\n",
" def construct(self):\n",
" # křivku definujeme přes čtyři body:\n",
" # 2 krajní, ve kterých začíná a končí\n",
" # 2 kontrolní, které určují tvar\n",
" positions = [\n",
" UP + LEFT * 3, # počáteční\n",
" UP + RIGHT * 2, # 1. kontrolní\n",
" DOWN + LEFT * 2, # 2. kontrolní\n",
" DOWN + RIGHT * 3, # koncový\n",
" ]\n",
"\n",
" points = VGroup(*[Dot().move_to(position) for position in positions]).scale(1.5)\n",
"\n",
" # rozlišíme kontrolní body\n",
" points[1].set_color(BLUE)\n",
" points[2].set_color(BLUE)\n",
"\n",
" bezier = CubicBezier(*positions).scale(1.5)\n",
"\n",
" self.play(Write(bezier), Write(points))\n",
"\n",
" # animace posunu\n",
" circle = Circle(fill_opacity=1, stroke_opacity=0).scale(0.25).move_to(points[0])\n",
"\n",
" self.play(FadeIn(circle, shift=RIGHT * 0.5))\n",
" self.play(MoveAlongPath(circle, bezier))\n",
"\n",
" self.play(FadeOut(circle))\n",
"\n",
" # animace posunu s mizením\n",
" circle = (\n",
" Circle(fill_color=GREEN, fill_opacity=1, stroke_opacity=0)\n",
" .scale(0.25)\n",
" .move_to(points[0])\n",
" )\n",
"\n",
" self.play(FadeIn(circle, shift=RIGHT * 0.5))\n",
" self.play(MoveAndFade(circle, bezier))\n",
"\n",
" self.play(FadeOut(bezier), FadeOut(points), FadeOut(circle))"
]
},
{
"cell_type": "markdown",
"id": "4de93509",
"metadata": {},
"source": [
"### 3D Game of Life [9b]"
]
},
{
"cell_type": "markdown",
"id": "eee60fd6",
"metadata": {},
"source": [
"#### Dvoustavový [5b]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d95d2328",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh GOLTwoState\n",
"\n",
"\n",
"class GOLTwoState(ThreeDScene):\n",
" def construct(self):\n",
" pass"
]
},
{
"cell_type": "markdown",
"id": "3fd9c87c",
"metadata": {},
"source": [
"#### Vícestavový [3b]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9525cea2",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh GOLMultiState\n",
"\n",
"\n",
"class GOLMultiState(ThreeDScene):\n",
" def construct(self):\n",
" pass"
]
},
{
"cell_type": "markdown",
"id": "464edd8b",
"metadata": {},
"source": [
"#### Vlastní [1b]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "01394a96",
"metadata": {},
"outputs": [],
"source": [
"%%manim -v WARNING -qh GOLCustom\n",
"\n",
"\n",
"class GOLCustom(ThreeDScene):\n",
" def construct(self):\n",
" pass"
]
}
],
"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.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}