From bc024dbbbb0647d72028ff3720bde2f646b847e4 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Thu, 20 Sep 2018 10:39:51 -0700 Subject: [PATCH] begin quat3d animations --- active_projects/quat3d.py | 152 +++++++++++++++++++++++++++++++++ active_projects/quaternions.py | 93 +++++++++++--------- 2 files changed, 203 insertions(+), 42 deletions(-) create mode 100644 active_projects/quat3d.py diff --git a/active_projects/quat3d.py b/active_projects/quat3d.py new file mode 100644 index 00000000..44dd16e3 --- /dev/null +++ b/active_projects/quat3d.py @@ -0,0 +1,152 @@ +from big_ol_pile_of_manim_imports import * +from active_projects.quaternions import * + +W_COLOR = YELLOW +I_COLOR = GREEN +J_COLOR = RED +K_COLOR = BLUE + + +class QuaternionLabel(VGroup): + CONFIG = { + "decimal_config": {} + } + + def __init__(self, quat, **kwargs): + VGroup.__init__(self, **kwargs) + dkwargs = dict(self.decimal_config) + self.add(DecimalNumber(quat[0], color=W_COLOR, **dkwargs)) + dkwargs["include_sign"] = True + self.add( + DecimalNumber(quat[1], color=I_COLOR, **dkwargs), + TexMobject("i"), + DecimalNumber(quat[2], color=J_COLOR, **dkwargs), + TexMobject("j"), + DecimalNumber(quat[3], color=K_COLOR, **dkwargs), + TexMobject("k"), + ) + self.arrange_submobjects(RIGHT, buff=SMALL_BUFF) + + +# Scenes + +class Introduction(QuaternionHistory): + CONFIG = { + "names_and_quotes": [ + ( + "Oliver Heaviside", + """\\Huge ``the quaternion was not only not + required, but was a positive evil''""" + ), + ( + "Lord Kelvin", + """\\Huge ``Quaternions... though beautifully \\\\ ingenious, + have been an unmixed evil'' """ + ), + ] + } + + def construct(self): + title_word = TextMobject("Quaternions:") + title_equation = TexMobject( + "i^2 = j^2 = k^2 = ijk = -1", + tex_to_color_map={ + "i": I_COLOR, + "j": J_COLOR, + "k": K_COLOR, + } + ) + # label = QuaternionLabel([ + # float(str((TAU * 10**(3 * k)) % 10)[:4]) + # for k in range(4) + # ]) + title = VGroup(title_word, title_equation) + title.arrange_submobjects(RIGHT) + title.to_edge(UP) + + images_group = self.get_dissenter_images_quotes_and_names() + images_group.to_edge(DOWN) + images, quotes, names = images_group + for pair in images_group: + pair[1].align_to(pair[0], UP) + + self.play( + FadeInFromDown(title_word), + Write(title_equation) + ) + self.wait() + self.play( + LaggedStart( + FadeInFrom, images, + lambda m: (m, 3 * DOWN), + lag_ratio=0.75 + ), + LaggedStart(FadeInFromLarge, names, lag_ratio=0.75), + *[ + LaggedStart( + FadeIn, VGroup(*it.chain(*quote)), + lag_ratio=0.3, + run_time=3 + ) + for quote in quotes + ], + ) + self.wait(2) + self.play( + title.shift, 2 * UP, + *[ + ApplyMethod(mob.shift, FRAME_WIDTH * vect / 2) + for pair in images_group + for mob, vect in zip(pair, [LEFT, RIGHT]) + ], + ) + + +class WhoCares(TeacherStudentsScene): + def construct(self): + quotes = Group(*[ + ImageMobject( + "CoderQuaternionResponse_{}".format(d), + height=2 + ) + for d in range(4) + ]) + logos = Group(*[ + ImageMobject(name, height=0.5) + for name in [ + "TwitterLogo", + "HackerNewsLogo", + "RedditLogo", + "YouTubeLogo", + ] + ]) + for quote, logo in zip(quotes, logos): + logo.move_to(quote.get_corner(UR)) + quote.add(logo) + + quotes.arrange_submobjects_in_grid() + quotes.set_height(4) + quotes.to_corner(UL) + + self.student_says( + "Um...who cares?", + target_mode="sassy", + added_anims=[self.teacher.change, "guilty"] + ) + self.wait(2) + self.play( + RemovePiCreatureBubble(self.students[1]), + self.teacher.change, "raise_right_hand" + ) + self.play( + LaggedStart( + FadeInFromDown, quotes, + run_time=3 + ), + self.get_student_changes(*3 * ["pondering"], look_at_arg=quotes) + ) + self.wait(2) + + # Show HN + + # Show Twitter diff --git a/active_projects/quaternions.py b/active_projects/quaternions.py index 70accdb4..6efae67a 100644 --- a/active_projects/quaternions.py +++ b/active_projects/quaternions.py @@ -728,6 +728,24 @@ class IntroduceHamilton(Scene): class QuaternionHistory(Scene): + CONFIG = { + "names_and_quotes": [ + ( + "Oliver Heaviside", + """\\huge ``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", + """\\huge ``Quaternions... though beautifully \\\\ ingenious, + have been an unmixed evil to those who have + touched them in any way, including Clerk Maxwell.''""" + ), + ] + } + def construct(self): self.show_dot_product_and_cross_product() self.teaching_students_quaternions() @@ -901,48 +919,8 @@ class QuaternionHistory(Scene): self.equation = equation def show_anti_quaternion_quote(self): - 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) - + group = self.get_dissenter_images_quotes_and_names() + images, quotes, names = group self.play( LaggedStart(FadeInFromDown, images), LaggedStart(FadeInFromLarge, names), @@ -1052,6 +1030,37 @@ class QuaternionHistory(Scene): self.remove(characters) self.wait() + # + def get_dissenter_images_quotes_and_names(self): + names_and_quotes = self.names_and_quotes + 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( + 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) + return Group(images, quotes, names) + class QuaternionRotationOverlay(Scene): def construct(self):