2017-05-09 14:54:58 -07:00
|
|
|
from helpers import *
|
|
|
|
|
|
|
|
from mobject.tex_mobject import TexMobject
|
|
|
|
from mobject import Mobject
|
|
|
|
from mobject.image_mobject import ImageMobject
|
|
|
|
from mobject.vectorized_mobject import *
|
|
|
|
|
|
|
|
from animation.animation import Animation
|
|
|
|
from animation.transform import *
|
|
|
|
from animation.simple_animations import *
|
|
|
|
from animation.playground import *
|
|
|
|
from topics.geometry import *
|
|
|
|
from topics.characters import *
|
|
|
|
from topics.functions import *
|
|
|
|
from topics.fractals import *
|
|
|
|
from topics.number_line import *
|
|
|
|
from topics.combinatorics import *
|
|
|
|
from topics.numerals import *
|
|
|
|
from topics.three_dimensions import *
|
|
|
|
from topics.objects import *
|
|
|
|
from topics.complex_numbers import *
|
|
|
|
from scene import Scene
|
|
|
|
from scene.reconfigurable_scene import ReconfigurableScene
|
|
|
|
from scene.zoomed_scene import *
|
|
|
|
from camera import Camera
|
|
|
|
from mobject.svg_mobject import *
|
|
|
|
from mobject.tex_mobject import *
|
|
|
|
|
|
|
|
# revert_to_original_skipping_status
|
|
|
|
|
2017-05-09 23:00:30 -07:00
|
|
|
def chi_func(n):
|
|
|
|
if n%2 == 0:
|
|
|
|
return 0
|
|
|
|
if n%4 == 1:
|
|
|
|
return 1
|
|
|
|
else:
|
|
|
|
return -1
|
|
|
|
|
|
|
|
######
|
2017-05-09 14:54:58 -07:00
|
|
|
|
|
|
|
class Introduction(PiCreatureScene):
|
|
|
|
def construct(self):
|
|
|
|
self.introduce_three_objects()
|
|
|
|
self.show_screen()
|
|
|
|
|
|
|
|
def introduce_three_objects(self):
|
|
|
|
primes = self.get_primes()
|
|
|
|
primes.to_corner(UP+RIGHT)
|
|
|
|
primes.shift(DOWN)
|
|
|
|
plane = self.get_complex_numbers()
|
|
|
|
plane.shift(2*LEFT)
|
|
|
|
pi_group = self.get_pi_group()
|
|
|
|
pi_group.next_to(primes, DOWN, buff = MED_LARGE_BUFF)
|
|
|
|
pi_group.shift_onto_screen()
|
|
|
|
|
|
|
|
morty = self.get_primary_pi_creature()
|
|
|
|
video = VideoIcon()
|
|
|
|
video.highlight(TEAL)
|
|
|
|
video.next_to(morty.get_corner(UP+LEFT), UP)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
morty.change_mode, "raise_right_hand",
|
|
|
|
DrawBorderThenFill(video)
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(
|
|
|
|
Write(primes, run_time = 2),
|
|
|
|
morty.change_mode, "happy",
|
|
|
|
video.scale_to_fit_height, 2*SPACE_WIDTH,
|
|
|
|
video.center,
|
|
|
|
video.set_fill, None, 0
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(
|
|
|
|
Write(plane, run_time = 2),
|
|
|
|
morty.change, "raise_right_hand"
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.remove(morty)
|
|
|
|
morty = morty.copy()
|
|
|
|
self.add(morty)
|
|
|
|
self.play(
|
|
|
|
ReplacementTransform(
|
|
|
|
morty.body,
|
|
|
|
pi_group.get_part_by_tex("pi"),
|
|
|
|
run_time = 1
|
|
|
|
),
|
|
|
|
FadeOut(VGroup(morty.eyes, morty.mouth)),
|
|
|
|
Write(VGroup(*pi_group[1:]))
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
self.play(
|
|
|
|
plane.scale_to_fit_width, pi_group.get_width(),
|
|
|
|
plane.next_to, pi_group, DOWN, MED_LARGE_BUFF
|
|
|
|
)
|
|
|
|
|
|
|
|
def show_screen(self):
|
|
|
|
screen = ScreenRectangle(height = 4.3)
|
|
|
|
screen.to_edge(LEFT)
|
|
|
|
titles = VGroup(
|
|
|
|
TextMobject("From zeta video"),
|
|
|
|
TextMobject("Coming up")
|
|
|
|
)
|
|
|
|
for title in titles:
|
|
|
|
title.next_to(screen, UP)
|
|
|
|
title.highlight(YELLOW)
|
|
|
|
self.play(
|
|
|
|
ShowCreation(screen),
|
|
|
|
FadeIn(titles[0])
|
|
|
|
)
|
|
|
|
self.show_frame()
|
|
|
|
self.dither(2)
|
|
|
|
self.play(Transform(*titles))
|
|
|
|
self.dither(3)
|
|
|
|
|
|
|
|
def get_primes(self):
|
|
|
|
return TexMobject("2, 3, 5, 7, 11, 13, \\dots")
|
|
|
|
|
|
|
|
def get_complex_numbers(self):
|
|
|
|
plane = ComplexPlane(
|
|
|
|
x_radius = 3,
|
|
|
|
y_radius = 2.5,
|
|
|
|
)
|
|
|
|
plane.add_coordinates()
|
|
|
|
point = plane.number_to_point(complex(1, 2))
|
2017-05-10 13:39:45 -07:00
|
|
|
dot = Dot(point, radius = YELLOW)
|
2017-05-09 14:54:58 -07:00
|
|
|
label = TexMobject("1 + 2i")
|
|
|
|
label.add_background_rectangle()
|
|
|
|
label.next_to(dot, UP+RIGHT, buff = SMALL_BUFF)
|
|
|
|
label.highlight(YELLOW)
|
|
|
|
plane.label = label
|
|
|
|
plane.add(dot, label)
|
|
|
|
return plane
|
|
|
|
|
|
|
|
def get_pi_group(self):
|
|
|
|
result = TexMobject("\\pi", "=", "%.8f\\dots"%np.pi)
|
|
|
|
pi = result.get_part_by_tex("pi")
|
|
|
|
pi.scale(2, about_point = pi.get_right())
|
|
|
|
pi.highlight(MAROON_B)
|
|
|
|
return result
|
|
|
|
|
2017-05-09 16:13:10 -07:00
|
|
|
class ShowSum(TeacherStudentsScene):
|
|
|
|
CONFIG = {
|
|
|
|
"num_terms_to_add" : 40,
|
|
|
|
}
|
2017-05-09 14:54:58 -07:00
|
|
|
def construct(self):
|
|
|
|
self.say_words()
|
|
|
|
self.show_sum()
|
|
|
|
|
|
|
|
def say_words(self):
|
|
|
|
self.teacher_says("This won't be easy")
|
|
|
|
self.change_student_modes(
|
|
|
|
"hooray", "sassy", "angry"
|
|
|
|
)
|
|
|
|
self.dither(2)
|
2017-05-09 16:13:10 -07:00
|
|
|
|
|
|
|
def show_sum(self):
|
|
|
|
line = UnitInterval()
|
|
|
|
line.add_numbers(0, 1)
|
2017-05-10 17:22:26 -07:00
|
|
|
# line.shift(UP)
|
2017-05-09 16:13:10 -07:00
|
|
|
sum_point = line.number_to_point(np.pi/4)
|
|
|
|
|
|
|
|
numbers = [0] + [
|
|
|
|
((-1)**n)/(2.0*n + 1)
|
|
|
|
for n in range(self.num_terms_to_add)
|
|
|
|
]
|
|
|
|
partial_sums = np.cumsum(numbers)
|
|
|
|
points = map(line.number_to_point, partial_sums)
|
|
|
|
arrows = [
|
|
|
|
Arrow(
|
|
|
|
p1, p2,
|
|
|
|
tip_length = 0.2*min(1, np.linalg.norm(p1-p2)),
|
|
|
|
buff = 0
|
|
|
|
)
|
|
|
|
for p1, p2 in zip(points, points[1:])
|
|
|
|
]
|
|
|
|
dot = Dot(points[0])
|
|
|
|
|
|
|
|
sum_mob = TexMobject(
|
2017-05-10 17:22:26 -07:00
|
|
|
"1", "-\\frac{1}{3}",
|
|
|
|
"+\\frac{1}{5}", "-\\frac{1}{7}",
|
|
|
|
"+\\frac{1}{9}", "-\\frac{1}{11}",
|
|
|
|
"+\\cdots"
|
2017-05-09 16:13:10 -07:00
|
|
|
)
|
2017-05-10 17:22:26 -07:00
|
|
|
sum_mob.to_corner(UP+RIGHT)
|
|
|
|
lhs = TexMobject(
|
|
|
|
"\\frac{\\pi}{4}", "=",
|
2017-05-09 16:13:10 -07:00
|
|
|
)
|
2017-05-10 17:22:26 -07:00
|
|
|
lhs.next_to(sum_mob, LEFT)
|
|
|
|
lhs.highlight_by_tex("pi", YELLOW)
|
2017-05-09 16:13:10 -07:00
|
|
|
sum_arrow = Arrow(
|
2017-05-10 17:22:26 -07:00
|
|
|
lhs.get_part_by_tex("pi").get_bottom(),
|
2017-05-09 16:13:10 -07:00
|
|
|
sum_point
|
|
|
|
)
|
|
|
|
fading_terms = [
|
|
|
|
TexMobject(sign + "\\frac{1}{%d}"%(2*n + 1))
|
|
|
|
for n, sign in zip(
|
|
|
|
range(self.num_terms_to_add),
|
|
|
|
it.cycle("+-")
|
|
|
|
)
|
|
|
|
]
|
|
|
|
for fading_term, arrow in zip(fading_terms, arrows):
|
|
|
|
fading_term.next_to(arrow, UP)
|
|
|
|
|
|
|
|
terms = it.chain(sum_mob, it.repeat(None))
|
|
|
|
last_arrows = it.chain([None], arrows)
|
|
|
|
last_fading_terms = it.chain([None], fading_terms)
|
|
|
|
|
2017-05-09 14:54:58 -07:00
|
|
|
self.change_student_modes(
|
2017-05-09 16:13:10 -07:00
|
|
|
*["pondering"]*3,
|
|
|
|
look_at_arg = line,
|
|
|
|
added_anims = [
|
|
|
|
FadeIn(VGroup(line, dot)),
|
2017-05-10 17:22:26 -07:00
|
|
|
FadeIn(lhs),
|
2017-05-09 16:13:10 -07:00
|
|
|
RemovePiCreatureBubble(
|
|
|
|
self.teacher,
|
|
|
|
target_mode = "raise_right_hand"
|
|
|
|
)
|
|
|
|
]
|
|
|
|
|
|
|
|
)
|
|
|
|
run_time = 1
|
|
|
|
for term, arrow, last_arrow, fading_term, last_fading_term in zip(
|
|
|
|
terms, arrows, last_arrows, fading_terms, last_fading_terms
|
|
|
|
):
|
|
|
|
anims = []
|
|
|
|
if term:
|
|
|
|
anims.append(Write(term))
|
|
|
|
if last_arrow:
|
|
|
|
anims.append(FadeOut(last_arrow))
|
|
|
|
if last_fading_term:
|
|
|
|
anims.append(FadeOut(last_fading_term))
|
|
|
|
dot_movement = ApplyMethod(dot.move_to, arrow.get_end())
|
|
|
|
anims.append(ShowCreation(arrow))
|
|
|
|
anims.append(dot_movement)
|
|
|
|
anims.append(FadeIn(fading_term))
|
|
|
|
self.play(*anims, run_time = run_time)
|
|
|
|
if term:
|
|
|
|
self.dither()
|
|
|
|
else:
|
|
|
|
run_time *= 0.8
|
|
|
|
self.play(
|
|
|
|
FadeOut(arrow),
|
|
|
|
FadeOut(fading_term),
|
|
|
|
dot.move_to, sum_point
|
|
|
|
)
|
2017-05-10 17:22:26 -07:00
|
|
|
self.play(ShowCreation(sum_arrow))
|
2017-05-09 16:13:10 -07:00
|
|
|
self.dither()
|
|
|
|
self.change_student_modes("erm", "confused", "maybe")
|
|
|
|
self.play(self.teacher.change_mode, "happy")
|
|
|
|
self.dither(2)
|
|
|
|
|
|
|
|
class FermatsDreamExcerptWrapper(Scene):
|
|
|
|
def construct(self):
|
|
|
|
words = TextMobject(
|
|
|
|
"From ``Fermat's dream'' by Kato, Kurokawa and Saito"
|
|
|
|
)
|
|
|
|
words.scale(0.8)
|
|
|
|
words.to_edge(UP)
|
|
|
|
self.add(words)
|
|
|
|
self.dither()
|
|
|
|
|
2017-05-09 23:00:30 -07:00
|
|
|
class ShowCalculus(PiCreatureScene):
|
|
|
|
def construct(self):
|
|
|
|
frac_sum = TexMobject(
|
|
|
|
"1 - \\frac{1}{3} + \\frac{1}{5} - \\frac{1}{7} + \\cdots",
|
|
|
|
)
|
|
|
|
int1 = TexMobject(
|
|
|
|
"= \\int_0^1 (1 - x^2 + x^4 - \\dots )\\,dx"
|
|
|
|
)
|
|
|
|
int2 = TexMobject(
|
|
|
|
"= \\int_0^1 \\frac{1}{1+x^2}\\,dx"
|
|
|
|
)
|
|
|
|
arctan = TexMobject("= \\tan^{-1}(1)")
|
|
|
|
pi_fourths = TexMobject("= \\frac{\\pi}{4}")
|
|
|
|
|
|
|
|
frac_sum.to_corner(UP+LEFT)
|
|
|
|
frac_sum.shift(RIGHT)
|
|
|
|
rhs_group = VGroup(int1, int2, arctan, pi_fourths)
|
|
|
|
rhs_group.arrange_submobjects(
|
|
|
|
DOWN, buff = MED_LARGE_BUFF,
|
|
|
|
aligned_edge = LEFT
|
|
|
|
)
|
|
|
|
rhs_group.shift(
|
|
|
|
frac_sum.get_right() + MED_SMALL_BUFF*RIGHT \
|
|
|
|
-int1[0].get_left()
|
|
|
|
)
|
|
|
|
|
|
|
|
self.add(frac_sum)
|
|
|
|
modes = it.chain(["plain"], it.cycle(["confused"]))
|
|
|
|
for rhs, mode in zip(rhs_group, modes):
|
|
|
|
self.play(
|
|
|
|
FadeIn(rhs),
|
|
|
|
self.pi_creature.change, mode
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.change_mode("maybe")
|
|
|
|
self.dither()
|
|
|
|
self.look_at(rhs_group[-1])
|
|
|
|
self.dither()
|
|
|
|
self.pi_creature_says(
|
|
|
|
"Where's the \\\\ circle?",
|
|
|
|
bubble_kwargs = {"width" : 4, "height" : 3},
|
|
|
|
target_mode = "maybe"
|
|
|
|
)
|
|
|
|
self.look_at(rhs_group[0])
|
|
|
|
self.dither()
|
2017-05-09 16:13:10 -07:00
|
|
|
|
2017-05-09 23:00:30 -07:00
|
|
|
def create_pi_creature(self):
|
|
|
|
return Randolph(color = BLUE_C).to_corner(DOWN+LEFT)
|
2017-05-09 14:54:58 -07:00
|
|
|
|
2017-05-10 17:22:26 -07:00
|
|
|
class CertainRegularityInPrimes(LatticePointScene):
|
|
|
|
def construct(self):
|
|
|
|
pass
|
|
|
|
|
2017-05-09 23:00:30 -07:00
|
|
|
class Outline(PiCreatureScene):
|
|
|
|
def construct(self):
|
|
|
|
self.generate_list()
|
|
|
|
self.wonder_at_pi()
|
|
|
|
self.count_lattice_points()
|
|
|
|
self.write_steps_2_and_3()
|
|
|
|
self.show_chi()
|
|
|
|
self.show_complicated_formula()
|
|
|
|
self.show_last_step()
|
|
|
|
|
|
|
|
def generate_list(self):
|
|
|
|
steps = VGroup(
|
|
|
|
TextMobject("1. Count lattice points"),
|
|
|
|
TexMobject("2. \\text{ Things like }17 = ", "4", "^2 + ", "1", "^2"),
|
|
|
|
TexMobject("3. \\text{ Things like }17 = (", "4", " + ", "i", ")(", "4", " - ", "i", ")"),
|
|
|
|
TextMobject("4. Introduce $\\chi$"),
|
|
|
|
TextMobject("5. Shift perspective"),
|
|
|
|
)
|
|
|
|
for step in steps[1:3]:
|
|
|
|
step.highlight_by_tex("1", RED, substring = False)
|
|
|
|
step.highlight_by_tex("i", RED, substring = False)
|
|
|
|
step.highlight_by_tex("4", GREEN, substring = False)
|
|
|
|
steps.arrange_submobjects(
|
|
|
|
DOWN,
|
|
|
|
buff = MED_LARGE_BUFF,
|
|
|
|
aligned_edge = LEFT
|
|
|
|
)
|
|
|
|
steps.to_corner(UP+LEFT)
|
2017-05-09 14:54:58 -07:00
|
|
|
|
2017-05-09 23:00:30 -07:00
|
|
|
self.steps = steps
|
2017-05-09 14:54:58 -07:00
|
|
|
|
2017-05-09 23:00:30 -07:00
|
|
|
def wonder_at_pi(self):
|
|
|
|
question = TexMobject("\\pi", "=???")
|
|
|
|
pi = question.get_part_by_tex("pi")
|
|
|
|
pi.scale(2, about_point = pi.get_right())
|
|
|
|
pi.highlight(YELLOW)
|
|
|
|
question.next_to(self.pi_creature.body, LEFT, aligned_edge = UP)
|
|
|
|
self.think(
|
|
|
|
"Who am I really?",
|
|
|
|
look_at_arg = question,
|
|
|
|
added_anims = [
|
|
|
|
FadeIn(question)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
self.play(
|
|
|
|
RemovePiCreatureBubble(self.pi_creature),
|
|
|
|
question.to_corner, UP+RIGHT
|
|
|
|
)
|
2017-05-09 14:54:58 -07:00
|
|
|
|
2017-05-09 23:00:30 -07:00
|
|
|
self.question = question
|
|
|
|
self.pi = question.get_part_by_tex("pi")
|
2017-05-09 14:54:58 -07:00
|
|
|
|
2017-05-09 23:00:30 -07:00
|
|
|
def count_lattice_points(self):
|
|
|
|
step = self.steps[0]
|
|
|
|
plane = NumberPlane(
|
|
|
|
x_radius = 10, y_radius = 10,
|
|
|
|
secondary_line_ratio = 0,
|
|
|
|
color = BLUE_E,
|
|
|
|
)
|
|
|
|
plane.scale_to_fit_height(6)
|
|
|
|
plane.next_to(step, DOWN)
|
|
|
|
plane.to_edge(LEFT)
|
|
|
|
circle = Circle(
|
|
|
|
color = YELLOW,
|
|
|
|
radius = np.linalg.norm(
|
|
|
|
plane.coords_to_points(10, 0) - \
|
|
|
|
plane.coords_to_points(0, 0)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
plane_center = plane.coords_to_points(0, 0)
|
|
|
|
circle.move_to(plane_center)
|
|
|
|
lattice_points = VGroup(*[
|
|
|
|
Dot(
|
|
|
|
plane.coords_to_points(a, b),
|
|
|
|
radius = 0.05,
|
|
|
|
color = PINK,
|
|
|
|
)
|
|
|
|
for a in range(-10, 11)
|
|
|
|
for b in range(-10, 11)
|
|
|
|
if a**2 + b**2 <= 10**2
|
|
|
|
])
|
|
|
|
lattice_points.sort_submobjects(
|
|
|
|
lambda p : np.linalg.norm(p - plane_center)
|
|
|
|
)
|
|
|
|
lattice_group = VGroup(plane, circle, lattice_points)
|
2017-05-09 14:54:58 -07:00
|
|
|
|
2017-05-09 23:00:30 -07:00
|
|
|
self.play(ShowCreation(circle))
|
|
|
|
self.play(Write(plane, run_time = 2), Animation(circle))
|
|
|
|
self.play(
|
|
|
|
*[
|
|
|
|
DrawBorderThenFill(
|
|
|
|
dot,
|
|
|
|
stroke_width = 4,
|
|
|
|
stroke_color = YELLOW,
|
|
|
|
run_time = 4,
|
|
|
|
rate_func = squish_rate_func(
|
|
|
|
double_smooth, a, a + 0.25
|
|
|
|
)
|
|
|
|
)
|
|
|
|
for dot, a in zip(
|
|
|
|
lattice_points,
|
|
|
|
np.linspace(0, 0.75, len(lattice_points))
|
|
|
|
)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
FadeIn(step)
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(
|
|
|
|
lattice_group.scale_to_fit_height, 2.5,
|
|
|
|
lattice_group.next_to, self.question, DOWN,
|
|
|
|
lattice_group.to_edge, RIGHT
|
|
|
|
)
|
|
|
|
|
|
|
|
def write_steps_2_and_3(self):
|
|
|
|
for step in self.steps[1:3]:
|
|
|
|
self.play(FadeIn(step))
|
|
|
|
self.dither(2)
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
def show_chi(self):
|
|
|
|
input_range = range(1, 7)
|
|
|
|
chis = VGroup(*[
|
|
|
|
TexMobject("\\chi(%d)"%n)
|
|
|
|
for n in input_range
|
|
|
|
])
|
|
|
|
chis.arrange_submobjects(RIGHT, buff = LARGE_BUFF)
|
|
|
|
chis.set_stroke(WHITE, width = 1)
|
|
|
|
numerators = VGroup()
|
|
|
|
arrows = VGroup()
|
|
|
|
for chi, n in zip(chis, input_range):
|
|
|
|
arrow = TexMobject("\\Downarrow")
|
|
|
|
arrow.next_to(chi, DOWN, SMALL_BUFF)
|
|
|
|
arrows.add(arrow)
|
|
|
|
value = TexMobject(str(chi_func(n)))
|
|
|
|
value.highlight_by_tex("1", BLUE)
|
|
|
|
value.highlight_by_tex("-1", GREEN)
|
|
|
|
value.next_to(arrow, DOWN)
|
|
|
|
numerators.add(value)
|
|
|
|
group = VGroup(chis, arrows, numerators)
|
|
|
|
group.scale_to_fit_width(1.3*SPACE_WIDTH)
|
|
|
|
group.to_corner(DOWN+LEFT)
|
|
|
|
|
|
|
|
self.play(FadeIn(self.steps[3]))
|
|
|
|
self.play(*[
|
|
|
|
FadeIn(
|
|
|
|
mob,
|
|
|
|
run_time = 3,
|
|
|
|
submobject_mode = "lagged_start"
|
|
|
|
)
|
|
|
|
for mob in [chis, arrows, numerators]
|
|
|
|
])
|
|
|
|
self.change_mode("pondering")
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
self.chis = chis
|
|
|
|
self.arrows = arrows
|
|
|
|
self.numerators = numerators
|
|
|
|
|
|
|
|
def show_complicated_formula(self):
|
|
|
|
rhs = TexMobject(
|
|
|
|
" = \\lim_{N \\to \\infty}",
|
|
|
|
" \\frac{1}{N}",
|
|
|
|
"\\sum_{n = 1}^N",
|
|
|
|
"\\sum_{d | n} \\chi(d)",
|
|
|
|
)
|
|
|
|
pi = self.pi
|
|
|
|
self.add(pi.copy())
|
|
|
|
pi.generate_target()
|
|
|
|
pi.target.next_to(self.steps[3], RIGHT, MED_LARGE_BUFF)
|
|
|
|
pi.target.shift(MED_LARGE_BUFF*DOWN)
|
|
|
|
rhs.next_to(pi.target, RIGHT)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
MoveToTarget(pi),
|
|
|
|
Write(rhs)
|
|
|
|
)
|
|
|
|
self.change_mode("confused")
|
|
|
|
self.dither(2)
|
|
|
|
|
|
|
|
self.complicated_formula = rhs
|
|
|
|
|
|
|
|
def show_last_step(self):
|
|
|
|
expression = TexMobject(
|
|
|
|
"=", "\\frac{\\quad}{1}",
|
|
|
|
*it.chain(*[
|
|
|
|
["+", "\\frac{\\quad}{%d}"%d]
|
|
|
|
for d in range(2, len(self.numerators)+1)
|
|
|
|
] + [["+ \\cdots"]])
|
|
|
|
)
|
|
|
|
pi = self.pi
|
|
|
|
pi.generate_target()
|
|
|
|
pi.target.to_corner(DOWN+LEFT)
|
|
|
|
pi.target.shift(UP)
|
|
|
|
expression.next_to(pi.target, RIGHT)
|
|
|
|
self.numerators.generate_target()
|
|
|
|
for num, denom in zip(self.numerators.target, expression[1::2]):
|
|
|
|
num.scale(1.2)
|
|
|
|
num.next_to(denom, UP, MED_SMALL_BUFF)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
MoveToTarget(self.numerators),
|
|
|
|
MoveToTarget(pi),
|
|
|
|
FadeOut(self.chis),
|
|
|
|
FadeOut(self.arrows),
|
|
|
|
FadeOut(self.complicated_formula),
|
|
|
|
)
|
|
|
|
self.play(
|
|
|
|
Write(expression),
|
|
|
|
self.pi_creature.change_mode, "pondering"
|
|
|
|
)
|
|
|
|
self.dither(3)
|
|
|
|
|
|
|
|
########
|
|
|
|
def create_pi_creature(self):
|
|
|
|
return Randolph(color = BLUE_B).flip().to_corner(DOWN+RIGHT)
|
|
|
|
|
|
|
|
class LatticePointScene(Scene):
|
|
|
|
CONFIG = {
|
|
|
|
"y_radius" : 6,
|
2017-05-10 13:39:45 -07:00
|
|
|
"x_radius" : None,
|
|
|
|
"plane_center" : ORIGIN,
|
2017-05-09 23:00:30 -07:00
|
|
|
"max_lattice_point_radius" : 6,
|
|
|
|
"dot_radius" : 0.075,
|
|
|
|
"secondary_line_ratio" : 0,
|
|
|
|
"plane_color" : BLUE_E,
|
|
|
|
"dot_color" : YELLOW,
|
|
|
|
"dot_drawing_stroke_color" : PINK,
|
|
|
|
"circle_color" : MAROON_D,
|
|
|
|
}
|
|
|
|
def setup(self):
|
2017-05-10 13:39:45 -07:00
|
|
|
if self.x_radius is None:
|
|
|
|
self.x_radius = self.y_radius*SPACE_WIDTH/SPACE_HEIGHT
|
2017-05-09 23:00:30 -07:00
|
|
|
plane = NumberPlane(
|
|
|
|
y_radius = self.y_radius,
|
2017-05-10 13:39:45 -07:00
|
|
|
x_radius = self.x_radius,
|
2017-05-09 23:00:30 -07:00
|
|
|
secondary_line_ratio = self.secondary_line_ratio,
|
|
|
|
color = self.plane_color
|
|
|
|
)
|
|
|
|
plane.scale_to_fit_height(2*SPACE_HEIGHT)
|
2017-05-10 13:39:45 -07:00
|
|
|
plane.shift(self.plane_center)
|
2017-05-09 23:00:30 -07:00
|
|
|
self.add(plane)
|
|
|
|
self.plane = plane
|
|
|
|
|
|
|
|
self.setup_lattice_points()
|
|
|
|
|
|
|
|
def setup_lattice_points(self):
|
|
|
|
M = self.max_lattice_point_radius
|
|
|
|
int_range = range(-M, M+1)
|
|
|
|
self.lattice_points = VGroup()
|
|
|
|
for x, y in it.product(*[int_range]*2):
|
|
|
|
r_squared = x**2 + y**2
|
|
|
|
if r_squared > M**2:
|
|
|
|
continue
|
|
|
|
dot = Dot(
|
|
|
|
self.plane.coords_to_point(x, y),
|
|
|
|
color = self.dot_color,
|
|
|
|
radius = self.dot_radius,
|
|
|
|
)
|
|
|
|
dot.r_squared = r_squared
|
|
|
|
self.lattice_points.add(dot)
|
|
|
|
self.lattice_points.sort_submobjects(np.linalg.norm)
|
|
|
|
|
|
|
|
def get_circle(self, radius = None, color = None):
|
|
|
|
if radius is None:
|
|
|
|
radius = self.max_lattice_point_radius
|
|
|
|
if color is None:
|
|
|
|
color = self.circle_color
|
|
|
|
radius *= self.plane.get_space_unit_to_y_unit()
|
2017-05-10 13:39:45 -07:00
|
|
|
circle = Circle(
|
2017-05-09 23:00:30 -07:00
|
|
|
color = color,
|
|
|
|
radius = radius,
|
|
|
|
)
|
2017-05-10 13:39:45 -07:00
|
|
|
circle.move_to(self.plane.get_center())
|
|
|
|
return circle
|
2017-05-09 23:00:30 -07:00
|
|
|
|
|
|
|
def get_lattice_points_on_r_squared_circle(self, r_squared):
|
2017-05-10 17:22:26 -07:00
|
|
|
points = VGroup(*filter(
|
2017-05-09 23:00:30 -07:00
|
|
|
lambda dot : dot.r_squared == r_squared,
|
|
|
|
self.lattice_points
|
|
|
|
))
|
2017-05-10 17:22:26 -07:00
|
|
|
points.sort_submobjects(
|
|
|
|
lambda p : angle_of_vector(p-self.plane_center)%(2*np.pi)
|
|
|
|
)
|
|
|
|
return points
|
2017-05-09 23:00:30 -07:00
|
|
|
|
|
|
|
def draw_lattice_points(self, points = None, run_time = 4):
|
|
|
|
if points is None:
|
|
|
|
points = self.lattice_points
|
|
|
|
self.play(*[
|
|
|
|
DrawBorderThenFill(
|
|
|
|
dot,
|
|
|
|
stroke_width = 4,
|
|
|
|
stroke_color = self.dot_drawing_stroke_color,
|
|
|
|
run_time = run_time,
|
|
|
|
rate_func = squish_rate_func(
|
|
|
|
double_smooth, a, a + 0.25
|
|
|
|
),
|
|
|
|
)
|
|
|
|
for dot, a in zip(
|
|
|
|
points,
|
|
|
|
np.linspace(0, 0.75, len(points))
|
|
|
|
)
|
|
|
|
])
|
|
|
|
|
|
|
|
class CountLatticePoints(LatticePointScene):
|
|
|
|
CONFIG = {
|
|
|
|
"y_radius" : 11,
|
|
|
|
"max_lattice_point_radius" : 10,
|
|
|
|
"dot_radius" : 0.05,
|
2017-05-10 13:39:45 -07:00
|
|
|
"example_coords" : (7, 5),
|
2017-05-09 23:00:30 -07:00
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
self.introduce_lattice_point()
|
|
|
|
self.draw_lattice_points_in_circle()
|
|
|
|
self.turn_points_int_units_of_area()
|
|
|
|
self.write_pi_R_squared()
|
2017-05-10 13:39:45 -07:00
|
|
|
self.allude_to_alternate_counting_method()
|
|
|
|
|
|
|
|
|
|
|
|
def introduce_lattice_point(self):
|
|
|
|
x, y = self.example_coords
|
|
|
|
example_dot = Dot(
|
|
|
|
self.plane.coords_to_point(x, y),
|
|
|
|
color = self.dot_color,
|
|
|
|
radius = 1.5*self.dot_radius,
|
|
|
|
)
|
|
|
|
label = TexMobject(str(self.example_coords))
|
|
|
|
label.add_background_rectangle()
|
|
|
|
label.next_to(example_dot, UP+RIGHT, buff = 0)
|
|
|
|
h_line = Line(
|
|
|
|
ORIGIN, self.plane.coords_to_point(x, 0),
|
|
|
|
color = GREEN
|
|
|
|
)
|
|
|
|
v_line = Line(
|
|
|
|
h_line.get_end(), self.plane.coords_to_point(x, y),
|
|
|
|
color = RED
|
|
|
|
)
|
|
|
|
lines = VGroup(h_line, v_line)
|
|
|
|
|
|
|
|
dots = self.lattice_points.copy()
|
|
|
|
random.shuffle(dots.submobjects)
|
|
|
|
|
|
|
|
self.play(*[
|
|
|
|
ApplyMethod(
|
|
|
|
dot.set_fill, None, 0,
|
|
|
|
run_time = 3,
|
|
|
|
rate_func = squish_rate_func(
|
|
|
|
lambda t : 1 - there_and_back(t),
|
|
|
|
a, a + 0.5
|
|
|
|
),
|
|
|
|
remover = True
|
|
|
|
)
|
|
|
|
for dot, a in zip(dots, np.linspace(0, 0.5, len(dots)))
|
|
|
|
])
|
|
|
|
self.play(
|
|
|
|
Write(label),
|
|
|
|
ShowCreation(lines),
|
|
|
|
DrawBorderThenFill(example_dot),
|
|
|
|
run_time = 2,
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
self.play(*map(FadeOut, [label, lines, example_dot]))
|
2017-05-09 23:00:30 -07:00
|
|
|
|
|
|
|
def draw_lattice_points_in_circle(self):
|
|
|
|
circle = self.get_circle()
|
2017-05-10 13:39:45 -07:00
|
|
|
radius = Line(ORIGIN, circle.get_right())
|
|
|
|
radius.highlight(RED)
|
|
|
|
brace = Brace(radius, DOWN, buff = SMALL_BUFF)
|
|
|
|
radius_label = brace.get_text(
|
|
|
|
str(self.max_lattice_point_radius),
|
|
|
|
buff = SMALL_BUFF
|
|
|
|
)
|
|
|
|
radius_label.add_background_rectangle()
|
|
|
|
brace.add(radius_label)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
ShowCreation(circle),
|
|
|
|
Rotating(radius, about_point = ORIGIN),
|
|
|
|
run_time = 2,
|
|
|
|
rate_func = smooth,
|
|
|
|
)
|
|
|
|
self.play(FadeIn(brace))
|
|
|
|
self.add_foreground_mobject(brace)
|
2017-05-09 23:00:30 -07:00
|
|
|
self.draw_lattice_points()
|
|
|
|
self.dither()
|
2017-05-10 13:39:45 -07:00
|
|
|
self.play(*map(FadeOut, [brace, radius]))
|
|
|
|
|
|
|
|
self.circle = circle
|
2017-05-09 14:54:58 -07:00
|
|
|
|
2017-05-10 13:39:45 -07:00
|
|
|
def turn_points_int_units_of_area(self):
|
|
|
|
square = Square(fill_opacity = 0.9)
|
|
|
|
unit_line = Line(
|
|
|
|
self.plane.coords_to_point(0, 0),
|
|
|
|
self.plane.coords_to_point(1, 0),
|
|
|
|
)
|
|
|
|
square.scale_to_fit_width(unit_line.get_width())
|
|
|
|
squares = VGroup(*[
|
|
|
|
square.copy().move_to(point)
|
|
|
|
for point in self.lattice_points
|
|
|
|
])
|
|
|
|
squares.gradient_highlight(BLUE_E, GREEN_E)
|
|
|
|
squares.set_stroke(WHITE, 1)
|
|
|
|
point_copies = self.lattice_points.copy()
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
ReplacementTransform(
|
|
|
|
point_copies, squares,
|
|
|
|
run_time = 3,
|
|
|
|
submobject_mode = "lagged_start",
|
|
|
|
lag_factor = 4,
|
|
|
|
),
|
|
|
|
Animation(self.lattice_points)
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(FadeOut(squares), Animation(self.lattice_points))
|
|
|
|
|
|
|
|
def write_pi_R_squared(self):
|
|
|
|
equations = VGroup(*[
|
|
|
|
VGroup(
|
|
|
|
TextMobject(
|
|
|
|
"\\# Lattice points\\\\",
|
|
|
|
"within radius ", R,
|
|
|
|
alignment = ""
|
|
|
|
),
|
|
|
|
TexMobject(
|
|
|
|
"\\approx \\pi", "(", R, ")^2"
|
|
|
|
)
|
|
|
|
).arrange_submobjects(RIGHT)
|
|
|
|
for R in "10", "1{,}000{,}000", "R"
|
|
|
|
])
|
|
|
|
radius_10_eq, radius_million_eq, radius_R_eq = equations
|
|
|
|
for eq in equations:
|
|
|
|
for tex_mob in eq:
|
|
|
|
tex_mob.highlight_by_tex("0", BLUE)
|
|
|
|
radius_10_eq.to_corner(UP+LEFT)
|
|
|
|
radius_million_eq.next_to(radius_10_eq, DOWN, LARGE_BUFF)
|
|
|
|
radius_million_eq.to_edge(LEFT)
|
|
|
|
brace = Brace(radius_million_eq, DOWN)
|
|
|
|
brace.add(brace.get_text("More accurate"))
|
|
|
|
brace.highlight(YELLOW)
|
|
|
|
|
|
|
|
background = FullScreenFadeRectangle(opacity = 0.9)
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
FadeIn(background),
|
|
|
|
Write(radius_10_eq)
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
self.play(ReplacementTransform(
|
|
|
|
radius_10_eq.copy(),
|
|
|
|
radius_million_eq
|
|
|
|
))
|
|
|
|
self.play(FadeIn(brace))
|
|
|
|
self.dither(3)
|
|
|
|
|
|
|
|
self.radius_10_eq = radius_10_eq
|
|
|
|
self.million_group = VGroup(radius_million_eq, brace)
|
|
|
|
self.radius_R_eq = radius_R_eq
|
|
|
|
|
|
|
|
def allude_to_alternate_counting_method(self):
|
|
|
|
alt_count = TextMobject(
|
|
|
|
"(...something else...)", "$R^2$", "=",
|
|
|
|
arg_separator = ""
|
|
|
|
)
|
|
|
|
alt_count.to_corner(UP+LEFT)
|
|
|
|
alt_count.highlight_by_tex("something", MAROON_B)
|
|
|
|
self.radius_R_eq.next_to(alt_count, RIGHT)
|
|
|
|
|
|
|
|
final_group = VGroup(
|
|
|
|
alt_count.get_part_by_tex("something"),
|
|
|
|
self.radius_R_eq[1].get_part_by_tex("pi"),
|
|
|
|
).copy()
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
FadeOut(self.million_group),
|
|
|
|
Write(alt_count),
|
|
|
|
ReplacementTransform(
|
|
|
|
self.radius_10_eq,
|
|
|
|
self.radius_R_eq
|
|
|
|
)
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
self.play(
|
|
|
|
final_group.arrange_submobjects, RIGHT,
|
|
|
|
final_group.next_to, ORIGIN, UP
|
|
|
|
)
|
|
|
|
rect = BackgroundRectangle(final_group)
|
|
|
|
self.play(FadeIn(rect), Animation(final_group))
|
|
|
|
self.dither(2)
|
|
|
|
|
|
|
|
class SoYouPlay(TeacherStudentsScene):
|
|
|
|
def construct(self):
|
|
|
|
self.teacher_says(
|
|
|
|
"So you play!",
|
|
|
|
run_time = 2
|
|
|
|
)
|
|
|
|
self.change_student_modes("happy", "thinking", "hesitant")
|
|
|
|
self.dither()
|
|
|
|
self.look_at(Dot().to_corner(UP+LEFT))
|
|
|
|
self.dither(3)
|
|
|
|
|
|
|
|
class CountThroughRings(LatticePointScene):
|
|
|
|
CONFIG = {
|
2017-05-10 17:22:26 -07:00
|
|
|
"example_coords" : (3, 2),
|
|
|
|
"num_rings_to_show_explicitly" : 7,
|
2017-05-10 13:39:45 -07:00
|
|
|
"x_radius" : 15,
|
2017-05-10 17:22:26 -07:00
|
|
|
|
2017-05-10 13:39:45 -07:00
|
|
|
"plane_center" : 2*RIGHT,
|
|
|
|
"max_lattice_point_radius" : 5,
|
|
|
|
}
|
|
|
|
def construct(self):
|
|
|
|
self.add_lattice_points()
|
|
|
|
self.preview_rings()
|
2017-05-10 17:22:26 -07:00
|
|
|
self.isolate_single_ring()
|
2017-05-10 13:39:45 -07:00
|
|
|
self.show_specific_lattice_point_distance()
|
|
|
|
self.count_through_rings()
|
|
|
|
|
|
|
|
def add_lattice_points(self):
|
|
|
|
big_circle = self.get_circle()
|
|
|
|
self.add(big_circle)
|
|
|
|
self.add(self.lattice_points)
|
|
|
|
self.big_circle = big_circle
|
|
|
|
|
|
|
|
def preview_rings(self):
|
|
|
|
radii = list(set([
|
|
|
|
np.sqrt(p.r_squared) for p in self.lattice_points
|
|
|
|
]))
|
|
|
|
radii.sort()
|
|
|
|
circles = VGroup(*[
|
|
|
|
self.get_circle(radius = r)
|
|
|
|
for r in radii
|
|
|
|
])
|
|
|
|
circles.set_stroke(width = 2)
|
|
|
|
|
|
|
|
self.add_foreground_mobject(self.lattice_points)
|
|
|
|
self.play(FadeIn(circles))
|
|
|
|
self.play(LaggedStart(
|
|
|
|
ApplyMethod,
|
|
|
|
circles,
|
|
|
|
arg_creator = lambda m : (m.set_stroke, PINK, 4),
|
|
|
|
rate_func = there_and_back,
|
|
|
|
))
|
|
|
|
self.dither()
|
|
|
|
self.remove_foreground_mobject(self.lattice_points)
|
2017-05-09 14:54:58 -07:00
|
|
|
|
2017-05-10 17:22:26 -07:00
|
|
|
digest_locals(self, ["circles", "radii"])
|
|
|
|
|
|
|
|
def isolate_single_ring(self):
|
|
|
|
x, y = self.example_coords
|
|
|
|
example_circle = self.circles[
|
|
|
|
self.radii.index(np.sqrt(x**2 + y**2))
|
|
|
|
]
|
|
|
|
self.circles.remove(example_circle)
|
|
|
|
points_on_example_circle = self.get_lattice_points_on_r_squared_circle(
|
|
|
|
x**2 + y**2
|
|
|
|
).copy()
|
|
|
|
|
|
|
|
self.play(
|
|
|
|
FadeOut(self.circles),
|
|
|
|
self.lattice_points.set_fill, GREY, 0.5,
|
|
|
|
Animation(points_on_example_circle)
|
|
|
|
)
|
|
|
|
self.dither()
|
2017-05-09 14:54:58 -07:00
|
|
|
|
2017-05-10 17:22:26 -07:00
|
|
|
digest_locals(self, ["points_on_example_circle", "example_circle"])
|
2017-05-09 14:54:58 -07:00
|
|
|
|
2017-05-10 13:39:45 -07:00
|
|
|
def show_specific_lattice_point_distance(self):
|
2017-05-10 17:22:26 -07:00
|
|
|
x, y = self.example_coords
|
|
|
|
dot = Dot(
|
|
|
|
self.plane.coords_to_point(x, y),
|
|
|
|
color = self.dot_color,
|
|
|
|
radius = self.dot_radius
|
|
|
|
)
|
|
|
|
label = TexMobject("(a, b)")
|
|
|
|
num_label = TexMobject(str(self.example_coords))
|
|
|
|
for mob in label, num_label:
|
|
|
|
mob.add_background_rectangle()
|
|
|
|
mob.next_to(dot, UP + RIGHT, SMALL_BUFF)
|
|
|
|
a, b = label[1][1].copy(), label[1][3].copy()
|
|
|
|
|
|
|
|
x_spot = self.plane.coords_to_point(x, 0)
|
|
|
|
radial_line = Line(self.plane_center, dot)
|
|
|
|
h_line = Line(self.plane_center, x_spot)
|
|
|
|
h_line.highlight(GREEN)
|
|
|
|
v_line = Line(x_spot, dot)
|
|
|
|
v_line.highlight(RED)
|
|
|
|
|
|
|
|
distance = TexMobject("\\sqrt{a^2 + b^2}")
|
|
|
|
distance_num = TexMobject("\\sqrt{%d}"%(x**2 + y**2))
|
|
|
|
for mob in distance, distance_num:
|
|
|
|
mob.scale(0.75)
|
|
|
|
mob.add_background_rectangle()
|
|
|
|
mob.next_to(radial_line.get_center(), UP, SMALL_BUFF)
|
|
|
|
mob.rotate(
|
|
|
|
radial_line.get_angle(),
|
|
|
|
about_point = mob.get_bottom()
|
|
|
|
)
|
|
|
|
|
|
|
|
self.play(Write(label))
|
|
|
|
self.play(
|
|
|
|
ApplyMethod(a.next_to, h_line, DOWN, SMALL_BUFF),
|
|
|
|
ApplyMethod(b.next_to, v_line, RIGHT, SMALL_BUFF),
|
|
|
|
ShowCreation(h_line),
|
|
|
|
ShowCreation(v_line),
|
|
|
|
)
|
|
|
|
self.play(ShowCreation(radial_line))
|
|
|
|
self.play(Write(distance))
|
|
|
|
self.dither(2)
|
|
|
|
|
|
|
|
a_num, b_num = [
|
|
|
|
TexMobject(str(coord))[0]
|
|
|
|
for coord in self.example_coords
|
|
|
|
]
|
|
|
|
a_num.move_to(a, UP)
|
|
|
|
b_num.move_to(b, LEFT)
|
|
|
|
self.play(
|
|
|
|
Transform(label, num_label),
|
|
|
|
Transform(a, a_num),
|
|
|
|
Transform(b, b_num),
|
|
|
|
)
|
|
|
|
self.dither()
|
|
|
|
self.play(Transform(distance, distance_num))
|
|
|
|
self.dither(3)
|
|
|
|
self.play(*map(FadeOut, [
|
|
|
|
self.example_circle, self.points_on_example_circle,
|
|
|
|
distance, a, b,
|
|
|
|
radial_line, h_line, v_line,
|
|
|
|
label
|
|
|
|
]))
|
2017-05-09 14:54:58 -07:00
|
|
|
|
2017-05-10 13:39:45 -07:00
|
|
|
def count_through_rings(self):
|
2017-05-10 17:22:26 -07:00
|
|
|
counts = [
|
|
|
|
len(self.get_lattice_points_on_r_squared_circle(N))
|
|
|
|
for N in range(self.max_lattice_point_radius**2 + 1)
|
|
|
|
]
|
|
|
|
left_list = VGroup(*[
|
|
|
|
TexMobject(
|
|
|
|
"\\sqrt{%d} \\Rightarrow"%n, str(count)
|
|
|
|
)
|
|
|
|
for n, count in zip(
|
|
|
|
range(self.num_rings_to_show_explicitly),
|
|
|
|
counts
|
|
|
|
)
|
|
|
|
])
|
|
|
|
left_counts = VGroup()
|
|
|
|
left_roots = VGroup()
|
|
|
|
for mob in left_list:
|
|
|
|
mob[1].highlight(YELLOW)
|
|
|
|
left_counts.add(VGroup(mob[1]))
|
|
|
|
mob.add_background_rectangle()
|
|
|
|
left_roots.add(VGroup(mob[0], mob[1][0]))
|
|
|
|
|
|
|
|
left_list.arrange_submobjects(
|
|
|
|
DOWN,
|
|
|
|
buff = MED_LARGE_BUFF,
|
|
|
|
aligned_edge = LEFT,
|
|
|
|
)
|
|
|
|
left_list.to_corner(UP + LEFT)
|
|
|
|
|
|
|
|
top_list = VGroup(*[
|
|
|
|
TexMobject("%d, "%count)
|
|
|
|
for count in counts
|
|
|
|
])
|
|
|
|
top_list.highlight(YELLOW)
|
|
|
|
top_list.arrange_submobjects(RIGHT, aligned_edge = DOWN)
|
|
|
|
top_list.scale_to_fit_width(2*SPACE_WIDTH - MED_LARGE_BUFF)
|
|
|
|
top_list.to_edge(UP, buff = SMALL_BUFF)
|
|
|
|
top_rect = BackgroundRectangle(top_list)
|
|
|
|
|
|
|
|
for r_squared, count_mob, root in zip(it.count(), left_counts, left_roots):
|
|
|
|
self.show_ring_count(
|
|
|
|
r_squared,
|
|
|
|
count_mob,
|
|
|
|
added_anims = [FadeIn(root)]
|
|
|
|
)
|
|
|
|
self.dither(2)
|
|
|
|
self.play(
|
|
|
|
FadeOut(left_roots),
|
|
|
|
FadeIn(top_rect),
|
|
|
|
*[
|
|
|
|
ReplacementTransform(
|
|
|
|
lc, VGroup(tc),
|
|
|
|
path_arc = np.pi/2
|
|
|
|
)
|
|
|
|
for lc, tc in zip(left_counts, top_list)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
for r_squared in range(len(left_counts), self.max_lattice_point_radius**2 + 1):
|
|
|
|
self.show_ring_count(
|
|
|
|
r_squared, top_list[r_squared],
|
|
|
|
)
|
|
|
|
self.dither(3)
|
|
|
|
|
|
|
|
|
|
|
|
def show_ring_count(
|
|
|
|
self, radius_squared, target,
|
|
|
|
added_anims = None,
|
|
|
|
run_time = 1
|
|
|
|
):
|
|
|
|
added_anims = added_anims or []
|
|
|
|
radius = np.sqrt(radius_squared)
|
|
|
|
points = self.get_lattice_points_on_r_squared_circle(radius_squared)
|
|
|
|
points.save_state()
|
|
|
|
circle = self.get_circle(radius)
|
|
|
|
radial_line = Line(
|
|
|
|
self.plane_center, self.plane.coords_to_point(radius, 0),
|
|
|
|
color = RED
|
|
|
|
)
|
|
|
|
root = TexMobject("\\sqrt{%d}"%radius_squared)
|
|
|
|
root.add_background_rectangle()
|
|
|
|
root.scale_to_fit_width(
|
|
|
|
min(0.7*radial_line.get_width(), root.get_width())
|
|
|
|
)
|
|
|
|
root.next_to(radial_line, DOWN, SMALL_BUFF)
|
|
|
|
if not hasattr(self, "little_circle"):
|
|
|
|
self.little_circle = circle
|
|
|
|
if not hasattr(self, "radial_line"):
|
|
|
|
self.radial_line = radial_line
|
|
|
|
if not hasattr(self, "root"):
|
|
|
|
self.root = root
|
|
|
|
if hasattr(self, "last_points"):
|
|
|
|
added_anims += [self.last_points.restore]
|
|
|
|
self.last_points = points
|
|
|
|
|
|
|
|
if radius_squared == 0:
|
|
|
|
points.set_fill(YELLOW, 1)
|
|
|
|
self.play(
|
|
|
|
DrawBorderThenFill(points, stroke_color = PINK),
|
|
|
|
*added_anims,
|
|
|
|
run_time = run_time
|
|
|
|
)
|
|
|
|
self.play(ReplacementTransform(
|
|
|
|
points.copy(), target
|
|
|
|
))
|
|
|
|
return
|
|
|
|
points.set_fill(YELLOW, 1)
|
|
|
|
self.play(
|
|
|
|
Transform(self.little_circle, circle),
|
|
|
|
Transform(self.radial_line, radial_line),
|
|
|
|
Transform(self.root, root),
|
|
|
|
DrawBorderThenFill(
|
|
|
|
points,
|
|
|
|
stroke_width = 4,
|
|
|
|
stroke_color = PINK,
|
|
|
|
),
|
|
|
|
*added_anims,
|
|
|
|
run_time = run_time
|
|
|
|
)
|
|
|
|
self.dither(run_time)
|
|
|
|
if len(points) > 0:
|
|
|
|
mover = points.copy()
|
|
|
|
else:
|
|
|
|
mover = VectorizedPoint(self.plane_center)
|
|
|
|
self.play(ReplacementTransform(mover, target, run_time = run_time))
|
2017-05-09 14:54:58 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|