mirror of
https://github.com/3b1b/manim.git
synced 2025-07-29 13:03:31 +08:00
Mobjects now contain submobjects, giving a heirarchy. Thus CompoundMobject is replaced simply with Mobject, and display etc. needed updating
This commit is contained in:
10
displayer.py
10
displayer.py
@ -37,7 +37,7 @@ def paint_region(region, image_array = None, color = None):
|
||||
def paint_mobject(mobject, image_array = None):
|
||||
return paint_mobjects([mobject], image_array)
|
||||
|
||||
def paint_mobjects(mobjects, image_array = None):
|
||||
def paint_mobjects(mobjects, image_array = None, include_sub_mobjects = True):
|
||||
pixels = get_pixels(image_array)
|
||||
height = pixels.shape[0]
|
||||
width = pixels.shape[1]
|
||||
@ -45,6 +45,13 @@ def paint_mobjects(mobjects, image_array = None):
|
||||
space_width = SPACE_HEIGHT * width / height
|
||||
pixels = pixels.reshape((pixels.size/3, 3)).astype('uint8')
|
||||
|
||||
if include_sub_mobjects:
|
||||
all_families = [
|
||||
mob.get_full_submobject_family()
|
||||
for mob in mobjects
|
||||
]
|
||||
mobjects = reduce(op.add, all_families, [])
|
||||
|
||||
for mobject in mobjects:
|
||||
if mobject.get_num_points() == 0:
|
||||
continue
|
||||
@ -73,7 +80,6 @@ def paint_mobjects(mobjects, image_array = None):
|
||||
flattener = np.array([[1], [width]], dtype = 'int')
|
||||
indices = np.dot(points, flattener)[:,0]
|
||||
pixels[indices] = rgbs.astype('uint8')
|
||||
|
||||
return pixels.reshape((height, width, 3))
|
||||
|
||||
def add_thickness(pixel_indices_and_rgbs, thickness, width, height):
|
||||
|
12
helpers.py
12
helpers.py
@ -11,8 +11,18 @@ import re
|
||||
|
||||
from constants import *
|
||||
|
||||
def remove_list_redundancies(l):
|
||||
"""
|
||||
Used instead of lsit(set(l)) to maintain order
|
||||
"""
|
||||
return sorted(list(set(l)), lambda a, b : l.index(a) - l.index(b))
|
||||
|
||||
def list_update(l1, l2):
|
||||
return filter(lambda e : e not in l2, l1) + l2
|
||||
"""
|
||||
Used instead of list(set(l1).update(l2)) to maintain order,
|
||||
making sure duplicates are removed from l1, not l2.
|
||||
"""
|
||||
return filter(lambda e : e not in l2, l1) + list(l2)
|
||||
|
||||
def all_elements_are_instances(iterable, Class):
|
||||
return all(map(lambda e : isinstance(e, Class), iterable))
|
||||
|
@ -23,24 +23,79 @@ class Mobject(object):
|
||||
"name" : None,
|
||||
}
|
||||
DIM = 3
|
||||
def __init__(self, **kwargs):
|
||||
def __init__(self, *sub_mobjects, **kwargs):
|
||||
digest_config(self, kwargs)
|
||||
self.sub_mobjects = list(sub_mobjects)
|
||||
self.color = Color(self.color)
|
||||
if self.name is None:
|
||||
self.name = self.__class__.__name__
|
||||
self.has_normals = hasattr(self, 'unit_normal')
|
||||
self.init_points()
|
||||
self.generate_points()
|
||||
if self.has_normals:
|
||||
self.unit_normals = np.apply_along_axis(
|
||||
self.unit_normal,
|
||||
1,
|
||||
self.points,
|
||||
)
|
||||
|
||||
def init_points(self):
|
||||
self.points = np.zeros((0, 3))
|
||||
self.rgbs = np.zeros((0, 3))
|
||||
if self.has_normals:
|
||||
self.unit_normals = np.zeros((0, 3))
|
||||
for attr in self.get_array_attrs():
|
||||
setattr(self, attr, np.zeros((0, 3)))
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def add_points(self, points, rgbs = None, color = None):
|
||||
"""
|
||||
points must be a Nx3 numpy array, as must rgbs if it is not None
|
||||
"""
|
||||
if not isinstance(points, np.ndarray):
|
||||
points = np.array(points)
|
||||
num_new_points = points.shape[0]
|
||||
self.points = np.append(self.points, points, axis = 0)
|
||||
if rgbs is None:
|
||||
color = Color(color) if color else self.color
|
||||
rgbs = np.array([color.get_rgb()] * num_new_points)
|
||||
elif rgbs.shape != points.shape:
|
||||
raise Exception("points and rgbs must have same shape")
|
||||
self.rgbs = np.append(self.rgbs, rgbs, axis = 0)
|
||||
if self.has_normals:
|
||||
self.unit_normals = np.append(
|
||||
self.unit_normals,
|
||||
np.apply_along_axis(self.unit_normal, 1, points),
|
||||
axis = 0
|
||||
)
|
||||
return self
|
||||
|
||||
def add(self, *mobjects):
|
||||
self.sub_mobjects = list_update(self.sub_mobjects, mobjects)
|
||||
return self
|
||||
|
||||
def get_array_attrs(self):
|
||||
result = ["points", "rgbs"]
|
||||
if self.has_normals:
|
||||
result.append("unit_normals")
|
||||
return result
|
||||
|
||||
def digest_mobject_attrs(self):
|
||||
"""
|
||||
Ensures all attributes which are mobjects are included
|
||||
in the sub_mobjects list.
|
||||
"""
|
||||
mobject_attrs = filter(
|
||||
lambda x : isinstance(x, Mobject),
|
||||
self.__dict__.values()
|
||||
)
|
||||
self.sub_mobjects = list_update(self.sub_mobjects, mobject_attrs)
|
||||
return self
|
||||
|
||||
|
||||
def apply_over_attr_arrays(self, func):
|
||||
for attr in self.get_array_attrs(self):
|
||||
setattr(self, attr, func(getattr(self, attr)))
|
||||
return self
|
||||
|
||||
def show(self):
|
||||
Image.fromarray(disp.paint_mobject(self)).show()
|
||||
|
||||
@ -49,42 +104,98 @@ class Mobject(object):
|
||||
os.path.join(MOVIE_DIR, (name or str(self)) + ".png")
|
||||
)
|
||||
|
||||
def add_points(self, points, rgbs = None, color = None):
|
||||
|
||||
#### Fundamental operations ######
|
||||
|
||||
def shift(self, *vectors):
|
||||
total_vector = reduce(op.add, vectors)
|
||||
for mob in self.get_full_submobject_family():
|
||||
mob.points += total_vector
|
||||
return self
|
||||
|
||||
def scale(self, scale_factor):
|
||||
for mob in self.get_full_submobject_family():
|
||||
mob.points *= scale_factor
|
||||
return self
|
||||
|
||||
def rotate(self, angle, axis = OUT):
|
||||
t_rotation_matrix = np.transpose(rotation_matrix(angle, axis))
|
||||
for mob in self.get_full_submobject_family():
|
||||
mob.points = np.dot(mob.points, t_rotation_matrix)
|
||||
if mob.has_normals:
|
||||
mob.unit_normals = np.dot(mob.unit_normals, t_rotation_matrix)
|
||||
return self
|
||||
|
||||
def stretch(self, factor, dim):
|
||||
for mob in self.get_full_submobject_family():
|
||||
mob.points[:,dim] *= factor
|
||||
return self
|
||||
|
||||
def apply_function(self, function):
|
||||
for mob in self.get_full_submobject_family():
|
||||
mob.points = np.apply_along_axis(function, 1, mob.points)
|
||||
return self
|
||||
|
||||
def wag(self, direction = RIGHT, axis = DOWN, wag_factor = 1.0):
|
||||
for mob in self.get_full_submobject_family():
|
||||
alphas = np.dot(mob.points, np.transpose(axis))
|
||||
alphas -= min(alphas)
|
||||
alphas /= max(alphas)
|
||||
alphas = alphas**wag_factor
|
||||
mob.points += np.dot(
|
||||
alphas.reshape((len(alphas), 1)),
|
||||
np.array(direction).reshape((1, mob.DIM))
|
||||
)
|
||||
return self
|
||||
|
||||
def highlight(self, color = "yellow", condition = None):
|
||||
"""
|
||||
points must be a Nx3 numpy array, as must rgbs if it is not None
|
||||
Condition is function which takes in one arguments, (x, y, z).
|
||||
"""
|
||||
points = np.array(points)
|
||||
num_new_points = points.shape[0]
|
||||
self.points = np.append(self.points, points)
|
||||
self.points = self.points.reshape((self.points.size / 3, 3))
|
||||
if rgbs is None:
|
||||
color = Color(color) if color else self.color
|
||||
rgbs = np.array([color.get_rgb()] * num_new_points)
|
||||
rgb = Color(color).get_rgb()
|
||||
for mob in self.get_full_submobject_family():
|
||||
if condition:
|
||||
to_change = np.apply_along_axis(condition, 1, mob.points)
|
||||
mob.rgbs[to_change, :] = rgb
|
||||
else:
|
||||
if rgbs.shape != points.shape:
|
||||
raise Exception("points and rgbs must have same shape")
|
||||
self.rgbs = np.append(self.rgbs, rgbs)
|
||||
self.rgbs = self.rgbs.reshape((self.rgbs.size / 3, 3))
|
||||
if self.has_normals:
|
||||
self.unit_normals = np.append(
|
||||
self.unit_normals,
|
||||
np.array([self.unit_normal(point) for point in points])
|
||||
).reshape(self.points.shape)
|
||||
mob.rgbs[:,:] = rgb
|
||||
return self
|
||||
|
||||
def add(self, *mobjects):
|
||||
for mobject in mobjects:
|
||||
self.add_points(mobject.points, mobject.rgbs)
|
||||
def filter_out(self, condition):
|
||||
for mob in self.get_full_submobject_family():
|
||||
to_eliminate = ~np.apply_along_axis(condition, 1, mob.points)
|
||||
mob.points = mob.points[to_eliminate]
|
||||
mob.rgbs = mob.rgbs[to_eliminate]
|
||||
return self
|
||||
|
||||
def sort_points(self, function = lambda p : p[0]):
|
||||
"""
|
||||
function is any map from R^3 to R
|
||||
"""
|
||||
for mob in self.get_full_submobject_family():
|
||||
indices = range(len(mob.points))
|
||||
indices.sort(
|
||||
lambda *pair : cmp(*map(function, mob.points[pair, :]))
|
||||
)
|
||||
mob.points = mob.points[indices]
|
||||
mob.rgbs = mob.rgbs[indices]
|
||||
return self
|
||||
|
||||
def repeat(self, count):
|
||||
#Can make transition animations nicer
|
||||
points, rgbs = deepcopy(self.points), deepcopy(self.rgbs)
|
||||
for x in range(count - 1):
|
||||
self.add_points(points, rgbs)
|
||||
"""
|
||||
This can make transition animations nicer
|
||||
"""
|
||||
def repeat_array(array):
|
||||
return reduce(
|
||||
lambda a1, a2 : np.append(a1, a2, axis = 0),
|
||||
[array]*count
|
||||
)
|
||||
for mob in self.get_full_submobject_family():
|
||||
mob.apply_over_attr_arrays(repeat_array)
|
||||
return self
|
||||
|
||||
#### In place operations ######
|
||||
|
||||
def do_in_place(self, method, *args, **kwargs):
|
||||
center = self.get_center()
|
||||
self.shift(-center)
|
||||
@ -92,96 +203,50 @@ class Mobject(object):
|
||||
self.shift(center)
|
||||
return self
|
||||
|
||||
def rotate(self, angle, axis = OUT):
|
||||
t_rotation_matrix = np.transpose(rotation_matrix(angle, axis))
|
||||
self.points = np.dot(self.points, t_rotation_matrix)
|
||||
if self.has_normals:
|
||||
self.unit_normals = np.dot(self.unit_normals, t_rotation_matrix)
|
||||
return self
|
||||
|
||||
def rotate_in_place(self, angle, axis = OUT):
|
||||
self.do_in_place(self.rotate, angle, axis)
|
||||
return self
|
||||
|
||||
def shift(self, vector):
|
||||
self.points += vector
|
||||
return self
|
||||
|
||||
def wag(self, wag_direction = RIGHT, wag_axis = DOWN,
|
||||
wag_factor = 1.0):
|
||||
alphas = np.dot(self.points, np.transpose(wag_axis))
|
||||
alphas -= min(alphas)
|
||||
alphas /= max(alphas)
|
||||
alphas = alphas**wag_factor
|
||||
self.points += np.dot(
|
||||
alphas.reshape((len(alphas), 1)),
|
||||
np.array(wag_direction).reshape((1, self.DIM))
|
||||
)
|
||||
return self
|
||||
|
||||
def center(self):
|
||||
self.shift(-self.get_center())
|
||||
return self
|
||||
|
||||
#Wrapper functions for better naming
|
||||
def to_corner(self, corner = LEFT+DOWN, buff = DEFAULT_MOBJECT_TO_EDGE_BUFFER):
|
||||
return self.align_on_border(corner, buff)
|
||||
|
||||
def to_edge(self, edge = LEFT, buff = DEFAULT_MOBJECT_TO_EDGE_BUFFER):
|
||||
return self.align_on_border(edge, buff)
|
||||
|
||||
def align_on_border(self, direction, buff = DEFAULT_MOBJECT_TO_EDGE_BUFFER):
|
||||
"""
|
||||
Direction just needs to be a vector pointing towards side or
|
||||
corner in the 2d plane.
|
||||
"""
|
||||
shift_val = np.zeros(3)
|
||||
space_dim = (SPACE_WIDTH, SPACE_HEIGHT)
|
||||
for i in [0, 1]:
|
||||
if direction[i] == 0:
|
||||
continue
|
||||
elif direction[i] > 0:
|
||||
shift_val[i] = space_dim[i]-buff-max(self.points[:,i])
|
||||
else:
|
||||
shift_val[i] = -space_dim[i]+buff-min(self.points[:,i])
|
||||
self.shift(shift_val)
|
||||
return self
|
||||
|
||||
def next_to(self, mobject,
|
||||
direction = RIGHT,
|
||||
buff = DEFAULT_MOBJECT_TO_MOBJECT_BUFFER,
|
||||
aligned_edge = None):
|
||||
direction = direction / np.linalg.norm(direction)
|
||||
if aligned_edge is not None:
|
||||
anchor_point = self.get_corner(aligned_edge-direction)
|
||||
target_point = mobject.get_corner(aligned_edge+direction)
|
||||
elif list(direction) in map(list, [LEFT, RIGHT, UP, DOWN]):
|
||||
anchor_point = self.get_edge_center(-direction)
|
||||
target_point = mobject.get_edge_center(direction)
|
||||
else:
|
||||
anchor_point = self.get_boundary_point(-direction)
|
||||
target_point = mobject.get_boundary_point(direction)
|
||||
self.shift(target_point - anchor_point + buff*direction)
|
||||
return self
|
||||
|
||||
def scale(self, scale_factor):
|
||||
self.points *= scale_factor
|
||||
return self
|
||||
|
||||
def scale_in_place(self, scale_factor):
|
||||
self.do_in_place(self.scale, scale_factor)
|
||||
return self
|
||||
|
||||
def stretch(self, factor, dim):
|
||||
self.points[:,dim] *= factor
|
||||
def pose_at_angle(self):
|
||||
self.rotate_in_place(np.pi / 7, RIGHT+UP)
|
||||
return self
|
||||
|
||||
def center(self):
|
||||
self.shift(-self.get_center())
|
||||
return self
|
||||
|
||||
def align_on_border(self, direction, buff = DEFAULT_MOBJECT_TO_EDGE_BUFFER):
|
||||
"""
|
||||
Direction just needs to be a vector pointing towards side or
|
||||
corner in the 2d plane.
|
||||
"""
|
||||
target_point = np.sign(direction) * (SPACE_WIDTH, SPACE_HEIGHT, 0)
|
||||
anchor_point = self.get_critical_point(direction)
|
||||
self.shift(target - anchor_point - buff * np.array(direction))
|
||||
return self
|
||||
|
||||
def to_corner(self, corner = LEFT+DOWN, buff = DEFAULT_MOBJECT_TO_EDGE_BUFFER):
|
||||
return self.align_on_border(corner, buff)
|
||||
|
||||
def to_edge(self, edge = LEFT, buff = DEFAULT_MOBJECT_TO_EDGE_BUFFER):
|
||||
return self.align_on_border(edge, buff)
|
||||
|
||||
def next_to(self, mobject,
|
||||
direction = RIGHT,
|
||||
buff = DEFAULT_MOBJECT_TO_MOBJECT_BUFFER,
|
||||
aligned_edge = ORIGIN):
|
||||
anchor_point = self.get_critical_point(aligned_edge-direction)
|
||||
target_point = mobject.get_critical_point(aligned_edge+direction)
|
||||
self.shift(target_point - anchor_point + buff*direction)
|
||||
return self
|
||||
|
||||
def stretch_to_fit(self, length, dim):
|
||||
center = self.get_center()
|
||||
old_length = max(self.points[:,dim]) - min(self.points[:,dim])
|
||||
self.center()
|
||||
self.stretch(length/old_length, dim)
|
||||
self.shift(center)
|
||||
old_length = self.length_over_dim(dim)
|
||||
self.do_in_place(self.stretch, length/old_length, dim)
|
||||
return self
|
||||
|
||||
def stretch_to_fit_width(self, width):
|
||||
@ -196,11 +261,6 @@ class Mobject(object):
|
||||
def scale_to_fit_height(self, height):
|
||||
return self.scale(height/self.get_height())
|
||||
|
||||
def pose_at_angle(self):
|
||||
self.rotate(np.pi / 7)
|
||||
self.rotate(np.pi / 7, [1, 0, 0])
|
||||
return self
|
||||
|
||||
def replace(self, mobject, stretch = False):
|
||||
if mobject.get_num_points() == 0:
|
||||
raise Warning("Attempting to replace mobject with no points")
|
||||
@ -213,27 +273,11 @@ class Mobject(object):
|
||||
self.center().shift(mobject.get_center())
|
||||
return self
|
||||
|
||||
def apply_function(self, function):
|
||||
self.points = np.apply_along_axis(function, 1, self.points)
|
||||
return self
|
||||
|
||||
def apply_complex_function(self, function):
|
||||
return self.apply_function(
|
||||
lambda (x, y, z) : complex_to_R3(function(complex(x, y)))
|
||||
)
|
||||
|
||||
def highlight(self, color = "yellow", condition = None):
|
||||
"""
|
||||
Condition is function which takes in one arguments, (x, y, z).
|
||||
"""
|
||||
rgb = Color(color).get_rgb()
|
||||
if condition:
|
||||
to_change = np.apply_along_axis(condition, 1, self.points)
|
||||
self.rgbs[to_change, :] = rgb
|
||||
else:
|
||||
self.rgbs[:,:] = rgb
|
||||
return self
|
||||
|
||||
def set_color(self, color):
|
||||
self.highlight(color)
|
||||
self.color = Color(color)
|
||||
@ -245,59 +289,92 @@ class Mobject(object):
|
||||
|
||||
def fade_to(self, color, alpha):
|
||||
self.rgbs = interpolate(self.rgbs, Color(color).rgb, alpha)
|
||||
for mob in self.sub_mobjects:
|
||||
mob.fade_to(color, alpha)
|
||||
return self
|
||||
|
||||
def fade(self, brightness = 0.5):
|
||||
self.rgbs *= brightness
|
||||
self.fade_to(BLACK, brightness)
|
||||
return self
|
||||
|
||||
def filter_out(self, condition):
|
||||
to_eliminate = ~np.apply_along_axis(condition, 1, self.points)
|
||||
self.points = self.points[to_eliminate]
|
||||
self.rgbs = self.rgbs[to_eliminate]
|
||||
return self
|
||||
def reduce_across_dimension(self, points_func, reduce_func, dim):
|
||||
try:
|
||||
values = [points_func(self.points[:, dim])]
|
||||
except:
|
||||
values = []
|
||||
values += [
|
||||
mob.reduce_across_dimension(points_func, reduce_func, dim)
|
||||
for mob in self.sub_mobjects
|
||||
]
|
||||
try:
|
||||
return reduce_func(values)
|
||||
except:
|
||||
return 0
|
||||
|
||||
def sort_points(self, function = lambda p : p[0]):
|
||||
"""
|
||||
function is any map from R^3 to R
|
||||
"""
|
||||
indices = range(self.get_num_points())
|
||||
indices.sort(
|
||||
lambda *pair : cmp(*map(function, self.points[pair, :]))
|
||||
def get_merged_array(self, array_attr):
|
||||
return reduce(
|
||||
lambda a1, a2 : np.append(a1, a2, axis = 0),
|
||||
[getattr(self, array_attr)] + [
|
||||
mob.get_merged_array(array_attr)
|
||||
for mob in self.sub_mobjects
|
||||
]
|
||||
)
|
||||
self.points = self.points[indices]
|
||||
self.rgbs = self.rgbs[indices]
|
||||
|
||||
def get_all_points(self):
|
||||
return self.get_merged_array("points")
|
||||
|
||||
def ingest_sub_mobjects(self):
|
||||
for attr in self.get_array_attrs():
|
||||
setattr(self, attr, get_merged_array(attr))
|
||||
self.sub_mobjects = []
|
||||
return self
|
||||
|
||||
def split(self):
|
||||
result = [self] if len(self.points) > 0 else []
|
||||
return result + self.sub_mobjects
|
||||
|
||||
def get_full_submobject_family(self):
|
||||
sub_families = map(Mobject.get_full_submobject_family, self.sub_mobjects)
|
||||
all_mobjects = [self] + reduce(op.add, sub_families, [])
|
||||
return remove_list_redundancies(all_mobjects)
|
||||
|
||||
### Getters ###
|
||||
|
||||
def get_num_points(self):
|
||||
return len(self.points)
|
||||
def get_num_points(self, including_submobjects = False):
|
||||
return self.reduce_across_dimension(len, sum, 0)
|
||||
|
||||
def get_center(self):
|
||||
if self.get_num_points() == 0:
|
||||
return ORIGIN
|
||||
return (np.max(self.points, 0) + np.min(self.points, 0))/2.0
|
||||
def get_critical_point(self, direction):
|
||||
result = np.zeros(self.DIM)
|
||||
for dim in [0, 1]:
|
||||
if direction[dim] <= 0:
|
||||
min_point = self.reduce_across_dimension(np.min, np.min, dim)
|
||||
if direction[dim] >= 0:
|
||||
max_point = self.reduce_across_dimension(np.max, np.max, dim)
|
||||
|
||||
def get_center_of_mass(self):
|
||||
return np.apply_along_axis(np.mean, 0, self.points)
|
||||
|
||||
def get_boundary_point(self, direction):
|
||||
return self.points[np.argmax(np.dot(self.points, direction))]
|
||||
|
||||
def get_edge_center(self, direction):
|
||||
dim = np.argmax(map(abs, direction))
|
||||
max_or_min_func = np.max if direction[dim] > 0 else np.min
|
||||
result = self.get_center()
|
||||
result[dim] = max_or_min_func(self.points[:,dim])
|
||||
if direction[dim] == 0:
|
||||
result[dim] = (max_point+min_point)/2
|
||||
elif direction[dim] < 0:
|
||||
result[dim] = min_point
|
||||
else:
|
||||
result[dim] = max_point
|
||||
return result
|
||||
|
||||
# Pseudonyms for more general get_critical_point method
|
||||
def get_edge_center(self, direction):
|
||||
return self.get_critical_point(direction)
|
||||
|
||||
def get_corner(self, direction):
|
||||
return sum([
|
||||
self.get_edge_center(RIGHT*direction[0]),
|
||||
self.get_edge_center(UP*direction[1]),
|
||||
-self.get_center()
|
||||
])
|
||||
return self.get_critical_point(direction)
|
||||
|
||||
def get_center(self):
|
||||
return self.get_critical_point(np.zeros(self.DIM))
|
||||
|
||||
def get_center_of_mass(self):
|
||||
return np.apply_along_axis(np.mean, 0, self.get_all_points())
|
||||
|
||||
def get_boundary_point(self, direction):
|
||||
all_points = self.get_all_points()
|
||||
return all_points[np.argmax(np.dot(all_points, direction))]
|
||||
|
||||
def get_top(self):
|
||||
return self.get_edge_center(UP)
|
||||
@ -311,11 +388,18 @@ class Mobject(object):
|
||||
def get_left(self):
|
||||
return self.get_edge_center(LEFT)
|
||||
|
||||
def length_over_dim(self, dim):
|
||||
return (
|
||||
self.reduce_across_dimension(np.max, np.max, dim) -
|
||||
self.reduce_across_dimension(np.min, np.min, dim)
|
||||
)
|
||||
|
||||
def get_width(self):
|
||||
return np.max(self.points[:, 0]) - np.min(self.points[:, 0])
|
||||
return self.length_over_dim(0)
|
||||
|
||||
def get_height(self):
|
||||
return np.max(self.points[:, 1]) - np.min(self.points[:, 1])
|
||||
return self.length_over_dim(1)
|
||||
|
||||
|
||||
def get_color(self):
|
||||
color = Color()
|
||||
@ -346,7 +430,7 @@ class Mobject(object):
|
||||
and mobject2.
|
||||
"""
|
||||
Mobject.align_data(mobject1, mobject2)
|
||||
for attr in ['points', 'rgbs']:
|
||||
for attr in self.get_array_attrs():
|
||||
setattr(target_mobject, attr, interpolate(
|
||||
getattr(mobject1, attr),
|
||||
getattr(mobject2, attr),
|
||||
@ -380,29 +464,6 @@ class Mobject2D(Mobject):
|
||||
self.epsilon = 1.0 / self.density
|
||||
Mobject.__init__(self, **kwargs)
|
||||
|
||||
class CompoundMobject(Mobject):
|
||||
def __init__(self, *mobjects):
|
||||
Mobject.__init__(self)
|
||||
self.original_mobs_num_points = []
|
||||
for mobject in mobjects:
|
||||
self.original_mobs_num_points.append(mobject.points.shape[0])
|
||||
self.add_points(mobject.points, mobject.rgbs)
|
||||
self.point_thickness = max([
|
||||
m.point_thickness
|
||||
for m in mobjects
|
||||
])
|
||||
|
||||
def split(self):
|
||||
result = []
|
||||
curr = 0
|
||||
for num_points in self.original_mobs_num_points:
|
||||
result.append(Mobject().add_points(
|
||||
self.points[curr:curr+num_points, :],
|
||||
self.rgbs[curr:curr+num_points, :]
|
||||
))
|
||||
curr += num_points
|
||||
return result
|
||||
|
||||
|
||||
class Point(Mobject):
|
||||
DEFAULT_CONFIG = {
|
||||
@ -415,47 +476,6 @@ class Point(Mobject):
|
||||
def generate_points(self):
|
||||
self.add_points([self.location])
|
||||
|
||||
# class CompoundMobject(Mobject):
|
||||
# """
|
||||
# Treats a collection of mobjects as if they were one.
|
||||
|
||||
# A weird form of inhertance is at play here...
|
||||
# """
|
||||
# def __init__(self, *mobjects):
|
||||
# Mobject.__init__(self)
|
||||
# self.mobjects = mobjects
|
||||
# name_to_method = dict(
|
||||
# inspect.getmembers(Mobject, predicate = inspect.ismethod)
|
||||
# )
|
||||
# names = name_to_method.keys()
|
||||
# #Most reductions take the form of mapping a given method across
|
||||
# #all constituent mobjects, then just returning self.
|
||||
# name_to_reduce = dict([
|
||||
# (name, lambda list : self)
|
||||
# for name in names
|
||||
# ])
|
||||
# name_to_reduce.update(self.get_special_reduce_functions())
|
||||
# def make_pseudo_method(name):
|
||||
# return lambda *args, **kwargs : name_to_reduce[name]([
|
||||
# name_to_method[name](mob, *args, **kwargs)
|
||||
# for mob in self.mobjects
|
||||
# ])
|
||||
# for name in names:
|
||||
# setattr(self, name, make_pseudo_method(name))
|
||||
|
||||
# def show(self):
|
||||
|
||||
|
||||
# def get_special_reduce_functions(self):
|
||||
# return {}
|
||||
|
||||
# def handle_method(self, method_name, *args, **kwargs):
|
||||
# pass
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -198,7 +198,7 @@ class ShowFrameNum(OverHand):
|
||||
OverHand.construct(self)
|
||||
for frame, count in zip(self.frames, it.count()):
|
||||
print count, "of", len(self.frames)
|
||||
mob = CompoundMobject(*[
|
||||
mob = Mobject(*[
|
||||
TexMobject(char).shift(0.3*x*RIGHT)
|
||||
for char, x, in zip(str(count), it.count())
|
||||
])
|
||||
@ -212,12 +212,12 @@ class CountTo1023(Scene):
|
||||
rh_map = get_hand_map("right")
|
||||
lh_map = get_hand_map("left")
|
||||
def get_num(count):
|
||||
return CompoundMobject(*[
|
||||
return Mobject(*[
|
||||
TexMobject(char).shift(0.35*x*RIGHT)
|
||||
for char, x, in zip(str(count), it.count())
|
||||
]).center().to_edge(UP)
|
||||
self.frames = [
|
||||
disp.paint_mobject(CompoundMobject(
|
||||
disp.paint_mobject(Mobject(
|
||||
rh_map[count%32], lh_map[count//32], get_num(count)
|
||||
))
|
||||
for count in range(2**10)
|
||||
@ -360,7 +360,7 @@ class ShowIncrementRule(Scene):
|
||||
(2.25, 3.5, 0),
|
||||
(1.5, 0.75, 0),
|
||||
]
|
||||
return CompoundMobject(*[
|
||||
return Mobject(*[
|
||||
deepcopy(arrow).shift(tip)
|
||||
for tip in tips
|
||||
])
|
||||
@ -379,7 +379,7 @@ class MindFindsShortcuts(Scene):
|
||||
hand = Hand(7).scale(0.5).center().shift(DOWN+2*LEFT)
|
||||
sum421 = TexMobject("4+2+1").shift(DOWN+2*RIGHT)
|
||||
seven = TexMobject("7").shift(DOWN+6*RIGHT)
|
||||
compound = CompoundMobject(
|
||||
compound = Mobject(
|
||||
Arrow(hand, sum421),
|
||||
sum421,
|
||||
Arrow(sum421, seven)
|
||||
@ -438,7 +438,7 @@ class CountingExampleSentence(ShowCounting):
|
||||
ShowCounting.construct(self)
|
||||
|
||||
def get_counting_mob(self, num):
|
||||
return CompoundMobject(*self.words[:num])
|
||||
return Mobject(*self.words[:num])
|
||||
|
||||
class FinishCountingExampleSentence(Scene):
|
||||
def construct(self):
|
||||
@ -449,7 +449,7 @@ class FinishCountingExampleSentence(Scene):
|
||||
two = TexMobject("2").shift([3, 3.65, 0])
|
||||
eightteen = TexMobject("18").shift([1.5, 2.5, 0])
|
||||
eightteen.sort_points()
|
||||
comp = CompoundMobject(sixteen, two)
|
||||
comp = Mobject(sixteen, two)
|
||||
self.add(hand, comp, words)
|
||||
self.dither()
|
||||
self.play(Transform(comp, eightteen))
|
||||
|
@ -50,7 +50,7 @@ class PreferOtherProofDialogue(Scene):
|
||||
self.dither(2)
|
||||
self.play(Transform(
|
||||
Dot(student_bubble.tip).highlight("black"),
|
||||
CompoundMobject(student_bubble, student_bubble.text)
|
||||
Mobject(student_bubble, student_bubble.text)
|
||||
))
|
||||
self.dither(2)
|
||||
self.remove(teacher_bubble.text)
|
||||
@ -81,7 +81,7 @@ class IllustrateDuality(GraphScene):
|
||||
for edge_pair in zip(self.edges, self.dual_edges)
|
||||
] + [
|
||||
Transform(
|
||||
CompoundMobject(*[
|
||||
Mobject(*[
|
||||
self.vertices[index]
|
||||
for index in cycle
|
||||
]),
|
||||
@ -143,7 +143,7 @@ class IntroduceGraph(GraphScene):
|
||||
self.add(not_okay)
|
||||
self.remove(*edges_to_remove)
|
||||
self.play(ShowCreation(
|
||||
CompoundMobject(*edges_to_remove),
|
||||
Mobject(*edges_to_remove),
|
||||
alpha_func = lambda t : 1 - t,
|
||||
run_time = 1.0
|
||||
))
|
||||
@ -182,10 +182,10 @@ class PlanarGraphDefinition(Scene):
|
||||
"Not \\\\", "``", "Planar", "''",
|
||||
# "no matter how \\\\ hard you try"
|
||||
]).split()
|
||||
shift_val = CompoundMobject(Not, planar).to_corner().get_center()
|
||||
shift_val = Mobject(Not, planar).to_corner().get_center()
|
||||
Not.highlight("red").shift(shift_val)
|
||||
graphs = [
|
||||
CompoundMobject(*GraphScene(g).mobjects)
|
||||
Mobject(*GraphScene(g).mobjects)
|
||||
for g in [
|
||||
CubeGraph(),
|
||||
CompleteGraph(5),
|
||||
@ -227,7 +227,7 @@ class TerminologyFromPolyhedra(GraphScene):
|
||||
point / 2 + OUT if abs(point[0]) == 2 else point + IN
|
||||
for point in self.points
|
||||
]
|
||||
cube = CompoundMobject(*[
|
||||
cube = Mobject(*[
|
||||
Line(vertices[edge[0]], vertices[edge[1]])
|
||||
for edge in self.graph.edges
|
||||
])
|
||||
@ -258,7 +258,7 @@ class TerminologyFromPolyhedra(GraphScene):
|
||||
self.remove(dots_to_vertices, *self.vertices)
|
||||
self.add(lines_to_edges)
|
||||
self.play(ApplyMethod(
|
||||
CompoundMobject(*self.edges).highlight, "yellow"
|
||||
Mobject(*self.edges).highlight, "yellow"
|
||||
))
|
||||
self.dither(2)
|
||||
self.clear()
|
||||
@ -312,7 +312,7 @@ class ThreePiecesOfTerminology(GraphScene):
|
||||
|
||||
self.clear()
|
||||
self.play(ApplyMethod(
|
||||
CompoundMobject(*terms).center
|
||||
Mobject(*terms).center
|
||||
))
|
||||
self.dither()
|
||||
|
||||
@ -361,14 +361,14 @@ class PathExamples(GraphScene):
|
||||
mob.to_edge(UP)
|
||||
kwargs = {"run_time" : 1.0}
|
||||
for path, non_path in zip(paths, non_paths):
|
||||
path_lines = CompoundMobject(*[
|
||||
path_lines = Mobject(*[
|
||||
Line(
|
||||
self.points[path[i]],
|
||||
self.points[path[i+1]]
|
||||
).highlight("yellow")
|
||||
for i in range(len(path) - 1)
|
||||
])
|
||||
non_path_lines = CompoundMobject(*[
|
||||
non_path_lines = Mobject(*[
|
||||
Line(
|
||||
self.points[pp[0]],
|
||||
self.points[pp[1]],
|
||||
@ -430,7 +430,7 @@ class DefineSpanningTree(GraphScene):
|
||||
randy.scale(RANDOLPH_SCALE_VAL).move_to(self.points[0])
|
||||
dollar_signs = TextMobject("\\$\\$")
|
||||
dollar_signs.scale(EDGE_ANNOTATION_SCALE_VAL)
|
||||
dollar_signs = CompoundMobject(*[
|
||||
dollar_signs = Mobject(*[
|
||||
deepcopy(dollar_signs).shift(edge.get_center())
|
||||
for edge in self.edges
|
||||
])
|
||||
@ -494,8 +494,8 @@ class NamingTree(GraphScene):
|
||||
|
||||
self.add(*branches)
|
||||
self.play(
|
||||
FadeOut(CompoundMobject(*self.edges + self.vertices)),
|
||||
Animation(CompoundMobject(*branches)),
|
||||
FadeOut(Mobject(*self.edges + self.vertices)),
|
||||
Animation(Mobject(*branches)),
|
||||
)
|
||||
self.clear()
|
||||
self.add(tree, *branches)
|
||||
@ -599,7 +599,7 @@ class FacebookGraphAsAbstractSet(Scene):
|
||||
accounts.shift(3*LEFT).to_edge(UP)
|
||||
friendships = TextMobject("\\textbf{Friendships}")
|
||||
friendships.shift(3*RIGHT).to_edge(UP)
|
||||
lines = CompoundMobject(
|
||||
lines = Mobject(
|
||||
Line(UP*SPACE_HEIGHT, DOWN*SPACE_HEIGHT),
|
||||
Line(LEFT*SPACE_WIDTH + 3*UP, RIGHT*SPACE_WIDTH + 3*UP)
|
||||
).highlight("white")
|
||||
@ -622,7 +622,7 @@ class ExamplesOfGraphs(GraphScene):
|
||||
)
|
||||
GraphScene.construct(self)
|
||||
self.generate_regions()
|
||||
objects, notions = CompoundMobject(*TextMobject(
|
||||
objects, notions = Mobject(*TextMobject(
|
||||
["Objects \\quad\\quad ", "Thing that connects objects"]
|
||||
)).to_corner().shift(0.5*RIGHT).split()
|
||||
horizontal_line = Line(
|
||||
@ -687,8 +687,8 @@ class ExamplesOfGraphs(GraphScene):
|
||||
]
|
||||
]
|
||||
|
||||
comp_words = CompoundMobject(*words)
|
||||
comp_lines = CompoundMobject(*lines)
|
||||
comp_words = Mobject(*words)
|
||||
comp_lines = Mobject(*lines)
|
||||
self.add(words1)
|
||||
self.play(ShowCreation(comp_words, run_time = 1.0))
|
||||
self.dither()
|
||||
@ -852,7 +852,7 @@ class ListOfCorrespondances(Scene):
|
||||
left.shift((min(arrow_xs) - SPACE_WIDTH, 0, 0))
|
||||
right.to_edge(LEFT)
|
||||
right.shift((max(arrow_xs) + SPACE_WIDTH, 0, 0))
|
||||
lines.append(CompoundMobject(left, right, this_arrow))
|
||||
lines.append(Mobject(left, right, this_arrow))
|
||||
last = None
|
||||
for line in lines:
|
||||
self.add(line.highlight("yellow"))
|
||||
@ -892,7 +892,7 @@ class CyclesCorrespondWithConnectedComponents(GraphScene):
|
||||
self.highlight_region(region)
|
||||
self.dither(2)
|
||||
self.reset_background()
|
||||
lines = CompoundMobject(*[
|
||||
lines = Mobject(*[
|
||||
Line(self.dual_points[last], self.dual_points[next])
|
||||
for last, next in zip(dual_cycle, dual_cycle[1:])
|
||||
]).highlight("red")
|
||||
@ -1015,7 +1015,7 @@ class RandolphMortimerSpanningTreeGame(GraphScene):
|
||||
cycle_index = region_ordering[-1]
|
||||
cycle = self.graph.region_cycles[cycle_index]
|
||||
self.highlight_region(self.regions[cycle_index], "black")
|
||||
self.play(ShowCreation(CompoundMobject(*[
|
||||
self.play(ShowCreation(Mobject(*[
|
||||
Line(self.points[last], self.points[next]).highlight("green")
|
||||
for last, next in zip(cycle, list(cycle)[1:] + [cycle[0]])
|
||||
])))
|
||||
@ -1116,7 +1116,7 @@ class DualSpanningTree(GraphScene):
|
||||
""").to_edge(UP)
|
||||
|
||||
self.add(self.spanning_tree, randy, morty)
|
||||
self.play(ShowCreation(CompoundMobject(
|
||||
self.play(ShowCreation(Mobject(
|
||||
*np.array(self.edges)[dual_edges]
|
||||
).highlight("red")))
|
||||
self.add(words)
|
||||
@ -1147,7 +1147,7 @@ class TreeCountFormula(Scene):
|
||||
self.remove(*all_dots)
|
||||
self.play(
|
||||
FadeOut(text),
|
||||
FadeIn(CompoundMobject(*gs.edges + gs.vertices)),
|
||||
FadeIn(Mobject(*gs.edges + gs.vertices)),
|
||||
*[
|
||||
Transform(*pair)
|
||||
for pair in zip(branches,gs.spanning_tree.split())
|
||||
@ -1162,7 +1162,7 @@ class FinalSum(Scene):
|
||||
"(\\text{Number of Mortimer's Edges}) + 1 &= F \\\\ \n",
|
||||
" \\Downarrow \\\\", "E","+","2","&=","V","+","F",
|
||||
], size = "\\large").split()
|
||||
for line in lines[:2] + [CompoundMobject(*lines[2:])]:
|
||||
for line in lines[:2] + [Mobject(*lines[2:])]:
|
||||
self.add(line)
|
||||
self.dither()
|
||||
self.dither()
|
||||
|
@ -96,7 +96,7 @@ def zero_to_one_interval():
|
||||
interval.elongate_tick_at(INTERVAL_RADIUS, 4)
|
||||
zero = TexMobject("0").shift(INTERVAL_RADIUS*LEFT+DOWN)
|
||||
one = TexMobject("1").shift(INTERVAL_RADIUS*RIGHT+DOWN)
|
||||
return CompoundMobject(interval, zero, one)
|
||||
return Mobject(interval, zero, one)
|
||||
|
||||
def draw_you(with_bubble = False):
|
||||
result = PiCreature()
|
||||
@ -175,7 +175,7 @@ class IntroduceDivergentSum(Scene):
|
||||
self.add(brace, sum_value)
|
||||
self.dither(0.75)
|
||||
self.remove(sum_value)
|
||||
ellipses = CompoundMobject(
|
||||
ellipses = Mobject(
|
||||
*[equation[NUM_WRITTEN_TERMS + i] for i in range(3)]
|
||||
)
|
||||
end_brace = deepcopy(brace).stretch_to_fit_width(
|
||||
@ -264,7 +264,7 @@ class OutlineOfVideo(Scene):
|
||||
]
|
||||
last_one_split = texts[-1].split()
|
||||
last_one_split[1].highlight("skyblue")
|
||||
texts[-1] = CompoundMobject(*last_one_split)
|
||||
texts[-1] = Mobject(*last_one_split)
|
||||
texts[0].shift(overbrace.get_top()+texts[0].get_height()*UP)
|
||||
texts[1].shift(sum([
|
||||
arrow.get_boundary_point(DOWN+RIGHT),
|
||||
@ -335,7 +335,7 @@ class OutlineOfVideo(Scene):
|
||||
# self.add(sum_mob)
|
||||
# self.play(FadeIn(discover))
|
||||
# self.dither()
|
||||
# self.play(FadeIn(CompoundMobject(*define_parts)))
|
||||
# self.play(FadeIn(Mobject(*define_parts)))
|
||||
# self.dither()
|
||||
|
||||
class YouAsMathematician(Scene):
|
||||
@ -376,7 +376,7 @@ class YouAsMathematician(Scene):
|
||||
self.remove(bubble, *equation_parts)
|
||||
self.disapproving_friend()
|
||||
self.add(bubble, equation)
|
||||
self.play(Transform(equation, CompoundMobject(*dot_pair)))
|
||||
self.play(Transform(equation, Mobject(*dot_pair)))
|
||||
self.remove(equation)
|
||||
self.add(*dot_pair)
|
||||
two_arrows = [
|
||||
@ -386,7 +386,7 @@ class YouAsMathematician(Scene):
|
||||
self.play(*[ShowCreation(a) for a in two_arrows])
|
||||
self.play(BlinkPiCreature(you))
|
||||
self.remove(*dot_pair+two_arrows)
|
||||
everything = CompoundMobject(*self.mobjects)
|
||||
everything = Mobject(*self.mobjects)
|
||||
self.clear()
|
||||
self.play(
|
||||
ApplyPointwiseFunction(
|
||||
@ -559,7 +559,7 @@ class OrganizePartialSums(Scene):
|
||||
|
||||
self.play(ShowCreation(dots))
|
||||
self.dither()
|
||||
self.play(FadeIn(CompoundMobject(down_arrow, infinite_sum)))
|
||||
self.play(FadeIn(Mobject(down_arrow, infinite_sum)))
|
||||
self.dither()
|
||||
|
||||
class SeeNumbersApproachOne(Scene):
|
||||
@ -569,7 +569,7 @@ class SeeNumbersApproachOne(Scene):
|
||||
arrow.shift(DOWN).highlight("yellow")
|
||||
num_dots = 6
|
||||
colors = Color("green").range_to("yellow", num_dots)
|
||||
dots = CompoundMobject(*[
|
||||
dots = Mobject(*[
|
||||
Dot(
|
||||
density = 2*DEFAULT_POINT_DENSITY_1D
|
||||
).scale(1+1.0/2.0**x).shift(
|
||||
@ -682,7 +682,7 @@ class ListOfPartialSums(Scene):
|
||||
self.play(ShowCreation(dots))
|
||||
self.dither()
|
||||
self.play(
|
||||
FadeIn(CompoundMobject(*equals)),
|
||||
FadeIn(Mobject(*equals)),
|
||||
*[
|
||||
Transform(deepcopy(number), finite_sum)
|
||||
for number, finite_sum in zip(numbers, sums)
|
||||
@ -712,7 +712,7 @@ class ShowDecreasingDistance(Scene):
|
||||
lines = [vert_line0, vert_line1, horiz_line]
|
||||
for line in lines:
|
||||
line.highlight("green")
|
||||
dots = CompoundMobject(*[
|
||||
dots = Mobject(*[
|
||||
Dot().scale(1.0/(n+1)).shift((1+partial_sum(n))*RIGHT)
|
||||
for n in range(10)
|
||||
])
|
||||
@ -734,7 +734,7 @@ class ShowDecreasingDistance(Scene):
|
||||
class CircleZoomInOnOne(Scene):
|
||||
def construct(self):
|
||||
number_line = NumberLine(interval_size = 1).add_numbers()
|
||||
dots = CompoundMobject(*[
|
||||
dots = Mobject(*[
|
||||
Dot().scale(1.0/(n+1)).shift((1+partial_sum(n))*RIGHT)
|
||||
for n in range(10)
|
||||
])
|
||||
@ -849,7 +849,7 @@ class DefineInfiniteSum(Scene):
|
||||
"\\sum_{n = 0}^\\infty a_n = X"
|
||||
]).split()
|
||||
define.highlight("skyblue")
|
||||
expression = CompoundMobject(define, infinite_sum)
|
||||
expression = Mobject(define, infinite_sum)
|
||||
|
||||
self.add(expression)
|
||||
self.dither()
|
||||
@ -1041,7 +1041,7 @@ class ChopIntervalInProportions(Scene):
|
||||
FadeIn(rt[0]),
|
||||
Transform(
|
||||
brace_to_replace.repeat(2),
|
||||
CompoundMobject(*braces)
|
||||
Mobject(*braces)
|
||||
),
|
||||
FadeIn(left_paren),
|
||||
FadeIn(right_paren),
|
||||
@ -1052,7 +1052,7 @@ class ChopIntervalInProportions(Scene):
|
||||
self.play(
|
||||
Transform(
|
||||
term_to_replace,
|
||||
CompoundMobject(lt[0], rt[1])
|
||||
Mobject(lt[0], rt[1])
|
||||
),
|
||||
FadeOut(left_paren),
|
||||
FadeOut(right_paren)
|
||||
@ -1064,26 +1064,26 @@ class ChopIntervalInProportions(Scene):
|
||||
FadeIn(rt[0]),
|
||||
Transform(
|
||||
brace_to_replace.repeat(2),
|
||||
CompoundMobject(*braces)
|
||||
Mobject(*braces)
|
||||
),
|
||||
Transform(
|
||||
term_to_replace,
|
||||
CompoundMobject(lt[0], rt[1])
|
||||
Mobject(lt[0], rt[1])
|
||||
),
|
||||
*additional_anims
|
||||
)
|
||||
self.remove(*lt+rt)
|
||||
lt, rt = CompoundMobject(*lt), CompoundMobject(*rt)
|
||||
lt, rt = Mobject(*lt), Mobject(*rt)
|
||||
self.add(lt, rt)
|
||||
else:
|
||||
self.play(
|
||||
Transform(
|
||||
brace_to_replace.repeat(2),
|
||||
CompoundMobject(*braces)
|
||||
Mobject(*braces)
|
||||
),
|
||||
Transform(
|
||||
term_to_replace,
|
||||
CompoundMobject(lt, rt)
|
||||
Mobject(lt, rt)
|
||||
),
|
||||
*additional_anims
|
||||
)
|
||||
@ -1379,10 +1379,10 @@ class SumPowersOfTwoAnimation(Scene):
|
||||
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()
|
||||
top_sum = Mobject(*full_top_sum[:n]).center()
|
||||
top_sum_end = deepcopy(full_top_sum[n]).center()
|
||||
top_sum.shift(topbrace.get_center()+0.5*UP)
|
||||
new_top_sum = CompoundMobject(*full_top_sum[:(n+1)]).center()
|
||||
new_top_sum = Mobject(*full_top_sum[:(n+1)]).center()
|
||||
self.add(top_sum, bottom_num)
|
||||
|
||||
if n == iterations:
|
||||
@ -1390,7 +1390,7 @@ class SumPowersOfTwoAnimation(Scene):
|
||||
new_dot = deepcopy(dot).shift(circle.get_center())
|
||||
shift_val = (2**n)*(dot_width+dot_buff)
|
||||
right += shift_val
|
||||
new_dots = CompoundMobject(new_dot, curr_dots)
|
||||
new_dots = Mobject(new_dot, curr_dots)
|
||||
new_dots.highlight(colors.next()).shift(shift_val)
|
||||
alt_bottombrace = deepcopy(bottombrace).shift(shift_val)
|
||||
alt_bottom_num = deepcopy(bottom_num).shift(shift_val)
|
||||
@ -1408,7 +1408,7 @@ class SumPowersOfTwoAnimation(Scene):
|
||||
if exp.get_width() > brace.get_width():
|
||||
exp.stretch_to_fit_width(brace.get_width())
|
||||
new_top_sum = new_top_sum.split()
|
||||
new_top_sum_start = CompoundMobject(*new_top_sum[:-1])
|
||||
new_top_sum_start = Mobject(*new_top_sum[:-1])
|
||||
new_top_sum_end = new_top_sum[-1]
|
||||
|
||||
self.dither()
|
||||
@ -1438,7 +1438,7 @@ class SumPowersOfTwoAnimation(Scene):
|
||||
top_sum_end, new_top_sum_end,
|
||||
alt_topbrace, alt_bottombrace
|
||||
)
|
||||
curr_dots = CompoundMobject(curr_dots, new_dots)
|
||||
curr_dots = Mobject(curr_dots, new_dots)
|
||||
|
||||
|
||||
class PretendTheyDoApproachNegativeOne(RearrangeEquation):
|
||||
@ -1730,7 +1730,7 @@ class RoomsAndSubrooms(Scene):
|
||||
]
|
||||
|
||||
for group in rectangle_groups:
|
||||
mob = CompoundMobject(*group)
|
||||
mob = Mobject(*group)
|
||||
mob.sort_points(np.linalg.norm)
|
||||
self.play(ShowCreation(mob))
|
||||
|
||||
@ -1945,7 +1945,7 @@ class DeduceWhereNegativeOneFalls(Scene):
|
||||
colors = list(get_room_colors())
|
||||
num_labels = len(colors)
|
||||
texts = [
|
||||
CompoundMobject(parts[0], parts[1].highlight(color))
|
||||
Mobject(parts[0], parts[1].highlight(color))
|
||||
for count, color in zip(it.count(), colors)
|
||||
for parts in [TextMobject([
|
||||
"Represented (heuristically) \\\\ by being in the same \\\\",
|
||||
@ -2025,7 +2025,7 @@ class PAdicMetric(Scene):
|
||||
self.play(DelayByOrder(Transform(curr, prime)))
|
||||
self.dither()
|
||||
if count == 2:
|
||||
self.spill(CompoundMobject(curr, text), arrow, new_numbers)
|
||||
self.spill(Mobject(curr, text), arrow, new_numbers)
|
||||
self.remove(curr)
|
||||
curr = prime
|
||||
self.play(DelayByOrder(Transform(curr, p_str)))
|
||||
@ -2052,7 +2052,7 @@ class FuzzyDiscoveryToNewMath(Scene):
|
||||
fuzzy.to_edge(UP).shift(SPACE_WIDTH*LEFT/2)
|
||||
new_math = TextMobject("New Math")
|
||||
new_math.to_edge(UP).shift(SPACE_WIDTH*RIGHT/2)
|
||||
lines = CompoundMobject(
|
||||
lines = Mobject(
|
||||
Line(DOWN*SPACE_HEIGHT, UP*SPACE_HEIGHT),
|
||||
Line(3*UP+LEFT*SPACE_WIDTH, 3*UP+RIGHT*SPACE_WIDTH)
|
||||
)
|
||||
@ -2071,7 +2071,7 @@ class FuzzyDiscoveryToNewMath(Scene):
|
||||
line.highlight("blue")
|
||||
char_mob = TexMobject(char).scale(0.25)
|
||||
line.add(char_mob.shift(line.get_center()))
|
||||
triangle = CompoundMobject(*triangle_lines)
|
||||
triangle = Mobject(*triangle_lines)
|
||||
triangle.center().shift(1.5*fuzzy_discoveries[0].get_right())
|
||||
how_length = TextMobject("But how is length defined?").scale(0.5)
|
||||
how_length.shift(0.75*DOWN)
|
||||
|
@ -48,7 +48,7 @@ def count_sections(*radians):
|
||||
else:
|
||||
sc.animate(ShowCreation(dots[x]))
|
||||
sc.add(dots[x])
|
||||
new_lines = CompoundMobject(*[
|
||||
new_lines = Mobject(*[
|
||||
Line(points[x], points[y]) for y in xrange(x)
|
||||
])
|
||||
sc.animate(Transform(deepcopy(dots[x]), new_lines, run_time = 2.0))
|
||||
@ -86,7 +86,7 @@ def summarize_pattern(*radians):
|
||||
dots = [Dot(point) for point in points]
|
||||
last_num = None
|
||||
for x in xrange(len(points)):
|
||||
new_lines = CompoundMobject(*[
|
||||
new_lines = Mobject(*[
|
||||
Line(points[x], points[y]) for y in xrange(x)
|
||||
])
|
||||
num = TexMobject(str(moser_function(x + 1))).center()
|
||||
@ -116,7 +116,7 @@ def connect_points(*radians):
|
||||
all_lines = []
|
||||
for x in xrange(len(points)):
|
||||
lines = [Line(points[x], points[y]) for y in range(len(points))]
|
||||
lines = CompoundMobject(*lines)
|
||||
lines = Mobject(*lines)
|
||||
anims.append(Transform(deepcopy(dots[x]), lines, run_time = 3.0))
|
||||
all_lines.append(lines)
|
||||
sc.animate(*anims)
|
||||
@ -127,13 +127,13 @@ def connect_points(*radians):
|
||||
def interesting_problems():
|
||||
sc = Scene()
|
||||
locales = [(6, 2, 0), (6, -2, 0), (-5, -2, 0)]
|
||||
fermat = CompoundMobject(*TexMobjects(["x^n","+","y^n","=","z^n"]))
|
||||
fermat = Mobject(*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))
|
||||
sb = SpeechBubble().shift((-2.4, 1.3, 0))
|
||||
fermat_copies, face_copies, tb_copies, sb_copies = (
|
||||
CompoundMobject(*[
|
||||
Mobject(*[
|
||||
deepcopy(mob).scale(0.5).shift(locale)
|
||||
for locale in locales
|
||||
])
|
||||
@ -162,11 +162,11 @@ def interesting_problems():
|
||||
def response_invitation():
|
||||
sc = Scene()
|
||||
video_icon = VideoIcon()
|
||||
mini_videos = CompoundMobject(*[
|
||||
mini_videos = Mobject(*[
|
||||
deepcopy(video_icon).scale(0.5).shift((3, y, 0))
|
||||
for y in [-2, 0, 2]
|
||||
])
|
||||
comments = CompoundMobject(*[
|
||||
comments = Mobject(*[
|
||||
Line((-1.2, y, 0), (1.2, y, 0), color = 'white')
|
||||
for y in [-1.5, -1.75, -2]
|
||||
])
|
||||
@ -191,7 +191,7 @@ def different_points(radians1, radians2):
|
||||
for radians in (radians1, radians2)
|
||||
)
|
||||
dots1, dots2 = (
|
||||
CompoundMobject(*[Dot(point) for point in points])
|
||||
Mobject(*[Dot(point) for point in points])
|
||||
for points in (points1, points2)
|
||||
)
|
||||
lines1, lines2 = (
|
||||
@ -219,14 +219,14 @@ def next_few_videos(*radians):
|
||||
(RADIUS * np.cos(angle), RADIUS * np.sin(angle), 0)
|
||||
for angle in radians
|
||||
]
|
||||
dots = CompoundMobject(*[
|
||||
dots = Mobject(*[
|
||||
Dot(point) for point in points
|
||||
])
|
||||
lines = CompoundMobject(*[
|
||||
lines = Mobject(*[
|
||||
Line(point1, point2)
|
||||
for point1, point2 in it.combinations(points, 2)
|
||||
])
|
||||
thumbnail = CompoundMobject(circle, dots, lines)
|
||||
thumbnail = Mobject(circle, dots, lines)
|
||||
frame = VideoIcon().highlight(
|
||||
"black",
|
||||
lambda point : np.linalg.norm(point) < 0.5
|
||||
|
@ -176,7 +176,7 @@ class HardProblemsSimplerQuestions(Scene):
|
||||
fermat = dict([
|
||||
(
|
||||
sym,
|
||||
CompoundMobject(*TexMobjects(
|
||||
Mobject(*TexMobjects(
|
||||
["x","^"+sym,"+","y","^"+sym,"=","z","^"+sym]
|
||||
))
|
||||
)
|
||||
@ -234,7 +234,7 @@ class HardProblemsSimplerQuestions(Scene):
|
||||
self.add(fermat["n"], fermat2, fermat3)
|
||||
self.dither()
|
||||
|
||||
circle_grid = CompoundMobject(
|
||||
circle_grid = Mobject(
|
||||
Circle(),
|
||||
Grid(radius = 2),
|
||||
TexMobject(r"\mathds{R}^2").shift((2, -2, 0))
|
||||
@ -244,12 +244,12 @@ class HardProblemsSimplerQuestions(Scene):
|
||||
for mob in circle_grid, start_line, end_line:
|
||||
mob.scale(0.5).shift(right_center + (0, 2, 0))
|
||||
|
||||
other_grid = CompoundMobject(
|
||||
other_grid = Mobject(
|
||||
Grid(radius = 2),
|
||||
TexMobject(r"\mathds{C}").shift((2, -2, 0))
|
||||
)
|
||||
omega = np.array((0.5, 0.5*np.sqrt(3), 0))
|
||||
dots = CompoundMobject(*[
|
||||
dots = Mobject(*[
|
||||
Dot(t*np.array((1, 0, 0)) + s * omega)
|
||||
for t, s in it.product(range(-2, 3), range(-2, 3))
|
||||
])
|
||||
@ -264,7 +264,7 @@ class HardProblemsSimplerQuestions(Scene):
|
||||
ShowCreation(dots)
|
||||
)
|
||||
self.dither()
|
||||
all_mobjects = CompoundMobject(*self.mobjects)
|
||||
all_mobjects = Mobject(*self.mobjects)
|
||||
self.remove(*self.mobjects)
|
||||
self.play(
|
||||
Transform(
|
||||
@ -273,7 +273,7 @@ class HardProblemsSimplerQuestions(Scene):
|
||||
),
|
||||
Transform(
|
||||
Point((-SPACE_WIDTH, 0, 0)),
|
||||
CompoundMobject(*CircleScene(RADIANS).mobjects)
|
||||
Mobject(*CircleScene(RADIANS).mobjects)
|
||||
)
|
||||
)
|
||||
|
||||
@ -436,7 +436,7 @@ class GeneralPositionRule(Scene):
|
||||
])
|
||||
if first_time:
|
||||
self.play(Transform(
|
||||
CompoundMobject(*intersecting_lines),
|
||||
Mobject(*intersecting_lines),
|
||||
words_mob
|
||||
))
|
||||
first_time = False
|
||||
@ -542,7 +542,7 @@ class IllustrateNChooseK(Scene):
|
||||
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])
|
||||
tuple_copy = Mobject(*[nrange_mobs[index-1] for index in tup])
|
||||
tuple_copy.highlight()
|
||||
self.add(tuple_copy)
|
||||
self.add(tuple_mobs[count])
|
||||
@ -550,7 +550,7 @@ class IllustrateNChooseK(Scene):
|
||||
self.remove(count_mob)
|
||||
self.remove(tuple_copy)
|
||||
self.add(count_mob)
|
||||
self.play(FadeIn(CompoundMobject(form1, form2, pronunciation)))
|
||||
self.play(FadeIn(Mobject(form1, form2, pronunciation)))
|
||||
|
||||
class IntersectionPointCorrespondances(CircleScene):
|
||||
args_list = [
|
||||
@ -661,7 +661,7 @@ class QuadrupletsToIntersections(CircleScene):
|
||||
dot_quad = [deepcopy(self.dots[i]) for i in quad]
|
||||
for dot in dot_quad:
|
||||
dot.scale_in_place(2)
|
||||
dot_quad = CompoundMobject(*dot_quad)
|
||||
dot_quad = Mobject(*dot_quad)
|
||||
dot_quad.highlight()
|
||||
self.add(dot_quad)
|
||||
self.dither(frame_time / 3)
|
||||
@ -674,7 +674,7 @@ class QuadrupletsToIntersections(CircleScene):
|
||||
class GraphsAndEulersFormulaJoke(Scene):
|
||||
def __init__(self, *args, **kwargs):
|
||||
Scene.__init__(self, *args, **kwargs)
|
||||
axes = CompoundMobject(
|
||||
axes = Mobject(
|
||||
NumberLine(),
|
||||
NumberLine().rotate(np.pi / 2)
|
||||
)
|
||||
@ -693,7 +693,7 @@ class GraphsAndEulersFormulaJoke(Scene):
|
||||
self.remove(*self.mobjects)
|
||||
self.add(eulers)
|
||||
self.play(CounterclockwiseTransform(
|
||||
CompoundMobject(axes, graph),
|
||||
Mobject(axes, graph),
|
||||
Point((-SPACE_WIDTH, SPACE_HEIGHT, 0))
|
||||
))
|
||||
self.play(CounterclockwiseTransform(
|
||||
@ -709,7 +709,7 @@ class DefiningGraph(GraphScene):
|
||||
edges_word = TextMobject("``Edges\"").shift(word_center)
|
||||
dots, lines = self.vertices, self.edges
|
||||
self.remove(*dots + lines)
|
||||
all_dots = CompoundMobject(*dots)
|
||||
all_dots = Mobject(*dots)
|
||||
self.play(ShowCreation(all_dots))
|
||||
self.remove(all_dots)
|
||||
self.add(*dots)
|
||||
@ -786,7 +786,7 @@ class EulersFormula(GraphScene):
|
||||
])
|
||||
for mob in form.values():
|
||||
mob.shift((0, SPACE_HEIGHT-0.7, 0))
|
||||
formula = CompoundMobject(*[form[k] for k in form.keys() if k != "=2"])
|
||||
formula = Mobject(*[form[k] for k in form.keys() if k != "=2"])
|
||||
new_form = dict([
|
||||
(key, deepcopy(mob).shift((0, -0.7, 0)))
|
||||
for key, mob in zip(form.keys(), form.values())
|
||||
@ -797,7 +797,7 @@ class EulersFormula(GraphScene):
|
||||
for d in self.dots
|
||||
]
|
||||
colored_edges = [
|
||||
CompoundMobject(
|
||||
Mobject(
|
||||
Line(midpoint, start),
|
||||
Line(midpoint, end),
|
||||
).highlight("red")
|
||||
@ -843,7 +843,7 @@ class CannotDirectlyApplyEulerToMoser(CircleScene):
|
||||
d.highlight("yellow").scale_in_place(2)
|
||||
for d in deepcopy(self.dots)
|
||||
]
|
||||
yellow_lines = CompoundMobject(*[
|
||||
yellow_lines = Mobject(*[
|
||||
l.highlight("yellow") for l in deepcopy(self.lines)
|
||||
])
|
||||
self.play(*[
|
||||
@ -896,7 +896,7 @@ class ShowMoserGraphLines(CircleScene):
|
||||
(self.lines, n_choose_2)
|
||||
]:
|
||||
self.add(symbol)
|
||||
compound = CompoundMobject(*mobs)
|
||||
compound = Mobject(*mobs)
|
||||
if mobs in (self.dots, self.intersection_dots):
|
||||
self.remove(*mobs)
|
||||
self.play(CounterclockwiseTransform(
|
||||
@ -916,7 +916,7 @@ class ShowMoserGraphLines(CircleScene):
|
||||
Transform(line, small_line, run_time = 3.0)
|
||||
for line, small_line in zip(self.lines, small_lines)
|
||||
])
|
||||
yellow_lines = CompoundMobject(*[
|
||||
yellow_lines = Mobject(*[
|
||||
line.highlight("yellow") for line in small_lines
|
||||
])
|
||||
self.add(plus_2_n_choose_4)
|
||||
@ -929,7 +929,7 @@ class ShowMoserGraphLines(CircleScene):
|
||||
for p, sp in zip(self.circle_pieces, self.smaller_circle_pieces)
|
||||
])
|
||||
self.add(plus_n)
|
||||
self.play(ShowCreation(CompoundMobject(*[
|
||||
self.play(ShowCreation(Mobject(*[
|
||||
mob.highlight("yellow") for mob in self.circle_pieces
|
||||
])))
|
||||
|
||||
@ -1111,7 +1111,7 @@ class ApplyEulerToMoser(CircleScene):
|
||||
self.add(*all_mobs)
|
||||
self.remove(*[d[1] for d in [V, minus, E, plus, F, equals, two]])
|
||||
self.play(
|
||||
Transform(V[2].repeat(2), CompoundMobject(n[3], minus1[3], nc4[3])),
|
||||
Transform(V[2].repeat(2), Mobject(n[3], minus1[3], nc4[3])),
|
||||
*[
|
||||
Transform(d[2], d[3])
|
||||
for d in [F, equals, E, minus, plus, two]
|
||||
@ -1120,7 +1120,7 @@ class ApplyEulerToMoser(CircleScene):
|
||||
self.dither()
|
||||
self.remove(*self.mobjects)
|
||||
self.play(
|
||||
Transform(E[3], CompoundMobject(
|
||||
Transform(E[3], Mobject(
|
||||
nc2[4], plus1[4], two1[4], nc41[4], plus2[4], n1[4]
|
||||
)),
|
||||
*[
|
||||
@ -1142,7 +1142,7 @@ class ApplyEulerToMoser(CircleScene):
|
||||
self.remove(*self.mobjects)
|
||||
self.play(
|
||||
Transform(
|
||||
CompoundMobject(plus2[4], n1[4], minus[4], n[4]),
|
||||
Mobject(plus2[4], n1[4], minus[4], n[4]),
|
||||
Point((SPACE_WIDTH, SPACE_HEIGHT, 0))
|
||||
),
|
||||
*[
|
||||
@ -1202,7 +1202,7 @@ class FormulaRelatesToPowersOfTwo(Scene):
|
||||
scale_factor = 1
|
||||
for mob in everything:
|
||||
mob.scale(scale_factor)
|
||||
CompoundMobject(*everything).show()
|
||||
Mobject(*everything).show()
|
||||
forms = everything[0::3]
|
||||
sums = everything[1::3]
|
||||
results = everything[2::3]
|
||||
@ -1238,7 +1238,7 @@ class DrawPascalsTriangle(PascalsTriangleScene):
|
||||
for n in range(1, nrows):
|
||||
starts = [deepcopy(self.coords_to_mobs[n-1][0])]
|
||||
starts += [
|
||||
CompoundMobject(
|
||||
Mobject(
|
||||
self.coords_to_mobs[n-1][k-1],
|
||||
self.coords_to_mobs[n-1][k]
|
||||
)
|
||||
@ -1384,11 +1384,11 @@ class PascalsTriangleSumRows(PascalsTriangleScene):
|
||||
powers_of_two.append(pof2)
|
||||
equalses.append(new_equals)
|
||||
powers_of_two_symbols.append(symbol)
|
||||
self.play(FadeIn(CompoundMobject(*pluses)))
|
||||
self.play(FadeIn(Mobject(*pluses)))
|
||||
run_time = 0.5
|
||||
to_remove = []
|
||||
for n in range(self.nrows):
|
||||
start = CompoundMobject(*[self.coords_to_mobs[n][k] for k in range(n+1)])
|
||||
start = Mobject(*[self.coords_to_mobs[n][k] for k in range(n+1)])
|
||||
to_remove.append(start)
|
||||
self.play(
|
||||
Transform(start, powers_of_two[n]),
|
||||
@ -1481,14 +1481,14 @@ class MoserSolutionInPascal(PascalsTriangleScene):
|
||||
self.add(self.coords_to_mobs[n][k])
|
||||
self.play(Transform(
|
||||
terms[k],
|
||||
CompoundMobject(*above_terms).highlight(term_color)
|
||||
Mobject(*above_terms).highlight(term_color)
|
||||
))
|
||||
self.remove(*above_terms)
|
||||
self.dither()
|
||||
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))
|
||||
self.play(Transform(Mobject(*terms), terms_sum))
|
||||
|
||||
class RotatingPolyhedra(Scene):
|
||||
args_list = [
|
||||
@ -1530,12 +1530,12 @@ class ExplainNChoose2Formula(Scene):
|
||||
r_paren, a_mob, comma, b_mob, l_paren = TexMobjects(
|
||||
("( %d , %d )"%(a, b)).split(" ")
|
||||
)
|
||||
parens = CompoundMobject(r_paren, comma, l_paren)
|
||||
parens = Mobject(r_paren, comma, l_paren)
|
||||
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 = Mobject(*nums)
|
||||
nums_compound.shift(a_mob.get_center() - nums[0].get_center())
|
||||
n_mob, n_minus_1, over_2 = TexMobject([
|
||||
str(n), "(%d-1)"%n, r"\over{2}"
|
||||
@ -1550,7 +1550,7 @@ class ExplainNChoose2Formula(Scene):
|
||||
self.remove(nums_compound)
|
||||
nums = nums_compound.split()
|
||||
a_mob = nums.pop(a-1)
|
||||
nums_compound = CompoundMobject(*nums)
|
||||
nums_compound = Mobject(*nums)
|
||||
self.add(a_mob, nums_compound)
|
||||
self.dither()
|
||||
right_shift = b_mob.get_center() - a_mob.get_center()
|
||||
@ -1602,17 +1602,17 @@ class ExplainNChoose4Formula(Scene):
|
||||
("( %d , %d , %d , %d )"%quad).split(" ")
|
||||
)
|
||||
quad_mobs = tuple_mobs[1::2]
|
||||
parens = CompoundMobject(*tuple_mobs[0::2])
|
||||
parens = Mobject(*tuple_mobs[0::2])
|
||||
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()
|
||||
form_mobs = Mobject(*form_mobs).scale(0.7).shift((4, 3, 0)).split()
|
||||
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 = Mobject(*nums)
|
||||
nums_compound.shift(quad_mobs[0].get_center() - nums[0].get_center())
|
||||
curr_num = 1
|
||||
self.add(parens)
|
||||
@ -1625,7 +1625,7 @@ class ExplainNChoose4Formula(Scene):
|
||||
nums = nums_compound.split()
|
||||
chosen = nums[quad[i]-1]
|
||||
nums[quad[i]-1] = Point(chosen.get_center()).highlight("black")
|
||||
nums_compound = CompoundMobject(*nums)
|
||||
nums_compound = Mobject(*nums)
|
||||
self.add(chosen)
|
||||
if i < 3:
|
||||
right_shift = quad_mobs[i+1].get_center() - chosen.get_center()
|
||||
@ -1657,10 +1657,10 @@ class ExplainNChoose4Formula(Scene):
|
||||
)
|
||||
for i in range(4)
|
||||
]
|
||||
compound_quad = CompoundMobject(*quad_mobs)
|
||||
compound_quad = Mobject(*quad_mobs)
|
||||
self.play(CounterclockwiseTransform(
|
||||
compound_quad,
|
||||
CompoundMobject(*new_quad_mobs)
|
||||
Mobject(*new_quad_mobs)
|
||||
))
|
||||
self.remove(compound_quad)
|
||||
quad_mobs = new_quad_mobs
|
||||
|
@ -81,12 +81,12 @@ class RightParen(Mobject):
|
||||
return Mobject.get_center(self) + 0.04*RIGHT
|
||||
|
||||
|
||||
class OpenInterval(CompoundMobject):
|
||||
class OpenInterval(Mobject):
|
||||
def __init__(self, center_point = ORIGIN, width = 2, **kwargs):
|
||||
digest_config(self, kwargs, locals())
|
||||
left = LeftParen().shift(LEFT*width/2)
|
||||
right = RightParen().shift(RIGHT*width/2)
|
||||
CompoundMobject.__init__(self, left, right, **kwargs)
|
||||
Mobject.__init__(self, left, right, **kwargs)
|
||||
# scale_factor = width / 2.0
|
||||
# self.stretch(scale_factor, 0)
|
||||
# self.stretch(0.5+0.5*scale_factor, 1)
|
||||
@ -199,7 +199,7 @@ class IntervalScene(NumberLineScene):
|
||||
tick = Line(point+tick_rad*DOWN, point+tick_rad*UP)
|
||||
tick.highlight("yellow")
|
||||
all_ticks.append(tick)
|
||||
all_ticks = CompoundMobject(*all_ticks)
|
||||
all_ticks = Mobject(*all_ticks)
|
||||
if run_time > 0:
|
||||
self.play(ShowCreation(all_ticks))
|
||||
else:
|
||||
@ -294,7 +294,7 @@ class MeasureTheoryToHarmony(IntervalScene):
|
||||
IntervalScene.construct(self)
|
||||
self.cover_fractions()
|
||||
self.dither()
|
||||
all_mobs = CompoundMobject(*self.mobjects)
|
||||
all_mobs = Mobject(*self.mobjects)
|
||||
all_mobs.sort_points()
|
||||
self.clear()
|
||||
radius = self.interval.radius
|
||||
@ -516,7 +516,7 @@ class DecomposeTwoFrequencies(Scene):
|
||||
sine1 = LongSine().shift(2*UP).highlight("yellow")
|
||||
sine2 = LongSine().shift(DOWN).highlight("lightgreen")
|
||||
sine1.stretch(2.0/3, 0)
|
||||
comp = CompoundMobject(sine1, sine2)
|
||||
comp = Mobject(sine1, sine2)
|
||||
|
||||
self.add(line)
|
||||
self.play(ApplyMethod(
|
||||
@ -562,12 +562,12 @@ class PatternInFrequencies(Scene):
|
||||
setup_width = 2*SPACE_WIDTH
|
||||
num_top_lines = int(setup_width)
|
||||
num_bot_lines = int(setup_width*num1/num2)
|
||||
top_lines = CompoundMobject(*[
|
||||
top_lines = Mobject(*[
|
||||
deepcopy(line_template).shift(k*(float(num1)/num2)*RIGHT)
|
||||
for k in range(num_top_lines)
|
||||
])
|
||||
line_template.shift(4*DOWN)
|
||||
bottom_lines = CompoundMobject(*[
|
||||
bottom_lines = Mobject(*[
|
||||
deepcopy(line_template).shift(k*RIGHT)
|
||||
for k in range(num_bot_lines)
|
||||
])
|
||||
@ -601,7 +601,7 @@ class CompareFractionComplexity(Scene):
|
||||
for num, den in [(4, 3), (1093,826)]:
|
||||
top = TexMobject("%d \\over"%num)
|
||||
bottom = TexMobject(str(den)).next_to(top, DOWN, buff = 0.3)
|
||||
fractions.append(CompoundMobject(top, bottom))
|
||||
fractions.append(Mobject(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)
|
||||
@ -642,7 +642,7 @@ class IrrationalGang(Scene):
|
||||
sqrt13.highlight("green")
|
||||
zeta3 = TexMobject("\\zeta(3)").shift(2*RIGHT)
|
||||
zeta3.highlight("grey")
|
||||
eyes = CompoundMobject(*randy.eyes)
|
||||
eyes = Mobject(*randy.eyes)
|
||||
eyes.scale(0.5)
|
||||
sqrt13.add(eyes.next_to(sqrt13, UP, buff = 0).shift(0.25*RIGHT))
|
||||
eyes.scale(0.5)
|
||||
@ -682,7 +682,7 @@ class PianoTuning(Scene):
|
||||
jump = piano.half_note_jump
|
||||
semicircle = Circle().filter_out(lambda p : p[1] < 0)
|
||||
semicircle.scale(jump/semicircle.get_width())
|
||||
semicircles = CompoundMobject(*[
|
||||
semicircles = Mobject(*[
|
||||
deepcopy(semicircle).shift(jump*k*RIGHT)
|
||||
for k in range(23)
|
||||
])
|
||||
@ -802,14 +802,14 @@ class PowersOfTwelfthRoot(Scene):
|
||||
])
|
||||
error_string = error_string.split()
|
||||
error_string[1].highlight()
|
||||
error_string = CompoundMobject(*error_string)
|
||||
error_string = Mobject(*error_string)
|
||||
error_string.scale(approx_form.get_height()/error_string.get_height())
|
||||
error_string.next_to(frac_mob)
|
||||
|
||||
mob_list.append(CompoundMobject(*[
|
||||
mob_list.append(Mobject(*[
|
||||
term, approx_copy, approx_form, words, frac_mob, error_string
|
||||
]))
|
||||
self.play(ShimmerIn(CompoundMobject(*mob_list), run_time = 3.0))
|
||||
self.play(ShimmerIn(Mobject(*mob_list), run_time = 3.0))
|
||||
|
||||
class InterestingQuestion(Scene):
|
||||
def construct(self):
|
||||
@ -898,7 +898,7 @@ class ChallengeTwo(Scene):
|
||||
class CoveringSetsWithOpenIntervals(IntervalScene):
|
||||
def construct(self):
|
||||
IntervalScene.construct(self)
|
||||
dots = CompoundMobject(*[
|
||||
dots = Mobject(*[
|
||||
Dot().shift(self.number_line.number_to_point(num)+UP)
|
||||
for num in set([0.2, 0.25, 0.45, 0.6, 0.65])
|
||||
])
|
||||
@ -1168,7 +1168,7 @@ class StepsToSolution(IntervalScene):
|
||||
tick_copy = deepcopy(tick).center().shift(1.6*UP)
|
||||
tick_copy.shift((-SPACE_WIDTH+self.spacing*count)*RIGHT)
|
||||
new_ticks.append(tick_copy)
|
||||
new_ticks = CompoundMobject(*new_ticks)
|
||||
new_ticks = Mobject(*new_ticks)
|
||||
anims.append(DelayByOrder(Transform(ticks, new_ticks)))
|
||||
self.dither()
|
||||
self.play(*anims)
|
||||
@ -1219,7 +1219,7 @@ class StepsToSolution(IntervalScene):
|
||||
frac_bottom.scale(scale_val)
|
||||
one = TexMobject("1").scale(scale_val)
|
||||
one.next_to(frac_bottom, UP, buff = 0.1)
|
||||
compound = CompoundMobject(frac_bottom, one)
|
||||
compound = Mobject(frac_bottom, one)
|
||||
if plus:
|
||||
compound.next_to(plus)
|
||||
else:
|
||||
@ -1313,9 +1313,9 @@ class TroubleDrawingSmallInterval(IntervalScene):
|
||||
def construct(self):
|
||||
IntervalScene.construct(self)
|
||||
interval, line = self.add_open_interval(0.5, 0.5)
|
||||
big = CompoundMobject(interval, line)
|
||||
big = Mobject(interval, line)
|
||||
small_int, small_line = self.add_open_interval(0.5, 0.01)
|
||||
small = CompoundMobject(small_int, line.scale_in_place(0.01/0.5))
|
||||
small = Mobject(small_int, line.scale_in_place(0.01/0.5))
|
||||
shrunk = deepcopy(big).scale_in_place(0.01/0.5)
|
||||
self.clear()
|
||||
IntervalScene.construct(self)
|
||||
@ -1354,7 +1354,7 @@ class ZoomInOnSqrt2Over2(IntervalScene):
|
||||
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))
|
||||
self.add(Mobject(epsilon, equals, num).center().shift(2*UP))
|
||||
intervals, lines = self.cover_fractions()
|
||||
self.remove(*lines)
|
||||
irr = TexMobject("\\frac{\\sqrt{2}}{2}")
|
||||
@ -1464,7 +1464,7 @@ class ShiftSetupByOne(IntervalScene):
|
||||
"real numbers \\emph{very very very} close to them",
|
||||
size = "\\small"
|
||||
)
|
||||
compound = CompoundMobject(answer1, answer2.next_to(answer1))
|
||||
compound = Mobject(answer1, answer2.next_to(answer1))
|
||||
compound.next_to(words, DOWN)
|
||||
answer1, answer2 = compound.split()
|
||||
|
||||
@ -1485,7 +1485,7 @@ class ShiftSetupByOne(IntervalScene):
|
||||
words[3].highlight()
|
||||
self.add(*words)
|
||||
self.play(ShowCreation(
|
||||
CompoundMobject(*intervals),
|
||||
Mobject(*intervals),
|
||||
run_time = 5.0
|
||||
))
|
||||
self.dither()
|
||||
@ -1502,12 +1502,12 @@ class FinalEquivalence(IntervalScene):
|
||||
for interval, frac in zip(intervals, rationals()):
|
||||
interval.scale_in_place(2.0/frac.denominator)
|
||||
self.remove(*intervals+lines)
|
||||
intervals = CompoundMobject(*intervals)
|
||||
intervals = Mobject(*intervals)
|
||||
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 = Mobject(top_words, bot_words)
|
||||
words.next_to(arrow)
|
||||
|
||||
self.play(
|
||||
@ -1517,7 +1517,7 @@ class FinalEquivalence(IntervalScene):
|
||||
intervals
|
||||
)
|
||||
)
|
||||
everything = CompoundMobject(*self.mobjects)
|
||||
everything = Mobject(*self.mobjects)
|
||||
self.clear()
|
||||
self.play(Transform(
|
||||
everything,
|
||||
|
@ -211,7 +211,7 @@ class ShowFrameNum(SceneFromVideo):
|
||||
SceneFromVideo.construct(self, path)
|
||||
for frame, count in zip(self.frames, it.count()):
|
||||
print count, "of", len(self.frames)
|
||||
mob = CompoundMobject(*[
|
||||
mob = Mobject(*[
|
||||
TexMobject(char).shift(0.3*x*RIGHT)
|
||||
for char, x, in zip(str(count), it.count())
|
||||
])
|
||||
|
@ -441,7 +441,7 @@ class LabelLargeSquare(DrawCSquareWithAllTraingles):
|
||||
args_list = []
|
||||
def construct(self):
|
||||
DrawCSquareWithAllTraingles.construct(self)
|
||||
everything = CompoundMobject(*self.mobjects)
|
||||
everything = Mobject(*self.mobjects)
|
||||
u_brace = Underbrace(2*(DOWN+LEFT), 2*(DOWN+RIGHT))
|
||||
u_brace.shift(0.2*DOWN)
|
||||
side_brace = deepcopy(u_brace).rotate(np.pi/2)
|
||||
|
@ -80,11 +80,9 @@ class Scene(object):
|
||||
"""
|
||||
So a scene can just add all mobjects it's defined up to that point
|
||||
"""
|
||||
caller_locals = inspect.currentframe().f_back.f_locals
|
||||
self.add(*filter(
|
||||
lambda m : isinstance(m, Mobject),
|
||||
caller_locals.values()
|
||||
))
|
||||
name_to_mob = get_caller_locals(lambda x : isinstance(x, Mobject))
|
||||
self.add(*name_to_mob.values())
|
||||
return self
|
||||
|
||||
def remove(self, *mobjects):
|
||||
if not all_elements_are_instances(mobjects, Mobject):
|
||||
@ -161,8 +159,17 @@ class Scene(object):
|
||||
for animation in animations:
|
||||
animation.set_run_time(run_time)
|
||||
moving_mobjects = [anim.mobject for anim in animations]
|
||||
self.remove(*moving_mobjects)
|
||||
background = self.get_frame()
|
||||
|
||||
bundle = Mobject(*self.mobjects)
|
||||
static_mobjects = filter(
|
||||
lambda m : m not in moving_mobjects,
|
||||
bundle.get_full_submobject_family()
|
||||
)
|
||||
background = disp.paint_mobjects(
|
||||
static_mobjects,
|
||||
self.background,
|
||||
include_sub_mobjects = False
|
||||
)
|
||||
|
||||
print "Generating " + ", ".join(map(str, animations))
|
||||
progress_bar = progressbar.ProgressBar(maxval=run_time)
|
||||
@ -176,7 +183,7 @@ class Scene(object):
|
||||
self.frames.append(new_frame)
|
||||
for animation in animations:
|
||||
animation.clean_up()
|
||||
self.add(*moving_mobjects)
|
||||
self.repaint_mojects()
|
||||
progress_bar.finish()
|
||||
return self
|
||||
|
||||
|
@ -10,8 +10,7 @@ class TkSceneRoot(Tkinter.Tk):
|
||||
raise Exception(str(scene) + " has no frames!")
|
||||
Tkinter.Tk.__init__(self)
|
||||
|
||||
height, width = scene.shape
|
||||
kwargs = {"height" : height, "width" : width}
|
||||
kwargs = {"height" : scene.height, "width" : scene.width}
|
||||
self.frame = Tkinter.Frame(self, **kwargs)
|
||||
self.frame.pack()
|
||||
self.canvas = Tkinter.Canvas(self.frame, **kwargs)
|
||||
|
@ -24,9 +24,9 @@ class RearrangeEquation(Scene):
|
||||
start_terms, end_terms, size
|
||||
)
|
||||
if start_transform:
|
||||
start_mobs = start_transform(CompoundMobject(*start_mobs)).split()
|
||||
start_mobs = start_transform(Mobject(*start_mobs)).split()
|
||||
if end_transform:
|
||||
end_mobs = end_transform(CompoundMobject(*end_mobs)).split()
|
||||
end_mobs = end_transform(Mobject(*end_mobs)).split()
|
||||
unmatched_start_indices = set(range(len(start_mobs)))
|
||||
unmatched_end_indices = set(range(len(end_mobs)))
|
||||
unmatched_start_indices.difference_update(
|
||||
@ -50,7 +50,7 @@ class RearrangeEquation(Scene):
|
||||
|
||||
self.add(*start_mobs)
|
||||
if leave_start_terms:
|
||||
self.add(CompoundMobject(*start_mobs))
|
||||
self.add(Mobject(*start_mobs))
|
||||
self.dither()
|
||||
self.play(*[
|
||||
Transform(*pair, **transform_kwargs)
|
||||
|
@ -1,15 +1,21 @@
|
||||
from copy import deepcopy
|
||||
|
||||
from helpers import *
|
||||
|
||||
from mobject import Mobject, CompoundMobject
|
||||
from image_mobject import ImageMobject
|
||||
from mobject import Mobject, Mobject, ImageMobject, TexMobject
|
||||
|
||||
|
||||
PI_CREATURE_DIR = os.path.join(IMAGE_DIR, "PiCreature")
|
||||
PI_CREATURE_PART_NAME_TO_DIR = lambda name : os.path.join(PI_CREATURE_DIR, "pi_creature_"+name) + ".png"
|
||||
PI_CREATURE_SCALE_VAL = 0.5
|
||||
PI_CREATURE_MOUTH_TO_EYES_DISTANCE = 0.25
|
||||
|
||||
class PiCreature(CompoundMobject):
|
||||
DEFAULT_COLOR = BLUE
|
||||
def part_name_to_directory(name):
|
||||
return os.path.join(PI_CREATURE_DIR, "pi_creature_"+name) + ".png"
|
||||
|
||||
class PiCreature(Mobject):
|
||||
DEFAULT_CONFIG = {
|
||||
"color" : BLUE_E
|
||||
}
|
||||
PART_NAMES = [
|
||||
'arm',
|
||||
'body',
|
||||
@ -23,42 +29,30 @@ class PiCreature(CompoundMobject):
|
||||
MOUTH_NAMES = ["smile", "frown", "straight_mouth"]
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
color = self.DEFAULT_COLOR if "color" not in kwargs else kwargs.pop("color")
|
||||
Mobject.__init__(self, **kwargs)
|
||||
for part_name in self.PART_NAMES:
|
||||
mob = ImageMobject(
|
||||
PI_CREATURE_PART_NAME_TO_DIR(part_name)
|
||||
part_name_to_directory(part_name),
|
||||
should_center = False
|
||||
)
|
||||
if part_name not in self.WHITE_PART_NAMES:
|
||||
mob.highlight(color)
|
||||
mob.scale(PI_CREATURE_SCALE_VAL)
|
||||
mob.highlight(self.color)
|
||||
setattr(self, part_name, mob)
|
||||
self.eyes = [self.left_eye, self.right_eye]
|
||||
self.legs = [self.left_leg, self.right_leg]
|
||||
self.eyes = Mobject(self.left_eye, self.right_eye)
|
||||
self.legs = Mobject(self.left_leg, self.right_leg)
|
||||
mouth_center = self.get_mouth_center()
|
||||
self.mouth.center()
|
||||
self.smile = deepcopy(self.mouth)
|
||||
self.smile = self.mouth
|
||||
self.frown = deepcopy(self.mouth).rotate(np.pi, RIGHT)
|
||||
self.straight_mouth = TexMobject("-").scale(0.5)
|
||||
for mouth_name in ["mouth"] + self.MOUTH_NAMES:
|
||||
mouth = getattr(self, mouth_name)
|
||||
for mouth in self.smile, self.frown, self.straight_mouth:
|
||||
mouth.sort_points(lambda p : p[0])
|
||||
mouth.highlight(self.color) ##to blend into background
|
||||
mouth.shift(mouth_center)
|
||||
#Ordering matters here, so hidden mouths are behind body
|
||||
self.part_names = self.MOUTH_NAMES + self.PART_NAMES
|
||||
self.white_parts = self.MOUTH_NAMES + self.WHITE_PART_NAMES
|
||||
CompoundMobject.__init__(
|
||||
self,
|
||||
*self.get_parts(),
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def sync_parts(self):
|
||||
CompoundMobject.__init__(self, *self.get_parts())
|
||||
return self
|
||||
|
||||
# def TODO_what_should_I_do_with_this(self):
|
||||
# for part_name, mob in zip(self.part_names, self.split()):
|
||||
# setattr(self, part_name, mob)
|
||||
self.digest_mobject_attrs()
|
||||
self.give_smile()
|
||||
self.add(self.mouth)
|
||||
self.scale(PI_CREATURE_SCALE_VAL)
|
||||
|
||||
|
||||
def get_parts(self):
|
||||
@ -68,26 +62,30 @@ class PiCreature(CompoundMobject):
|
||||
return [getattr(self, pn) for pn in self.white_parts]
|
||||
|
||||
def get_mouth_center(self):
|
||||
left_center = self.left_eye.get_center()
|
||||
right_center = self.right_eye.get_center()
|
||||
l_to_r = right_center-left_center
|
||||
eyes_to_mouth = rotate_vector(l_to_r, -np.pi/2, OUT)
|
||||
eyes_to_mouth /= np.linalg.norm(eyes_to_mouth)
|
||||
return left_center/2 + right_center/2 + \
|
||||
PI_CREATURE_MOUTH_TO_EYES_DISTANCE*eyes_to_mouth
|
||||
result = self.body.get_center()
|
||||
result[0] = self.eyes.get_center()[0]
|
||||
return result
|
||||
# left_center = self.left_eye.get_center()
|
||||
# right_center = self.right_eye.get_center()
|
||||
# l_to_r = right_center-left_center
|
||||
# eyes_to_mouth = rotate_vector(l_to_r, -np.pi/2, OUT)
|
||||
# eyes_to_mouth /= np.linalg.norm(eyes_to_mouth)
|
||||
# return left_center/2 + right_center/2 + \
|
||||
# PI_CREATURE_MOUTH_TO_EYES_DISTANCE*eyes_to_mouth
|
||||
|
||||
def highlight(self, color, condition = None):
|
||||
for part in set(self.get_parts()).difference(self.get_white_parts()):
|
||||
part.highlight(color, condition)
|
||||
return self.sync_parts()
|
||||
return self
|
||||
|
||||
def move_to(self, destination):
|
||||
self.shift(destination-self.get_bottom())
|
||||
return self.sync_parts()
|
||||
return self
|
||||
|
||||
def change_mouth_to(self, mouth_name):
|
||||
self.mouth = getattr(self, mouth_name)
|
||||
return self.sync_parts()
|
||||
self.mouth.points = getattr(self, mouth_name).points
|
||||
self.mouth.highlight(WHITE)
|
||||
return self
|
||||
|
||||
def give_smile(self):
|
||||
return self.change_mouth_to("smile")
|
||||
@ -99,29 +97,24 @@ class PiCreature(CompoundMobject):
|
||||
return self.change_mouth_to("straight_mouth")
|
||||
|
||||
def get_eye_center(self):
|
||||
return center_of_mass([
|
||||
self.left_eye.get_center(),
|
||||
self.right_eye.get_center()
|
||||
]) + 0.04*RIGHT + 0.02*UP
|
||||
return self.eyes.get_center()
|
||||
|
||||
def make_mean(self):
|
||||
eye_x, eye_y = self.get_eye_center()[:2]
|
||||
def should_delete((x, y, z)):
|
||||
return y - eye_y > 0.3*abs(x - eye_x)
|
||||
for eye in self.left_eye, self.right_eye:
|
||||
eye.highlight("black", should_delete)
|
||||
self.eyes.highlight("black", should_delete)
|
||||
self.give_straight_face()
|
||||
return self.sync_parts()
|
||||
return self
|
||||
|
||||
def make_sad(self):
|
||||
eye_x, eye_y = self.get_eye_center()[:2]
|
||||
eye_y += 0.15
|
||||
def should_delete((x, y, z)):
|
||||
return y - eye_y > -0.3*abs(x - eye_x)
|
||||
for eye in self.left_eye, self.right_eye:
|
||||
eye.highlight("black", should_delete)
|
||||
self.eyey.highlight("black", should_delete)
|
||||
self.give_frown()
|
||||
return self.sync_parts()
|
||||
return self
|
||||
|
||||
def get_step_intermediate(self, pi_creature):
|
||||
vect = pi_creature.get_center() - self.get_center()
|
||||
@ -136,23 +129,22 @@ class PiCreature(CompoundMobject):
|
||||
else:
|
||||
result.right_leg.wag(vect/2.0, DOWN)
|
||||
result.left_leg.wag(-vect/2.0, DOWN)
|
||||
return result.sync_parts()
|
||||
return result
|
||||
|
||||
def blink(self):
|
||||
for eye in self.left_eye, self.right_eye:
|
||||
bottom = eye.get_bottom()
|
||||
eye.apply_function(
|
||||
bottom = self.eyes.get_bottom()
|
||||
self.eyes.apply_function(
|
||||
lambda (x, y, z) : (x, bottom[1], z)
|
||||
)
|
||||
return self.sync_parts()
|
||||
return self
|
||||
|
||||
def shift_eyes(self):
|
||||
for eye in self.left_eye, self.right_eye:
|
||||
eye.rotate_in_place(np.pi, UP)
|
||||
return self.sync_parts()
|
||||
return self
|
||||
|
||||
def to_symbol(self):
|
||||
CompoundMobject.__init__(
|
||||
Mobject.__init__(
|
||||
self,
|
||||
*list(set(self.get_parts()).difference(self.get_white_parts()))
|
||||
)
|
||||
|
@ -2,7 +2,7 @@ from helpers import *
|
||||
|
||||
from helpers import *
|
||||
|
||||
from mobject import Mobject, Mobject1D, CompoundMobject
|
||||
from mobject import Mobject, Mobject1D, Mobject
|
||||
|
||||
|
||||
class FunctionGraph(Mobject1D):
|
||||
@ -58,11 +58,11 @@ class ParametricFunction(Mobject):
|
||||
])
|
||||
|
||||
|
||||
class Axes(CompoundMobject):
|
||||
class Axes(Mobject):
|
||||
def __init__(self, **kwargs):
|
||||
x_axis = NumberLine(**kwargs)
|
||||
y_axis = NumberLine(**kwargs).rotate(np.pi/2, OUT)
|
||||
CompoundMobject.__init__(self, x_axis, y_axis)
|
||||
Mobject.__init__(self, x_axis, y_axis)
|
||||
|
||||
|
||||
|
@ -217,7 +217,7 @@ class GraphScene(Scene):
|
||||
|
||||
def draw_vertices(self, **kwargs):
|
||||
self.clear()
|
||||
self.play(ShowCreation(CompoundMobject(*self.vertices), **kwargs))
|
||||
self.play(ShowCreation(Mobject(*self.vertices), **kwargs))
|
||||
|
||||
def draw_edges(self):
|
||||
self.play(*[
|
||||
@ -227,8 +227,8 @@ class GraphScene(Scene):
|
||||
|
||||
def accent_vertices(self, **kwargs):
|
||||
self.remove(*self.vertices)
|
||||
start = CompoundMobject(*self.vertices)
|
||||
end = CompoundMobject(*[
|
||||
start = Mobject(*self.vertices)
|
||||
end = Mobject(*[
|
||||
Dot(point, radius = 3*Dot.DEFAULT_RADIUS, color = "lightgreen")
|
||||
for point in self.points
|
||||
])
|
||||
@ -275,7 +275,7 @@ class GraphScene(Scene):
|
||||
time_per_edge = run_time / len(cycle)
|
||||
next_in_cycle = it.cycle(cycle)
|
||||
next_in_cycle.next()#jump one ahead
|
||||
self.traced_cycle = CompoundMobject(*[
|
||||
self.traced_cycle = Mobject(*[
|
||||
Line(self.points[i], self.points[j]).highlight(color)
|
||||
for i, j in zip(cycle, next_in_cycle)
|
||||
])
|
||||
@ -299,7 +299,7 @@ class GraphScene(Scene):
|
||||
self.spanning_tree_index_pairs.append(pair)
|
||||
spanned_vertices.add(pair[1])
|
||||
to_check.add(pair[1])
|
||||
self.spanning_tree = CompoundMobject(*[
|
||||
self.spanning_tree = Mobject(*[
|
||||
Line(
|
||||
self.points[pair[0]],
|
||||
self.points[pair[1]]
|
||||
@ -361,7 +361,7 @@ class GraphScene(Scene):
|
||||
])
|
||||
for index in indices
|
||||
]
|
||||
self.treeified_spanning_tree = CompoundMobject(*[
|
||||
self.treeified_spanning_tree = Mobject(*[
|
||||
Line(new_points[i], new_points[j]).highlight(color)
|
||||
for i, j in self.spanning_tree_index_pairs
|
||||
])
|
||||
|
@ -1,7 +1,7 @@
|
||||
import numpy as np
|
||||
import itertools as it
|
||||
|
||||
from mobject import Mobject, Mobject1D, Mobject2D, CompoundMobject
|
||||
from mobject import Mobject, Mobject1D, Mobject2D, Mobject
|
||||
from geometry import Line
|
||||
from helpers import *
|
||||
|
||||
@ -87,7 +87,7 @@ class Dodecahedron(Mobject1D):
|
||||
(x-y+z, v2),
|
||||
(x-y-z, v2),
|
||||
]
|
||||
five_lines_points = CompoundMobject(*[
|
||||
five_lines_points = Mobject(*[
|
||||
Line(pair[0], pair[1], density = 1.0/self.epsilon)
|
||||
for pair in vertex_pairs
|
||||
]).points
|
||||
|
Reference in New Issue
Block a user