mirror of
https://github.com/3b1b/manim.git
synced 2025-07-29 13:03:31 +08:00
Changed all files to (mostly) conform to PEP8
This commit is contained in:
@ -4,7 +4,6 @@ import numpy as np
|
||||
import operator as op
|
||||
import os
|
||||
|
||||
from PIL import Image
|
||||
from colour import Color
|
||||
|
||||
from constants import *
|
||||
@ -16,28 +15,28 @@ from utils.color import interpolate_color
|
||||
from utils.iterables import list_update
|
||||
from utils.iterables import remove_list_redundancies
|
||||
from utils.paths import straight_path
|
||||
from utils.space_ops import R3_to_complex
|
||||
from utils.space_ops import angle_of_vector
|
||||
from utils.space_ops import complex_to_R3
|
||||
from utils.space_ops import rotation_matrix
|
||||
|
||||
|
||||
#TODO: Explain array_attrs
|
||||
# TODO: Explain array_attrs
|
||||
|
||||
class Mobject(Container):
|
||||
"""
|
||||
Mathematical Object
|
||||
"""
|
||||
CONFIG = {
|
||||
"color" : WHITE,
|
||||
"stroke_width" : DEFAULT_POINT_THICKNESS,
|
||||
"name" : None,
|
||||
"dim" : 3,
|
||||
"target" : None,
|
||||
"color": WHITE,
|
||||
"stroke_width": DEFAULT_POINT_THICKNESS,
|
||||
"name": None,
|
||||
"dim": 3,
|
||||
"target": None,
|
||||
}
|
||||
|
||||
def __init__(self, *submobjects, **kwargs):
|
||||
Container.__init__(self, *submobjects, **kwargs)
|
||||
if not all(map(lambda m : isinstance(m, Mobject), submobjects)):
|
||||
if not all(map(lambda m: isinstance(m, Mobject), submobjects)):
|
||||
raise Exception("All submobjects must be of type Mobject")
|
||||
self.submobjects = list(submobjects)
|
||||
self.color = Color(self.color)
|
||||
@ -54,11 +53,11 @@ class Mobject(Container):
|
||||
self.points = np.zeros((0, self.dim))
|
||||
|
||||
def init_colors(self):
|
||||
#For subclasses
|
||||
# For subclasses
|
||||
pass
|
||||
|
||||
def generate_points(self):
|
||||
#Typically implemented in subclass, unless purposefully left blank
|
||||
# Typically implemented in subclass, unless purposefully left blank
|
||||
pass
|
||||
|
||||
def add(self, *mobjects):
|
||||
@ -87,7 +86,7 @@ class Mobject(Container):
|
||||
in the submobjects list.
|
||||
"""
|
||||
mobject_attrs = filter(
|
||||
lambda x : isinstance(x, Mobject),
|
||||
lambda x: isinstance(x, Mobject),
|
||||
self.__dict__.values()
|
||||
)
|
||||
self.submobjects = list_update(self.submobjects, mobject_attrs)
|
||||
@ -98,24 +97,24 @@ class Mobject(Container):
|
||||
setattr(self, attr, func(getattr(self, attr)))
|
||||
return self
|
||||
|
||||
def get_image(self, camera = None):
|
||||
def get_image(self, camera=None):
|
||||
if camera is None:
|
||||
from camera.camera import Camera
|
||||
camera = Camera()
|
||||
camera.capture_mobject(self)
|
||||
return camera.get_image()
|
||||
|
||||
def show(self, camera = None):
|
||||
self.get_image(camera = camera).show()
|
||||
def show(self, camera=None):
|
||||
self.get_image(camera=camera).show()
|
||||
|
||||
def save_image(self, name = None):
|
||||
def save_image(self, name=None):
|
||||
self.get_image().save(
|
||||
os.path.join(ANIMATIONS_DIR, (name or str(self)) + ".png")
|
||||
)
|
||||
|
||||
def copy(self):
|
||||
#TODO, either justify reason for shallow copy, or
|
||||
#remove this redundancy everywhere
|
||||
# TODO, either justify reason for shallow copy, or
|
||||
# remove this redundancy everywhere
|
||||
return self.deepcopy()
|
||||
|
||||
copy_mobject = copy.copy(self)
|
||||
@ -132,8 +131,8 @@ class Mobject(Container):
|
||||
def deepcopy(self):
|
||||
return copy.deepcopy(self)
|
||||
|
||||
def generate_target(self, use_deepcopy = False):
|
||||
self.target = None #Prevent exponential explosion
|
||||
def generate_target(self, use_deepcopy=False):
|
||||
self.target = None # Prevent exponential explosion
|
||||
if use_deepcopy:
|
||||
self.target = self.deepcopy()
|
||||
else:
|
||||
@ -149,8 +148,8 @@ class Mobject(Container):
|
||||
def shift(self, *vectors):
|
||||
total_vector = reduce(op.add, vectors)
|
||||
for mob in self.family_members_with_points():
|
||||
mob.points = mob.points.astype('float')
|
||||
mob.points += total_vector
|
||||
mob.points = mob.points.astype('float')
|
||||
mob.points += total_vector
|
||||
return self
|
||||
|
||||
def scale(self, scale_factor, **kwargs):
|
||||
@ -164,61 +163,61 @@ class Mobject(Container):
|
||||
respect to that point.
|
||||
"""
|
||||
self.apply_points_function_about_point(
|
||||
lambda points : scale_factor*points, **kwargs
|
||||
lambda points: scale_factor * points, **kwargs
|
||||
)
|
||||
return self
|
||||
|
||||
def rotate_about_origin(self, angle, axis = OUT, axes = []):
|
||||
return self.rotate(angle, axis, about_point = ORIGIN)
|
||||
def rotate_about_origin(self, angle, axis=OUT, axes=[]):
|
||||
return self.rotate(angle, axis, about_point=ORIGIN)
|
||||
|
||||
def rotate(self, angle, axis = OUT, **kwargs):
|
||||
def rotate(self, angle, axis=OUT, **kwargs):
|
||||
rot_matrix = rotation_matrix(angle, axis)
|
||||
self.apply_points_function_about_point(
|
||||
lambda points : np.dot(points, rot_matrix.T),
|
||||
lambda points: np.dot(points, rot_matrix.T),
|
||||
**kwargs
|
||||
)
|
||||
return self
|
||||
|
||||
def flip(self, axis = UP, **kwargs):
|
||||
return self.rotate(TAU/2, axis, **kwargs)
|
||||
def flip(self, axis=UP, **kwargs):
|
||||
return self.rotate(TAU / 2, axis, **kwargs)
|
||||
|
||||
def stretch(self, factor, dim, **kwargs):
|
||||
def func(points):
|
||||
points[:,dim] *= factor
|
||||
points[:, dim] *= factor
|
||||
return points
|
||||
self.apply_points_function_about_point(func, **kwargs)
|
||||
return self
|
||||
|
||||
def apply_function(self, function, **kwargs):
|
||||
#Default to applying matrix about the origin, not mobjects center
|
||||
# Default to applying matrix about the origin, not mobjects center
|
||||
if len(kwargs) == 0:
|
||||
kwargs["about_point"] = ORIGIN
|
||||
self.apply_points_function_about_point(
|
||||
lambda points : np.apply_along_axis(function, 1, points),
|
||||
lambda points: np.apply_along_axis(function, 1, points),
|
||||
**kwargs
|
||||
)
|
||||
return self
|
||||
|
||||
def apply_matrix(self, matrix, **kwargs):
|
||||
#Default to applying matrix about the origin, not mobjects center
|
||||
# Default to applying matrix about the origin, not mobjects center
|
||||
if len(kwargs) == 0:
|
||||
kwargs["about_point"] = ORIGIN
|
||||
full_matrix = np.identity(self.dim)
|
||||
matrix = np.array(matrix)
|
||||
full_matrix[:matrix.shape[0],:matrix.shape[1]] = matrix
|
||||
full_matrix[:matrix.shape[0], :matrix.shape[1]] = matrix
|
||||
self.apply_points_function_about_point(
|
||||
lambda points : np.dot(points, full_matrix.T),
|
||||
lambda points: np.dot(points, full_matrix.T),
|
||||
**kwargs
|
||||
)
|
||||
return self
|
||||
|
||||
def apply_complex_function(self, function, **kwargs):
|
||||
return self.apply_function(
|
||||
lambda (x, y, z) : complex_to_R3(function(complex(x, y))),
|
||||
lambda (x, y, z): complex_to_R3(function(complex(x, y))),
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def wag(self, direction = RIGHT, axis = DOWN, wag_factor = 1.0):
|
||||
def wag(self, direction=RIGHT, axis=DOWN, wag_factor=1.0):
|
||||
for mob in self.family_members_with_points():
|
||||
alphas = np.dot(mob.points, np.transpose(axis))
|
||||
alphas -= min(alphas)
|
||||
@ -233,7 +232,7 @@ class Mobject(Container):
|
||||
def reverse_points(self):
|
||||
for mob in self.family_members_with_points():
|
||||
mob.apply_over_attr_arrays(
|
||||
lambda arr : np.array(list(reversed(arr)))
|
||||
lambda arr: np.array(list(reversed(arr)))
|
||||
)
|
||||
return self
|
||||
|
||||
@ -243,18 +242,18 @@ class Mobject(Container):
|
||||
"""
|
||||
def repeat_array(array):
|
||||
return reduce(
|
||||
lambda a1, a2 : np.append(a1, a2, axis = 0),
|
||||
[array]*count
|
||||
lambda a1, a2: np.append(a1, a2, axis=0),
|
||||
[array] * count
|
||||
)
|
||||
for mob in self.family_members_with_points():
|
||||
mob.apply_over_attr_arrays(repeat_array)
|
||||
return self
|
||||
|
||||
#### In place operations ######
|
||||
#Note, much of these are now redundant with default behavior of
|
||||
#above methods
|
||||
# Note, much of these are now redundant with default behavior of
|
||||
# above methods
|
||||
|
||||
def apply_points_function_about_point(self, func, about_point = None, about_edge = ORIGIN):
|
||||
def apply_points_function_about_point(self, func, about_point=None, about_edge=ORIGIN):
|
||||
if about_point is None:
|
||||
about_point = self.get_critical_point(about_edge)
|
||||
for mob in self.family_members_with_points():
|
||||
@ -263,20 +262,20 @@ class Mobject(Container):
|
||||
mob.points += about_point
|
||||
return self
|
||||
|
||||
def rotate_in_place(self, angle, axis = OUT):
|
||||
def rotate_in_place(self, angle, axis=OUT):
|
||||
# redundant with default behavior of rotate now.
|
||||
return self.rotate(angle, axis = axis)
|
||||
return self.rotate(angle, axis=axis)
|
||||
|
||||
def scale_in_place(self, scale_factor, **kwargs):
|
||||
#Redundant with default behavior of scale now.
|
||||
# Redundant with default behavior of scale now.
|
||||
return self.scale(scale_factor, **kwargs)
|
||||
|
||||
def scale_about_point(self, scale_factor, point):
|
||||
#Redundant with default behavior of scale now.
|
||||
return self.scale(scale_factor, about_point = point)
|
||||
# Redundant with default behavior of scale now.
|
||||
return self.scale(scale_factor, about_point=point)
|
||||
|
||||
def pose_at_angle(self, **kwargs):
|
||||
self.rotate(TAU/14, RIGHT+UP, **kwargs)
|
||||
self.rotate(TAU / 14, RIGHT + UP, **kwargs)
|
||||
return self
|
||||
|
||||
#### Positioning methods ####
|
||||
@ -285,7 +284,7 @@ class Mobject(Container):
|
||||
self.shift(-self.get_center())
|
||||
return self
|
||||
|
||||
def align_on_border(self, direction, buff = DEFAULT_MOBJECT_TO_EDGE_BUFFER):
|
||||
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.
|
||||
@ -297,19 +296,19 @@ class Mobject(Container):
|
||||
self.shift(shift_val)
|
||||
return self
|
||||
|
||||
def to_corner(self, corner = LEFT+DOWN, buff = DEFAULT_MOBJECT_TO_EDGE_BUFFER):
|
||||
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):
|
||||
def to_edge(self, edge=LEFT, buff=DEFAULT_MOBJECT_TO_EDGE_BUFFER):
|
||||
return self.align_on_border(edge, buff)
|
||||
|
||||
def next_to(self, mobject_or_point,
|
||||
direction = RIGHT,
|
||||
buff = DEFAULT_MOBJECT_TO_MOBJECT_BUFFER,
|
||||
aligned_edge = ORIGIN,
|
||||
submobject_to_align = None,
|
||||
index_of_submobject_to_align = None,
|
||||
coor_mask = np.array([1,1,1]),
|
||||
direction=RIGHT,
|
||||
buff=DEFAULT_MOBJECT_TO_MOBJECT_BUFFER,
|
||||
aligned_edge=ORIGIN,
|
||||
submobject_to_align=None,
|
||||
index_of_submobject_to_align=None,
|
||||
coor_mask=np.array([1, 1, 1]),
|
||||
):
|
||||
if isinstance(mobject_or_point, Mobject):
|
||||
mob = mobject_or_point
|
||||
@ -329,10 +328,11 @@ class Mobject(Container):
|
||||
else:
|
||||
aligner = self
|
||||
point_to_align = aligner.get_critical_point(aligned_edge - direction)
|
||||
self.shift((target_point - point_to_align + buff*direction)*coor_mask)
|
||||
self.shift((target_point - point_to_align +
|
||||
buff * direction) * coor_mask)
|
||||
return self
|
||||
|
||||
def align_to(self, mobject_or_point, direction = ORIGIN, alignment_vect = UP):
|
||||
def align_to(self, mobject_or_point, direction=ORIGIN, alignment_vect=UP):
|
||||
"""
|
||||
Examples:
|
||||
mob1.align_to(mob2, UP) moves mob1 vertically so that its
|
||||
@ -349,12 +349,12 @@ class Mobject(Container):
|
||||
target_point = mobject_or_point
|
||||
direction_norm = np.linalg.norm(direction)
|
||||
if direction_norm > 0:
|
||||
alignment_vect = np.array(direction)/direction_norm
|
||||
alignment_vect = np.array(direction) / direction_norm
|
||||
reference_point = self.get_critical_point(direction)
|
||||
else:
|
||||
reference_point = self.get_center()
|
||||
diff = target_point - reference_point
|
||||
self.shift(alignment_vect*np.dot(diff, alignment_vect))
|
||||
self.shift(alignment_vect * np.dot(diff, alignment_vect))
|
||||
return self
|
||||
|
||||
def shift_onto_screen(self, **kwargs):
|
||||
@ -380,57 +380,57 @@ class Mobject(Container):
|
||||
return False
|
||||
|
||||
def stretch_about_point(self, factor, dim, point):
|
||||
return self.stretch(factor, dim, about_point = point)
|
||||
return self.stretch(factor, dim, about_point=point)
|
||||
|
||||
def stretch_in_place(self, factor, dim):
|
||||
#Now redundant with stretch
|
||||
# Now redundant with stretch
|
||||
return self.stretch(factor, dim)
|
||||
|
||||
def rescale_to_fit(self, length, dim, stretch = False, **kwargs):
|
||||
def rescale_to_fit(self, length, dim, stretch=False, **kwargs):
|
||||
old_length = self.length_over_dim(dim)
|
||||
if old_length == 0:
|
||||
return self
|
||||
if stretch:
|
||||
self.stretch(length/old_length, dim, **kwargs)
|
||||
self.stretch(length / old_length, dim, **kwargs)
|
||||
else:
|
||||
self.scale(length/old_length, **kwargs)
|
||||
self.scale(length / old_length, **kwargs)
|
||||
return self
|
||||
|
||||
def stretch_to_fit_width(self, width, **kwargs):
|
||||
return self.rescale_to_fit(width, 0, stretch = True, **kwargs)
|
||||
return self.rescale_to_fit(width, 0, stretch=True, **kwargs)
|
||||
|
||||
def stretch_to_fit_height(self, height, **kwargs):
|
||||
return self.rescale_to_fit(height, 1, stretch = True, **kwargs)
|
||||
return self.rescale_to_fit(height, 1, stretch=True, **kwargs)
|
||||
|
||||
def stretch_to_fit_depth(self, depth, **kwargs):
|
||||
return self.rescale_to_fit(depth, 1, stretch = True, **kwargs)
|
||||
return self.rescale_to_fit(depth, 1, stretch=True, **kwargs)
|
||||
|
||||
def scale_to_fit_width(self, width, **kwargs):
|
||||
return self.rescale_to_fit(width, 0, stretch = False, **kwargs)
|
||||
return self.rescale_to_fit(width, 0, stretch=False, **kwargs)
|
||||
|
||||
def scale_to_fit_height(self, height, **kwargs):
|
||||
return self.rescale_to_fit(height, 1, stretch = False, **kwargs)
|
||||
return self.rescale_to_fit(height, 1, stretch=False, **kwargs)
|
||||
|
||||
def scale_to_fit_depth(self, depth, **kwargs):
|
||||
return self.rescale_to_fit(depth, 2, stretch = False, **kwargs)
|
||||
return self.rescale_to_fit(depth, 2, stretch=False, **kwargs)
|
||||
|
||||
def space_out_submobjects(self, factor = 1.5, **kwargs):
|
||||
def space_out_submobjects(self, factor=1.5, **kwargs):
|
||||
self.scale(factor, **kwargs)
|
||||
for submob in self.submobjects:
|
||||
submob.scale(1./factor)
|
||||
submob.scale(1. / factor)
|
||||
return self
|
||||
|
||||
def move_to(self, point_or_mobject, aligned_edge = ORIGIN,
|
||||
coor_mask = np.array([1,1,1])):
|
||||
def move_to(self, point_or_mobject, aligned_edge=ORIGIN,
|
||||
coor_mask=np.array([1, 1, 1])):
|
||||
if isinstance(point_or_mobject, Mobject):
|
||||
target = point_or_mobject.get_critical_point(aligned_edge)
|
||||
else:
|
||||
target = point_or_mobject
|
||||
point_to_align = self.get_critical_point(aligned_edge)
|
||||
self.shift((target - point_to_align)*coor_mask)
|
||||
self.shift((target - point_to_align) * coor_mask)
|
||||
return self
|
||||
|
||||
def replace(self, mobject, dim_to_match = 0, stretch = False):
|
||||
def replace(self, mobject, dim_to_match=0, stretch=False):
|
||||
if not mobject.get_num_points() and not mobject.submobjects:
|
||||
raise Warning("Attempting to replace mobject with no points")
|
||||
return self
|
||||
@ -441,12 +441,12 @@ class Mobject(Container):
|
||||
self.rescale_to_fit(
|
||||
mobject.length_over_dim(dim_to_match),
|
||||
dim_to_match,
|
||||
stretch = False
|
||||
stretch=False
|
||||
)
|
||||
self.shift(mobject.get_center() - self.get_center())
|
||||
return self
|
||||
|
||||
def surround(self, mobject, dim_to_match = 0, stretch = False, buffer_factor = 1.2):
|
||||
def surround(self, mobject, dim_to_match=0, stretch=False, buffer_factor=1.2):
|
||||
self.replace(mobject, dim_to_match, stretch)
|
||||
self.scale_in_place(buffer_factor)
|
||||
|
||||
@ -455,15 +455,15 @@ class Mobject(Container):
|
||||
if np.all(curr_vect == 0):
|
||||
raise Exception("Cannot position endpoints of closed loop")
|
||||
target_vect = end - start
|
||||
self.scale(np.linalg.norm(target_vect)/np.linalg.norm(curr_vect))
|
||||
self.scale(np.linalg.norm(target_vect) / np.linalg.norm(curr_vect))
|
||||
self.rotate(
|
||||
angle_of_vector(target_vect) - \
|
||||
angle_of_vector(target_vect) -
|
||||
angle_of_vector(curr_vect)
|
||||
)
|
||||
self.shift(start-self.points[0])
|
||||
self.shift(start - self.points[0])
|
||||
return self
|
||||
|
||||
## Match other mobvject properties
|
||||
# Match other mobvject properties
|
||||
|
||||
def match_color(self, mobject):
|
||||
return self.set_color(mobject.get_color())
|
||||
@ -483,9 +483,9 @@ class Mobject(Container):
|
||||
def match_depth(self, mobject, **kwargs):
|
||||
return self.match_dim(mobject, 2, **kwargs)
|
||||
|
||||
## Color functions
|
||||
# Color functions
|
||||
|
||||
def set_color(self, color = YELLOW_C, family = True):
|
||||
def set_color(self, color=YELLOW_C, family=True):
|
||||
"""
|
||||
Condition is function which takes in one arguments, (x, y, z).
|
||||
Here it just recurses to submobjects, but in subclasses this
|
||||
@ -494,7 +494,7 @@ class Mobject(Container):
|
||||
"""
|
||||
if family:
|
||||
for submob in self.submobjects:
|
||||
submob.set_color(color, family = family)
|
||||
submob.set_color(color, family=family)
|
||||
self.color = color
|
||||
return self
|
||||
|
||||
@ -502,8 +502,9 @@ class Mobject(Container):
|
||||
self.set_submobject_colors_by_gradient(*colors)
|
||||
return self
|
||||
|
||||
def set_colors_by_radial_gradient(self, center = None, radius = 1, inner_color = WHITE, outer_color = BLACK):
|
||||
self.set_submobject_colors_by_radial_gradient(center, radius, inner_color, outer_color)
|
||||
def set_colors_by_radial_gradient(self, center=None, radius=1, inner_color=WHITE, outer_color=BLACK):
|
||||
self.set_submobject_colors_by_radial_gradient(
|
||||
center, radius, inner_color, outer_color)
|
||||
return self
|
||||
|
||||
def set_submobject_colors_by_gradient(self, *colors):
|
||||
@ -516,19 +517,19 @@ class Mobject(Container):
|
||||
new_colors = color_gradient(colors, len(mobs))
|
||||
|
||||
for mob, color in zip(mobs, new_colors):
|
||||
mob.set_color(color, family = False)
|
||||
mob.set_color(color, family=False)
|
||||
return self
|
||||
|
||||
def set_submobject_colors_by_radial_gradient(self, center = None, radius = 1, inner_color = WHITE, outer_color = BLACK):
|
||||
def set_submobject_colors_by_radial_gradient(self, center=None, radius=1, inner_color=WHITE, outer_color=BLACK):
|
||||
mobs = self.family_members_with_points()
|
||||
if center == None:
|
||||
center = self.get_center()
|
||||
|
||||
for mob in self.family_members_with_points():
|
||||
t = np.linalg.norm(mob.get_center() - center)/radius
|
||||
t = min(t,1)
|
||||
t = np.linalg.norm(mob.get_center() - center) / radius
|
||||
t = min(t, 1)
|
||||
mob_color = interpolate_color(inner_color, outer_color, t)
|
||||
mob.set_color(mob_color, family = False)
|
||||
mob.set_color(mob_color, family=False)
|
||||
|
||||
return self
|
||||
|
||||
@ -538,7 +539,7 @@ class Mobject(Container):
|
||||
|
||||
# Some objects (e.g., VMobjects) have special fading
|
||||
# behavior. We let every object handle its individual
|
||||
# fading via fade_no_recurse (notionally a purely internal method),
|
||||
# fading via fade_no_recurse (notionally a purely internal method),
|
||||
# and then have fade() itself call this recursively on each submobject
|
||||
#
|
||||
# Similarly for fade_to_no_recurse and fade_to, the underlying functions
|
||||
@ -549,7 +550,7 @@ class Mobject(Container):
|
||||
start = color_to_rgb(self.get_color())
|
||||
end = color_to_rgb(color)
|
||||
new_rgb = interpolate(start, end, alpha)
|
||||
self.set_color(Color(rgb = new_rgb), family = False)
|
||||
self.set_color(Color(rgb=new_rgb), family=False)
|
||||
return self
|
||||
|
||||
def fade_to(self, color, alpha):
|
||||
@ -561,7 +562,7 @@ class Mobject(Container):
|
||||
self.fade_to_no_recurse(BLACK, darkness)
|
||||
return self
|
||||
|
||||
def fade(self, darkness = 0.5):
|
||||
def fade(self, darkness=0.5):
|
||||
for submob in self.submobject_family():
|
||||
submob.fade_no_recurse(darkness)
|
||||
return self
|
||||
@ -570,9 +571,9 @@ class Mobject(Container):
|
||||
return self.color
|
||||
##
|
||||
|
||||
def save_state(self, use_deepcopy = False):
|
||||
def save_state(self, use_deepcopy=False):
|
||||
if hasattr(self, "saved_state"):
|
||||
#Prevent exponential growth of data
|
||||
# Prevent exponential growth of data
|
||||
self.saved_state = None
|
||||
if use_deepcopy:
|
||||
self.saved_state = self.deepcopy()
|
||||
@ -634,7 +635,7 @@ class Mobject(Container):
|
||||
max_point = self.reduce_across_dimension(np.max, np.max, dim)
|
||||
|
||||
if direction[dim] == 0:
|
||||
result[dim] = (max_point+min_point)/2
|
||||
result[dim] = (max_point + min_point) / 2
|
||||
elif direction[dim] < 0:
|
||||
result[dim] = min_point
|
||||
else:
|
||||
@ -694,8 +695,7 @@ class Mobject(Container):
|
||||
def point_from_proportion(self, alpha):
|
||||
raise Exception("Not implemented")
|
||||
|
||||
|
||||
## Family matters
|
||||
# Family matters
|
||||
|
||||
def __getitem__(self, value):
|
||||
self_list = self.split()
|
||||
@ -724,22 +724,22 @@ class Mobject(Container):
|
||||
|
||||
def family_members_with_points(self):
|
||||
return filter(
|
||||
lambda m : m.get_num_points() > 0,
|
||||
lambda m: m.get_num_points() > 0,
|
||||
self.submobject_family()
|
||||
)
|
||||
|
||||
def arrange_submobjects(self, direction = RIGHT, center = True, **kwargs):
|
||||
def arrange_submobjects(self, direction=RIGHT, center=True, **kwargs):
|
||||
for m1, m2 in zip(self.submobjects, self.submobjects[1:]):
|
||||
m2.next_to(m1, direction, **kwargs)
|
||||
if center:
|
||||
self.center()
|
||||
return self
|
||||
|
||||
def arrange_submobjects_in_grid(self, n_rows = None, n_cols = None, **kwargs):
|
||||
def arrange_submobjects_in_grid(self, n_rows=None, n_cols=None, **kwargs):
|
||||
submobs = self.submobjects
|
||||
if n_rows is None and n_cols is None:
|
||||
n_cols = int(np.sqrt(len(submobs)))
|
||||
|
||||
|
||||
if n_rows is not None:
|
||||
v1 = RIGHT
|
||||
v2 = DOWN
|
||||
@ -749,35 +749,35 @@ class Mobject(Container):
|
||||
v2 = RIGHT
|
||||
n = len(submobs) / n_cols
|
||||
Group(*[
|
||||
Group(*submobs[i:i+n]).arrange_submobjects(v1, **kwargs)
|
||||
Group(*submobs[i:i + n]).arrange_submobjects(v1, **kwargs)
|
||||
for i in range(0, len(submobs), n)
|
||||
]).arrange_submobjects(v2, **kwargs)
|
||||
return self
|
||||
|
||||
def sort_submobjects(self, point_to_num_func = lambda p : p[0]):
|
||||
def sort_submobjects(self, point_to_num_func=lambda p: p[0]):
|
||||
self.submobjects.sort(
|
||||
lambda *mobs : cmp(*[
|
||||
lambda *mobs: cmp(*[
|
||||
point_to_num_func(mob.get_center())
|
||||
for mob in mobs
|
||||
])
|
||||
)
|
||||
return self
|
||||
|
||||
def print_submobject_family(self, n_tabs = 0):
|
||||
def print_submobject_family(self, n_tabs=0):
|
||||
"""For debugging purposes"""
|
||||
print "\t"*n_tabs, self, id(self)
|
||||
print "\t" * n_tabs, self, id(self)
|
||||
for submob in self.submobjects:
|
||||
submob.print_mobject_family(n_tabs + 1)
|
||||
|
||||
## Alignment
|
||||
# Alignment
|
||||
def align_data(self, mobject):
|
||||
self.align_submobjects(mobject)
|
||||
self.align_points(mobject)
|
||||
#Recurse
|
||||
# Recurse
|
||||
for m1, m2 in zip(self.submobjects, mobject.submobjects):
|
||||
m1.align_data(m2)
|
||||
|
||||
def get_point_mobject(self, center = None):
|
||||
def get_point_mobject(self, center=None):
|
||||
"""
|
||||
The simplest mobject to be transformed to or from self.
|
||||
Should by a point of the appropriate type
|
||||
@ -797,8 +797,8 @@ class Mobject(Container):
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def align_submobjects(self, mobject):
|
||||
#If one is empty, and the other is not,
|
||||
#push it into its submobject list
|
||||
# If one is empty, and the other is not,
|
||||
# push it into its submobject list
|
||||
self_has_points, mob_has_points = [
|
||||
mob.get_num_points() > 0
|
||||
for mob in self, mobject
|
||||
@ -809,7 +809,7 @@ class Mobject(Container):
|
||||
self.null_point_align(mobject)
|
||||
self_count = len(self.submobjects)
|
||||
mob_count = len(mobject.submobjects)
|
||||
diff = self_count-mob_count
|
||||
diff = self_count - mob_count
|
||||
if diff < 0:
|
||||
self.add_n_more_submobjects(-diff)
|
||||
elif diff > 0:
|
||||
@ -840,7 +840,7 @@ class Mobject(Container):
|
||||
self.add(self.copy())
|
||||
n -= 1
|
||||
curr += 1
|
||||
indices = curr*np.arange(curr+n)/(curr+n)
|
||||
indices = curr * np.arange(curr + n) / (curr + n)
|
||||
new_submobjects = []
|
||||
for index in indices:
|
||||
submob = self.submobjects[index]
|
||||
@ -854,7 +854,7 @@ class Mobject(Container):
|
||||
return submob.copy()
|
||||
|
||||
def interpolate(self, mobject1, mobject2,
|
||||
alpha, path_func = straight_path):
|
||||
alpha, path_func=straight_path):
|
||||
"""
|
||||
Turns self into an interpolation between mobject1
|
||||
and mobject2.
|
||||
@ -865,7 +865,7 @@ class Mobject(Container):
|
||||
self.interpolate_color(mobject1, mobject2, alpha)
|
||||
|
||||
def interpolate_color(self, mobject1, mobject2, alpha):
|
||||
pass #To implement in subclass
|
||||
pass # To implement in subclass
|
||||
|
||||
def become_partial(self, mobject, a, b):
|
||||
"""
|
||||
@ -874,15 +874,16 @@ class Mobject(Container):
|
||||
Inputs 0 <= a < b <= 1 determine what portion
|
||||
of mobject to become.
|
||||
"""
|
||||
pass #To implement in subclasses
|
||||
pass # To implement in subclasses
|
||||
|
||||
#TODO, color?
|
||||
# TODO, color?
|
||||
|
||||
def pointwise_become_partial(self, mobject, a, b):
|
||||
pass #To implement in subclass
|
||||
pass # To implement in subclass
|
||||
|
||||
|
||||
class Group(Mobject):
|
||||
#Alternate name to improve readibility in cases where
|
||||
#the mobject is used primarily for its submobject housing
|
||||
#functionality.
|
||||
# Alternate name to improve readibility in cases where
|
||||
# the mobject is used primarily for its submobject housing
|
||||
# functionality.
|
||||
pass
|
||||
|
Reference in New Issue
Block a user