diff --git a/old_projects/eoc/chapter4.py b/old_projects/eoc/chapter4.py index c7aad5fa..ae4be91e 100644 --- a/old_projects/eoc/chapter4.py +++ b/old_projects/eoc/chapter4.py @@ -1349,7 +1349,7 @@ class IntroduceProductAsArea(ReconfigurableScene): line = NumberLine( x_min = 0, x_max = self.slider_x_max, - space_unit_to_num = float(self.slider_width)/self.slider_x_max, + unit_size = float(self.slider_width)/self.slider_x_max, color = GREY, numbers_with_elongated_ticks = numbers, tick_frequency = 0.25, diff --git a/old_projects/eoc/chapter9.py b/old_projects/eoc/chapter9.py index a7f9050f..0228e83a 100644 --- a/old_projects/eoc/chapter9.py +++ b/old_projects/eoc/chapter9.py @@ -1982,7 +1982,7 @@ class ASecondIntegralSensation(TeacherStudentsScene): continuum = UnitInterval( color = GREY, - space_unit_to_num = 6 + unit_size = 6 ) continuum.next_to(finite_average, RIGHT, 2) line = Line(continuum.get_left(), continuum.get_right()) diff --git a/old_projects/eoc/old_chapter1.py b/old_projects/eoc/old_chapter1.py index 2d6f7b31..2d8db1a9 100644 --- a/old_projects/eoc/old_chapter1.py +++ b/old_projects/eoc/old_chapter1.py @@ -1415,7 +1415,7 @@ class DerivativeAsTangentLine(ZoomedScene): x_axis = NumberLine( x_min = -0.25, x_max = 4, - space_unit_to_num = 2, + unit_size = 2, tick_frequency = 0.25, leftmost_tick = -0.25, numbers_with_elongated_ticks = [0, 1, 2, 3, 4], @@ -1431,7 +1431,7 @@ class DerivativeAsTangentLine(ZoomedScene): y_axis = NumberLine( x_min = -2, x_max = 20, - space_unit_to_num = 0.3, + unit_size = 0.3, tick_frequency = 2.5, leftmost_tick = 0, longer_tick_multiple = -2, diff --git a/old_projects/leibniz.py b/old_projects/leibniz.py index 25253ecf..46f52d1b 100644 --- a/old_projects/leibniz.py +++ b/old_projects/leibniz.py @@ -2217,7 +2217,7 @@ class FactorizationPattern(Scene): line = NumberLine( x_min = 0, x_max = 36, - space_unit_to_num = 0.4, + unit_size = 0.4, numbers_to_show = range(0, 33, 4), numbers_with_elongated_ticks = range(0, 33, 4), ) diff --git a/old_projects/tattoo.py b/old_projects/tattoo.py index c41430ea..6eda1ed7 100644 --- a/old_projects/tattoo.py +++ b/old_projects/tattoo.py @@ -44,7 +44,7 @@ class TrigRepresentationsScene(Scene): def init_axes(self): self.axes = Axes( - space_unit_to_num = self.unit_length, + unit_size = self.unit_length, ) self.axes.highlight(self.axes_color) self.add(self.axes) diff --git a/old_projects/zeta.py b/old_projects/zeta.py index f9b858a8..189b0010 100644 --- a/old_projects/zeta.py +++ b/old_projects/zeta.py @@ -461,7 +461,7 @@ class DefineForRealS(PiCreatureScene): x_max = 3, tick_frequency = 0.25, numbers_with_elongated_ticks = range(4), - space_unit_to_num = 3, + unit_size = 3, ) number_line.add_numbers() number_line.next_to(self.pi_creature, LEFT) @@ -862,7 +862,7 @@ class FromRealToComplex(ComplexTransformationScene): def show_real_to_real(self): zeta = self.get_zeta_definition("2", "\\frac{\\pi^2}{6}") number_line = NumberLine( - space_unit_to_num = 2, + unit_size = 2, tick_frequency = 0.5, numbers_with_elongated_ticks = range(-2, 3) ) diff --git a/topics/complex_numbers.py b/topics/complex_numbers.py index 6357211d..7839da1b 100644 --- a/topics/complex_numbers.py +++ b/topics/complex_numbers.py @@ -13,16 +13,8 @@ from scene import Scene class ComplexTransformationScene(Scene): CONFIG = { - "plane_config" : { - "x_line_frequency" : 1, - "y_line_frequency" : 1, - "secondary_line_ratio" : 1, - }, + "plane_config" : {}, "background_fade_factor" : 0.5, - "x_min" : -int(SPACE_WIDTH), - "x_max" : int(SPACE_WIDTH), - "y_min" : -SPACE_HEIGHT, - "y_max" : SPACE_HEIGHT, "use_multicolored_plane" : False, "vert_start_color" : BLUE, ##TODO "vert_end_color" : BLUE, @@ -34,11 +26,14 @@ class ComplexTransformationScene(Scene): "run_time" : 5, }, "background_label_scale_val" : 0.5, + "include_coordinate_labels" : True, } def setup(self): self.foreground_mobjects = [] self.transformable_mobjects = [] self.add_background_plane() + if self.include_coordinate_labels: + self.add_coordinate_labels() def add_foreground_mobject(self, mobject): self.add_foreground_mobjects(mobject) @@ -62,49 +57,38 @@ class ComplexTransformationScene(Scene): ) def add_background_plane(self): - background = NumberPlane(**self.plane_config).fade( - self.background_fade_factor - ) - real_labels = VGroup(*[ - TexMobject(str(x)).shift( - background.num_pair_to_point((x, 0)) - ) - for x in range(-int(background.x_radius), int(background.x_radius)) - ]) - imag_labels = VGroup(*[ - TexMobject("%di"%y).shift( - background.num_pair_to_point((0, y)) - ) - for y in range(-int(background.y_radius), int(background.y_radius)) - if y != 0 - ]) - for labels in real_labels, imag_labels: - for label in labels: - label.scale_in_place(self.background_label_scale_val) - label.next_to(label.get_center(), DOWN+LEFT, buff = SMALL_BUFF) - label.add_background_rectangle() - background.add(labels) - self.real_labels = real_labels - self.imag_labels = imag_labels + background = ComplexPlane(**self.plane_config) + background.fade(self.background_fade_factor) self.add(background) self.background = background - def add_transformable_plane(self, animate = False): - self.plane_config.update({ - "x_radius" : (self.x_max - self.x_min)/2., - "y_radius" : (self.y_max - self.y_min)/2., - }) - plane = NumberPlane(**self.plane_config) - plane.shift( - (self.x_max+self.x_min)*RIGHT/2., - (self.y_max+self.y_min)*UP/2., - ) - self.paint_plane(plane) - if animate: - self.play(ShowCreation(plane, run_time = 2)) - else: - self.add(plane) - self.plane = plane + def add_coordinate_labels(self): + self.background.add_coordinates() + self.add(self.background) + + def add_transformable_plane(self, **kwargs): + self.plane = self.get_transformable_plane() + self.add(self.plane) + + def get_transformable_plane(self, x_range = None, y_range = None): + """ + x_range and y_range would be tuples (min, max) + """ + plane_config = dict(self.plane_config) + shift_val = ORIGIN + if x_range is not None: + x_min, x_max = x_range + plane_config["x_radius"] = x_max - x_min + shift_val += (x_max+x_min)*RIGHT/2. + if y_range is not None: + y_min, y_max = y_range + plane_config["y_radius"] = y_max - y_min + shift_val += (y_max+y_min)*UP/2. + plane = ComplexPlane(**plane_config) + plane.shift(shift_val) + if self.use_multicolored_plane: + self.paint_plane(plane) + return plane def prepare_for_transformation(self, mob): if hasattr(mob, "prepare_for_nonlinear_transform"): @@ -114,22 +98,20 @@ class ComplexTransformationScene(Scene): #TODO... def paint_plane(self, plane): - if self.use_multicolored_plane: - for lines in plane.main_lines, plane.secondary_lines: - lines.gradient_highlight( - self.vert_start_color, - self.vert_end_color, - self.horiz_start_color, - self.horiz_end_color, - ) - plane.axes.gradient_highlight( + for lines in plane.main_lines, plane.secondary_lines: + lines.gradient_highlight( + self.vert_start_color, + self.vert_end_color, self.horiz_start_color, - self.vert_start_color + self.horiz_end_color, ) + # plane.axes.gradient_highlight( + # self.horiz_start_color, + # self.vert_start_color + # ) def z_to_point(self, z): - z = complex(z) - return self.background.num_pair_to_point((z.real, z.imag)) + return self.background.number_to_point(z) def get_transformer(self, **kwargs): transform_kwargs = dict(self.default_apply_complex_function_kwargs) @@ -145,7 +127,14 @@ class ComplexTransformationScene(Scene): def apply_complex_function(self, func, added_anims = [], **kwargs): transformer, transform_kwargs = self.get_transformer(**kwargs) transformer.generate_target() + #Rescale, apply function, scale back + transformer.target.shift(-self.background.get_center_point()) + transformer.target.scale(1./self.background.unit_size) transformer.target.apply_complex_function(func) + transformer.target.scale(self.background.unit_size) + transformer.target.shift(self.background.get_center_point()) + # + for mob in transformer.target[0].family_members_with_points(): mob.make_smooth() if self.post_transformation_stroke_width is not None: @@ -159,7 +148,8 @@ class ComplexTransformationScene(Scene): transformer, transform_kwargs = self.get_transformer(**kwargs) def homotopy(x, y, z, t): output = complex_homotopy(complex(x, y), t) - return (output.real, output.imag, z) + rescaled_output = self.z_to_point(output) + return (rescaled_output.real, rescaled_output.imag, z) self.play( SmoothedVectorizedHomotopy( @@ -176,24 +166,21 @@ def complex_string(complex_num): class ComplexPlane(NumberPlane): CONFIG = { - "color" : BLUE, - "unit_to_spatial_width" : 1, - "line_frequency" : 1, - "faded_line_frequency" : 0.5, - "number_at_center" : complex(0), - "number_scale_factor" : 0.5, + "color" : BLUE, + "unit_size" : 1, + "line_frequency" : 1, + "faded_line_frequency" : 0.5, + "number_scale_factor" : 0.5, } def __init__(self, **kwargs): digest_config(self, kwargs) kwargs.update({ - "x_unit_to_spatial_width" : self.unit_to_spatial_width, - "y_unit_to_spatial_height" : self.unit_to_spatial_width, - "x_line_frequency" : self.line_frequency, - "x_faded_line_frequency" : self.faded_line_frequency, - "y_line_frequency" : self.line_frequency, - "y_faded_line_frequency" : self.faded_line_frequency, - "num_pair_at_center" : (self.number_at_center.real, - self.number_at_center.imag), + "x_unit_size" : self.unit_size, + "y_unit_size" : self.unit_size, + "x_line_frequency" : self.line_frequency, + "x_faded_line_frequency" : self.faded_line_frequency, + "y_line_frequency" : self.line_frequency, + "y_faded_line_frequency" : self.faded_line_frequency, }) NumberPlane.__init__(self, **kwargs) diff --git a/topics/graph_scene.py b/topics/graph_scene.py index 13a9a2aa..fb808666 100644 --- a/topics/graph_scene.py +++ b/topics/graph_scene.py @@ -50,7 +50,7 @@ class GraphScene(Scene): x_axis = NumberLine( x_min = self.x_min, x_max = self.x_max, - space_unit_to_num = self.space_unit_to_x, + unit_size = self.space_unit_to_x, tick_frequency = self.x_tick_frequency, leftmost_tick = self.x_leftmost_tick, numbers_with_elongated_ticks = self.x_labeled_nums, @@ -81,7 +81,7 @@ class GraphScene(Scene): y_axis = NumberLine( x_min = self.y_min, x_max = self.y_max, - space_unit_to_num = self.space_unit_to_y, + unit_size = self.space_unit_to_y, tick_frequency = self.y_tick_frequency, leftmost_tick = self.y_bottom_tick, numbers_with_elongated_ticks = self.y_labeled_nums, diff --git a/topics/number_line.py b/topics/number_line.py index af852811..2d1646fc 100644 --- a/topics/number_line.py +++ b/topics/number_line.py @@ -11,7 +11,7 @@ class NumberLine(VMobject): "color" : BLUE, "x_min" : -SPACE_WIDTH, "x_max" : SPACE_WIDTH, - "space_unit_to_num" : 1, + "unit_size" : 1, "tick_size" : 0.1, "tick_frequency" : 1, "leftmost_tick" : None, #Defaults to ceil(x_min) @@ -35,7 +35,7 @@ class NumberLine(VMobject): self.add_tick(x, self.tick_size) for x in self.numbers_with_elongated_ticks: self.add_tick(x, self.longer_tick_multiple*self.tick_size) - self.stretch(self.space_unit_to_num, 0) + self.stretch(self.unit_size, 0) self.shift(-self.number_to_point(self.number_at_center)) def add_tick(self, x, size): @@ -108,7 +108,7 @@ class UnitInterval(NumberLine): CONFIG = { "x_min" : 0, "x_max" : 1, - "space_unit_to_num" : 6, + "unit_size" : 6, "tick_frequency" : 0.1, "numbers_with_elongated_ticks" : [0, 1], "number_at_center" : 0.5, @@ -130,20 +130,26 @@ class NumberPlane(VMobject): "secondary_color" : BLUE_E, "axes_color" : WHITE, "secondary_stroke_width" : 1, - "x_radius": SPACE_WIDTH, - "y_radius": SPACE_HEIGHT, - "space_unit_to_x_unit" : 1, - "space_unit_to_y_unit" : 1, + "x_radius": None, + "y_radius": None, + "x_unit_size" : 1, + "y_unit_size" : 1, + "center_point" : ORIGIN, "x_line_frequency" : 1, "y_line_frequency" : 1, "secondary_line_ratio" : 1, "written_coordinate_height" : 0.2, "written_coordinate_nudge" : 0.1*(DOWN+RIGHT), - "coords_at_center" : (0, 0), "propogate_style_to_family" : False, } def generate_points(self): + if self.x_radius is None: + center_to_edge = (SPACE_WIDTH + abs(self.center_point[0])) + self.x_radius = center_to_edge / self.x_unit_size + if self.y_radius is None: + center_to_edge = (SPACE_HEIGHT + abs(self.center_point[1])) + self.y_radius = center_to_edge / self.y_unit_size self.axes = VMobject() self.main_lines = VMobject() self.secondary_lines = VMobject() @@ -176,8 +182,9 @@ class NumberPlane(VMobject): else: self.secondary_lines.add(line1, line2) self.add(self.secondary_lines, self.main_lines, self.axes) - self.stretch(self.space_unit_to_x_unit, 0) - self.stretch(self.space_unit_to_y_unit, 1) + self.stretch(self.x_unit_size, 0) + self.stretch(self.y_unit_size, 1) + self.shift(self.center_point) #Put x_axis before y_axis y_axis, x_axis = self.axes.split() self.axes = VMobject(x_axis, y_axis) @@ -192,26 +199,25 @@ class NumberPlane(VMobject): return self def get_center_point(self): - return self.num_pair_to_point(self.coords_at_center) + return self.coords_to_point(0, 0) def coords_to_point(self, x, y): - x, y = np.array([x, y]) + self.coords_at_center + x, y = np.array([x, y]) result = self.axes.get_center() - result += x*self.get_space_unit_to_x_unit()*RIGHT - result += y*self.get_space_unit_to_y_unit()*UP + result += x*self.get_x_unit_size()*RIGHT + result += y*self.get_y_unit_size()*UP return result def point_to_coords(self, point): - new_point = point-self.axes.get_center() - center_x, center_y = self.coords_at_center - x = center_x + new_point[0]/self.get_space_unit_to_x_unit() - y = center_y + new_point[1]/self.get_space_unit_to_y_unit() + new_point = point - self.axes.get_center() + x = new_point[0]/self.get_x_unit_size() + y = new_point[1]/self.get_y_unit_size() return x, y - def get_space_unit_to_x_unit(self): + def get_x_unit_size(self): return self.axes.get_width() / (2.0*self.x_radius) - def get_space_unit_to_y_unit(self): + def get_y_unit_size(self): return self.axes.get_height() / (2.0*self.y_radius) def get_coordinate_labels(self, x_vals = None, y_vals = None): @@ -225,7 +231,7 @@ class NumberPlane(VMobject): if val == 0: continue num_pair[index] = val - point = self.num_pair_to_point(num_pair) + point = self.coords_to_point(*num_pair) num = TexMobject(str(val)) num.add_background_rectangle() num.scale_to_fit_height(