from manimlib.imports import * class EnumerableSaveScene(Scene): def setup(self): self.save_count = 0 def save_enumerated_image(self): file_path = self.file_writer.get_image_file_path() file_path = file_path.replace( ".png", "{:02}.png".format(self.save_count) ) self.update_frame(ignore_skipping=True) image = self.get_image() image.save(file_path) self.save_count += 1 class LayersOfAbstraction(EnumerableSaveScene): def construct(self): self.save_count = 0 # self.add_title() self.show_layers() self.show_pairwise_relations() self.circle_certain_pairs() def add_title(self): title = TextMobject("Layers of abstraction") title.scale(1.5) title.to_edge(UP, buff=MED_SMALL_BUFF) line = Line(LEFT, RIGHT) line.set_width(FRAME_WIDTH) line.next_to(title, DOWN, SMALL_BUFF) self.add(title, line) def show_layers(self): layers = self.layers = self.get_layers() for layer in layers: self.add(layer[0]) self.save_enumerated_image() for layer in layers: self.add(layer) self.save_enumerated_image() def show_pairwise_relations(self): p1, p2 = [l.get_left() for l in self.layers[2:4]] down_arrow = Arrow(p2, p1, path_arc=PI) down_words = TextMobject("``For example''") down_words.scale(0.8) down_words.next_to(down_arrow, LEFT) up_arrow = Arrow(p1, p2, path_arc=-PI) up_words = TextMobject("``In general''") up_words.scale(0.8) up_words.next_to(up_arrow, LEFT) VGroup(up_words, down_words).set_color(YELLOW) self.add(down_arrow, down_words) self.save_enumerated_image() self.remove(down_arrow, down_words) self.add(up_arrow, up_words) self.save_enumerated_image() self.remove(up_arrow, up_words) def circle_certain_pairs(self): layers = self.layers for l1, l2 in zip(layers, layers[1:]): group = VGroup(l1, l2) group.save_state() layers.save_state() layers.fade(0.75) rect = SurroundingRectangle(group) rect.set_stroke(YELLOW, 5) group.restore() self.add(rect) self.save_enumerated_image() self.remove(rect) layers.restore() # def get_layers(self): layers = VGroup(*[ VGroup(Rectangle(height=1, width=5)) for x in range(6) ]) layers.arrange_submobjects(UP, buff=0) layers.set_stroke(GREY, 2) layers.set_sheen(1, UL) # Layer 0: Quantities triangle = Triangle().set_height(0.25) tri_dots = VGroup(*[Dot(v) for v in triangle.get_vertices()]) dots_rect = VGroup(*[Dot() for x in range(12)]) dots_rect.arrange_in_grid(3, 4, buff=SMALL_BUFF) for i, color in enumerate([RED, GREEN, BLUE]): dots_rect[i::4].set_color(color) pi_chart = VGroup(*[ Sector(start_angle=a, angle=TAU / 3) for a in np.arange(0, TAU, TAU / 3) ]) pi_chart.set_fill(opacity=0) pi_chart.set_stroke(WHITE, 2) pi_chart[0].set_fill(BLUE, 1) pi_chart.rotate(PI / 3) pi_chart.match_height(dots_rect) quantities = VGroup(tri_dots, dots_rect, pi_chart) quantities.arrange(RIGHT, buff=LARGE_BUFF) # Layer 1: Numbers numbers = VGroup( TexMobject("3"), TexMobject("3 \\times 4"), TexMobject("1 / 3"), ) for number, quantity in zip(numbers, quantities): number.move_to(quantity) # Layer 2: Algebra algebra = VGroup( TexMobject("x^2 - 1 = (x + 1)(x - 1)") ) algebra.set_width(layers.get_width() - MED_LARGE_BUFF) # Layer 3: Functions functions = VGroup( TexMobject("f(x) = 0"), TexMobject("\\frac{df}{dx}"), ) functions.set_height(layers[0].get_height() - 2 * SMALL_BUFF) functions.arrange(RIGHT, buff=LARGE_BUFF) # functions.match_width(algebra) # Layer 4: Vector space t2c_map = { "\\textbf{v}": YELLOW, "\\textbf{w}": PINK, } vector_spaces = VGroup( TexMobject( "\\textbf{v} + \\textbf{w} =" "\\textbf{w} + \\textbf{v}", tex_to_color_map=t2c_map, ), TexMobject( "s(\\textbf{v} + \\textbf{w}) =" "s\\textbf{v} + s\\textbf{w}", tex_to_color_map=t2c_map, ), ) vector_spaces.arrange(DOWN, buff=MED_SMALL_BUFF) vector_spaces.set_height(layers[0].get_height() - MED_LARGE_BUFF) v, w = vectors = VGroup( Vector([2, 1, 0], color=YELLOW), Vector([1, 2, 0], color=PINK), ) vectors.add(DashedLine(v.get_end(), v.get_end() + w.get_vector())) vectors.add(DashedLine(w.get_end(), w.get_end() + v.get_vector())) vectors.match_height(vector_spaces) vectors.next_to(vector_spaces, RIGHT) vectors.set_stroke(width=2) # vector_spaces.add(vectors) inner_product = TexMobject( "\\langle f, g \\rangle =" "\\int f(x)g(x)dx" ) inner_product.match_height(vector_spaces) inner_product.next_to(vector_spaces, RIGHT) vector_spaces.add(inner_product) # Layer 5: Categories dots = VGroup(Dot(UP), Dot(UR), Dot(RIGHT)) arrows = VGroup( Arrow(dots[0], dots[1], buff=SMALL_BUFF), Arrow(dots[1], dots[2], buff=SMALL_BUFF), Arrow(dots[0], dots[2], buff=SMALL_BUFF), ) arrows.set_stroke(width=2) arrow_labels = VGroup( TexMobject("m_1").next_to(arrows[0], UP, SMALL_BUFF), TexMobject("m_2").next_to(arrows[1], RIGHT, SMALL_BUFF), TexMobject("m_2 \\circ m_1").rotate(-45 * DEGREES).move_to( arrows[2] ).shift(MED_SMALL_BUFF * DL) ) categories = VGroup(dots, arrows, arrow_labels) categories.set_height(layers[0].get_height() - MED_SMALL_BUFF) # Put it all together all_content = [ quantities, numbers, algebra, functions, vector_spaces, categories, ] for layer, content in zip(layers, all_content): content.move_to(layer) layer.add(content) layer.content = content layer_titles = VGroup(*map(TextMobject, [ "Quantities", "Numbers", "Algebra", "Functions", "Vector spaces", "Categories", ])) for layer, title in zip(layers, layer_titles): title.next_to(layer, RIGHT) layer.add(title) layer.title = title layers.titles = layer_titles layers.center() layers.to_edge(DOWN) layers.shift(0.5 * RIGHT) return layers class DifferenceOfSquares(Scene): def construct(self): squares = VGroup(*[ VGroup(*[ Square() for x in range(8) ]).arrange(RIGHT, buff=0) for y in range(8) ]).arrange(DOWN, buff=0) squares.set_height(4) squares.set_stroke(BLUE, 3) squares.set_fill(BLUE, 0.5) last_row_parts = VGroup() for row in squares[-3:]: row[-3:].set_color(RED) row[:-3].set_color(BLUE_B) last_row_parts.add(row[:-3]) squares.to_edge(LEFT) arrow = Vector(RIGHT, color=WHITE) arrow.shift(1.5 * LEFT) squares.next_to(arrow, LEFT) new_squares = squares[:-3].copy() new_squares.next_to(arrow, RIGHT) new_squares.align_to(squares, UP) x1 = TexMobject("x").set_color(BLUE) x2 = x1.copy() x1.next_to(squares, UP) x2.next_to(squares, LEFT) y1 = TexMobject("y").set_color(RED) y2 = y1.copy() y1.next_to(squares[-2], RIGHT) y2.next_to(squares[-1][-2], DOWN) xpy = TexMobject("x", "+", "y") xmy = TexMobject("x", "-", "y") for mob in xpy, xmy: mob[0].set_color(BLUE) mob[2].set_color(RED) xpy.next_to(new_squares, UP) # xmy.rotate(90 * DEGREES) xmy.next_to(new_squares, RIGHT) xmy.to_edge(RIGHT) self.add(squares, x1, x2, y1, y2) self.play( ReplacementTransform( squares[:-3].copy().set_fill(opacity=0), new_squares ), ShowCreation(arrow), lag_ratio=0, ) last_row_parts = last_row_parts.copy() last_row_parts.save_state() last_row_parts.set_fill(opacity=0) self.play( last_row_parts.restore, last_row_parts.rotate, -90 * DEGREES, last_row_parts.next_to, new_squares, RIGHT, {"buff": 0}, lag_ratio=0, ) self.play(Write(xmy), Write(xpy)) self.wait() class Lightbulbs(EnumerableSaveScene): def construct(self): dots = VGroup(*[Dot() for x in range(4)]) dots.set_height(0.5) dots.arrange(RIGHT, buff=2) dots.set_fill(opacity=0) dots.set_stroke(width=2, color=WHITE) dot_radius = dots[0].get_width() / 2 connections = VGroup() for d1, d2 in it.product(dots, dots): line = Line( d1.get_center(), d2.get_center(), path_arc=30 * DEGREES, buff=dot_radius, color=YELLOW, ) connections.add(line) lower_dots = dots[:3].copy() lower_dots.next_to(dots, DOWN, buff=2) lower_lines = VGroup(*[ Line(d.get_center(), ld.get_center(), buff=dot_radius) for d, ld in it.product(dots, lower_dots[1:]) ]) lower_lines.match_style(connections) top_dot = dots[0].copy() top_dot.next_to(dots, UP, buff=2) top_lines = VGroup(*[ Line(d.get_center(), top_dot.get_center(), buff=dot_radius) for d in dots ]) top_lines.match_style(connections) self.add(dots) self.add(top_dot) self.save_enumerated_image() dots.set_fill(YELLOW, 1) self.save_enumerated_image() self.add(connections) self.save_enumerated_image() self.add(lower_dots) self.add(lower_lines) lower_dots[1:].set_fill(YELLOW, 1) self.save_enumerated_image() self.add(top_lines) connections.set_stroke(width=1) lower_lines.set_stroke(width=1) top_dot.set_fill(YELLOW, 1) self.save_enumerated_image() self.remove(connections) self.remove(top_lines) self.remove(lower_lines) dots.set_fill(opacity=0) lower_dots.set_fill(opacity=0) class LayersOfLightbulbs(Scene): CONFIG = { "random_seed": 1, } def construct(self): layers = VGroup() for x in range(6): n_dots = 5 + (x % 2) dots = VGroup(*[Dot() for x in range(n_dots)]) dots.scale(2) dots.arrange(RIGHT, buff=MED_LARGE_BUFF) dots.set_stroke(WHITE, 2) for dot in dots: dot.set_fill(YELLOW, np.random.random()) layers.add(dots) layers.arrange(UP, buff=LARGE_BUFF) lines = VGroup() for l1, l2 in zip(layers, layers[1:]): for d1, d2 in it.product(l1, l2): color = interpolate_color( YELLOW, GREEN, np.random.random() ) line = Line( d1.get_center(), d2.get_center(), buff=(d1.get_width() / 2), color=color, stroke_width=2 * np.random.random(), ) lines.add(line) self.add(layers, lines) class Test(Scene): def construct(self): # self.change_all_student_modes("hooray") # self.teacher.change("raise_right_hand") # self.look_at(3 * UP) randy = Randolph() randy.change("pondering") randy.set_height(6) randy.look(RIGHT) self.add(randy) # eq = TexMobject("143", "=", "11 \\cdot 13") # eq[0].set_color(YELLOW) # eq.scale(0.7) # self.add(eq)