Some refactor of NumberPlane. Quite likely breaks some old_projects

This commit is contained in:
Grant Sanderson
2017-05-23 13:17:31 -07:00
parent ea3535b0d6
commit c5e18f4eef
9 changed files with 100 additions and 107 deletions

View File

@ -1349,7 +1349,7 @@ class IntroduceProductAsArea(ReconfigurableScene):
line = NumberLine( line = NumberLine(
x_min = 0, x_min = 0,
x_max = self.slider_x_max, 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, color = GREY,
numbers_with_elongated_ticks = numbers, numbers_with_elongated_ticks = numbers,
tick_frequency = 0.25, tick_frequency = 0.25,

View File

@ -1982,7 +1982,7 @@ class ASecondIntegralSensation(TeacherStudentsScene):
continuum = UnitInterval( continuum = UnitInterval(
color = GREY, color = GREY,
space_unit_to_num = 6 unit_size = 6
) )
continuum.next_to(finite_average, RIGHT, 2) continuum.next_to(finite_average, RIGHT, 2)
line = Line(continuum.get_left(), continuum.get_right()) line = Line(continuum.get_left(), continuum.get_right())

View File

@ -1415,7 +1415,7 @@ class DerivativeAsTangentLine(ZoomedScene):
x_axis = NumberLine( x_axis = NumberLine(
x_min = -0.25, x_min = -0.25,
x_max = 4, x_max = 4,
space_unit_to_num = 2, unit_size = 2,
tick_frequency = 0.25, tick_frequency = 0.25,
leftmost_tick = -0.25, leftmost_tick = -0.25,
numbers_with_elongated_ticks = [0, 1, 2, 3, 4], numbers_with_elongated_ticks = [0, 1, 2, 3, 4],
@ -1431,7 +1431,7 @@ class DerivativeAsTangentLine(ZoomedScene):
y_axis = NumberLine( y_axis = NumberLine(
x_min = -2, x_min = -2,
x_max = 20, x_max = 20,
space_unit_to_num = 0.3, unit_size = 0.3,
tick_frequency = 2.5, tick_frequency = 2.5,
leftmost_tick = 0, leftmost_tick = 0,
longer_tick_multiple = -2, longer_tick_multiple = -2,

View File

@ -2217,7 +2217,7 @@ class FactorizationPattern(Scene):
line = NumberLine( line = NumberLine(
x_min = 0, x_min = 0,
x_max = 36, x_max = 36,
space_unit_to_num = 0.4, unit_size = 0.4,
numbers_to_show = range(0, 33, 4), numbers_to_show = range(0, 33, 4),
numbers_with_elongated_ticks = range(0, 33, 4), numbers_with_elongated_ticks = range(0, 33, 4),
) )

View File

@ -44,7 +44,7 @@ class TrigRepresentationsScene(Scene):
def init_axes(self): def init_axes(self):
self.axes = Axes( self.axes = Axes(
space_unit_to_num = self.unit_length, unit_size = self.unit_length,
) )
self.axes.highlight(self.axes_color) self.axes.highlight(self.axes_color)
self.add(self.axes) self.add(self.axes)

View File

@ -461,7 +461,7 @@ class DefineForRealS(PiCreatureScene):
x_max = 3, x_max = 3,
tick_frequency = 0.25, tick_frequency = 0.25,
numbers_with_elongated_ticks = range(4), numbers_with_elongated_ticks = range(4),
space_unit_to_num = 3, unit_size = 3,
) )
number_line.add_numbers() number_line.add_numbers()
number_line.next_to(self.pi_creature, LEFT) number_line.next_to(self.pi_creature, LEFT)
@ -862,7 +862,7 @@ class FromRealToComplex(ComplexTransformationScene):
def show_real_to_real(self): def show_real_to_real(self):
zeta = self.get_zeta_definition("2", "\\frac{\\pi^2}{6}") zeta = self.get_zeta_definition("2", "\\frac{\\pi^2}{6}")
number_line = NumberLine( number_line = NumberLine(
space_unit_to_num = 2, unit_size = 2,
tick_frequency = 0.5, tick_frequency = 0.5,
numbers_with_elongated_ticks = range(-2, 3) numbers_with_elongated_ticks = range(-2, 3)
) )

View File

@ -13,16 +13,8 @@ from scene import Scene
class ComplexTransformationScene(Scene): class ComplexTransformationScene(Scene):
CONFIG = { CONFIG = {
"plane_config" : { "plane_config" : {},
"x_line_frequency" : 1,
"y_line_frequency" : 1,
"secondary_line_ratio" : 1,
},
"background_fade_factor" : 0.5, "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, "use_multicolored_plane" : False,
"vert_start_color" : BLUE, ##TODO "vert_start_color" : BLUE, ##TODO
"vert_end_color" : BLUE, "vert_end_color" : BLUE,
@ -34,11 +26,14 @@ class ComplexTransformationScene(Scene):
"run_time" : 5, "run_time" : 5,
}, },
"background_label_scale_val" : 0.5, "background_label_scale_val" : 0.5,
"include_coordinate_labels" : True,
} }
def setup(self): def setup(self):
self.foreground_mobjects = [] self.foreground_mobjects = []
self.transformable_mobjects = [] self.transformable_mobjects = []
self.add_background_plane() self.add_background_plane()
if self.include_coordinate_labels:
self.add_coordinate_labels()
def add_foreground_mobject(self, mobject): def add_foreground_mobject(self, mobject):
self.add_foreground_mobjects(mobject) self.add_foreground_mobjects(mobject)
@ -62,49 +57,38 @@ class ComplexTransformationScene(Scene):
) )
def add_background_plane(self): def add_background_plane(self):
background = NumberPlane(**self.plane_config).fade( background = ComplexPlane(**self.plane_config)
self.background_fade_factor background.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
self.add(background) self.add(background)
self.background = background self.background = background
def add_transformable_plane(self, animate = False): def add_coordinate_labels(self):
self.plane_config.update({ self.background.add_coordinates()
"x_radius" : (self.x_max - self.x_min)/2., self.add(self.background)
"y_radius" : (self.y_max - self.y_min)/2.,
}) def add_transformable_plane(self, **kwargs):
plane = NumberPlane(**self.plane_config) self.plane = self.get_transformable_plane()
plane.shift( self.add(self.plane)
(self.x_max+self.x_min)*RIGHT/2.,
(self.y_max+self.y_min)*UP/2., 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) self.paint_plane(plane)
if animate: return plane
self.play(ShowCreation(plane, run_time = 2))
else:
self.add(plane)
self.plane = plane
def prepare_for_transformation(self, mob): def prepare_for_transformation(self, mob):
if hasattr(mob, "prepare_for_nonlinear_transform"): if hasattr(mob, "prepare_for_nonlinear_transform"):
@ -114,7 +98,6 @@ class ComplexTransformationScene(Scene):
#TODO... #TODO...
def paint_plane(self, plane): def paint_plane(self, plane):
if self.use_multicolored_plane:
for lines in plane.main_lines, plane.secondary_lines: for lines in plane.main_lines, plane.secondary_lines:
lines.gradient_highlight( lines.gradient_highlight(
self.vert_start_color, self.vert_start_color,
@ -122,14 +105,13 @@ class ComplexTransformationScene(Scene):
self.horiz_start_color, self.horiz_start_color,
self.horiz_end_color, self.horiz_end_color,
) )
plane.axes.gradient_highlight( # plane.axes.gradient_highlight(
self.horiz_start_color, # self.horiz_start_color,
self.vert_start_color # self.vert_start_color
) # )
def z_to_point(self, z): def z_to_point(self, z):
z = complex(z) return self.background.number_to_point(z)
return self.background.num_pair_to_point((z.real, z.imag))
def get_transformer(self, **kwargs): def get_transformer(self, **kwargs):
transform_kwargs = dict(self.default_apply_complex_function_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): def apply_complex_function(self, func, added_anims = [], **kwargs):
transformer, transform_kwargs = self.get_transformer(**kwargs) transformer, transform_kwargs = self.get_transformer(**kwargs)
transformer.generate_target() 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.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(): for mob in transformer.target[0].family_members_with_points():
mob.make_smooth() mob.make_smooth()
if self.post_transformation_stroke_width is not None: if self.post_transformation_stroke_width is not None:
@ -159,7 +148,8 @@ class ComplexTransformationScene(Scene):
transformer, transform_kwargs = self.get_transformer(**kwargs) transformer, transform_kwargs = self.get_transformer(**kwargs)
def homotopy(x, y, z, t): def homotopy(x, y, z, t):
output = complex_homotopy(complex(x, y), 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( self.play(
SmoothedVectorizedHomotopy( SmoothedVectorizedHomotopy(
@ -177,23 +167,20 @@ def complex_string(complex_num):
class ComplexPlane(NumberPlane): class ComplexPlane(NumberPlane):
CONFIG = { CONFIG = {
"color" : BLUE, "color" : BLUE,
"unit_to_spatial_width" : 1, "unit_size" : 1,
"line_frequency" : 1, "line_frequency" : 1,
"faded_line_frequency" : 0.5, "faded_line_frequency" : 0.5,
"number_at_center" : complex(0),
"number_scale_factor" : 0.5, "number_scale_factor" : 0.5,
} }
def __init__(self, **kwargs): def __init__(self, **kwargs):
digest_config(self, kwargs) digest_config(self, kwargs)
kwargs.update({ kwargs.update({
"x_unit_to_spatial_width" : self.unit_to_spatial_width, "x_unit_size" : self.unit_size,
"y_unit_to_spatial_height" : self.unit_to_spatial_width, "y_unit_size" : self.unit_size,
"x_line_frequency" : self.line_frequency, "x_line_frequency" : self.line_frequency,
"x_faded_line_frequency" : self.faded_line_frequency, "x_faded_line_frequency" : self.faded_line_frequency,
"y_line_frequency" : self.line_frequency, "y_line_frequency" : self.line_frequency,
"y_faded_line_frequency" : self.faded_line_frequency, "y_faded_line_frequency" : self.faded_line_frequency,
"num_pair_at_center" : (self.number_at_center.real,
self.number_at_center.imag),
}) })
NumberPlane.__init__(self, **kwargs) NumberPlane.__init__(self, **kwargs)

View File

@ -50,7 +50,7 @@ class GraphScene(Scene):
x_axis = NumberLine( x_axis = NumberLine(
x_min = self.x_min, x_min = self.x_min,
x_max = self.x_max, 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, tick_frequency = self.x_tick_frequency,
leftmost_tick = self.x_leftmost_tick, leftmost_tick = self.x_leftmost_tick,
numbers_with_elongated_ticks = self.x_labeled_nums, numbers_with_elongated_ticks = self.x_labeled_nums,
@ -81,7 +81,7 @@ class GraphScene(Scene):
y_axis = NumberLine( y_axis = NumberLine(
x_min = self.y_min, x_min = self.y_min,
x_max = self.y_max, 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, tick_frequency = self.y_tick_frequency,
leftmost_tick = self.y_bottom_tick, leftmost_tick = self.y_bottom_tick,
numbers_with_elongated_ticks = self.y_labeled_nums, numbers_with_elongated_ticks = self.y_labeled_nums,

View File

@ -11,7 +11,7 @@ class NumberLine(VMobject):
"color" : BLUE, "color" : BLUE,
"x_min" : -SPACE_WIDTH, "x_min" : -SPACE_WIDTH,
"x_max" : SPACE_WIDTH, "x_max" : SPACE_WIDTH,
"space_unit_to_num" : 1, "unit_size" : 1,
"tick_size" : 0.1, "tick_size" : 0.1,
"tick_frequency" : 1, "tick_frequency" : 1,
"leftmost_tick" : None, #Defaults to ceil(x_min) "leftmost_tick" : None, #Defaults to ceil(x_min)
@ -35,7 +35,7 @@ class NumberLine(VMobject):
self.add_tick(x, self.tick_size) self.add_tick(x, self.tick_size)
for x in self.numbers_with_elongated_ticks: for x in self.numbers_with_elongated_ticks:
self.add_tick(x, self.longer_tick_multiple*self.tick_size) 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)) self.shift(-self.number_to_point(self.number_at_center))
def add_tick(self, x, size): def add_tick(self, x, size):
@ -108,7 +108,7 @@ class UnitInterval(NumberLine):
CONFIG = { CONFIG = {
"x_min" : 0, "x_min" : 0,
"x_max" : 1, "x_max" : 1,
"space_unit_to_num" : 6, "unit_size" : 6,
"tick_frequency" : 0.1, "tick_frequency" : 0.1,
"numbers_with_elongated_ticks" : [0, 1], "numbers_with_elongated_ticks" : [0, 1],
"number_at_center" : 0.5, "number_at_center" : 0.5,
@ -130,20 +130,26 @@ class NumberPlane(VMobject):
"secondary_color" : BLUE_E, "secondary_color" : BLUE_E,
"axes_color" : WHITE, "axes_color" : WHITE,
"secondary_stroke_width" : 1, "secondary_stroke_width" : 1,
"x_radius": SPACE_WIDTH, "x_radius": None,
"y_radius": SPACE_HEIGHT, "y_radius": None,
"space_unit_to_x_unit" : 1, "x_unit_size" : 1,
"space_unit_to_y_unit" : 1, "y_unit_size" : 1,
"center_point" : ORIGIN,
"x_line_frequency" : 1, "x_line_frequency" : 1,
"y_line_frequency" : 1, "y_line_frequency" : 1,
"secondary_line_ratio" : 1, "secondary_line_ratio" : 1,
"written_coordinate_height" : 0.2, "written_coordinate_height" : 0.2,
"written_coordinate_nudge" : 0.1*(DOWN+RIGHT), "written_coordinate_nudge" : 0.1*(DOWN+RIGHT),
"coords_at_center" : (0, 0),
"propogate_style_to_family" : False, "propogate_style_to_family" : False,
} }
def generate_points(self): 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.axes = VMobject()
self.main_lines = VMobject() self.main_lines = VMobject()
self.secondary_lines = VMobject() self.secondary_lines = VMobject()
@ -176,8 +182,9 @@ class NumberPlane(VMobject):
else: else:
self.secondary_lines.add(line1, line2) self.secondary_lines.add(line1, line2)
self.add(self.secondary_lines, self.main_lines, self.axes) self.add(self.secondary_lines, self.main_lines, self.axes)
self.stretch(self.space_unit_to_x_unit, 0) self.stretch(self.x_unit_size, 0)
self.stretch(self.space_unit_to_y_unit, 1) self.stretch(self.y_unit_size, 1)
self.shift(self.center_point)
#Put x_axis before y_axis #Put x_axis before y_axis
y_axis, x_axis = self.axes.split() y_axis, x_axis = self.axes.split()
self.axes = VMobject(x_axis, y_axis) self.axes = VMobject(x_axis, y_axis)
@ -192,26 +199,25 @@ class NumberPlane(VMobject):
return self return self
def get_center_point(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): 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 = self.axes.get_center()
result += x*self.get_space_unit_to_x_unit()*RIGHT result += x*self.get_x_unit_size()*RIGHT
result += y*self.get_space_unit_to_y_unit()*UP result += y*self.get_y_unit_size()*UP
return result return result
def point_to_coords(self, point): def point_to_coords(self, point):
new_point = point-self.axes.get_center() new_point = point - self.axes.get_center()
center_x, center_y = self.coords_at_center x = new_point[0]/self.get_x_unit_size()
x = center_x + new_point[0]/self.get_space_unit_to_x_unit() y = new_point[1]/self.get_y_unit_size()
y = center_y + new_point[1]/self.get_space_unit_to_y_unit()
return x, y 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) 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) return self.axes.get_height() / (2.0*self.y_radius)
def get_coordinate_labels(self, x_vals = None, y_vals = None): def get_coordinate_labels(self, x_vals = None, y_vals = None):
@ -225,7 +231,7 @@ class NumberPlane(VMobject):
if val == 0: if val == 0:
continue continue
num_pair[index] = val num_pair[index] = val
point = self.num_pair_to_point(num_pair) point = self.coords_to_point(*num_pair)
num = TexMobject(str(val)) num = TexMobject(str(val))
num.add_background_rectangle() num.add_background_rectangle()
num.scale_to_fit_height( num.scale_to_fit_height(