Refactored tex_utils, and made TexMobject proper objects

This commit is contained in:
Grant Sanderson
2015-10-28 17:18:50 -07:00
parent 468d05d049
commit e97a8708a5
24 changed files with 598 additions and 587 deletions

View File

@ -57,7 +57,7 @@ LEFT_SIDE = SPACE_WIDTH*LEFT
RIGHT_SIDE = SPACE_WIDTH*RIGHT
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
FILE_DIR = os.path.join(THIS_DIR, "files")
FILE_DIR = os.path.join(THIS_DIR, os.pardir, "animation_files")
IMAGE_DIR = os.path.join(FILE_DIR, "images")
GIF_DIR = os.path.join(FILE_DIR, "gifs")
MOVIE_DIR = os.path.join(FILE_DIR, "movies")

3
mobject/__init__.py Normal file
View File

@ -0,0 +1,3 @@
from mobject import *
from image_mobject import *
from tex_mobject import *

View File

@ -5,7 +5,6 @@ from PIL import Image
from random import random
from helpers import *
from tex_utils import tex_to_image
from mobject import Mobject
class ImageMobject(Mobject):

161
mobject/tex_mobject.py Normal file
View File

@ -0,0 +1,161 @@
from mobject import Mobject
from image_mobject import ImageMobject
from helpers import *
#TODO, Cleanup and refactor this file.
class TexMobject(Mobject):
DEFAULT_CONFIG = {
"template_tex_file" : TEMPLATE_TEX_FILE,
"color" : WHITE,
"point_thickness" : 1,
"should_center" : False,
}
def __init__(self, expression, **kwargs):
if "size" not in kwargs:
#Todo, make this more sophisticated.
if len("".join(expression)) < MAX_LEN_FOR_HUGE_TEX_FONT:
size = "\\Huge"
else:
size = "\\large"
digest_locals(self)
Mobject.__init__(self, **kwargs)
def generate_points(self):
image_files = tex_to_image_files(
self.expression,
self.size,
self.template_tex_file
)
for image_file in image_files:
self.add(ImageMobject(image_file))
if self.should_center:
self.center()
self.highlight(self.color)
class TextMobject(TexMobject):
DEFAULT_CONFIG = {
"template_tex_file" : TEMPLATE_TEXT_FILE,
"size" : "\\Large", #TODO, auto-adjust?
}
class Underbrace(TexMobject):
DEFAULT_CONFIG = {
"buff" : 0.2,
}
def __init__(self, left, right, **kwargs):
expression = "\\underbrace{%s}"%(14*"\\quad")
TexMobject.__init__(self, expression, **kwargs)
result.stretch_to_fit_width(right[0]-left[0])
result.shift(left - result.points[0] + buff*DOWN)
def tex_hash(expression, size):
return str(hash(expression + size))
def tex_to_image_files(expression, size, template_tex_file):
"""
Returns list of images for correpsonding with a list of expressions
"""
image_dir = os.path.join(TEX_IMAGE_DIR, tex_hash(expression, size))
if os.path.exists(image_dir):
return get_sorted_image_list(image_dir)
tex_file = generate_tex_file(expression, size, template_tex_file)
dvi_file = tex_to_dvi(tex_file)
return dvi_to_png(dvi_file)
def generate_tex_file(expression, size, template_tex_file):
if isinstance(expression, list):
expression = tex_expression_list_as_string(expression)
result = os.path.join(TEX_DIR, tex_hash(expression, size))+".tex"
if not os.path.exists(result):
print "Writing %s at size %s to %s"%(
"".join(expression), size, result
)
with open(template_tex_file, "r") as infile:
body = infile.read()
body = body.replace(SIZE_TO_REPLACE, size)
body = body.replace(TEX_TEXT_TO_REPLACE, expression)
with open(result, "w") as outfile:
outfile.write(body)
return result
def tex_to_dvi(tex_file):
result = tex_file.replace(".tex", ".dvi")
if not os.path.exists(filestem + ".dvi"):
commands = [
"latex",
"-interaction=batchmode",
"-output-directory=" + TEX_DIR,
tex_file,
"> /dev/null"
]
#TODO, Error check
os.system(" ".join(commands))
return result
def tex_expression_list_as_string(expression):
return "\n".join([
"\onslide<%d>{"%count + exp + "}"
for count, exp in zip(it.count(1), expression)
])
def dvi_to_png(dvi_file, regen_if_exists = False):
"""
Converts a dvi, which potentially has multiple slides, into a
directory full of enumerated pngs corresponding with these slides.
Returns a list of PIL Image objects for these images sorted as they
where in the dvi
"""
directory, filename = os.path.split(dvi_file)
name = filename.replace(".dvi", "")
images_dir = os.path.join(TEX_IMAGE_DIR, name)
if not os.path.exists(images_dir):
os.mkdir(images_dir)
if os.listdir(images_dir) == [] or regen_if_exists:
commands = [
"convert",
"-density",
str(PDF_DENSITY),
path,
"-size",
str(DEFAULT_WIDTH) + "x" + str(DEFAULT_HEIGHT),
os.path.join(images_dir, name + ".png")
]
os.system(" ".join(commands))
return get_sorted_image_list(images_dir)
def get_sorted_image_list(images_dir):
return sorted([
os.path.join(images_dir, name)
for name in os.listdir(images_dir)
if name.endswith(".png")
], cmp_enumerated_files)
def cmp_enumerated_files(name1, name2):
num1, num2 = [
int(name.split(".")[0].split("-")[-1])
for name in (name1, name2)
]
return num1 - num2

View File

@ -195,7 +195,7 @@ class DrawComplexAngleAndMagnitude(Scene):
def draw_number(self, tex_representation, number):
point = self.plane.number_to_point(number)
dot = Dot(point)
label = tex_mobject(tex_representation)
label = TexMobject(tex_representation)
max_width = 0.8*self.plane.unit_to_spatial_width
if label.get_width() > max_width:
label.scale_to_fit_width(max_width)
@ -235,17 +235,17 @@ class DrawComplexAngleAndMagnitude(Scene):
# tex_parts = tex_representation.split("+")
# elif "-" in tex_representation:
# tex_parts = tex_representation.split("-")
# x_label, y_label = map(tex_mobject, tex_parts)
# x_label, y_label = map(TexMobject, tex_parts)
# for label in x_label, y_label:
# label.scale_to_fit_height(0.5)
# x_label.next_to(x_line, point[1]*DOWN/abs(point[1]))
# y_label.next_to(y_line, point[0]*RIGHT/abs(point[0]))
norm = np.linalg.norm(point)
brace = underbrace(ORIGIN, ORIGIN+norm*RIGHT)
brace = Underbrace(ORIGIN, ORIGIN+norm*RIGHT)
if point[1] > 0:
brace.rotate(np.pi, RIGHT)
brace.rotate(np.log(number).imag)
norm_label = tex_mobject("%.1f"%abs(number))
norm_label = TexMobject("%.1f"%abs(number))
norm_label.scale(0.5)
axis = OUT if point[1] > 0 else IN
norm_label.next_to(brace, rotate_vector(point, np.pi/2, axis))

View File

@ -81,7 +81,7 @@ COUNT_TO_TIP_POS = {
}
def finger_tip_power_of_2(finger_no):
return tex_mobject(str(2**finger_no)).shift(COUNT_TO_TIP_POS[finger_no])
return TexMobject(str(2**finger_no)).shift(COUNT_TO_TIP_POS[finger_no])
class Hand(ImageMobject):
STARTING_BOTTOM_RIGHT = [4.61111111e+00, -3.98888889e+00, 9.80454690e-16]
@ -114,7 +114,7 @@ class Hand(ImageMobject):
# )
def get_algorithm():
return text_mobject(ALGORITHM_TEXT)
return TextMobject(ALGORITHM_TEXT)
def get_finger_colors():
return list(Color("yellow").range_to("red", 5))
@ -186,7 +186,7 @@ class ShowCounting(OverHand):
]
def get_counting_mob(self, count):
mob = tex_mobject(str(count))
mob = TexMobject(str(count))
mob.scale(2)
mob.shift(LEFT)
mob.to_edge(UP, buff = 0.1)
@ -199,7 +199,7 @@ class ShowFrameNum(OverHand):
for frame, count in zip(self.frames, it.count()):
print count, "of", len(self.frames)
mob = CompoundMobject(*[
tex_mobject(char).shift(0.3*x*RIGHT)
TexMobject(char).shift(0.3*x*RIGHT)
for char, x, in zip(str(count), it.count())
])
self.frames[count] = disp.paint_mobject(
@ -213,7 +213,7 @@ class CountTo1023(Scene):
lh_map = get_hand_map("left")
def get_num(count):
return CompoundMobject(*[
tex_mobject(char).shift(0.35*x*RIGHT)
TexMobject(char).shift(0.35*x*RIGHT)
for char, x, in zip(str(count), it.count())
]).center().to_edge(UP)
self.frames = [
@ -225,7 +225,7 @@ class CountTo1023(Scene):
class Introduction(Scene):
def construct(self):
words = text_mobject("""
words = TextMobject("""
First, let's see how to count
to 31 on just one hand...
""")
@ -242,10 +242,10 @@ class Introduction(Scene):
class ShowReadingRule(Scene):
def construct(self):
sample_counts = [6, 17, 27, 31]
question = text_mobject("""
question = TextMobject("""
How do you recognize what number a given configuration represents?
""", size = "\\Huge").scale(0.75).to_corner(UP+LEFT)
answer = text_mobject([
answer = TextMobject([
"Think of each finger as representing a power of 2, ",
"then add up the numbers represented by the standing fingers."
], size = "\\Huge").scale(0.75).to_corner(UP+LEFT).split()
@ -278,7 +278,7 @@ class ShowReadingRule(Scene):
count_mobs[1].shift(0.2*DOWN + 0.2*LEFT)
if num in [6, 17]:
hand.shift(0.8*LEFT)
sum_mobs = tex_mobject(
sum_mobs = TexMobject(
" + ".join([str(2**c) for c in counts]).split(" ") + ["=%d"%num]
).to_corner(UP+RIGHT).split()
self.add(hand, *count_mobs)
@ -298,7 +298,7 @@ class ShowIncrementRule(Scene):
def to_left(words):
return "\\begin{flushleft}" + words + "\\end{flushleft}"
phrases = [
text_mobject(to_left(words), size = "\\Huge").scale(0.75).to_corner(UP+LEFT)
TextMobject(to_left(words), size = "\\Huge").scale(0.75).to_corner(UP+LEFT)
for words in [
"But while you're counting, you don't need to think about powers of 2.",
"Can you see the pattern for incrementing?",
@ -337,7 +337,7 @@ class ShowIncrementRule(Scene):
self.frames += [self.frames[-1]]*int(1.0/self.frame_duration)
def get_arrow_set(self, num):
arrow = tex_mobject("\\downarrow", size = "\\Huge")
arrow = TexMobject("\\downarrow", size = "\\Huge")
arrow.highlight("green")
arrow.shift(-arrow.get_bottom())
if num == 12:
@ -368,17 +368,17 @@ class ShowIncrementRule(Scene):
class MindFindsShortcuts(Scene):
def construct(self):
words1 = text_mobject("""
words1 = TextMobject("""
Before long, your mind starts to recognize certain
patterns without needing to perform the addition.
""", size = "\\Huge").scale(0.75).to_corner(LEFT+UP)
words2 = text_mobject("""
words2 = TextMobject("""
Which makes it faster to recognize other patterns...
""", size = "\\Huge").scale(0.75).to_corner(LEFT+UP)
hand = Hand(7).scale(0.5).center().shift(DOWN+2*LEFT)
sum421 = tex_mobject("4+2+1").shift(DOWN+2*RIGHT)
seven = tex_mobject("7").shift(DOWN+6*RIGHT)
sum421 = TexMobject("4+2+1").shift(DOWN+2*RIGHT)
seven = TexMobject("7").shift(DOWN+6*RIGHT)
compound = CompoundMobject(
Arrow(hand, sum421),
sum421,
@ -393,7 +393,7 @@ class MindFindsShortcuts(Scene):
self.dither()
self.play(
Transform(compound, Arrow(hand, seven).highlight("yellow")),
ShimmerIn(text_mobject("Directly recognize").shift(1.5*DOWN+2*RIGHT))
ShimmerIn(TextMobject("Directly recognize").shift(1.5*DOWN+2*RIGHT))
)
self.dither()
@ -406,10 +406,10 @@ class MindFindsShortcuts(Scene):
hands[16].shift(LEFT)
hands[7].shift(3*RIGHT)
for num in 7, 16:
hands[num].add(tex_mobject(str(num)).shift(hands[num].get_top()+0.5*UP))
plus = tex_mobject("+").shift(DOWN + RIGHT)
equals = tex_mobject("=").shift(DOWN + 2.5*LEFT)
equals23 = tex_mobject("=23").shift(DOWN + 5.5*RIGHT)
hands[num].add(TexMobject(str(num)).shift(hands[num].get_top()+0.5*UP))
plus = TexMobject("+").shift(DOWN + RIGHT)
equals = TexMobject("=").shift(DOWN + 2.5*LEFT)
equals23 = TexMobject("=23").shift(DOWN + 5.5*RIGHT)
self.add(words2, hands[23])
self.dither()
@ -434,7 +434,7 @@ class MindFindsShortcuts(Scene):
class CountingExampleSentence(ShowCounting):
def construct(self):
words = "As an example, this is me counting the number of words in this sentence on just one hand!"
self.words = text_mobject(words.split(), size = "\\Huge").scale(0.7).to_corner(UP+LEFT, buff = 0.25).split()
self.words = TextMobject(words.split(), size = "\\Huge").scale(0.7).to_corner(UP+LEFT, buff = 0.25).split()
ShowCounting.construct(self)
def get_counting_mob(self, num):
@ -443,11 +443,11 @@ class CountingExampleSentence(ShowCounting):
class FinishCountingExampleSentence(Scene):
def construct(self):
words = "As an example, this is me counting the number of words in this sentence on just one hand!"
words = text_mobject(words, size = "\\Huge").scale(0.7).to_corner(UP+LEFT, buff = 0.25)
words = TextMobject(words, size = "\\Huge").scale(0.7).to_corner(UP+LEFT, buff = 0.25)
hand = Hand(18)
sixteen = tex_mobject("16").shift([0, 2.25, 0])
two = tex_mobject("2").shift([3, 3.65, 0])
eightteen = tex_mobject("18").shift([1.5, 2.5, 0])
sixteen = TexMobject("16").shift([0, 2.25, 0])
two = TexMobject("2").shift([3, 3.65, 0])
eightteen = TexMobject("18").shift([1.5, 2.5, 0])
eightteen.sort_points()
comp = CompoundMobject(sixteen, two)
self.add(hand, comp, words)
@ -457,18 +457,18 @@ class FinishCountingExampleSentence(Scene):
class Question(Scene):
def construct(self):
self.add(text_mobject("Left to ponder: Why does this rule for incrementing work?"))
self.add(TextMobject("Left to ponder: Why does this rule for incrementing work?"))
class TwoHandStatement(Scene):
def construct(self):
self.add(text_mobject(
self.add(TextMobject(
"With 10 fingers, you can count up to $2^{10} - 1 = 1023$..."
))
class WithToes(Scene):
def construct(self):
words = text_mobject([
words = TextMobject([
"If you were dexterous enough to use your toes as well,",
"you could count to 1,048,575"
]).split()

View File

@ -23,19 +23,19 @@ DUAL_CYCLE = [3, 4, 5, 6, 1, 0, 2, 3]
class EulersFormulaWords(Scene):
def construct(self):
self.add(tex_mobject("V-E+F=2"))
self.add(TexMobject("V-E+F=2"))
class TheTheoremWords(Scene):
def construct(self):
self.add(text_mobject("The Theorem:"))
self.add(TextMobject("The Theorem:"))
class ProofAtLastWords(Scene):
def construct(self):
self.add(text_mobject("The Proof At Last..."))
self.add(TextMobject("The Proof At Last..."))
class DualSpanningTreeWords(Scene):
def construct(self):
self.add(text_mobject("Spanning trees have duals too!"))
self.add(TextMobject("Spanning trees have duals too!"))
class PreferOtherProofDialogue(Scene):
def construct(self):
@ -63,7 +63,7 @@ class IllustrateDuality(GraphScene):
GraphScene.construct(self)
self.generate_dual_graph()
self.add(text_mobject("Duality").to_edge(UP))
self.add(TextMobject("Duality").to_edge(UP))
self.remove(*self.vertices)
def special_alpha(t):
if t > 0.5:
@ -107,11 +107,11 @@ class IntroduceGraph(GraphScene):
for pair in [(4, 5), (0, 5), (1, 5), (7, 1), (8, 3)]
]
connected, planar, graph = text_mobject([
connected, planar, graph = TextMobject([
"Connected ", "Planar ", "Graph"
]).to_edge(UP).split()
not_okay = text_mobject("Not Okay").highlight("red")
planar_explanation = text_mobject("""
not_okay = TextMobject("Not Okay").highlight("red")
planar_explanation = TextMobject("""
(``Planar'' just means we can draw it without
intersecting lines)
""", size = "\\small")
@ -162,7 +162,7 @@ class OldIntroduceGraphs(GraphScene):
self.clear()
self.add(*self.edges)
self.replace_vertices_with(Face().scale(0.4))
friends = text_mobject("Friends").scale(EDGE_ANNOTATION_SCALE_VAL)
friends = TextMobject("Friends").scale(EDGE_ANNOTATION_SCALE_VAL)
self.annotate_edges(friends.shift((0, friends.get_height()/2, 0)))
self.play(*[
CounterclockwiseTransform(vertex, Dot(point))
@ -178,7 +178,7 @@ class OldIntroduceGraphs(GraphScene):
class PlanarGraphDefinition(Scene):
def construct(self):
Not, quote, planar, end_quote = text_mobject([
Not, quote, planar, end_quote = TextMobject([
"Not \\\\", "``", "Planar", "''",
# "no matter how \\\\ hard you try"
]).split()
@ -233,9 +233,9 @@ class TerminologyFromPolyhedra(GraphScene):
])
cube.rotate(-np.pi/3, [0, 0, 1])
cube.rotate(-np.pi/3, [0, 1, 0])
dots_to_vertices = text_mobject("Dots $\\to$ Vertices").to_corner()
lines_to_edges = text_mobject("Lines $\\to$ Edges").to_corner()
regions_to_faces = text_mobject("Regions $\\to$ Faces").to_corner()
dots_to_vertices = TextMobject("Dots $\\to$ Vertices").to_corner()
lines_to_edges = TextMobject("Lines $\\to$ Edges").to_corner()
regions_to_faces = TextMobject("Regions $\\to$ Faces").to_corner()
self.clear()
# self.play(TransformAnimations(
@ -274,7 +274,7 @@ class ThreePiecesOfTerminology(GraphScene):
def construct(self):
GraphScene.construct(self)
terms = cycles, spanning_trees, dual_graphs = [
text_mobject(phrase).shift(y*UP).to_edge()
TextMobject(phrase).shift(y*UP).to_edge()
for phrase, y in [
("Cycles", 3),
("Spanning Trees", 1),
@ -355,8 +355,8 @@ class PathExamples(GraphScene):
[(0, 1), (7, 8), (5, 6),],
[(5, 0), (0, 2), (0, 1)],
]
valid_path = text_mobject("Valid \\\\ Path").highlight("green")
not_a_path = text_mobject("Not a \\\\ Path").highlight("red")
valid_path = TextMobject("Valid \\\\ Path").highlight("green")
not_a_path = TextMobject("Not a \\\\ Path").highlight("red")
for mob in valid_path, not_a_path:
mob.to_edge(UP)
kwargs = {"run_time" : 1.0}
@ -413,7 +413,7 @@ class IntroduceRandolph(GraphScene):
def construct(self):
GraphScene.construct(self)
randy = Randolph().move_to((-3, 0, 0))
name = text_mobject("Randolph")
name = TextMobject("Randolph")
self.play(Transform(
randy,
deepcopy(randy).scale(RANDOLPH_SCALE_VAL).move_to(self.points[0]),
@ -428,13 +428,13 @@ class DefineSpanningTree(GraphScene):
GraphScene.construct(self)
randy = Randolph()
randy.scale(RANDOLPH_SCALE_VAL).move_to(self.points[0])
dollar_signs = text_mobject("\\$\\$")
dollar_signs = TextMobject("\\$\\$")
dollar_signs.scale(EDGE_ANNOTATION_SCALE_VAL)
dollar_signs = CompoundMobject(*[
deepcopy(dollar_signs).shift(edge.get_center())
for edge in self.edges
])
unneeded = text_mobject("unneeded!")
unneeded = TextMobject("unneeded!")
unneeded.scale(EDGE_ANNOTATION_SCALE_VAL)
self.generate_spanning_tree()
def green_dot_at_index(index):
@ -489,8 +489,8 @@ class NamingTree(GraphScene):
branches = self.spanning_tree.split()
branches_copy = deepcopy(branches)
treeified_branches = self.treeified_spanning_tree.split()
tree = text_mobject("``Tree''").to_edge(UP)
spanning_tree = text_mobject("``Spanning Tree''").to_edge(UP)
tree = TextMobject("``Tree''").to_edge(UP)
spanning_tree = TextMobject("``Spanning Tree''").to_edge(UP)
self.add(*branches)
self.play(
@ -521,7 +521,7 @@ class DualGraph(GraphScene):
def construct(self):
GraphScene.construct(self)
self.generate_dual_graph()
self.add(text_mobject("Dual Graph").to_edge(UP).shift(2*LEFT))
self.add(TextMobject("Dual Graph").to_edge(UP).shift(2*LEFT))
self.play(*[
ShowCreation(mob)
for mob in self.dual_edges + self.dual_vertices
@ -544,7 +544,7 @@ class FacebookGraph(GraphScene):
logo.shift(0.2*LEFT + 0.1*UP)
account.add(logo).center()
account.shift(0.2*LEFT + 0.1*UP)
friends = tex_mobject(
friends = TexMobject(
"\\leftarrow \\text{friends} \\rightarrow"
).scale(0.5*EDGE_ANNOTATION_SCALE_VAL)
@ -591,13 +591,13 @@ class FacebookGraphAsAbstractSet(Scene):
"\\text{%s}&\\leftrightarrow\\text{%s}"%(names[i],names[j])
for i, j in friend_pairs
] + ["\\vdots"])
names_mob = text_mobject(names_string).shift(3*LEFT)
friends_mob = tex_mobject(
names_mob = TextMobject(names_string).shift(3*LEFT)
friends_mob = TexMobject(
friends_string, size = "\\Large"
).shift(3*RIGHT)
accounts = text_mobject("\\textbf{Accounts}")
accounts = TextMobject("\\textbf{Accounts}")
accounts.shift(3*LEFT).to_edge(UP)
friendships = text_mobject("\\textbf{Friendships}")
friendships = TextMobject("\\textbf{Friendships}")
friendships.shift(3*RIGHT).to_edge(UP)
lines = CompoundMobject(
Line(UP*SPACE_HEIGHT, DOWN*SPACE_HEIGHT),
@ -622,7 +622,7 @@ class ExamplesOfGraphs(GraphScene):
)
GraphScene.construct(self)
self.generate_regions()
objects, notions = CompoundMobject(*text_mobject(
objects, notions = CompoundMobject(*TextMobject(
["Objects \\quad\\quad ", "Thing that connects objects"]
)).to_corner().shift(0.5*RIGHT).split()
horizontal_line = Line(
@ -649,8 +649,8 @@ class ExamplesOfGraphs(GraphScene):
self.clear()
self.add(objects, notions, horizontal_line, vertical_line)
for (obj, notion), height in zip(objects_and_notions, it.count(2, -1)):
obj_mob = text_mobject(obj, size = "\\small").to_edge(LEFT)
not_mob = text_mobject(notion, size = "\\small").to_edge(LEFT)
obj_mob = TextMobject(obj, size = "\\small").to_edge(LEFT)
not_mob = TextMobject(notion, size = "\\small").to_edge(LEFT)
not_mob.shift((vert_line_x_val + SPACE_WIDTH)*RIGHT)
obj_mob.shift(height*UP)
not_mob.shift(height*UP)
@ -666,7 +666,7 @@ class ExamplesOfGraphs(GraphScene):
self.dither()
def handle_english_words(self, words1, words2):
words = map(text_mobject, ["graph", "grape", "gape", "gripe"])
words = map(TextMobject, ["graph", "grape", "gape", "gripe"])
words[0].shift(RIGHT)
words[1].shift(3*RIGHT)
words[2].shift(3*RIGHT + 2*UP)
@ -701,9 +701,9 @@ class ExamplesOfGraphs(GraphScene):
def handle_dual_graph(self, words1, words2):
words1.highlight("yellow")
words2.highlight("yellow")
connected = text_mobject("Connected")
connected = TextMobject("Connected")
connected.highlight("lightgreen")
not_connected = text_mobject("Not Connected")
not_connected = TextMobject("Not Connected")
not_connected.highlight("red")
for mob in connected, not_connected:
mob.shift(self.points[3] + UP)
@ -818,7 +818,7 @@ class EdgesAreTheSame(GraphScene):
])
self.dither()
self.add(
text_mobject("""
TextMobject("""
(Or at least I would argue they should \\\\
be thought of as the same thing.)
""", size = "\\small").to_edge(UP)
@ -839,11 +839,11 @@ class ListOfCorrespondances(Scene):
for corr in correspondances:
corr[0] += " original graph"
corr[1] += " dual graph"
arrow = tex_mobject("\\leftrightarrow", size = "\\large")
arrow = TexMobject("\\leftrightarrow", size = "\\large")
lines = []
for corr, height in zip(correspondances, it.count(3, -1)):
left = text_mobject(corr[0], size = "\\small")
right = text_mobject(corr[1], size = "\\small")
left = TextMobject(corr[0], size = "\\small")
right = TextMobject(corr[1], size = "\\small")
this_arrow = deepcopy(arrow)
for mob in left, right, this_arrow:
mob.shift(height*UP)
@ -917,7 +917,7 @@ class IntroduceMortimer(GraphScene):
self.generate_regions()
randy = Randolph().shift(LEFT)
morty = Mortimer().shift(RIGHT)
name = text_mobject("Mortimer")
name = TextMobject("Mortimer")
name.shift(morty.get_center() + 1.2*UP)
randy_path = (0, 1, 3)
morty_path = (-2, -3, -4)
@ -1031,7 +1031,7 @@ class MortimerCannotTraverseCycle(GraphScene):
morty = Mortimer().scale(RANDOLPH_SCALE_VAL)
morty.move_to(self.dual_points[dual_cycle[0]])
time_per_edge = 0.5
text = text_mobject("""
text = TextMobject("""
One of these lines must be included
in the spanning tree if those two inner
vertices are to be reached.
@ -1073,14 +1073,14 @@ class MortimerCannotTraverseCycle(GraphScene):
class TwoPropertiesOfSpanningTree(Scene):
def construct(self):
spanning, tree = text_mobject(
spanning, tree = TextMobject(
["Spanning ", "Tree"],
size = "\\Huge"
).split()
spanning_explanation = text_mobject("""
spanning_explanation = TextMobject("""
Touches every vertex
""").shift(spanning.get_center() + 2*DOWN)
tree_explanation = text_mobject("""
tree_explanation = TextMobject("""
No Cycles
""").shift(tree.get_center() + 2*UP)
@ -1111,7 +1111,7 @@ class DualSpanningTree(GraphScene):
morty.scale(RANDOLPH_SCALE_VAL)
morty.move_to(self.dual_points[0])
dual_edges = [1, 3, 4, 7, 11, 9, 13]
words = text_mobject("""
words = TextMobject("""
The red edges form a spanning tree of the dual graph!
""").to_edge(UP)
@ -1125,7 +1125,7 @@ class DualSpanningTree(GraphScene):
class TreeCountFormula(Scene):
def construct(self):
time_per_branch = 0.5
text = text_mobject("""
text = TextMobject("""
In any tree:
$$E + 1 = V$$
""")
@ -1157,7 +1157,7 @@ class TreeCountFormula(Scene):
class FinalSum(Scene):
def construct(self):
lines = tex_mobject([
lines = TexMobject([
"(\\text{Number of Randolph's Edges}) + 1 &= V \\\\ \n",
"(\\text{Number of Mortimer's Edges}) + 1 &= F \\\\ \n",
" \\Downarrow \\\\", "E","+","2","&=","V","+","F",
@ -1167,10 +1167,10 @@ class FinalSum(Scene):
self.dither()
self.dither()
symbols = V, minus, E, plus, F, equals, two = tex_mobject(
symbols = V, minus, E, plus, F, equals, two = TexMobject(
"V - E + F = 2".split(" ")
)
plus = tex_mobject("+")
plus = TexMobject("+")
anims = []
for mob, index in zip(symbols, [-3, -2, -7, -6, -1, -4, -5]):
copy = plus if index == -2 else deepcopy(mob)

View File

@ -47,7 +47,7 @@ class LogoGeneration(Scene):
lambda point: np.linalg.norm(point) < \
self.INNER_RADIUS_RATIO*self.LOGO_RADIUS
)
name = text_mobject("3Blue1Brown").center()
name = TextMobject("3Blue1Brown").center()
name.highlight("grey")
name.shift(2*DOWN)

View File

@ -76,13 +76,13 @@ NUM_INTERVAL_TICKS = 16
def divergent_sum():
return tex_mobject(DIVERGENT_SUM_TEXT, size = "\\large").scale(2)
return TexMobject(DIVERGENT_SUM_TEXT, size = "\\large").scale(2)
def convergent_sum():
return tex_mobject(CONVERGENT_SUM_TEXT, size = "\\large").scale(2)
return TexMobject(CONVERGENT_SUM_TEXT, size = "\\large").scale(2)
def underbrace(left, right):
result = tex_mobject("\\underbrace{%s}"%(14*"\\quad"))
def Underbrace(left, right):
result = TexMobject("\\Underbrace{%s}"%(14*"\\quad"))
result.stretch_to_fit_width(right[0]-left[0])
result.shift(left - result.points[0])
return result
@ -94,8 +94,8 @@ def zero_to_one_interval():
)
interval.elongate_tick_at(-INTERVAL_RADIUS, 4)
interval.elongate_tick_at(INTERVAL_RADIUS, 4)
zero = tex_mobject("0").shift(INTERVAL_RADIUS*LEFT+DOWN)
one = tex_mobject("1").shift(INTERVAL_RADIUS*RIGHT+DOWN)
zero = TexMobject("0").shift(INTERVAL_RADIUS*LEFT+DOWN)
one = TexMobject("1").shift(INTERVAL_RADIUS*RIGHT+DOWN)
return CompoundMobject(interval, zero, one)
def draw_you(with_bubble = False):
@ -132,7 +132,7 @@ class FlipThroughNumbers(Animation):
self.start_center = start_center
self.end_center = end_center
self.current_number = function(start)
mobject = tex_mobject(str(self.current_number)).shift(start_center)
mobject = TexMobject(str(self.current_number)).shift(start_center)
Animation.__init__(self, mobject, **kwargs)
def update_mobject(self, alpha):
@ -141,7 +141,7 @@ class FlipThroughNumbers(Animation):
)
if new_number != self.current_number:
self.current_number = new_number
self.mobject = tex_mobject(str(new_number)).shift(self.start_center)
self.mobject = TexMobject(str(new_number)).shift(self.start_center)
if not all(self.start_center == self.end_center):
self.mobject.center().shift(
(1-alpha)*self.start_center + alpha*self.end_center
@ -154,7 +154,7 @@ class IntroduceDivergentSum(Scene):
def construct(self):
equation = divergent_sum().split()
sum_value = None
brace = underbrace(
brace = Underbrace(
equation[0].get_boundary_point(DOWN+LEFT),
equation[1].get_boundary_point(DOWN+RIGHT)
).shift(0.2*DOWN)
@ -170,7 +170,7 @@ class IntroduceDivergentSum(Scene):
brace.to_edge(LEFT, buff = SPACE_WIDTH+min_x_coord)
if sum_value:
self.remove(sum_value)
sum_value = tex_mobject(str(2**(x+1) - 1))
sum_value = TexMobject(str(2**(x+1) - 1))
sum_value.shift(brace.get_center() + 0.5*DOWN)
self.add(brace, sum_value)
self.dither(0.75)
@ -203,9 +203,9 @@ class ClearlyNonsense(Scene):
def construct(self):
number_line = NumberLine().add_numbers()
div_sum = divergent_sum()
this_way = text_mobject("Sum goes this way...")
this_way = TextMobject("Sum goes this way...")
this_way.to_edge(LEFT).shift(RIGHT*(SPACE_WIDTH+1) + DOWN)
how_here = text_mobject("How does it end up here?")
how_here = TextMobject("How does it end up here?")
how_here.shift(1.5*UP+LEFT)
neg_1_arrow = Arrow(
(-1, 0.3, 0),
@ -237,7 +237,7 @@ class OutlineOfVideo(Scene):
def construct(self):
conv_sum = convergent_sum().scale(0.5)
div_sum = divergent_sum().scale(0.5)
overbrace = underbrace(
overbrace = Underbrace(
conv_sum.get_left(),
conv_sum.get_right()
).rotate(np.pi, RIGHT).shift(0.75*UP*conv_sum.get_height())
@ -247,14 +247,14 @@ class OutlineOfVideo(Scene):
dots.get_bottom(),
direction = UP+LEFT
)
u_brace = underbrace(div_sum.get_left(), div_sum.get_right())
u_brace = Underbrace(div_sum.get_left(), div_sum.get_right())
u_brace.shift(1.5*div_sum.get_bottom())
for mob in conv_sum, overbrace, arrow, dots:
mob.shift(2*UP)
for mob in div_sum, u_brace:
mob.shift(DOWN)
texts = [
text_mobject(words).highlight("yellow")
TextMobject(words).highlight("yellow")
for words in [
"1. Discover this",
"2. Clarify what this means",
@ -288,7 +288,7 @@ class OutlineOfVideo(Scene):
# # class ReasonsForMakingVideo(Scene):
# # def construct(self):
# # text = text_mobject([
# # text = TextMobject([
# # """
# # \\begin{itemize}
# # \\item Understand what ``$
@ -320,9 +320,9 @@ class OutlineOfVideo(Scene):
# class DiscoverAndDefine(Scene):
# def construct(self):
# sum_mob = tex_mobject("\\sum_{n = 1}^\\infty a_n")
# discover = text_mobject("What does it feel like to discover these?")
# define = text_mobject([
# sum_mob = TexMobject("\\sum_{n = 1}^\\infty a_n")
# discover = TextMobject("What does it feel like to discover these?")
# define = TextMobject([
# "What does it feel like to",
# "\\emph{define} ",
# "them?"
@ -341,7 +341,7 @@ class OutlineOfVideo(Scene):
class YouAsMathematician(Scene):
def construct(self):
you, bubble = draw_you(with_bubble = True)
explanation = text_mobject(
explanation = TextMobject(
"You as a (questionably accurate portrayal of a) mathematician.",
size = "\\small"
).shift([2, you.get_center()[1], 0])
@ -473,7 +473,7 @@ class DanceDotOnInterval(Scene):
for x in LEFT, RIGHT
]
color_range = Color("green").range_to("yellow", num_written_terms)
conv_sum = tex_mobject(sum_terms, size = "\\large").split()
conv_sum = TexMobject(sum_terms, size = "\\large").split()
self.add(interval)
self.play(*[
@ -510,7 +510,7 @@ class DanceDotOnInterval(Scene):
self.dither()
def write_partial_sums(self):
partial_sums = tex_mobject(PARTIAL_CONVERGENT_SUMS_TEXT, size = "\\small")
partial_sums = TexMobject(PARTIAL_CONVERGENT_SUMS_TEXT, size = "\\small")
partial_sums.scale(1.5).to_edge(UP)
partial_sum_parts = partial_sums.split()
partial_sum_parts[0].highlight("yellow")
@ -525,7 +525,7 @@ class DanceDotOnInterval(Scene):
class OrganizePartialSums(Scene):
def construct(self):
partial_sums = tex_mobject(PARTIAL_CONVERGENT_SUMS_TEXT, size = "\\small")
partial_sums = TexMobject(PARTIAL_CONVERGENT_SUMS_TEXT, size = "\\small")
partial_sums.scale(1.5).to_edge(UP)
partial_sum_parts = partial_sums.split()
for x in [0] + range(2, len(partial_sum_parts), 4):
@ -549,11 +549,11 @@ class OrganizePartialSums(Scene):
for mob in partial_sum_parts
if mob not in pure_sums
])
down_arrow = tex_mobject("\\downarrow")
down_arrow = TexMobject("\\downarrow")
down_arrow.to_edge(LEFT).shift(2*RIGHT+2*DOWN)
dots = tex_mobject("\\vdots")
dots = TexMobject("\\vdots")
dots.shift(down_arrow.get_center()+down_arrow.get_height()*UP)
infinite_sum = tex_mobject("".join(CONVERGENT_SUM_TEXT[:-1]), size = "\\samll")
infinite_sum = TexMobject("".join(CONVERGENT_SUM_TEXT[:-1]), size = "\\samll")
infinite_sum.scale(1.5/1.25)
infinite_sum.to_corner(DOWN+LEFT).shift(2*RIGHT)
@ -589,7 +589,7 @@ class SeeNumbersApproachOne(Scene):
class OneAndInfiniteSumAreTheSameThing(Scene):
def construct(self):
one, equals, inf_sum = tex_mobject([
one, equals, inf_sum = TexMobject([
"1", "=", "\\sum_{n=1}^\\infty \\frac{1}{2^n}"
]).split()
point = Point(equals.get_center()).highlight("black")
@ -609,12 +609,12 @@ class OneAndInfiniteSumAreTheSameThing(Scene):
class HowDoYouDefineInfiniteSums(Scene):
def construct(self):
you = draw_you().center().rewire_part_attributes()
text = text_mobject(
text = TextMobject(
["How", " do", " you,\\\\", "\\emph{define}"],
size = "\\Huge"
).shift(UP).split()
text[-1].shift(3*DOWN).highlight("skyblue")
sum_mob = tex_mobject("\\sum_{n=0}^\\infty{a_n}")
sum_mob = TexMobject("\\sum_{n=0}^\\infty{a_n}")
text[-1].shift(LEFT)
sum_mob.shift(text[-1].get_center()+2*RIGHT)
@ -633,18 +633,18 @@ class HowDoYouDefineInfiniteSums(Scene):
class LessAboutNewThoughts(Scene):
def construct(self):
words = generating, new, thoughts, to, definitions = text_mobject([
words = generating, new, thoughts, to, definitions = TextMobject([
"Generating", " new", " thoughts", "$\\rightarrow$",
"useful definitions"
], size = "\\large").split()
gen_cross = tex_mobject("\\hline").highlight("red")
gen_cross = TexMobject("\\hline").highlight("red")
new_cross = deepcopy(gen_cross)
for cross, mob in [(gen_cross, generating), (new_cross, new)]:
cross.replace(mob)
cross.stretch_to_fit_height(0.03)
disecting = text_mobject("Disecting").highlight("green")
disecting = TextMobject("Disecting").highlight("green")
disecting.shift(generating.get_center() + 0.6*UP)
old = text_mobject("old").highlight("green")
old = TextMobject("old").highlight("green")
old.shift(new.get_center()+0.6*UP)
kwargs = {"run_time" : 0.25}
@ -660,7 +660,7 @@ class LessAboutNewThoughts(Scene):
class ListOfPartialSums(Scene):
def construct(self):
all_terms = np.array(tex_mobject(
all_terms = np.array(TexMobject(
ALT_PARTIAL_SUM_TEXT,
size = "\\large"
).split())
@ -739,11 +739,11 @@ class CircleZoomInOnOne(Scene):
for n in range(10)
])
circle = Circle().shift(2*RIGHT)
text = text_mobject(
text = TextMobject(
"All but finitely many dots fall inside even the tiniest circle."
)
numbers = map(
lambda s : tex_mobject("\\frac{1}{%s}"%s),
lambda s : TexMobject("\\frac{1}{%s}"%s),
["100", "1,000,000", "g_{g_{64}}"]
)
for num in numbers + [text]:
@ -784,7 +784,7 @@ class ZoomInOnOne(Scene):
nl_with_nums = deepcopy(number_line).add_numbers()
self.play(ApplyMethod(nl_with_nums.shift, 2*LEFT))
zero, one, two = [
tex_mobject(str(n)).scale(0.5).shift(0.4*DOWN+2*(-1+n)*RIGHT)
TexMobject(str(n)).scale(0.5).shift(0.4*DOWN+2*(-1+n)*RIGHT)
for n in 0, 1, 2
]
self.play(
@ -801,7 +801,7 @@ class ZoomInOnOne(Scene):
def zoom_with_numbers(self, numbers, next_numbers):
all_numbers = map(
lambda (n, u): tex_mobject(str(n)).scale(0.5).shift(0.4*DOWN+2*u*RIGHT),
lambda (n, u): TexMobject(str(n)).scale(0.5).shift(0.4*DOWN+2*u*RIGHT),
zip(numbers+next_numbers, it.cycle([-1, 1]))
)
@ -844,7 +844,7 @@ class DefineInfiniteSum(Scene):
def put_expression_in_corner(self):
buff = 0.24
define, infinite_sum = tex_mobject([
define, infinite_sum = TexMobject([
"\\text{\\emph{Define} }",
"\\sum_{n = 0}^\\infty a_n = X"
]).split()
@ -879,10 +879,10 @@ class DefineInfiniteSum(Scene):
]
for n in range(num_terms)
])
terms = tex_mobject(term_strings, size = "\\large").split()
terms = TexMobject(term_strings, size = "\\large").split()
number_line = NumberLine()
ex_point = 2*RIGHT
ex = tex_mobject("X").shift(ex_point + LEFT + UP)
ex = TexMobject("X").shift(ex_point + LEFT + UP)
arrow = Arrow(ex_point, tail = ex.points[-1]).nudge()
for term, count in zip(terms, it.count()):
@ -928,7 +928,7 @@ class DefineInfiniteSum(Scene):
class YouJustInventedSomeMath(Scene):
def construct(self):
text = text_mobject([
text = TextMobject([
"You ", "just ", "invented\\\\", "some ", "math"
]).split()
for mob in text[:3]:
@ -959,7 +959,7 @@ class SeekMoreGeneralTruths(Scene):
"\\frac{(-1)^n}{(2n)!}",
"\\frac{2\sqrt{2}}{99^2}\\frac{(4n)!}{(n!)^4} \\cdot \\frac{26390n + 1103}{396^{4k}}",
]
sums = tex_mobject([
sums = TexMobject([
"&\\sum_{n = 0}^\\infty" + summand + "= ? \\\\"
for summand in summands
], size = "")
@ -984,7 +984,7 @@ class ChopIntervalInProportions(Scene):
num_terms = 2
left_terms, right_terms = [
[
tex_mobject("\\frac{%d}{%d}"%(k, (10**(count+1))))
TexMobject("\\frac{%d}{%d}"%(k, (10**(count+1))))
for count in range(num_terms)
]
for k in 9, 1
@ -992,19 +992,19 @@ class ChopIntervalInProportions(Scene):
if mode == "p":
num_terms = 4
prop = 0.7
left_terms = map(tex_mobject, ["(1-p)", ["p","(1-p)"]]+[
left_terms = map(TexMobject, ["(1-p)", ["p","(1-p)"]]+[
["p^%d"%(count), "(1-p)"]
for count in range(2, num_terms)
])
right_terms = map(tex_mobject, ["p"] + [
right_terms = map(TexMobject, ["p"] + [
["p", "^%d"%(count+1)]
for count in range(1, num_terms)
])
interval = zero_to_one_interval()
left = INTERVAL_RADIUS*LEFT
right = INTERVAL_RADIUS*RIGHT
left_paren = tex_mobject("(")
right_paren = tex_mobject(")").shift(right + 1.1*UP)
left_paren = TexMobject("(")
right_paren = TexMobject(")").shift(right + 1.1*UP)
curr = left.astype("float")
brace_to_replace = None
term_to_replace = None
@ -1015,7 +1015,7 @@ class ChopIntervalInProportions(Scene):
last = deepcopy(curr)
curr += 2*RIGHT*INTERVAL_RADIUS*(1-prop)*(prop**count)
braces = [
underbrace(a, b).rotate(np.pi, RIGHT)
Underbrace(a, b).rotate(np.pi, RIGHT)
for a, b in [(last, curr), (curr, right)]
]
for term, brace, count2 in zip([lt, rt], braces, it.count()):
@ -1098,7 +1098,7 @@ class ChopIntervalInProportions(Scene):
brace_to_replace = braces[1]
term_to_replace = rt
if mode == "9":
split_100 = tex_mobject("\\frac{9}{1000}+\\frac{1}{1000}")
split_100 = TexMobject("\\frac{9}{1000}+\\frac{1}{1000}")
split_100.scale(0.5)
split_100.shift(right_terms[-1].get_center())
split_100.to_edge(RIGHT)
@ -1166,7 +1166,7 @@ class PointNineRepeating(RearrangeEquation):
4 : 4,
6 : 5,
}
for term in tex_mobject(start_terms).split():
for term in TexMobject(start_terms).split():
self.add(term)
self.dither(0.5)
self.clear()
@ -1182,11 +1182,11 @@ class PointNineRepeating(RearrangeEquation):
class PlugNumbersIntoRightside(Scene):
def construct(self):
scale_factor = 1.5
lhs, rhs = tex_mobject(
lhs, rhs = TexMobject(
["1 + p + p^2 + p^3 + \\cdots = ", "\\frac{1}{1-p}"],
size = "\\large"
).scale(scale_factor).split()
rhs = tex_mobject(
rhs = TexMobject(
["1 \\over 1 - ", "p"],
size = "\\large"
).replace(rhs).split()
@ -1195,7 +1195,7 @@ class PlugNumbersIntoRightside(Scene):
"0.2", "27", "i"
]
nums = [
tex_mobject(num_string, size="\\large")
TexMobject(num_string, size="\\large")
for num_string in num_strings
]
for num, num_string in zip(nums, num_strings):
@ -1205,10 +1205,10 @@ class PlugNumbersIntoRightside(Scene):
num.highlight("green")
if num_string == "(-1)":
num.shift(0.3*RIGHT)
right_words = text_mobject(
right_words = TextMobject(
"This side makes sense for almost any value of $p$,"
).shift(2*UP)
left_words = text_mobject(
left_words = TextMobject(
"even if it seems like this side will not."
).shift(2*DOWN)
right_words.add(Arrow(
@ -1318,11 +1318,11 @@ class ListPartialDivergentSums(Scene):
"\\\\"
for n in range(num_lines)
]
terms = tex_mobject(
terms = TexMobject(
list(it.chain.from_iterable(zip(rhss, lhss))) + ["\\vdots&", ""],
size = "\\large"
).shift(RIGHT).split()
words = text_mobject("These numbers don't \\\\ approach anything")
words = TextMobject("These numbers don't \\\\ approach anything")
words.to_edge(LEFT)
arrow = Arrow(3*DOWN+2*LEFT, direction = DOWN, length = 6)
@ -1339,8 +1339,8 @@ class ListPartialDivergentSums(Scene):
class NotARobot(Scene):
def construct(self):
you = draw_you().center()
top_words = text_mobject("You are a mathematician,")
low_words = text_mobject("not a robot.")
top_words = TextMobject("You are a mathematician,")
low_words = TextMobject("not a robot.")
top_words.shift(1.5*UP)
low_words.shift(1.5*DOWN)
@ -1361,22 +1361,22 @@ class SumPowersOfTwoAnimation(Scene):
bottom_brace_left = left + 0.3*DOWN
circle = Circle().scale(dot_width[0]/2).shift(left+dot_width/2)
curr_dots = deepcopy(dot).shift(left+1.5*dot_width+dot_buff)
topbrace = underbrace(top_brace_left, right).rotate(np.pi, RIGHT)
bottombrace = underbrace(bottom_brace_left, right)
topbrace = Underbrace(top_brace_left, right).rotate(np.pi, RIGHT)
bottombrace = Underbrace(bottom_brace_left, right)
colors = Color("yellow").range_to("purple", iterations)
curr_dots.highlight(colors.next())
equation = tex_mobject(
equation = TexMobject(
"1+2+4+\\cdots+2^n=2^{n+1} - 1",
size = "\\Huge"
).shift(3*UP)
full_top_sum = tex_mobject(["1", "+2", "+4", "+8", "+16"]).split()
full_top_sum = TexMobject(["1", "+2", "+4", "+8", "+16"]).split()
self.add(equation)
self.dither()
self.add(circle, curr_dots, topbrace, bottombrace)
for n in range(1,iterations):
bottom_num = tex_mobject(str(2**n))
new_bottom_num = tex_mobject(str(2**(n+1)))
bottom_num = TexMobject(str(2**n))
new_bottom_num = TexMobject(str(2**(n+1)))
bottom_num.shift(bottombrace.get_center()+0.5*DOWN)
top_sum = CompoundMobject(*full_top_sum[:n]).center()
@ -1396,8 +1396,8 @@ class SumPowersOfTwoAnimation(Scene):
alt_bottom_num = deepcopy(bottom_num).shift(shift_val)
alt_topbrace = deepcopy(alt_bottombrace).rotate(np.pi, RIGHT)
top_sum_end.shift(alt_topbrace.get_center()+0.5*UP)
new_topbrace = underbrace(top_brace_left, right).rotate(np.pi, RIGHT)
new_bottombrace = underbrace(bottom_brace_left, right)
new_topbrace = Underbrace(top_brace_left, right).rotate(np.pi, RIGHT)
new_bottombrace = Underbrace(bottom_brace_left, right)
new_bottom_num.shift(new_bottombrace.get_center()+0.5*DOWN)
new_top_sum.shift(new_topbrace.get_center()+0.5*UP)
for exp, brace in [
@ -1446,7 +1446,7 @@ class PretendTheyDoApproachNegativeOne(RearrangeEquation):
num_lines = 6
da = "\\downarrow"
columns = [
tex_mobject("\\\\".join([
TexMobject("\\\\".join([
n_func(n)
for n in range(num_lines)
]+last_bits), size = "\\Large").to_corner(UP+LEFT)
@ -1477,15 +1477,15 @@ class DistanceBetweenRationalNumbers(Scene):
def construct(self):
locii = [2*LEFT, 2*RIGHT]
nums = [
tex_mobject(s).shift(1.3*d)
TexMobject(s).shift(1.3*d)
for s, d in zip(["\\frac{1}{2}", "3"], locii)
]
arrows = [
Arrow(direction, tail = ORIGIN)
for direction in locii
]
dist = tex_mobject("\\frac{5}{2}").scale(0.5).shift(0.5*UP)
text = text_mobject("How we define distance between rational numbers")
dist = TexMobject("\\frac{5}{2}").scale(0.5).shift(0.5*UP)
text = TextMobject("How we define distance between rational numbers")
text.to_edge(UP)
self.add(text, *nums)
self.play(*[ShowCreation(arrow) for arrow in arrows])
@ -1497,7 +1497,7 @@ class NotTheOnlyWayToOrganize(Scene):
self.play(ShowCreation(NumberLine().add_numbers()))
self.dither()
words = "Is there any other reasonable way to organize numbers?"
self.play(FadeIn(text_mobject(words).shift(2*UP)))
self.play(FadeIn(TextMobject(words).shift(2*UP)))
self.dither()
class DistanceIsAFunction(Scene):
@ -1517,7 +1517,7 @@ class DistanceIsAFunction(Scene):
dist_text = "random\\_dist"
elif mode == "2adic":
dist_text = "2\\_adic\\_dist"
dist, r_paren, arg0, comma, arg1, l_paren, equals, result = text_mobject([
dist, r_paren, arg0, comma, arg1, l_paren, equals, result = TextMobject([
dist_text, "(", "000", ",", "000", ")", "=", "000"
]).split()
point_origin = comma.get_center()+0.2*UP
@ -1551,9 +1551,9 @@ class DistanceIsAFunction(Scene):
self.dither()
example_mobs = [
(
tex_mobject(tup[0]).shift(arg0.get_center()),
tex_mobject(tup[1]).shift(arg1.get_center()),
tex_mobject(tup[2]).shift(result.get_center())
TexMobject(tup[0]).shift(arg0.get_center()),
TexMobject(tup[1]).shift(arg1.get_center()),
TexMobject(tup[2]).shift(result.get_center())
)
for tup in examples
]
@ -1578,13 +1578,13 @@ class DistanceIsAFunction(Scene):
class ShiftInvarianceNumberLine(Scene):
def construct(self):
number_line = NumberLine().add_numbers()
topbrace = underbrace(ORIGIN, 2*RIGHT).rotate(np.pi, RIGHT)
dist0 = text_mobject(["dist(", "$0$", ",", "$2$",")"])
dist1 = text_mobject(["dist(", "$2$", ",", "$4$",")"])
topbrace = Underbrace(ORIGIN, 2*RIGHT).rotate(np.pi, RIGHT)
dist0 = TextMobject(["dist(", "$0$", ",", "$2$",")"])
dist1 = TextMobject(["dist(", "$2$", ",", "$4$",")"])
for dist in dist0, dist1:
dist.shift(topbrace.get_center()+0.3*UP)
dist1.shift(2*RIGHT)
footnote = text_mobject("""
footnote = TextMobject("""
\\begin{flushleft}
*yeah yeah, I know I'm still drawing them on a line,
but until a few minutes from now I have no other way
@ -1606,19 +1606,19 @@ class ShiftInvarianceNumberLine(Scene):
class NameShiftInvarianceProperty(Scene):
def construct(self):
prop = text_mobject([
prop = TextMobject([
"dist($A$, $B$) = dist(",
"$A+x$, $B+x$",
") \\quad for all $x$"
])
mid_part = prop.split()[1]
u_brace = underbrace(
u_brace = Underbrace(
mid_part.get_boundary_point(DOWN+LEFT),
mid_part.get_boundary_point(DOWN+RIGHT)
).shift(0.3*DOWN)
label = text_mobject("Shifted values")
label = TextMobject("Shifted values")
label.shift(u_brace.get_center()+0.5*DOWN)
name = text_mobject("``Shift Invariance''")
name = TextMobject("``Shift Invariance''")
name.highlight("green").to_edge(UP)
for mob in u_brace, label:
mob.highlight("yellow")
@ -1634,7 +1634,7 @@ class TriangleInequality(Scene):
def construct(self):
symbols = ["A", "B", "C"]
locations = [2*(DOWN+LEFT), UP, 4*RIGHT]
ab, plus, bc, greater_than, ac = text_mobject([
ab, plus, bc, greater_than, ac = TextMobject([
"dist($A$, $B$)",
"$+$",
"dist($B$, $C$)",
@ -1656,7 +1656,7 @@ class TriangleInequality(Scene):
for dist, line in zip(all_dists, all_lines)
]
for symbol, loc in zip(symbols, locations):
self.add(tex_mobject(symbol).shift(loc))
self.add(TexMobject(symbol).shift(loc))
self.play(ShowCreation(ac_line), FadeIn(ac_copy))
self.dither()
self.play(*[
@ -1679,12 +1679,12 @@ class TriangleInequality(Scene):
class StruggleToFindFrameOfMind(Scene):
def construct(self):
you, bubble = draw_you(with_bubble = True)
questions = text_mobject("???", size = "\\Huge").scale(1.5)
questions = TextMobject("???", size = "\\Huge").scale(1.5)
contents = [
tex_mobject("2, 4, 8, 16, 32, \\dots \\rightarrow 0"),
text_mobject("dist(0, 2) $<$ dist(0, 64)"),
TexMobject("2, 4, 8, 16, 32, \\dots \\rightarrow 0"),
TextMobject("dist(0, 2) $<$ dist(0, 64)"),
NumberLine().sort_points(lambda p : -p[1]).add(
text_mobject("Not on a line?").shift(UP)
TextMobject("Not on a line?").shift(UP)
),
]
kwargs = {"run_time" : 0.5}
@ -1759,11 +1759,11 @@ class RoomsAndSubroomsWithNumbers(Scene):
def draw_numbers(self, zero_local, zero_one_width):
num_numbers = 5
zero = tex_mobject("0").shift(zero_local)
zero = TexMobject("0").shift(zero_local)
self.add(zero)
nums = []
for n in range(num_numbers):
num = tex_mobject(str(2**n))
num = TexMobject(str(2**n))
num.scale(1.0/(n+1))
num.shift(
zero_local+\
@ -1820,7 +1820,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
for mob, count in zip(new_power_mobs, it.count(1)):
self.center_in_closest_rect(mob, small_rects)
new_power_mobs[-1].shift(DOWN)
dots = tex_mobject("\\vdots")
dots = TexMobject("\\vdots")
dots.scale(0.5).shift(new_zero.get_center()+0.5*DOWN)
self.play(
Transform(zero, new_zero),
@ -1859,7 +1859,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
ApplyMethod(mob.shift, shift_val)
for mob in zero_copy, power_mob_copy
])
num_mobs[n] = tex_mobject(str(n))
num_mobs[n] = TexMobject(str(n))
num_mobs[n].scale(1.0/(power_of_divisor(n, 2)+1))
width_ratio = max_width / num_mobs[n].get_width()
if width_ratio < 1:
@ -1882,7 +1882,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
mobject.shift(diffs[np.argmin(map(np.linalg.norm, diffs))])
def add_negative_one(self, num_mobs):
neg_one = tex_mobject("-1").scale(0.5)
neg_one = TexMobject("-1").scale(0.5)
shift_val = num_mobs[15].get_center()-neg_one.get_center()
neg_one.shift(UP)
self.play(ApplyMethod(neg_one.shift, shift_val))
@ -1897,7 +1897,7 @@ class RoomsAndSubroomsWithNumbers(Scene):
dist_string = "1"
else:
dist_string = "$\\frac{1}{%d}$"%(2**count)
text = text_mobject(
text = TextMobject(
"Any of these pairs are considered to be a distance " +\
dist_string +\
" away from each other"
@ -1934,10 +1934,10 @@ class RoomsAndSubroomsWithNumbers(Scene):
class DeduceWhereNegativeOneFalls(Scene):
def construct(self):
part0, arg0, part1, part2, arg1, part3 = text_mobject([
part0, arg0, part1, part2, arg1, part3 = TextMobject([
"dist(-1, ", "0000", ") = ", "dist(0, ", "0000", ")"
]).scale(1.5).split()
u_brace = underbrace(
u_brace = Underbrace(
part2.get_boundary_point(DOWN+LEFT),
part3.get_boundary_point(DOWN+RIGHT)
).shift(0.3+DOWN)
@ -1947,7 +1947,7 @@ class DeduceWhereNegativeOneFalls(Scene):
texts = [
CompoundMobject(parts[0], parts[1].highlight(color))
for count, color in zip(it.count(), colors)
for parts in [text_mobject([
for parts in [TextMobject([
"Represented (heuristically) \\\\ by being in the same \\\\",
(count*"sub-")+"room"
]).split()]
@ -1961,7 +1961,7 @@ class DeduceWhereNegativeOneFalls(Scene):
for n in range(1, 15):
rest_time = 0.3 + 1.0/(n+1)
new_args = [
text_mobject("$%d$"%k).scale(1.5)
TextMobject("$%d$"%k).scale(1.5)
for k in 2**n-1, 2**n
]
for new_arg, old_arg in zip(new_args, last_args):
@ -1986,7 +1986,7 @@ class DeduceWhereNegativeOneFalls(Scene):
class OtherRationalNumbers(Scene):
def construct(self):
import random
self.add(text_mobject("Where do other \\\\ rational numbers fall?"))
self.add(TextMobject("Where do other \\\\ rational numbers fall?"))
pairs = [
(1, 2),
(1, 3),
@ -2002,17 +2002,17 @@ class OtherRationalNumbers(Scene):
3*DOWN,
]
for pair, locus in zip(pairs, locii):
fraction = tex_mobject("\\frac{%d}{%d}"%pair).shift(locus)
fraction = TexMobject("\\frac{%d}{%d}"%pair).shift(locus)
self.play(ShimmerIn(fraction))
self.dither()
class PAdicMetric(Scene):
def construct(self):
p_str, text = text_mobject(["$p$", "-adic metric"]).shift(2*UP).split()
primes = [tex_mobject(str(p)) for p in [2, 3, 5, 7, 11, 13, 17, 19, 23]]
p_str, text = TextMobject(["$p$", "-adic metric"]).shift(2*UP).split()
primes = [TexMobject(str(p)) for p in [2, 3, 5, 7, 11, 13, 17, 19, 23]]
p_str.highlight("yellow")
colors = Color("green").range_to("skyblue", len(primes))
new_numbers = text_mobject("Completely new types of numbers!")
new_numbers = TextMobject("Completely new types of numbers!")
new_numbers.highlight("skyblue").shift(2.3*DOWN)
arrow = Arrow(2*DOWN, tail = 1.7*UP)
@ -2048,19 +2048,19 @@ class PAdicMetric(Scene):
class FuzzyDiscoveryToNewMath(Scene):
def construct(self):
fuzzy = text_mobject("Fuzzy Discovery")
fuzzy = TextMobject("Fuzzy Discovery")
fuzzy.to_edge(UP).shift(SPACE_WIDTH*LEFT/2)
new_math = text_mobject("New Math")
new_math = TextMobject("New Math")
new_math.to_edge(UP).shift(SPACE_WIDTH*RIGHT/2)
lines = CompoundMobject(
Line(DOWN*SPACE_HEIGHT, UP*SPACE_HEIGHT),
Line(3*UP+LEFT*SPACE_WIDTH, 3*UP+RIGHT*SPACE_WIDTH)
)
fuzzy_discoveries = [
tex_mobject("a^2 + b^2 = c^2"),
tex_mobject("".join(CONVERGENT_SUM_TEXT)),
tex_mobject("".join(DIVERGENT_SUM_TEXT)),
tex_mobject("e^{\pi i} = -1"),
TexMobject("a^2 + b^2 = c^2"),
TexMobject("".join(CONVERGENT_SUM_TEXT)),
TexMobject("".join(DIVERGENT_SUM_TEXT)),
TexMobject("e^{\pi i} = -1"),
]
triangle_lines = [
Line(ORIGIN, LEFT),
@ -2069,21 +2069,21 @@ class FuzzyDiscoveryToNewMath(Scene):
]
for line, char in zip(triangle_lines, ["a", "c", "b"]):
line.highlight("blue")
char_mob = tex_mobject(char).scale(0.25)
char_mob = TexMobject(char).scale(0.25)
line.add(char_mob.shift(line.get_center()))
triangle = CompoundMobject(*triangle_lines)
triangle.center().shift(1.5*fuzzy_discoveries[0].get_right())
how_length = text_mobject("But how is length defined?").scale(0.5)
how_length = TextMobject("But how is length defined?").scale(0.5)
how_length.shift(0.75*DOWN)
fuzzy_discoveries[0].add(triangle, how_length)
new_maths = [
text_mobject("""
TextMobject("""
Define distance between points $(x_0, y_0)$ and
$(x_1, y_1)$ as $\\sqrt{(x_1-x_0)^2 + (y_1-y_0)^2}$
"""),
text_mobject("Define ``approach'' and infinite sums"),
text_mobject("Discover $2$-adic numbers"),
text_mobject(
TextMobject("Define ``approach'' and infinite sums"),
TextMobject("Discover $2$-adic numbers"),
TextMobject(
"Realize exponentiation is doing something much \
different from repeated multiplication"
)
@ -2112,13 +2112,13 @@ class FuzzyDiscoveryToNewMath(Scene):
class DiscoveryAndInvention(Scene):
def construct(self):
invention, vs, discovery = text_mobject([
invention, vs, discovery = TextMobject([
"Invention ", "vs. ", "Discovery"
]).split()
nrd = text_mobject(
nrd = TextMobject(
"Non-rigorous truths"
).shift(2*UP)
rt = text_mobject(
rt = TextMobject(
"Rigorous terms"
).shift(2*DOWN)

View File

@ -37,7 +37,7 @@ class SimpleText(Scene):
return initials(filter(lambda c : c in string.letters + " ", text))
def construct(self, text):
self.add(text_mobject(text))
self.add(TextMobject(text))
class SimpleTex(Scene):
@ -56,12 +56,12 @@ class SimpleTex(Scene):
return words
def construct(self, expression, words):
self.add(tex_mobject(expression))
self.add(TexMobject(expression))
class OneMinusOnePoem(Scene):
def construct(self):
verse1 = text_mobject("""
verse1 = TextMobject("""
\\begin{flushleft}
When one takes one from one \\\\
plus one from one plus one \\\\
@ -75,7 +75,7 @@ class OneMinusOnePoem(Scene):
until the infinite. \\\\
\\end{flushleft}
""").scale(0.5).to_corner(UP+LEFT)
verse2 = text_mobject("""
verse2 = TextMobject("""
\\begin{flushleft}
Lest you should think that such \\\\
less well-known sums are much \\\\
@ -89,7 +89,7 @@ class OneMinusOnePoem(Scene):
the universe gives ``half''. \\\\
\\end{flushleft}
""").scale(0.5).to_corner(DOWN+LEFT)
equation = tex_mobject(
equation = TexMobject(
"1-1+1-1+\\cdots = \\frac{1}{2}"
)
self.add(verse1, verse2, equation)
@ -111,7 +111,7 @@ class PowersOfTwoSmall(Scene):
class FinalSlide(Scene):
def construct(self):
self.add(text_mobject("""
self.add(TextMobject("""
\\begin{flushleft}
Needless to say, what I said here only scratches the
surface of the tip of the iceberg of the p-adic metric.

View File

@ -17,7 +17,7 @@ def matrix_to_string(matrix):
return "--".join(["-".join(map(str, row)) for row in matrix])
def matrix_mobject(matrix):
return text_mobject(
return TextMobject(
"""
\\left(
\\begin{array}{%s}
@ -100,7 +100,7 @@ class ExamplesOfNonlinearOneDimensionalTransforms(NumberLineScene):
return (np.sin(x) + 1.2*x, y, z)
def shift_zero((x, y, z)):
return (2*x+4, y, z)
self.nonlinear = text_mobject("Not a Linear Transform")
self.nonlinear = TextMobject("Not a Linear Transform")
self.nonlinear.highlight(LIGHT_RED).to_edge(UP, buff = 1.5)
pairs = [
(sinx_plux_x, "numbers don't remain evenly spaced"),
@ -118,7 +118,7 @@ class ExamplesOfNonlinearOneDimensionalTransforms(NumberLineScene):
"density" : 5*DEFAULT_POINT_DENSITY_1D,
}
NumberLineScene.construct(self, **config)
words = text_mobject(explanation).highlight(LIGHT_RED)
words = TextMobject(explanation).highlight(LIGHT_RED)
words.next_to(self.nonlinear, DOWN, buff = 0.5)
self.add(words)
@ -300,7 +300,7 @@ class ExamplesOfNonlinearTwoDimensionalTransformations(Scene):
return (x+np.sin(y), y+np.cos(x), z)
def shift_zero((x, y, z)):
return (2*x + 3*y + 4, -1*x+y+2, z)
self.nonlinear = text_mobject("Nonlinear Transform")
self.nonlinear = TextMobject("Nonlinear Transform")
self.nonlinear.highlight(LIGHT_RED)
self.nonlinear.to_edge(UP, buff = 1.5)
pairs = [
@ -322,7 +322,7 @@ class ExamplesOfNonlinearTwoDimensionalTransformations(Scene):
}
number_plane = NumberPlane(**config)
numbers = number_plane.get_coordinate_labels()
words = text_mobject(explanation)
words = TextMobject(explanation)
words.highlight(LIGHT_RED)
words.next_to(self.nonlinear, DOWN, buff = 0.5)
@ -356,7 +356,7 @@ class ExamplesOfNonlinearTwoDimensionalTransformations(Scene):
region = region_from_polygon_vertices(*vertices)
image = disp.paint_region(region, color = WHITE)
self.blackness = text_mobject("")
self.blackness = TextMobject("")
ImageMobject.generate_points_from_image_array(self.blackness, image)
self.blackness.highlight(BLACK)
rectangle = Rectangle(width = 7, height=1.7)
@ -375,7 +375,7 @@ class TrickyExamplesOfNonlinearTwoDimensionalTransformations(Scene):
"point_thickness" : 2*DEFAULT_POINT_THICKNESS
}
number_plane = NumberPlane(**config)
phrase1, phrase2 = text_mobject([
phrase1, phrase2 = TextMobject([
"These might look like they keep lines straight...",
"but diagonal lines get curved"
]).to_edge(UP, buff = 1.5).split()
@ -427,7 +427,7 @@ class TrickyExamplesOfNonlinearTwoDimensionalTransformations(Scene):
region = region_from_polygon_vertices(*vertices)
image = disp.paint_region(region, color = WHITE)
self.blackness = text_mobject("")
self.blackness = TextMobject("")
ImageMobject.generate_points_from_image_array(self.blackness, image)
self.blackness.highlight(BLACK)
rectangle = Rectangle(width = 9, height=1.5)

View File

@ -61,7 +61,7 @@ def count_sections(*radians):
last_num = None
for reg, count in zip(regions, it.count(1)):
number = tex_mobject(str(count)).shift((RADIUS, 3, 0))
number = TexMobject(str(count)).shift((RADIUS, 3, 0))
sc.highlight_region(reg)
rt = 1.0 / (x**0.8)
sc.add(number)
@ -89,7 +89,7 @@ def summarize_pattern(*radians):
new_lines = CompoundMobject(*[
Line(points[x], points[y]) for y in xrange(x)
])
num = tex_mobject(str(moser_function(x + 1))).center()
num = TexMobject(str(moser_function(x + 1))).center()
sc.animate(
Transform(last_num, num) if last_num else ShowCreation(num),
FadeIn(new_lines),
@ -127,7 +127,7 @@ def connect_points(*radians):
def interesting_problems():
sc = Scene()
locales = [(6, 2, 0), (6, -2, 0), (-5, -2, 0)]
fermat = CompoundMobject(*tex_mobjects(["x^n","+","y^n","=","z^n"]))
fermat = CompoundMobject(*TexMobjects(["x^n","+","y^n","=","z^n"]))
fermat.scale(0.5).shift((-2.5, 0.7, 0))
face = SimpleFace()
tb = ThoughtBubble().shift((-1.5, 1, 0))
@ -274,13 +274,13 @@ if __name__ == '__main__':
# summarize_pattern(*different_radians).write_to_movie("moser/PatternWithDifferentPoints")
#Images
# tex_mobject(r"""
# \underbrace{1, 2, 4, 8, 16, 31, \dots}_\text{What?}
# TexMobject(r"""
# \Underbrace{1, 2, 4, 8, 16, 31, \dots}_\text{What?}
# """).save_image("moser/NumberList31")
# tex_mobject("""
# TexMobject("""
# 1, 2, 4, 8, 16, 32, 63, \dots
# """).save_image("moser/NumberList63")
# tex_mobject("""
# TexMobject("""
# 1, 2, 4, 8, 15, \dots
# """).save_image("moser/NumberList15")

View File

@ -51,7 +51,7 @@ class CircleScene(Scene):
]
self.dots = [Dot(point) for point in self.points]
self.lines = [Line(p1, p2) for p1, p2 in it.combinations(self.points, 2)]
self.n_equals = tex_mobject(
self.n_equals = TexMobject(
"n=%d"%len(radians),
).shift((-SPACE_WIDTH+1, SPACE_HEIGHT-1.5, 0))
self.add(self.circle, self.n_equals, *self.dots + self.lines)
@ -149,7 +149,7 @@ class MoserPattern(CircleScene):
def __init__(self, radians, *args, **kwargs):
CircleScene.__init__(self, radians, *args, **kwargs)
self.remove(*self.dots + self.lines + [self.n_equals])
n_equals, num = tex_mobject(["n=", "10"]).split()
n_equals, num = TexMobject(["n=", "10"]).split()
for mob in n_equals, num:
mob.shift((-SPACE_WIDTH + 1.5, SPACE_HEIGHT - 1.5, 0))
self.add(n_equals)
@ -157,8 +157,8 @@ class MoserPattern(CircleScene):
self.add(*self.dots[:n])
self.add(*[Line(p[0], p[1]) for p in it.combinations(self.points[:n], 2)])
tex_stuffs = [
tex_mobject(str(moser_function(n))),
tex_mobject(str(n)).shift(num.get_center())
TexMobject(str(moser_function(n))),
TexMobject(str(n)).shift(num.get_center())
]
self.add(*tex_stuffs)
self.dither(0.5)
@ -176,14 +176,14 @@ class HardProblemsSimplerQuestions(Scene):
fermat = dict([
(
sym,
CompoundMobject(*tex_mobjects(
CompoundMobject(*TexMobjects(
["x","^"+sym,"+","y","^"+sym,"=","z","^"+sym]
))
)
for sym in ["n", "2", "3"]
])
# not_that_hard = text_mobject("(maybe not that hard...)").scale(0.5)
fermat2, fermat2_jargon = tex_mobject([
# not_that_hard = TextMobject("(maybe not that hard...)").scale(0.5)
fermat2, fermat2_jargon = TexMobject([
r"&x^2 + y^2 = z^2 \\",
r"""
&(3, 4, 5) \\
@ -194,7 +194,7 @@ class HardProblemsSimplerQuestions(Scene):
&\quad \vdots
"""
]).split()
fermat3, fermat3_jargon = tex_mobject([
fermat3, fermat3_jargon = TexMobject([
r"&x^3 + y^3 = z^3\\",
r"""
&y^3 = (z - x)(z - \omega x)(z - \omega^2 x) \\
@ -237,7 +237,7 @@ class HardProblemsSimplerQuestions(Scene):
circle_grid = CompoundMobject(
Circle(),
Grid(radius = 2),
tex_mobject(r"\mathds{R}^2").shift((2, -2, 0))
TexMobject(r"\mathds{R}^2").shift((2, -2, 0))
)
start_line = Line((-1, 0, 0), (-1, 2, 0))
end_line = Line((-1, 0, 0), (-1, -2, 0))
@ -246,7 +246,7 @@ class HardProblemsSimplerQuestions(Scene):
other_grid = CompoundMobject(
Grid(radius = 2),
tex_mobject(r"\mathds{C}").shift((2, -2, 0))
TexMobject(r"\mathds{C}").shift((2, -2, 0))
)
omega = np.array((0.5, 0.5*np.sqrt(3), 0))
dots = CompoundMobject(*[
@ -283,9 +283,9 @@ class CountLines(CircleScene):
#TODO, Count things explicitly?
text_center = (self.radius + 1, self.radius -1, 0)
scale_factor = 0.4
text = tex_mobject(r"\text{How Many Lines?}", size = r"\large")
text = TexMobject(r"\text{How Many Lines?}", size = r"\large")
n = len(radians)
formula, answer = tex_mobject([
formula, answer = TexMobject([
r"{%d \choose 2} = \frac{%d(%d - 1)}{2} = "%(n, n, n),
str(choose(n, 2))
])
@ -330,9 +330,9 @@ class CountIntersectionPoints(CircleScene):
text_center = (self.radius + 0.5, self.radius -0.5, 0)
size = r"\large"
scale_factor = 0.4
text = tex_mobject(r"\text{How Many Intersection Points?}", size = size)
text = TexMobject(r"\text{How Many Intersection Points?}", size = size)
n = len(radians)
formula, answer = tex_mobject([
formula, answer = TexMobject([
r"{%d \choose 4} = \frac{%d(%d - 1)(%d - 2)(%d-3)}{1\cdot 2\cdot 3 \cdot 4}="%(n, n, n, n, n),
str(choose(n, 4))
]).split()
@ -369,7 +369,7 @@ class NonGeneralPosition(CircleScene):
]
)
center_region
text = tex_mobject(r"\text{This region disappears}", size = r"\large")
text = TexMobject(r"\text{This region disappears}", size = r"\large")
text.center().scale(0.5).shift((-self.radius, self.radius-0.3, 0))
arrow = Arrow(
point = (-0.35, -0.1, 0),
@ -417,7 +417,7 @@ class GeneralPositionRule(Scene):
for radians, words, pairs in tuples:
cs = CircleScene(radians)
self.add(*cs.mobjects)
words_mob = text_mobject(words).scale(2).shift((5, 3, 0))
words_mob = TextMobject(words).scale(2).shift((5, 3, 0))
if not first_time:
self.add(words_mob)
if words == "Okay":
@ -492,8 +492,8 @@ class IllustrateNChooseK(Scene):
Scene.__init__(self, *args, **kwargs)
nrange = range(1, n+1)
tuples = list(it.combinations(nrange, k))
nrange_mobs = tex_mobject([str(n) + r'\;' for n in nrange]).split()
tuple_mobs = tex_mobjects(
nrange_mobs = TexMobject([str(n) + r'\;' for n in nrange]).split()
tuple_mobs = TexMobjects(
[
(r'\\&' if c%(20//k) == 0 else r'\;\;') + str(p)
for p, c in zip(tuples, it.count())
@ -515,12 +515,12 @@ class IllustrateNChooseK(Scene):
"""%(n, k, n, n, n, n)
else:
str1 = r"{%d \choose %d} ="%(n, k)
form1, count, form2 = tex_mobject([
form1, count, form2 = TexMobject([
str1,
"%d"%choose(n, k),
r" \text{ total %s}"%tuple_term
])
pronunciation = text_mobject(
pronunciation = TextMobject(
"(pronounced ``%d choose %d\'\')"%(n, k)
)
for mob in nrange_mobs:
@ -539,7 +539,7 @@ class IllustrateNChooseK(Scene):
run_time = 6.0
frame_time = run_time / len(tuples)
for tup, count in zip(tuples, it.count()):
count_mob = tex_mobject(str(count+1))
count_mob = TexMobject(str(count+1))
count_mob.center().shift(count_center)
self.add(count_mob)
tuple_copy = CompoundMobject(*[nrange_mobs[index-1] for index in tup])
@ -582,8 +582,8 @@ class IntersectionPointCorrespondances(CircleScene):
self.dots[p]
for p in indices
]
line_statement = tex_mobject(r"\text{Pair of Lines}")
dots_statement = tex_mobject(r"&\text{Quadruplet of} \\ &\text{outer dots}")
line_statement = TexMobject(r"\text{Pair of Lines}")
dots_statement = TexMobject(r"&\text{Quadruplet of} \\ &\text{outer dots}")
for mob in line_statement, dots_statement:
mob.center()
mob.scale(0.7)
@ -685,7 +685,7 @@ class GraphsAndEulersFormulaJoke(Scene):
graph.filter_out(lambda (x, y, z) : abs(y) > SPACE_HEIGHT)
self.add(axes)
self.play(ShowCreation(graph), run_time = 1.0)
eulers = tex_mobject("e^{\pi i} = -1").shift((0, 3, 0))
eulers = TexMobject("e^{\pi i} = -1").shift((0, 3, 0))
self.play(CounterclockwiseTransform(
deepcopy(graph), eulers
))
@ -705,8 +705,8 @@ class DefiningGraph(GraphScene):
def __init__(self, *args, **kwargs):
GraphScene.__init__(self, *args, **kwargs)
word_center = (0, 3, 0)
vertices_word = text_mobject("``Vertices\"").shift(word_center)
edges_word = text_mobject("``Edges\"").shift(word_center)
vertices_word = TextMobject("``Vertices\"").shift(word_center)
edges_word = TextMobject("``Edges\"").shift(word_center)
dots, lines = self.vertices, self.edges
self.remove(*dots + lines)
all_dots = CompoundMobject(*dots)
@ -782,7 +782,7 @@ class EulersFormula(GraphScene):
terms = "V - E + F =2".split(" ")
form = dict([
(key, mob)
for key, mob in zip(terms, tex_mobjects(terms))
for key, mob in zip(terms, TexMobjects(terms))
])
for mob in form.values():
mob.shift((0, SPACE_HEIGHT-0.7, 0))
@ -831,7 +831,7 @@ class CannotDirectlyApplyEulerToMoser(CircleScene):
def __init__(self, radians, *args, **kwargs):
CircleScene.__init__(self, radians, *args, **kwargs)
self.remove(self.n_equals)
n_equals, intersection_count = tex_mobject([
n_equals, intersection_count = TexMobject([
r"&n = %d\\"%len(radians),
r"&{%d \choose 4} = %d"%(len(radians), choose(len(radians), 4))
]).split()
@ -854,7 +854,7 @@ class CannotDirectlyApplyEulerToMoser(CircleScene):
self.play(ShowCreation(yellow_lines))
self.dither()
self.remove(yellow_lines)
cannot_intersect = text_mobject(r"""
cannot_intersect = TextMobject(r"""
Euler's formula does not apply to \\
graphs whose edges intersect!
"""
@ -877,8 +877,8 @@ class ShowMoserGraphLines(CircleScene):
radians = list(set(map(lambda x : x%(2*np.pi), radians)))
radians.sort()
CircleScene.__init__(self, radians, *args, **kwargs)
n, plus_n_choose_4 = tex_mobject(["n", "+{n \\choose 4}"]).split()
n_choose_2, plus_2_n_choose_4, plus_n = tex_mobject([
n, plus_n_choose_4 = TexMobject(["n", "+{n \\choose 4}"]).split()
n_choose_2, plus_2_n_choose_4, plus_n = TexMobject([
r"{n \choose 2}",r"&+2{n \choose 4}\\",r"&+n"
]).split()
for mob in n, plus_n_choose_4, n_choose_2, plus_2_n_choose_4, plus_n:
@ -1028,19 +1028,19 @@ class ApplyEulerToMoser(CircleScene):
equals, two, two1, n, n1, nc2, nc4, nc41]
V[1], minus[1], E[1], plus[1], F[1], equals[1], two[1] = \
tex_mobject(["V", "-", "E", "+", "F", "=", "2"]).split()
TexMobject(["V", "-", "E", "+", "F", "=", "2"]).split()
F[2], equals[2], E[2], minus[2], V[2], plus[2], two[2] = \
tex_mobject(["F", "=", "E", "-", "V", "+", "2"]).split()
TexMobject(["F", "=", "E", "-", "V", "+", "2"]).split()
F[3], equals[3], E[3], minus[3], n[3], minus1[3], nc4[3], plus[3], two[3] = \
tex_mobject(["F", "=", "E", "-", "n", "-", r"{n \choose 4}", "+", "2"]).split()
TexMobject(["F", "=", "E", "-", "n", "-", r"{n \choose 4}", "+", "2"]).split()
F[4], equals[4], nc2[4], plus1[4], two1[4], nc41[4], plus2[4], n1[4], minus[4], n[4], minus1[4], nc4[4], plus[4], two[4] = \
tex_mobject(["F", "=", r"{n \choose 2}", "+", "2", r"{n \choose 4}", "+", "n","-", "n", "-", r"{n \choose 4}", "+", "2"]).split()
TexMobject(["F", "=", r"{n \choose 2}", "+", "2", r"{n \choose 4}", "+", "n","-", "n", "-", r"{n \choose 4}", "+", "2"]).split()
F[5], equals[5], nc2[5], plus1[5], two1[5], nc41[5], minus1[5], nc4[5], plus[5], two[5] = \
tex_mobject(["F", "=", r"{n \choose 2}", "+", "2", r"{n \choose 4}", "-", r"{n \choose 4}", "+", "2"]).split()
TexMobject(["F", "=", r"{n \choose 2}", "+", "2", r"{n \choose 4}", "-", r"{n \choose 4}", "+", "2"]).split()
F[6], equals[6], nc2[6], plus1[6], nc4[6], plus[6], two[6] = \
tex_mobject(["F", "=", r"{n \choose 2}", "+", r"{n \choose 4}", "+", "2"]).split()
TexMobject(["F", "=", r"{n \choose 2}", "+", r"{n \choose 4}", "+", "2"]).split()
F[7], equals[7], two[7], plus[7], nc2[7], plus1[7], nc4[7] = \
tex_mobject(["F", "=", "2", "+", r"{n \choose 2}", "+", r"{n \choose 4}"]).split()
TexMobject(["F", "=", "2", "+", r"{n \choose 2}", "+", r"{n \choose 4}"]).split()
shift_val = (0, 3, 0)
for d in dicts:
if not d:
@ -1181,7 +1181,7 @@ class ApplyEulerToMoser(CircleScene):
self.highlight_region(self.exterior, "black")
self.remove(two[6])
two = two[7]
one = tex_mobject("1").shift(two.get_center())
one = TexMobject("1").shift(two.get_center())
two.highlight("red")
self.add(two)
self.play(CounterclockwiseTransform(two, one))
@ -1198,7 +1198,7 @@ class FormulaRelatesToPowersOfTwo(Scene):
]
for n in [1, 2, 3, 4, 5, 10]
]
everything = tex_mobjects(sum(strings, []), size = r"\large")
everything = TexMobjects(sum(strings, []), size = r"\large")
scale_factor = 1
for mob in everything:
mob.scale(scale_factor)
@ -1216,7 +1216,7 @@ class FormulaRelatesToPowersOfTwo(Scene):
for s, result in zip(sums, results)
])
powers_of_two = [
tex_mobject("2^{%d}"%(i-1)
TexMobject("2^{%d}"%(i-1)
).scale(scale_factor
).shift(result.get_center()
).highlight()
@ -1260,7 +1260,7 @@ class PascalRuleExample(PascalsTriangleScene):
k = randint(1, n-1)
self.coords_to_mobs[n][k].highlight("green")
self.dither()
plus = tex_mobject("+").scale(0.5)
plus = TexMobject("+").scale(0.5)
nums_above = [self.coords_to_mobs[n-1][k-1], self.coords_to_mobs[n-1][k]]
plus.center().shift(sum(map(Mobject.get_center, nums_above)) / 2)
self.add(plus)
@ -1298,7 +1298,7 @@ class PascalsTriangleNChooseKExample(PascalsTriangleScene):
PascalsTriangleScene.__init__(self, nrows, *args, **kwargs)
dither_time = 0.5
triangle_terms = [self.coords_to_mobs[a][b] for a, b in self.coords]
formula_terms = left, n_mob, k_mob, right = tex_mobject([
formula_terms = left, n_mob, k_mob, right = TexMobject([
r"\left(", str(n), r"\atop %d"%k, r"\right)"
])
formula_center = (SPACE_WIDTH - 1, SPACE_HEIGHT - 1, 0)
@ -1317,7 +1317,7 @@ class PascalsTriangleNChooseKExample(PascalsTriangleScene):
self.remove(n_mob, k_mob)
for a in range(n+1):
row = [self.coords_to_mobs[a][b] for b in range(a+1)]
a_mob = tex_mobject(str(a))
a_mob = TexMobject(str(a))
a_mob.shift(n_mob.get_center())
a_mob.highlight("green")
self.add(a_mob)
@ -1330,7 +1330,7 @@ class PascalsTriangleNChooseKExample(PascalsTriangleScene):
self.remove(a_mob)
self.dither()
for b in range(k+1):
b_mob = tex_mobject(str(b))
b_mob = TexMobject(str(b))
b_mob.shift(k_mob.get_center())
b_mob.highlight("yellow")
self.add(b_mob)
@ -1353,7 +1353,7 @@ class PascalsTriangleSumRows(PascalsTriangleScene):
powers_of_two = []
equalses = []
powers_of_two_symbols = []
plus = tex_mobject("+")
plus = TexMobject("+")
desired_plus_width = self.coords_to_mobs[0][0].get_width()
if plus.get_width() > desired_plus_width:
plus.scale(desired_plus_width / plus.get_width())
@ -1364,12 +1364,12 @@ class PascalsTriangleSumRows(PascalsTriangleScene):
new_plus.center().shift(self.coords_to_mobs[n][k].get_center())
new_plus.shift((-self.cell_width / 2.0, 0, 0))
pluses.append(new_plus)
equals = tex_mobject("=")
equals = TexMobject("=")
equals.scale(min(1, 0.7 * self.cell_height / equals.get_width()))
for n in range(self.nrows):
new_equals = deepcopy(equals)
pof2 = tex_mobjects(str(2**n))
symbol = tex_mobject("2^{%d}"%n)
pof2 = TexMobjects(str(2**n))
symbol = TexMobject("2^{%d}"%n)
desired_center = np.array((
self.diagram_width / 2.0,
self.coords_to_mobs[n][0].get_center()[1],
@ -1423,7 +1423,7 @@ class MoserSolutionInPascal(PascalsTriangleScene):
term_color = "green"
self.generate_n_choose_k_mobs()
self.remove(*[self.coords_to_mobs[n0][k0] for n0, k0 in self.coords])
terms = one, plus0, n_choose_2, plus1, n_choose_4 = tex_mobject([
terms = one, plus0, n_choose_2, plus1, n_choose_4 = TexMobject([
"1", "+", r"{%d \choose 2}"%n, "+", r"{%d \choose 4}"%n
]).split()
target_terms = []
@ -1485,7 +1485,7 @@ class MoserSolutionInPascal(PascalsTriangleScene):
))
self.remove(*above_terms)
self.dither()
terms_sum = tex_mobject(str(moser_function(n)))
terms_sum = TexMobject(str(moser_function(n)))
terms_sum.shift((SPACE_WIDTH-1, terms[0].get_center()[1], 0))
terms_sum.highlight(term_color)
self.play(Transform(CompoundMobject(*terms), terms_sum))
@ -1527,17 +1527,17 @@ class ExplainNChoose2Formula(Scene):
def __init__(self, n, a, b, *args, **kwargs):
Scene.__init__(self, *args, **kwargs)
r_paren, a_mob, comma, b_mob, l_paren = tex_mobjects(
r_paren, a_mob, comma, b_mob, l_paren = TexMobjects(
("( %d , %d )"%(a, b)).split(" ")
)
parens = CompoundMobject(r_paren, comma, l_paren)
nums = [tex_mobject(str(k)) for k in range(1, n+1)]
nums = [TexMobject(str(k)) for k in range(1, n+1)]
height = 1.5*nums[0].get_height()
for x in range(n):
nums[x].shift((0, x*height, 0))
nums_compound = CompoundMobject(*nums)
nums_compound.shift(a_mob.get_center() - nums[0].get_center())
n_mob, n_minus_1, over_2 = tex_mobject([
n_mob, n_minus_1, over_2 = TexMobject([
str(n), "(%d-1)"%n, r"\over{2}"
]).split()
for part in n_mob, n_minus_1, over_2:
@ -1585,7 +1585,7 @@ class ExplainNChoose2Formula(Scene):
CounterclockwiseTransform(a_mob, a_copy),
CounterclockwiseTransform(b_mob, b_copy),
FadeIn(parens_copy),
FadeIn(text_mobject("is considered the same as"))
FadeIn(TextMobject("is considered the same as"))
)
class ExplainNChoose4Formula(Scene):
@ -1598,17 +1598,17 @@ class ExplainNChoose4Formula(Scene):
Scene.__init__(self, *args, **kwargs)
# quad = list(it.combinations(range(1,n+1), 4))[randint(0, choose(n, 4)-1)]
quad = (4, 2, 5, 1)
tuple_mobs = tex_mobjects(
tuple_mobs = TexMobjects(
("( %d , %d , %d , %d )"%quad).split(" ")
)
quad_mobs = tuple_mobs[1::2]
parens = CompoundMobject(*tuple_mobs[0::2])
form_mobs = tex_mobject([
form_mobs = TexMobject([
str(n), "(%d-1)"%n, "(%d-2)"%n,"(%d-3)"%n,
r"\over {4 \cdot 3 \cdot 2 \cdot 1}"
]).split()
form_mobs = CompoundMobject(*form_mobs).scale(0.7).shift((4, 3, 0)).split()
nums = [tex_mobject(str(k)) for k in range(1, n+1)]
nums = [TexMobject(str(k)) for k in range(1, n+1)]
height = 1.5*nums[0].get_height()
for x in range(n):
nums[x].shift((0, x*height, 0))
@ -1643,7 +1643,7 @@ class ExplainNChoose4Formula(Scene):
])
curr_num = quad[i]
self.remove(*self.mobjects)
num_perms_explain = text_mobject(
num_perms_explain = TextMobject(
r"There are $(4 \cdot 3 \cdot 2 \cdot 1)$ total permutations"
).shift((0, -2, 0))
self.add(parens, num_perms_explain, *form_mobs)
@ -1685,7 +1685,7 @@ class IntersectionChoppingExamples(Scene):
for pairs, exp in [(pairs1, "3 + 2(2) = 7"),
(pairs2, "4 + 2(3) = 10")]:
lines = [Line(*pair).scale(2) for pair in pairs]
self.add(tex_mobject(exp).shift((0, SPACE_HEIGHT-1, 0)))
self.add(TexMobject(exp).shift((0, SPACE_HEIGHT-1, 0)))
self.add(*lines)
self.dither()
self.play(*[

View File

@ -12,7 +12,7 @@ from constants import *
from region import *
from scene import Scene, NumberLineScene
from script_wrapper import command_line_create_scene
from inventing_math import underbrace
from inventing_math import Underbrace
import random
@ -46,7 +46,7 @@ def rationals():
def fraction_mobject(fraction):
n, d = fraction.numerator, fraction.denominator
return tex_mobject("\\frac{%d}{%d}"%(n, d))
return TexMobject("\\frac{%d}{%d}"%(n, d))
def continued_fraction(int_list):
if len(int_list) == 1:
@ -60,13 +60,13 @@ def zero_to_one_interval():
)
interval.elongate_tick_at(-INTERVAL_RADIUS, TICK_STRETCH_FACTOR)
interval.elongate_tick_at(INTERVAL_RADIUS, TICK_STRETCH_FACTOR)
interval.add(tex_mobject("0").shift(INTERVAL_RADIUS*LEFT+DOWN))
interval.add(tex_mobject("1").shift(INTERVAL_RADIUS*RIGHT+DOWN))
interval.add(TexMobject("0").shift(INTERVAL_RADIUS*LEFT+DOWN))
interval.add(TexMobject("1").shift(INTERVAL_RADIUS*RIGHT+DOWN))
return interval
class LeftParen(Mobject):
def generate_points(self):
self.add(tex_mobject("("))
self.add(TexMobject("("))
self.center()
def get_center(self):
@ -74,7 +74,7 @@ class LeftParen(Mobject):
class RightParen(Mobject):
def generate_points(self):
self.add(tex_mobject(")"))
self.add(TexMobject(")"))
self.center()
def get_center(self):
@ -258,17 +258,17 @@ class IntervalScene(NumberLineScene):
class TwoChallenges(Scene):
def construct(self):
two_challenges = text_mobject("Two Challenges", size = "\\Huge").to_edge(UP)
one, two = map(text_mobject, ["1.", "2."])
two_challenges = TextMobject("Two Challenges", size = "\\Huge").to_edge(UP)
one, two = map(TextMobject, ["1.", "2."])
one.shift(UP).to_edge(LEFT)
two.shift(DOWN).to_edge(LEFT)
notes = ImageMobject("musical_notes").scale(0.3)
notes.next_to(one)
notes.highlight("blue")
measure = text_mobject("Measure Theory").next_to(two)
probability = text_mobject("Probability")
measure = TextMobject("Measure Theory").next_to(two)
probability = TextMobject("Probability")
probability.next_to(measure).shift(DOWN+RIGHT)
integration = tex_mobject("\\int")
integration = TexMobject("\\int")
integration.next_to(measure).shift(UP+RIGHT)
arrow_to_prob = Arrow(measure, probability)
arrow_to_int = Arrow(measure, integration)
@ -309,7 +309,7 @@ class MeasureTheoryToHarmony(IntervalScene):
class ChallengeOne(Scene):
def construct(self):
title = text_mobject("Challenge #1").to_edge(UP)
title = TextMobject("Challenge #1").to_edge(UP)
start_color = Color("blue")
colors = start_color.range_to("white", 6)
self.bottom_vibration = VibratingString(
@ -323,14 +323,14 @@ class ChallengeOne(Scene):
)
for freq in [1, 2, 5.0/3, 4.0/3, 2]
]
freq_220 = text_mobject("220 Hz")
freq_r220 = text_mobject("$r\\times$220 Hz")
freq_330 = text_mobject("1.5$\\times$220 Hz")
freq_sqrt2 = text_mobject("$\\sqrt{2}\\times$220 Hz")
freq_220 = TextMobject("220 Hz")
freq_r220 = TextMobject("$r\\times$220 Hz")
freq_330 = TextMobject("1.5$\\times$220 Hz")
freq_sqrt2 = TextMobject("$\\sqrt{2}\\times$220 Hz")
freq_220.shift(1.5*DOWN)
for freq in freq_r220, freq_330, freq_sqrt2:
freq.shift(1.5*UP)
r_constraint = tex_mobject("(1<r<2)", size = "\\large")
r_constraint = TexMobject("(1<r<2)", size = "\\large")
self.add(title)
self.dither()
@ -362,8 +362,8 @@ class ChallengeOne(Scene):
one, two = 2*number_line.interval_size*RIGHT, 4*number_line.interval_size*RIGHT
arrow1 = Arrow(one+UP, one)
arrow2 = Arrow(two+UP, two)
r1 = tex_mobject("r").next_to(arrow1, UP)
r2 = tex_mobject("r").next_to(arrow2, UP)
r1 = TexMobject("r").next_to(arrow1, UP)
r2 = TexMobject("r").next_to(arrow2, UP)
kwargs = {
"run_time" : 5.0,
"alpha_func" : there_and_back
@ -395,10 +395,10 @@ class JustByAnalyzingTheNumber(Scene):
1.2020569031595942,
]
last = None
r_equals = tex_mobject("r=").shift(2*LEFT)
r_equals = TexMobject("r=").shift(2*LEFT)
self.add(r_equals)
for num in nums:
mob = tex_mobject(str(num)).next_to(r_equals)
mob = TexMobject(str(num)).next_to(r_equals)
mob.highlight()
mob.sort_points()
if last:
@ -412,23 +412,23 @@ class JustByAnalyzingTheNumber(Scene):
class QuestionAndAnswer(Scene):
def construct(self):
Q = text_mobject("Q:").shift(UP).to_edge(LEFT)
A = text_mobject("A:").shift(DOWN).to_edge(LEFT)
Q = TextMobject("Q:").shift(UP).to_edge(LEFT)
A = TextMobject("A:").shift(DOWN).to_edge(LEFT)
string1 = VibratingString(center = 3*UP, color = "blue")
string2 = VibratingString(num_periods = 2, center = 3.5*UP, color = "green")
twotwenty = tex_mobject("220").scale(0.25).next_to(string1.mobject, LEFT)
r220 = tex_mobject("r\\times220").scale(0.25).next_to(string2.mobject, LEFT)
question = text_mobject(
twotwenty = TexMobject("220").scale(0.25).next_to(string1.mobject, LEFT)
r220 = TexMobject("r\\times220").scale(0.25).next_to(string2.mobject, LEFT)
question = TextMobject(
"For what values of $r$ will the frequencies 220~Hz and \
$r\\times$220~Hz sound nice together?"
).next_to(Q)
answer = text_mobject([
answer = TextMobject([
"When $r$ is",
"sufficiently close to",
"a rational number"
], size = "\\small").scale(1.5)
answer.next_to(A)
correction1 = text_mobject(
correction1 = TextMobject(
"with sufficiently low denominator",
size = "\\small"
).scale(1.5)
@ -476,7 +476,7 @@ class PlaySimpleRatio(Scene):
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 = TexMobject("\\frac{e^\\pi - \\pi}{15} \\approx \\frac{4}{3}")
mob.shift(0.5*UP)
self.add(mob)
self.play(string1, string2)
@ -496,7 +496,7 @@ class DecomposeMusicalNote(Scene):
"run_time" : 4.0,
"alpha_func" : None
}
words = text_mobject("Imagine 220 per second...")
words = TextMobject("Imagine 220 per second...")
words.shift(2*UP)
self.add(line)
@ -528,7 +528,7 @@ class DecomposeTwoFrequencies(Scene):
class MostRationalsSoundBad(Scene):
def construct(self):
self.add(text_mobject("Most rational numbers sound bad!"))
self.add(TextMobject("Most rational numbers sound bad!"))
class FlashOnXProximity(Animation):
def __init__(self, mobject, x_val, *close_mobjects, **kwargs):
@ -579,7 +579,7 @@ class PatternInFrequencies(Scene):
}
self.add(big_line)
self.add(tex_mobject("%d:%d"%(num1, num2)))
self.add(TexMobject("%d:%d"%(num1, num2)))
fracs = (
1.0/(num_top_lines-1),
1.0/(num_bot_lines-1)
@ -599,18 +599,18 @@ class CompareFractionComplexity(Scene):
def construct(self):
fractions = []
for num, den in [(4, 3), (1093,826)]:
top = tex_mobject("%d \\over"%num)
bottom = tex_mobject(str(den)).next_to(top, DOWN, buff = 0.3)
top = TexMobject("%d \\over"%num)
bottom = TexMobject(str(den)).next_to(top, DOWN, buff = 0.3)
fractions.append(CompoundMobject(top, bottom))
frac0 = fractions[0].shift(3*LEFT).split()
frac1 = fractions[1].shift(3*RIGHT).split()
arrow1 = Arrow(UP, ORIGIN).next_to(frac0[0], UP)
arrow2 = Arrow(UP, ORIGIN).next_to(frac1[0], UP)
simple = text_mobject("Simple").next_to(arrow1, UP)
simple = TextMobject("Simple").next_to(arrow1, UP)
simple.highlight("green")
complicated = text_mobject("Complicated").next_to(arrow2, UP)
complicated = TextMobject("Complicated").next_to(arrow2, UP)
complicated.highlight("red")
indicates = text_mobject("Indicates complexity").shift(2*DOWN)
indicates = TextMobject("Indicates complexity").shift(2*DOWN)
arrow3 = Arrow(indicates.get_top(), frac0[1])
arrow4 = Arrow(indicates.get_top(), frac1[1])
@ -638,9 +638,9 @@ class IrrationalGang(Scene):
randy = Randolph()
randy.mouth.highlight(randy.DEFAULT_COLOR)
randy.sync_parts()
sqrt13 = tex_mobject("\\sqrt{13}").shift(2*LEFT)
sqrt13 = TexMobject("\\sqrt{13}").shift(2*LEFT)
sqrt13.highlight("green")
zeta3 = tex_mobject("\\zeta(3)").shift(2*RIGHT)
zeta3 = TexMobject("\\zeta(3)").shift(2*RIGHT)
zeta3.highlight("grey")
eyes = CompoundMobject(*randy.eyes)
eyes.scale(0.5)
@ -691,7 +691,7 @@ class PianoTuning(Scene):
semicircles.shift(0.05*RIGHT)
semicircles.sort_points(lambda p : p[0])
first_jump = semicircles.split()[0]
twelfth_root = tex_mobject("2^{\\left(\\frac{1}{12}\\right)}")
twelfth_root = TexMobject("2^{\\left(\\frac{1}{12}\\right)}")
twelfth_root.scale(0.75).next_to(first_jump, UP, buff = 1.5)
line = Line(twelfth_root, first_jump).highlight("grey")
self.keys = piano.split()
@ -720,23 +720,23 @@ class PianoTuning(Scene):
colors = list(Color("blue").range_to("yellow", 7))
low = self.keys[whole_notes_to_base]
high = self.keys[whole_notes_to_base + interval - 1]
u_brace = underbrace(low.get_bottom(), high.get_bottom())
u_brace = Underbrace(low.get_bottom(), high.get_bottom())
u_brace.highlight("yellow")
ratio = tex_mobject("2^{\\left(\\frac{%d}{12}\\right)}"%half_steps)
ratio = TexMobject("2^{\\left(\\frac{%d}{12}\\right)}"%half_steps)
ratio.next_to(u_brace, DOWN, buff = 0.2)
semicircles = self.semicircles[half_notes_to_base:half_notes_to_base+half_steps]
product = tex_mobject(
product = TexMobject(
["\\left(2^{\\left(\\frac{1}{12}\\right)}\\right)"]*half_steps,
size = "\\small"
).next_to(self.piano, UP, buff = 1.0)
approximate_form = tex_mobject("\\approx"+str(2**(float(half_steps)/12)))
approximate_form = TexMobject("\\approx"+str(2**(float(half_steps)/12)))
approximate_form.scale(0.75)
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 = TextMobject("Should be $\\frac{%d}{%d}$"%num_den)
should_be.next_to(u_brace, DOWN)
self.play(ApplyMethod(low.highlight, colors[0]))
@ -776,28 +776,28 @@ class PowersOfTwelfthRoot(Scene):
9 : Fraction(5, 3),
10 : Fraction(16, 9),
}
approx = tex_mobject("\\approx").scale(0.5)
approx = TexMobject("\\approx").scale(0.5)
curr_height = max_height*UP
spacing = UP*(max_height-min_height)/(len(fraction_map)-1.0)
for i in range(1, num_terms+1):
if i not in fraction_map:
continue
term = tex_mobject("2^{\\left(\\frac{%d}{12}\\right)}"%i)
term = TexMobject("2^{\\left(\\frac{%d}{12}\\right)}"%i)
term.shift(curr_height)
curr_height -= spacing
term.shift(4*LEFT)
value = 2**(i/12.0)
approx_form = tex_mobject(str(value)[:10])
approx_form = TexMobject(str(value)[:10])
approx_copy = deepcopy(approx).next_to(term)
approx_form.scale(0.5).next_to(approx_copy)
words = text_mobject("is close to")
words = TextMobject("is close to")
words.scale(approx_form.get_height()/words.get_height())
words.next_to(approx_form)
frac = fraction_map[i]
frac_mob = tex_mobject("%d/%d"%(frac.numerator, frac.denominator))
frac_mob = TexMobject("%d/%d"%(frac.numerator, frac.denominator))
frac_mob.scale(0.5).next_to(words)
percent_error = abs(100*((value - frac) / frac))
error_string = text_mobject([
error_string = TextMobject([
"with", str(percent_error)[:4] + "\\%", "error"
])
error_string = error_string.split()
@ -813,7 +813,7 @@ class PowersOfTwelfthRoot(Scene):
class InterestingQuestion(Scene):
def construct(self):
words = text_mobject("Interesting Question:", size = "\\Huge")
words = TextMobject("Interesting Question:", size = "\\Huge")
words.scale(2.0)
self.add(words)
@ -824,7 +824,7 @@ class SupposeThereIsASavant(Scene):
"who finds pleasure in all pairs of " + \
"notes whose frequencies have a rational ratio"
words = words.split(" ")
word_mobs = text_mobject(words).split()
word_mobs = TextMobject(words).split()
word_mobs[4].highlight()
word_mobs[5].highlight()
for word, word_mob in zip(words, word_mobs):
@ -842,8 +842,8 @@ class AllValuesBetween1And2(NumberLineScene):
)
top_arrow = Arrow(one+UP, one)
bot_arrow = Arrow(irr+2*DOWN, irr)
r = tex_mobject("r").next_to(top_arrow, UP)
irr_mob = tex_mobject(str(irrational)+"\\dots").next_to(bot_arrow, DOWN)
r = TexMobject("r").next_to(top_arrow, UP)
irr_mob = TexMobject(str(irrational)+"\\dots").next_to(bot_arrow, DOWN)
approximations = [
continued_fraction(cont_frac[:k])
@ -893,7 +893,7 @@ class AllValuesBetween1And2(NumberLineScene):
class ChallengeTwo(Scene):
def construct(self):
self.add(text_mobject("Challenge #2"))
self.add(TextMobject("Challenge #2"))
class CoveringSetsWithOpenIntervals(IntervalScene):
def construct(self):
@ -903,7 +903,7 @@ class CoveringSetsWithOpenIntervals(IntervalScene):
for num in set([0.2, 0.25, 0.45, 0.6, 0.65])
])
theorems = [
text_mobject(words).shift(UP)
TextMobject(words).shift(UP)
for words in [
"Heine-Borel Theorem",
"Lebesgue's Number Lemma",
@ -931,7 +931,7 @@ class DefineOpenInterval(IntervalScene):
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()
a, less_than1, x, less_than2, b = \
tex_mobject(["a", "<", "x", "<", "b"]).shift(UP).split()
TexMobject(["a", "<", "x", "<", "b"]).shift(UP).split()
left_arrow = Arrow(a.get_corner(DOWN+LEFT), left)
right_arrow = Arrow(b.get_corner(DOWN+RIGHT), right)
@ -1010,15 +1010,15 @@ class SumOfIntervalsMustBeLessThan1(IntervalScene):
self.remove(line)
int_copy = deepcopy(open_interval)
int_copy.scale(0.6).next_to(last_plus, buff = 0.1)
last_plus = tex_mobject("+").scale(0.3)
last_plus = TexMobject("+").scale(0.3)
last_plus.next_to(int_copy, buff = 0.1)
anims.append(Transform(open_interval, int_copy))
if num < 1.0:
anims.append(FadeIn(last_plus))
less_than1 = tex_mobject("<1").scale(0.5)
less_than1 = TexMobject("<1").scale(0.5)
less_than1.next_to(int_copy)
dots = tex_mobject("\\dots").replace(int_copy)
words = text_mobject("Use infinitely many intervals")
dots = TexMobject("\\dots").replace(int_copy)
words = TextMobject("Use infinitely many intervals")
words.shift(UP)
self.dither()
@ -1032,7 +1032,7 @@ class SumOfIntervalsMustBeLessThan1(IntervalScene):
class RationalsAreDense(IntervalScene):
def construct(self):
IntervalScene.construct(self)
words = text_mobject(["Rationals are", "\\emph{dense}", "in the reals"])
words = TextMobject(["Rationals are", "\\emph{dense}", "in the reals"])
words.shift(2*UP)
words = words.split()
words[1].highlight()
@ -1057,12 +1057,12 @@ class RationalsAreDense(IntervalScene):
class SurelyItsImpossible(Scene):
def construct(self):
self.add(text_mobject("Surely it's impossible!"))
self.add(TextMobject("Surely it's impossible!"))
class HowCanYouNotCoverEntireInterval(IntervalScene):
def construct(self):
IntervalScene.construct(self)
small_words = text_mobject("""
small_words = TextMobject("""
In case you are wondering, it is indeed true
that if you cover all real numbers between 0
and 1 with a set of open intervals, the sum
@ -1072,7 +1072,7 @@ class HowCanYouNotCoverEntireInterval(IntervalScene):
it for yourself!
""")
small_words.scale(0.5).to_corner(UP+RIGHT)
big_words = text_mobject("""
big_words = TextMobject("""
Covering all numbers from 0 to 1 \\emph{will}
force the sum of the lengths of your intervals
to be at least 1.
@ -1105,8 +1105,8 @@ class HowCanYouNotCoverEntireInterval(IntervalScene):
class PauseNow(Scene):
def construct(self):
top_words = text_mobject("Try for yourself!").scale(2).shift(3*UP)
bot_words = text_mobject("""
top_words = TextMobject("Try for yourself!").scale(2).shift(3*UP)
bot_words = TextMobject("""
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
@ -1118,7 +1118,7 @@ class StepsToSolution(IntervalScene):
def construct(self):
IntervalScene.construct(self)
self.spacing = 0.7
steps = map(text_mobject, [
steps = map(TextMobject, [
"Enumerate all rationals in (0, 1)",
"Assign one interval to each rational",
"Choose sum of the form $\\mathlarger{\\sum}_{n=1}^\\infty a_n = 1$",
@ -1159,7 +1159,7 @@ class StepsToSolution(IntervalScene):
mob_copy = deepcopy(mob).center()
mob_copy.shift((2.4-mob_copy.get_bottom()[1])*UP)
mob_copy.shift((-SPACE_WIDTH+self.spacing*count)*RIGHT)
comma = text_mobject(",").next_to(mob_copy, buff = 0.1, aligned_edge = DOWN)
comma = TextMobject(",").next_to(mob_copy, buff = 0.1, aligned_edge = DOWN)
anims.append(Transform(mob, mob_copy))
commas.add(comma)
anims.append(ShimmerIn(commas))
@ -1215,24 +1215,24 @@ class StepsToSolution(IntervalScene):
scale_val = 0.6
plus = None
for count in range(1, 10):
frac_bottom = tex_mobject("\\over %d"%(2**count))
frac_bottom = TexMobject("\\over %d"%(2**count))
frac_bottom.scale(scale_val)
one = tex_mobject("1").scale(scale_val)
one = TexMobject("1").scale(scale_val)
one.next_to(frac_bottom, UP, buff = 0.1)
compound = CompoundMobject(frac_bottom, one)
if plus:
compound.next_to(plus)
else:
compound.to_edge(LEFT)
plus = tex_mobject("+").scale(scale_val)
plus = TexMobject("+").scale(scale_val)
plus.next_to(compound)
frac_bottom, one = compound.split()
self.ones.append(one)
self.add(frac_bottom, one, plus)
self.dither(0.2)
dots = tex_mobject("\\dots").scale(scale_val).next_to(plus)
dots = TexMobject("\\dots").scale(scale_val).next_to(plus)
arrow = Arrow(ORIGIN, RIGHT).next_to(dots)
one = tex_mobject("1").next_to(arrow)
one = TexMobject("1").next_to(arrow)
self.ones.append(one)
self.play(*[ShowCreation(mob) for mob in dots, arrow, one])
self.dither()
@ -1241,7 +1241,7 @@ class StepsToSolution(IntervalScene):
self.play(*[
CounterclockwiseTransform(
one,
tex_mobject("\\epsilon").replace(one)
TexMobject("\\epsilon").replace(one)
)
for one in self.ones
])
@ -1259,11 +1259,11 @@ class StepsToSolution(IntervalScene):
class OurSumCanBeArbitrarilySmall(Scene):
def construct(self):
step_size = 0.01
epsilon = tex_mobject("\\epsilon")
equals = tex_mobject("=").next_to(epsilon)
epsilon = TexMobject("\\epsilon")
equals = TexMobject("=").next_to(epsilon)
self.add(epsilon, equals)
for num in np.arange(1, 0, -step_size):
parts = map(tex_mobject, str(num))
parts = map(TexMobject, str(num))
parts[0].next_to(equals)
for i in range(1, len(parts)):
parts[i].next_to(parts[i-1], buff = 0.1, aligned_edge = DOWN)
@ -1272,7 +1272,7 @@ class OurSumCanBeArbitrarilySmall(Scene):
self.remove(*parts)
self.dither()
self.clear()
words = text_mobject([
words = TextMobject([
"Not only can the sum be $< 1$,\\\\",
"it can be \\emph{arbitrarily small} !"
]).split()
@ -1283,13 +1283,13 @@ class OurSumCanBeArbitrarilySmall(Scene):
class ProofDoesNotEqualIntuition(Scene):
def construct(self):
self.add(text_mobject("Proof $\\ne$ Intuition"))
self.add(TextMobject("Proof $\\ne$ Intuition"))
class StillFeelsCounterintuitive(IntervalScene):
def construct(self):
IntervalScene.construct(self)
ticks = self.add_fraction_ticks(run_time = 1.0)
epsilon, equals, num = map(tex_mobject, ["\\epsilon", "=", "0.3"])
epsilon, equals, num = map(TexMobject, ["\\epsilon", "=", "0.3"])
epsilon.shift(2*UP)
equals.next_to(epsilon)
num.next_to(equals)
@ -1303,11 +1303,11 @@ class StillFeelsCounterintuitive(IntervalScene):
class VisualIntuition(Scene):
def construct(self):
self.add(text_mobject("Visual Intuition:"))
self.add(TextMobject("Visual Intuition:"))
class SideNote(Scene):
def construct(self):
self.add(text_mobject("(Brief Sidenote)"))
self.add(TextMobject("(Brief Sidenote)"))
class TroubleDrawingSmallInterval(IntervalScene):
def construct(self):
@ -1319,7 +1319,7 @@ class TroubleDrawingSmallInterval(IntervalScene):
shrunk = deepcopy(big).scale_in_place(0.01/0.5)
self.clear()
IntervalScene.construct(self)
words = text_mobject("This tiny stretch")
words = TextMobject("This tiny stretch")
words.shift(2*UP+2*LEFT)
arrow = Arrow(words, line)
@ -1344,20 +1344,20 @@ class TroubleDrawingSmallInterval(IntervalScene):
class WhatDoesItLookLikeToBeOutside(Scene):
def construct(self):
self.add(text_mobject(
self.add(TextMobject(
"What does it look like for a number to be outside a dense set of intervals?"
))
class ZoomInOnSqrt2Over2(IntervalScene):
def construct(self):
IntervalScene.construct(self)
epsilon, equals, num = map(tex_mobject, ["\\epsilon", "=", "0.3"])
epsilon, equals, num = map(TexMobject, ["\\epsilon", "=", "0.3"])
equals.next_to(epsilon)
num.next_to(equals)
self.add(CompoundMobject(epsilon, equals, num).center().shift(2*UP))
intervals, lines = self.cover_fractions()
self.remove(*lines)
irr = tex_mobject("\\frac{\\sqrt{2}}{2}")
irr = TexMobject("\\frac{\\sqrt{2}}{2}")
point = self.number_line.number_to_point(np.sqrt(2)/2)
arrow = Arrow(point+UP, point)
irr.next_to(arrow, UP)
@ -1372,9 +1372,9 @@ class ZoomInOnSqrt2Over2(IntervalScene):
class NotCoveredMeansCacophonous(Scene):
def construct(self):
statement1 = text_mobject("$\\frac{\\sqrt{2}}{2}$ is not covered")
implies = tex_mobject("\\Rightarrow")
statement2 = text_mobject("Rationals which are close to $\\frac{\\sqrt{2}}{2}$ must have large denominators")
statement1 = TextMobject("$\\frac{\\sqrt{2}}{2}$ is not covered")
implies = TexMobject("\\Rightarrow")
statement2 = TextMobject("Rationals which are close to $\\frac{\\sqrt{2}}{2}$ must have large denominators")
statement1.to_edge(LEFT)
implies.next_to(statement1)
statement2.next_to(implies)
@ -1401,7 +1401,7 @@ class ShiftSetupByOne(IntervalScene):
self.add(new_interval)
self.number_line.add_numbers(0)
self.remove(*self.number_mobs)
epsilon_mob = tex_mobject("\\epsilon = 0.01").to_edge(UP)
epsilon_mob = TexMobject("\\epsilon = 0.01").to_edge(UP)
self.add(epsilon_mob)
fraction_ticks = self.add_fraction_ticks()
self.remove(fraction_ticks)
@ -1438,7 +1438,7 @@ class ShiftSetupByOne(IntervalScene):
])
self.number_line = new_interval
self.dither()
words = text_mobject(
words = TextMobject(
"Almost all the covered numbers are harmonious!",
size = "\\small"
).shift(2*UP)
@ -1447,20 +1447,20 @@ class ShiftSetupByOne(IntervalScene):
for num in [7, 5]:
point = self.number_line.number_to_point(2**(num/12.))
arrow = Arrow(point+DOWN, point)
mob = tex_mobject(
mob = TexMobject(
"2^{\\left(\\frac{%d}{12}\\right)}"%num
).next_to(arrow, DOWN)
self.play(ShimmerIn(mob), ShowCreation(arrow))
self.dither()
self.remove(mob, arrow)
self.remove(words)
words = text_mobject(
words = TextMobject(
"Cacophonous covered numbers:",
size = "\\small"
)
words.shift(2*UP)
answer1 = text_mobject("Complicated rationals,", size = "\\small")
answer2 = text_mobject(
answer1 = TextMobject("Complicated rationals,", size = "\\small")
answer2 = TextMobject(
"real numbers \\emph{very very very} close to them",
size = "\\small"
)
@ -1476,7 +1476,7 @@ class ShiftSetupByOne(IntervalScene):
self.add(answer2)
self.dither()
self.remove(words, answer1, answer2)
words = text_mobject([
words = TextMobject([
"To a", "savant,", "harmonious numbers could be ",
"\\emph{precisely}", "those 1\\% covered by the intervals"
]).shift(2*UP)
@ -1503,9 +1503,9 @@ class FinalEquivalence(IntervalScene):
interval.scale_in_place(2.0/frac.denominator)
self.remove(*intervals+lines)
intervals = CompoundMobject(*intervals)
arrow = tex_mobject("\\Leftrightarrow")
top_words = text_mobject("Harmonious numbers are rare,")
bot_words = text_mobject("even for the savant")
arrow = TexMobject("\\Leftrightarrow")
top_words = TextMobject("Harmonious numbers are rare,")
bot_words = TextMobject("even for the savant")
bot_words.highlight().next_to(top_words, DOWN)
words = CompoundMobject(top_words, bot_words)
words.next_to(arrow)

View File

@ -187,7 +187,7 @@ class ShowCounting(SceneFromVideo):
total_time = len(self.frames)*self.frame_duration
for count in range(32):
print count
mob = tex_mobject(str(count)).scale(1.5)
mob = TexMobject(str(count)).scale(1.5)
mob.shift(0.3*LEFT).to_edge(UP, buff = 0.1)
index_range = range(
max(COUNT_TO_FRAME_NUM[count]-10, 0),
@ -212,7 +212,7 @@ class ShowFrameNum(SceneFromVideo):
for frame, count in zip(self.frames, it.count()):
print count, "of", len(self.frames)
mob = CompoundMobject(*[
tex_mobject(char).shift(0.3*x*RIGHT)
TexMobject(char).shift(0.3*x*RIGHT)
for char, x, in zip(str(count), it.count())
])
self.frames[count] = disp.paint_mobject(

View File

@ -47,7 +47,7 @@ class Triangle(Polygon):
return self
def add_letter(self, char, nudge = 0.3):
mob = tex_mobject(char).scale(TEX_MOB_SCALE_VAL)
mob = TexMobject(char).scale(TEX_MOB_SCALE_VAL)
if char == "a":
points = self.get_vertices()[[0, 2, 1]]
elif char == "b":
@ -89,7 +89,7 @@ def c_square(**kwargs):
class DrawPointsReference(Scene):
def construct(self):
for point, count in zip(POINTS, it.count()):
mob = tex_mobject(str(count)).scale(TEX_MOB_SCALE_VAL)
mob = TexMobject(str(count)).scale(TEX_MOB_SCALE_VAL)
mob.shift(POINTS[count])
self.add(mob)
@ -104,7 +104,7 @@ class DrawAllThreeSquares(Scene):
c = c_square()
self.add(Triangle(), a, b, c)
for letter, mob in zip("abc", [a, b, c]):
char_mob = tex_mobject(letter+"^2").scale(TEX_MOB_SCALE_VAL)
char_mob = TexMobject(letter+"^2").scale(TEX_MOB_SCALE_VAL)
char_mob.shift(mob.get_center())
self.add(char_mob)
@ -230,13 +230,13 @@ class ShowBigRectangleDimensions(DrawAllThreeSquaresWithMoreTriangles):
args_list = [(10, False)]
def construct(self, num, fill):
DrawAllThreeSquaresWithMoreTriangles.construct(self, num, fill)
u_brace = underbrace((-3, -2, 0), (4, -2, 0))
side_brace = underbrace((-3, -3, 0), (2, -3, 0))
u_brace = Underbrace((-3, -2, 0), (4, -2, 0))
side_brace = Underbrace((-3, -3, 0), (2, -3, 0))
for brace in u_brace, side_brace:
brace.shift(0.2*DOWN)
side_brace.rotate(-np.pi/2)
a_plus_2b = tex_mobject("a+2b").scale(TEX_MOB_SCALE_VAL)
b_plus_2a = tex_mobject("b+2a").scale(TEX_MOB_SCALE_VAL)
a_plus_2b = TexMobject("a+2b").scale(TEX_MOB_SCALE_VAL)
b_plus_2a = TexMobject("b+2a").scale(TEX_MOB_SCALE_VAL)
a_plus_2b.next_to(u_brace, DOWN)
b_plus_2a.next_to(side_brace, LEFT)
self.add_local_mobjects()
@ -263,7 +263,7 @@ class DrawOnlyABSquares(Scene):
a = a_square()
b = b_square()
for char, mob in zip("ab", [a, b]):
symobl = tex_mobject(char+"^2").scale(TEX_MOB_SCALE_VAL)
symobl = TexMobject(char+"^2").scale(TEX_MOB_SCALE_VAL)
symobl.shift(mob.get_center())
self.add(symobl)
triangle = Triangle()
@ -394,8 +394,8 @@ class ZoomInOnTroublePoint(Scene):
for mob in self.mobjects:
mob.rotate(np.pi/2)
if with_labels:
alpha = tex_mobject("\\alpha").scale(TEX_MOB_SCALE_VAL)
beta = tex_mobject("90-\\alpha").scale(TEX_MOB_SCALE_VAL)
alpha = TexMobject("\\alpha").scale(TEX_MOB_SCALE_VAL)
beta = TexMobject("90-\\alpha").scale(TEX_MOB_SCALE_VAL)
if rotate:
alpha.next_to(angle1_arc, UP+0.1*LEFT)
beta.next_to(angle2_arc, DOWN+0.5*LEFT)
@ -427,8 +427,8 @@ class DrawTriangleWithAngles(Scene):
angle2_arc = Circle(radius = 0.2, **kwargs).filter_out(
lambda (x, y, z) : not(x < 0 and y > 0 and y < -3*x)
).shift(vertices[2])
alpha = tex_mobject("\\alpha")
beta = tex_mobject("90-\\alpha")
alpha = TexMobject("\\alpha")
beta = TexMobject("90-\\alpha")
alpha.shift(vertices[1]+3*RIGHT+DOWN)
beta.shift(vertices[2]+3*RIGHT+UP)
arrow1 = Arrow(alpha, angle1_arc)
@ -442,11 +442,11 @@ class LabelLargeSquare(DrawCSquareWithAllTraingles):
def construct(self):
DrawCSquareWithAllTraingles.construct(self)
everything = CompoundMobject(*self.mobjects)
u_brace = underbrace(2*(DOWN+LEFT), 2*(DOWN+RIGHT))
u_brace = Underbrace(2*(DOWN+LEFT), 2*(DOWN+RIGHT))
u_brace.shift(0.2*DOWN)
side_brace = deepcopy(u_brace).rotate(np.pi/2)
upper_brace = deepcopy(u_brace).rotate(np.pi)
a_plus_b = tex_mobject("a+b").scale(TEX_MOB_SCALE_VAL)
a_plus_b = TexMobject("a+b").scale(TEX_MOB_SCALE_VAL)
upper_brace.add(a_plus_b.next_to(upper_brace, UP))
side_brace.add(a_plus_b.next_to(side_brace, RIGHT))
self.add(upper_brace, side_brace)

View File

@ -73,12 +73,12 @@ MOVIE_PREFIX = "tau_poem/"
class Welcome(LogoGeneration):
def construct(self):
text = "Happy $\\tau$ Day, from 3Blue1Brown!"
self.add(text_mobject(text).to_edge(UP))
self.add(TextMobject(text).to_edge(UP))
LogoGeneration.construct(self)
class HappyTauDayWords(Scene):
def construct(self):
words = text_mobject("Happy Tau Day Everybody!").scale(2)
words = TextMobject("Happy Tau Day Everybody!").scale(2)
tau = TauCreature().move_to(2*LEFT + UP)
pi = PiCreature().move_to(2*RIGHT + 3*DOWN)
pi.highlight("red")
@ -128,7 +128,7 @@ class TauPoem(Scene):
self.first_word_to_last_digit()
def add_line_and_number(self):
self.first_digits, new_digit, last_digits = tex_mobject([
self.first_digits, new_digit, last_digits = TexMobject([
"".join(DIGITS[:self.line_num]),
DIGITS[self.line_num],
"".join(DIGITS[(self.line_num+1):]),
@ -140,11 +140,11 @@ class TauPoem(Scene):
index = line_str.index("ders")
else:
index = line_str.index(" ")
first_word, rest_of_line = text_mobject(
first_word, rest_of_line = TextMobject(
[line_str[:index], line_str[index:]]
).to_edge(UP).shift(BUFF*DOWN).split()
first_word.shift(0.15*RIGHT) #Stupid
number_word = text_mobject(DIGIT_TO_WORD[DIGITS[self.line_num][-1]])
number_word = TextMobject(DIGIT_TO_WORD[DIGITS[self.line_num][-1]])
number_word.shift(first_word.get_center())
number_word.shift(BUFF * UP / 2)
@ -178,7 +178,7 @@ class TauPoem(Scene):
)
def line0(self):
two, pi = tex_mobject(["2", "\\pi"]).scale(2).split()
two, pi = TexMobject(["2", "\\pi"]).scale(2).split()
self.add(two, pi)
two_copy = deepcopy(two).rotate(np.pi/10).highlight("yellow")
self.play(Transform(
@ -191,7 +191,7 @@ class TauPoem(Scene):
))
def line1(self):
two_pi = tex_mobject(["2", "\\pi"]).scale(2)
two_pi = TexMobject(["2", "\\pi"]).scale(2)
tau = TauCreature()
tau.to_symbol()
sphere = Mobject()
@ -277,7 +277,7 @@ class TauPoem(Scene):
""")
self.add(pi, bubble)
formulae = tex_mobject(FORMULAE, size = "\\small")
formulae = TexMobject(FORMULAE, size = "\\small")
formulae.scale(1.25)
formulae.to_corner([1, -1, 0])
self.play(FadeIn(formulae))
@ -349,12 +349,12 @@ class TauPoem(Scene):
self.play(WaveArm(tau),Transform(pi, new_pi))
def line10(self):
formulae = tex_mobject(FORMULAE, "\\small")
formulae = TexMobject(FORMULAE, "\\small")
formulae.scale(1.5).to_edge(DOWN)
self.add(formulae)
def line11(self):
formulae = tex_mobject(FORMULAE, "\\small")
formulae = TexMobject(FORMULAE, "\\small")
formulae.scale(1.5).to_edge(DOWN)
formulae = formulae.split()
f_copy = deepcopy(formulae)
@ -391,14 +391,14 @@ class TauPoem(Scene):
)
grid = Grid(radius = radius).shift(grid_center)
circle = Circle().scale(interval_size).shift(grid_center)
grid.add(tex_mobject("e^{ix}").shift(grid_center+UP+RIGHT))
grid.add(TexMobject("e^{ix}").shift(grid_center+UP+RIGHT))
circle.highlight("white")
tau_line = Line(
*[np.pi*interval_size*vect for vect in LEFT, RIGHT],
density = 5*DEFAULT_POINT_DENSITY_1D
)
tau_line.highlight("red")
tau = tex_mobject("\\tau")
tau = TexMobject("\\tau")
tau.shift(tau_line.get_center() + 0.5*UP)
self.add(axes, grid)
@ -423,7 +423,7 @@ class TauPoem(Scene):
def line13(self):
formula = form_start, two_pi, form_end = tex_mobject([
formula = form_start, two_pi, form_end = TexMobject([
"\\hat{f^{(n)}}(\\xi) = (",
"2\\pi",
"i\\xi)^n \\hat{f}(\\xi)"
@ -453,7 +453,7 @@ class TauPoem(Scene):
pi, bubble = self.pi_speaking(
"sticks oddly \\\\ to one half when \\\\ tau's preferred."
)
formula = form_start, half, form_end = tex_mobject([
formula = form_start, half, form_end = TexMobject([
"A = ",
"\\frac{1}{2}",
"\\tau r^2"
@ -464,7 +464,7 @@ class TauPoem(Scene):
self.play(ApplyMethod(half.highlight, "yellow"))
def line16(self):
self.add(tex_mobject(
self.add(TexMobject(
"\\frac{1}{2}\\tau r^2"
).scale(2).shift(DOWN))
@ -489,8 +489,8 @@ class TauPoem(Scene):
-norm,
0
)
tau_r = tex_mobject("\\tau r").shift(1.3*DOWN)
r = tex_mobject("r").shift(0.2*RIGHT + 0.7*DOWN)
tau_r = TexMobject("\\tau r").shift(1.3*DOWN)
r = TexMobject("r").shift(0.2*RIGHT + 0.7*DOWN)
lines = [
Line(DOWN+np.pi*LEFT, DOWN+np.pi*RIGHT),
Line(ORIGIN, DOWN)

View File

@ -1,153 +0,0 @@
from image_mobject import ImageMobject
from helpers import *
#TODO, Cleanup and refactor this file.
#TODO, Make both of these proper mobject classes
def text_mobject(text, size = None):
size = size or "\\Large" #TODO, auto-adjust?
return tex_mobject(text, size, TEMPLATE_TEXT_FILE)
def tex_mobject(expression,
size = None,
template_tex_file = TEMPLATE_TEX_FILE):
if size == None:
if len("".join(expression)) < MAX_LEN_FOR_HUGE_TEX_FONT:
size = "\\Huge"
else:
size = "\\large"
#Todo, make this more sophisticated.
image_files = tex_to_image(expression, size, template_tex_file)
config = {
"point_thickness" : 1,
"should_center" : False,
}
if isinstance(image_files, list):
#TODO, is checking listiness really the best here?
result = CompoundMobject(*[
ImageMobject(f, **config)
for f in image_files
])
else:
result = ImageMobject(image_files, **config)
return result.center().highlight("white")
def underbrace(left, right, buff = 0.2):
result = tex_mobject("\\underbrace{%s}"%(14*"\\quad"))
result.stretch_to_fit_width(right[0]-left[0])
result.shift(left - result.points[0] + buff*DOWN)
return result
def tex_to_image(expression,
size = "\HUGE",
template_tex_file = TEMPLATE_TEX_FILE):
"""
Returns list of images for correpsonding with a list of expressions
"""
return_list = isinstance(expression, list)
simple_tex = "".join(expression)
if return_list:
expression = tex_expression_list_as_string(expression)
exp_hash = str(hash(expression + size))
image_dir = os.path.join(TEX_IMAGE_DIR, exp_hash)
if os.path.exists(image_dir):
result = [
os.path.join(image_dir, png_file)
for png_file in sorted(
os.listdir(image_dir),
cmp_enumerated_files
)
]
else:
filestem = os.path.join(TEX_DIR, exp_hash)
if not os.path.exists(filestem + ".tex"):
print "Writing %s at size %s to %s.tex"%(
simple_tex, size, filestem
)
with open(template_tex_file, "r") as infile:
body = infile.read()
body = body.replace(SIZE_TO_REPLACE, size)
body = body.replace(TEX_TEXT_TO_REPLACE, expression)
with open(filestem + ".tex", "w") as outfile:
outfile.write(body)
if not os.path.exists(filestem + ".dvi"):
commands = [
"latex",
"-interaction=batchmode",
"-output-directory=" + TEX_DIR,
filestem + ".tex",
"> /dev/null"
]
#TODO, Error check
os.system(" ".join(commands))
result = dvi_to_png(filestem + ".dvi")
return result if return_list else result[0]
def tex_expression_list_as_string(expression):
return "\n".join([
"\onslide<%d>{"%count + exp + "}"
for count, exp in zip(it.count(1), expression)
])
def dvi_to_png(filename, regen_if_exists = False):
"""
Converts a dvi, which potentially has multiple slides, into a
directory full of enumerated pngs corresponding with these slides.
Returns a list of PIL Image objects for these images sorted as they
where in the dvi
"""
possible_paths = [
filename,
os.path.join(TEX_DIR, filename),
os.path.join(TEX_DIR, filename + ".dvi"),
]
for path in possible_paths:
if os.path.exists(path):
directory, filename = os.path.split(path)
name = filename.split(".")[0]
images_dir = os.path.join(TEX_IMAGE_DIR, name)
if not os.path.exists(images_dir):
os.mkdir(images_dir)
if os.listdir(images_dir) == [] or regen_if_exists:
commands = [
"convert",
"-density",
str(PDF_DENSITY),
path,
"-size",
str(DEFAULT_WIDTH) + "x" + str(DEFAULT_HEIGHT),
os.path.join(images_dir, name + ".png")
]
os.system(" ".join(commands))
image_paths = [
os.path.join(images_dir, name)
for name in os.listdir(images_dir)
if name.endswith(".png")
]
image_paths.sort(cmp_enumerated_files)
return image_paths
raise IOError("File not Found")
def cmp_enumerated_files(name1, name2):
num1, num2 = [
int(name.split(".")[0].split("-")[-1])
for name in (name1, name2)
]
return num1 - num2

View File

@ -4,6 +4,7 @@ import itertools as it
from helpers import *
from scene import Scene
from animation import Animation
from mobject import TexMobject
class RearrangeEquation(Scene):
def construct(
@ -67,8 +68,8 @@ class RearrangeEquation(Scene):
"""
num_start_terms = len(start_terms)
all_mobs = np.array(
tex_mobject(start_terms, size = size).split() + \
tex_mobject(end_terms, size = size).split()
TexMobject(start_terms, size = size).split() + \
TexMobject(end_terms, size = size).split()
)
all_terms = np.array(start_terms+end_terms)
for term in set(all_terms):
@ -88,7 +89,7 @@ class FlipThroughSymbols(Animation):
"end_center" : ORIGIN,
}
def __init__(self, tex_list, **kwargs):
mobject = tex_mobject(self.curr_tex).shift(start_center)
mobject = TexMobject(self.curr_tex).shift(start_center)
Animation.__init__(self, mobject, **kwargs)
def update_mobject(self, alpha):
@ -96,7 +97,7 @@ class FlipThroughSymbols(Animation):
if new_tex != self.curr_tex:
self.curr_tex = new_tex
self.mobject = tex_mobject(new_tex).shift(self.start_center)
self.mobject = TexMobject(new_tex).shift(self.start_center)
if not all(self.start_center == self.end_center):
self.mobject.center().shift(
(1-alpha)*self.start_center + alpha*self.end_center

View File

@ -33,7 +33,7 @@ class PiCreature(CompoundMobject):
self.mouth.center()
self.smile = deepcopy(self.mouth)
self.frown = deepcopy(self.mouth).rotate(np.pi, RIGHT)
self.straight_mouth = tex_mobject("-").scale(0.5)
self.straight_mouth = TexMobject("-").scale(0.5)
for mouth_name in ["mouth"] + self.MOUTH_NAMES:
mouth = getattr(self, mouth_name)
mouth.sort_points(lambda p : p[0])
@ -211,7 +211,7 @@ class Bubble(Mobject):
return self
def write(self, text):
self.add_content(text_mobject(text))
self.add_content(TextMobject(text))
return self
def clear(self):

View File

@ -40,7 +40,7 @@ class CountingScene(Scene):
self.add(*mobjects)
for mob, num in zip(mobjects, it.count(1)):
if display_numbers:
num_mob = tex_mobject(str(num))
num_mob = TexMobject(str(num))
num_mob.center().shift(num_offset)
self.add(num_mob)
if mode == "highlight":
@ -69,7 +69,7 @@ class CountingScene(Scene):
raise Warning("Unknown mode")
frame_time = run_time / (len(regions))
for region, count in zip(regions, it.count(1)):
num_mob = tex_mobject(str(count))
num_mob = TexMobject(str(count))
num_mob.center().shift(num_offset)
self.add(num_mob)
self.highlight_region(region)
@ -112,7 +112,7 @@ class PascalsTriangleScene(Scene):
num = choose(n, k)
center = self.coords_to_center(n, k)
if num not in num_to_num_mob:
num_to_num_mob[num] = tex_mobject(str(num))
num_to_num_mob[num] = TexMobject(str(num))
num_mob = deepcopy(num_to_num_mob[num])
scale_factor = min(
1,
@ -135,7 +135,7 @@ class PascalsTriangleScene(Scene):
def generate_n_choose_k_mobs(self):
self.coords_to_n_choose_k = {}
for n, k in self.coords:
nck_mob = tex_mobject(r"{%d \choose %d}"%(n, k))
nck_mob = TexMobject(r"{%d \choose %d}"%(n, k))
scale_factor = min(
1,
self.portion_to_fill * self.cell_height / nck_mob.get_height(),
@ -148,7 +148,7 @@ class PascalsTriangleScene(Scene):
self.coords_to_n_choose_k[n][k] = nck_mob
def generate_sea_of_zeros(self):
zero = tex_mobject("0")
zero = TexMobject("0")
self.sea_of_zeros = []
for n in range(self.nrows):
for a in range((self.nrows - n)/2 + 1):

View File

@ -49,7 +49,7 @@ class ComplexPlane(NumberPlane):
num_str = "0"
else:
num_str = str(number).replace("j", "i")
num = tex_mobject(num_str)
num = TexMobject(num_str)
num.scale(self.number_scale_factor)
num.shift(point-num.get_corner(UP+LEFT)+nudge)
result.append(num)
@ -167,7 +167,7 @@ class ComplexMultiplication(Scene):
radius = 0.1*self.plane.unit_to_spatial_width,
color = BLUE if value == 1 else YELLOW
)
label = tex_mobject(tex_string)
label = TexMobject(tex_string)
label.shift(dot.get_center()+1.5*UP+RIGHT)
arrow = Arrow(label, dot)
self.add(label)

View File

@ -1,6 +1,6 @@
from helpers import *
from mobject import Mobject1D
from mobject import Mobject1D, TexMobject
from scene import Scene
class NumberLine(Mobject1D):
@ -80,7 +80,7 @@ class NumberLine(Mobject1D):
numbers = self.default_numbers_to_display()
result = []
for number in numbers:
mob = tex_mobject(str(int(number)))
mob = TexMobject(str(int(number)))
vert_scale = 2*self.tick_size/mob.get_height()
hori_scale = self.tick_frequency*self.unit_length_to_spatial_width/mob.get_width()
mob.scale(min(vert_scale, hori_scale))
@ -187,7 +187,7 @@ class NumberPlane(Mobject1D):
for val in vals:
num_pair[index] = val
point = self.num_pair_to_point(num_pair)
num = tex_mobject(str(val))
num = TexMobject(str(val))
num.scale(self.number_scale_factor)
num.shift(point-num.get_corner(UP+LEFT)+nudge)
result.append(num)