2015-08-07 18:10:00 -07:00
|
|
|
import numpy as np
|
|
|
|
import itertools as it
|
|
|
|
|
2015-10-28 16:03:33 -07:00
|
|
|
from helpers import *
|
2015-08-07 18:10:00 -07:00
|
|
|
from scene import Scene
|
2015-10-27 21:00:50 -07:00
|
|
|
from animation import Animation
|
2015-10-28 17:18:50 -07:00
|
|
|
from mobject import TexMobject
|
2015-08-07 18:10:00 -07:00
|
|
|
|
|
|
|
class RearrangeEquation(Scene):
|
|
|
|
def construct(
|
|
|
|
self,
|
|
|
|
start_terms,
|
|
|
|
end_terms,
|
|
|
|
index_map,
|
|
|
|
size = None,
|
2015-10-20 21:55:46 -07:00
|
|
|
path = counterclockwise_path(),
|
2015-08-07 18:10:00 -07:00
|
|
|
start_transform = None,
|
|
|
|
end_transform = None,
|
|
|
|
leave_start_terms = False,
|
|
|
|
transform_kwargs = {},
|
|
|
|
):
|
2016-01-01 14:51:16 -08:00
|
|
|
transform_kwargs["path_func"] = path
|
2015-08-07 18:10:00 -07:00
|
|
|
start_mobs, end_mobs = self.get_mobs_from_terms(
|
|
|
|
start_terms, end_terms, size
|
|
|
|
)
|
|
|
|
if start_transform:
|
2015-11-02 13:03:01 -08:00
|
|
|
start_mobs = start_transform(Mobject(*start_mobs)).split()
|
2015-08-07 18:10:00 -07:00
|
|
|
if end_transform:
|
2015-11-02 13:03:01 -08:00
|
|
|
end_mobs = end_transform(Mobject(*end_mobs)).split()
|
2015-08-07 18:10:00 -07:00
|
|
|
unmatched_start_indices = set(range(len(start_mobs)))
|
|
|
|
unmatched_end_indices = set(range(len(end_mobs)))
|
|
|
|
unmatched_start_indices.difference_update(
|
|
|
|
[n%len(start_mobs) for n in index_map]
|
|
|
|
)
|
|
|
|
unmatched_end_indices.difference_update(
|
|
|
|
[n%len(end_mobs) for n in index_map.values()]
|
|
|
|
)
|
|
|
|
mobject_pairs = [
|
|
|
|
(start_mobs[a], end_mobs[b])
|
|
|
|
for a, b in index_map.iteritems()
|
|
|
|
]+ [
|
|
|
|
(Point(end_mobs[b].get_center()), end_mobs[b])
|
|
|
|
for b in unmatched_end_indices
|
|
|
|
]
|
|
|
|
if not leave_start_terms:
|
|
|
|
mobject_pairs += [
|
|
|
|
(start_mobs[a], Point(start_mobs[a].get_center()))
|
|
|
|
for a in unmatched_start_indices
|
|
|
|
]
|
|
|
|
|
|
|
|
self.add(*start_mobs)
|
|
|
|
if leave_start_terms:
|
2015-11-02 13:03:01 -08:00
|
|
|
self.add(Mobject(*start_mobs))
|
2015-08-07 18:10:00 -07:00
|
|
|
self.dither()
|
2015-09-25 19:43:53 -07:00
|
|
|
self.play(*[
|
2015-08-07 18:10:00 -07:00
|
|
|
Transform(*pair, **transform_kwargs)
|
|
|
|
for pair in mobject_pairs
|
|
|
|
])
|
|
|
|
self.dither()
|
|
|
|
|
|
|
|
|
|
|
|
def get_mobs_from_terms(self, start_terms, end_terms, size):
|
|
|
|
"""
|
|
|
|
Need to ensure that all image mobjects for a tex expression
|
|
|
|
stemming from the same string are point-for-point copies of one
|
|
|
|
and other. This makes transitions much smoother, and not look
|
|
|
|
like point-clouds.
|
|
|
|
"""
|
|
|
|
num_start_terms = len(start_terms)
|
|
|
|
all_mobs = np.array(
|
2015-10-28 17:18:50 -07:00
|
|
|
TexMobject(start_terms, size = size).split() + \
|
|
|
|
TexMobject(end_terms, size = size).split()
|
2015-08-07 18:10:00 -07:00
|
|
|
)
|
|
|
|
all_terms = np.array(start_terms+end_terms)
|
|
|
|
for term in set(all_terms):
|
|
|
|
matches = all_terms == term
|
|
|
|
if sum(matches) > 1:
|
|
|
|
base_mob = all_mobs[list(all_terms).index(term)]
|
|
|
|
all_mobs[matches] = [
|
2015-11-02 19:09:55 -08:00
|
|
|
base_mob.copy().replace(target_mob)
|
2015-08-07 18:10:00 -07:00
|
|
|
for target_mob in all_mobs[matches]
|
|
|
|
]
|
|
|
|
return all_mobs[:num_start_terms], all_mobs[num_start_terms:]
|
|
|
|
|
|
|
|
|
2015-10-27 21:00:50 -07:00
|
|
|
class FlipThroughSymbols(Animation):
|
2016-02-27 16:32:53 -08:00
|
|
|
CONFIG = {
|
2015-10-27 21:00:50 -07:00
|
|
|
"start_center" : ORIGIN,
|
|
|
|
"end_center" : ORIGIN,
|
|
|
|
}
|
|
|
|
def __init__(self, tex_list, **kwargs):
|
2015-10-28 17:18:50 -07:00
|
|
|
mobject = TexMobject(self.curr_tex).shift(start_center)
|
2015-10-27 21:00:50 -07:00
|
|
|
Animation.__init__(self, mobject, **kwargs)
|
|
|
|
|
|
|
|
def update_mobject(self, alpha):
|
|
|
|
new_tex = self.tex_list[np.ceil(alpha*len(self.tex_list))-1]
|
2015-08-07 18:10:00 -07:00
|
|
|
|
2015-10-27 21:00:50 -07:00
|
|
|
if new_tex != self.curr_tex:
|
|
|
|
self.curr_tex = new_tex
|
2015-10-28 17:18:50 -07:00
|
|
|
self.mobject = TexMobject(new_tex).shift(self.start_center)
|
2015-10-27 21:00:50 -07:00
|
|
|
if not all(self.start_center == self.end_center):
|
|
|
|
self.mobject.center().shift(
|
|
|
|
(1-alpha)*self.start_center + alpha*self.end_center
|
|
|
|
)
|
2015-08-07 18:10:00 -07:00
|
|
|
|
|
|
|
|
|
|
|
|