From 80f5c39b24b0b05c679faf3139edd7a09f5fda25 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Sun, 26 Apr 2015 14:41:03 -0700 Subject: [PATCH] Whoops, forgot to commit these deletions... --- animate.py | 346 ----------- epii/__init__.py | 0 epii/cccd_animations.py | 787 ----------------------- epii/dexp_generate_images.py | 16 - epii/epii_animations.py | 1141 ---------------------------------- epii/poem_animations.py | 298 --------- mobject.py | 515 --------------- tex_image_utils.py | 70 --- 8 files changed, 3173 deletions(-) delete mode 100644 animate.py delete mode 100644 epii/__init__.py delete mode 100644 epii/cccd_animations.py delete mode 100644 epii/dexp_generate_images.py delete mode 100644 epii/epii_animations.py delete mode 100644 epii/poem_animations.py delete mode 100644 mobject.py delete mode 100644 tex_image_utils.py diff --git a/animate.py b/animate.py deleted file mode 100644 index 39bae881..00000000 --- a/animate.py +++ /dev/null @@ -1,346 +0,0 @@ -from PIL import Image -from colour import Color -import numpy as np -import warnings -import time -import os -import copy -import progressbar -import inspect -from images2gif import writeGif - - -from helpers import * -from mobject import * -import displayer as disp - -class MobjectMovement(object): - def __init__(self, - mobject, - run_time = DEFAULT_ANIMATION_RUN_TIME, - alpha_func = high_inflection_0_to_1, - name = None): - if isinstance(mobject, type) and issubclass(mobject, Mobject): - self.mobject = mobject() - elif isinstance(mobject, Mobject): - self.mobject = mobject - else: - raise Exception("Invalid mobject parameter, must be \ - subclass or instance of Mobject") - self.starting_mobject = copy.deepcopy(self.mobject) - self.reference_mobjects = [self.starting_mobject] - self.alpha_func = alpha_func or (lambda x : x) - self.run_time = run_time - #TODO, Adress the idea of filtering the mobmov - self.filter_functions = [] - self.restricted_height = SPACE_HEIGHT - self.restricted_width = SPACE_WIDTH - self.spacial_center = np.zeros(3) - self.name = name or self.__class__.__name__ + str(self.mobject) - - def __str__(self): - return self.name - - def get_points_and_rgbs(self): - """ - It is the responsibility of this class to only emit points within - the space. Returns np array of points and corresponding np array - of rgbs - """ - #TODO, I don't think this should be necessary. This should happen - #under the individual mobjects. - points = self.mobject.points - rgbs = self.mobject.rgbs - #Filters out what is out of bounds. - admissibles = (abs(points[:,0]) < self.restricted_width) * \ - (abs(points[:,1]) < self.restricted_height) - for filter_function in self.filter_functions: - admissibles *= ~filter_function(points) - if any(self.spacial_center): - points += self.spacial_center - #Filter out points pushed off the edge - admissibles *= (abs(points[:,0]) < SPACE_WIDTH) * \ - (abs(points[:,1]) < SPACE_HEIGHT) - if rgbs.shape[0] < points.shape[0]: - #TODO, this shouldn't be necessary, find what's happening. - points = points[:rgbs.shape[0], :] - admissibles = admissibles[:rgbs.shape[0]] - return points[admissibles, :], rgbs[admissibles, :] - - def update(self, alpha): - if alpha < 0: - alpha = 0 - if alpha > 1: - alpha = 1 - self.update_mobject(self.alpha_func(alpha)) - - def filter_out(self, *filter_functions): - self.filter_functions += filter_functions - return self - - def restrict_height(self, height): - self.restricted_height = min(height, SPACE_HEIGHT) - return self - - def restrict_width(self, width): - self.restricted_width = min(width, SPACE_WIDTH) - return self - - def shift(self, vector): - self.spacial_center += vector - return self - - def set_run_time(self, time): - self.run_time = time - return self.reload() - - def set_alpha_func(self, alpha_func): - if alpha_func is None: - alpha_func = lambda x : x - self.alpha_func = alpha_func - return self - - def set_name(self, name): - self.name = name - return self - - # def drag_pixels(self): - # self.frames = drag_pixels(self.get_frames()) - # return self - - # def reverse(self): - # self.get_frames().reverse() - # self.name = 'Reversed' + str(self) - # return self - - def update_mobject(self, alpha): - #Typically ipmlemented by subclass - pass - - def clean_up(self): - pass - - -###### Concrete MobjectMovement ######## - -class Rotating(MobjectMovement): - def __init__(self, - mobject, - axis = None, - axes = [[0, 0, 1], [0, 1, 0]], - radians = 2 * np.pi, - run_time = 20.0, - alpha_func = None, - *args, **kwargs): - MobjectMovement.__init__( - self, mobject, - run_time = run_time, - alpha_func = alpha_func, - *args, **kwargs - ) - self.axes = [axis] if axis else axes - self.radians = radians - - def update_mobject(self, alpha): - self.mobject.points = self.starting_mobject.points - for axis in self.axes: - self.mobject.rotate( - self.radians * alpha, - axis - ) - -class RotationAsTransform(Rotating): - def __init__(self, mobject, radians, axis = (0, 0, 1), axes = None, - run_time = DEFAULT_ANIMATION_RUN_TIME, - alpha_func = high_inflection_0_to_1, - *args, **kwargs): - Rotating.__init__( - self, - mobject, - axis = axis, - axes = axes, - run_time = run_time, - radians = radians, - alpha_func = alpha_func, - ) - -class FadeOut(MobjectMovement): - def update_mobject(self, alpha): - self.mobject.rgbs = self.starting_mobject.rgbs * (1 - alpha) - -class Reveal(MobjectMovement): - def update_mobject(self, alpha): - self.mobject.rgbs = self.starting_mobject.rgbs * alpha - if self.mobject.points.shape != self.starting_mobject.points.shape: - self.mobject.points = self.starting_mobject.points - #TODO, Why do you need to do this? Shouldn't points always align? - -class Transform(MobjectMovement): - def __init__(self, mobject1, mobject2, - run_time = DEFAULT_TRANSFORM_RUN_TIME, - *args, **kwargs): - count1, count2 = mobject1.get_num_points(), mobject2.get_num_points() - Mobject.align_data(mobject1, mobject2) - MobjectMovement.__init__(self, mobject1, run_time = run_time, *args, **kwargs) - self.ending_mobject = mobject2 - self.mobject.SHOULD_BUFF_POINTS = \ - mobject1.SHOULD_BUFF_POINTS and mobject2.SHOULD_BUFF_POINTS - self.reference_mobjects.append(mobject2) - self.name += "To" + str(mobject2) - - if count2 < count1: - #Ensure redundant pixels fade to black - indices = self.non_redundant_m2_indices = \ - np.arange(0, count1-1, float(count1) / count2).astype('int') - temp = np.zeros(mobject2.points.shape) - temp[indices] = mobject2.rgbs[indices] - mobject2.rgbs = temp - - def update_mobject(self, alpha): - Mobject.interpolate( - self.starting_mobject, - self.ending_mobject, - self.mobject, - alpha - ) - - def clean_up(self): - if hasattr(self, "non_redundant_m2_indices"): - #Reduce mobject (which has become identical to mobject2), as - #well as mobject2 itself - for mobject in [self.mobject, self.ending_mobject]: - for attr in ['points', 'rgbs']: - setattr( - mobject, attr, - getattr( - self.ending_mobject, - attr - )[self.non_redundant_m2_indices] - ) - -class ApplyMethod(Transform): - def __init__(self, method, mobject, *args, **kwargs): - """ - Method is a method of Mobject - """ - method_args = () - if isinstance(method, tuple): - method, method_args = method[0], method[1:] - if not inspect.ismethod(method): - raise "Not a valid Mobject method" - Transform.__init__( - self, - mobject, - method(copy.deepcopy(mobject), *method_args), - *args, **kwargs - ) - -class ApplyFunction(Transform): - def __init__(self, function, mobject, run_time = DEFAULT_ANIMATION_RUN_TIME, - *args, **kwargs): - map_image = copy.deepcopy(mobject) - map_image.points = np.array(map(function, map_image.points)) - Transform.__init__(self, mobject, map_image, run_time = run_time, - *args, **kwargs) - self.name = "".join([ - "Apply", - "".join([s.capitalize() for s in function.__name__.split("_")]), - "To" + str(mobject) - ]) - -class ComplexFunction(ApplyFunction): - def __init__(self, function, *args, **kwargs): - def point_map(point): - x, y, z = point - c = np.complex(x, y) - c = function(c) - return c.real, c.imag, z - if len(args) > 0: - args = list(args) - mobject = args.pop(0) - elif "mobject" in kwargs: - mobject = kwargs.pop("mobject") - else: - mobject = Grid() - ApplyFunction.__init__(self, point_map, mobject, *args, **kwargs) - self.name = "ComplexFunction" + to_cammel_case(function.__name__) - #Todo, abstract away function naming' - -class Homotopy(MobjectMovement): - def __init__(self, homotopy, *args, **kwargs): - """ - Homotopy a function from (x, y, z, t) to (x', y', z') - """ - self.homotopy = homotopy - MobjectMovement.__init__(self, *args, **kwargs) - - def update_mobject(self, alpha): - self.mobject.points = np.array([ - self.homotopy((x, y, z, alpha)) - for x, y, z in self.starting_mobject.points - ]) - -class ComplexHomotopy(Homotopy): - def __init__(self, complex_homotopy, *args, **kwargs): - """ - Complex Hootopy a function (z, t) to z' - """ - def homotopy((x, y, z, t)): - c = complex_homotopy((complex(x, y), t)) - return (c.real, c.imag, z) - if len(args) > 0: - args = list(args) - mobject = args.pop(0) - elif "mobject" in kwargs: - mobject = kwargs["mobject"] - else: - mobject = Grid() - Homotopy.__init__(self, homotopy, mobject, *args, **kwargs) - self.name = "ComplexHomotopy" + \ - to_cammel_case(complex_homotopy.__name__) - - -class ShowCreation(MobjectMovement): - def update_mobject(self, alpha): - #TODO, shoudl I make this more efficient? - new_num_points = int(alpha * self.starting_mobject.points.shape[0]) - for attr in ["points", "rgbs"]: - setattr( - self.mobject, - attr, - getattr(self.starting_mobject, attr)[:new_num_points, :] - ) - -class Flash(MobjectMovement): - def __init__(self, mobject, color = "white", slow_factor = 0.01, - run_time = 0.1, alpha_func = None, - *args, **kwargs): - MobjectMovement.__init__(self, mobject, run_time = run_time, - alpha_func = alpha_func, - *args, **kwargs) - self.intermediate = Mobject(color = color) - self.intermediate.add_points([ - point + (x, y, 0) - for point in self.mobject.points - for x in [-1, 1] - for y in [-1, 1] - ]) - self.reference_mobjects.append(self.intermediate) - self.slow_factor = slow_factor - - def update_mobject(self, alpha): - #Makes alpha go from 0 to slow_factor to 0 instead of 0 to 1 - alpha = self.slow_factor * (1.0 - 4 * (alpha - 0.5)**2) - Mobject.interpolate( - self.starting_mobject, - self.intermediate, - self.mobject, - alpha - ) - - - - - - - diff --git a/epii/__init__.py b/epii/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/epii/cccd_animations.py b/epii/cccd_animations.py deleted file mode 100644 index 4c8e0f6f..00000000 --- a/epii/cccd_animations.py +++ /dev/null @@ -1,787 +0,0 @@ -from PIL import Image -from animate import * -from mobject import * -from constants import * -from helpers import * -from tex_image_utils import load_pdf_images -from displayer import * -import itertools as it -import os -import numpy as np -from copy import deepcopy - -from epii_animations import MULTIPLIER_COLOR, ADDER_COLOR, ONE_COLOR - -CCCD_MOVIE_DIR = "cccd" - -symbol_images = load_pdf_images("cccd_symbols.pdf", regen_if_exists = False) -phrase_images = load_pdf_images("cccd_phrases.pdf", regen_if_exists = False) - -name_to_image = dict( - zip([ - "two", - "minus_1", - "i", - "x_squared", - "four", - "one", - "multiplication_function", - "deriv_def_base", - "deriv_def_inner_e_to_x", - "deriv_def_plus_h", - "deriv_def_e_to_h", - "deriv_def_one", - "deriv_def_outer_e_to_x", - "series_terms", - "series_exponents", - "series_exponents_minus_1", - "d_series_coefficients", - "one_plus", - "d_series_simple", - "deriv_x_squared", - "deriv_e_to_x", - "question_mark", - ], symbol_images) + zip([ - "complex_derivative_title", - "limit_explanation", - "velocity_vector_explanation", - "both_same_point", - "maybe_like_this", - "or_this", - "why_vectors", - "pause_and_ponder", - "think_in_pictures", - "remember_this", - ], phrase_images) -) - -def function_of_numbers(): - kwargs = {"dither_time" : 0} - two, minus_1, i, x_squared, four, one = [ - ImageMobject(name_to_image[name]) - for name in ["two", "minus_1", "i", "x_squared", - "four", "one"] - ] - minus_1_copy = copy.deepcopy(minus_1) - for mob1, mob2, height in [ - (two, four, 2), - (minus_1, one, 0), - (i, minus_1_copy, -2) - ]: - mob1.center().shift((-2, height, 0)) - mob2.center().shift((2, height, 0)) - x_squared.center() - point = Point() - inputs = CompoundMobject(two, minus_1, i) - outputs = CompoundMobject(four, one, minus_1_copy) - return Transform( - inputs, point, **kwargs - ).then( - Transform(point, outputs, **kwargs) - ).with_background(x_squared) - - -def real_function_graph(): - graph = NumberLine() - graph.add(NumberLine().rotate(np.pi / 2)) - int_size = graph.interval_size - min_x = SPACE_WIDTH / int_size - graph.add(FunctionGraph( - lambda x : x**2, - x_range = [-min_x, min_x] - )) - point = graph.points[-20,:] - line = Line((2, 0, 0), (2, 1.1, 0)) #Terrible... - line.highlight("yellow") - return ShowCreation(graph).then(ShowCreation(line).with_background(graph)) - -def two_grids(): - grid1, grid2 = Grid(), Grid() - return ShowCreation(grid1).then( - Rotating(grid1, run_time = 7.0, radians = np.pi / 3).while_also( - ShowCreation(grid2, dither_time = 2.0).while_also( - Rotating, axis = [1, 1, 0] - ) - ) - ) - -def z_squared(): - return ComplexHomotopy(square_homotopy) - -def z_squared_marked(): - #Hard coded 2, i, -1 - return ComplexHomotopy( - lambda (z, t) : z**(1 + t) - ).while_also( - ComplexHomotopy( - lambda (z, t) : z + complex(2, 0)**(1 + t), - Cross( - color = random_color() - ) - ) - ).while_also( - ComplexHomotopy( - lambda (z, t) : z + complex(-1, 0)**(1 + t), - Cross( - color = random_color() - ) - ) - ).while_also( - ComplexHomotopy( - lambda (z, t) : z + complex(0, 1)**(1 + t), - Cross( - color = random_color() - ) - ) - ) - -def multiplier_in_the_wild(point): - func = ComplexFunction(lambda z : z*point) - one = Cross().highlight(ONE_COLOR).shift((1, 0, 0)) - point = Cross().highlight( - MULTIPLIER_COLOR - ).shift((point.real, point.imag, 0)) - func_copy = copy.deepcopy(func) - return func.then( - func_copy.while_also( - Transform(one, point, run_time = DEFAULT_ANIMATION_RUN_TIME) - ) - ).then( - Animation( - Grid(), run_time = 2.0, dither_time = 0 - ).with_background(point) - ) - -def random_looking_function(): - wongky_map = Transform( - Grid(), CubeShell().scale(SPACE_HEIGHT), - alpha_func = lambda t : 0.5 * high_inflection_0_to_1(t), - run_time = 3.0 - ) - return wongky_map.then(copy.deepcopy(wongky_map).reverse()) - -def zoom_in_on_map(function, is_homotopy, point, zoom_level): - center_line = ParametricFunction(lambda t : (0, t * SPACE_HEIGHT, 0)) - half_width = SPACE_WIDTH / 2 - left_center = (-half_width + center_line.epsilon, 0, 0) - right_center = (half_width - center_line.epsilon, 0, 0) - left_divider = copy.deepcopy(center_line).shift(right_center) - right_divider = copy.deepcopy(center_line).shift(left_center) - - point = complex(point) - outer_circle = Circle().scale(SPACE_HEIGHT + SPACE_WIDTH + half_width) - inner_circle = Circle().scale(zoom_level).shift( - (point.real, point.imag, 0) - ) - outer_to_inner = Transform(outer_circle, inner_circle).with_background(Grid()) - big_radius = min(half_width, SPACE_HEIGHT) - big_circle = Circle().scale(big_radius) - bts_ratio = big_radius / zoom_level - half_grid = Grid().filter_out(lambda (x, y, z) : abs(x) > half_width or y > SPACE_HEIGHT) - one = Cross().shift((1, 0, 0)).highlight(ONE_COLOR) - if is_homotopy: - global_function = ComplexHomotopy(function, copy.deepcopy(half_grid)) - def local_homotopoy((z, t)): - return bts_ratio * (function((z/bts_ratio + point, t)) - function((point,t))) - local_function = ComplexHomotopy(local_homotopoy, copy.deepcopy(half_grid)) - one_following = ComplexHomotopy( - lambda (z, t) : z + local_homotopoy((1, t)) - 1, - one - ) - circle_following = ComplexHomotopy( - lambda (z, t) : z + function((point, t)) - point, - inner_circle - ) - else: - global_function = ComplexFunction(function, copy.deepcopy(half_grid)) - def local_lambda(z): - return bts_ratio*(function(z/bts_ratio + point) - function(point)) - local_function = ComplexFunction(local_lambda, copy.deepcopy(half_grid)) - one_following = ComplexFunction(lambda z : z + local_lambda(1) - 1, one) - circle_following = ComplexFunction( - lambda z : z + function(point) - point, - inner_circle - ) - zoom_region = Circle().scale(zoom_level) - zoom_region.add(Grid().filter_out(lambda p : np.linalg.norm(p) > zoom_level)) - zoom_region.shift(left_center).shift((point.real, point.imag, 0)) - zoom_in = ComplexFunction( - lambda z : bts_ratio * (z - point - complex(left_center[0], left_center[1])) + \ - complex(right_center[0], right_center[1]), - zoom_region - ).set_run_time(DEFAULT_TRANSFORM_RUN_TIME) - - grow_local_grid = ShowCreation( - Grid().filter_out(lambda p : np.linalg.norm(p) > big_radius), - run_time = 1.0 - ).with_background(big_circle) - def out_of_circle(points): - return np.apply_along_axis(np.linalg.norm, 1, points) > big_radius - local_function.filter_out(out_of_circle) - for anim in global_function, outer_to_inner, circle_following: - anim.shift(left_center).restrict_width(half_width).with_background(left_divider) - for anim in local_function, grow_local_grid, one_following: - anim.shift(right_center).with_background(right_divider, big_circle) - for anim in outer_to_inner, zoom_in, grow_local_grid: - anim.set_dither(0) - #Kind of hacky...one day there will be a better way of doing this. - show_left_grid = Animation(Mobject().add_points(*global_function.get_points_and_rgbs())) - show_left_grid.with_background(copy.deepcopy(inner_circle).shift(left_center)) - return outer_to_inner.then( - zoom_in.while_also(show_left_grid), - ).then( - grow_local_grid.while_also(show_left_grid).while_also(zoom_in) - ).then( - global_function.while_also( - local_function - ).while_also( - circle_following - ).while_also( - one_following - ) - ) - -def z_squared_derivative_example(point, zoom_level): - point = complex(point) - point_coords = np.array((point.real, point.imag, 0)) - circle = Circle().scale(zoom_level).shift(point_coords) - z = Cross(color = Circle.DEFAULT_COLOR).shift(point_coords) - two_z = Cross(color = MULTIPLIER_COLOR).shift(2*point_coords) - zero = Cross() - one = Cross(color = ONE_COLOR).shift((1, 0, 0)) - plane = Grid() - return Transform(circle, z).with_background(plane, zero).then( - Transform(z, two_z).with_background( - plane, zero - ).while_also( - Reveal(one).with_background( - two_z, plane, zero - ) - ).set_dither(0) - ).then( - ComplexFunction(lambda c : c * 2 * point, plane).with_background( - two_z, zero - ).while_also( - ComplexFunction(lambda c : c - 1 + 2 * point, one) - ) - ) - -def z_squared_derivative_2z(zoom_level): - circles = Mobject() - crosses = Mobject() - mini_maps = [] - mini_grids = Mobject() - example_range = range(-3, 4, 2) - for x in example_range: - for y in example_range: - circle = Circle().scale(zoom_level).shift((x, y, 0)) - cross = Cross().shift((2*x, 2*y, 0)) - mini_grid = Grid( - radius = zoom_level, - subinterval_size = 0.25 - ).filter_out( - lambda point : np.linalg.norm(point) > zoom_level - ) - mini_maps.append( - ComplexFunction( - lambda z : (z + complex(x, y))**2 - complex(x, y)**2, - mini_grid - ).filter_out( - lambda points : np.apply_along_axis(np.linalg.norm, 1, points) \ - > zoom_level - ).with_background( - Circle().scale(zoom_level) - ).shift((x, y, 0)).set_dither(0) - )#generate frames so that lambda doesn't change - mini_grids.add(copy.deepcopy(mini_grid).shift((x, y, 0))) - Mobject.align_data(circle, cross) - circles.add(circle) - crosses.add(cross) - all_mini_maps = reduce(Animation.while_also, mini_maps) - crosses.highlight(MULTIPLIER_COLOR) - return FadeOut(Grid()).while_also( - Animation(CompoundMobject(circles, mini_grids)) - ).then( - all_mini_maps.with_background(circles) - ).then( - ComplexFunction(lambda z : 2*z).while_also( - Transform( - circles, crosses, - run_time = DEFAULT_ANIMATION_RUN_TIME - ) - ) - ) - - -def visualize_exp(): - kwargs1 = {"run_time" : 2.0, "dither_time" : 1.0} - kwargs2 = {"run_time" : 2.0, "dither_time" : 0.0} - cylinder = Grid().apply_function( - lambda (x, y, z) : (x, np.sin(y), np.cos(y)) - ).rotate(np.pi/9, [0, 1, 0]) - exp_plane = Grid().apply_complex_function(np.exp) - rotating_cyl = Rotating(cylinder, radians = np.pi/5, run_time = 5.0) - return Transform(Grid(), cylinder, **kwargs1).then( - Transform(cylinder, exp_plane, **kwargs2) - ) - -def derivative_definition(): - base, inner_e_to_x, plus_h, e_to_h, one, outer_e_to_x = [ - ImageMobject(name_to_image["deriv_def_" + name]) - for name in [ - "base", - "inner_e_to_x", - "plus_h", - "e_to_h", - "one", - "outer_e_to_x", - ] - ] - shift = (-0.2, -0.2, 0) - base.shift(shift) - outer_e_to_x.shift(shift) - limit_explanation = ImageMobject(name_to_image["limit_explanation"]) - limit_explanation.shift((1, -2, 0)) - return Transform(plus_h, e_to_h).with_background( - base, inner_e_to_x - ).then( - Transform(inner_e_to_x, outer_e_to_x).while_also( - Reveal(one, dither_time = 1.0, run_time = 1.0) - ).with_background(base, e_to_h) - ).then( - Reveal(limit_explanation).with_background( - base, outer_e_to_x, one, e_to_h - ) - ) - - -def take_derivative_of_series(): - series_terms, series_exponents, series_exponents_minus_1, \ - d_series_coefficients, one_plus, d_series_simple = [ - ImageMobject(name_to_image[name]) - for name in [ - "series_terms", - "series_exponents", - "series_exponents_minus_1", - "d_series_coefficients", - "one_plus", - "d_series_simple", - ] - ] - coefficients = copy.deepcopy(series_exponents) - fraction_bars = copy.deepcopy(series_exponents) - coefficients.filter_out(lambda (x, y, z) : y < 0.5) - series_exponents_minus_1.filter_out(lambda (x, y, z) : y < 0.5) - fraction_bars.filter_out(lambda (x, y, z) : y > 0.5) - exponenets_to_coefficients = Homotopy( - lambda (x, y, z, t) : (x - 0.5*t, y - 0.5*t + np.sin(np.pi * t), z), - coefficients - ).with_background(fraction_bars) - d_series_non_simple = CompoundMobject( - series_terms, - copy.deepcopy(coefficients).shift((-0.5, -0.5, 0)), - series_exponents_minus_1, - series_exponents - ) - d_series_simple.center().shift((1, 0, 0)) - - #Yeah, this is totally good programming... - fdxc = [-2, -0.4, 1.3] #first dividing x coordinates - sdxc = [-1.7, -0.8, .3] #second dividing x coordinates - broken_series_terms = [ - copy.deepcopy(d_series_non_simple).filter_out( - lambda (x, y, z) : x > fdxc[0]), - copy.deepcopy(d_series_non_simple).filter_out( - lambda (x, y, z) : x > fdxc[1] or x < fdxc[0]), - copy.deepcopy(d_series_non_simple).filter_out( - lambda (x, y, z) : x > fdxc[2] or x < fdxc[1]), - copy.deepcopy(d_series_non_simple).filter_out( - lambda (x, y, z) : x < fdxc[2]), - ] - broken_dseries_terms = [ - copy.deepcopy(d_series_simple).filter_out( - lambda (x, y, z) : x > sdxc[0]), - copy.deepcopy(d_series_simple).filter_out( - lambda (x, y, z) : x > sdxc[1] or x < sdxc[0]), - copy.deepcopy(d_series_simple).filter_out( - lambda (x, y, z) : x > sdxc[2] or x < sdxc[1]), - copy.deepcopy(d_series_simple).filter_out( - lambda (x, y, z) : x < sdxc[2]), - ] - simplify = None - for term1, term2 in zip(broken_series_terms, broken_dseries_terms): - anim = Transform(term1, term2) - if simplify: - simplify.while_also(anim) - else: - simplify = anim - series_terms.add(series_exponents) - return exponenets_to_coefficients.while_also( - Reveal(series_exponents_minus_1).with_background( - series_terms, series_exponents - ) - ).while_also( - Transform(one_plus, Point(one_plus.get_center())) - ).set_dither(1.0, True).set_run_time(1.0, True).then( - simplify - ) - -def e_to_x_takes_adder_to_multiplier(point): - point = complex(point) - point_coords = (point.real, point.imag, 0) - image = np.exp(point) - image_coords = (image.real, image.imag, 0) - adder_cross = Cross().shift(point_coords).highlight(ADDER_COLOR) - multi_cross = Cross().shift(image_coords).highlight(MULTIPLIER_COLOR) - zero = Cross() - one = Cross().shift((1, 0, 0)).highlight(ONE_COLOR) - - adder = ComplexFunction( - lambda z : z + point, - CompoundMobject(Grid(radius = SPACE_WIDTH + SPACE_HEIGHT), zero) - ).with_background(adder_cross) - e_to_x = ComplexFunction(np.exp).while_also( - Transform(adder_cross, multi_cross, run_time = DEFAULT_ANIMATION_RUN_TIME) - ) - multiplier = ComplexFunction(lambda z : image * z).while_also( - Transform(one, multi_cross, run_time = DEFAULT_ANIMATION_RUN_TIME) - ).with_background(zero, multi_cross) - return adder.then(e_to_x).then(multiplier) - -def e_to_x_derivative_zoom(point, zoom_level): - point = complex(point) - image_point = np.exp(point) - both_same_point = ImageMobject( - name_to_image["both_same_point"] - ).shift((image_point.real, SPACE_HEIGHT - 1, 0)) - left_point = (image_point.real - SPACE_WIDTH/2, image_point.imag, 0) - right_point = (image_point.real + SPACE_WIDTH/2, image_point.imag, 0) - left_arrow = Arrow(left_point, (-1, -1, 0)).highlight("white") - right_arrow = Arrow(right_point, (1, -1, 0)).highlight("white") - - e_deriv_anim = zoom_in_on_map(np.exp, False, point, zoom_level) - #SUPER HACKY, YOU MUST MAKE A BETTER WAY TO DO THIS IN FUTURE - last_anim = e_deriv_anim.generate_frames().following_animations[-1] - background = Mobject() - for anim in [last_anim] + last_anim.concurrent_animations: - background.add_points(*anim.get_points_and_rgbs()) - # background.display() - return e_deriv_anim.then( - Reveal(CompoundMobject( - left_arrow, right_arrow, both_same_point - )).with_background(background) - ) - -def other_possible_functions(): - phrases = [ - ImageMobject(name_to_image[name]).center().shift((0, -2, 0)) - for name in ["maybe_like_this", "or_this"] - ] - return ComplexFunction(np.sin).with_background( - phrases[0] - ).then( - ComplexFunction(np.sinc).with_background( - phrases[1] - ) - ) - -def setup_velocity_vector_discussion(zoom_level): - def homotopy((x, y, z, t)): - t = 3*t - 1.5 - return ( - x + t, - y + t**3 - t, - z - ) - big_radius = SPACE_HEIGHT - def out_of_circle(points): - return np.apply_along_axis(np.linalg.norm, 1, points) > big_radius - landing_point = homotopy((0, 0, 0, 1)) - cross = Cross().highlight(Circle.DEFAULT_COLOR) - small_circle = Circle().scale(2*zoom_level) - big_circle = Circle().scale(big_radius) - new_cross = copy.deepcopy(cross) - for mob in new_cross, small_circle: - mob.shift(landing_point) - wandering = Homotopy(homotopy, cross) - one = Cross().highlight(ONE_COLOR).shift((1, 0, 0)) - multiply = ComplexFunction( - lambda z : z * complex(landing_point[0], landing_point[1]) - ).filter_out(out_of_circle) - return wandering.then( - Transform(small_circle, big_circle).with_background( - new_cross - ) - ).then( - multiply.with_background(big_circle).while_also( - Transform(one, new_cross, run_time = DEFAULT_ANIMATION_RUN_TIME) - ).with_background( - new_cross - ) - ) - - -def traced_path(): - path = ParametricFunction( - lambda t : ( - np.sin(2 * np.pi * t), - (t-1)**2 + 1, - 0 - ) - ) - new_path = copy.deepcopy(path).apply_complex_function(np.exp) - return ShowCreation(path).then( - Transform(path, new_path) - ) - - -def walking_north(start_point, vector_len): - vv_explanation = ImageMobject(name_to_image["velocity_vector_explanation"]) - vv_explanation.scale(0.75).shift((0, -3, 0)) - - walk_kwargs = {"alpha_func" : None, "run_time" : 5.0} - start_point = complex(start_point) - end_point = start_point + complex(0, 4) - start_coords = (start_point.real, start_point.imag, 0) - end_coords = (end_point.real, end_point.imag, 0) - vector = Vector((0, vector_len, 0)).shift(start_coords) - vector.add(vv_explanation) - start_cross = Cross().shift(start_coords) - end_cross = Cross().shift(end_coords) - path = Line(start_coords, end_coords).highlight(start_cross.DEFAULT_COLOR) - return Transform( - start_cross, end_cross, **walk_kwargs - ).with_background(Grid()).while_also( - ShowCreation(path, **walk_kwargs) - ).then( - Animation(vector), True - ) - -def map_north_vector(start_point, vector_len, zoom_level): - question_mark = ImageMobject(name_to_image["question_mark"]).center() - kwargs = { - "run_time" : DEFAULT_ANIMATION_RUN_TIME, - "dither_time" : DEFAULT_DITHER_TIME - } - start_point = complex(start_point) - image_point = np.exp(start_point) - start_coords = np.array((start_point.real, start_point.imag, 0)) - image_coords = np.array((image_point.real, image_point.imag, 0)) - - vector = Vector((0, vector_len, 0)).add(Circle().scale(zoom_level)) - vimage = copy.deepcopy(vector) - image_len = np.linalg.norm(image_coords) - image_arg = np.log(image_point).imag - stretched = copy.deepcopy(vimage).scale(image_len) - - vector.shift(start_coords) - for vect in vimage, stretched: - vect.shift(image_coords) - question_mark.shift(image_coords + (0.3, 0, 0)) - - line_to_image = Line((0, 0, 0), image_coords) - line_along_horiz = Line((0, 0, 0), (image_len, 0, 0)).highlight(Grid.DEFAULT_COLOR) - - return Transform(vector, vimage).then( - Reveal(question_mark, dither_time = 0).with_background(vimage) - ).then( - Transform(vimage, stretched, **kwargs).while_also( - ShowCreation(line_to_image, **kwargs) - ) - ).with_background(Grid()).then( - RotationAsTransform( - copy.deepcopy(stretched).shift(-image_coords), - radians = image_arg, **kwargs - ).shift(image_coords).while_also( - RotationAsTransform( - line_along_horiz, radians = image_arg, **kwargs - ).with_background(Grid(), line_to_image) - ) - ) - -def all_possible_vectors(vector_len): - tvkwargs = {"run_time" : 2.0, "dither_time" : 0} - turn_vectors = Animation(Grid(), **tvkwargs) - prototype = Vector((0, vector_len, 0)) - start_vectors = Mobject() - final_vectors = Mobject() - radii = [] - example_range = range(-3, 4) - for x, y in it.product(*[example_range]*2): - length = np.linalg.norm((x, y)) - arg = np.log(complex(x, y)).imag - new = copy.deepcopy(prototype) - turn_vectors.while_also( - ComplexFunction( - lambda z : z * complex(x, y), - new, **tvkwargs - ).shift((x, y, 0)) - ) - if length > 0: - radii.append(length) - start_vectors.add(copy.deepcopy(new).shift((x, y, 0))) - final_vectors.add(copy.deepcopy(new).scale(length).rotate(arg).shift((x, y, 0))) - to_vectors = Transform(prototype, start_vectors, **tvkwargs).with_background(Grid()) - turn_vectors.set_name("TurnVectors") - radii = sorted(set(radii)) - show_all_circles = Reveal(CompoundMobject(*[ - Circle().scale(radius) for radius in radii - ]), dither_time = 2.0) - show_all_circles.with_background(Grid(), final_vectors) - show_all_circles.set_name("ShowAllCircles") - return to_vectors.then(turn_vectors).then(show_all_circles) - -class VelocityVectorsOfPath(Animation): - def __init__(self, path, vector_len = 1, alpha_func = None, *args, **kwargs): - self.path = path.points - diffs = path.points[1:,:] - path.points[:-1, :] - self.unit_distance = np.mean(np.apply_along_axis(np.linalg.norm, 1, diffs)) - Animation.__init__( - self, Vector(point = (vector_len, 0, 0)), alpha_func = alpha_func - ) - self.with_background(path) - - def update_mobject(self, alpha): - index = int(alpha * self.path.shape[0]) - if index >= self.path.shape[0] - 1: - return - point1, point2 = self.path[index, :], self.path[index + 1, :] - diff = (point2 - point1) - distance = np.linalg.norm(diff) - arg = np.log(complex(diff[0], diff[1])).imag - self.mobject.points = self.starting_mobject.points * (distance / self.unit_distance) - self.mobject.rotate(arg).shift(point1) - - -def map_trajectories(vector_len, path_func): - half_width = SPACE_WIDTH / 2 - left_center = np.array((-half_width, 0, 0)) - right_center = np.array((half_width, 0, 0)) - dividing_line = Line((half_width, SPACE_HEIGHT, 0), (half_width, -SPACE_HEIGHT, 0)) - left_grid = Grid(radius = SPACE_HEIGHT) - left_path = ParametricFunction(path_func).highlight("white") - right_path = copy.deepcopy(left_path).apply_complex_function(np.exp) - right_grid = copy.deepcopy(left_grid).apply_complex_function(np.exp) - for grid in left_grid, right_grid: - grid.filter_out( - lambda (x, y, z) : abs(x) > half_width - ) - left_start = Cross().shift(left_path.points[0, :]) - right_start = Cross().shift(right_path.points[0, :]) - - apply_function = ComplexFunction( - np.exp, copy.deepcopy(left_grid) - ).restrict_width(half_width + 0.1) #STUPID HACK - move_right_grid = ComplexFunction( - lambda z : z + SPACE_WIDTH, - copy.deepcopy(right_grid).shift(left_center), - run_time = DEFAULT_TRANSFORM_RUN_TIME - ).with_background(copy.deepcopy(left_grid).shift(left_center)) - draw_left_path = ShowCreation(left_path) - draw_right_path = ShowCreation(right_path) - show_left_start = Reveal(left_start) - show_right_start = Reveal(right_start) - left_vectors = VelocityVectorsOfPath(left_path, vector_len) - right_vectors = VelocityVectorsOfPath(right_path, vector_len) - - for anim in apply_function, draw_left_path, show_left_start, left_vectors: - anim.shift(left_center).with_background( - left_grid, dividing_line - ) - for anim in draw_right_path, show_right_start, right_vectors: - anim.shift(right_center).with_background(right_grid) - for anim in draw_left_path, draw_right_path, show_left_start, show_right_start: - anim.set_dither(0) - for anim, bg in (show_left_start, left_path), (show_right_start, right_path): - anim.set_alpha_func(there_and_back).with_background(bg) - left_vectors.with_background(left_path) - right_vectors.with_background(right_path) - return apply_function.then(move_right_grid).then( - draw_left_path.while_also(draw_right_path) - ).then( - show_left_start.while_also(show_right_start) - ).then( - left_vectors.while_also(right_vectors) - ) - - - -if __name__ == '__main__': - example_complex = complex(1, 1) - example_complex2 = complex(2, -1) - zoom_level = 0.5 - strong_zoom_level = 0.1 - vector_len = 0.5 - def square_homotopy((z, t)): - return z**(1 + t) - def example_walk(t): - return ((t + 1)/2, ((t + 1)/2)**2, 0) - def walk_imaginary_axis(t): - return (0, np.pi * (t + 1), 0) - functions = [ - # function_of_numbers, - # real_function_graph, - # two_grids, - # z_squared, - # z_squared_marked, - # (multiplier_in_the_wild, [example_complex2]), - # random_looking_function, - # (zoom_in_on_map, [square_homotopy, True, example_complex, zoom_level]), - # (zoom_in_on_map, [square_homotopy, True, example_complex, strong_zoom_level]), - # (z_squared_derivative_example, [example_complex, zoom_level]), - # (z_squared_derivative_2z, [zoom_level]), - # visualize_exp, - # take_derivative_of_series, - # derivative_definition, - # (e_to_x_takes_adder_to_multiplier, [example_complex]), - # (e_to_x_derivative_zoom, [example_complex, strong_zoom_level]), - # other_possible_functions, - # (setup_velocity_vector_discussion, [strong_zoom_level]), - # traced_path, - # (walking_north, [example_complex, vector_len]), - # (map_north_vector, [example_complex, vector_len, strong_zoom_level]), - # (all_possible_vectors, [vector_len]), - # (map_trajectories, [vector_len, example_walk]), - # (map_trajectories, [vector_len, walk_imaginary_axis]) - ] - - full_path = os.path.join(MOVIE_DIR, CCCD_MOVIE_DIR) - if not os.path.exists(full_path): - os.mkdir(full_path) - for func in functions: - args = [] - if isinstance(func, tuple): - func, args = func - name = os.path.join( - CCCD_MOVIE_DIR, - to_cammel_case(func.__name__) + hash_args(args) - ) - func(*args).write_to_movie(name) - - for anim in [ - # ComplexFunction(lambda z : 0.1*(z**3 - z**2 + 3)), - # ComplexFunction(np.exp, Grid(radius = SPACE_HEIGHT)), - ]: - anim.write_to_movie(os.path.join(CCCD_MOVIE_DIR, str(anim))) - - for name in [ - # "complex_derivative_title", - # "why_vectors", - # "pause_and_ponder", - # "think_in_pictures", - # "remember_this", - # "deriv_x_squared", - # "deriv_e_to_x", - # "multiplication_function", - ]: - ImageMobject(name_to_image[name]).center().save_image( - os.path.join(CCCD_MOVIE_DIR, to_cammel_case(name)) - ) - - - - - - - - diff --git a/epii/dexp_generate_images.py b/epii/dexp_generate_images.py deleted file mode 100644 index 4779c236..00000000 --- a/epii/dexp_generate_images.py +++ /dev/null @@ -1,16 +0,0 @@ -from PIL import Image -import itertools as it - -from constants import * -from helpers import invert_image -from tex_image_utils import load_pdf_images - - -if __name__ == "__main__": - folder = os.path.join(MOVIE_DIR, "dexp") - if not os.path.exists(folder): - os.makedirs(folder) - images = load_pdf_images("discover_exp.pdf", regen_if_exists = False) - for image, count in zip(images, it.count()): - filepath = os.path.join(folder, "dexp-%d.png"%count) - invert_image(image).save(filepath) diff --git a/epii/epii_animations.py b/epii/epii_animations.py deleted file mode 100644 index 83f85077..00000000 --- a/epii/epii_animations.py +++ /dev/null @@ -1,1141 +0,0 @@ -#!/usr/bin/env python - -from PIL import Image -from animate import * -from mobject import * -from constants import * -from helpers import * -from tex_image_utils import load_pdf_images -from displayer import * -import itertools as it -import os -import numpy as np -from copy import deepcopy - - -PI_COLOR = "red" -E_COLOR = "skyblue" -I_COLOR = "green" -ADDER_COLOR = "limegreen" -MULTIPLIER_COLOR = "yellow" -ONE_COLOR = "skyblue" - -EPII_MOVIE_DIR = "epii" - -symbol_images = load_pdf_images("epii_symbols.pdf", regen_if_exists = False) -phrase_images = load_pdf_images("epii_phrases.pdf", regen_if_exists = False) - -name_to_image = dict( - zip([ - "e", - "pi", - "i", - "equals_neg1", - "pile_of_equations", - "two", - "plus", - "three", - "four", - "times", - "five", - "fours_underbrace", - "e_to_x", - "e_by_e_x_times", - "e_by_e_pi_i_times", - "e_to_x_property", - "e_to_x_series", - "e_to_5", - "e_to_sum_ones", - "e_to_1_product", - "e_to_x_plus_y", - "e_by_e_x_plus_y_times", - "x_es_then_y_es", - "e_to_x_e_to_y", - "i_squared_equals_neg_1", - "epii_series", - "e_to_complex", - "e_to_matrix", - "e_to_derivative", - "adder_to_multiplier_property", - "defining_property", - "e_by_e", - "e_by_e_by_e", - "e_def", - "e_approx", - "one", - "sqrt_neg1", - "e_digits", - "twenty", - "three_point_five", - "sqrt_two", - "six", - "e_to_2_value", - "e_to_3_value", - "e_to_5_value", - "zero", - "minus", - "neg_1", - "to_the_x", - ], symbol_images) + zip([ - "e_question", - "pi_question", - "i_question", - "what", - "just_trust_it", - "ish", - "question_marks", - "not_what_is_happening", - "what_it_means", - "why_it_works", - "why_it_is_intuitive", - "colon_explanation", - "adder", - "multiplier", - "other_way_around", - "how_do_we_define_this", - "unlearn_what_you_have_learned", - "e_in_nature", - ], phrase_images) -) - -def logo_to_epii(): - e, pi, i, equals_neg1 = [ - ImageMobject(name_to_image[name]) - for name in [ - "e", "pi", "i", "equals_neg1" - ] - ] - epii_neg1 = CompoundMobject(e, pi, i, equals_neg1) - epii_neg1.center().shift((0, 2, 0)) - # stars = Stars() - return Transform( - ImageMobject(LOGO_PATH, invert = False), - epii_neg1, - dither_time = 0, run_time = 2.0, - ).then( - Animation(epii_neg1) - ) - # .then( - # Transform( - # stars, - # epii_neg1, - # dither_time = 0, run_time = 3.0, - # ) - - -def write_epii(): - e, pi, i, equals_neg1 = [ - ImageMobject(name_to_image[name]) - for name in ["e", "pi", "i", "equals_neg1"] - ] - center = CompoundMobject(e, pi, i, equals_neg1).get_center() - for mob in e, pi, i, equals_neg1: - mob.shift(-center) - anims=[ - ShowCreation(e), - ShowCreation(pi).with_background(e), - ShowCreation(i).with_background(e, pi), - ShowCreation(equals_neg1).with_background(e, pi, i), - ] - for anim in anims: - anim.set_run_time(1.0) - for anim in anims[1:]: - anim.set_dither(1) - anims[0].then(anim) - return anims[0] - - -def the_terms(): - e, pi, i, one, e_digits, sqrt_neg1, equals_neg1 = [ - ImageMobject(name_to_image[name]) - for name in [ - "e", "pi", "i", "one", "e_digits", - "sqrt_neg1", "equals_neg1" - ] - ] - center = CompoundMobject(e, pi, i, equals_neg1).get_center() - for mob in [e, pi, i, equals_neg1]: - mob.shift(-center + (0, 2, 0)) - colored_e = deepcopy(e).highlight(E_COLOR) - colored_pi = deepcopy(pi).highlight(PI_COLOR) - colored_i = deepcopy(i).highlight(I_COLOR) - - e_digits.highlight(E_COLOR) - sqrt_neg1.highlight(I_COLOR) - - e_digits.shift([2, -2, 0]) - sqrt_neg1.shift([2, 2, 0]) - - pi_copy = deepcopy(colored_pi) - pi_copy.scale(1.5) - pi_copy.center() - pi_copy.shift([-0.8, 0, 0]) - - one.center() - one.shift([0.2, 0, 0]) - - long_line = ParametricFunction(lambda t : (-1, np.pi * t, 0)) - diameter = ParametricFunction(lambda t : (0, t, 0)) - circle = Circle() - for mobject in [circle, diameter, one, long_line, pi_copy]: - mobject.shift([-1, 0, 0]) - mobject.highlight(PI_COLOR) - - return Transform( - CompoundMobject(e, pi, i, equals_neg1), - CompoundMobject(colored_e, colored_pi, colored_i, equals_neg1) - ).then( - Transform( - colored_e, e_digits - ).while_also( - Transform( - colored_i, sqrt_neg1 - ) - ).while_also( - Transform( - colored_pi, pi_copy - ) - ).while_also( - Transform( - circle, long_line, - ) - ).with_background( - diameter, one, colored_e, colored_pi, colored_i, equals_neg1 - ) - ) - -def literal_epii(): - e, pi, i, e_by_e_pi_i_times, what = [ - ImageMobject(name_to_image[name]) - for name in [ - "e", "pi", "i", "e_by_e_pi_i_times", "what" - ] - ] - what.shift([0, -1, 0]) - return Transform( - CompoundMobject(e, pi, i).center().shift((0, 2, 0)), - e_by_e_pi_i_times - ).then( - Animation(what, run_time = 2.1).with_background( - e_by_e_pi_i_times - ) - ) - -def pile_of_equations(): - return ShowCreation( - CompoundMobject( - ImageMobject(name_to_image["pile_of_equations"]).center(), - ImageMobject( - name_to_image["just_trust_it"] - ).center().shift([2, -3, 0]).highlight("red") - ), - alpha_func = None, - run_time = 5.0 - ) - -def confusion_of_terms(): - e, pi, i, e_question, pi_question, i_question, what_it_means = [ - ImageMobject(name_to_image[name]) - for name in [ - "e", "pi", "i", "e_question", "pi_question", "i_question", "what_it_means" - ] - ] - colored_e = deepcopy(e).highlight(E_COLOR) - colored_pi = deepcopy(pi).highlight(PI_COLOR) - colored_i = deepcopy(i).highlight(I_COLOR) - - e_question.highlight(E_COLOR).shift([2, 1, 0]) - pi_question.highlight(PI_COLOR).shift([0, -1, 0]) - i_question.highlight(I_COLOR).shift([-1, 0, 0]) - what_it_means.center().shift((-3, 0, 0)) - - stars = Stars() - - e_anim = Transform(colored_e, e_question) - e_anim.with_background(colored_pi, colored_i) - i_anim = Transform(colored_i, i_question) - i_anim.with_background(e_question, colored_pi) - pi_anim = Transform(colored_pi, pi_question) - pi_anim.with_background(e_question, i_question) - all_questions = CompoundMobject(e_question, pi_question, i_question) - to_stars = Transform( - all_questions, - stars, run_time = 5.0, dither_time = 0 - ) - stall_1 = Animation(all_questions) - to_goal = Transform(stars, what_it_means, dither_time = 0, run_time = 2.0) - for anim in [e_anim, i_anim, pi_anim]: - anim.set_run_time(1.0) - anim.set_dither(0) - for anim in [i_anim, pi_anim, stall_1, to_stars, to_goal]: - e_anim.then(anim) - return e_anim - -def list_of_goals(): - goals = [ - ImageMobject(name_to_image[name]).center() - for name in [ - "what_it_means", "why_it_works", "why_it_is_intuitive" - ] - ] - for x in range(3): - goals[x].shift((3*(x - 1), 0, 0)) - stars = Stars() - rotating_stars = Rotating(stars, radians = np.pi / 3) - return Transform(stars, goals[0]).while_also( - rotating_stars, display = False - ).then( - Reveal(goals[1], dither_time = 0).with_background(goals[0]) - ).then( - Reveal(goals[2]).with_background(*goals[:2]) - ) - -def not_repeated_multiplication(): - e_to_x, e_by_e_x_times, not_what_is_happening = [ - ImageMobject(name_to_image[name]).center() - for name in ["e_to_x", "e_by_e_x_times", "not_what_is_happening"] - ] - not_what_is_happening.rotate(np.pi/7).highlight("red") - return Transform(e_to_x, e_by_e_x_times).then( - Reveal(not_what_is_happening).with_background(e_by_e_x_times) - ).then( - Animation( - CompoundMobject(e_by_e_x_times, not_what_is_happening), - run_time = 1.0 - ) - ) - -def problems_with_repeated_multiplication(): - e, e_by_e, e_by_e_by_e, e_def, how_do_we_define_this = [ - ImageMobject(name_to_image[name]).center() - for name in ["e", "e_by_e", "e_by_e_by_e", - "e_def", "how_do_we_define_this"] - ] - how_do_we_define_this.highlight(E_COLOR).shift((0, -1, 0)) - kwargs = {"run_time" : 0.2, "dither_time" : 0.5} - return Transform(e, e_by_e, **kwargs).then( - Transform(e_by_e, e_by_e_by_e, **kwargs) - ).then( - Transform(e_by_e_by_e, e_def).while_also( - Reveal(how_do_we_define_this) - ) - ) - -def numbers_as_actions(): - three = ImageMobject(name_to_image["three"]).center() - sphere = Sphere().scale(2).highlight(MULTIPLIER_COLOR) - def custom_alpha(t): - return high_inflection_0_to_1(1.7 * t * (1 - t)) - return Transform( - three, sphere, run_time = 3.0, - alpha_func = custom_alpha - ).while_also( - Rotating(sphere, radians = 10 * np.pi), - display = False - ) - - -def numbers_as_counting(): - three = ImageMobject(name_to_image["three"]) - three.center() - spheres = CompoundMobject(*[ - Sphere().scale(0.5).shift([x - 1, 0, 0]) - for x in range(3) - ]) - return Transform( - three, spheres, - ).while_also( - Rotating(spheres, axis = [1, 0, 0]), - display = False - ) - - -def addition_by_counting(): - two, plus, three, five = [ - ImageMobject(name_to_image[name]) - for name in [ - "two", "plus", "three", "five" - ] - ] - tps_center = CompoundMobject(two, plus, three).get_center() - for mob in two, plus, three: - mob.shift(tps_center) - five.center() - spheres = [] - for x in range(5): - spheres.append(Sphere().scale(0.5).shift([x-2, 0, 0])) - first_two = CompoundMobject(*spheres[:2]) - last_three = CompoundMobject(*spheres[2:]) - all_five = CompoundMobject(*spheres) - plus_three = CompoundMobject(plus, three) - return Animation( - CompoundMobject(two, plus_three), - run_time = 2.0, dither_time = 0.0, - ).then( - Transform( - two, first_two, - ).set_dither(0).with_background( - plus_three - ) - ).then( - Transform( - plus_three, last_three, - ).with_background(first_two).set_dither(0) - ).then( - Transform( - all_five, five, - ).set_dither(0) - ).then( - Animation(five, run_time = 1.0, dither_time = 0.0) - ) - -def multiplication_by_counting(): - four, times, five, fours_underbrace, twenty = [ - ImageMobject(name_to_image[name]) - for name in [ - "four", "times", "five", "fours_underbrace", "twenty" - ] - ] - spheres = CompoundMobject(*[ - Sphere().scale(0.5).shift([1.5*x-3, 1.5-y, 0]) - for y in range(4) - for x in range(5) - ]) - fours_underbrace.center() - twenty.center() - rot_spheres = Rotating(spheres, axis = [1, 0, 0], radians = np.pi) - four_times_five = CompoundMobject(four, times, five).center() - first = Transform(four_times_five, fours_underbrace).set_dither(0.5) - second = Transform(copy.deepcopy(fours_underbrace), spheres).set_dither(0) - second.while_also(rot_spheres, display = False).generate_frames() - third = Transform(spheres, twenty).set_dither(0.5) - third.while_also(rot_spheres, display = False) - return first.then(second).then(third) - -def fraction_counting(): - three_point_five = ImageMobject(name_to_image["three_point_five"]).center() - spheres = [ - Sphere().scale(0.5).shift([x-1.5, 0, 0]) - for x in range(4) - ] - num_points = spheres[-1].get_num_points() - for attr in ['points', 'rgbs']: - setattr( - spheres[-1], attr, - getattr(spheres[-1], attr)[:num_points/2, :] - ) - spheres = CompoundMobject(*spheres) - spheres.rotate(np.pi/4, [1, 0, 0]) - return Transform( - three_point_five, spheres, - ).while_also( - Rotating(spheres, axis = [1, 0, 0], radians = np.pi), - display = False - ) - -def irrational_counting(): - sqrt_two = ImageMobject(name_to_image["sqrt_two"]).center() - ish = ImageMobject(name_to_image["ish"]).center() - spheres = [ - Sphere().scale(0.5).rotate(np.pi/4, [1, 0, 0]).shift([x-0.5, 0, 0]) - for x in range(2) - ] - num_points = spheres[-1].get_num_points() - for attr in ['points', 'rgbs']: - setattr( - spheres[-1], attr, - getattr(spheres[-1], attr)[:int(num_points*(np.sqrt(2)-2)), :] - ) - ish.shift([1.3, 0, 0]) - spheres = CompoundMobject(ish, *spheres) - return Transform( - sqrt_two, spheres - ).while_also( - Rotating(spheres, axis = [1, 0, 0], radians = np.pi), - display = False - ) - -def imaginary_counting(): - sqrt_neg1, question_marks = [ - ImageMobject(name_to_image[name]).center() - for name in ["sqrt_neg1", "question_marks"] - ] - return Transform(sqrt_neg1, question_marks) - -def real_number_as_three_things(): - three, adder, multiplier = [ - ImageMobject(name_to_image[name]).center() - for name in ["three", "adder", "multiplier"] - ] - adder_three = copy.deepcopy(three).highlight(ADDER_COLOR) - mult_three = copy.deepcopy(three).highlight(MULTIPLIER_COLOR) - - three.shift([0, 2, 0]) - adder_three.shift([-1, 2, 0]) - mult_three.shift([1, 2, 0]) - - adder.highlight(ADDER_COLOR).shift((2, 2, 0)) - multiplier.highlight(MULTIPLIER_COLOR).shift((2, 2, 0)) - - radius = 2 * SPACE_WIDTH - marked_number_line = NumberLine( - radius = radius, - with_numbers = True - ) - number_line = NumberLine(radius = radius) - three_dist = 3 * number_line.interval_size - - split_three = Transform( - copy.deepcopy(three), - CompoundMobject(three, adder_three, mult_three) - ) - adder_three.center().shift(three.get_center()) - mult_three.center().shift(three.get_center()) - draw_number_line = ShowCreation(marked_number_line) - three_to_point = Transform( - copy.deepcopy(three), - Point((three_dist, 0, 0)) - ) - add_by_three = ApplyFunction( - lambda (x, y, z) : (three_dist+x, y, z), - number_line, dither_time = 2.0 - ).while_also(Reveal(adder, dither_time = 2.0)) - multiply_by_three = ApplyFunction( - lambda (x, y, z) : (3*x, y, z), - number_line, dither_time = 2.0 - ).while_also(Reveal(multiplier, dither_time = 2.0)) - draw_number_line.set_dither(0) - - return split_three.then( - draw_number_line.with_background(three) - ).then( - add_by_three.with_background(adder_three) - ).then( - multiply_by_three.with_background(mult_three) - ) - - -def wrong_adder_conception(): - vert_disp = -0.3 - number_line = NumberLine(radius = SPACE_WIDTH + 3) - nlis = number_line.interval_size - three = ImageMobject(name_to_image["three"]) - three.center().shift((0, 2, 0)).highlight(ADDER_COLOR) - initial_numbers = [ - ImageMobject( - NAME_TO_IMAGE_FILE[str(x)] - ).center().scale(0.5).shift((x*nlis, vert_disp, 0)) - for x in range(-3, 4) - ] - final_numbers = [ - ImageMobject( - NAME_TO_IMAGE_FILE[str(x)] - ).center().scale(0.5).shift((x*nlis, vert_disp, 0)) - for x in range(0, 7) - ] - dots1 = ImageMobject(NAME_TO_IMAGE_FILE["cdots"]).center() - dots2 = copy.deepcopy(dots1).shift((-4 * nlis, vert_disp, 0)) - dots1.shift((4*nlis, vert_disp, 0)) - number_line.add(dots1, dots2) - kwargs = {"run_time" : 2.0, "dither_time" : 1.0} - anim = ComplexFunction(lambda z : z + 3*nlis, number_line, **kwargs) - for init, final in zip(initial_numbers, final_numbers): - anim.while_also(Transform(init, final, **kwargs)) - anim.while_also( - Transform(three, CompoundMobject(*final_numbers), **kwargs) - ) - return anim - -def real_addition_rule(): - three = ImageMobject(name_to_image["three"]).center() - three.shift([0, 2, 0]).highlight(ADDER_COLOR) - marked_number_line = NumberLine(radius = 2 * SPACE_WIDTH, with_numbers = True) - number_line = NumberLine(radius = 2 * SPACE_WIDTH) - three_dist = 3 * number_line.interval_size - shifted_line = copy.deepcopy(number_line).shift((three_dist, 0, 0)) - zero_arrow = Arrow().nudge().shift((0, -0.3, 0)) - three_arrow = Arrow((three_dist, -0.3, 0)).nudge().highlight(ADDER_COLOR) - return Reveal( - CompoundMobject(zero_arrow, three_arrow) - ).with_background(marked_number_line, three).then( - Transform( - CompoundMobject(number_line, zero_arrow), - CompoundMobject(shifted_line, three_arrow), - dither_time = 0, run_time = 3.0 - ).with_background(three, three_arrow) - ).then( - Flash(three_arrow).with_background(shifted_line, three) - ).then( - Animation(CompoundMobject(three_arrow, shifted_line, three)) - ) - -def real_multiplication_rule(): - three = ImageMobject(name_to_image["three"]).center() - three.shift([0, 2, 0]).highlight(MULTIPLIER_COLOR) - marked_number_line = NumberLine(with_numbers = True) - number_line = NumberLine() - three_dist = 3 * number_line.interval_size - stretched_line = copy.deepcopy(number_line) - stretched_line.points = np.array( - map(lambda (x, y, z) : (3*x, y, z), stretched_line.points) - ) - zero_arrow = Arrow(direction = (0, 1, 0)).nudge().shift((0, -0.3, 0)) - zero_arrow.highlight("white") - one_arrow = Arrow().nudge().shift((number_line.interval_size, -0.3, 0)) - one_arrow.highlight(ONE_COLOR) - three_arrow = Arrow((three_dist, -0.3, 0)).nudge().highlight(MULTIPLIER_COLOR) - return Reveal( - CompoundMobject(zero_arrow, one_arrow, three_arrow) - ).with_background(marked_number_line, three).then( - Transform( - CompoundMobject(number_line, one_arrow), - CompoundMobject(stretched_line, three_arrow), - dither_time = 0, run_time = 3.0 - ).with_background(three, three_arrow, zero_arrow) - ).then( - Flash(three_arrow).with_background(stretched_line, three, zero_arrow) - ).then( - Animation(CompoundMobject(zero_arrow, three_arrow, stretched_line, three)) - ) - -def real_addition_by_sliding(): - two, plus, three, five = [ - ImageMobject( - name_to_image[name] - ) - for name in [ - "two", "plus", "three", "five" - ] - ] - center = CompoundMobject(two, plus, three).get_center() - for mob in two, plus, three: - mob.shift(-center + (0, 2, 0)).highlight(ADDER_COLOR) - five.center().shift((0, 2, 0)).highlight(ADDER_COLOR) - number_line = NumberLine(radius = 2 * SPACE_WIDTH) #Numbers? - int_size = number_line.interval_size - shifted_line = dict() - for x in [2, 5]: - shifted_line[x] = copy.deepcopy(number_line).shift((x*int_size, 0, 0)) - return Transform( - copy.deepcopy(number_line), shifted_line[2], dither_time = 0.5 - ).with_background(two).then( - Transform( - shifted_line[2], shifted_line[5], dither_time = 0.5 - ).with_background(two, plus, three) - ).then( - Transform( - number_line, shifted_line[5], dither_time = 0.5 - ).with_background(five) - ) - -def real_multiplication_by_stretching(): - two, times, three, six = [ - ImageMobject( - name_to_image[name] - ).highlight(MULTIPLIER_COLOR) - for name in [ - "two", "times", "three", "six" - ] - ] - center = CompoundMobject(two, times, three).get_center() - for mob in two, times, three: - mob.shift(-center + (0, 2, 0)) - six.center().shift((0, 2, 0)) - number_line = NumberLine() #Numbers? - int_size = number_line.interval_size - stretched_line = dict() - for num in [2, 6]: - stretched_line[num] = copy.deepcopy(number_line) - stretched_line[num].points = np.array( - map(lambda (x, y, z) : (num*x, y, z), stretched_line[num].points) - ) - return Transform( - copy.deepcopy(number_line), stretched_line[2], dither_time = 0.5 - ).with_background(two).then( - Transform( - stretched_line[2], stretched_line[6], dither_time = 0.5 - ).with_background(two, times, three) - ).then( - Transform( - number_line, stretched_line[6], dither_time = 0.5 - ).with_background(six) - ) - - - -def exp_turns_adder_to_muliplier(): - two, e_to_x, e_to_2_value = [ - ImageMobject(name_to_image[name]).center() - for name in ["two", "e_to_x", "e_to_2_value"] - ] - two.center().shift((-2, 2, 0)).highlight(ADDER_COLOR) - e_to_x.center().shift((0, 2, 0)) - e_to_2_value.center().shift((2, 2, 0)).highlight(MULTIPLIER_COLOR) - number_line = NumberLine(radius = SPACE_WIDTH*2) - point = Point(e_to_x.get_center()) - shift_line = ApplyFunction( - lambda (x,y,z) : (x+2*number_line.interval_size,y,z), - copy.deepcopy(number_line), - run_time = 1.0, dither_time = 0 - ) - stretch_line = ApplyFunction( - lambda (x,y,z) : (x*np.exp(2),y,z), - number_line, - run_time = 1.0 - ) - return Reveal(two).set_dither(0).with_background(e_to_x).then( - shift_line.with_background(two, e_to_x) - ).then( - Transform(two, point, dither_time = 0).with_background(e_to_x) - ).then( - Transform(point, e_to_2_value, dither_time = 0).with_background(e_to_x) - ).then( - stretch_line.with_background(e_to_x, e_to_2_value) - ) - -def exp_is_homomorphism(): - two, three, five, e_to_x, e_to_2_value, e_to_3_value, e_to_5_value, plus, times = [ - ImageMobject(name_to_image[name]).center() - for name in ["two", "three", "five", "e_to_x", "e_to_2_value", - "e_to_3_value", "e_to_5_value", "plus", "times"] - ] - two.shift((-2.2, 2.2, 0)) - three.shift((-1.8, 1.8, 0)) - two_three = CompoundMobject(two, three).highlight(ADDER_COLOR) - five.shift((-2, -2, 0)).highlight(ADDER_COLOR) - e_to_2_value.shift((1.8, 2.2, 0)) - e_to_3_value.shift((2.2, 1.8, 0)) - e_to_2_value_e_to_3_value = CompoundMobject(e_to_2_value, e_to_3_value).highlight(MULTIPLIER_COLOR) - e_to_5_value.shift((2, -2, 0)).highlight(MULTIPLIER_COLOR) - e_to_x_copy = copy.deepcopy(e_to_x) - e_to_x.shift((0, 2, 0)) - e_to_x_copy.shift((0, -2, 0)) - plus.shift((-2, 0, 0)) - times.shift((2, 0, 0)) - operations = CompoundMobject(e_to_x, e_to_x_copy, plus, times) - high_exp_point = Point(e_to_x.get_center()) - low_exp_point = Point(e_to_x_copy.get_center()) - plus_point = Point(plus.get_center()) - times_point = Point(times.get_center()) - - anim = Transform( - two_three, plus_point, dither_time = 0 - ).with_background(operations) - for start, end in [ - (plus_point, five), - (five, low_exp_point), - (low_exp_point, e_to_5_value), - (copy.deepcopy(two_three), high_exp_point), - (high_exp_point, e_to_2_value_e_to_3_value), - (e_to_2_value_e_to_3_value, times_point), - (times_point, e_to_5_value) - ]: - anim.then(Transform(start, end, dither_time = 0), - carry_over_background = True - ) - if end in [e_to_5_value, five, e_to_2_value_e_to_3_value]: - anim.then( - Animation(end, run_time = 1.0, dither_time = 0), - carry_over_background = True, - ) - return anim - -def repeated_product_gives_property(): - expressions = [ - ImageMobject(name_to_image[name]).center() - for name in ["e_to_x_plus_y", "e_by_e_x_plus_y_times", - "x_es_then_y_es", "e_to_x_e_to_y",] - ] - anim = Transform(expressions[0], expressions[1], run_time = 0.5) - for x in range(1, 3): - anim.then( - Transform(expressions[x], expressions[x + 1]), - run_time = 0.5 - ) - return anim - - -def repeated_product_as_consequence(): - defining_property, other_way_around, e_to_5, \ - e_to_sum_ones, e_to_1_product = [ - ImageMobject(name_to_image[name]).center() - for name in ["defining_property", "other_way_around", "e_to_5", - "e_to_sum_ones", "e_to_1_product"] - ] - return Animation(other_way_around, run_time = 1.0, dither_time = 0).then( - Animation(defining_property, run_time = 2.0, dither_time = 0) - ).then( - Transform(e_to_5, e_to_sum_ones, run_time = 0.5) - ).then( - Transform(e_to_sum_ones, e_to_1_product, run_time = 0.5) - ) - - -def e_to_x_definition(): - adder_to_multiplier_property, e_to_x_series, \ - colon_explanation, e_def, e_approx, e_in_nature = [ - ImageMobject(name_to_image[name]) - for name in [ - "adder_to_multiplier_property", - "e_to_x_series", - "colon_explanation", - "e_def", - "e_approx", - "e_in_nature" - ] - ] - for mob in e_to_x_series, colon_explanation: - mob.center() - colon_explanation.shift((-1, 1.5, 0)) - colon_explanation.add(Arrow(point = (-3.5, 0.4, 0), direction = (-1,-1,0))) - e_in_nature.shift((0, -2, 0)) - for mob in e_def, e_approx: - mob.shift((0, 1, 0)) - return Transform( - adder_to_multiplier_property, - e_to_x_series - ).then( - Reveal(colon_explanation).with_background(e_to_x_series) - ).then( - Transform(e_to_x_series, e_def).while_also( - Reveal(CompoundMobject(e_approx, e_in_nature)) - ) - ) - -def less_natural_exponentials(): - two, five, i, to_the_x, adder_to_multiplier_property = [ - ImageMobject(name_to_image[name]) - for name in ["two", "five", "i", "to_the_x", - "adder_to_multiplier_property"] - ] - two.center() - five.center() - i.scale(1.5).center() - to_the_x.shift((0, -0.25, 0)) - kwargs = {"dither_time" : 0.5} - return Transform( - adder_to_multiplier_property, - CompoundMobject(two, to_the_x), **kwargs - ).then( - Transform(two, five, **kwargs).with_background( - to_the_x - ) - ).then( - Transform(five, i, **kwargs).with_background( - to_the_x - ) - ) - - -def complex_addition(num): - complex_plane = Grid(radius = 2 * SPACE_WIDTH).add(Cross()) - point = Cross().shift((num.real, num.imag, 0)).highlight(ADDER_COLOR) - return ShowCreation(point).with_background(complex_plane).then( - ComplexFunction( - (lambda z : z + num), complex_plane - ).with_background( - point - ) - ) - -def complex_multiplication(num): - complex_plane = Grid(radius = 2 * SPACE_WIDTH) - zero = Cross() - one = Cross().shift((1, 0, 0)).highlight(ONE_COLOR) - num_dot = Cross().shift((num.real, num.imag, 0)).highlight(MULTIPLIER_COLOR) - return ComplexFunction( - (lambda z : z*num), complex_plane - ).while_also( - ComplexFunction((lambda z : z + num - 1), one) - ).with_background( - zero, num_dot - ) - -def multiply_i_twice(): - zero, one, i, new_one = [ - Cross(), - Cross().shift((1, 0, 0)).highlight(ONE_COLOR), - Cross().shift((0, 1, 0)).highlight(MULTIPLIER_COLOR), - Cross().shift((0, 1, 0)).highlight(ONE_COLOR), - ] - complex_plane = Grid(radius = 2 * SPACE_WIDTH) - return RotationAsTransform(complex_plane, np.pi/2).while_also( - RotationAsTransform(one, np.pi/2) - ).with_background(zero, i).then( - RotationAsTransform(complex_plane, np.pi/2).while_also( - RotationAsTransform(CompoundMobject(new_one), np.pi/2) - ).with_background(zero) - ) - -def multiply_neg_1(): - zero, one, neg_1 = [ - Cross(), - Cross().shift((1, 0, 0)).highlight(ONE_COLOR), - Cross().shift((-1, 0, 0)).highlight(MULTIPLIER_COLOR), - ] - complex_plane = Grid(radius = 2 * SPACE_WIDTH).add(zero, one) - return RotationAsTransform( - complex_plane.add(zero, one), np.pi - ).with_background(neg_1) - -def i_squared_equals_neg_1(): - equation = ImageMobject(name_to_image["i_squared_equals_neg_1"]).center() - plane = Grid().add(Cross(), Cross().shift((-1, 0, 0)).highlight(MULTIPLIER_COLOR)) - return Transform(plane, equation, dither_time = 2.0) - -def reals_in_complex(): - radius = 2 * SPACE_WIDTH - plain_complex_plane = Grid(radius = radius) - complex_plane = copy.deepcopy(plain_complex_plane) - complex_plane.highlight(NumberLine.DEFAULT_COLOR, lambda (x, y, z) : y == 0) - shifted = copy.deepcopy(complex_plane).shift((3, 0, 0)) - stretched = copy.deepcopy(complex_plane).scale(2) - anim = Transform(plain_complex_plane, complex_plane) - for start, end in [ - (copy.deepcopy(complex_plane), shifted), - (shifted, complex_plane), - (copy.deepcopy(complex_plane), stretched), - (stretched, complex_plane) - ]: - anim.then(Transform(start, end, run_time = 2.0, dither_time = 0.0)) - return anim - -def broken_up_complex_addition(num): - complex_plane = Grid(radius = 2 * SPACE_WIDTH).add(Cross()) - point = Cross().shift((num.real, num.imag, 0)).highlight(ADDER_COLOR) - plane_plus_real = copy.deepcopy(complex_plane).shift((num.real, 0, 0)) - plane_plus_num = copy.deepcopy(complex_plane).shift((num.real, num.imag, 0)) - return Transform(complex_plane, plane_plus_real).with_background(point).then( - Transform(plane_plus_real, plane_plus_num), - carry_over_background = True - ) - -def broken_up_complex_multiplication(num): - complex_plane = Grid(radius = 2 * SPACE_WIDTH) - zero = Cross() - one = Cross().shift((1, 0, 0)).highlight(ONE_COLOR) - num_dot = Cross().shift((num.real, num.imag, 0)).highlight(MULTIPLIER_COLOR) - plane_stretched = copy.deepcopy(complex_plane).scale(np.linalg.norm(num)) - plane_times_num = copy.deepcopy(plane_stretched).rotate(np.log(num).imag) - one_stretched = copy.deepcopy(one).shift((np.linalg.norm(num) - 1, 0, 0)) - one_times_num = copy.deepcopy(one).center().shift(num_dot.get_center()) - return Transform( - complex_plane, plane_stretched - ).with_background(zero, num_dot).while_also( - Transform(one, one_stretched) - ).then( - Transform( - plane_stretched, plane_times_num - ).while_also(Transform(one_stretched, one_times_num)), - carry_over_background = True - ) - -def new_dimensions(): - adder = ComplexFunction(lambda z : z + complex(0, 1)) - multiplier = RotationAsTransform(Grid(radius = SPACE_HEIGHT + SPACE_WIDTH), np.pi / 3) - for anim in adder, multiplier: - anim.set_run_time(5.0).set_dither(0.5).set_alpha_func(there_and_back) - return adder.then(multiplier) - - -def wrap_imaginaries_to_circle(): - imaginaries = ParametricFunction( - lambda t : (0, t * SPACE_HEIGHT, 0), - color = ADDER_COLOR - ) - imaginaries.shift((0.01, 0, 0)) - circle = Circle(color = MULTIPLIER_COLOR) - Mobject.align_data(imaginaries, circle) - complex_plane = Grid() - hidden_plane = Grid(color = "black") - return FadeOut( - complex_plane, alpha_func = there_and_back - ).with_background(imaginaries).then( - ShowCreation(circle).with_background(imaginaries, complex_plane), - ).then( - ComplexFunction(np.exp, imaginaries).with_background( - circle, complex_plane), - ) - -def wrap_imaginaries_to_circle_with_measurments(): - pi, i, minus, neg_1 = [ - ImageMobject(name_to_image[name]) - for name in ["pi", "i", "minus", "neg_1"] - ] - pi_i = CompoundMobject(pi, i).center() - minus_pi_i = copy.deepcopy(pi_i).center().add( - minus.center().scale(0.5).shift((-0.2, 0, 0)) - ) - for mob, sgn in (pi_i, 1), (minus_pi_i, -1): - mob.shift((-0.3, sgn*np.pi, 0)) - mob.add( - Cross().scale(0.5).shift((0, sgn*np.pi, 0)).highlight(ADDER_COLOR) - ) - neg_1.center().shift((-1.2, 0, 0)) - imaginaries = ParametricFunction( - lambda t : (0, np.pi * t, 0), - color = ADDER_COLOR - ) - complex_plane = Grid() - circle = Circle(color = MULTIPLIER_COLOR) - return ComplexFunction(np.exp, imaginaries).with_background( - circle, complex_plane - ).while_also( - Transform(CompoundMobject(pi_i, minus_pi_i), neg_1, - run_time = DEFAULT_ANIMATION_RUN_TIME, - ) - ) - -def definition_of_pi(): - pi, one, two = [ - ImageMobject(name_to_image[name]).center() - for name in [ - "pi", "one", "two" - ] - ] - two.scale(0.7).shift((-0.1, 0, 0)) - two_pi = CompoundMobject(two, pi.shift((0.1, 0, 0))) - one.shift((0.5, 0.3, 0)) - two_pi.shift((0, -1.3, 0)) - circle = Circle().rotate(np.pi/4) - line = Line((-np.pi, -1, 0), (np.pi, -1, 0)).highlight(Circle.DEFAULT_COLOR) - radius = Line((0, 0, 0), (1, 0, 0)) - kwargs = {"run_time" : 2, "dither_time" : 1} - return Transform(circle, line, **kwargs).with_background( - one, radius - ).while_also( - Reveal(two_pi, **kwargs) - ) - - -def epii_adder_to_multiplier(): - e, pi, i, equals_neg1, neg_1 = [ - ImageMobject(name_to_image[name]) - for name in [ - "e", "pi", "i", "equals_neg1", "neg_1" - ] - ] - pi.highlight(ADDER_COLOR) - i.highlight(ADDER_COLOR) - equals_neg1.highlight(MULTIPLIER_COLOR, lambda (x, y, z) : x > 0.25) - neg_1.highlight(MULTIPLIER_COLOR) - epii_neg1 = CompoundMobject(e, pi, i, equals_neg1) - - dividing_line = Line((0, -SPACE_HEIGHT, 0), (0, SPACE_HEIGHT, 0)) - half_width = SPACE_WIDTH / 2 - left_grid = Grid(radius = SPACE_HEIGHT + np.pi).filter_out( - lambda (x, y, z) : abs(x) > half_width - ).add(Cross()) - right_grid = Grid().add(Cross(), Cross().highlight(ONE_COLOR).shift((1, 0, 0))) - # pi_i = CompoundMobject(pi, i).center().shift((-0.25, np.pi, 0)) - pi_i = Cross().highlight(ADDER_COLOR).shift((0, np.pi, 0)) - # neg_1.center().shift((-1.5, 0, 0)) - neg_1 = Cross().highlight(MULTIPLIER_COLOR).shift((-1, 0, 0)) - return Animation(epii_neg1, run_time = 2, dither_time = 0).then( - ComplexFunction(lambda z : z + complex(0, np.pi), left_grid).with_background( - pi_i, dividing_line.shift((half_width, 0, 0)) - ).shift((-half_width, 0, 0)).while_also( - RotationAsTransform(right_grid, np.pi).with_background( - neg_1 - ).restrict_width(half_width).shift((half_width, 0, 0)) - ).while_also( - Animation(epii_neg1) - ) - ) - - # return Animation(epii_neg1, run_time = 1.0, dither_time = 0).then( - # ComplexFunction(lambda z : z + complex(0, np.pi), Grid(radius = 2*SPACE_HEIGHT)) - # ).with_background(epii_neg1).then( - # RotationAsTransform(Grid(radius = 2*SPACE_HEIGHT), np.pi) - # ).with_background(epii_neg1) - -def e_to_all_kinds_of_things(): - expressions = [ - ImageMobject(name_to_image[name]) - for name in [ - "e_to_complex", "e_to_matrix", "e_to_derivative", "e_def" - ] - ] - return reduce( - Animation.then, - [ - Transform(expressions[x], expressions[x + 1]) - for x in range(3) - ] - ) - - - -if __name__ == '__main__': - example_complex = complex(2, 1) - functions = [ - # (logo_to_epii, []), - # (write_epii, []), - # (the_terms, []), - # (literal_epii, []), - # (pile_of_equations, []), - # (confusion_of_terms, []), - # (list_of_goals, []), - # (not_repeated_multiplication, []), - # (problems_with_repeated_multiplication, []), - # (numbers_as_actions, []), - # (numbers_as_counting, []), - # (addition_by_counting, []), - # (multiplication_by_counting, []), - # (fraction_counting, []), - # (irrational_counting, []), - # (imaginary_counting, []), - # (real_number_as_three_things, []), - # (wrong_adder_conception, []), - # (real_addition_rule, []), - # (real_multiplication_rule, []), - # (real_addition_by_sliding, []), - # (real_multiplication_by_stretching, []), - # (exp_turns_adder_to_muliplier, []), - # (exp_is_homomorphism, []), - # (repeated_product_gives_property, []), - # (repeated_product_as_consequence, []), - (e_to_x_definition, []), - # (less_natural_exponentials, []), - # (complex_addition, [example_complex]), - # (complex_multiplication, [example_complex]), - # (multiply_i_twice, []), - # (multiply_neg_1, []), - # (i_squared_equals_neg_1, []), - # (complex_addition, [complex(0, 1)]), - # (reals_in_complex, []), - # (broken_up_complex_addition, [example_complex]), - # (broken_up_complex_multiplication, [example_complex]), - # (new_dimensions, []), - # (wrap_imaginaries_to_circle, []), - # (wrap_imaginaries_to_circle_with_measurments, []), - # (definition_of_pi, []), - # (epii_adder_to_multiplier, []), - # (e_to_all_kinds_of_things, []), - ] - - full_path = os.path.join(MOVIE_DIR, EPII_MOVIE_DIR) - if not os.path.exists(full_path): - os.mkdir(full_path) - for func, args in functions: - name = os.path.join( - EPII_MOVIE_DIR, - to_cammel_case(func.__name__) + hash_args(args) - ) - func(*args).write_to_movie(name) - - for anim in [ - # ShowCreation(Grid(), run_time = 3.0), - # Rotating(Stars(), radians = np.pi / 3), - # ComplexFunction(np.exp, Grid(radius = SPACE_HEIGHT)) - ]: - anim.write_to_movie(os.path.join(EPII_MOVIE_DIR, str(anim))) - - - - - - - - - diff --git a/epii/poem_animations.py b/epii/poem_animations.py deleted file mode 100644 index d9c8d6ed..00000000 --- a/epii/poem_animations.py +++ /dev/null @@ -1,298 +0,0 @@ -#!/usr/bin/env python - -from PIL import Image -from animate import * -from mobject import * -from constants import * -from helpers import * -from tex_image_utils import load_pdf_images -from displayer import * -import itertools as it -import os -import numpy as np -from copy import deepcopy - -from epii_animations import name_to_image - - -PI_COLOR = "red" -E_COLOR = "skyblue" -I_COLOR = "green" -ADDER_COLOR = "limegreen" -MULTIPLIER_COLOR = "yellow" -ONE_COLOR = "skyblue" - -POEM_MOVIE_DIR = "poem" - -symbol_images = load_pdf_images("epii_poem.pdf", regen_if_exists = False) - -RUN_TIMES = [ - 0.4, - 0.4, - 0.4, - 0.4, - 0.4, - 0.4, - 0.4, - 0.4, -] -DITHER_TIMES = [ - 0, - 0.1, - 0, - 0.1, - 0, - 0.05, - 0.0, - 0.1, -] -LAST_FRAME_REST_KWARGS = {"run_time" : 1.0, "dither_time" : 0} -LINE_KWARGS = [ - {"run_time" : run_time, "dither_time" : dither_time} - for run_time, dither_time in zip(RUN_TIMES, DITHER_TIMES) -] - -LINES_PER_VERSE = 8 -LINES_PER_LAST_VERSE = 4 -VERSES = 10 - -def get_text_transitions(verse): - num_lines = LINES_PER_LAST_VERSE if (verse == VERSES - 1) else LINES_PER_VERSE - lines = [ - ImageMobject(symbol_images[LINES_PER_VERSE * verse + x]) - for x in range(num_lines) - ] - lines[2].shift((-1, 0, 0)) - transitions = [] - for x in range(num_lines): - if x == 0: - transition = Animation(lines[x], **LINE_KWARGS[x]) - elif x == 1: - transition = Reveal(lines[x], **LINE_KWARGS[x]) - elif x in range(2, num_lines-1): - transition = Transform(lines[x-2], lines[x], **LINE_KWARGS[x]) - else: - transition = Transform( - CompoundMobject(lines[x-2], lines[x-1]), lines[x], - **LINE_KWARGS[x] - ) - if x in range(1, num_lines-1): - transition.with_background(lines[x - 1]) - transitions.append(transition) - return transitions - -def augment_verse_0(transitions): - mobs = [e, pi, i, equals_neg1] = [ - ImageMobject(name_to_image[name]) - for name in ["e", "pi", "i", "equals_neg1"] - ] - center = CompoundMobject(*mobs).get_center() - for mob in mobs: - mob.shift(-center) - for x, mob in zip([1, 2, 3, 7], mobs): - transitions[x].while_also(ShowCreation(mob, **LINE_KWARGS[x])) - for y in range(x + 1, LINES_PER_VERSE): - transitions[y].with_background(mob) - -def augment_verse_1(transitions): - e, pi, i, e_by_e_pi_i_times = [ - ImageMobject(name_to_image[name]) - for name in ["e", "pi", "i", "e_by_e_pi_i_times"] - ] - epii = CompoundMobject(e, pi, i).center() - for x in range(4): - transitions[x].with_background(epii) - transitions[4].while_also(Transform(epii, e_by_e_pi_i_times, **LINE_KWARGS[4])) - for x in range(5, LINES_PER_VERSE): - transitions[x].with_background(e_by_e_pi_i_times) - -def augment_verse_2(transitions): - e, pi, i, pi_question, i_question = [ - ImageMobject(name_to_image[name]) - for name in ["e", "pi", "i", "pi_question", "i_question"] - ] - center = CompoundMobject(e, pi, i).get_center() - for mob in e, pi, i: - mob.shift(-center) - pi.highlight(PI_COLOR) - pi_question.highlight(PI_COLOR).shift((-1, -1, 0)) - i.highlight(I_COLOR) - i_question.highlight(I_COLOR).shift((1, 1, 0)) - for x in [2, 3]: - transitions[x].with_background(pi_question, i_question) - transitions[4].while_also( - Transform(pi_question, pi, **LINE_KWARGS[4]) - ).with_background(i_question) - transitions[5].while_also( - Transform(i_question, i, **LINE_KWARGS[5]) - ).with_background(pi) - for x in [6, 7]: - transitions[x].with_background(pi, i) - transitions[7].while_also(Reveal(e, **LINE_KWARGS[7])) - -def augment_verse_3(transitions): - one, i, minus, two, three_point_five = [ - ImageMobject(name_to_image[name]) - for name in ["one", "i", "minus", "two", "three_point_five"] - ] - minus.shift((-0.8, 0.25, 0)) - minus_two = CompoundMobject(minus, two) - nums = [one, i, minus_two, three_point_five] - for num in nums: - num.center().shift((0.5, 0, 0)).highlight(ADDER_COLOR) - i.scale(2) - - plane = Grid(radius = SPACE_WIDTH + SPACE_HEIGHT) - transitions[3].while_also(ShowCreation(plane, **LINE_KWARGS[3])) - for x, c, num in zip([4, 5, 6, 7], [1, complex(0, 1), -2, 3.5], nums): - transitions[x].while_also( - ComplexFunction(lambda z : z + c, plane, **LINE_KWARGS[x]) - ).with_background(num) - -def augment_verse_4(transitions): - i, two = [ - ImageMobject(name_to_image[name]) - for name in ["i", "two"] - ] - for num in i, two: - num.center().shift((0.5, 0, 0)).highlight(MULTIPLIER_COLOR) - - plane = Grid(radius = SPACE_WIDTH + SPACE_HEIGHT) - for x in [0, 1, 2, 3, 6, 7]: - transitions[x].with_background(plane) - transitions[4].while_also( - RotationAsTransform(plane, np.pi/2, **LINE_KWARGS[4]) - ).with_background(i) - transitions[5].while_also( - ComplexFunction(lambda z : 2*z, plane, **LINE_KWARGS[5]) - ).with_background(two) - -def augment_verse_5(transitions): - e_to_x = ImageMobject(name_to_image["e_to_x"]).center() - for transition in transitions: - transition.with_background(e_to_x) - -def augment_verse_6(transitions): - e_to_x, e_by_e_x_times, not_what_is_happening, two, e_to_2 = [ - ImageMobject(name_to_image[name]) - for name in ["e_to_x", "e_by_e_x_times", "not_what_is_happening", - "two", "e_to_2_value"] - ] - two.center().shift((-2, 0, 0)).highlight(ADDER_COLOR) - e_to_2.center().shift((2, 0, 0)).highlight(MULTIPLIER_COLOR) - e_to_x.center() - point = Point() - not_what_is_happening.rotate(np.pi/7).highlight("red") - transitions[0].while_also(Transform(e_to_x, e_by_e_x_times, **LINE_KWARGS[0])) - transitions[1].while_also( - Reveal(not_what_is_happening, **LINE_KWARGS[1]) - ).with_background(e_by_e_x_times) - for x in [2, 3]: - transitions[x].with_background(e_by_e_x_times, not_what_is_happening) - transitions[4].with_background(two, e_to_x) - transitions[5].while_also( - Transform(two, point, **LINE_KWARGS[5]) - ).with_background(e_to_x) - transitions[6].while_also( - Transform(point, e_to_2, **LINE_KWARGS[6]) - ).with_background(e_to_x) - transitions[7].with_background(e_to_2, e_to_x) - - -def augment_verse_7(transitions): - plane = Grid(SPACE_HEIGHT + SPACE_WIDTH) - for x, c in zip([0, 1, 4, 5], [1, -1, complex(0, 1), complex(0, -1)]): - transitions[x].while_also( - ComplexFunction(lambda z : z + c, plane, **LINE_KWARGS[x]) - ) - big_plane = copy.deepcopy(plane).scale(2) - for x, c, mob in zip([2, 3], [2, 0.5], [plane, big_plane]): - transitions[x].while_also( - ComplexFunction(lambda z : z*c, mob, **LINE_KWARGS[x]) - ) - rotated_plane = copy.deepcopy(plane).rotate(np.pi / 4) - for x, r, mob in zip([6, 7], [np.pi/4, -np.pi/4], [plane, rotated_plane]): - transitions[x].while_also( - RotationAsTransform(mob, r, **LINE_KWARGS[x]) - ) - -def augment_verse_8(transitions): - pi, i, neg_1 = [ - ImageMobject(name_to_image[name]) - for name in ["pi", "i", "neg_1"] - ] - pi_i = CompoundMobject(pi, i).center() - pi_i.shift((-0.3, np.pi, 0)) - neg_1.center().shift((-1.2, 0, 0)) - imaginaries = ParametricFunction( - lambda t : (0, np.pi * t, 0), - color = ADDER_COLOR - ) - plane = Grid() - circle = Circle(color = MULTIPLIER_COLOR) - - transitions[0].with_background(plane) - transitions[1].while_also( - Reveal(pi_i, **LINE_KWARGS[1]) - ).with_background(plane) - transitions[2].while_also( - ComplexFunction(lambda z : z + np.pi * complex(0, 1), **LINE_KWARGS[2]) - ).with_background(pi_i) - transitions[3].with_background(plane, pi_i) - transitions[4].while_also( - Transform(imaginaries, circle, **LINE_KWARGS[4]) - ).while_also( - Transform(pi, neg_1, **LINE_KWARGS[4]) - ).with_background(plane) - transitions[5].with_background(plane, neg_1, circle) - transitions[6].while_also( - RotationAsTransform(plane, np.pi, **LINE_KWARGS[6]) - ).with_background(circle, neg_1) - transitions[7].with_background(plane, circle, neg_1) - -def augment_verse_9(transitions): - mobs = [e, pi, i, equals_neg1] = [ - ImageMobject(name_to_image[name]) - for name in ["e", "pi", "i", "equals_neg1"] - ] - epii_neg1 = CompoundMobject(*mobs).center() - for transition in transitions: - transition.with_background(epii_neg1) - - -if __name__ == '__main__': - augment_verse = [ - augment_verse_0, - augment_verse_1, - augment_verse_2, - augment_verse_3, - augment_verse_4, - augment_verse_5, - augment_verse_6, - augment_verse_7, - augment_verse_8, - augment_verse_9, - ] - for verse in range(VERSES): - transitions = get_text_transitions(verse) - augment_verse[verse](transitions) - name = os.path.join(POEM_MOVIE_DIR, "Verse%d"%verse) - reduce(Animation.then, transitions).write_to_movie(name) - - - - - - - - - - - - - - - - - - diff --git a/mobject.py b/mobject.py deleted file mode 100644 index 9a496b79..00000000 --- a/mobject.py +++ /dev/null @@ -1,515 +0,0 @@ -import numpy as np -import itertools as it -import os -from PIL import Image -from random import random -from copy import deepcopy -from colour import Color - -from constants import * -from helpers import * -import displayer as disp - - -class Mobject(object): - """ - Mathematical Object - """ - #Number of numbers used to describe a point (3 for pos, 3 for normal vector) - DIM = 3 - - DEFAULT_COLOR = Color("skyblue") - - SHOULD_BUFF_POINTS = GENERALLY_BUFF_POINTS - - def __init__(self, - color = None, - name = None, - center = None, - ): - self.color = Color(color) if color else Color(self.DEFAULT_COLOR) - if not hasattr(self, "name"): - self.name = name or self.__class__.__name__ - self.has_normals = hasattr(self, 'unit_normal') - self.points = np.zeros((0, 3)) - self.rgbs = np.zeros((0, 3)) - if self.has_normals: - self.unit_normals = np.zeros((0, 3)) - self.generate_points() - if center: - self.center().shift(center) - - def __str__(self): - return self.name - - def show(self): - Image.fromarray(disp.paint_mobject(self)).show() - - def save_image(self, name = None): - Image.fromarray(disp.paint_mobject(self)).save( - os.path.join(MOVIE_DIR, (name or str(self)) + ".png") - ) - - def add_points(self, points, rgbs = None, color = None): - """ - points must be a Nx3 numpy array, as must rgbs if it is not None - """ - 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) - else: - if rgbs.shape != points.shape: - raise Exception("points and rgbs must have same shape") - self.rgbs = np.append(self.rgbs, rgbs).reshape(self.points.shape) - 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) - return self - - def rotate(self, angle, axis = [0, 0, 1]): - 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 shift(self, vector): - cycle = it.cycle(vector) - v = np.array([cycle.next() for x in range(self.points.size)]).reshape(self.points.shape) - self.points += v - return self - - def center(self): - self.shift(-self.get_center()) - return self - - def scale(self, scale_factor): - self.points *= scale_factor - return self - - def scale_in_place(self, scale_factor): - center = self.get_center() - return self.center().scale(scale_factor).shift(center) - - def add(self, *mobjects): - for mobject in mobjects: - self.add_points(mobject.points, mobject.rgbs) - 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) - return self - - def get_num_points(self): - return self.points.shape[0] - - def pose_at_angle(self): - self.rotate(np.pi / 7) - self.rotate(np.pi / 7, [1, 0, 0]) - 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): - def point_map((x, y, z)): - result = function(complex(x, y)) - return (result.real, result.imag, 0) - return self.apply_function(point_map) - - def highlight(self, color = "red", condition = lambda x : True): - """ - Condition is function which takes in one arguments, (x, y, z). - """ - #TODO, Should self.color change? - to_change = np.apply_along_axis(condition, 1, self.points) - self.rgbs[to_change, :] *= 0 - self.rgbs[to_change, :] += Color(color).get_rgb() - return self - - def fade(self, amount = 0.5): - self.rgbs += amount - 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 - - ### Getters ### - def get_center(self): - return np.apply_along_axis(np.mean, 0, self.points) - - def get_width(self): - return np.max(self.points[:, 0]) - np.min(self.points[:, 0]) - - def get_height(self): - return np.max(self.points[:, 1]) - np.min(self.points[:, 1]) - - ### Stuff subclasses should deal with ### - def should_buffer_points(self): - # potentially changed in subclasses - return GENERALLY_BUFF_POINTS - - def generate_points(self): - #Typically implemented in subclass, unless purposefully left blank - pass - - ### Static Methods ### - def align_data(mobject1, mobject2): - count1, count2 = mobject1.get_num_points(), mobject2.get_num_points() - if count1 == 0: - mobject1.add_points([(0, 0, 0)]) - if count2 == 0: - mobject2.add_points([(0, 0, 0)]) - if count1 == count2: - return - for attr in ['points', 'rgbs']: - new_arrays = make_even(getattr(mobject1, attr), getattr(mobject2, attr)) - for array, mobject in zip(new_arrays, [mobject1, mobject2]): - setattr(mobject, attr, np.array(array)) - - def interpolate(mobject1, mobject2, target_mobject, alpha): - """ - Turns target_mobject into an interpolation between mobject1 - and mobject2. - """ - Mobject.align_data(mobject1, mobject2) - for attr in ['points', 'rgbs']: - new_array = (1 - alpha) * getattr(mobject1, attr) + \ - alpha * getattr(mobject2, attr) - setattr(target_mobject, attr, new_array) - -class Mobject1D(Mobject): - def __init__(self, density = DEFAULT_POINT_DENSITY_1D, *args, **kwargs): - self.epsilon = 1.0 / density - Mobject.__init__(self, *args, **kwargs) - -class Mobject2D(Mobject): - def __init__(self, density = DEFAULT_POINT_DENSITY_2D, *args, **kwargs): - self.epsilon = 1.0 / density - Mobject.__init__(self, *args, **kwargs) - -class CompoundMobject(Mobject): - def __init__(self, *mobjects): - Mobject.__init__(self) - for mobject in mobjects: - self.add_points(mobject.points, mobject.rgbs) - - -###### Concrete Mobjects ######## - -class Stars(Mobject): - DEFAULT_COLOR = "white" - SHOULD_BUFF_POINTS = False - def __init__(self, num_points = DEFAULT_NUM_STARS, - *args, **kwargs): - self.num_points = num_points - Mobject.__init__(self, *args, **kwargs) - - def generate_points(self): - self.add_points([ - ( - r * np.sin(phi)*np.cos(theta), - r * np.sin(phi)*np.sin(theta), - r * np.cos(phi) - ) - for x in range(self.num_points) - for r, phi, theta in [[ - max(SPACE_HEIGHT, SPACE_WIDTH) * random(), - np.pi * random(), - 2 * np.pi * random(), - ]] - ]) - -class Point(Mobject): - def __init__(self, point = (0, 0, 0), *args, **kwargs): - Mobject.__init__(self, *args, **kwargs) - self.points = np.array(point).reshape(1, 3) - self.rgbs = np.array(self.color.get_rgb()).reshape(1, 3) - -class Arrow(Mobject1D): - DEFAULT_COLOR = "white" - NUNGE_DISTANCE = 0.1 - def __init__(self, point = (0, 0, 0), direction = (-1, 1, 0), - length = 1, tip_length = 0.25, - normal = (0, 0, 1), *args, **kwargs): - self.point = np.array(point) - self.direction = np.array(direction) / np.linalg.norm(direction) - self.normal = np.array(normal) - self.length = length - self.tip_length = tip_length - Mobject1D.__init__(self, *args, **kwargs) - - def generate_points(self): - self.add_points([ - [x, x, x] * self.direction + self.point - for x in np.arange(-self.length, 0, self.epsilon) - ]) - tips_dir = np.array(-self.direction), np.array(-self.direction) - for i, sgn in zip([0, 1], [-1, 1]): - tips_dir[i] = rotate_vector(tips_dir[i], sgn * np.pi / 4, self.normal) - self.add_points([ - [x, x, x] * tips_dir[i] + self.point - for x in np.arange(0, self.tip_length, self.epsilon) - for i in [0, 1] - ]) - - def nudge(self): - return self.shift(-self.direction * self.NUNGE_DISTANCE) - -class Vector(Arrow): - def __init__(self, point = (1, 0, 0), *args, **kwargs): - length = np.linalg.norm(point) - Arrow.__init__(self, point = point, direction = point, - length = length, tip_length = 0.2 * length, - *args, **kwargs) - -class Dot(Mobject1D): #Use 1D density, even though 2D - DEFAULT_COLOR = "white" - def __init__(self, center = (0, 0, 0), radius = 0.05, *args, **kwargs): - center = np.array(center) - if center.size == 1: - raise Exception("Center must have 2 or 3 coordinates!") - elif center.size == 2: - center = np.append(center, [0]) - self.center_point = center - self.radius = radius - Mobject1D.__init__(self, *args, **kwargs) - - def generate_points(self): - self.add_points([ - np.array((t*np.cos(theta), t*np.sin(theta), 0)) + self.center_point - for t in np.arange(0, self.radius, self.epsilon) - for theta in np.arange(0, 2 * np.pi, self.epsilon) - ]) - -class Cross(Mobject1D): - RADIUS = 0.3 - DEFAULT_COLOR = "white" - def generate_points(self): - self.add_points([ - (sgn * x, x, 0) - for x in np.arange(-self.RADIUS / 2, self.RADIUS/2, self.epsilon) - for sgn in [-1, 1] - ]) - -class Line(Mobject1D): - def __init__(self, start, end, density = DEFAULT_POINT_DENSITY_1D, *args, **kwargs): - self.start = np.array(start) - self.end = np.array(end) - density *= np.linalg.norm(self.start - self.end) - Mobject1D.__init__(self, density = density, *args, **kwargs) - - def generate_points(self): - self.add_points([ - t * self.end + (1 - t) * self.start - for t in np.arange(0, 1, self.epsilon) - ]) - -class CurvedLine(Line): - def generate_points(self): - equidistant_point = rotate_vector( - self.end - self.start, - np.pi/3, [0,0,1] - ) + self.start - self.add_points([ - (1 - t*(1-t))*(t*self.end + (1-t)*self.start) \ - + t*(1-t)*equidistant_point - for t in np.arange(0, 1, self.epsilon) - ]) - self.ep = equidistant_point - -class CubeWithFaces(Mobject2D): - def generate_points(self): - self.add_points([ - sgn * np.array(coords) - for x in np.arange(-1, 1, self.epsilon) - for y in np.arange(x, 1, self.epsilon) - for coords in it.permutations([x, y, 1]) - for sgn in [-1, 1] - ]) - self.pose_at_angle() - - def unit_normal(self, coords): - return np.array(map(lambda x : 1 if abs(x) == 1 else 0, coords)) - -class Cube(Mobject1D): - DEFAULT_COLOR = "yellow" - def generate_points(self): - self.add_points([ - ([a, b, c][p[0]], [a, b, c][p[1]], [a, b, c][p[2]]) - for p in [(0, 1, 2), (2, 0, 1), (1, 2, 0)] - for a, b, c in it.product([-1, 1], [-1, 1], np.arange(-1, 1, self.epsilon)) - ]) - self.pose_at_angle() - - -class Sphere(Mobject2D): - def generate_points(self): - self.add_points([ - ( - np.sin(phi) * np.cos(theta), - np.sin(phi) * np.sin(theta), - np.cos(phi) - ) - for phi in np.arange(self.epsilon, np.pi, self.epsilon) - for theta in np.arange(0, 2 * np.pi, 2 * self.epsilon / np.sin(phi)) - ]) - - def unit_normal(self, coords): - return np.array(coords) / np.linalg.norm(coords) - -class Circle(Mobject1D): - DEFAULT_COLOR = "red" - def generate_points(self): - self.add_points([ - (np.cos(theta), np.sin(theta), 0) - for theta in np.arange(0, 2 * np.pi, self.epsilon) - ]) - -class FunctionGraph(Mobject1D): - DEFAULT_COLOR = "lightblue" - def __init__(self, function, x_range = [-10, 10], *args, **kwargs): - self.function = function - self.x_min = x_range[0] / SPACE_WIDTH - self.x_max = x_range[1] / SPACE_WIDTH - Mobject1D.__init__(self, *args, **kwargs) - - def generate_points(self): - scale_factor = 2.0 * SPACE_WIDTH / (self.x_max - self.x_min) - self.epsilon /= scale_factor - self.add_points([ - np.array([x, self.function(x), 0]) - for x in np.arange(self.x_min, self.x_max, self.epsilon) - ]) - self.scale(scale_factor) - - -class ParametricFunction(Mobject): - DEFAULT_COLOR = "lightblue" - def __init__(self, - function, - dim = 1, - expected_measure = 10.0, - density = None, - *args, - **kwargs): - self.function = function - self.dim = dim - self.expected_measure = expected_measure - if density: - self.epsilon = 1.0 / density - elif self.dim == 1: - self.epsilon = 1.0 / expected_measure / DEFAULT_POINT_DENSITY_1D - else: - self.epsilon = 1.0 / np.sqrt(expected_measure) / DEFAULT_POINT_DENSITY_2D - Mobject.__init__(self, *args, **kwargs) - - def generate_points(self): - if self.dim == 1: - self.add_points([ - self.function(t) - for t in np.arange(-1, 1, self.epsilon) - ]) - if self.dim == 2: - self.add_points([ - self.function(s, t) - for t in np.arange(-1, 1, self.epsilon) - for s in np.arange(-1, 1, self.epsilon) - ]) - -class Grid(Mobject1D): - DEFAULT_COLOR = "green" - def __init__(self, - radius = max(SPACE_HEIGHT, SPACE_WIDTH), - interval_size = 1.0, - subinterval_size = 0.5, - *args, **kwargs): - self.radius = radius - self.interval_size = interval_size - self.subinterval_size = subinterval_size - Mobject1D.__init__(self, *args, **kwargs) - - def generate_points(self): - self.add_points([ - (sgns[0] * x, sgns[1] * y, 0) - for beta in np.arange(0, self.radius, self.interval_size) - for alpha in np.arange(0, self.radius, self.epsilon) - for sgns in it.product((-1, 1), (-1, 1)) - for x, y in [(alpha, beta), (beta, alpha)] - ]) - if self.subinterval_size: - si = self.subinterval_size - color = Color(self.color) - color.set_rgb([x/2 for x in color.get_rgb()]) - self.add_points([ - (sgns[0] * x, sgns[1] * y, 0) - for beta in np.arange(0, self.radius, si) - if abs(beta % self.interval_size) > self.epsilon - for alpha in np.arange(0, self.radius, self.epsilon) - for sgns in it.product((-1, 1), (-1, 1)) - for x, y in [(alpha, beta), (beta, alpha)] - ], color = color) - -class NumberLine(Mobject1D): - def __init__(self, - radius = SPACE_WIDTH, - interval_size = 0.5, tick_size = 0.1, - with_numbers = False, *args, **kwargs): - self.radius = int(radius) + 1 - self.interval_size = interval_size - self.tick_size = tick_size - self.with_numbers = with_numbers - Mobject1D.__init__(self, *args, **kwargs) - - def generate_points(self): - self.add_points([ - (x, 0, 0) - for x in np.arange(-self.radius, self.radius, self.epsilon) - ]) - self.add_points([ - (0, y, 0) - for y in np.arange(-2*self.tick_size, 2*self.tick_size, self.epsilon) - ]) - self.add_points([ - (x, y, 0) - for x in np.arange(-self.radius, self.radius, self.interval_size) - for y in np.arange(-self.tick_size, self.tick_size, self.epsilon) - ]) - if self.with_numbers: - #TODO, test - vertical_displacement = -0.3 - nums = range(-self.radius, self.radius) - nums = map(lambda x : x / self.interval_size, nums) - mobs = tex_mobjects(*[str(num) for num in nums]) - for num, mob in zip(nums, mobs): - mob.center().shift([num, vertical_displacement, 0]) - self.add(*mobs) - -# class ComplexPlane(Grid): -# def __init__(self, *args, **kwargs): -# Grid.__init__(self, *args, **kwargs) -# self.add(Dot()) - - - - - - - - - - - diff --git a/tex_image_utils.py b/tex_image_utils.py deleted file mode 100644 index 5051a6de..00000000 --- a/tex_image_utils.py +++ /dev/null @@ -1,70 +0,0 @@ -import os -from PIL import Image -from constants import PDF_DIR, IMAGE_DIR, WIDTH, HEIGHT, PDF_DENSITY - -def load_pdf_images(filename, regen_if_exists = False): - """ - Converts a pdf, which potentially has multiple slides, into a - directory full of enumerated pngs corresponding with these slides. - Returns a list of PIL Image objects for these images sorted as they - where in the pdf - """ - #TODO, Handle case where there is one page in the pdf! - possible_paths = [ - filename, - os.path.join(PDF_DIR, filename), - os.path.join(PDF_DIR, filename + ".pdf"), - ] - for path in possible_paths: - if os.path.exists(path): - directory, filename = os.path.split(path) - name = filename.split(".")[0] - images_dir = os.path.join(IMAGE_DIR, name) - already_exists = os.path.exists(images_dir) - if not already_exists: - os.mkdir(images_dir) - if not already_exists or regen_if_exists: - commands = [ - "convert", - "-density", - str(PDF_DENSITY), - path, - "-size", - str(WIDTH) + "x" + str(HEIGHT), - os.path.join(images_dir, name + ".png") - ] - os.system(" ".join(commands)) - image_paths = [ - os.path.join(images_dir, name) - for name in os.listdir(images_dir) - if name.endswith(".png") - ] - image_paths.sort(cmp_enumerated_files) - return [Image.open(path).convert('RGB') for path in image_paths] - raise IOError("File not Found") - -def cmp_enumerated_files(name1, name2): - num1, num2 = [ - int(name.split(".")[0].split("-")[-1]) - for name in (name1, name2) - ] - return num1 - num2 - -SYMBOL_IMAGES = load_pdf_images("symbols.pdf", regen_if_exists = False) - -NAME_TO_IMAGE_FILE = dict( - zip([ - "-3", - "-2", - "-1", - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "cdots", - "3Blue1Brown", - ], SYMBOL_IMAGES) -) \ No newline at end of file