mirror of
https://github.com/3b1b/manim.git
synced 2025-04-13 09:47:07 +00:00
898 lines
27 KiB
Python
898 lines
27 KiB
Python
from manimlib.imports import *
|
|
|
|
|
|
class TrigRepresentationsScene(Scene):
|
|
CONFIG = {
|
|
"unit_length" : 1.5,
|
|
"arc_radius" : 0.5,
|
|
"axes_color" : WHITE,
|
|
"circle_color" : RED,
|
|
"theta_color" : YELLOW,
|
|
"theta_height" : 0.3,
|
|
"theta_value" : np.pi/5,
|
|
"x_line_colors" : MAROON_B,
|
|
"y_line_colors" : BLUE,
|
|
}
|
|
def setup(self):
|
|
self.init_axes()
|
|
self.init_circle()
|
|
self.init_theta_group()
|
|
|
|
def init_axes(self):
|
|
self.axes = Axes(
|
|
unit_size = self.unit_length,
|
|
)
|
|
self.axes.set_color(self.axes_color)
|
|
self.add(self.axes)
|
|
|
|
def init_circle(self):
|
|
self.circle = Circle(
|
|
radius = self.unit_length,
|
|
color = self.circle_color
|
|
)
|
|
self.add(self.circle)
|
|
|
|
def init_theta_group(self):
|
|
self.theta_group = self.get_theta_group()
|
|
self.add(self.theta_group)
|
|
|
|
def add_trig_lines(self, *funcs, **kwargs):
|
|
lines = VGroup(*[
|
|
self.get_trig_line(func, **kwargs)
|
|
for func in funcs
|
|
])
|
|
self.add(*lines)
|
|
|
|
def get_theta_group(self):
|
|
arc = Arc(
|
|
self.theta_value,
|
|
radius = self.arc_radius,
|
|
color = self.theta_color,
|
|
)
|
|
theta = TexMobject("\\theta")
|
|
theta.shift(1.5*arc.point_from_proportion(0.5))
|
|
theta.set_color(self.theta_color)
|
|
theta.set_height(self.theta_height)
|
|
line = Line(ORIGIN, self.get_circle_point())
|
|
dot = Dot(line.get_end(), radius = 0.05)
|
|
return VGroup(line, arc, theta, dot)
|
|
|
|
def get_circle_point(self):
|
|
return rotate_vector(self.unit_length*RIGHT, self.theta_value)
|
|
|
|
def get_trig_line(self, func_name = "sin", color = None):
|
|
assert(func_name in ["sin", "tan", "sec", "cos", "cot", "csc"])
|
|
is_co = func_name in ["cos", "cot", "csc"]
|
|
if color is None:
|
|
if is_co:
|
|
color = self.y_line_colors
|
|
else:
|
|
color = self.x_line_colors
|
|
|
|
#Establish start point
|
|
if func_name in ["sin", "cos", "tan", "cot"]:
|
|
start_point = self.get_circle_point()
|
|
else:
|
|
start_point = ORIGIN
|
|
|
|
#Establish end point
|
|
if func_name is "sin":
|
|
end_point = start_point[0]*RIGHT
|
|
elif func_name is "cos":
|
|
end_point = start_point[1]*UP
|
|
elif func_name in ["tan", "sec"]:
|
|
end_point = (1./np.cos(self.theta_value))*self.unit_length*RIGHT
|
|
elif func_name in ["cot", "csc"]:
|
|
end_point = (1./np.sin(self.theta_value))*self.unit_length*UP
|
|
return Line(start_point, end_point, color = color)
|
|
|
|
class Introduce(TeacherStudentsScene):
|
|
def construct(self):
|
|
self.teacher_says(
|
|
"Something different today!",
|
|
target_mode = "hooray",
|
|
run_time = 2
|
|
)
|
|
self.change_student_modes("thinking", "happy", "sassy")
|
|
self.random_blink(2)
|
|
|
|
class ReactionsToTattoo(PiCreatureScene):
|
|
def construct(self):
|
|
modes = [
|
|
"horrified",
|
|
"hesitant",
|
|
"pondering",
|
|
"thinking",
|
|
"sassy",
|
|
]
|
|
tattoo_on_math = TextMobject("Tattoo on \\\\ math")
|
|
tattoo_on_math.to_edge(UP)
|
|
self.wait(2)
|
|
for mode in modes:
|
|
self.play(
|
|
self.pi_creature.change_mode, mode,
|
|
self.pi_creature.look, UP+RIGHT
|
|
)
|
|
self.wait(2)
|
|
self.play(
|
|
Write(tattoo_on_math),
|
|
self.pi_creature.change_mode, "hooray",
|
|
self.pi_creature.look, UP
|
|
)
|
|
self.wait()
|
|
self.change_mode("happy")
|
|
self.wait(2)
|
|
|
|
|
|
def create_pi_creature(self):
|
|
randy = Randolph()
|
|
randy.next_to(ORIGIN, DOWN)
|
|
return randy
|
|
|
|
class IntroduceCSC(TrigRepresentationsScene):
|
|
def construct(self):
|
|
self.clear()
|
|
Cam_S_C = TextMobject("Cam", "S.", "C.")
|
|
CSC = TextMobject("C", "S", "C", arg_separator = "")
|
|
csc_of_theta = TextMobject("c", "s", "c", "(\\theta)", arg_separator = "")
|
|
csc, of_theta = VGroup(*csc_of_theta[:3]), csc_of_theta[-1]
|
|
of_theta[1].set_color(YELLOW)
|
|
CSC.move_to(csc, DOWN)
|
|
|
|
csc_line = self.get_trig_line("csc")
|
|
csc_line.set_stroke(width = 8)
|
|
cot_line = self.get_trig_line("cot")
|
|
cot_line.set_color(WHITE)
|
|
brace = Brace(csc_line, LEFT)
|
|
|
|
self.play(Write(Cam_S_C))
|
|
self.wait()
|
|
self.play(Transform(Cam_S_C, CSC))
|
|
self.wait()
|
|
self.play(Transform(Cam_S_C, csc))
|
|
self.remove(Cam_S_C)
|
|
self.add(csc)
|
|
self.play(Write(of_theta))
|
|
self.wait(2)
|
|
|
|
csc_of_theta.add_to_back(BackgroundRectangle(csc))
|
|
self.play(
|
|
ShowCreation(self.axes),
|
|
ShowCreation(self.circle),
|
|
GrowFromCenter(brace),
|
|
csc_of_theta.rotate, np.pi/2,
|
|
csc_of_theta.next_to, brace, LEFT,
|
|
path_arc = np.pi/2,
|
|
)
|
|
self.play(Write(self.theta_group, run_time = 1))
|
|
self.play(ShowCreation(cot_line))
|
|
self.play(
|
|
ShowCreation(csc_line),
|
|
csc.set_color, csc_line.get_color(),
|
|
)
|
|
self.wait(3)
|
|
|
|
class TeachObscureTrigFunctions(TeacherStudentsScene):
|
|
def construct(self):
|
|
self.teacher_says(
|
|
"$\\sec(\\theta)$, ",
|
|
"$\\csc(\\theta)$, ",
|
|
"$\\cot(\\theta)$",
|
|
)
|
|
content = self.teacher.bubble.content.copy()
|
|
self.change_student_modes(*["confused"]*3)
|
|
self.student_says(
|
|
"But why?",
|
|
target_mode = "pleading",
|
|
added_anims = [content.to_corner, UP+RIGHT]
|
|
)
|
|
self.wait()
|
|
self.play(self.get_teacher().change_mode, "pondering")
|
|
self.wait(3)
|
|
|
|
class CanYouExplainTheTattoo(TeacherStudentsScene):
|
|
def construct(self):
|
|
self.student_says("""
|
|
Wait, can you explain
|
|
the actual tattoo here?
|
|
""")
|
|
self.random_blink()
|
|
self.play(self.get_teacher().change_mode, "hooray")
|
|
self.wait()
|
|
|
|
class ExplainTrigFunctionDistances(TrigRepresentationsScene, PiCreatureScene):
|
|
CONFIG = {
|
|
"use_morty" : False,
|
|
"alt_theta_val" : 2*np.pi/5,
|
|
}
|
|
def setup(self):
|
|
PiCreatureScene.setup(self)
|
|
TrigRepresentationsScene.setup(self)
|
|
|
|
def construct(self):
|
|
self.introduce_angle()
|
|
self.show_sine_and_cosine()
|
|
self.show_tangent_and_cotangent()
|
|
self.show_secant_and_cosecant()
|
|
self.explain_cosecant()
|
|
self.summarize_full_group()
|
|
|
|
def introduce_angle(self):
|
|
self.remove(self.circle)
|
|
self.remove(self.theta_group)
|
|
line, arc, theta, dot = self.theta_group
|
|
line.rotate(-self.theta_value)
|
|
brace = Brace(line, UP, buff = SMALL_BUFF)
|
|
one = brace.get_text("1", buff = SMALL_BUFF)
|
|
VGroup(line, brace, one).rotate(self.theta_value)
|
|
one.rotate_in_place(-self.theta_value)
|
|
self.circle.rotate(self.theta_value)
|
|
|
|
words = TextMobject("Corresponding point")
|
|
words.next_to(dot, UP+RIGHT, buff = 1.5*LARGE_BUFF)
|
|
words.shift_onto_screen()
|
|
arrow = Arrow(words.get_bottom(), dot, buff = SMALL_BUFF)
|
|
|
|
self.play(
|
|
ShowCreation(line),
|
|
ShowCreation(arc),
|
|
)
|
|
self.play(Write(theta))
|
|
self.play(self.pi_creature.change_mode, "pondering")
|
|
self.play(
|
|
ShowCreation(self.circle),
|
|
Rotating(line, rate_func = smooth, in_place = False),
|
|
run_time = 2
|
|
)
|
|
self.play(
|
|
Write(words),
|
|
ShowCreation(arrow),
|
|
ShowCreation(dot)
|
|
)
|
|
self.wait()
|
|
self.play(
|
|
GrowFromCenter(brace),
|
|
Write(one)
|
|
)
|
|
self.wait(2)
|
|
self.play(*list(map(FadeOut, [
|
|
words, arrow, brace, one
|
|
])))
|
|
self.radial_line_label = VGroup(brace, one)
|
|
|
|
def show_sine_and_cosine(self):
|
|
sin_line, sin_brace, sin_text = sin_group = self.get_line_brace_text("sin")
|
|
cos_line, cos_brace, cos_text = cos_group = self.get_line_brace_text("cos")
|
|
|
|
self.play(ShowCreation(sin_line))
|
|
self.play(
|
|
GrowFromCenter(sin_brace),
|
|
Write(sin_text),
|
|
)
|
|
self.play(self.pi_creature.change_mode, "happy")
|
|
self.play(ShowCreation(cos_line))
|
|
self.play(
|
|
GrowFromCenter(cos_brace),
|
|
Write(cos_text),
|
|
)
|
|
self.wait()
|
|
self.change_mode("well")
|
|
|
|
mover = VGroup(
|
|
sin_group,
|
|
cos_group,
|
|
self.theta_group,
|
|
)
|
|
thetas = np.linspace(self.theta_value, self.alt_theta_val, 100)
|
|
targets = []
|
|
for theta in thetas:
|
|
self.theta_value = theta
|
|
targets.append(VGroup(
|
|
self.get_line_brace_text("sin"),
|
|
self.get_line_brace_text("cos"),
|
|
self.get_theta_group()
|
|
))
|
|
self.play(Succession(
|
|
*[
|
|
Transform(mover, target, rate_func=linear)
|
|
for target in targets
|
|
],
|
|
run_time = 5,
|
|
rate_func = there_and_back
|
|
))
|
|
self.theta_value = thetas[0]
|
|
|
|
self.change_mode("happy")
|
|
self.wait()
|
|
self.sin_group, self.cos_group = sin_group, cos_group
|
|
|
|
def show_tangent_and_cotangent(self):
|
|
tan_group = self.get_line_brace_text("tan")
|
|
cot_group = self.get_line_brace_text("cot")
|
|
tan_text = tan_group[-1]
|
|
cot_text = cot_group[-1]
|
|
line = Line(UP, DOWN).scale(FRAME_Y_RADIUS)
|
|
line.rotate(self.theta_value)
|
|
line.move_to(self.theta_group[-1])
|
|
line.set_stroke(width = 2)
|
|
|
|
sin_tex = "{\\sin(\\theta)}"
|
|
cos_tex = "{\\cos(\\theta)}"
|
|
tan_frac = TexMobject("= \\frac" + sin_tex + cos_tex)
|
|
cot_frac = TexMobject("= \\frac" + cos_tex + sin_tex)
|
|
tan_frac.to_corner(UP+LEFT)
|
|
tan_frac.shift(2*RIGHT)
|
|
cot_frac.next_to(tan_frac, DOWN)
|
|
|
|
|
|
self.change_mode("pondering")
|
|
for frac, text in (tan_frac, tan_text), (cot_frac, cot_text):
|
|
VGroup(frac[5], frac[-2]).set_color(YELLOW)
|
|
frac.scale_in_place(0.7)
|
|
text.save_state()
|
|
text.next_to(frac, LEFT)
|
|
self.play(Write(VGroup(text, frac)))
|
|
self.wait()
|
|
self.change_mode("confused")
|
|
self.wait()
|
|
self.play(*list(map(FadeOut, [
|
|
tan_frac, cot_frac, self.sin_group, self.cos_group
|
|
])))
|
|
self.wait()
|
|
|
|
self.play(
|
|
self.theta_group[-1].set_color, YELLOW,
|
|
ShowCreation(line),
|
|
self.pi_creature.change_mode, 'pondering'
|
|
)
|
|
small_lines = VGroup()
|
|
for group in tan_group, cot_group:
|
|
small_line, brace, text = group
|
|
self.play(
|
|
ShowCreation(small_line),
|
|
GrowFromCenter(brace),
|
|
text.restore,
|
|
)
|
|
self.wait()
|
|
small_lines.add(small_line)
|
|
self.play(FadeOut(line), Animation(small_lines))
|
|
|
|
mover = VGroup(
|
|
tan_group,
|
|
cot_group,
|
|
self.theta_group,
|
|
)
|
|
thetas = np.linspace(self.theta_value, self.alt_theta_val, 100)
|
|
targets = []
|
|
for theta in thetas:
|
|
self.theta_value = theta
|
|
targets.append(VGroup(
|
|
self.get_line_brace_text("tan"),
|
|
self.get_line_brace_text("cot"),
|
|
self.get_theta_group()
|
|
))
|
|
self.play(Succession(
|
|
*[
|
|
Transform(mover, target, rate_func=linear)
|
|
for target in targets
|
|
],
|
|
run_time = 5,
|
|
rate_func = there_and_back
|
|
))
|
|
self.theta_value = thetas[0]
|
|
|
|
self.change_mode("happy")
|
|
self.wait(2)
|
|
|
|
self.tangent_line = self.get_tangent_line()
|
|
self.add(self.tangent_line)
|
|
self.play(*it.chain(*[
|
|
list(map(FadeOut, [tan_group, cot_group])),
|
|
[Animation(self.theta_group[-1])]
|
|
]))
|
|
|
|
def show_secant_and_cosecant(self):
|
|
sec_group = self.get_line_brace_text("sec")
|
|
csc_group = self.get_line_brace_text("csc")
|
|
sec_line, sec_brace, sec_text = sec_group
|
|
csc_line, csc_brace, csc_text = csc_group
|
|
|
|
sec_frac = TexMobject("= \\frac{1}{\\cos(\\theta)}")
|
|
sec_frac.to_corner(UP+LEFT).shift(2*RIGHT)
|
|
csc_frac = TexMobject("= \\frac{1}{\\sin(\\theta)}")
|
|
csc_frac.next_to(sec_frac, DOWN)
|
|
|
|
sec_dot, csc_dot = [
|
|
Dot(line.get_end(), color = line.get_color())
|
|
for line in (sec_line, csc_line)
|
|
]
|
|
sec_group.add(sec_dot)
|
|
csc_group.add(csc_dot)
|
|
|
|
for text, frac in (sec_text, sec_frac), (csc_text, csc_frac):
|
|
frac[-2].set_color(YELLOW)
|
|
frac.scale_in_place(0.7)
|
|
text.save_state()
|
|
text.next_to(frac, LEFT)
|
|
frac.add_to_back(text.copy())
|
|
self.play(
|
|
Write(frac),
|
|
self.pi_creature.change_mode, "erm"
|
|
)
|
|
self.wait()
|
|
self.wait()
|
|
for group in sec_group, csc_group:
|
|
line, brace, text, dot = group
|
|
dot.save_state()
|
|
dot.move_to(text)
|
|
dot.set_fill(opacity = 0)
|
|
self.play(dot.restore)
|
|
self.wait()
|
|
self.play(
|
|
ShowCreation(line),
|
|
GrowFromCenter(brace),
|
|
text.restore,
|
|
self.pi_creature.change_mode, "pondering"
|
|
)
|
|
self.wait()
|
|
|
|
mover = VGroup(
|
|
sec_group,
|
|
csc_group,
|
|
self.theta_group,
|
|
self.tangent_line,
|
|
)
|
|
thetas = np.linspace(self.theta_value, self.alt_theta_val, 100)
|
|
targets = []
|
|
for theta in thetas:
|
|
self.theta_value = theta
|
|
new_sec_group = self.get_line_brace_text("sec")
|
|
new_csc_group = self.get_line_brace_text("csc")
|
|
for group in new_sec_group, new_csc_group:
|
|
line = group[0]
|
|
group.add(
|
|
Dot(line.get_end(), color = line.get_color())
|
|
)
|
|
targets.append(VGroup(
|
|
new_sec_group,
|
|
new_csc_group,
|
|
self.get_theta_group(),
|
|
self.get_tangent_line(),
|
|
))
|
|
self.play(Succession(
|
|
*[
|
|
Transform(mover, target, rate_func=linear)
|
|
for target in targets
|
|
],
|
|
run_time = 5,
|
|
rate_func = there_and_back
|
|
))
|
|
self.theta_value = thetas[0]
|
|
|
|
self.change_mode("confused")
|
|
self.wait(2)
|
|
|
|
self.play(*list(map(FadeOut, [
|
|
sec_group, sec_frac
|
|
])))
|
|
self.csc_group = csc_group
|
|
self.csc_frac =csc_frac
|
|
|
|
def explain_cosecant(self):
|
|
sin_group = self.get_line_brace_text("sin")
|
|
sin_line, sin_brace, sin_text = sin_group
|
|
csc_line, csc_brace, csc_text, csc_dot = self.csc_group
|
|
csc_subgroup = VGroup(csc_brace, csc_text)
|
|
|
|
arc_theta = VGroup(*self.theta_group[1:3]).copy()
|
|
arc_theta.rotate(-np.pi/2)
|
|
arc_theta.shift(csc_line.get_end())
|
|
arc_theta[1].rotate_in_place(np.pi/2)
|
|
|
|
radial_line = self.theta_group[0]
|
|
|
|
tri1 = Polygon(
|
|
ORIGIN, radial_line.get_end(), sin_line.get_end(),
|
|
color = GREEN,
|
|
stroke_width = 8,
|
|
)
|
|
tri2 = Polygon(
|
|
csc_line.get_end(), ORIGIN, radial_line.get_end(),
|
|
color = GREEN,
|
|
stroke_width = 8,
|
|
)
|
|
|
|
opp_over_hyp = TexMobject(
|
|
"\\frac{\\text{Opposite}}{\\text{Hypotenuse}} ="
|
|
)
|
|
frac1 = TexMobject("\\frac{\\sin(\\theta)}{1}")
|
|
frac1.next_to(opp_over_hyp)
|
|
frac1[-4].set_color(YELLOW)
|
|
frac2 = TexMobject("= \\frac{1}{\\csc(\\theta)}")
|
|
frac2.next_to(frac1)
|
|
frac2[-2].set_color(YELLOW)
|
|
frac_group = VGroup(opp_over_hyp, frac1, frac2)
|
|
frac_group.set_width(FRAME_X_RADIUS-1)
|
|
frac_group.next_to(ORIGIN, RIGHT).to_edge(UP)
|
|
|
|
question = TextMobject("Why is this $\\theta$?")
|
|
question.set_color(YELLOW)
|
|
question.to_corner(UP+RIGHT)
|
|
arrow = Arrow(question.get_bottom(), arc_theta)
|
|
|
|
one_brace, one = self.radial_line_label
|
|
one.move_to(one_brace.get_center_of_mass())
|
|
|
|
self.play(ShowCreation(tri1))
|
|
self.play(
|
|
ApplyMethod(tri1.rotate_in_place, np.pi/12, rate_func = wiggle),
|
|
self.pi_creature.change_mode, "thinking"
|
|
)
|
|
self.wait()
|
|
tri1.save_state()
|
|
self.play(Transform(tri1, tri2, path_arc = np.pi/2))
|
|
self.play(Write(arc_theta))
|
|
self.play(ApplyMethod(
|
|
tri1.rotate_in_place, np.pi/12,
|
|
rate_func = wiggle
|
|
))
|
|
self.wait(2)
|
|
self.play(
|
|
Write(question),
|
|
ShowCreation(arrow),
|
|
self.pi_creature.change_mode, "confused"
|
|
)
|
|
self.wait(2)
|
|
self.play(*list(map(FadeOut, [question, arrow])))
|
|
|
|
|
|
self.play(Write(opp_over_hyp))
|
|
self.wait()
|
|
csc_subgroup.save_state()
|
|
self.play(
|
|
tri1.restore,
|
|
csc_subgroup.fade, 0.7
|
|
)
|
|
self.play(
|
|
ShowCreation(sin_line),
|
|
GrowFromCenter(sin_brace),
|
|
Write(sin_text)
|
|
)
|
|
self.wait()
|
|
self.play(Write(one))
|
|
self.wait()
|
|
self.play(Write(frac1))
|
|
self.wait()
|
|
self.play(
|
|
Transform(tri1, tri2),
|
|
FadeOut(sin_group)
|
|
)
|
|
self.play(
|
|
radial_line.rotate_in_place, np.pi/12,
|
|
rate_func = wiggle
|
|
)
|
|
self.wait()
|
|
self.play(csc_subgroup.restore)
|
|
self.wait()
|
|
self.play(Write(frac2))
|
|
self.change_mode("happy")
|
|
self.play(FadeOut(opp_over_hyp))
|
|
self.reciprocate(frac1, frac2)
|
|
self.play(*list(map(FadeOut, [
|
|
one, self.csc_group, tri1,
|
|
frac1, frac2, self.csc_frac,
|
|
arc_theta
|
|
])))
|
|
|
|
def reciprocate(self, frac1, frac2):
|
|
# Not general, meant only for these definitions:
|
|
# frac1 = TexMobject("\\frac{\\sin(\\theta)}{1}")
|
|
# frac2 = TexMobject("= \\frac{1}{\\csc(\\theta)}")
|
|
num1 = VGroup(*frac1[:6])
|
|
dem1 = frac1[-1]
|
|
num2 = frac2[1]
|
|
dem2 = VGroup(*frac2[-6:])
|
|
group = VGroup(frac1, frac2)
|
|
|
|
self.play(
|
|
group.scale, 1/0.7,
|
|
group.to_corner, UP+RIGHT,
|
|
)
|
|
self.play(
|
|
num1.move_to, dem1,
|
|
dem1.move_to, num1,
|
|
num2.move_to, dem2,
|
|
dem2.move_to, num2,
|
|
path_arc = np.pi
|
|
)
|
|
self.wait()
|
|
self.play(
|
|
dem2.move_to, frac2[2],
|
|
VGroup(*frac2[1:3]).set_fill, BLACK, 0
|
|
)
|
|
self.wait()
|
|
|
|
def summarize_full_group(self):
|
|
scale_factor = 1.5
|
|
theta_subgroup = VGroup(self.theta_group[0], self.theta_group[-1])
|
|
self.play(*it.chain(*[
|
|
[mob.scale, scale_factor]
|
|
for mob in [
|
|
self.circle, self.axes,
|
|
theta_subgroup, self.tangent_line
|
|
]
|
|
]))
|
|
self.unit_length *= scale_factor
|
|
|
|
to_fade = VGroup()
|
|
for func_name in ["sin", "tan", "sec", "cos", "cot", "csc"]:
|
|
line, brace, text = self.get_line_brace_text(func_name)
|
|
if func_name in ["sin", "cos"]:
|
|
angle = line.get_angle()
|
|
if np.cos(angle) < 0:
|
|
angle += np.pi
|
|
if func_name is "sin":
|
|
target = line.get_center()+0.2*LEFT+0.1*DOWN
|
|
else:
|
|
target = VGroup(brace, line).get_center_of_mass()
|
|
text.scale(0.75)
|
|
text.rotate(angle)
|
|
text.move_to(target)
|
|
line.set_stroke(width = 6)
|
|
self.play(
|
|
ShowCreation(line),
|
|
Write(text, run_time = 1)
|
|
)
|
|
else:
|
|
self.play(
|
|
ShowCreation(line),
|
|
GrowFromCenter(brace),
|
|
Write(text, run_time = 1)
|
|
)
|
|
if func_name in ["sec", "csc", "cot"]:
|
|
to_fade.add(*self.get_mobjects_from_last_animation())
|
|
if func_name is "sec":
|
|
self.wait()
|
|
self.wait()
|
|
self.change_mode("surprised")
|
|
self.wait(2)
|
|
self.remove(self.tangent_line)
|
|
self.play(
|
|
FadeOut(to_fade),
|
|
self.pi_creature.change_mode, "sassy"
|
|
)
|
|
self.wait(2)
|
|
|
|
def get_line_brace_text(self, func_name = "sin"):
|
|
line = self.get_trig_line(func_name)
|
|
angle = line.get_angle()
|
|
vect = rotate_vector(UP, angle)
|
|
vect = np.round(vect, 1)
|
|
if (vect[1] < 0) ^ (func_name is "sec"):
|
|
vect = -vect
|
|
angle += np.pi
|
|
brace = Brace(
|
|
Line(
|
|
line.get_length()*LEFT/2,
|
|
line.get_length()*RIGHT/2,
|
|
),
|
|
UP
|
|
)
|
|
brace.rotate(angle)
|
|
brace.shift(line.get_center())
|
|
brace.set_color(line.get_color())
|
|
text = TexMobject("\\%s(\\theta)"%func_name)
|
|
text.scale(0.75)
|
|
text[-2].set_color(self.theta_color)
|
|
text.add_background_rectangle()
|
|
text.next_to(brace.get_center_of_mass(), vect, buff = 1.2*MED_SMALL_BUFF)
|
|
return VGroup(line, brace, text)
|
|
|
|
def get_tangent_line(self):
|
|
return Line(
|
|
self.unit_length*(1./np.sin(self.theta_value))*UP,
|
|
self.unit_length*(1./np.cos(self.theta_value))*RIGHT,
|
|
color = GREY
|
|
)
|
|
|
|
class RenameAllInTermsOfSine(Scene):
|
|
def construct(self):
|
|
texs = [
|
|
"\\sin(\\theta)",
|
|
"\\cos(\\theta)",
|
|
"\\tan(\\theta)",
|
|
"\\csc(\\theta)",
|
|
"\\sec(\\theta)",
|
|
"\\cot(\\theta)",
|
|
]
|
|
shift_vals = [
|
|
4*LEFT+3*UP,
|
|
4*LEFT+UP,
|
|
4*LEFT+DOWN,
|
|
4*RIGHT+3*UP,
|
|
4*RIGHT+UP,
|
|
4*RIGHT+DOWN,
|
|
]
|
|
equivs = [
|
|
"",
|
|
"= \\sin(90^\\circ - \\theta)",
|
|
"= \\frac{\\sin(\\theta)}{\\sin(90^\\circ - \\theta)}",
|
|
"= \\frac{1}{\\sin(\\theta)}",
|
|
"= \\frac{1}{\\sin(90^\\circ - \\theta)}",
|
|
"= \\frac{\\sin(90^\\circ - \\theta)}{\\sin(\\theta)}",
|
|
]
|
|
mobs = VGroup(*list(map(TexMobject, texs)))
|
|
sin, cos, tan = mobs[:3]
|
|
sin.target_color = YELLOW
|
|
cos.target_color = GREEN
|
|
tan.target_color = RED
|
|
|
|
rhs_mobs = VGroup(*list(map(TexMobject, equivs)))
|
|
rhs_mobs.submobjects[0] = VectorizedPoint()
|
|
for mob, shift_val in zip(mobs, shift_vals):
|
|
mob.shift(shift_val)
|
|
self.play(Write(mobs))
|
|
self.wait()
|
|
for mob, rhs_mob in zip(mobs, rhs_mobs):
|
|
rhs_mob.next_to(mob)
|
|
rhs_mob.set_color(sin.target_color)
|
|
mob.save_state()
|
|
mob.generate_target()
|
|
VGroup(mob.target, rhs_mob).move_to(mob)
|
|
sin.target.set_color(sin.target_color)
|
|
self.play(*it.chain(*[
|
|
list(map(MoveToTarget, mobs)),
|
|
[Write(rhs_mobs)]
|
|
]))
|
|
self.wait(2)
|
|
|
|
anims = []
|
|
for mob, rhs_mob in list(zip(mobs, rhs_mobs))[1:3]:
|
|
anims += [
|
|
FadeOut(rhs_mob),
|
|
mob.restore,
|
|
mob.set_color, mob.target_color,
|
|
]
|
|
self.play(*anims)
|
|
self.wait()
|
|
|
|
new_rhs_mobs = [
|
|
TexMobject("=\\frac{1}{\\%s(\\theta)}"%s).set_color(color)
|
|
for s, color in [
|
|
("cos", cos.target_color),
|
|
("tan", tan.target_color),
|
|
]
|
|
]
|
|
anims = []
|
|
for mob, rhs, new_rhs in zip(mobs[-2:], rhs_mobs[-2:], new_rhs_mobs):
|
|
new_rhs.next_to(mob)
|
|
VGroup(mob.target, new_rhs).move_to(
|
|
VGroup(mob, rhs)
|
|
)
|
|
anims += [
|
|
MoveToTarget(mob),
|
|
Transform(rhs, new_rhs)
|
|
]
|
|
self.play(*anims)
|
|
self.wait(2)
|
|
|
|
class MisMatchOfCoPrefix(TeacherStudentsScene):
|
|
def construct(self):
|
|
eq1 = TexMobject(
|
|
"\\text{secant}(\\theta) = \\frac{1}{\\text{cosine}(\\theta)}"
|
|
)
|
|
eq2 = TexMobject(
|
|
"\\text{cosecant}(\\theta) = \\frac{1}{\\text{sine}(\\theta)}"
|
|
)
|
|
eq1.to_corner(UP+LEFT)
|
|
eq1.to_edge(LEFT)
|
|
eq2.next_to(eq1, DOWN, buff = LARGE_BUFF)
|
|
eqs = VGroup(eq1, eq2)
|
|
|
|
self.play(
|
|
self.get_teacher().change_mode, "speaking",
|
|
Write(eqs),
|
|
*[
|
|
ApplyMethod(pi.look_at, eqs)
|
|
for pi in self.get_students()
|
|
]
|
|
)
|
|
self.random_blink()
|
|
self.play(
|
|
VGroup(*eq1[-9:-7]).set_color, YELLOW,
|
|
VGroup(*eq2[:2]).set_color, YELLOW,
|
|
*[
|
|
ApplyMethod(pi.change_mode, "confused")
|
|
for pi in self.get_students()
|
|
]
|
|
)
|
|
self.random_blink(2)
|
|
|
|
class Credit(Scene):
|
|
def construct(self):
|
|
morty = Mortimer()
|
|
morty.next_to(ORIGIN, DOWN)
|
|
morty.to_edge(RIGHT)
|
|
|
|
headphones = Headphones(height = 1)
|
|
headphones.move_to(morty.eyes, aligned_edge = DOWN)
|
|
headphones.shift(0.1*DOWN)
|
|
|
|
url = TextMobject("www.audibletrial.com/3blue1brown")
|
|
url.scale(0.8)
|
|
url.to_corner(UP+RIGHT, buff = LARGE_BUFF)
|
|
|
|
book = ImageMobject("zen_and_motorcycles")
|
|
book.set_height(5)
|
|
book.to_edge(DOWN, buff = LARGE_BUFF)
|
|
border = Rectangle(color = WHITE)
|
|
border.replace(book, stretch = True)
|
|
|
|
self.play(PiCreatureSays(
|
|
morty, "Book recommendation!",
|
|
target_mode = "surprised"
|
|
))
|
|
self.play(Blink(morty))
|
|
self.play(
|
|
FadeIn(headphones),
|
|
morty.change_mode, "thinking",
|
|
FadeOut(morty.bubble),
|
|
FadeOut(morty.bubble.content),
|
|
)
|
|
self.play(Write(url))
|
|
self.play(morty.change_mode, "happy")
|
|
self.wait(2)
|
|
self.play(Blink(morty))
|
|
self.wait(2)
|
|
self.play(
|
|
morty.change_mode, "raise_right_hand",
|
|
morty.look_at, url
|
|
)
|
|
self.wait(2)
|
|
self.play(
|
|
morty.change_mode, "happy",
|
|
morty.look_at, book
|
|
)
|
|
self.play(FadeIn(book))
|
|
self.play(ShowCreation(border))
|
|
self.wait(2)
|
|
self.play(Blink(morty))
|
|
self.wait()
|
|
self.play(
|
|
morty.change_mode, "thinking",
|
|
morty.look_at, book
|
|
)
|
|
self.wait(2)
|
|
self.play(Blink(morty))
|
|
self.wait(4)
|
|
self.play(Blink(morty))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|