mirror of
https://github.com/3b1b/manim.git
synced 2025-07-30 21:44:19 +08:00
True end of Music and Measure draft 1
This commit is contained in:
@ -98,10 +98,6 @@ class ImageMobject(Mobject):
|
|||||||
points *= 2 * SPACE_WIDTH / width
|
points *= 2 * SPACE_WIDTH / width
|
||||||
self.add_points(points, rgbs = rgbs)
|
self.add_points(points, rgbs = rgbs)
|
||||||
|
|
||||||
def should_buffer_points(self):
|
|
||||||
# potentially changed in subclasses
|
|
||||||
return False
|
|
||||||
|
|
||||||
class Face(ImageMobject):
|
class Face(ImageMobject):
|
||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
"mode" : "simple",
|
"mode" : "simple",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import itertools as it
|
import itertools as it
|
||||||
|
import operator as op
|
||||||
import os
|
import os
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from random import random
|
from random import random
|
||||||
@ -7,6 +8,7 @@ from copy import deepcopy
|
|||||||
from colour import Color
|
from colour import Color
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
|
|
||||||
from constants import *
|
from constants import *
|
||||||
from helpers import *
|
from helpers import *
|
||||||
import displayer as disp
|
import displayer as disp
|
||||||
@ -312,10 +314,6 @@ class Mobject(object):
|
|||||||
return color
|
return color
|
||||||
|
|
||||||
### Stuff subclasses should deal with ###
|
### Stuff subclasses should deal with ###
|
||||||
def should_buffer_points(self):
|
|
||||||
# potentially changed in subclasses
|
|
||||||
return GENERALLY_BUFFER_POINTS
|
|
||||||
|
|
||||||
def generate_points(self):
|
def generate_points(self):
|
||||||
#Typically implemented in subclass, unless purposefully left blank
|
#Typically implemented in subclass, unless purposefully left blank
|
||||||
pass
|
pass
|
||||||
@ -371,6 +369,11 @@ class CompoundMobject(Mobject):
|
|||||||
for mobject in mobjects:
|
for mobject in mobjects:
|
||||||
self.original_mobs_num_points.append(mobject.points.shape[0])
|
self.original_mobs_num_points.append(mobject.points.shape[0])
|
||||||
self.add_points(mobject.points, mobject.rgbs)
|
self.add_points(mobject.points, mobject.rgbs)
|
||||||
|
self.should_buffer_points = reduce(
|
||||||
|
op.and_,
|
||||||
|
[m.should_buffer_points for m in mobjects],
|
||||||
|
GENERALLY_BUFFER_POINTS
|
||||||
|
)
|
||||||
|
|
||||||
def split(self):
|
def split(self):
|
||||||
result = []
|
result = []
|
||||||
|
@ -110,7 +110,10 @@ class Piano(ImageMobject):
|
|||||||
left = self.get_left()[0]
|
left = self.get_left()[0]
|
||||||
keys = []
|
keys = []
|
||||||
for count in range(14):
|
for count in range(14):
|
||||||
key = Mobject(color = "white")
|
key = Mobject(
|
||||||
|
color = "white",
|
||||||
|
should_buffer_points = False
|
||||||
|
)
|
||||||
x0 = left + count*self.ivory_jump
|
x0 = left + count*self.ivory_jump
|
||||||
x1 = x0 + self.ivory_jump
|
x1 = x0 + self.ivory_jump
|
||||||
key.add_points(
|
key.add_points(
|
||||||
@ -380,7 +383,32 @@ class ChallengeOne(Scene):
|
|||||||
)
|
)
|
||||||
for vib in vibrations:
|
for vib in vibrations:
|
||||||
vib.set_run_time(3.0)
|
vib.set_run_time(3.0)
|
||||||
self.play(bottom_vibration, top_vib_1)
|
self.play(bottom_vibration, top_vib_1)
|
||||||
|
|
||||||
|
class JustByAnalyzingTheNumber(Scene):
|
||||||
|
def construct(self):
|
||||||
|
nums = [
|
||||||
|
1.5,
|
||||||
|
np.sqrt(2),
|
||||||
|
2**(5/12.),
|
||||||
|
4/3.,
|
||||||
|
1.2020569031595942,
|
||||||
|
]
|
||||||
|
last = None
|
||||||
|
r_equals = tex_mobject("r=").shift(2*LEFT)
|
||||||
|
self.add(r_equals)
|
||||||
|
for num in nums:
|
||||||
|
mob = tex_mobject(str(num)).next_to(r_equals)
|
||||||
|
mob.highlight()
|
||||||
|
mob.sort_points()
|
||||||
|
if last:
|
||||||
|
self.play(DelayByOrder(Transform(last, mob, run_time = 0.5)))
|
||||||
|
self.remove(last)
|
||||||
|
self.add(mob)
|
||||||
|
else:
|
||||||
|
self.add(mob)
|
||||||
|
self.dither()
|
||||||
|
last = mob
|
||||||
|
|
||||||
class QuestionAndAnswer(Scene):
|
class QuestionAndAnswer(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
@ -430,6 +458,7 @@ class PlaySimpleRatio(Scene):
|
|||||||
(Fraction(8, 5), "skyblue"),
|
(Fraction(8, 5), "skyblue"),
|
||||||
(Fraction(211, 198), "orange"),
|
(Fraction(211, 198), "orange"),
|
||||||
(Fraction(1093, 826), "red"),
|
(Fraction(1093, 826), "red"),
|
||||||
|
((np.exp(np.pi)-np.pi)/15, "#7e008e")
|
||||||
]
|
]
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def args_to_string(fraction, color):
|
def args_to_string(fraction, color):
|
||||||
@ -444,9 +473,18 @@ class PlaySimpleRatio(Scene):
|
|||||||
num_periods = fraction, run_time = 5.0,
|
num_periods = fraction, run_time = 5.0,
|
||||||
center = 2*UP, color = color
|
center = 2*UP, color = color
|
||||||
)
|
)
|
||||||
self.add(fraction_mobject(fraction).shift(0.5*UP))
|
if isinstance(fraction, Fraction):
|
||||||
|
mob = fraction_mobject(fraction).shift(0.5*UP)
|
||||||
|
else:
|
||||||
|
mob = tex_mobject("\\frac{e^\\pi - \\pi}{15} \\approx \\frac{4}{3}")
|
||||||
|
mob.shift(0.5*UP)
|
||||||
|
self.add(mob)
|
||||||
self.play(string1, string2)
|
self.play(string1, string2)
|
||||||
|
|
||||||
|
class MostRationalsSoundBad(Scene):
|
||||||
|
def construct(self):
|
||||||
|
self.add(text_mobject("Most rational numbers sound bad!"))
|
||||||
|
|
||||||
class FlashOnXProximity(Animation):
|
class FlashOnXProximity(Animation):
|
||||||
def __init__(self, mobject, x_val, *close_mobjects, **kwargs):
|
def __init__(self, mobject, x_val, *close_mobjects, **kwargs):
|
||||||
self.x_val = x_val
|
self.x_val = x_val
|
||||||
@ -572,6 +610,26 @@ class IrrationalGang(Scene):
|
|||||||
self.play(BlinkPiCreature(randy))
|
self.play(BlinkPiCreature(randy))
|
||||||
|
|
||||||
|
|
||||||
|
class ConstructPiano(Scene):
|
||||||
|
def construct(self):
|
||||||
|
piano = Piano()
|
||||||
|
keys = piano.split()
|
||||||
|
anims = []
|
||||||
|
askew = deepcopy(keys[-1])
|
||||||
|
keys[-1].rotate_in_place(np.pi/5)
|
||||||
|
for key in keys:
|
||||||
|
key.should_buffer_points = False
|
||||||
|
key_copy = deepcopy(key).to_corner(DOWN+LEFT)
|
||||||
|
key_copy.scale_in_place(0.25)
|
||||||
|
key_copy.shift(1.8*random.random()*SPACE_WIDTH*RIGHT)
|
||||||
|
key_copy.shift(1.8*random.random()*SPACE_HEIGHT*UP)
|
||||||
|
key_copy.rotate(2*np.pi*random.random())
|
||||||
|
anims.append(Transform(key_copy, key))
|
||||||
|
self.play(*anims, run_time = 3.0)
|
||||||
|
self.dither()
|
||||||
|
self.play(Transform(anims[-1].mobject, askew))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
class PianoTuning(Scene):
|
class PianoTuning(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
@ -629,12 +687,22 @@ class PianoTuning(Scene):
|
|||||||
approximate_form = tex_mobject("\\approx"+str(2**(float(half_steps)/12)))
|
approximate_form = tex_mobject("\\approx"+str(2**(float(half_steps)/12)))
|
||||||
approximate_form.scale(0.75)
|
approximate_form.scale(0.75)
|
||||||
approximate_form.next_to(ratio)
|
approximate_form.next_to(ratio)
|
||||||
|
if interval == 5:
|
||||||
|
num_den = (3, 2)
|
||||||
|
elif interval == 4:
|
||||||
|
num_den = (4, 3)
|
||||||
|
should_be = text_mobject("Should be $\\frac{%d}{%d}$"%num_den)
|
||||||
|
should_be.next_to(u_brace, DOWN)
|
||||||
|
|
||||||
self.play(ApplyMethod(low.highlight, colors[0]))
|
self.play(ApplyMethod(low.highlight, colors[0]))
|
||||||
self.play(
|
self.play(
|
||||||
ApplyMethod(high.highlight, colors[interval]),
|
ApplyMethod(high.highlight, colors[interval]),
|
||||||
Transform(Point(u_brace.get_left()), u_brace),
|
Transform(Point(u_brace.get_left()), u_brace),
|
||||||
)
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(ShimmerIn(should_be))
|
||||||
|
self.dither()
|
||||||
|
self.remove(should_be)
|
||||||
terms = product.split()
|
terms = product.split()
|
||||||
for term, semicircle in zip(terms, semicircles):
|
for term, semicircle in zip(terms, semicircles):
|
||||||
self.add(term, semicircle)
|
self.add(term, semicircle)
|
||||||
@ -702,14 +770,15 @@ class PowersOfTwelfthRoot(Scene):
|
|||||||
class SupposeThereIsASavant(Scene):
|
class SupposeThereIsASavant(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
words = "Suppose there is a musical savant " + \
|
words = "Suppose there is a musical savant " + \
|
||||||
"who find pleasure in all pairs of " + \
|
"who finds pleasure in all pairs of " + \
|
||||||
"notes whose frequencies have a rational ratio"
|
"notes whose frequencies have a rational ratio"
|
||||||
words = text_mobject(words.split(" ")).split()
|
words = words.split(" ")
|
||||||
words[4].highlight()
|
word_mobs = text_mobject(words).split()
|
||||||
words[5].highlight()
|
word_mobs[4].highlight()
|
||||||
for word in words:
|
word_mobs[5].highlight()
|
||||||
self.add(word)
|
for word, word_mob in zip(words, word_mobs):
|
||||||
self.dither(0.2)
|
self.add(word_mob)
|
||||||
|
self.dither(0.1*len(word))
|
||||||
|
|
||||||
class AllValuesBetween1And2(NumberLineScene):
|
class AllValuesBetween1And2(NumberLineScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
@ -771,6 +840,10 @@ class AllValuesBetween1And2(NumberLineScene):
|
|||||||
self.dither(0.5)
|
self.dither(0.5)
|
||||||
|
|
||||||
|
|
||||||
|
class ChallengeTwo(Scene):
|
||||||
|
def construct(self):
|
||||||
|
self.add(text_mobject("Challenge #2"))
|
||||||
|
|
||||||
class CoveringSetsWithOpenIntervals(IntervalScene):
|
class CoveringSetsWithOpenIntervals(IntervalScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
IntervalScene.construct(self)
|
IntervalScene.construct(self)
|
||||||
@ -804,12 +877,12 @@ class CoveringSetsWithOpenIntervals(IntervalScene):
|
|||||||
class DefineOpenInterval(IntervalScene):
|
class DefineOpenInterval(IntervalScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
IntervalScene.construct(self)
|
IntervalScene.construct(self)
|
||||||
open_interval, line = self.add_open_interval(0.5, 0.05, run_time = 1.0)
|
open_interval, line = self.add_open_interval(0.5, 0.75, run_time = 1.0)
|
||||||
left, right = open_interval.get_left(), open_interval.get_right()
|
left, right = open_interval.get_left(), open_interval.get_right()
|
||||||
a, less_than1, x, less_than2, b = \
|
a, less_than1, x, less_than2, b = \
|
||||||
tex_mobject(["a", "<", "x", "<", "b"]).shift(UP).split()
|
tex_mobject(["a", "<", "x", "<", "b"]).shift(UP).split()
|
||||||
left_arrow = Arrow(a, left)
|
left_arrow = Arrow(a.get_corner(DOWN+LEFT), left)
|
||||||
right_arrow = Arrow(b, right)
|
right_arrow = Arrow(b.get_corner(DOWN+RIGHT), right)
|
||||||
|
|
||||||
self.play(*[ShimmerIn(mob) for mob in a, less_than1, x])
|
self.play(*[ShimmerIn(mob) for mob in a, less_than1, x])
|
||||||
self.play(ShowCreation(left_arrow))
|
self.play(ShowCreation(left_arrow))
|
||||||
@ -931,11 +1004,14 @@ class RationalsAreDense(IntervalScene):
|
|||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
|
class SurelyItsImpossible(Scene):
|
||||||
|
def construct(self):
|
||||||
|
self.add(text_mobject("Surely it's impossible!"))
|
||||||
|
|
||||||
class HowCanYouNotCoverEntireInterval(IntervalScene):
|
class HowCanYouNotCoverEntireInterval(IntervalScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
IntervalScene.construct(self)
|
IntervalScene.construct(self)
|
||||||
words = text_mobject("""
|
small_words = text_mobject("""
|
||||||
In case you are wondering, it is indeed true
|
In case you are wondering, it is indeed true
|
||||||
that if you cover all real numbers between 0
|
that if you cover all real numbers between 0
|
||||||
and 1 with a set of open intervals, the sum
|
and 1 with a set of open intervals, the sum
|
||||||
@ -944,7 +1020,14 @@ class HowCanYouNotCoverEntireInterval(IntervalScene):
|
|||||||
as obvious as it might seem, just try to prove
|
as obvious as it might seem, just try to prove
|
||||||
it for yourself!
|
it for yourself!
|
||||||
""")
|
""")
|
||||||
words.scale(0.5).to_corner(UP+RIGHT)
|
small_words.scale(0.5).to_corner(UP+RIGHT)
|
||||||
|
big_words = text_mobject("""
|
||||||
|
Covering all numbers from 0 to 1 \\emph{will}
|
||||||
|
force the sum of the lengths of your intervals
|
||||||
|
to be at least 1.
|
||||||
|
""")
|
||||||
|
big_words.next_to(self.number_line, DOWN, buff = 0.5)
|
||||||
|
|
||||||
ticks = self.add_fraction_ticks()
|
ticks = self.add_fraction_ticks()
|
||||||
left = self.number_line.number_to_point(0)
|
left = self.number_line.number_to_point(0)
|
||||||
right = self.number_line.number_to_point(1)
|
right = self.number_line.number_to_point(1)
|
||||||
@ -963,10 +1046,22 @@ class HowCanYouNotCoverEntireInterval(IntervalScene):
|
|||||||
Transform(tick, full_line)
|
Transform(tick, full_line)
|
||||||
for tick in ticks.split()
|
for tick in ticks.split()
|
||||||
])
|
])
|
||||||
|
self.play(ShimmerIn(big_words))
|
||||||
|
self.dither()
|
||||||
# self.play(DelayByOrder(FadeToColor(full_line, "red")))
|
# self.play(DelayByOrder(FadeToColor(full_line, "red")))
|
||||||
self.play(ShimmerIn(words))
|
self.play(ShimmerIn(small_words))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
class PauseNow(Scene):
|
||||||
|
def construct(self):
|
||||||
|
top_words = text_mobject("Try for yourself!").scale(2).shift(3*UP)
|
||||||
|
bot_words = text_mobject("""
|
||||||
|
If you've never seen this before, you will get
|
||||||
|
the most out of the solution and the intuitions
|
||||||
|
I illustrate only after pulling out a pencil and
|
||||||
|
paper and taking a wack at it yourself.
|
||||||
|
""").next_to(top_words, DOWN, buff = 0.5)
|
||||||
|
self.add(top_words, bot_words)
|
||||||
|
|
||||||
class StepsToSolution(IntervalScene):
|
class StepsToSolution(IntervalScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
@ -975,12 +1070,14 @@ class StepsToSolution(IntervalScene):
|
|||||||
steps = map(text_mobject, [
|
steps = map(text_mobject, [
|
||||||
"Enumerate all rationals in (0, 1)",
|
"Enumerate all rationals in (0, 1)",
|
||||||
"Assign one interval to each rational",
|
"Assign one interval to each rational",
|
||||||
"Choose sum of the form $\\sum_{n=1}^\\infty a_n = 1$",
|
"Choose sum of the form $\\mathlarger{\\sum}_{n=1}^\\infty a_n = 1$",
|
||||||
"Pick any $\\epsilon$ such that $0 < \\epsilon < 1$",
|
"Pick any $\\epsilon$ such that $0 < \\epsilon < 1$",
|
||||||
"Stretch the $n$th interval to have length $\\epsilon/2^n$",
|
"Stretch the $n$th interval to have length $\\epsilon/2^n$",
|
||||||
])
|
])
|
||||||
for step in steps:
|
for step in steps:
|
||||||
step.shift(DOWN)
|
step.shift(DOWN)
|
||||||
|
for step in steps[2:]:
|
||||||
|
step.shift(DOWN)
|
||||||
for step, count in zip(steps, it.count()):
|
for step, count in zip(steps, it.count()):
|
||||||
self.add(step)
|
self.add(step)
|
||||||
self.dither()
|
self.dither()
|
||||||
@ -1036,11 +1133,21 @@ class StepsToSolution(IntervalScene):
|
|||||||
def assign_intervals_to_rationals(self):
|
def assign_intervals_to_rationals(self):
|
||||||
anims = []
|
anims = []
|
||||||
for tick in self.ticks:
|
for tick in self.ticks:
|
||||||
interval = OpenInterval(tick.get_center(), self.spacing/2)
|
interval = OpenInterval(tick.get_center(), self.spacing)
|
||||||
|
interval.scale_in_place(0.5)
|
||||||
squished = deepcopy(interval).stretch_to_fit_width(0)
|
squished = deepcopy(interval).stretch_to_fit_width(0)
|
||||||
anims.append(Transform(squished, interval))
|
anims.append(Transform(squished, interval))
|
||||||
self.play(*anims)
|
self.play(*anims)
|
||||||
|
self.show_frame()
|
||||||
self.dither()
|
self.dither()
|
||||||
|
to_remove = [self.number_line] + self.number_mobs
|
||||||
|
self.play(*[
|
||||||
|
ApplyMethod(mob.shift, 2*SPACE_WIDTH*RIGHT)
|
||||||
|
for mob in to_remove
|
||||||
|
])
|
||||||
|
self.remove(*to_remove)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
self.intervals = [a.mobject for a in anims]
|
self.intervals = [a.mobject for a in anims]
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"run_time" : 2.0,
|
"run_time" : 2.0,
|
||||||
@ -1054,16 +1161,22 @@ class StepsToSolution(IntervalScene):
|
|||||||
|
|
||||||
def add_terms(self):
|
def add_terms(self):
|
||||||
self.ones = []
|
self.ones = []
|
||||||
scale_val = 0.3
|
scale_val = 0.6
|
||||||
|
plus = None
|
||||||
for count in range(1, 10):
|
for count in range(1, 10):
|
||||||
frac_bottom = tex_mobject("\\over %d"%(2**count))
|
frac_bottom = tex_mobject("\\over %d"%(2**count))
|
||||||
frac_bottom.scale(scale_val)
|
frac_bottom.scale(scale_val)
|
||||||
frac_bottom.shift(0.5*UP + (-SPACE_WIDTH+self.spacing*count)*RIGHT)
|
|
||||||
one = tex_mobject("1").scale(scale_val)
|
one = tex_mobject("1").scale(scale_val)
|
||||||
one.next_to(frac_bottom, UP, buff = 0.1)
|
one.next_to(frac_bottom, UP, buff = 0.1)
|
||||||
self.ones.append(one)
|
compound = CompoundMobject(frac_bottom, one)
|
||||||
|
if plus:
|
||||||
|
compound.next_to(plus)
|
||||||
|
else:
|
||||||
|
compound.to_edge(LEFT)
|
||||||
plus = tex_mobject("+").scale(scale_val)
|
plus = tex_mobject("+").scale(scale_val)
|
||||||
plus.next_to(frac_bottom, buff = self.spacing/4)
|
plus.next_to(compound)
|
||||||
|
frac_bottom, one = compound.split()
|
||||||
|
self.ones.append(one)
|
||||||
self.add(frac_bottom, one, plus)
|
self.add(frac_bottom, one, plus)
|
||||||
self.dither(0.2)
|
self.dither(0.2)
|
||||||
dots = tex_mobject("\\dots").scale(scale_val).next_to(plus)
|
dots = tex_mobject("\\dots").scale(scale_val).next_to(plus)
|
||||||
@ -1117,6 +1230,9 @@ class OurSumCanBeArbitrarilySmall(Scene):
|
|||||||
self.play(ShimmerIn(words[1].highlight()))
|
self.play(ShimmerIn(words[1].highlight()))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
class ProofDoesNotEqualIntuition(Scene):
|
||||||
|
def construct(self):
|
||||||
|
self.add(text_mobject("Proof $\\ne$ Intuition"))
|
||||||
|
|
||||||
class StillFeelsCounterintuitive(IntervalScene):
|
class StillFeelsCounterintuitive(IntervalScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
@ -1134,6 +1250,9 @@ class StillFeelsCounterintuitive(IntervalScene):
|
|||||||
self.play(ShowCreation(ticks))
|
self.play(ShowCreation(ticks))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
class VisualIntuition(Scene):
|
||||||
|
def construct(self):
|
||||||
|
self.add(text_mobject("Visual Intuition:"))
|
||||||
|
|
||||||
class ZoomInOnSqrt2Over2(IntervalScene):
|
class ZoomInOnSqrt2Over2(IntervalScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
@ -1192,19 +1311,31 @@ class ShiftSetupByOne(IntervalScene):
|
|||||||
self.add(epsilon_mob)
|
self.add(epsilon_mob)
|
||||||
fraction_ticks = self.add_fraction_ticks()
|
fraction_ticks = self.add_fraction_ticks()
|
||||||
self.remove(fraction_ticks)
|
self.remove(fraction_ticks)
|
||||||
all_intervals, all_lines = self.cover_fractions(
|
intervals, lines = self.cover_fractions(
|
||||||
epsilon = 0.01,
|
epsilon = 0.01,
|
||||||
num_fractions = 150,
|
num_fractions = 150,
|
||||||
run_time_per_interval = 0,
|
run_time_per_interval = 0,
|
||||||
)
|
)
|
||||||
self.remove(*all_intervals+all_lines)
|
self.remove(*intervals+lines)
|
||||||
|
for interval, frac in zip(intervals, rationals()):
|
||||||
|
interval.scale_in_place(2.0/frac.denominator)
|
||||||
|
|
||||||
intervals, lines = self.cover_fractions(epsilon = 0.01)
|
|
||||||
|
for interval in intervals[:10]:
|
||||||
|
squished = deepcopy(interval).stretch_to_fit_width(0)
|
||||||
|
self.play(Transform(squished, interval), run_time = 0.2)
|
||||||
|
self.remove(squished)
|
||||||
|
self.add(interval)
|
||||||
|
for interval in intervals[10:50]:
|
||||||
|
self.add(interval)
|
||||||
|
self.dither(0.1)
|
||||||
|
for interval in intervals[50:]:
|
||||||
|
self.add(interval)
|
||||||
self.dither()
|
self.dither()
|
||||||
mobs_shifts = [
|
mobs_shifts = [
|
||||||
(intervals+lines, UP),
|
(intervals, UP),
|
||||||
([self.number_line, new_interval], side_shift_val*LEFT),
|
([self.number_line, new_interval], side_shift_val*LEFT),
|
||||||
(intervals+lines, DOWN)
|
(intervals, DOWN)
|
||||||
]
|
]
|
||||||
for mobs, shift_val in mobs_shifts:
|
for mobs, shift_val in mobs_shifts:
|
||||||
self.play(*[
|
self.play(*[
|
||||||
@ -1245,7 +1376,7 @@ class ShiftSetupByOne(IntervalScene):
|
|||||||
|
|
||||||
self.add(words)
|
self.add(words)
|
||||||
self.dither()
|
self.dither()
|
||||||
self.remove(*intervals+lines)
|
self.remove(*intervals)
|
||||||
self.add(answer1)
|
self.add(answer1)
|
||||||
self.play(ShowCreation(fraction_ticks, run_time = 5.0))
|
self.play(ShowCreation(fraction_ticks, run_time = 5.0))
|
||||||
self.add(answer2)
|
self.add(answer2)
|
||||||
@ -1259,16 +1390,14 @@ class ShiftSetupByOne(IntervalScene):
|
|||||||
words[1].highlight()
|
words[1].highlight()
|
||||||
words[3].highlight()
|
words[3].highlight()
|
||||||
self.add(*words)
|
self.add(*words)
|
||||||
for interval, frac in zip(all_intervals, rationals()):
|
self.play(ShowCreation(
|
||||||
interval.scale_in_place(2.0/frac.denominator)
|
CompoundMobject(*intervals),
|
||||||
self.add(interval)
|
run_time = 5.0
|
||||||
self.dither(0.1)
|
))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
command_line_create_scene(MOVIE_PREFIX)
|
command_line_create_scene(MOVIE_PREFIX)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user