Redid digest_config and introduced digest_locals

This commit is contained in:
Grant Sanderson 2015-10-28 16:03:33 -07:00
parent 2e074afb60
commit 468d05d049
22 changed files with 185 additions and 193 deletions

View file

@ -9,8 +9,7 @@ import progressbar
import inspect import inspect
from helpers import * from helpers import *
from mobject import Mobject from mobject import Mobject, Point
from topics.geometry import Point
class Animation(object): class Animation(object):
DEFAULT_CONFIG = { DEFAULT_CONFIG = {
@ -21,7 +20,7 @@ class Animation(object):
def __init__(self, mobject, **kwargs): def __init__(self, mobject, **kwargs):
mobject = instantiate(mobject) mobject = instantiate(mobject)
assert(isinstance(mobject, Mobject)) assert(isinstance(mobject, Mobject))
digest_config(self, Animation, kwargs, locals()) digest_config(self, kwargs, locals())
self.starting_mobject = copy.deepcopy(self.mobject) self.starting_mobject = copy.deepcopy(self.mobject)
if self.alpha_func is None: if self.alpha_func is None:
self.alpha_func = (lambda x : x) self.alpha_func = (lambda x : x)

View file

@ -18,12 +18,12 @@ class DelayByOrder(Animation):
"max_power" : 5 "max_power" : 5
} }
def __init__(self, animation, **kwargs): def __init__(self, animation, **kwargs):
digest_config(self, DelayByOrder, kwargs, locals()) digest_locals(self)
self.num_mobject_points = animation.mobject.get_num_points()
kwargs.update(dict([ kwargs.update(dict([
(attr, getattr(animation, attr)) (attr, getattr(animation, attr))
for attr in Animation.DEFAULT_CONFIG for attr in Animation.DEFAULT_CONFIG
])) ]))
self.num_mobject_points = animation.mobject.get_num_points()
Animation.__init__(self, animation.mobject, **kwargs) Animation.__init__(self, animation.mobject, **kwargs)
self.name = self.__class__.__name__ + str(self.animation) self.name = self.__class__.__name__ + str(self.animation)
@ -44,7 +44,6 @@ class TransformAnimations(Transform):
"alpha_func" : squish_alpha_func(smooth) "alpha_func" : squish_alpha_func(smooth)
} }
def __init__(self, start_anim, end_anim, **kwargs): def __init__(self, start_anim, end_anim, **kwargs):
digest_config(self, TransformAnimations, kwargs, locals())
if "run_time" in kwargs: if "run_time" in kwargs:
self.run_time = kwargs.pop("run_time") self.run_time = kwargs.pop("run_time")
else: else:

View file

@ -16,10 +16,6 @@ class Rotating(Animation):
"run_time" : 20.0, "run_time" : 20.0,
"alpha_func" : None, "alpha_func" : None,
} }
def __init__(self, mobject, **kwargs):
digest_config(self, Rotating, kwargs, locals())
Animation.__init__(self, mobject, **kwargs)
def update_mobject(self, alpha): def update_mobject(self, alpha):
self.mobject.points = self.starting_mobject.points self.mobject.points = self.starting_mobject.points
for axis in self.axes: for axis in self.axes:
@ -61,7 +57,6 @@ class Flash(Animation):
"alpha_func" : None, "alpha_func" : None,
} }
def __init__(self, mobject, **kwargs): def __init__(self, mobject, **kwargs):
digest_config(self, Flash, kwargs, locals())
self.intermediate = Mobject(color = self.color) self.intermediate = Mobject(color = self.color)
self.intermediate.add_points([ self.intermediate.add_points([
point + (x, y, 0) point + (x, y, 0)
@ -82,12 +77,12 @@ class Flash(Animation):
) )
class Homotopy(Animation): class Homotopy(Animation):
def __init__(self, homotopy, **kwargs): def __init__(self, homotopy, mobject, **kwargs):
""" """
Homotopy a function from (x, y, z, t) to (x', y', z') Homotopy a function from (x, y, z, t) to (x', y', z')
""" """
digest_config(self, Homotopy, kwargs, locals()) digest_locals(self)
Animation.__init__(self, **kwargs) Animation.__init__(self, mobject, **kwargs)
def update_mobject(self, alpha): def update_mobject(self, alpha):
self.mobject.points = np.array([ self.mobject.points = np.array([

View file

@ -7,9 +7,7 @@ import warnings
from helpers import * from helpers import *
from animation import Animation from animation import Animation
from mobject import Mobject from mobject import Mobject, Point
from topics.geometry import Point
from topics.complex_numbers import ComplexPlane
class Transform(Animation): class Transform(Animation):
DEFAULT_CONFIG = { DEFAULT_CONFIG = {
@ -18,7 +16,7 @@ class Transform(Animation):
} }
def __init__(self, mobject, ending_mobject, **kwargs): def __init__(self, mobject, ending_mobject, **kwargs):
mobject, ending_mobject = map(instantiate, [mobject, ending_mobject]) mobject, ending_mobject = map(instantiate, [mobject, ending_mobject])
digest_config(self, Transform, kwargs, locals()) digest_config(self, kwargs, locals())
count1, count2 = mobject.get_num_points(), ending_mobject.get_num_points() count1, count2 = mobject.get_num_points(), ending_mobject.get_num_points()
if count2 == 0: if count2 == 0:
ending_mobject.add_points([SPACE_WIDTH*RIGHT+SPACE_HEIGHT*UP]) ending_mobject.add_points([SPACE_WIDTH*RIGHT+SPACE_HEIGHT*UP])
@ -73,24 +71,17 @@ class ClockwiseTransform(Transform):
DEFAULT_CONFIG = { DEFAULT_CONFIG = {
"interpolation_function" : clockwise_path() "interpolation_function" : clockwise_path()
} }
def __init__(self, *args, **kwargs):
digest_config(self, ClockwiseTransform, kwargs)
Transform.__init__(self, *args, **kwargs)
class CounterclockwiseTransform(Transform): class CounterclockwiseTransform(Transform):
DEFAULT_CONFIG = { DEFAULT_CONFIG = {
"interpolation_function" : counterclockwise_path() "interpolation_function" : counterclockwise_path()
} }
def __init__(self, *args, **kwargs):
digest_config(self, ClockwiseTransform, kwargs)
Transform.__init__(self, *args, **kwargs)
class SpinInFromNothing(Transform): class SpinInFromNothing(Transform):
DEFAULT_CONFIG = { DEFAULT_CONFIG = {
"interpolation_function" : counterclockwise_path() "interpolation_function" : counterclockwise_path()
} }
def __init__(self, mob, **kwargs): def __init__(self, mob, **kwargs):
digest_config(self, SpinInFromNothing, kwargs)
Transform.__init__(self, Point(mob.get_center()), mob, **kwargs) Transform.__init__(self, Point(mob.get_center()), mob, **kwargs)
class ApplyMethod(Transform): class ApplyMethod(Transform):
@ -121,7 +112,6 @@ class ApplyPointwiseFunction(ApplyMethod):
"run_time" : DEFAULT_POINTWISE_FUNCTION_RUN_TIME "run_time" : DEFAULT_POINTWISE_FUNCTION_RUN_TIME
} }
def __init__(self, function, mobject, **kwargs): def __init__(self, function, mobject, **kwargs):
digest_config(self, ApplyPointwiseFunction, kwargs)
ApplyMethod.__init__( ApplyMethod.__init__(
self, mobject.apply_function, function, **kwargs self, mobject.apply_function, function, **kwargs
) )

View file

@ -12,23 +12,31 @@ from helpers import *
from scene import Scene from scene import Scene
HELP_MESSAGE = """ HELP_MESSAGE = """
<script name> [<scene name or initials>] [<arg_string>] Usage:
python extract_scene.py <module> [<scene name>] [<arg_string>]
-p preview in low quality -p preview in low quality
-s show and save picture of last frame -s show and save picture of last frame
-w write result to file [this is default if nothing else is stated]
-l use low quality -l use low quality
-a run and save every scene in the script -m use medium quality
-a run and save every scene in the script, or all args for the given scene
-q don't pring progress -q don't pring progress
""" """
SCENE_NOT_FOUND_MESSAGE = """ SCENE_NOT_FOUND_MESSAGE = """
That scene is not in the script That scene is not in the script
""" """
CHOOSE_NUMBER_MESSAGE = """ CHOOSE_NUMBER_MESSAGE = """
Choose number corresponding to desired scene arguments. Choose number corresponding to desired scene/arguments.
(Use comma separated list for multiple entries) (Use comma separated list for multiple entries)
Choice(s): """ Choice(s): """
INVALID_NUMBER_MESSAGE = "Fine then, if you don't want to give a valid number I'll just quit" INVALID_NUMBER_MESSAGE = "Fine then, if you don't want to give a valid number I'll just quit"
NO_SCENE_MESSAGE = """
There are no scenes inside that module
"""
def get_configuration(sys_argv): def get_configuration(sys_argv):
try: try:
@ -72,8 +80,10 @@ def get_configuration(sys_argv):
if not any([config[key] for key in actions]): if not any([config[key] for key in actions]):
config["write"] = True config["write"] = True
if len(args) > 0: if len(args) == 0:
config["module"] = args[0] print HELP_MESSAGE
sys.exit()
config["module"] = args[0].replace(".py", "")
if len(args) > 1: if len(args) > 1:
config["scene_name"] = args[1] config["scene_name"] = args[1]
if len(args) > 2: if len(args) > 2:
@ -110,16 +120,16 @@ def is_scene(obj):
return False return False
return True return True
def prompt_user_for_args(args_list, args_to_string): def prompt_user_for_choice(name_to_obj):
num_to_args = {} num_to_name = {}
for count, args in zip(it.count(1), args_list): for count, name in zip(it.count(1), name_to_obj):
print "%d: %s"%(count, args_to_string(*args)) print "%d: %s"%(count, name)
num_to_args[count] = args num_to_name[count] = name
try: try:
choice = raw_input(CHOOSE_NUMBER_MESSAGE) user_input = raw_input(CHOOSE_NUMBER_MESSAGE)
return [ return [
num_to_args[int(num_str)] name_to_obj[num_to_name[int(num_str)]]
for num_str in choice.split(",") for num_str in user_input.split(",")
] ]
except: except:
print INVALID_NUMBER_MESSAGE print INVALID_NUMBER_MESSAGE
@ -139,38 +149,49 @@ def get_scene_args(SceneClass, config):
if num_args == 0: if num_args == 0:
return [()] return [()]
elif config["write_all"]: if config["write_all"]:
return args_list return args_list
elif config["args_extension"] in preset_extensions: if config["args_extension"] in preset_extensions:
index = preset_extensions.index(config["args_extension"]) index = preset_extensions.index(config["args_extension"])
return [args_list[index]] return [args_list[index]]
elif len(args_list) == 1: if config["args_extension"] == "" :
return [args_list[0]] name_to_args = dict(zip(preset_extensions, args_list))
elif config["args_extension"] == "" : return prompt_user_for_choice(name_to_args)
return prompt_user_for_args(args_list, SceneClass.args_to_string) if len(args_list) == 1:
else: return args_list
return [SceneClass.string_to_args(config["args_extension"])] return [SceneClass.string_to_args(config["args_extension"])]
def get_scene_classes(scene_names_to_classes, config):
if len(scene_names_to_classes) == 0:
print NO_SCENE_MESSAGE
return []
if len(scene_names_to_classes) == 1:
return scene_names_to_classes.values()
if config["scene_name"] in scene_names_to_classes:
return [scene_names_to_classes[config["scene_name"]] ]
if config["scene_name"] != "":
print SCENE_NOT_FOUND_MESSAGE
return []
if config["write_all"]:
return scene_names_to_classes.values()
return prompt_user_for_choice(scene_names_to_classes)
def main(): def main():
config = get_configuration(sys.argv) config = get_configuration(sys.argv)
module = imp.load_source(config["module_name"], ".") module = imp.load_module(
config["module"],
*imp.find_module(config["module"])
)
scene_names_to_classes = dict( scene_names_to_classes = dict(
inspect.getmembers(module, is_scene) inspect.getmembers(module, is_scene)
) )
config["movie_prefix"] = config["module_name"].split(".py")[0] config["movie_prefix"] = config["module"]
if config["scene_name"] in scene_names_to_classes:
scene_classes = [scene_names_to_classes[config["scene_name"]] ]
elif config["scene_name"] == "" and config["write_all"]:
scene_classes = scene_names_to_classes.values()
else:
print SCENE_NOT_FOUND_MESSAGE
return
scene_kwargs = { scene_kwargs = {
"display_config" : config["display_config"], "display_config" : config["display_config"],
"announce_construction" : True "announce_construction" : True
} }
for SceneClass in scene_classes: for SceneClass in get_scene_classes(scene_names_to_classes, config):
for args in get_scene_args(SceneClass, config): for args in get_scene_args(SceneClass, config):
scene_kwargs["construct_args"] = args scene_kwargs["construct_args"] = args
try: try:

View file

@ -1,11 +1,13 @@
import numpy as np import numpy as np
import itertools as it import itertools as it
import operator as op
from PIL import Image from PIL import Image
from colour import Color from colour import Color
from random import random from random import random
import inspect
import string import string
import re import re
import operator as op
from constants import * from constants import *
@ -24,24 +26,37 @@ def instantiate(obj):
return obj() if isinstance(obj, type) else obj return obj() if isinstance(obj, type) else obj
def digest_config(obj, Class, kwargs, local_args = {}): def filtered_locals(local_args):
result = local_args.copy()
ignored_local_args = ["self", "kwargs"]
for arg in ignored_local_args:
result.pop(arg, local_args)
return result
def digest_config(obj, kwargs, local_args = {}):
""" """
To be used in initializing most-to-all objects. Sets init args and DEFAULT_CONFIG values as local variables
Sets key word args as local variables
""" """
### Assemble list of DEFAULT_CONFIGs from all super classes
classes_in_heirarchy = [obj.__class__]
default_configs = []
while len(classes_in_heirarchy) > 0:
Class = classes_in_heirarchy.pop()
classes_in_heirarchy += Class.__bases__
if hasattr(Class, "DEFAULT_CONFIG"): if hasattr(Class, "DEFAULT_CONFIG"):
config = Class.DEFAULT_CONFIG.copy() default_configs.append(Class.DEFAULT_CONFIG)
else:
config = {} #Order matters a lot here, first dicts have higher priority
for key in config.keys(): all_dicts = [kwargs, filtered_locals(local_args), obj.__dict__]
if hasattr(obj, key): all_dicts += default_configs
config.pop(key) item_lists = reversed([d.items() for d in all_dicts])
if key in kwargs: obj.__dict__ = dict(reduce(op.add, item_lists))
config[key] = kwargs.pop(key)
for key in local_args: def digest_locals(obj):
if key not in ["self", "kwargs"]: caller_locals = inspect.currentframe().f_back.f_locals
config[key] = local_args[key] obj.__dict__.update(filtered_locals(caller_locals))
obj.__dict__.update(config)
def interpolate(start, end, alpha): def interpolate(start, end, alpha):
return (1-alpha)*start + alpha*end return (1-alpha)*start + alpha*end

View file

@ -4,6 +4,7 @@ import os
from PIL import Image from PIL import Image
from random import random from random import random
from helpers import *
from tex_utils import tex_to_image from tex_utils import tex_to_image
from mobject import Mobject from mobject import Mobject
@ -20,7 +21,7 @@ class ImageMobject(Mobject):
"should_center" : True "should_center" : True
} }
def __init__(self, image_file, **kwargs): def __init__(self, image_file, **kwargs):
digest_config(self, ImageMobject, kwargs, locals()) digest_locals(self)
Mobject.__init__(self, **kwargs) Mobject.__init__(self, **kwargs)
self.filter_rgb = 255 * np.array(Color(self.filter_color).get_rgb()).astype('uint8') self.filter_rgb = 255 * np.array(Color(self.filter_color).get_rgb()).astype('uint8')
self.name = to_cammel_case( self.name = to_cammel_case(
@ -98,40 +99,3 @@ class ImageMobject(Mobject):
points *= 2 * SPACE_WIDTH / width points *= 2 * SPACE_WIDTH / width
self.add_points(points, rgbs = rgbs) self.add_points(points, rgbs = rgbs)
#TODO, Make both of these proper mobject classes
def text_mobject(text, size = None):
size = size or "\\Large" #TODO, auto-adjust?
return tex_mobject(text, size, TEMPLATE_TEXT_FILE)
def tex_mobject(expression,
size = None,
template_tex_file = TEMPLATE_TEX_FILE):
if size == None:
if len("".join(expression)) < MAX_LEN_FOR_HUGE_TEX_FONT:
size = "\\Huge"
else:
size = "\\large"
#Todo, make this more sophisticated.
image_files = tex_to_image(expression, size, template_tex_file)
config = {
"point_thickness" : 1,
"should_center" : False,
}
if isinstance(image_files, list):
#TODO, is checking listiness really the best here?
result = CompoundMobject(*[
ImageMobject(f, **config)
for f in image_files
])
else:
result = ImageMobject(image_files, **config)
return result.center().highlight("white")
def underbrace(left, right, buff = 0.2):
result = tex_mobject("\\underbrace{%s}"%(14*"\\quad"))
result.stretch_to_fit_width(right[0]-left[0])
result.shift(left - result.points[0] + buff*DOWN)
return result

View file

@ -24,7 +24,7 @@ class Mobject(object):
} }
DIM = 3 DIM = 3
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, Mobject, kwargs) digest_config(self, kwargs)
self.color = Color(self.color) self.color = Color(self.color)
if self.name is None: if self.name is None:
self.name = self.__class__.__name__ self.name = self.__class__.__name__
@ -358,10 +358,11 @@ class Mobject1D(Mobject):
"density" : DEFAULT_POINT_DENSITY_1D, "density" : DEFAULT_POINT_DENSITY_1D,
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, Mobject1D, kwargs) digest_config(self, kwargs)
self.epsilon = 1.0 / self.density self.epsilon = 1.0 / self.density
Mobject.__init__(self, **kwargs) Mobject.__init__(self, **kwargs)
def add_line(self, start, end, min_density = 0.1, color = None): def add_line(self, start, end, min_density = 0.1, color = None):
length = np.linalg.norm(end - start) length = np.linalg.norm(end - start)
epsilon = self.epsilon / max(length, min_density) epsilon = self.epsilon / max(length, min_density)
@ -375,7 +376,7 @@ class Mobject2D(Mobject):
"density" : DEFAULT_POINT_DENSITY_2D, "density" : DEFAULT_POINT_DENSITY_2D,
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, Mobject2D, kwargs) digest_config(self, kwargs)
self.epsilon = 1.0 / self.density self.epsilon = 1.0 / self.density
Mobject.__init__(self, **kwargs) Mobject.__init__(self, **kwargs)
@ -402,6 +403,18 @@ class CompoundMobject(Mobject):
curr += num_points curr += num_points
return result return result
class Point(Mobject):
DEFAULT_CONFIG = {
"color" : BLACK,
}
def __init__(self, location = ORIGIN, **kwargs):
digest_locals(self)
Mobject.__init__(self, **kwargs)
def generate_points(self):
self.add_points([self.location])
# class CompoundMobject(Mobject): # class CompoundMobject(Mobject):
# """ # """
# Treats a collection of mobjects as if they were one. # Treats a collection of mobjects as if they were one.

View file

@ -10,8 +10,6 @@ from helpers import *
from scene import Scene from scene import Scene
from number_line import NumberLineScene from number_line import NumberLineScene
MOVIE_PREFIX = "matrix_as_transform_2d/"
ARROW_CONFIG = {"point_thickness" : 2*DEFAULT_POINT_THICKNESS} ARROW_CONFIG = {"point_thickness" : 2*DEFAULT_POINT_THICKNESS}
LIGHT_RED = RED_E LIGHT_RED = RED_E
@ -543,9 +541,3 @@ class Show90DegreeRotation(TransformScene2D):
]) ])
self.dither() self.dither()
if __name__ == "__main__":
command_line_create_scene(MOVIE_PREFIX)

View file

@ -83,7 +83,7 @@ class RightParen(Mobject):
class OpenInterval(CompoundMobject): class OpenInterval(CompoundMobject):
def __init__(self, center_point = ORIGIN, width = 2, **kwargs): def __init__(self, center_point = ORIGIN, width = 2, **kwargs):
digest_config(self, OpenInterval, kwargs, locals()) digest_config(self, kwargs, locals())
left = LeftParen().shift(LEFT*width/2) left = LeftParen().shift(LEFT*width/2)
right = RightParen().shift(RIGHT*width/2) right = RightParen().shift(RIGHT*width/2)
CompoundMobject.__init__(self, left, right, **kwargs) CompoundMobject.__init__(self, left, right, **kwargs)
@ -99,7 +99,7 @@ class Piano(ImageMobject):
"scale_value" : 0.5 "scale_value" : 0.5
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, Piano, kwargs) digest_config(self, kwargs)
ImageMobject.__init__(self, "piano_keyboard") ImageMobject.__init__(self, "piano_keyboard")
jump = self.get_width()/24 jump = self.get_width()/24
self.center() self.center()
@ -137,7 +137,7 @@ class VibratingString(Animation):
"alpha_func" : None "alpha_func" : None
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, VibratingString, kwargs) digest_config(self, kwargs)
def func(x, t): def func(x, t):
return sum([ return sum([
(self.amplitude/((k+1)**2.5))*np.sin(2*mult*t)*np.sin(k*mult*x) (self.amplitude/((k+1)**2.5))*np.sin(2*mult*t)*np.sin(k*mult*x)

View file

@ -9,8 +9,6 @@ from scene import Scene
from geometry import Polygon from geometry import Polygon
from region import region_from_polygon_vertices, region_from_line_boundary from region import region_from_polygon_vertices, region_from_line_boundary
MOVIE_PREFIX = "pythagorean_proof"
A_COLOR = BLUE A_COLOR = BLUE
B_COLOR = MAROON_D B_COLOR = MAROON_D
C_COLOR = YELLOW C_COLOR = YELLOW

View file

@ -1,3 +1 @@
from scene import * from scene import *
from scene_from_video import *
from tk_scene import *

View file

@ -13,6 +13,7 @@ from helpers import *
import displayer as disp import displayer as disp
from tk_scene import TkSceneRoot from tk_scene import TkSceneRoot
from mobject import Mobject
class Scene(object): class Scene(object):
DEFAULT_CONFIG = { DEFAULT_CONFIG = {
@ -23,7 +24,7 @@ class Scene(object):
"announce_construction" : False, "announce_construction" : False,
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, Scene, kwargs) digest_config(self, kwargs)
if self.announce_construction: if self.announce_construction:
print "Constructing %s..."%str(self) print "Constructing %s..."%str(self)
self.frame_duration = self.display_config["frame_duration"] self.frame_duration = self.display_config["frame_duration"]

View file

@ -1,10 +1,44 @@
import os
import itertools as it
from PIL import Image
from image_mobject import ImageMobject
from helpers import * from helpers import *
#TODO, Cleanup and refactor this file. #TODO, Cleanup and refactor this file.
#TODO, Make both of these proper mobject classes
def text_mobject(text, size = None):
size = size or "\\Large" #TODO, auto-adjust?
return tex_mobject(text, size, TEMPLATE_TEXT_FILE)
def tex_mobject(expression,
size = None,
template_tex_file = TEMPLATE_TEX_FILE):
if size == None:
if len("".join(expression)) < MAX_LEN_FOR_HUGE_TEX_FONT:
size = "\\Huge"
else:
size = "\\large"
#Todo, make this more sophisticated.
image_files = tex_to_image(expression, size, template_tex_file)
config = {
"point_thickness" : 1,
"should_center" : False,
}
if isinstance(image_files, list):
#TODO, is checking listiness really the best here?
result = CompoundMobject(*[
ImageMobject(f, **config)
for f in image_files
])
else:
result = ImageMobject(image_files, **config)
return result.center().highlight("white")
def underbrace(left, right, buff = 0.2):
result = tex_mobject("\\underbrace{%s}"%(14*"\\quad"))
result.stretch_to_fit_width(right[0]-left[0])
result.shift(left - result.points[0] + buff*DOWN)
return result
def tex_to_image(expression, def tex_to_image(expression,
size = "\HUGE", size = "\HUGE",

View file

@ -5,7 +5,5 @@ from complex_numbers import *
from functions import * from functions import *
from geometry import * from geometry import *
from graph_theory import * from graph_theory import *
from matrix_as_transform_2d import *
from number_line import * from number_line import *
from pythagorean_proof import *
from three_dimensions import * from three_dimensions import *

View file

@ -1,6 +1,7 @@
import numpy as np import numpy as np
import itertools as it import itertools as it
from helpers import *
from scene import Scene from scene import Scene
from animation import Animation from animation import Animation
@ -87,8 +88,6 @@ class FlipThroughSymbols(Animation):
"end_center" : ORIGIN, "end_center" : ORIGIN,
} }
def __init__(self, tex_list, **kwargs): def __init__(self, tex_list, **kwargs):
digest_config(self, FlipThroughSymbols, kwargs, locals())
self.curr_tex = self.tex_list[0]
mobject = tex_mobject(self.curr_tex).shift(start_center) mobject = tex_mobject(self.curr_tex).shift(start_center)
Animation.__init__(self, mobject, **kwargs) Animation.__init__(self, mobject, **kwargs)

View file

@ -172,7 +172,6 @@ class Bubble(Mobject):
"center_point" : ORIGIN, "center_point" : ORIGIN,
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, Bubble, kwargs)
Mobject.__init__(self, **kwargs) Mobject.__init__(self, **kwargs)
self.center_offset = self.center_point - Mobject.get_center(self) self.center_offset = self.center_point - Mobject.get_center(self)
if self.direction[0] > 0: if self.direction[0] > 0:
@ -224,9 +223,6 @@ class SpeechBubble(Bubble):
"initial_width" : 4, "initial_width" : 4,
"initial_height" : 2, "initial_height" : 2,
} }
def __init__(self, **kwargs):
digest_config(self, SpeechBubble, kwargs)
Bubble.__init__(self, **kwargs)
def generate_points(self): def generate_points(self):
complex_power = 0.9 complex_power = 0.9
@ -261,7 +257,6 @@ class ThoughtBubble(Bubble):
"initial_width" : 6 "initial_width" : 6
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, ThoughtBubble, kwargs)
Bubble.__init__(self, **kwargs) Bubble.__init__(self, **kwargs)
self.index_of_tip = np.argmin(self.points[:,1]) self.index_of_tip = np.argmin(self.points[:,1])

View file

@ -2,7 +2,7 @@ from helpers import *
from number_line import NumberPlane from number_line import NumberPlane
from animation.transform import ApplyPointwiseFunction from animation.transform import ApplyPointwiseFunction
from animation.animation import Homotopy from animation.simple_animations import Homotopy
from scene import Scene from scene import Scene
@ -18,7 +18,7 @@ class ComplexPlane(NumberPlane):
"number_at_center" : complex(0), "number_at_center" : complex(0),
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, ComplexPlane, kwargs) digest_config(self, kwargs)
kwargs.update({ kwargs.update({
"x_unit_to_spatial_width" : self.unit_to_spatial_width, "x_unit_to_spatial_width" : self.unit_to_spatial_width,
"y_uint_to_spatial_height" : self.unit_to_spatial_width, "y_uint_to_spatial_height" : self.unit_to_spatial_width,

View file

@ -13,7 +13,7 @@ class FunctionGraph(Mobject1D):
"spatial_radius" : SPACE_WIDTH, "spatial_radius" : SPACE_WIDTH,
} }
def __init__(self, function, **kwargs): def __init__(self, function, **kwargs):
digest_config(self, FunctionGraph, kwargs, locals()) self.function = function
Mobject1D.__init__(self, **kwargs) Mobject1D.__init__(self, **kwargs)
def generate_points(self): def generate_points(self):
@ -35,14 +35,14 @@ class ParametricFunction(Mobject):
"density" : None "density" : None
} }
def __init__(self, function, **kwargs): def __init__(self, function, **kwargs):
digest_config(self, ParametricFunction, kwargs, locals()) self.function = function
if self.density: if self.density:
self.epsilon = 1.0 / self.density self.epsilon = 1.0 / self.density
elif self.dim == 1: elif self.dim == 1:
self.epsilon = 1.0 / self.expected_measure / DEFAULT_POINT_DENSITY_1D self.epsilon = 1.0 / self.expected_measure / DEFAULT_POINT_DENSITY_1D
else: else:
self.epsilon = 1.0 / np.sqrt(self.expected_measure) / DEFAULT_POINT_DENSITY_2D self.epsilon = 1.0 / np.sqrt(self.expected_measure) / DEFAULT_POINT_DENSITY_2D
Mobject.__init__(self, *args, **kwargs) Mobject.__init__(self, **kwargs)
def generate_points(self): def generate_points(self):
if self.dim == 1: if self.dim == 1:
@ -63,3 +63,6 @@ class Axes(CompoundMobject):
x_axis = NumberLine(**kwargs) x_axis = NumberLine(**kwargs)
y_axis = NumberLine(**kwargs).rotate(np.pi/2, OUT) y_axis = NumberLine(**kwargs).rotate(np.pi/2, OUT)
CompoundMobject.__init__(self, x_axis, y_axis) CompoundMobject.__init__(self, x_axis, y_axis)

View file

@ -3,24 +3,12 @@ from helpers import *
from mobject import Mobject, Mobject1D from mobject import Mobject, Mobject1D
class Point(Mobject):
DEFAULT_CONFIG = {
"color" : BLACK,
}
def __init__(self, location = ORIGIN, **kwargs):
digest_config(self, Point, kwargs, locals())
Mobject.__init__(self, **kwargs)
def generate_points(self):
self.add_points([self.location])
class Dot(Mobject1D): #Use 1D density, even though 2D class Dot(Mobject1D): #Use 1D density, even though 2D
DEFAULT_CONFIG = { DEFAULT_CONFIG = {
"radius" : 0.05 "radius" : 0.05
} }
def __init__(self, center_point = ORIGIN, **kwargs): def __init__(self, center_point = ORIGIN, **kwargs):
digest_config(self, Dot, kwargs, locals()) digest_locals(self)
Mobject1D.__init__(self, **kwargs) Mobject1D.__init__(self, **kwargs)
def generate_points(self): def generate_points(self):
@ -37,7 +25,7 @@ class Cross(Mobject1D):
"radius" : 0.3 "radius" : 0.3
} }
def __init__(self, center_point = ORIGIN, **kwargs): def __init__(self, center_point = ORIGIN, **kwargs):
digest_config(self, Cross, kwargs, locals()) digest_locals(self)
Mobject1D.__init__(self, **kwargs) Mobject1D.__init__(self, **kwargs)
def generate_points(self): def generate_points(self):
@ -54,7 +42,6 @@ class Line(Mobject1D):
"min_density" : 0.1 "min_density" : 0.1
} }
def __init__(self, start, end, **kwargs): def __init__(self, start, end, **kwargs):
digest_config(self, Line, kwargs)
self.set_start_and_end(start, end) self.set_start_and_end(start, end)
Mobject1D.__init__(self, **kwargs) Mobject1D.__init__(self, **kwargs)
@ -93,7 +80,6 @@ class Arrow(Line):
"tip_length" : 0.25 "tip_length" : 0.25
} }
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
digest_config(self, Arrow, kwargs)
Line.__init__(self, *args, **kwargs) Line.__init__(self, *args, **kwargs)
self.add_tip() self.add_tip()
@ -150,7 +136,7 @@ class PartialCircle(Mobject1D):
"start_angle" : 0 "start_angle" : 0
} }
def __init__(self, angle, **kwargs): def __init__(self, angle, **kwargs):
digest_config(self, PartialCircle, kwargs, locals()) digest_locals(self)
Mobject1D.__init__(self, **kwargs) Mobject1D.__init__(self, **kwargs)
def generate_points(self): def generate_points(self):
@ -169,7 +155,6 @@ class Circle(PartialCircle):
"color" : RED, "color" : RED,
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, Circle, kwargs)
PartialCircle.__init__(self, angle = 2*np.pi, **kwargs) PartialCircle.__init__(self, angle = 2*np.pi, **kwargs)
class Polygon(Mobject1D): class Polygon(Mobject1D):
@ -179,8 +164,7 @@ class Polygon(Mobject1D):
} }
def __init__(self, *points, **kwargs): def __init__(self, *points, **kwargs):
assert len(points) > 1 assert len(points) > 1
digest_config(self, Polygon, kwargs) digest_locals(self)
self.original_points = points
Mobject1D.__init__(self, **kwargs) Mobject1D.__init__(self, **kwargs)
def generate_points(self): def generate_points(self):
@ -189,9 +173,7 @@ class Polygon(Mobject1D):
else: else:
colors = it.cycle([self.color]) colors = it.cycle([self.color])
self.indices_of_vertices = [] self.indices_of_vertices = []
points = list(self.original_points) for start, end in adjascent_pairs(self.points):
points.append(points[0])
for start, end in zip(points, points[1:]):
self.indices_of_vertices.append(self.get_num_points()) self.indices_of_vertices.append(self.get_num_points())
self.add_line(start, end, color = colors.next()) self.add_line(start, end, color = colors.next())
@ -206,10 +188,6 @@ class Rectangle(Mobject1D):
"height" : 2.0, "height" : 2.0,
"width" : 4.0 "width" : 4.0
} }
def __init__(self, **kwargs):
digest_config(self, Rectangle, kwargs)
Mobject1D.__init__(self, **kwargs)
def generate_points(self): def generate_points(self):
wh = [self.width/2.0, self.height/2.0] wh = [self.width/2.0, self.height/2.0]
self.add_points([ self.add_points([
@ -224,7 +202,13 @@ class Square(Rectangle):
"side_length" : 2.0, "side_length" : 2.0,
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, Square, kwargs) digest_config(self, kwargs)
for arg in ["height", "width"]: for arg in ["height", "width"]:
kwargs[arg] = self.side_length kwargs[arg] = self.side_length
Rectangle.__init__(self, **kwargs) Rectangle.__init__(self, **kwargs)

View file

@ -16,7 +16,7 @@ class NumberLine(Mobject1D):
"longer_tick_multiple" : 2, "longer_tick_multiple" : 2,
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, NumberLine, kwargs) digest_config(self, kwargs)
if self.leftmost_tick is None: if self.leftmost_tick is None:
self.leftmost_tick = -int(self.numerical_radius) self.leftmost_tick = -int(self.numerical_radius)
self.left_num = self.number_at_center - self.numerical_radius self.left_num = self.number_at_center - self.numerical_radius
@ -107,9 +107,6 @@ class UnitInterval(NumberLine):
"number_at_center" : 0.5, "number_at_center" : 0.5,
"numbers_with_elongated_ticks" : [0, 1], "numbers_with_elongated_ticks" : [0, 1],
} }
def __init__(self, **kwargs):
digest_config(self, UnitInterval, kwargs)
NumberLine.__init__(self, **kwargs)
class NumberPlane(Mobject1D): class NumberPlane(Mobject1D):
@ -127,9 +124,6 @@ class NumberPlane(Mobject1D):
"number_scale_factor" : 0.25, "number_scale_factor" : 0.25,
"num_pair_at_center" : np.array((0, 0)), "num_pair_at_center" : np.array((0, 0)),
} }
def __init__(self, **kwargs):
digest_config(self, NumberPlane, kwargs)
Mobject1D.__init__(self, **kwargs)
def generate_points(self): def generate_points(self):
#TODO, clean this #TODO, clean this