def side_project(self, morty): rect = PictureInPictureFrame() rect.next_to(morty, UP+LEFT) side_project = TextMobject("Side project") side_project.next_to(rect, UP) dollar_sign = TexMobject("\\$") cross = VGroup(*[ Line(vect, -vect, color = RED) for vect in UP+RIGHT, UP+LEFT ]) cross.scale_to_fit_height(dollar_sign.get_height()) no_money = VGroup(dollar_sign, cross) no_money.next_to(rect, DOWN) self.play( morty.change_mode, "raise_right_hand", morty.look_at, rect ) self.play( Write(side_project), ShowCreation(rect) ) self.dither() self.play(Blink(morty)) self.dither() self.play(Write(dollar_sign)) self.play(ShowCreation(cross)) self.screen_title = side_project self.cross = cross
def generate_points(self): self.cell_height = self.height / self.nrows self.cell_width = self.width / self.nrows self.bottom_left = (self.cell_width * self.nrows / 2.0)*LEFT + \ (self.cell_height * self.nrows / 2.0)*DOWN num_to_num_mob = {} self.coords_to_mobs = {} self.coords = [ (n, k) for n in range(self.nrows) for k in range(n+1) ] for n, k in self.coords: num = choose(n, k) center = self.coords_to_center(n, k) num_mob = TexMobject(str(num)) scale_factor = min( 1, self.portion_to_fill * self.cell_height / num_mob.get_height(), self.portion_to_fill * self.cell_width / num_mob.get_width(), ) num_mob.center().scale(scale_factor).shift(center) if n not in self.coords_to_mobs: self.coords_to_mobs[n] = {} self.coords_to_mobs[n][k] = num_mob self.add(*[ self.coords_to_mobs[n][k] for n, k in self.coords ]) return self
def side_project(self, morty): rect = PictureInPictureFrame() rect.next_to(morty, UP+LEFT) side_project = TextMobject("Side project") side_project.next_to(rect, UP) dollar_sign = TexMobject("\\$") cross = VGroup(*[ Line(vect, -vect, color = RED) for vect in UP+RIGHT, UP+LEFT ]) cross.scale_to_fit_height(dollar_sign.get_height()) no_money = VGroup(dollar_sign, cross) no_money.next_to(rect, DOWN) self.play( morty.change_mode, "raise_right_hand", morty.look_at, rect ) self.play( Write(side_project), ShowCreation(rect) ) self.wait() self.play(Blink(morty)) self.wait() self.play(Write(dollar_sign)) self.play(ShowCreation(cross)) self.screen_title = side_project self.cross = cross
def get_number_mobjects(self, *numbers): # TODO, handle decimals if len(numbers) == 0: numbers = self.default_numbers_to_display() result = [] for number in numbers: mob = TexMobject(str(int(number))) vert_scale = 2 * self.tick_size / mob.get_height() hori_scale = self.tick_frequency * self.unit_length_to_spatial_width / mob.get_width() mob.scale(min(vert_scale, hori_scale)) mob.shift(self.number_to_point(number)) mob.shift(self.get_vertical_number_offset()) result.append(mob) return result
def generate_n_choose_k_mobs(self): self.coords_to_n_choose_k = {} for n, k in self.coords: nck_mob = TexMobject(r"{%d \choose %d}" % (n, k)) scale_factor = min( 1, self.portion_to_fill * self.cell_height / nck_mob.get_height(), self.portion_to_fill * self.cell_width / nck_mob.get_width(), ) center = self.coords_to_mobs[n][k].get_center() nck_mob.center().scale(scale_factor).shift(center) if n not in self.coords_to_n_choose_k: self.coords_to_n_choose_k[n] = {} self.coords_to_n_choose_k[n][k] = nck_mob return self
def generate_n_choose_k_mobs(self): self.coords_to_n_choose_k = {} for n, k in self.coords: nck_mob = TexMobject(r"{%d \choose %d}"%(n, k)) scale_factor = min( 1, self.portion_to_fill * self.cell_height / nck_mob.get_height(), self.portion_to_fill * self.cell_width / nck_mob.get_width(), ) center = self.coords_to_mobs[n][k].get_center() nck_mob.center().scale(scale_factor).shift(center) if n not in self.coords_to_n_choose_k: self.coords_to_n_choose_k[n] = {} self.coords_to_n_choose_k[n][k] = nck_mob return self
def get_number_mobjects(self, *numbers): #TODO, handle decimals if len(numbers) == 0: numbers = self.default_numbers_to_display() result = [] for number in numbers: mob = TexMobject(str(int(number))) vert_scale = 2 * self.tick_size / mob.get_height() hori_scale = self.tick_frequency * self.unit_length_to_spatial_width / mob.get_width( ) mob.scale(min(vert_scale, hori_scale)) mob.shift(self.number_to_point(number)) mob.shift(self.get_vertical_number_offset()) result.append(mob) return result
def scale_vector(self, v, factor, v_label, v_name = "v", factor_tex = None): starting_mobjects = list(self.mobjects) if factor_tex is None: factor_tex = str(factor) scaled_vector = self.add_vector( factor*v.get_end(), animate = False ) self.remove(scaled_vector) label_tex = "%s\\vec{\\textbf{%s}}"%(factor_tex, v_name) label = self.label_vector( scaled_vector, label_tex, animate = False, add_to_vector = False ) self.remove(label) factor_mob = TexMobject(factor_tex) if factor_mob.get_height() > 1: factor_mob.scale_to_fit_height(0.9) if factor_mob.get_width() > 1: factor_mob.scale_to_fit_width(0.9) factor_mob.shift(1.5*RIGHT+2.5*UP) num_factor_parts = len(factor_mob.split()) factor_mob_parts_in_label = label.split()[:num_factor_parts] label_remainder_parts = label.split()[num_factor_parts:] factor_in_label = VMobject(*factor_mob_parts_in_label) label_remainder = VMobject(*label_remainder_parts) self.play(Write(factor_mob, run_time = 1)) self.dither() self.play( ApplyMethod(v.copy().highlight, DARK_GREY), ApplyMethod(v_label.copy().highlight, DARK_GREY), Transform(factor_mob, factor_in_label), Transform(v.copy(), scaled_vector), Transform(v_label.copy(), label_remainder), ) self.dither(2) self.clear() self.add(*starting_mobjects)
def scale_vector(self, v, factor, v_label, v_name = "v", factor_tex = None): starting_mobjects = list(self.mobjects) if factor_tex is None: factor_tex = str(factor) scaled_vector = self.add_vector( factor*v.get_end(), animate = False ) self.remove(scaled_vector) label_tex = "%s\\vec{\\textbf{%s}}"%(factor_tex, v_name) label = self.label_vector( scaled_vector, label_tex, animate = False, add_to_vector = False ) self.remove(label) factor_mob = TexMobject(factor_tex) if factor_mob.get_height() > 1: factor_mob.scale_to_fit_height(0.9) if factor_mob.get_width() > 1: factor_mob.scale_to_fit_width(0.9) factor_mob.shift(1.5*RIGHT+2.5*UP) num_factor_parts = len(factor_mob.split()) factor_mob_parts_in_label = label.split()[:num_factor_parts] label_remainder_parts = label.split()[num_factor_parts:] factor_in_label = VMobject(*factor_mob_parts_in_label) label_remainder = VMobject(*label_remainder_parts) self.play(Write(factor_mob, run_time = 1)) self.wait() self.play( ApplyMethod(v.copy().highlight, DARK_GREY), ApplyMethod(v_label.copy().highlight, DARK_GREY), Transform(factor_mob, factor_in_label), Transform(v.copy(), scaled_vector), Transform(v_label.copy(), label_remainder), ) self.wait(2) self.clear() self.add(*starting_mobjects)
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): 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)