def construct(self): curve = HilbertCurve(order=1) grid = Grid(2, 2, stroke_width=1) self.add(grid, curve) for order in range(2, 6): self.dither() new_grid = Grid(2**order, 2**order, stroke_width=1) self.play(ShowCreation(new_grid), Animation(curve)) self.remove(grid) grid = new_grid self.play(Transform(curve, HilbertCurve(order=order))) square = Square(side_length=6, color=WHITE) square.corner = Mobject1D() square.corner.add_line(3 * DOWN, ORIGIN) square.corner.add_line(ORIGIN, 3 * RIGHT) square.digest_mobject_attrs() square.scale(2**(-5)) square.corner.highlight( Color(rgb=curve.rgbs[curve.get_num_points() / 3])) square.shift( grid.get_corner(UP+LEFT)-\ square.get_corner(UP+LEFT) ) self.dither() self.play(FadeOut(grid), FadeOut(curve), FadeIn(square)) self.play(ApplyMethod(square.replace, grid)) self.dither()
def construct(self): curve = PeanoCurve(order=5) curve.stretch_to_fit_width(2 * SPACE_WIDTH) curve.stretch_to_fit_height(2 * SPACE_HEIGHT) curve_start = curve.copy() curve_start.apply_over_attr_arrays(lambda arr: arr[:200]) time_line = get_time_line() time_line.shift(-time_line.number_to_point(2000)) self.add(time_line) self.play( ApplyMethod(time_line.shift, -time_line.number_to_point(1900), run_time=3)) brace = Brace( Mobject( Point(time_line.number_to_point(1865)), Point(time_line.number_to_point(1888)), ), UP) words = TextMobject(""" Cantor drives himself (and the \\\\ mathematical community at large) \\\\ crazy with research on infinity. """) words.next_to(brace, UP) self.play(GrowFromCenter(brace), ShimmerIn(words)) self.dither() self.play(Transform(time_line, curve_start), FadeOut(brace), FadeOut(words)) self.play(ShowCreation(curve, run_time=5, rate_func=None)) self.dither()
def construct(self): names = [ "Johann_Bernoulli2", "Jacob_Bernoulli", "Gottfried_Wilhelm_von_Leibniz", "Newton" ] guys = [ImageMobject(name, invert=False) for name in names] johann = guys[0] johann.scale(0.8) pensive_johann = johann.copy() pensive_johann.scale(0.25) pensive_johann.to_corner(DOWN + LEFT) comparitive_johann = johann.copy() template = Square(side_length=2) comparitive_johann.replace(template) comparitive_johann.shift(UP + LEFT) greater_than = TexMobject(">") greater_than.next_to(comparitive_johann) for guy, name in zip(guys, names)[1:]: guy.replace(template) guy.next_to(greater_than) name_mob = TextMobject(name.replace("_", " ")) name_mob.scale(0.5) name_mob.next_to(guy, DOWN) guy.name_mob = name_mob guy.sort_points(lambda p: np.dot(p, DOWN + RIGHT)) bubble = ThoughtBubble(initial_width=12) bubble.stretch_to_fit_height(6) bubble.ingest_submobjects() bubble.pin_to(pensive_johann) bubble.shift(DOWN) point = Point(johann.get_corner(UP + RIGHT)) upper_point = Point(comparitive_johann.get_corner(UP + RIGHT)) lightbulb = ImageMobject("Lightbulb", invert=False) lightbulb.scale(0.1) lightbulb.sort_points(np.linalg.norm) lightbulb.next_to(upper_point, RIGHT) self.add(johann) self.wait() self.play(Transform(johann, pensive_johann), Transform(point, bubble), run_time=2) self.remove(point) self.add(bubble) weakling = guys[1] self.play(FadeIn(comparitive_johann), ShowCreation(greater_than), FadeIn(weakling)) self.wait(2) for guy in guys[2:]: self.play(DelayByOrder(Transform(weakling, upper_point))) self.play(FadeIn(guy), ShimmerIn(guy.name_mob)) self.wait(3) self.remove(guy.name_mob) weakling = guy self.play(FadeOut(weakling), FadeOut(greater_than)) self.play(ShowCreation(lightbulb)) self.wait() self.play(FadeOut(comparitive_johann), FadeOut(lightbulb)) self.play(ApplyMethod(Mobject(johann, bubble).scale, 10, run_time=3))
def __init__(self, pi_creature, **kwargs): assert hasattr(pi_creature, "bubble") digest_config(self, kwargs, locals()) AnimationGroup.__init__( self, ApplyMethod(pi_creature.change_mode, self.target_mode), FadeOut(pi_creature.bubble), FadeOut(pi_creature.bubble.content), )
def __init__(self, pi_creature, **kwargs): assert hasattr(pi_creature, "bubble") digest_config(self, kwargs, locals()) pi_creature.generate_target() pi_creature.target.change_mode(self.target_mode) if self.look_at_arg is not None: pi_creature.target.look_at(self.look_at_arg) AnimationGroup.__init__( self, MoveToTarget(pi_creature), FadeOut(pi_creature.bubble), FadeOut(pi_creature.bubble.content), )
def construct(self): words = TextMobject([ "One does not simply define the limit \\\\ \ of a sequence of", "curves", "\\dots" ]) top_words = TextMobject(["curves", "are functions"]).to_edge(UP) curves1 = words.split()[1] curves2 = top_words.split()[0] words.ingest_submobjects() number = TexMobject("0.27") pair = TexMobject("(0.53, 0.02)") pair.next_to(number, buff=2) arrow = Arrow(number, pair) Mobject(number, arrow, pair).center().shift(UP) number_line = UnitInterval() number_line.stretch_to_fit_width(5) number_line.to_edge(LEFT).shift(DOWN) grid = Grid(4, 4).scale(0.4) grid.next_to(number_line, buff=2) low_arrow = Arrow(number_line, grid) self.play(ShimmerIn(words)) self.dither() self.play(FadeOut(words), ApplyMethod(curves1.replace, curves2), ShimmerIn(top_words.split()[1])) self.dither() self.play(FadeIn(number)) self.play(ShowCreation(arrow)) self.play(FadeIn(pair)) self.dither() self.play(ShowCreation(number_line)) self.play(ShowCreation(low_arrow)) self.play(ShowCreation(grid)) self.dither()
def coords_to_vector(self, vector, coords_start=2 * RIGHT + 2 * UP, clean_up=True): starting_mobjects = list(self.mobjects) array = Matrix(vector) array.shift(coords_start) arrow = Vector(vector) x_line = Line(ORIGIN, vector[0] * RIGHT) y_line = Line(x_line.get_end(), arrow.get_end()) x_line.highlight(X_COLOR) y_line.highlight(Y_COLOR) x_coord, y_coord = array.get_mob_matrix().flatten() self.play(Write(array, run_time=1)) self.dither() self.play( ApplyFunction( lambda x: self.position_x_coordinate(x, x_line, vector), x_coord)) self.play(ShowCreation(x_line)) self.play( ApplyFunction( lambda y: self.position_y_coordinate(y, y_line, vector), y_coord), FadeOut(array.get_brackets())) y_coord, brackets = self.get_mobjects_from_last_animation() self.play(ShowCreation(y_line)) self.play(ShowCreation(arrow)) self.dither() if clean_up: self.clear() self.add(*starting_mobjects)
def construct(self): curve = HilbertCurve(order = 6) curve.highlight(WHITE) colored_curve = curve.copy() colored_curve.thin_out(3) lion = ImageMobject("lion", invert = False) lion.replace(curve, stretch = True) sparce_lion = lion.copy() sparce_lion.thin_out(100) distance_matrix = cdist(colored_curve.points, sparce_lion.points) closest_point_indices = np.apply_along_axis( np.argmin, 1, distance_matrix ) colored_curve.rgbas = sparce_lion.rgbas[closest_point_indices] line = Line(5*LEFT, 5*RIGHT) Mobject.align_data(line, colored_curve) line.rgbas = colored_curve.rgbas self.add(lion) self.play(ShowCreation(curve, run_time = 3)) self.play( FadeOut(lion), Transform(curve, colored_curve), run_time = 3 ) self.wait() self.play(Transform(curve, line, run_time = 5)) self.wait()
def construct(self): grid = get_grid() grid.sort_points(np.linalg.norm) freq_line = get_freq_line() freq_line.sort_points(lambda p : p[0]) red, blue = Color(RED), Color(BLUE) freq_line.gradient_highlight(red, blue) colors = [ Color(rgb = interpolate( np.array(red.rgb), np.array(blue.rgb), alpha )) for alpha in np.arange(4)/3. ] string = Line(3*LEFT, 3*RIGHT, color = colors[1]) vibration = Vibrate(string) vibration_copy = vibration.copy() vibration_copy.mobject.stroke_width = 1 sub_vibrations = [ Vibrate( string.copy().shift((n-1)*UP).highlight(colors[n]), overtones = 1, spatial_period = 6./(n+1), temporal_period = 1./(n+1), amplitude = 0.5/(n+1) ) for n in range(4) ] words = TexMobject("&\\vdots \\\\ \\text{thousands }& \\text{of frequencies} \\\\ &\\vdots") words.to_edge(UP, buff = 0.1) self.add(grid) self.dither() self.play(DelayByOrder(ApplyMethod( grid.gradient_highlight, red, blue ))) self.play(Transform(grid, freq_line)) self.dither() self.play( ShimmerIn( words, rate_func = squish_rate_func(smooth, 0, 0.2) ), *sub_vibrations, run_time = 5 ) self.play( *[ TransformAnimations( sub_vib, vibration ) for sub_vib in sub_vibrations ]+[FadeOut(words)] ) self.clear() self.add(freq_line) self.play(vibration)
def construct(self): logo = MirekOlsakLogo(self.camera) series_title = TextMobject(self.series_str).to_edge(UP) self.add(series_title) chapter_title = TextMobject(self.chapter_str) chapter_title.scale(1.4) self.play(Write(chapter_title)) self.play(ShowCreation(logo)) self.dither(self.dither_time) self.play(FadeOut(VGroup(series_title, chapter_title, logo)))
def construct(self): val = 0.3 text = TextMobject([ "PHC", "$_n", "(", "%3.1f"%val, ")$", " has a ", "limit point ", "as $n \\to \\infty$" ]) func_parts = text.copy().split()[:5] Mobject(*func_parts).center().to_edge(UP) num_str, val_str = func_parts[1], func_parts[3] curve = UnitInterval() curve.sort_points(lambda p : p[0]) dot = Dot().shift(curve.number_to_point(val)) arrow = Arrow(val_str, dot, buff = 0.1) curve.add_numbers(0, 1) self.play(ShowCreation(curve)) self.play( ShimmerIn(val_str), ShowCreation(arrow), ShowCreation(dot) ) self.wait() self.play( FadeOut(arrow), *[ FadeIn(func_parts[i]) for i in 0, 1, 2, 4 ] ) for num in range(2,9): new_curve = HilbertCurve(order = num) new_curve.scale(0.8) new_dot = Dot(new_curve.points[int(val*new_curve.get_num_points())]) new_num_str = TexMobject(str(num)).replace(num_str) self.play( Transform(curve, new_curve), Transform(dot, new_dot), Transform(num_str, new_num_str) ) self.wait() text.to_edge(UP) text_parts = text.split() for index in 1, -1: text_parts[index].highlight() starters = Mobject(*func_parts + [ Point(mob.get_center(), stroke_width=1) for mob in text_parts[5:] ]) self.play(Transform(starters, text)) arrow = Arrow(text_parts[-2].get_bottom(), dot, buff = 0.1) self.play(ShowCreation(arrow)) self.wait()
def construct(self): mathy, bubble = get_mathy_and_bubble() squiggle_mouth = mathy.mouth.copy() squiggle_mouth.apply_function( lambda (x, y, z) : (x, y+0.02*np.sin(50*x), z) ) bubble.ingest_submobjects() bubble.write("Why not use a Hilbert curve \\textinterrobang ") words1 = bubble.content bubble.write("So, it's not one curve but an infinite family of curves \\dots") words2 = bubble.content bubble.write("Well, no, it \\emph{is} just one thing, but I need \\\\ \ to tell you about a certain infinite family first.") words3 = bubble.content description = TextMobject("Mathematician friend", size = "\\small") description.next_to(mathy, buff = 2) arrow = Arrow(description, mathy) self.add(mathy) self.play( ShowCreation(arrow), ShimmerIn(description) ) self.dither() point = Point(bubble.get_tip()) self.play( Transform(point, bubble), ) self.remove(point) self.add(bubble) self.play(ShimmerIn(words1)) self.dither() self.remove(description, arrow) self.play( Transform(mathy.mouth, squiggle_mouth), ApplyMethod(mathy.arm.wag, 0.2*RIGHT, LEFT), ) self.remove(words1) self.add(words2) self.dither(2) self.remove(words2) self.add(words3) self.dither(2) self.play( ApplyPointwiseFunction( lambda p : 15*p/np.linalg.norm(p), bubble ), ApplyMethod(mathy.shift, 5*(DOWN+LEFT)), FadeOut(words3), run_time = 3 )
def introduce_bubble(self, content, bubble_type, pi_creature, target_mode = None, added_anims = [], **bubble_kwargs): if all(map(lambda s : isinstance(s, str), content)): content = TextMobject(*content) elif len(content) == 1 and isinstance(content[0], Mobject): content = content[0] else: raise Exception("Invalid content type") anims = [] #Remove other bubbles for p in self.get_everyone(): if (p.bubble is not None) and (p is not pi_creature): anims += [ FadeOut(p.bubble), FadeOut(p.bubble.content) ] p.bubble = None anims.append(ApplyMethod(p.change_mode, "plain")) #Bring in new bubble anims += self.get_bubble_intro_animation( content, bubble_type, pi_creature, **bubble_kwargs ) #Add changing mode if not target_mode: if bubble_type is "speech": target_mode = "speaking" else: target_mode = "pondering" anims.append( ApplyMethod( pi_creature.change_mode, target_mode, ) ) self.play(*anims + added_anims) return pi_creature.bubble
def construct(self): morty = Mortimer() morty.next_to(ORIGIN, DOWN) n_patrons = len(self.specific_patrons) special_thanks = TextMobject("Special thanks") special_thanks.highlight(YELLOW) special_thanks.to_edge(UP) patreon_logo = PatreonLogo() patreon_logo.next_to(morty, UP, buff=MED_LARGE_BUFF) patrons = map(TextMobject, self.specific_patrons) patron_groups = [] index = 0 counter = 0 while index < len(patrons): next_index = index + self.patron_group_size group = VGroup(*patrons[index:next_index]) group.arrange_submobjects(DOWN, aligned_edge=LEFT) if counter % 2 == 0: group.to_edge(LEFT) else: group.to_edge(RIGHT) patron_groups.append(group) index = next_index counter += 1 self.play( morty.change_mode, "gracious", DrawBorderThenFill(patreon_logo), ) self.play(Write(special_thanks, run_time=1)) for i, group in enumerate(patron_groups): anims = [ FadeIn( group, run_time=2, submobject_mode="lagged_start", lag_factor=4, ), morty.look_at, group.get_top(), ] if i >= 2: anims.append(FadeOut(patron_groups[i - 2])) self.play(*anims) self.play(morty.look_at, group.get_bottom()) self.play(Blink(morty))
def construct(self): morty = Mortimer() morty.next_to(ORIGIN, DOWN) patreon_logo = PatreonLogo() patreon_logo.to_edge(UP) n_patrons = len(self.specific_patrons) patrons = map(TextMobject, self.specific_patrons) num_groups = float(len(patrons)) / self.max_patron_group_size proportion_range = np.linspace(0, 1, num_groups + 1) indices = (len(patrons)*proportion_range).astype('int') patron_groups = [ VGroup(*patrons[i:j]) for i, j in zip(indices, indices[1:]) ] for i, group in enumerate(patron_groups): left_group = VGroup(*group[:len(group)/2]) right_group = VGroup(*group[len(group)/2:]) for subgroup, vect in (left_group, LEFT), (right_group, RIGHT): subgroup.arrange_submobjects(DOWN, aligned_edge = LEFT) subgroup.scale(self.patron_scale_val) subgroup.to_edge(vect) last_group = None for i, group in enumerate(patron_groups): anims = [] if last_group is not None: self.play( FadeOut(last_group), morty.look, UP+LEFT ) else: anims += [ DrawBorderThenFill(patreon_logo), ] self.play( LaggedStart( FadeIn, group, run_time = 2, ), morty.change, "gracious", group.get_corner(UP+LEFT), *anims ) self.play(morty.look_at, group.get_corner(DOWN+LEFT)) self.play(morty.look_at, group.get_corner(UP+RIGHT)) self.play(morty.look_at, group.get_corner(DOWN+RIGHT)) self.play(Blink(morty)) last_group = group
def introduce_bubble(self, content, bubble_type, pi_creature, pi_creature_target_mode = None, added_anims = [], **bubble_kwargs): if all(map(lambda s : isinstance(s, str), content)): content = TextMobject(*content) elif len(content) == 1 and isinstance(content[0], TexMobject): content = content[0] else: raise Exception("Invalid content type") content_intro_anims = self.get_bubble_intro_animation( content, bubble_type, pi_creature, **bubble_kwargs ) if not pi_creature_target_mode: if bubble_type is "speech": pi_creature_target_mode = "speaking" else: pi_creature_target_mode = "pondering" for p in self.get_everyone(): if p.bubble and p is not pi_creature: added_anims += [ FadeOut(p.bubble), FadeOut(p.bubble.content) ] p.bubble = None added_anims.append(ApplyMethod(p.change_mode, "plain")) anims = added_anims + content_intro_anims + [ ApplyMethod( pi_creature.change_mode, pi_creature_target_mode, ), ] self.play(*anims) return pi_creature.bubble
def construct(self): morty = Mortimer() morty.next_to(ORIGIN, DOWN) n_patrons = len(self.specific_patrons) special_thanks = TextMobject("Special thanks") special_thanks.highlight(YELLOW) special_thanks.to_edge(UP) patreon_logo = PatreonLogo() patreon_logo.next_to(morty, UP, buff=MED_LARGE_BUFF) patrons = map(TextMobject, self.specific_patrons) num_groups = float(len(patrons)) / self.patron_group_size proportion_range = np.linspace(0, 1, num_groups + 1) indices = (len(patrons) * proportion_range).astype('int') patron_groups = [ VGroup(*patrons[i:j]) for i, j in zip(indices, indices[1:]) ] for i, group in enumerate(patron_groups): group.arrange_submobjects(DOWN, aligned_edge=LEFT) group.scale(self.patron_scale_val) group.to_edge(LEFT if i % 2 == 0 else RIGHT) self.play( morty.change_mode, "gracious", DrawBorderThenFill(patreon_logo), ) self.play(Write(special_thanks, run_time=1)) print len(patron_groups) for i, group in enumerate(patron_groups): anims = [ FadeIn( group, run_time=2, submobject_mode="lagged_start", lag_factor=4, ), morty.look_at, group.get_top(), ] if i >= 2: anims.append(FadeOut(patron_groups[i - 2])) self.play(*anims) self.play(morty.look_at, group.get_bottom()) self.play(Blink(morty))
def construct(self): big_grid_dim = 20. small_grid_dim = 6. big_grid = Grid(64, 64, height=big_grid_dim, width=big_grid_dim) big_grid.to_corner(UP + RIGHT, buff=2) small_grid = big_grid.copy() small_grid.scale(small_grid_dim / big_grid_dim) small_grid.center() pixel = MobjectFromRegion( region_from_polygon_vertices( *0.2 * np.array([RIGHT + DOWN, RIGHT + UP, LEFT + UP, LEFT + DOWN]))) pixel.set_color(WHITE) pixel_width = big_grid.width / big_grid.columns pixel.scale_to_fit_width(pixel_width) pixel.to_corner(UP + RIGHT, buff=2) pixel.shift(5 * pixel_width * (2 * LEFT + DOWN)) freq_line = get_freq_line() dot = Dot() dot.shift(freq_line.get_center() + 2 * RIGHT) string = Line(LEFT, RIGHT, color=GREEN) arrow = Arrow(dot, string.get_center()) vibration_config = { "overtones": 1, "spatial_period": 2, } vibration, loud_vibration, quiet_vibration = [ Vibrate(string.copy(), amplitude=a, **vibration_config) for a in [0.5, 1., 0.25] ] self.add(small_grid) self.dither() self.play(Transform(small_grid, big_grid)) self.play(FadeIn(pixel)) self.dither() self.play(FadeOut(small_grid), ShowCreation(freq_line)) self.remove(small_grid) self.play(Transform(pixel, dot), ) self.dither() self.play(ShowCreation(arrow)) self.play(loud_vibration) self.play(TransformAnimations(loud_vibration, quiet_vibration), ApplyMethod(dot.fade, 0.9)) self.clear() self.add(freq_line, dot, arrow) self.play(quiet_vibration)
def animate_product(self, left, right, result): l_matrix = left.get_mob_matrix() r_matrix = right.get_mob_matrix() result_matrix = result.get_mob_matrix() circle = Circle(radius=l_matrix[0][0].get_height(), color=GREEN) circles = VMobject(*[ entry.get_point_mobject() for entry in l_matrix[0][0], r_matrix[0][0] ]) (m, k), n = l_matrix.shape, r_matrix.shape[1] for mob in result_matrix.flatten(): mob.highlight(BLACK) lagging_anims = [] for a in range(m): for b in range(n): for c in range(k): l_matrix[a][c].highlight(YELLOW) r_matrix[c][b].highlight(YELLOW) for c in range(k): start_parts = VMobject(l_matrix[a][c].copy(), r_matrix[c][b].copy()) result_entry = result_matrix[a][b].split()[c] new_circles = VMobject(*[ circle.copy().shift(part.get_center()) for part in start_parts.split() ]) self.play(Transform(circles, new_circles)) self.play( Transform( start_parts, result_entry.copy().highlight(YELLOW), path_arc=-np.pi / 2, submobject_mode="all_at_once", ), *lagging_anims) result_entry.highlight(YELLOW) self.remove(start_parts) lagging_anims = [ ApplyMethod(result_entry.highlight, WHITE) ] for c in range(k): l_matrix[a][c].highlight(WHITE) r_matrix[c][b].highlight(WHITE) self.play(FadeOut(circles), *lagging_anims) self.wait()
def get_bubble_fade_anims(self, target_mode="plain"): return [ FadeOut(self.pi_creature.bubble), FadeOut(self.pi_creature.bubble.content), self.pi_creature.change_mode, target_mode ]