def show_value_at_zero(self): arrow, x_equals_0 = ax0_group = self.get_arrow_x_equals_0_group() ax0_group.next_to( self.cosine_label, RIGHT, align_using_submobjects = True ) one = TexMobject("1") one.next_to(arrow, RIGHT) one.save_state() one.move_to(self.cosine_label) one.set_fill(opacity = 0) v_line = self.get_vertical_line_to_graph( 0, self.cosine_graph, line_class = DashedLine, color = YELLOW ) self.play(ShowCreation(v_line)) self.play( ShowCreation(arrow), Write(x_equals_0, run_time = 2) ) self.play(one.restore) self.dither() self.v_line = v_line self.equals_one_group = VGroup(arrow, x_equals_0, one)
def construct(self): l_m1, l_m2, eq, r_m2, r_m1 = TexMobject([ "M_1", "M_2", "=", "M_2", "M_1" ]).scale(1.5).split() VMobject(l_m1, r_m1).highlight(YELLOW) VMobject(l_m2, r_m2).highlight(PINK) q_marks = TextMobject("???") q_marks.highlight(TEAL) q_marks.next_to(eq, UP) neq = TexMobject("\\neq") neq.move_to(eq) self.play(*map(Write, [l_m1, l_m2, eq])) self.play( Transform(l_m1.copy(), r_m1), Transform(l_m2.copy(), r_m2), path_arc = -np.pi, run_time = 2 ) self.play(Write(q_marks)) self.dither() self.play(Transform( VMobject(eq, q_marks), VMobject(neq), submobject_mode = "lagged_start" )) self.dither()
def add_disks(self): self.disks = VGroup(*[ Rectangle( height = self.disk_height, width = width, fill_color = color, fill_opacity = 1, stroke_width = 0, ) for width, color in zip( np.linspace( self.disk_min_width, self.disk_max_width, self.num_disks ), color_gradient( self.disk_start_and_end_colors, self.num_disks ) ) ]) for number, disk in enumerate(self.disks): label = TexMobject(str(number)) label.highlight(BLACK) label.scale_to_fit_height(self.disk_height/2) label.move_to(disk) disk.add(label) disk.label = label self.reset_disks(run_time = 0) self.add(self.disks)
def add_polygons(self): a = self.i_hat.get_end()[0]*RIGHT b = self.j_hat.get_end()[0]*RIGHT c = self.i_hat.get_end()[1]*UP d = self.j_hat.get_end()[1]*UP shapes_colors_and_tex = [ (Polygon(ORIGIN, a, a+c), TEAL, "bd/2"), (Polygon(ORIGIN, d+b, d), TEAL, "\\dfrac{bd}{2}"), (Polygon(a+c, a+b+c, a+b+c+d), MAROON, "\\dfrac{ac}{2}"), (Polygon(b+d, a+b+c+d, b+c+d), MAROON, "ac/2"), (Polygon(a, a+b, a+b+c, a+c), PINK, "bc"), (Polygon(d, d+b, d+b+c, d+c), PINK, "bc"), ] everyone = VMobject() for shape, color, tex in shapes_colors_and_tex: shape.set_stroke(width = 0) shape.set_fill(color = color, opacity = 0.7) tex_mob = TexMobject(tex) tex_mob.scale(0.7) tex_mob.move_to(shape.get_center_of_mass()) everyone.add(shape, tex_mob) self.play(FadeIn( everyone, submobject_mode = "lagged_start", run_time = 1 ))
def show_derivative(self): func_tex, graph = self.func_tex, self.graph new_graph = FunctionGraph(lambda x: (x**2) / 3. - 1) new_graph.highlight(YELLOW) func_tex.generate_target() lp, rp = parens = TexMobject("()") parens.scale_to_fit_height(func_tex.get_height()) L, equals = TexMobject("L=") deriv = TexMobject("\\frac{d}{dx}") new_func = TexMobject("\\frac{1}{3}x^2 - 1") new_func.highlight(YELLOW) group = VGroup(L, lp, func_tex.target, rp, equals, new_func) group.arrange_submobjects() group.shift(2 * UP).to_edge(LEFT, buff=2 * MED_BUFF) rect = BackgroundRectangle(group) group.add_to_back(rect) deriv.move_to(L, aligned_edge=RIGHT) self.play(MoveToTarget(func_tex), *map(Write, [L, lp, rp, equals, new_func])) self.remove(func_tex) self.add(func_tex.target) self.dither() faded_graph = graph.copy().fade() self.add(faded_graph) self.play(Transform(graph, new_graph, run_time=2), Animation(group)) self.dither() self.play(Transform(L, deriv)) self.play(ShowSlopes(faded_graph)) self.dither()
def exchange_money(self): for from_name, to_name, num in self.payments: from_pi = getattr(self, from_name.lower()) to_pi = getattr(self, to_name.lower()) cash = TexMobject("\\$" * (num / 10)).highlight(GREEN) cash.scale_to_fit_height(0.5) cash.move_to(from_pi) self.play(cash.move_to, to_pi, to_pi.change_mode, "hooray") self.play(FadeOut(cash)) self.dither()
def construct(self): self.lock_in_faded_grid() self.add_unit_square(animate=False) self.remove(self.square) square = self.square v = Vector(self.v_coords, color=V_COLOR) w = Vector(self.w_coords, color=W_COLOR) v.label = self.get_vector_label(v, "v", "right", color=V_COLOR) w.label = self.get_vector_label(w, "w", "left", color=W_COLOR) new_v = v.copy().scale(3) new_v.label = self.get_vector_label(new_v, "3\\vec{\\textbf{v}}", "right", color=V_COLOR) for vect in v, w, new_v: vect.add(vect.label) transform = self.get_matrix_transformation( [self.v_coords, self.w_coords]) square.apply_function(transform) new_squares = Group( *[square.copy().shift(m * v.get_end()) for m in range(3)]) v_tex, w_tex = get_vect_tex("v", "w") cross_product = TexMobject(v_tex, "\\times", w_tex) rhs = TexMobject("=3(", v_tex, "\\times", w_tex, ")") three_v = TexMobject("(3", v_tex, ")") for tex_mob in cross_product, rhs, three_v: tex_mob.highlight_by_tex(v_tex, V_COLOR) tex_mob.highlight_by_tex(w_tex, W_COLOR) equation = Group(cross_product, rhs) equation.arrange_submobjects() equation.to_edge(UP) v_tex_mob = cross_product[0] three_v.move_to(v_tex_mob, aligned_edge=RIGHT) for tex_mob in cross_product, rhs: tex_mob.add_background_rectangle() self.add(cross_product) self.play(ShowCreation(v)) self.play(ShowCreation(w)) self.play(ShowCreation(square), *map(Animation, [v, w])) self.dither() self.play( Transform(v, new_v), Transform(v_tex_mob, three_v), ) self.dither() self.play(Transform(square, new_squares), *map(Animation, [v, w]), path_arc=-np.pi / 6) self.dither() self.play(Write(rhs)) self.dither()
def show_symbolic_sum(self, new_array, vector): new_mob = TexMobject([ "(%d)\\hat{\\imath}" % self.vector_coords[0], "+", "(%d)\\hat{\\jmath}" % self.vector_coords[1] ]) new_mob.move_to(new_array) new_mob.shift_onto_screen() i_hat, plus, j_hat = new_mob.split() i_hat.highlight(X_COLOR) j_hat.highlight(Y_COLOR) self.play(Transform(new_array, new_mob)) self.wait()
def celebrate(self): title = TextMobject("2 year Anniversary!") title.scale(1.5) title.to_edge(UP) first_video = Rectangle( height=2, width=2 * (16.0 / 9), stroke_color=WHITE, fill_color="#111111", fill_opacity=0.75, ) first_video.next_to(self.get_teacher(), UP + LEFT) first_video.shift(RIGHT) formula = TexMobject("e^{\\pi i} = -1") formula.move_to(first_video) first_video.add(formula) hats = self.get_party_hats() confetti_spirils = self.get_confetti_animations() self.play( Write(title, run_time=2), *[ ApplyMethod(pi.change_mode, "hooray") for pi in self.get_pi_creatures() ]) self.play( DrawBorderThenFill( hats, submobject_mode="lagged_start", rate_func=None, run_time=2, ), *confetti_spirils + [ Succession(Animation(pi, run_time=2), ApplyMethod(pi.look, UP + LEFT), ApplyMethod(pi.look, UP + RIGHT), Animation(pi), ApplyMethod(pi.look_at, first_video), rate_func=None) for pi in self.get_students() ] + [ Succession(Animation(self.get_teacher(), run_time=2), Blink(self.get_teacher()), Animation(self.get_teacher(), run_time=2), ApplyMethod(self.get_teacher().change_mode, "raise_right_hand"), rate_func=None), DrawBorderThenFill(first_video, run_time=10, rate_func=squish_rate_func( smooth, 0.5, 0.7)) ]) self.change_student_modes(*["confused"] * 3)
def show_symbolic_sum(self, new_array, vector): new_mob = TexMobject([ "(%d)\\hat{\\imath}"%self.vector_coords[0], "+", "(%d)\\hat{\\jmath}"%self.vector_coords[1] ]) new_mob.move_to(new_array) new_mob.shift_onto_screen() i_hat, plus, j_hat = new_mob.split() i_hat.highlight(X_COLOR) j_hat.highlight(Y_COLOR) self.play(Transform(new_array, new_mob)) self.dither()
def construct(self): hydrogen_atom = Mobject() title = TexMobject("Hydrogen Atom") point_A = (-2,2,0) point_B = (-2,-2,0) arrow = Arrow(ORIGIN+LEFT*0.9,ORIGIN+RIGHT*0.9) add_sign = TexMobject("+", stroke_width=0.7) orbit = Circle(radius=1.3).scale(0.85) proton = Dot(radius=0.4, color="GREY").scale(0.85) elec = Dot(radius=0.2, color="RED").scale(0.85) p_charge = TexMobject("+", stroke_width=0.5) e_charge = TexMobject("-",stroke_width=0.5) title.move_to(title.get_center()+UP*2) elec.move_to(orbit.points[0]) e_charge.move_to(elec.get_center()) p_charge.move_to(proton.get_center()) self.play(ShowCreation(title)) self.play(ShowCreation(orbit)) self.play(GrowFromCenter(proton), GrowFromCenter(p_charge)) self.play(GrowFromCenter(elec), GrowFromCenter(e_charge)) self.play(MoveAlongPath(elec, orbit),MaintainPositionRelativeTo(e_charge, elec), run_time=5,rate_func=None) hydrogen_atom.add(orbit,elec, proton, e_charge, p_charge) atom_copy = hydrogen_atom.copy() h1_text = TexMobject("H").move_to(point_A+LEFT*2) h2_text = TexMobject("H").move_to(point_B+LEFT*2) names = VGroup(h1_text, h2_text) self.play(ApplyMethod(atom_copy.shift, point_A),ApplyMethod(hydrogen_atom.shift, point_B),Transform(title, names)) add_sign.move_to(atom_copy.get_center()+DOWN*2) self.play(ShowCreation(add_sign),ShowCreation(arrow)) h1_atom = atom_copy.copy().move_to(arrow.get_end()+RIGHT*3.5) h2_atom = hydrogen_atom.copy().move_to(arrow.get_end()+RIGHT*1.5) self.remove(atom_copy, hydrogen_atom) h2_atom[1].move_to(h2_atom[0].points[2]) h2_atom[3].move_to(h2_atom[1].get_center()) h1_atom[1].move_to(h1_atom[0].points[14]) h1_atom[3].move_to(h1_atom[1].get_center()) h2_molecule = VGroup(h1_atom,h2_atom) two_atoms = VGroup(atom_copy,hydrogen_atom) #org.copy() molecule_name = TexMobject("H_{2}").move_to(h2_molecule.get_center()+DOWN*2.5) self.play(Transform(two_atoms, h2_molecule), FadeOut(arrow.add(add_sign))) self.add(h2_molecule) self.remove(title,two_atoms) self.play(Transform(names, molecule_name))
def write_second_derivative(self): ddf_over_dx_squared = TexMobject( "{d(df)", "\\over", "(dx)^2}" ) ddf_over_dx_squared.scale(0.8) ddf_over_dx_squared.move_to(self.ddf, RIGHT) ddf_over_dx_squared.highlight_by_tex("df", self.ddf.get_color()) parens = VGroup( ddf_over_dx_squared[0][1], ddf_over_dx_squared[0][4], ddf_over_dx_squared[2][0], ddf_over_dx_squared[2][3], ) right_shifter = ddf_over_dx_squared[0][0] left_shifter = ddf_over_dx_squared[2][4] exp_two = TexMobject("2") exp_two.highlight(self.ddf.get_color()) exp_two.scale(0.5) exp_two.move_to(right_shifter.get_corner(UP+RIGHT), LEFT) exp_two.shift(MED_SMALL_BUFF*RIGHT) pre_exp_two = VGroup(ddf_over_dx_squared[0][2]) self.play( Write(ddf_over_dx_squared.get_part_by_tex("over")), *[ ReplacementTransform( mob, ddf_over_dx_squared.get_part_by_tex(tex), path_arc = -np.pi/2, ) for mob, tex in (self.ddf, "df"), (self.dx_squared, "dx") ] ) self.wait(2) self.play(FadeOut(parens)) self.play( left_shifter.shift, 0.2*LEFT, right_shifter.shift, 0.2*RIGHT, ReplacementTransform(pre_exp_two, exp_two), ddf_over_dx_squared.get_part_by_tex("over").scale_in_place, 0.8 ) self.wait(2)
def write_second_derivative(self): ddf_over_dx_squared = TexMobject( "{d(df)", "\\over", "(dx)^2}" ) ddf_over_dx_squared.scale(0.8) ddf_over_dx_squared.move_to(self.ddf, RIGHT) ddf_over_dx_squared.highlight_by_tex("df", self.ddf.get_color()) parens = VGroup( ddf_over_dx_squared[0][1], ddf_over_dx_squared[0][4], ddf_over_dx_squared[2][0], ddf_over_dx_squared[2][3], ) right_shifter = ddf_over_dx_squared[0][0] left_shifter = ddf_over_dx_squared[2][4] exp_two = TexMobject("2") exp_two.highlight(self.ddf.get_color()) exp_two.scale(0.5) exp_two.move_to(right_shifter.get_corner(UP+RIGHT), LEFT) exp_two.shift(MED_SMALL_BUFF*RIGHT) pre_exp_two = VGroup(ddf_over_dx_squared[0][2]) self.play( Write(ddf_over_dx_squared.get_part_by_tex("over")), *[ ReplacementTransform( mob, ddf_over_dx_squared.get_part_by_tex(tex), path_arc = -np.pi/2, ) for mob, tex in (self.ddf, "df"), (self.dx_squared, "dx") ] ) self.dither(2) self.play(FadeOut(parens)) self.play( left_shifter.shift, 0.2*LEFT, right_shifter.shift, 0.2*RIGHT, ReplacementTransform(pre_exp_two, exp_two), ddf_over_dx_squared.get_part_by_tex("over").scale_in_place, 0.8 ) self.dither(2)
def count_from(self, start, scene): ori_foreground = scene.foreground_mobjects scene.foreground_mobjects = [] scene.add(self) for n in reversed(range(1,start+1)): white = self.copy() white.set_fill(opacity = 0) white.highlight(WHITE) number = TexMobject(str(n)) number.move_to(self) number.scale_to_fit_height(self.get_height()/2) scene.add(number) scene.play(Uncreate(white)) scene.remove(number) scene.remove(self) scene.foreground_mobjects = ori_foreground
def get_plus_one_anim(self, count): plus_one = TexMobject("+1") plus_one.highlight(YELLOW) plus_one.move_to(count) plus_one.next_to(count, DOWN) plus_one.generate_target() plus_one.target.move_to(count) plus_one.target.set_fill(opacity = 0) move = MoveToTarget(plus_one, remover = True) grow = GrowFromCenter(plus_one) return UpdateFromAlphaFunc( plus_one, lambda m, a : ( (grow if a < 0.5 else move).update(2*a%1) ), remover = True, rate_func = double_smooth, run_time = 2 )
def let_one_day_pass(self, run_time = 2): all_creatures = self.get_pi_creatures() on_screen_creatures = self.get_on_screen_pi_creatures() low_i = len(on_screen_creatures) high_i = min(2*low_i, len(all_creatures)) new_creatures = VGroup(*all_creatures[low_i:high_i]) to_children_anims = [] growing_anims = [] for old_pi, pi in zip(on_screen_creatures, new_creatures): pi.save_state() child = pi.copy() child.scale(0.25, about_point = child.get_bottom()) child.eyes.scale(1.5, about_point = child.eyes.get_bottom()) pi.move_to(old_pi) pi.set_fill(opacity = 0) index = list(new_creatures).index(pi) prop = float(index)/len(new_creatures) alpha = np.clip(len(new_creatures)/8.0, 0, 0.5) rate_func = squish_rate_func( smooth, alpha*prop, alpha*prop+(1-alpha) ) to_child_anim = Transform(pi, child, rate_func = rate_func) to_child_anim.update(1) growing_anim = ApplyMethod(pi.restore, rate_func = rate_func) to_child_anim.update(0) to_children_anims.append(to_child_anim) growing_anims.append(growing_anim) time = self.t_expression[-1] total_new_creatures = len(on_screen_creatures) + len(new_creatures) new_time = TexMobject(str(int(np.log2(total_new_creatures)))) new_time.move_to(time, LEFT) growing_anims.append(Transform(time, new_time)) self.play(*to_children_anims, run_time = run_time/2.0) self.play(*growing_anims, run_time = run_time/2.0)
def take_derivatives_of_monomial(self, term): """ Must be a group of pure TexMobjects, last part must be of the form x^n """ n = int(term[-1].get_tex_string()[-1]) curr_term = term for k in range(n, 0, -1): exponent = curr_term[-1][-1] exponent_copy = exponent.copy() front_num = TexMobject("%d \\cdot"%k) front_num.move_to(curr_term[0][0], DOWN+LEFT) new_monomial = TexMobject("x^%d"%(k-1)) new_monomial.replace(curr_term[-1]) Transform(curr_term[-1], new_monomial).update(1) curr_term.generate_target() curr_term.target.shift( (front_num.get_width()+SMALL_BUFF)*RIGHT ) curr_term[-1][-1].set_fill(opacity = 0) self.play( ApplyMethod( exponent_copy.replace, front_num[0], path_arc = np.pi, ), Write( front_num[1], rate_func = squish_rate_func(smooth, 0.5, 1) ), MoveToTarget(curr_term), run_time = 2 ) self.remove(exponent_copy) self.add(front_num) curr_term = VGroup(front_num, *curr_term) self.dither() self.play(FadeOut(curr_term[-1])) return VGroup(*curr_term[:-1])
def contrast_with_prior(self): prior = TexMobject("P(", "\\text{Sick}", ")", "= 0.1\\%") prior.highlight_by_tex("Sick", SICKLY_GREEN) prior.move_to(self.posterior, UP + RIGHT) self.revert_to_original_skipping_status() self.play( Write(prior, run_time=1), self.posterior.shift, DOWN, ) arrow = Arrow( prior.get_right(), self.posterior.get_right(), path_arc=-np.pi, ) times_90 = TexMobject("\\times 90") times_90.next_to(arrow, RIGHT) self.play(ShowCreation(arrow)) self.play(Write(times_90, run_time=1)) self.dither(2)
def let_one_day_pass(self, run_time=2): all_creatures = self.get_pi_creatures() on_screen_creatures = self.get_on_screen_pi_creatures() low_i = len(on_screen_creatures) high_i = min(2 * low_i, len(all_creatures)) new_creatures = VGroup(*all_creatures[low_i:high_i]) to_children_anims = [] growing_anims = [] for old_pi, pi in zip(on_screen_creatures, new_creatures): pi.save_state() child = pi.copy() child.scale(0.25, about_point=child.get_bottom()) child.eyes.scale(1.5, about_point=child.eyes.get_bottom()) pi.move_to(old_pi) pi.set_fill(opacity=0) index = list(new_creatures).index(pi) prop = float(index) / len(new_creatures) alpha = np.clip(len(new_creatures) / 8.0, 0, 0.5) rate_func = squish_rate_func(smooth, alpha * prop, alpha * prop + (1 - alpha)) to_child_anim = Transform(pi, child, rate_func=rate_func) to_child_anim.update(1) growing_anim = ApplyMethod(pi.restore, rate_func=rate_func) to_child_anim.update(0) to_children_anims.append(to_child_anim) growing_anims.append(growing_anim) time = self.t_expression[-1] total_new_creatures = len(on_screen_creatures) + len(new_creatures) new_time = TexMobject(str(int(np.log2(total_new_creatures)))) new_time.move_to(time, LEFT) growing_anims.append(Transform(time, new_time)) self.play(*to_children_anims, run_time=run_time / 2.0) self.play(*growing_anims, run_time=run_time / 2.0)
def construct(self): image = get_image("Leonhard_Euler_by_Handmann") image.scale_to_fit_height(4) image.to_edge(DOWN) image.shift(4 * LEFT) bubble = ThoughtBubble(height=4.5) bubble.next_to(image, RIGHT) bubble.to_edge(UP, buff=SMALL_BUFF) bubble.shift(0.8 * LEFT) bubble.set_fill(BLACK, 0.3) pi_vs_tau = TextMobject("Should $\\pi$ represent \\\\", "3.1415...", "or", "6.2831...", "?") pi_vs_tau.highlight_by_tex_to_color_map({ "3.14": GREEN, "6.28": RED, }) pi_vs_tau.move_to(bubble.get_bubble_center()) question = TexMobject( "\\frac{1}{1} + \\frac{1}{4} + \\frac{1}{9} + \\frac{1}{16} + \\cdots = ", "\\;???") question[0].gradient_highlight(BLUE_C, BLUE_B) question.move_to(bubble.get_bubble_center()) question.shift(2 * SMALL_BUFF * UP) cross = Cross(pi_vs_tau) cross.set_stroke(RED, 8) self.add(image) self.play(ShowCreation(bubble), Write(pi_vs_tau)) self.play(ShowCreation(cross)) self.wait() self.play( FadeOut(VGroup(pi_vs_tau, cross)), FadeIn(question), ) self.wait()
def show_digital_signatures(self): rect = SurroundingRectangle( VGroup(self.public_keys[0], self.private_key_rects[0], self.locks[0])) digital_signatures = VGroup() for i, signature in enumerate(self.signatures): bits = bin(hash(str(i)))[-8:] digital_signature = TexMobject(bits + "\\dots") digital_signature.scale(0.7) digital_signature.highlight(signature.get_color()) digital_signature.move_to(signature, DOWN) digital_signatures.add(digital_signature) arrows = VGroup(*[ Arrow(rect.get_corner(UP), sig.get_bottom(), tip_length=0.15, color=WHITE) for sig in digital_signatures ]) words = VGroup( *map(TextMobject, ["Different messages", "Completely different signatures"])) words.arrange_submobjects(DOWN, aligned_edge=LEFT) words.scale(1.3) words.next_to(self.documents, RIGHT) self.play(FadeIn(rect)) self.play(*map(ShowCreation, arrows)) self.play(Transform(self.signatures, digital_signatures)) self.play(*[ ApplyMethod(pi.change, "pondering", digital_signatures) for pi in self.pi_creatures ]) for word in words: self.play(FadeIn(word)) self.dither() self.play(FadeOut(words))
def construct(self): l_m1, l_m2, eq, r_m2, r_m1 = TexMobject( ["M_1", "M_2", "=", "M_2", "M_1"]).scale(1.5).split() VMobject(l_m1, r_m1).highlight(YELLOW) VMobject(l_m2, r_m2).highlight(PINK) q_marks = TextMobject("???") q_marks.highlight(TEAL) q_marks.next_to(eq, UP) neq = TexMobject("\\neq") neq.move_to(eq) self.play(*map(Write, [l_m1, l_m2, eq])) self.play(Transform(l_m1.copy(), r_m1), Transform(l_m2.copy(), r_m2), path_arc=-np.pi, run_time=2) self.play(Write(q_marks)) self.wait() self.play( Transform(VMobject(eq, q_marks), VMobject(neq), submobject_mode="lagged_start")) self.wait()
def show_ledger(self): network = self.get_network() ledger = self.get_ledger() payments = [ ("Alice", "Bob", 20), ("Bob", "Charlie", 40), ("Alice", "You", 50), ] self.play(*map(FadeIn, [network, ledger])) for payment in payments: new_line = self.add_payment_line_to_ledger(*payment) from_name, to_name, amount = payment from_pi = getattr(self, from_name.lower()) to_pi = getattr(self, to_name.lower()) cash = TexMobject("\\$" * (amount / 10)) cash.scale(0.5) cash.move_to(from_pi) cash.highlight(GREEN) self.play(cash.move_to, to_pi, to_pi.change_mode, "hooray") self.play(FadeOut(cash), Write(new_line, run_time=1)) self.dither()
def show_squaring(self): self.force_skipping() self.square_point() dot = self.example_dot old_label = self.example_label line = self.example_line square_dot = self.square_dot old_square_label = self.square_label square_line = self.square_line z_to_z_squared = self.z_to_z_squared arrow = self.z_to_z_squared_arrow result_length_label = self.result_length_label self.clear() self.add(self.plane, self.plane.coordinate_labels) self.revert_to_original_skipping_status() label = TexMobject("u+vi") label.move_to(old_label, LEFT) label.add_background_rectangle() square_label = TexMobject("(u+vi)^2") square_label.move_to(old_square_label, LEFT) square_label.add_background_rectangle() self.add(label, dot, line) self.play(ShowCreation(arrow), FadeIn(z_to_z_squared)) self.play(*[ ReplacementTransform( start.copy(), target, run_time=1.5, path_arc=np.pi / 2) for start, target in [ (dot, square_dot), (line, square_line), (label, square_label), ] ]) self.example_label = label self.square_label = square_label
def add_polygons(self): a = self.i_hat.get_end()[0] * RIGHT b = self.j_hat.get_end()[0] * RIGHT c = self.i_hat.get_end()[1] * UP d = self.j_hat.get_end()[1] * UP shapes_colors_and_tex = [ (Polygon(ORIGIN, a, a + c), MAROON, "ac/2"), (Polygon(ORIGIN, d + b, d, d), TEAL, "\\dfrac{bd}{2}"), (Polygon(a + c, a + b + c, a + b + c, a + b + c + d), TEAL, "\\dfrac{bd}{2}"), (Polygon(b + d, a + b + c + d, b + c + d), MAROON, "ac/2"), (Polygon(a, a + b, a + b + c, a + c), PINK, "bc"), (Polygon(d, d + b, d + b + c, d + c), PINK, "bc"), ] everyone = VMobject() for shape, color, tex in shapes_colors_and_tex: shape.set_stroke(width=0) shape.set_fill(color=color, opacity=0.7) tex_mob = TexMobject(tex) tex_mob.scale(0.7) tex_mob.move_to(shape.get_center_of_mass()) everyone.add(shape, tex_mob) self.play(FadeIn(everyone, submobject_mode="lagged_start", run_time=1))
def construct(self): base_str = self.base_str func_def = TexMobject("M(", "t", ")", "= ", "%s^" % base_str, "t") func_def.to_corner(UP + LEFT) self.add(func_def) ratio = TexMobject("{ {%s^" % base_str, "{t", "+", "dt}", "-", "%s^" % base_str, "t}", "\\over \\,", "dt}") ratio.shift(UP + LEFT) lhs = TexMobject("{dM", "\\over \\,", "dt}", "(", "t", ")", "=") lhs.next_to(ratio, LEFT) two_to_t_plus_dt = VGroup(*ratio[:4]) two_to_t = VGroup(*ratio[5:7]) two_to_t_two_to_dt = TexMobject("%s^" % base_str, "t", "%s^" % base_str, "{dt}") two_to_t_two_to_dt.move_to(two_to_t_plus_dt, DOWN + LEFT) exp_prop_brace = Brace(two_to_t_two_to_dt, UP) one = TexMobject("1") one.move_to(ratio[5], DOWN) lp, rp = parens = TexMobject("()") parens.stretch(1.3, 1) parens.scale_to_fit_height(ratio.get_height()) lp.next_to(ratio, LEFT, buff=0) rp.next_to(ratio, RIGHT, buff=0) extracted_two_to_t = TexMobject("%s^" % base_str, "t") extracted_two_to_t.next_to(lp, LEFT, buff=SMALL_BUFF) expressions = [ ratio, two_to_t_two_to_dt, extracted_two_to_t, lhs, func_def ] for expression in expressions: expression.highlight_by_tex("t", YELLOW) expression.highlight_by_tex("dt", GREEN) #Apply exponential property self.play(Write(ratio), Write(lhs), self.pi_creature.change_mode, "raise_right_hand") self.dither(2) self.play(two_to_t_plus_dt.next_to, exp_prop_brace, UP, self.pi_creature.change_mode, "pondering") self.play( ReplacementTransform( two_to_t_plus_dt.copy(), two_to_t_two_to_dt, run_time=2, path_arc=np.pi, ), FadeIn(exp_prop_brace)) self.dither(2) #Talk about exponential property add_exp_rect, mult_rect = rects = [ Rectangle( stroke_color=BLUE, stroke_width=2, ).replace(mob).scale_in_place(1.1) for mob in [VGroup(*two_to_t_plus_dt[1:]), two_to_t_two_to_dt] ] words = VGroup( *[TextMobject(s, " ideas") for s in "Additive", "Multiplicative"]) words[0].move_to(words[1], LEFT) words.highlight(BLUE) words.next_to(two_to_t_plus_dt, RIGHT, buff=1.5 * LARGE_BUFF) arrows = VGroup(*[ Arrow(word.get_left(), rect, color=words.get_color()) for word, rect in zip(words, rects) ]) self.play(ShowCreation(add_exp_rect)) self.dither() self.play(ReplacementTransform(add_exp_rect.copy(), mult_rect)) self.dither() self.change_mode("happy") self.play(Write(words[0], run_time=2)) self.play(ShowCreation(arrows[0])) self.dither() self.play( Transform(*words), Transform(*arrows), ) self.dither(2) self.play(*map(FadeOut, [ words[0], arrows[0], add_exp_rect, mult_rect, two_to_t_plus_dt, exp_prop_brace, ])) #Factor out 2^t self.play(*[ FadeIn(mob, run_time=2, rate_func=squish_rate_func(smooth, 0.5, 1)) for mob in one, lp, rp ] + [ ReplacementTransform( mob, extracted_two_to_t, path_arc=np.pi / 2, run_time=2, ) for mob in two_to_t, VGroup(*two_to_t_two_to_dt[:2]) ] + [lhs.next_to, extracted_two_to_t, LEFT]) self.change_mode("pondering") shifter = VGroup(ratio[4], one, *two_to_t_two_to_dt[2:]) stretcher = VGroup(lp, ratio[7], rp) self.play(shifter.next_to, ratio[7], UP, stretcher.stretch_in_place, 0.9, 0) self.dither(2) #Ask about dt -> 0 brace = Brace(VGroup(extracted_two_to_t, ratio), DOWN) alt_brace = Brace(parens, DOWN) dt_to_zero = TexMobject("dt", "\\to 0") dt_to_zero.highlight_by_tex("dt", GREEN) dt_to_zero.next_to(brace, DOWN) self.play(GrowFromCenter(brace)) self.play(Write(dt_to_zero)) self.dither(2) #Who cares randy = Randolph() randy.scale(0.7) randy.to_edge(DOWN) self.play( FadeIn(randy), self.pi_creature.change_mode, "plain", ) self.play( PiCreatureSays( randy, "Who cares?", bubble_kwargs={"direction": LEFT}, target_mode="angry", )) self.dither(2) self.play(RemovePiCreatureBubble(randy), FadeOut(randy), self.pi_creature.change_mode, "hooray", self.pi_creature.look_at, parens) self.play(Transform(brace, alt_brace), dt_to_zero.next_to, alt_brace, DOWN) self.dither() #Highlight separation rects = [ Rectangle( stroke_color=color, stroke_width=2, ).replace(mob, stretch=True).scale_in_place(1.1) for mob, color in [ (VGroup(parens, dt_to_zero), GREEN), (extracted_two_to_t, YELLOW), ] ] self.play(ShowCreation(rects[0])) self.dither(2) self.play(ReplacementTransform(rects[0].copy(), rects[1])) self.change_mode("happy") self.dither() self.play(*map(FadeOut, rects)) #Plug in specific values static_constant = self.try_specific_dt_values() constant = static_constant.copy() #Replace with actual constant limit_term = VGroup(brace, dt_to_zero, ratio[4], one, rects[0], *ratio[7:] + two_to_t_two_to_dt[2:]) self.play(FadeIn(rects[0])) self.play(limit_term.to_corner, DOWN + LEFT) self.play(lp.stretch, 0.5, 1, lp.stretch, 0.8, 0, lp.next_to, extracted_two_to_t[0], RIGHT, rp.stretch, 0.5, 1, rp.stretch, 0.8, 0, rp.next_to, lp, RIGHT, SMALL_BUFF, rp.shift, constant.get_width() * RIGHT, constant.next_to, extracted_two_to_t[0], RIGHT, MED_LARGE_BUFF) self.dither() self.change_mode("confused") self.dither() #Indicate distinction between dt group and t group again for mob in limit_term, extracted_two_to_t: self.play(FocusOn(mob)) self.play(Indicate(mob)) self.dither() #hold_final_value derivative = VGroup(lhs, extracted_two_to_t, parens, constant) func_def_rhs = VGroup(*func_def[-2:]).copy() func_lp, func_rp = func_parens = TexMobject("()") func_parens.set_fill(opacity=0) func_lp.next_to(func_def_rhs[0], LEFT, buff=0) func_rp.next_to(func_lp, RIGHT, buff=func_def_rhs.get_width()) func_def_rhs.add(func_parens) M = lhs[0][1] self.play( FadeOut(M), func_def_rhs.move_to, M, LEFT, func_def_rhs.set_fill, None, 1, ) lhs[0].submobjects[1] = func_def_rhs self.dither() self.play(derivative.next_to, self.pi_creature, UP, derivative.to_edge, RIGHT, self.pi_creature.change_mode, "raise_right_hand") self.dither(2) for mob in extracted_two_to_t, constant: self.play(Indicate(mob)) self.dither() self.dither(2)
def construct(self): base_str = self.base_str func_def = TexMobject("M(", "t", ")", "= ", "%s^"%base_str, "t") func_def.to_corner(UP+LEFT) self.add(func_def) ratio = TexMobject( "{ {%s^"%base_str, "{t", "+", "dt}", "-", "%s^"%base_str, "t}", "\\over \\,", "dt}" ) ratio.shift(UP+LEFT) lhs = TexMobject("{dM", "\\over \\,", "dt}", "(", "t", ")", "=") lhs.next_to(ratio, LEFT) two_to_t_plus_dt = VGroup(*ratio[:4]) two_to_t = VGroup(*ratio[5:7]) two_to_t_two_to_dt = TexMobject( "%s^"%base_str, "t", "%s^"%base_str, "{dt}" ) two_to_t_two_to_dt.move_to(two_to_t_plus_dt, DOWN+LEFT) exp_prop_brace = Brace(two_to_t_two_to_dt, UP) one = TexMobject("1") one.move_to(ratio[5], DOWN) lp, rp = parens = TexMobject("()") parens.stretch(1.3, 1) parens.scale_to_fit_height(ratio.get_height()) lp.next_to(ratio, LEFT, buff = 0) rp.next_to(ratio, RIGHT, buff = 0) extracted_two_to_t = TexMobject("%s^"%base_str, "t") extracted_two_to_t.next_to(lp, LEFT, buff = SMALL_BUFF) expressions = [ ratio, two_to_t_two_to_dt, extracted_two_to_t, lhs, func_def ] for expression in expressions: expression.highlight_by_tex("t", YELLOW) expression.highlight_by_tex("dt", GREEN) #Apply exponential property self.play( Write(ratio), Write(lhs), self.pi_creature.change_mode, "raise_right_hand" ) self.dither(2) self.play( two_to_t_plus_dt.next_to, exp_prop_brace, UP, self.pi_creature.change_mode, "pondering" ) self.play( ReplacementTransform( two_to_t_plus_dt.copy(), two_to_t_two_to_dt, run_time = 2, path_arc = np.pi, ), FadeIn(exp_prop_brace) ) self.dither(2) #Talk about exponential property add_exp_rect, mult_rect = rects = [ Rectangle( stroke_color = BLUE, stroke_width = 2, ).replace(mob).scale_in_place(1.1) for mob in [ VGroup(*two_to_t_plus_dt[1:]), two_to_t_two_to_dt ] ] words = VGroup(*[ TextMobject(s, " ideas") for s in "Additive", "Multiplicative" ]) words[0].move_to(words[1], LEFT) words.highlight(BLUE) words.next_to(two_to_t_plus_dt, RIGHT, buff = 1.5*LARGE_BUFF) arrows = VGroup(*[ Arrow(word.get_left(), rect, color = words.get_color()) for word, rect in zip(words, rects) ]) self.play(ShowCreation(add_exp_rect)) self.dither() self.play(ReplacementTransform( add_exp_rect.copy(), mult_rect )) self.dither() self.change_mode("happy") self.play(Write(words[0], run_time = 2)) self.play(ShowCreation(arrows[0])) self.dither() self.play( Transform(*words), Transform(*arrows), ) self.dither(2) self.play(*map(FadeOut, [ words[0], arrows[0], add_exp_rect, mult_rect, two_to_t_plus_dt, exp_prop_brace, ])) #Factor out 2^t self.play(*[ FadeIn( mob, run_time = 2, rate_func = squish_rate_func(smooth, 0.5, 1) ) for mob in one, lp, rp ] + [ ReplacementTransform( mob, extracted_two_to_t, path_arc = np.pi/2, run_time = 2, ) for mob in two_to_t, VGroup(*two_to_t_two_to_dt[:2]) ] + [ lhs.next_to, extracted_two_to_t, LEFT ]) self.change_mode("pondering") shifter = VGroup(ratio[4], one, *two_to_t_two_to_dt[2:]) stretcher = VGroup(lp, ratio[7], rp) self.play( shifter.next_to, ratio[7], UP, stretcher.stretch_in_place, 0.9, 0 ) self.dither(2) #Ask about dt -> 0 brace = Brace(VGroup(extracted_two_to_t, ratio), DOWN) alt_brace = Brace(parens, DOWN) dt_to_zero = TexMobject("dt", "\\to 0") dt_to_zero.highlight_by_tex("dt", GREEN) dt_to_zero.next_to(brace, DOWN) self.play(GrowFromCenter(brace)) self.play(Write(dt_to_zero)) self.dither(2) #Who cares randy = Randolph() randy.scale(0.7) randy.to_edge(DOWN) self.play( FadeIn(randy), self.pi_creature.change_mode, "plain", ) self.play(PiCreatureSays( randy, "Who cares?", bubble_kwargs = {"direction" : LEFT}, target_mode = "angry", )) self.dither(2) self.play( RemovePiCreatureBubble(randy), FadeOut(randy), self.pi_creature.change_mode, "hooray", self.pi_creature.look_at, parens ) self.play( Transform(brace, alt_brace), dt_to_zero.next_to, alt_brace, DOWN ) self.dither() #Highlight separation rects = [ Rectangle( stroke_color = color, stroke_width = 2, ).replace(mob, stretch = True).scale_in_place(1.1) for mob, color in [ (VGroup(parens, dt_to_zero), GREEN), (extracted_two_to_t, YELLOW), ] ] self.play(ShowCreation(rects[0])) self.dither(2) self.play(ReplacementTransform(rects[0].copy(), rects[1])) self.change_mode("happy") self.dither() self.play(*map(FadeOut, rects)) #Plug in specific values static_constant = self.try_specific_dt_values() constant = static_constant.copy() #Replace with actual constant limit_term = VGroup( brace, dt_to_zero, ratio[4], one, rects[0], *ratio[7:]+two_to_t_two_to_dt[2:] ) self.play(FadeIn(rects[0])) self.play(limit_term.to_corner, DOWN+LEFT) self.play( lp.stretch, 0.5, 1, lp.stretch, 0.8, 0, lp.next_to, extracted_two_to_t[0], RIGHT, rp.stretch, 0.5, 1, rp.stretch, 0.8, 0, rp.next_to, lp, RIGHT, SMALL_BUFF, rp.shift, constant.get_width()*RIGHT, constant.next_to, extracted_two_to_t[0], RIGHT, MED_LARGE_BUFF ) self.dither() self.change_mode("confused") self.dither() #Indicate distinction between dt group and t group again for mob in limit_term, extracted_two_to_t: self.play(FocusOn(mob)) self.play(Indicate(mob)) self.dither() #hold_final_value derivative = VGroup( lhs, extracted_two_to_t, parens, constant ) func_def_rhs = VGroup(*func_def[-2:]).copy() func_lp, func_rp = func_parens = TexMobject("()") func_parens.set_fill(opacity = 0) func_lp.next_to(func_def_rhs[0], LEFT, buff = 0) func_rp.next_to(func_lp, RIGHT, buff = func_def_rhs.get_width()) func_def_rhs.add(func_parens) M = lhs[0][1] self.play( FadeOut(M), func_def_rhs.move_to, M, LEFT, func_def_rhs.set_fill, None, 1, ) lhs[0].submobjects[1] = func_def_rhs self.dither() self.play( derivative.next_to, self.pi_creature, UP, derivative.to_edge, RIGHT, self.pi_creature.change_mode, "raise_right_hand" ) self.dither(2) for mob in extracted_two_to_t, constant: self.play(Indicate(mob)) self.dither() self.dither(2)
def show_lighthouses_on_number_line(self): self.number_line = NumberLine( x_min=0, color=WHITE, number_at_center=1.6, stroke_width=1, numbers_with_elongated_ticks=range(1, 5), numbers_to_show=range(1, 5), unit_size=2, tick_frequency=0.2, line_to_number_buff=LARGE_BUFF, label_direction=UP, ) self.number_line.label_direction = DOWN self.number_line_labels = self.number_line.get_number_mobjects() self.add(self.number_line, self.number_line_labels) self.wait() origin_point = self.number_line.number_to_point(0) self.default_pi_creature_class = Randolph randy = self.get_primary_pi_creature() randy.scale(0.5) randy.flip() right_pupil = randy.pupils[1] randy.next_to(origin_point, LEFT, buff=0, submobject_to_align=right_pupil) light_indicator = LightIndicator( radius=INDICATOR_RADIUS, opacity_for_unit_intensity=OPACITY_FOR_UNIT_INTENSITY, color=LIGHT_COLOR) light_indicator.reading.scale(0.8) bubble = ThoughtBubble(direction=RIGHT, width=2.5, height=3.5) bubble.next_to(randy, LEFT + UP) bubble.add_content(light_indicator) self.play(randy.change, "wave_2", ShowCreation(bubble), FadeIn(light_indicator)) light_sources = [] euler_sum_above = TexMobject("1", "+", "{1\over 4}", "+", "{1\over 9}", "+", "{1\over 16}", "+", "{1\over 25}", "+", "{1\over 36}") for (i, term) in zip(range(len(euler_sum_above)), euler_sum_above): #horizontal alignment with tick marks term.next_to(self.number_line.number_to_point(0.5 * i + 1), UP, buff=2) # vertical alignment with light indicator old_y = term.get_center()[1] new_y = light_indicator.get_center()[1] term.shift([0, new_y - old_y, 0]) for i in range(1, NUM_CONES + 1): light_source = LightSource( opacity_function=inverse_quadratic(1, 2, 1), num_levels=NUM_LEVELS, radius=12.0, ) point = self.number_line.number_to_point(i) light_source.move_source_to(point) light_sources.append(light_source) for ls in light_sources: self.add_foreground_mobject(ls.lighthouse) light_indicator.set_intensity(0) intensities = np.cumsum( np.array([1. / n**2 for n in range(1, NUM_CONES + 1)])) opacities = intensities * light_indicator.opacity_for_unit_intensity self.remove_foreground_mobjects(light_indicator) # slowly switch on visible light cones and increment indicator for (i, light_source) in zip(range(NUM_VISIBLE_CONES), light_sources[:NUM_VISIBLE_CONES]): indicator_start_time = 0.4 * ( i + 1 ) * SWITCH_ON_RUN_TIME / light_source.radius * self.number_line.unit_size indicator_stop_time = indicator_start_time + INDICATOR_UPDATE_TIME indicator_rate_func = squish_rate_func(smooth, indicator_start_time, indicator_stop_time) self.play( SwitchOn(light_source.ambient_light), FadeIn(euler_sum_above[2 * i], run_time=SWITCH_ON_RUN_TIME, rate_func=indicator_rate_func), FadeIn(euler_sum_above[2 * i - 1], run_time=SWITCH_ON_RUN_TIME, rate_func=indicator_rate_func), # this last line *technically* fades in the last term, but it is off-screen ChangeDecimalToValue(light_indicator.reading, intensities[i], rate_func=indicator_rate_func, run_time=SWITCH_ON_RUN_TIME), ApplyMethod(light_indicator.foreground.set_fill, None, opacities[i])) if i == 0: # move a copy out of the thought bubble for comparison light_indicator_copy = light_indicator.copy() old_y = light_indicator_copy.get_center()[1] new_y = self.number_line.get_center()[1] self.play(light_indicator_copy.shift, [0, new_y - old_y, 0]) # quickly switch on off-screen light cones and increment indicator for (i, light_source) in zip(range(NUM_VISIBLE_CONES, NUM_CONES), light_sources[NUM_VISIBLE_CONES:NUM_CONES]): indicator_start_time = 0.5 * ( i + 1 ) * FAST_SWITCH_ON_RUN_TIME / light_source.radius * self.number_line.unit_size indicator_stop_time = indicator_start_time + FAST_INDICATOR_UPDATE_TIME indicator_rate_func = squish_rate_func( #smooth, 0.8, 0.9) smooth, indicator_start_time, indicator_stop_time) self.play( SwitchOn(light_source.ambient_light, run_time=FAST_SWITCH_ON_RUN_TIME), ChangeDecimalToValue(light_indicator.reading, intensities[i - 1], rate_func=indicator_rate_func, run_time=FAST_SWITCH_ON_RUN_TIME), ApplyMethod(light_indicator.foreground.set_fill, None, opacities[i - 1])) # show limit value in light indicator and an equals sign limit_reading = TexMobject("{\pi^2 \over 6}") limit_reading.move_to(light_indicator.reading) equals_sign = TexMobject("=") equals_sign.next_to(randy, UP) old_y = equals_sign.get_center()[1] new_y = euler_sum_above.get_center()[1] equals_sign.shift([0, new_y - old_y, 0]) self.play( FadeOut(light_indicator.reading), FadeIn(limit_reading), FadeIn(equals_sign), ) self.wait()
class IntroScene(PiCreatureScene): CONFIG = { "rect_height": 0.2, "duration": 1.0, "eq_spacing": 3 * MED_LARGE_BUFF } def construct(self): randy = self.get_primary_pi_creature() randy.scale(0.7).to_corner(DOWN + RIGHT) self.build_up_euler_sum() self.build_up_sum_on_number_line() self.show_pi_answer() self.other_pi_formulas() self.refocus_on_euler_sum() def build_up_euler_sum(self): self.euler_sum = TexMobject("1", "+", "{1 \\over 4}", "+", "{1 \\over 9}", "+", "{1 \\over 16}", "+", "{1 \\over 25}", "+", "\\cdots", "=", arg_separator=" \\, ") self.euler_sum.to_edge(UP) self.euler_sum.shift(2 * LEFT) terms = [1. / n**2 for n in range(1, 6)] partial_results_values = np.cumsum(terms) self.play(FadeIn(self.euler_sum[0], run_time=self.duration)) equals_sign = self.euler_sum.get_part_by_tex("=") self.partial_sum_decimal = DecimalNumber(partial_results_values[1], num_decimal_points=2) self.partial_sum_decimal.next_to(equals_sign, RIGHT) for i in range(4): FadeIn(self.partial_sum_decimal, run_time=self.duration) if i == 0: self.play( FadeIn(self.euler_sum[1], run_time=self.duration), FadeIn(self.euler_sum[2], run_time=self.duration), FadeIn(equals_sign, run_time=self.duration), FadeIn(self.partial_sum_decimal, run_time=self.duration)) else: self.play( FadeIn(self.euler_sum[2 * i + 1], run_time=self.duration), FadeIn(self.euler_sum[2 * i + 2], run_time=self.duration), ChangeDecimalToValue(self.partial_sum_decimal, partial_results_values[i + 1], run_time=self.duration, num_decimal_points=6, show_ellipsis=True, position_update_func=lambda m: m. next_to(equals_sign, RIGHT))) self.wait() self.q_marks = TextMobject("???").highlight(LIGHT_COLOR) self.q_marks.move_to(self.partial_sum_decimal) self.play( FadeIn(self.euler_sum[-3], run_time=self.duration), # + FadeIn(self.euler_sum[-2], run_time=self.duration), # ... ReplacementTransform(self.partial_sum_decimal, self.q_marks)) def build_up_sum_on_number_line(self): self.number_line = NumberLine( x_min=0, color=WHITE, number_at_center=1, stroke_width=1, numbers_with_elongated_ticks=[0, 1, 2, 3], numbers_to_show=np.arange(0, 5), unit_size=5, tick_frequency=0.2, line_to_number_buff=MED_LARGE_BUFF) self.number_line_labels = self.number_line.get_number_mobjects() self.add(self.number_line, self.number_line_labels) self.wait() # create slabs for series terms max_n = 10 terms = [0] + [1. / (n**2) for n in range(1, max_n + 1)] series_terms = np.cumsum(terms) lines = VGroup() self.rects = VGroup() slab_colors = [YELLOW, BLUE] * (max_n / 2) for t1, t2, color in zip(series_terms, series_terms[1:], slab_colors): line = Line(*map(self.number_line.number_to_point, [t1, t2])) rect = Rectangle() rect.stroke_width = 0 rect.fill_opacity = 1 rect.highlight(color) rect.stretch_to_fit_height(self.rect_height, ) rect.stretch_to_fit_width(line.get_width()) rect.move_to(line) self.rects.add(rect) lines.add(line) #self.rects.radial_gradient_highlight(ORIGIN, 5, YELLOW, BLUE) for i in range(5): self.play( GrowFromPoint(self.rects[i], self.euler_sum[2 * i].get_center(), run_time=self.duration)) for i in range(5, max_n): self.play( GrowFromPoint(self.rects[i], self.euler_sum[10].get_center(), run_time=self.duration)) def show_pi_answer(self): self.pi_answer = TexMobject("{\\pi^2 \\over 6}").highlight(YELLOW) self.pi_answer.move_to(self.partial_sum_decimal) self.pi_answer.next_to(self.euler_sum[-1], RIGHT, submobject_to_align=self.pi_answer[-2]) self.play(ReplacementTransform(self.q_marks, self.pi_answer)) def other_pi_formulas(self): self.play(FadeOut(self.rects), FadeOut(self.number_line_labels), FadeOut(self.number_line)) self.leibniz_sum = TexMobject( "1-{1\\over 3}+{1\\over 5}-{1\\over 7}+{1\\over 9}-\\cdots", "=", "{\\pi \\over 4}") self.wallis_product = TexMobject( "{2\\over 1} \\cdot {2\\over 3} \\cdot {4\\over 3} \\cdot {4\\over 5}" + "\\cdot {6\\over 5} \\cdot {6\\over 7} \\cdots", "=", "{\\pi \\over 2}") self.leibniz_sum.next_to( self.euler_sum.get_part_by_tex("="), DOWN, buff=self.eq_spacing, submobject_to_align=self.leibniz_sum.get_part_by_tex("=")) self.wallis_product.next_to( self.leibniz_sum.get_part_by_tex("="), DOWN, buff=self.eq_spacing, submobject_to_align=self.wallis_product.get_part_by_tex("=")) self.play(Write(self.leibniz_sum)) self.play(Write(self.wallis_product)) def refocus_on_euler_sum(self): self.euler_sum.add(self.pi_answer) self.play( FadeOut(self.leibniz_sum), FadeOut(self.wallis_product), ApplyMethod(self.euler_sum.shift, ORIGIN + 2 * UP - self.euler_sum.get_center())) # focus on pi squared pi_squared = self.euler_sum.get_part_by_tex("\\pi")[-3] self.play(ScaleInPlace(pi_squared, 2, rate_func=wiggle)) # Morty thinks of a circle q_circle = Circle(stroke_color=YELLOW, fill_color=YELLOW, fill_opacity=0.5, radius=0.4, stroke_width=10.0) q_mark = TexMobject("?") q_mark.next_to(q_circle) thought = Group(q_circle, q_mark) q_mark.scale_to_fit_height(0.8 * q_circle.get_height()) self.pi_creature_thinks(thought, target_mode="confused", bubble_kwargs={ "height": 2, "width": 3 }) self.wait()
def construct(self): MAX_OPACITY = 0.4 INDICATOR_RADIUS = 0.6 OPACITY_FOR_UNIT_INTENSITY = 0.5 A = np.array([5., -3., 0.]) B = np.array([-5., 3., 0.]) C = np.array([-5., -3., 0.]) morty = self.get_primary_pi_creature() morty.scale(0.3).flip() right_pupil = morty.pupils[1] morty.next_to(C, LEFT, buff=0, submobject_to_align=right_pupil) horizontal = VMobject(stroke_width=1) horizontal.set_points_as_corners([C, A]) vertical = VMobject(stroke_width=1) vertical.set_points_as_corners([C, B]) self.play(ShowCreation(horizontal), ShowCreation(vertical)) indicator = LightIndicator( color=LIGHT_COLOR, radius=INDICATOR_RADIUS, opacity_for_unit_intensity=OPACITY_FOR_UNIT_INTENSITY, show_reading=True, precision=2) indicator.next_to(morty, LEFT) self.play(Write(indicator)) ls1 = LightSource(radius=20, num_levels=50) ls2 = ls1.deepcopy() #print "===" #print ls1.get_source_point() ls1.move_source_to(A) #print ls1.get_source_point() #print "===" #print ls2.get_source_point() ls2.move_source_to(B) #print ls2.get_source_point() self.play(FadeIn(ls1.lighthouse), FadeIn(ls2.lighthouse), SwitchOn(ls1.ambient_light), SwitchOn(ls2.ambient_light)) distance1 = np.linalg.norm(C - ls1.get_source_point()) intensity = ls1.ambient_light.opacity_function( distance1) / indicator.opacity_for_unit_intensity distance2 = np.linalg.norm(C - ls2.get_source_point()) intensity += ls2.ambient_light.opacity_function( distance2) / indicator.opacity_for_unit_intensity self.play(UpdateLightIndicator(indicator, intensity)) self.wait() ls3 = ls1.deepcopy() ls3.move_to(np.array([6, 3.5, 0])) new_indicator = indicator.copy() new_indicator.light_source = ls3 new_indicator.measurement_point = C self.add(new_indicator) self.play(indicator.shift, 2 * UP) #intensity = intensity_for_light_source(ls3) self.play( SwitchOff(ls1.ambient_light), #FadeOut(ls1.lighthouse), SwitchOff(ls2.ambient_light), #FadeOut(ls2.lighthouse), UpdateLightIndicator(new_indicator, 0.0)) # create a *continual* animation for the replacement source updater = ContinualLightIndicatorUpdate(new_indicator) self.add(updater) self.play( SwitchOn(ls3.ambient_light), FadeIn(ls3.lighthouse), ) self.wait() # move the light source around # TODO: moving along a path arc location = np.array([-3, -2., 0.]) self.play(ls3.move_source_to, location) location = np.array([6., 1., 0.]) self.play(ls3.move_source_to, location) location = np.array([5., 2., 0.]) self.play(ls3.move_source_to, location) closer_location = interpolate(location, C, 0.5) self.play(ls3.move_source_to, closer_location) self.play(ls3.move_source_to, location) # maybe move in a circle around C using a loop? # find the coords of the altitude point H # as the solution of a certain LSE xA = A[0] yA = A[1] xB = B[0] yB = B[1] xC = C[0] yC = C[1] matrix = np.array([[yA - yB, xB - xA], [xA - xB, yA - yB]]) # sic vector = np.array([xB * yA - xA * yB, xC * (xA - xB) + yC * (yA - yB)]) H2 = np.linalg.solve(matrix, vector) H = np.append(H2, 0.) self.play(ls3.move_source_to, H) # draw lines to complete the geometric picture # and label the lengths line_a = VMobject() line_a.set_points_as_corners([B, C]) line_b = VMobject() line_b.set_points_as_corners([A, C]) line_c = VMobject() line_c.set_points_as_corners([A, B]) line_h = VMobject() line_h.set_points_as_corners([H, C]) label_a = TexMobject("a") label_a.next_to(line_a, LEFT, buff=0.5) label_b = TexMobject("b") label_b.next_to(line_b, DOWN, buff=0.5) label_h = TexMobject("h") label_h.next_to(line_h.get_center(), RIGHT, buff=0.5) self.play(ShowCreation(line_a), Write(label_a)) self.play(ShowCreation(line_b), Write(label_b)) self.play(ShowCreation(line_c), ) self.play(ShowCreation(line_h), Write(label_h)) # state the IPT theorem_location = np.array([3., 2., 0.]) theorem = TexMobject("{1\over a^2} + {1\over b^2} = {1\over h^2}") theorem_name = TextMobject("Inverse Pythagorean Theorem") buffer = 1.2 theorem_box = Rectangle(width=buffer * theorem.get_width(), height=buffer * theorem.get_height()) theorem.move_to(theorem_location) theorem_box.move_to(theorem_location) theorem_name.next_to(theorem_box, UP) self.play(Write(theorem), ) self.play( ShowCreation(theorem_box), Write(theorem_name), )
def construct(self): tri1 = VGroup( Line(ORIGIN, 2*RIGHT, color = BLUE), Line(2*RIGHT, 3*UP, color = YELLOW), Line(3*UP, ORIGIN, color = MAROON_B), ) tri1.shift(2.5*(DOWN+LEFT)) tri2, tri3, tri4 = copies = [ tri1.copy().rotate(-i*np.pi/2) for i in range(1, 4) ] a = TexMobject("a").next_to(tri1[0], DOWN, buff = MED_BUFF) b = TexMobject("b").next_to(tri1[2], LEFT, buff = MED_BUFF) c = TexMobject("c").next_to(tri1[1].get_center(), UP+RIGHT) c_square = Polygon(*[ tri[1].get_end() for tri in [tri1] + copies ]) c_square.set_stroke(width = 0) c_square.set_fill(color = YELLOW, opacity = 0.5) c_square_tex = TexMobject("c^2") big_square = Polygon(*[ tri[0].get_start() for tri in [tri1] + copies ]) big_square.highlight(WHITE) a_square = Square(side_length = 2) a_square.shift(1.5*(LEFT+UP)) a_square.set_stroke(width = 0) a_square.set_fill(color = BLUE, opacity = 0.5) a_square_tex = TexMobject("a^2") a_square_tex.move_to(a_square) b_square = Square(side_length = 3) b_square.move_to( a_square.get_corner(DOWN+RIGHT), aligned_edge = UP+LEFT ) b_square.set_stroke(width = 0) b_square.set_fill(color = MAROON_B, opacity = 0.5) b_square_tex = TexMobject("b^2") b_square_tex.move_to(b_square) self.play(ShowCreation(tri1, run_time = 2)) self.play(*map(Write, [a, b, c])) self.dither() self.play( FadeIn(c_square), Animation(c) ) self.play(Transform(c, c_square_tex)) self.dither(2) mover = tri1.copy() for copy in copies: self.play(Transform( mover, copy, path_arc = -np.pi/2 )) self.add(copy) self.remove(mover) self.add(big_square, *[tri1]+copies) self.dither(2) self.play(*map(FadeOut, [a, b, c, c_square])) self.play( tri3.shift, tri1.get_corner(UP+LEFT) -\ tri3.get_corner(UP+LEFT) ) self.play(tri2.shift, 2*RIGHT) self.play(tri4.shift, 3*UP) self.dither() self.play(FadeIn(a_square)) self.play(FadeIn(b_square)) self.play(Write(a_square_tex)) self.play(Write(b_square_tex)) self.dither(2)
def introduce_graph(self, graph, origin): h_line, v_line = [ Line(origin, origin, color=color, stroke_width=2) for color in MAROON_B, YELLOW ] def h_update(h_line, proportion=1): end = graph.point_from_proportion(proportion) t_axis_point = end[0] * RIGHT + origin[1] * UP h_line.put_start_and_end_on(t_axis_point, end) def v_update(v_line, proportion=1): end = graph.point_from_proportion(proportion) d_axis_point = origin[0] * RIGHT + end[1] * UP v_line.put_start_and_end_on(d_axis_point, end) car = Car() car.rotate(np.pi / 2) car.move_to(origin) self.add(car) self.play( ShowCreation( graph, rate_func=None, ), MoveCar( car, self.coords_to_point(0, 100), ), UpdateFromFunc(h_line, h_update), UpdateFromFunc(v_line, v_update), run_time=10, ) self.dither() self.play(*map(FadeOut, [h_line, v_line, car])) #Show example vertical distance h_update(h_line, 0.6) t_dot = Dot(h_line.get_start(), color=h_line.get_color()) t_dot.save_state() t_dot.move_to(self.x_axis_label_mob) t_dot.set_fill(opacity=0) dashed_h = DashedLine(*h_line.get_start_and_end()) dashed_h.highlight(h_line.get_color()) brace = Brace(dashed_h, RIGHT) brace_text = brace.get_text("Distance traveled") self.play(t_dot.restore) self.dither() self.play(ShowCreation(dashed_h)) self.play(GrowFromCenter(brace), Write(brace_text)) self.dither(2) self.play(*map(FadeOut, [t_dot, dashed_h, brace, brace_text])) #Name graph s_of_t = TexMobject("s(t)") s_of_t.next_to(graph.point_from_proportion(1), DOWN + RIGHT, buff=SMALL_BUFF) s = s_of_t[0] d = TexMobject("d") d.move_to(s, DOWN) d.highlight(YELLOW) self.play(Write(s_of_t)) self.dither() s.save_state() self.play(Transform(s, d)) self.dither() self.play(s.restore)
def relate_growth_rate_to_pop_size(self): false_deriv = TexMobject("{d(2^t) ", "\\over dt}", "= 2^t") difference_eq = TexMobject("{ {2^{t+1} - 2^t} \\over", "1}", "= 2^t") real_deriv = TexMobject("{ {2^{t+dt} - 2^t} \\over", "dt}", "= \\, ???") VGroup( false_deriv[0][3], false_deriv[2][-1], difference_eq[0][1], difference_eq[0][-2], difference_eq[2][-1], difference_eq[2][-1], real_deriv[0][1], real_deriv[0][-2], ).highlight(YELLOW) VGroup( difference_eq[0][3], difference_eq[1][-1], real_deriv[0][3], real_deriv[0][4], real_deriv[1][-2], real_deriv[1][-1], ).highlight(GREEN) expressions = [false_deriv, difference_eq, real_deriv] text_arg_list = [ ( "Tempting", "...", ), ("Rate of change", "\\\\ over one full day"), ("Rate of change", "\\\\ in a small time"), ] for expression, text_args in zip(expressions, text_arg_list): expression.next_to( self.function, DOWN, buff=LARGE_BUFF, aligned_edge=LEFT, ) expression.brace = Brace(expression, DOWN) expression.brace_text = expression.brace.get_text(*text_args) time = self.t_expression[-1] new_time = TexMobject("3") new_time.move_to(time, LEFT) fading_creatures = VGroup(*self.get_on_screen_pi_creatures()[8:]) self.play(*map( FadeIn, [false_deriv, false_deriv.brace, false_deriv.brace_text])) self.dither() self.play(Transform(time, new_time), FadeOut(fading_creatures)) self.dither() for x in range(3): self.let_one_day_pass(run_time=2) self.dither(2) for expression in difference_eq, real_deriv: expression.brace_text[1].highlight(GREEN) self.play( Transform(false_deriv, expression), Transform(false_deriv.brace, expression.brace), Transform(false_deriv.brace_text, expression.brace_text), ) self.dither(3) self.reset() for x in range(self.get_num_days()): self.let_one_day_pass() self.dither() rect = Rectangle(color=YELLOW) rect.replace(real_deriv) rect.stretch_to_fit_width(rect.get_width() + MED_SMALL_BUFF) rect.stretch_to_fit_height(rect.get_height() + MED_SMALL_BUFF) self.play(*map(FadeOut, [false_deriv.brace, false_deriv.brace_text])) self.play(ShowCreation(rect)) self.play(*[ ApplyFunction( lambda pi: pi.change_mode("pondering").look_at(real_deriv), pi, run_time=2, rate_func=squish_rate_func(smooth, a, a + 0.5)) for pi in self.get_pi_creatures() for a in [0.5 * random.random()] ]) self.dither(3)
def relate_growth_rate_to_pop_size(self): false_deriv = TexMobject( "{d(2^t) ", "\\over dt}", "= 2^t" ) difference_eq = TexMobject( "{ {2^{t+1} - 2^t} \\over", "1}", "= 2^t" ) real_deriv = TexMobject( "{ {2^{t+dt} - 2^t} \\over", "dt}", "= \\, ???" ) VGroup( false_deriv[0][3], false_deriv[2][-1], difference_eq[0][1], difference_eq[0][-2], difference_eq[2][-1], difference_eq[2][-1], real_deriv[0][1], real_deriv[0][-2], ).highlight(YELLOW) VGroup( difference_eq[0][3], difference_eq[1][-1], real_deriv[0][3], real_deriv[0][4], real_deriv[1][-2], real_deriv[1][-1], ).highlight(GREEN) expressions = [false_deriv, difference_eq, real_deriv] text_arg_list = [ ("Tempting", "...",), ("Rate of change", "\\\\ over one full day"), ("Rate of change", "\\\\ in a small time"), ] for expression, text_args in zip(expressions, text_arg_list): expression.next_to( self.function, DOWN, buff = LARGE_BUFF, aligned_edge = LEFT, ) expression.brace = Brace(expression, DOWN) expression.brace_text = expression.brace.get_text(*text_args) time = self.t_expression[-1] new_time = TexMobject("3") new_time.move_to(time, LEFT) fading_creatures = VGroup(*self.get_on_screen_pi_creatures()[8:]) self.play(*map(FadeIn, [ false_deriv, false_deriv.brace, false_deriv.brace_text ])) self.dither() self.play( Transform(time, new_time), FadeOut(fading_creatures) ) self.dither() for x in range(3): self.let_one_day_pass(run_time = 2) self.dither(2) for expression in difference_eq, real_deriv: expression.brace_text[1].highlight(GREEN) self.play( Transform(false_deriv, expression), Transform(false_deriv.brace, expression.brace), Transform(false_deriv.brace_text, expression.brace_text), ) self.dither(3) self.reset() for x in range(self.get_num_days()): self.let_one_day_pass() self.dither() rect = Rectangle(color = YELLOW) rect.replace(real_deriv) rect.stretch_to_fit_width(rect.get_width()+MED_SMALL_BUFF) rect.stretch_to_fit_height(rect.get_height()+MED_SMALL_BUFF) self.play(*map(FadeOut, [ false_deriv.brace, false_deriv.brace_text ])) self.play(ShowCreation(rect)) self.play(*[ ApplyFunction( lambda pi : pi.change_mode("pondering").look_at(real_deriv), pi, run_time = 2, rate_func = squish_rate_func(smooth, a, a+0.5) ) for pi in self.get_pi_creatures() for a in [0.5*random.random()] ]) self.dither(3)
def square_algebraically(self): #Crazy hacky. To anyone looking at this, for God's #sake, don't mimic this. rect = Rectangle(height=3.5, width=7, stroke_color=WHITE, stroke_width=2, fill_color=BLACK, fill_opacity=0.8) rect.to_corner(UP + RIGHT, buff=0) number = self.number_label[1].copy() top_line = TexMobject("(3+2i)", "(3+2i)") for part in top_line: for i, color in zip([1, 3], [BLUE, YELLOW]): part[i].highlight(color) second_line = TexMobject( "\\big( 3^2 + (2i)^2 \\big) + " + \ "\\big(3 \\cdot 2 + 2 \\cdot 3 \\big)i" ) for i in 1, 12, 18: second_line[i].highlight(BLUE) for i in 5, 14, 16: second_line[i].highlight(YELLOW) second_line.scale(0.9) final_line = TexMobject("5 + 12i") for i in 0, 2, 3: final_line[i].highlight(GREEN) lines = VGroup(top_line, second_line, final_line) lines.arrange_submobjects(DOWN, buff=MED_LARGE_BUFF) lines.next_to(rect.get_top(), DOWN) minus = TexMobject("-").scale(0.9) minus.move_to(second_line[3]) self.play(FadeIn(rect), Transform(VGroup(number), top_line), run_time=2) self.dither() index_alignment_lists = [ [(0, 0, 0), (0, 1, 1), (1, 1, 2), (1, 5, 9)], [(0, 2, 3), (1, 3, 4), (0, 3, 5), (0, 4, 6), (1, 4, 7), (1, 3, 8)], [ (0, 2, 10), (0, 0, 11), (0, 1, 12), (1, 3, 13), (1, 3, 14), (1, 5, 19), (0, 4, 20), (1, 4, 20), ], [ (0, 2, 15), (0, 3, 16), (1, 1, 17), (1, 1, 18), ], ] for index_alignment in index_alignment_lists[:2]: self.play(*[ ReplacementTransform( top_line[i][j].copy(), second_line[k], run_time=1.5) for i, j, k in index_alignment ]) self.dither() self.play( Transform(second_line[3], minus), FadeOut(VGroup(*[second_line[i] for i in 4, 6, 7])), second_line[5].shift, 0.35 * RIGHT, ) self.play(VGroup(*second_line[:4]).shift, 0.55 * RIGHT) self.dither() for index_alignment in index_alignment_lists[2:]: self.play(*[ ReplacementTransform( top_line[i][j].copy(), second_line[k], run_time=1.5) for i, j, k in index_alignment ]) self.dither() self.play(FadeIn(final_line)) self.dither() self.final_line = final_line
def construct(self): scale_factor = 0.7 sick = "\\text{sick}" positive = "\\text{positive}" formula = TexMobject("P(", sick, "\\,|\\,", positive, ")", "=", "{\\quad P(", sick, "\\text{ and }", positive, ") \\quad", "\\over", "P(", positive, ")}", "=", "{1/1{,}000", "\\over", "1/1{,}000", "+", "(999/1{,}000)(0.01)}") formula.scale(scale_factor) formula.next_to(self.pi_creatures, UP, LARGE_BUFF) formula.shift_onto_screen(buff=MED_LARGE_BUFF) equals_group = formula.get_parts_by_tex("=") equals_indices = [ formula.index_of_part(equals) for equals in equals_group ] lhs = VGroup(*formula[:equals_indices[0]]) initial_formula = VGroup(*formula[:equals_indices[1]]) initial_formula.save_state() initial_formula.shift(3 * RIGHT) over = formula.get_part_by_tex("\\over") num_start_index = equals_indices[0] + 1 num_end_index = formula.index_of_part(over) numerator = VGroup(*formula[num_start_index:num_end_index]) numerator_rect = SurroundingRectangle(numerator) alt_numerator = TexMobject("P(", sick, ")", "P(", positive, "\\,|\\,", sick, ")") alt_numerator.scale(scale_factor) alt_numerator.move_to(numerator) number_fraction = VGroup(*formula[equals_indices[-1]:]) rhs = TexMobject("\\approx 0.09") rhs.scale(scale_factor) rhs.move_to(equals_group[-1], LEFT) rhs.highlight(YELLOW) for mob in formula, alt_numerator: mob.highlight_by_tex(sick, SICKLY_GREEN) mob.highlight_by_tex(positive, YELLOW) #Ask question self.student_says("What does the \\\\ formula look like here?") self.play(self.teacher.change, "happy") self.dither() self.play( Write(lhs), RemovePiCreatureBubble( self.students[1], target_mode="pondering", ), self.teacher.change, "raise_right_hand", self.students[0].change, "pondering", self.students[2].change, "pondering", ) self.dither() #Show initial formula lhs_copy = lhs.copy() self.play( LaggedStart(FadeIn, initial_formula, lag_ratio=0.7), Animation(lhs_copy, remover=True), ) self.dither(2) self.play(ShowCreation(numerator_rect)) self.play(FadeOut(numerator_rect)) self.dither() self.play(Transform(numerator, alt_numerator)) initial_formula.add(*numerator) formula.add(*numerator) self.dither(3) #Show number_fraction self.play(initial_formula.move_to, initial_formula.saved_state, FadeIn(VGroup(*number_fraction[:3]))) self.dither(2) self.play( LaggedStart(FadeIn, VGroup(*number_fraction[3:]), run_time=3, lag_ratio=0.7)) self.dither(2) #Show rhs self.play(formula.shift, UP) self.play(Write(rhs)) self.change_student_modes(*["happy"] * 3) self.look_at(rhs) self.dither(2)
def construct(self): title = TextMobject("Putnam Competition") title.to_edge(UP, buff = MED_SMALL_BUFF) title.highlight(BLUE) six_hours = TextMobject("6", "hours") three_hours = TextMobject("3", "hours") for mob in six_hours, three_hours: mob.next_to(title, DOWN, MED_LARGE_BUFF) # mob.highlight(BLUE) three_hours.shift(SPACE_WIDTH*LEFT/2) three_hours_copy = three_hours.copy() three_hours_copy.shift(SPACE_WIDTH*RIGHT) question_groups = VGroup(*[ VGroup(*[ TextMobject("%s%d)"%(c, i)) for i in range(1, 7) ]).arrange_submobjects(DOWN, buff = MED_LARGE_BUFF) for c in "A", "B" ]).arrange_submobjects(RIGHT, buff = SPACE_WIDTH - MED_SMALL_BUFF) question_groups.to_edge(LEFT) question_groups.to_edge(DOWN, MED_LARGE_BUFF) flat_questions = VGroup(*it.chain(*question_groups)) rects = VGroup() for questions in question_groups: rect = SurroundingRectangle(questions, buff = MED_SMALL_BUFF) rect.set_stroke(WHITE, 2) rect.stretch_to_fit_width(SPACE_WIDTH - 1) rect.move_to(questions.get_left() + MED_SMALL_BUFF*LEFT, LEFT) rects.add(rect) out_of_tens = VGroup() for question in flat_questions: out_of_ten = TexMobject("/10") out_of_ten.highlight(GREEN) out_of_ten.move_to(question) dist = rects[0].get_width() - 1.2 out_of_ten.shift(dist*RIGHT) out_of_tens.add(out_of_ten) out_of_120 = TexMobject("/120") out_of_120.next_to(title, RIGHT, LARGE_BUFF) out_of_120.highlight(GREEN) out_of_120.generate_target() out_of_120.target.to_edge(RIGHT, LARGE_BUFF) median = TexMobject("2") median.next_to(out_of_120.target, LEFT, SMALL_BUFF) median.highlight(RED) median.align_to(out_of_120[-1]) median_words = TextMobject("Typical median $\\rightarrow$") median_words.next_to(median, LEFT) difficulty_strings = [ "Pretty hard", "Hard", "Harder", "Very hard", "Ughhh", "Can I go home?" ] colors = color_gradient([YELLOW, RED], len(difficulty_strings)) difficulties = VGroup() for i, s, color in zip(it.count(), difficulty_strings, colors): for question_group in question_groups: question = question_group[i] text = TextMobject("\\dots %s \\dots"%s) text.scale(0.7) text.next_to(question, RIGHT) text.highlight(color) difficulties.add(text) if self.dont_animate: test = VGroup() test.rect = rects[0] test.questions = question_groups[0] test.out_of_tens = VGroup(*out_of_tens[:6]) test.difficulties = VGroup(*difficulties[::2]) test.digest_mobject_attrs() self.test = test return self.add(title) self.play(Write(six_hours)) self.play(LaggedStart( GrowFromCenter, flat_questions, run_time = 3, )) self.play( ReplacementTransform(six_hours, three_hours), ReplacementTransform(six_hours.copy(), three_hours_copy), *map(ShowCreation, rects) ) self.dither() self.play(LaggedStart( DrawBorderThenFill, out_of_tens, run_time = 3, stroke_color = YELLOW )) self.dither() self.play(ReplacementTransform( out_of_tens.copy(), VGroup(out_of_120), submobject_mode = "lagged_start", run_time = 2, )) self.dither() self.play( title.next_to, median_words.copy(), LEFT, LARGE_BUFF, MoveToTarget(out_of_120), Write(median_words) ) self.play(Write(median)) self.play(Write(difficulties, run_time = 3)) self.dither()
def construct(self): tri1 = VGroup( Line(ORIGIN, 2 * RIGHT, color=BLUE), Line(2 * RIGHT, 3 * UP, color=YELLOW), Line(3 * UP, ORIGIN, color=MAROON_B), ) tri1.shift(2.5 * (DOWN + LEFT)) tri2, tri3, tri4 = copies = [ tri1.copy().rotate(-i * np.pi / 2) for i in range(1, 4) ] a = TexMobject("a").next_to(tri1[0], DOWN, buff=MED_BUFF) b = TexMobject("b").next_to(tri1[2], LEFT, buff=MED_BUFF) c = TexMobject("c").next_to(tri1[1].get_center(), UP + RIGHT) c_square = Polygon(*[tri[1].get_end() for tri in [tri1] + copies]) c_square.set_stroke(width=0) c_square.set_fill(color=YELLOW, opacity=0.5) c_square_tex = TexMobject("c^2") big_square = Polygon(*[tri[0].get_start() for tri in [tri1] + copies]) big_square.highlight(WHITE) a_square = Square(side_length=2) a_square.shift(1.5 * (LEFT + UP)) a_square.set_stroke(width=0) a_square.set_fill(color=BLUE, opacity=0.5) a_square_tex = TexMobject("a^2") a_square_tex.move_to(a_square) b_square = Square(side_length=3) b_square.move_to(a_square.get_corner(DOWN + RIGHT), aligned_edge=UP + LEFT) b_square.set_stroke(width=0) b_square.set_fill(color=MAROON_B, opacity=0.5) b_square_tex = TexMobject("b^2") b_square_tex.move_to(b_square) self.play(ShowCreation(tri1, run_time=2)) self.play(*map(Write, [a, b, c])) self.dither() self.play(FadeIn(c_square), Animation(c)) self.play(Transform(c, c_square_tex)) self.dither(2) mover = tri1.copy() for copy in copies: self.play(Transform(mover, copy, path_arc=-np.pi / 2)) self.add(copy) self.remove(mover) self.add(big_square, *[tri1] + copies) self.dither(2) self.play(*map(FadeOut, [a, b, c, c_square])) self.play( tri3.shift, tri1.get_corner(UP+LEFT) -\ tri3.get_corner(UP+LEFT) ) self.play(tri2.shift, 2 * RIGHT) self.play(tri4.shift, 3 * UP) self.dither() self.play(FadeIn(a_square)) self.play(FadeIn(b_square)) self.play(Write(a_square_tex)) self.play(Write(b_square_tex)) self.dither(2)