mirror of
https://github.com/3b1b/manim.git
synced 2025-07-28 20:43:56 +08:00
Some refactor of NumberPlane. Quite likely breaks some old_projects
This commit is contained in:
@ -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,
|
||||
|
@ -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())
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
Reference in New Issue
Block a user