Added QuaternionHistory Scene

This commit is contained in:
Grant Sanderson 2018-09-04 16:14:54 -07:00
parent 5b9ae8ddb3
commit a1e21a4606

View file

@ -32,7 +32,7 @@ def get_three_d_scene_config(high_quality=True):
"num_axis_pieces": 1,
},
"sphere_config": {
# "resolution": (4, 12),
"resolution": (12, 24),
}
}
if high_quality:
@ -396,8 +396,12 @@ class QuaternionTracker(ValueTracker):
class RubiksCube(VGroup):
CONFIG = {
"colors": [
"#C41E3A", "#009E60", "#0051BA",
"#FF5800", "#FFD500", "#FFFFFF"
"#FFD500", # Yellow
"#C41E3A", # Orange
"#009E60", # Green
"#FF5800", # Red
"#0051BA", # Blue
"#FFFFFF" # White
],
}
@ -711,37 +715,328 @@ class IntroduceHamilton(Scene):
class QuaternionHistory(Scene):
def construct(self):
self.show_dot_product_and_cross_product() # With date
self.show_dot_product_and_cross_product()
self.teaching_students_quaternions()
self.show_anti_quaternion_quote()
self.mad_hatter()
self.vestiges_in_modern_notation()
def show_dot_product_and_cross_product(self):
date = TexMobject("1843")
date.scale(2)
date.to_edge(UP)
t2c = self.t2c = {
"x_1": GREEN,
"x_2": GREEN,
"y_1": RED,
"y_2": RED,
"z_1": BLUE,
"z_2": BLUE,
}
def get_colored_tex_mobject(tex):
return TexMobject(tex, tex_to_color_map=t2c)
v1, v2 = [
Matrix([
["{}_{}".format(c, i)]
for c in "xyz"
])
], element_to_mobject=get_colored_tex_mobject)
for i in (1, 2)
]
dot_rhs = get_colored_tex_mobject(
"x_1 x_2 + y_1 y_2 + z_1 z_2",
)
cross_rhs = Matrix([
["y_1 z_2 - z_1 y_2"],
["z_1 x_2 - x_1 z_2"],
["x_1 y_2 - y_1 x_2"],
], element_to_mobject=get_colored_tex_mobject)
dot_product = VGroup(
v1.copy(), TexMobject("\\cdot").scale(2),
v2.copy(), TexMobject("="),
dot_rhs
)
cross_product = VGroup(
v1.copy(), TexMobject("\\times"),
v2.copy(), TexMobject("="),
cross_rhs
)
for product in dot_product, cross_product:
product.arrange_submobjects(RIGHT, buff=2 * SMALL_BUFF)
product.set_height(1.5)
dot_product.next_to(date, DOWN, buff=MED_LARGE_BUFF)
dot_product.to_edge(LEFT, buff=LARGE_BUFF)
cross_product.next_to(
dot_product, DOWN,
buff=MED_LARGE_BUFF,
aligned_edge=LEFT,
)
self.play(FadeInFrom(dot_product, 2 * RIGHT))
self.play(FadeInFrom(cross_product, 2 * LEFT))
self.wait()
self.play(FadeInFromDown(date))
self.play(ApplyMethod(dot_product.fade, 0.7))
self.play(ApplyMethod(cross_product.fade, 0.7))
self.wait()
self.play(
FadeOutAndShift(dot_product, 2 * LEFT),
FadeOutAndShift(cross_product, 2 * RIGHT),
)
self.date = date
def teaching_students_quaternions(self):
pass
hamilton = ImageMobject("Hamilton")
hamilton.set_height(4)
hamilton.pixel_array = hamilton.pixel_array[:, ::-1, :]
hamilton.to_corner(UR)
hamilton.shift(MED_SMALL_BUFF * DOWN)
colors = color_gradient([BLUE_E, GREY_BROWN, BLUE_B], 7)
random.shuffle(colors)
students = VGroup(*[
PiCreature(color=color)
for color in colors
])
students.set_height(2)
students.arrange_submobjects(RIGHT)
students.set_width(FRAME_WIDTH - hamilton.get_width() - 1)
students.to_corner(DL)
equation = TexMobject("""
(x_1 i + y_1 j + z_1 k)
(x_2 i + y_2 j + z_2 k)
=
(-x_1 x_2 - y_1 y_2 - z_1 z_2) +
(y_1 z_2 - z_1 y_2)i +
(z_1 x_2 - x_1 z_2)j +
(x_1 y_2 - y_1 x_2)k
""", tex_to_color_map=self.t2c)
equation.set_width(FRAME_WIDTH - 1)
equation.to_edge(UP, buff=MED_SMALL_BUFF)
images = Group()
image_labels = VGroup()
images_with_labels = Group()
names = ["Peter Tait", "Robert Ball", "Macfarlane Alexander"]
for name in names:
image = ImageMobject(name)
image.set_height(3)
label = TextMobject(name)
label.scale(0.5)
label.next_to(image, DOWN)
image.label = label
image_labels.add(label)
images.add(image)
images_with_labels.add(Group(image, label))
images_with_labels.arrange_submobjects(RIGHT)
images_with_labels.next_to(hamilton, LEFT, LARGE_BUFF)
images_with_labels.shift(MED_LARGE_BUFF * DOWN)
society_title = TextMobject("Quaternion society")
society_title.next_to(images, UP, MED_LARGE_BUFF, UP)
def blink_wait(n_loops):
for x in range(n_loops):
self.play(Blink(random.choice(students)))
self.wait(random.random())
self.play(
FadeInFromDown(hamilton),
Write(
self.date,
rate_func=lambda t: smooth(1 - t),
remover=True
)
)
self.play(LaggedStart(
FadeInFrom, students,
lambda m: (m, LEFT),
))
self.play(
LaggedStart(
ApplyMethod, students,
lambda pi: (
pi.change,
random.choice(["confused", "maybe", "erm"]),
3 * LEFT + 2 * UP,
),
),
Write(equation),
)
blink_wait(3)
self.play(
LaggedStart(FadeInFromDown, images),
LaggedStart(FadeInFromLarge, image_labels),
Write(society_title)
)
blink_wait(3)
self.play(
FadeOutAndShift(hamilton, RIGHT),
LaggedStart(
FadeOutAndShift, images_with_labels,
lambda m: (m, UP)
),
FadeOutAndShift(students, DOWN),
FadeOut(society_title),
run_time=1
)
self.equation = equation
def show_anti_quaternion_quote(self):
pass
names_and_quotes = [
(
"Oliver Heaviside",
"""``As far as the vector analysis I required was
concerned, the quaternion was not only not
required, but was a positive evil of no
inconsiderable magnitude.''"""
),
(
"Lord Kelvin",
"""``Quaternions... though beautifully \\\\ ingenious,
have been an unmixed evil to those who have
touched them in any way, including Clerk Maxwell.''"""
),
]
images = Group()
quotes = VGroup()
names = VGroup()
images_with_quotes = Group()
for name, quote_text in names_and_quotes:
image = Group(ImageMobject(name))
image.set_height(4)
label = TextMobject(name)
label.next_to(image, DOWN)
names.add(label)
quote = TextMobject(
"\\huge " + quote_text,
tex_to_color_map={
"positive evil": RED,
"unmixed evil": RED,
},
alignment=""
)
quote.scale(0.3)
quote.next_to(image, UP)
images.add(image)
quotes.add(quote)
images_with_quotes.add(Group(image, label, quote))
images_with_quotes.arrange_submobjects(RIGHT, buff=LARGE_BUFF)
images_with_quotes.to_edge(DOWN, MED_LARGE_BUFF)
self.play(
LaggedStart(FadeInFromDown, images),
LaggedStart(FadeInFromLarge, names),
lag_ratio=0.75,
run_time=2,
)
for quote in quotes:
self.play(LaggedStart(
FadeIn, VGroup(*quote.family_members_with_points()),
lag_ratio=0.3
))
self.wait()
self.play(FadeOut(images_with_quotes))
def mad_hatter(self):
pass
title = TextMobject(
"Lewis Carroll's", "``Alice in wonderland''"
)
title.to_edge(UP, buff=LARGE_BUFF)
author_brace = Brace(title[0], DOWN)
aka = TextMobject("a.k.a. Mathematician Charles Dodgson")
aka.scale(0.8)
aka.set_color(BLUE)
aka.next_to(author_brace, DOWN)
def vestiges_in_modern_notation(self):
pass
quote = TextMobject(
"""
``Why, you might just as well say that\\\\
I see what I eat is the same thing as\\\\
I eat what I see!''
""",
tex_to_color_map={
"I see what I eat": BLUE,
"I eat what I see": YELLOW,
},
alignment=""
)
quote.to_edge(UP, buff=LARGE_BUFF)
hatter = PiCreature(color=RED, mode="surprised")
hat = SVGMobject(file_name="hat")
hat_back = hat.copy()
hat_back[0].remove(*[
sm for sm in hat_back[0] if sm.is_subpath
])
hat_back.set_fill(DARK_GREY)
hat.add_to_back(hat_back)
hat.set_height(1.25)
hat.next_to(hatter.body, UP, buff=-MED_SMALL_BUFF)
hatter.add(hat)
hatter.look(DL)
hatter.pupils[1].save_state()
hatter.look(UL)
hatter.pupils[1].restore()
hatter.set_height(2)
hare = SVGMobject(file_name="bunny")
mouse = SVGMobject(file_name="mouse")
for mob in hare, mouse:
mob.set_color(LIGHT_GREY)
mob.set_sheen(0.2, UL)
mob.set_height(1.5)
characters = VGroup(hatter, hare, mouse)
for mob, p in zip(characters, [UP, DL, DR]):
mob.move_to(p)
hare.shift(MED_SMALL_BUFF * LEFT)
characters.space_out_submobjects(1.5)
characters.to_edge(DOWN)
def change_single_place(char, **kwargs):
i = characters.submobjects.index(char)
target = characters[(i + 1) % 3]
return ApplyMethod(
char.move_to, target,
path_arc=-90 * DEGREES,
**kwargs
)
def get_change_places():
return LaggedStart(
change_single_place, characters,
lag_ratio=0.6
)
self.play(
Write(title),
LaggedStart(FadeInFromDown, characters)
)
self.play(
get_change_places(),
GrowFromCenter(author_brace),
FadeIn(aka)
)
for x in range(4):
self.play(get_change_places())
self.play(
FadeOutAndShift(VGroup(title, author_brace, aka)),
FadeInFromDown(quote),
)
self.play(get_change_places())
self.play(
get_change_places(),
VFadeOut(characters, run_time=2)
)
self.remove(characters)
self.wait()
class QuaternionRotationOverlay(Scene):
@ -3199,7 +3494,6 @@ class TwoDStereographicProjection(IntroduceFelix):
def get_sphere_dot(sphere_point):
dot = Dot()
dot.rotate(90 * DEGREES)
dot.set_shade_in_3d(True)
dot.set_fill(PINK)
dot.shift(OUT)
@ -4722,19 +5016,23 @@ class HypersphereStereographicProjection(SpecialThreeDScene):
return self.q_tracker.get_value()
def specially_color_sphere(self, sphere):
for submob in sphere:
u, v = submob.u1, submob.v1
x = np.cos(v) * np.sin(u)
y = np.sin(v) * np.sin(u)
z = np.cos(u)
rgb = sum([
(x**2) * hex_to_rgb(GREEN),
(y**2) * hex_to_rgb(RED),
(z**2) * hex_to_rgb(BLUE),
])
clip_in_place(rgb, 0, 1)
submob.set_fill(rgb_to_hex(rgb))
sphere.set_color_by_gradient(BLUE, GREEN, PINK)
return sphere
# for submob in sphere:
# u, v = submob.u1, submob.v1
# x = np.cos(v) * np.sin(u)
# y = np.sin(v) * np.sin(u)
# z = np.cos(u)
# # rgb = sum([
# # (x**2) * hex_to_rgb(GREEN),
# # (y**2) * hex_to_rgb(RED),
# # (z**2) * hex_to_rgb(BLUE),
# # ])
# # clip_in_place(rgb, 0, 1)
# # color = rgb_to_hex(rgb)
# color = interpolate_color(BLUE, RED, ((z**3) + 1) / 2)
# submob.set_fill(color)
# return sphere
class RuleOfQuaternionMultiplicationOverlay(Scene):
@ -5179,7 +5477,7 @@ class ShowMultiplicationBy135Example(RuleOfQuaternionMultiplication):
solid=False,
stroke_width=0.5,
stroke_opacity=0.2,
fill_opacity=0.1,
fill_opacity=0.2,
)
self.specially_color_sphere(result)
return result