mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Merge branch 'master' into lighthouse
This commit is contained in:
commit
6eee427c5e
4 changed files with 87 additions and 45 deletions
|
@ -2455,18 +2455,57 @@ class WhiteComplexExponentialExpression(DrawFrequencyPlot):
|
||||||
self.generate_center_of_mass_dot_update_anim()
|
self.generate_center_of_mass_dot_update_anim()
|
||||||
|
|
||||||
self.add(graph, pol_graph, wps_label)
|
self.add(graph, pol_graph, wps_label)
|
||||||
|
self.set_variables_as_attrs(pol_graph, wps_label)
|
||||||
|
self.time_axes_group = VGroup(self.time_axes, graph)
|
||||||
|
|
||||||
def show_winding_with_both_coordinates(self):
|
def show_winding_with_both_coordinates(self):
|
||||||
#TODO, tie dashed lines to dot
|
com_dot = self.center_of_mass_dot
|
||||||
|
plane = self.circle_plane
|
||||||
|
v_line = Line(ORIGIN, UP)
|
||||||
|
h_line = Line(ORIGIN, RIGHT)
|
||||||
|
lines = VGroup(v_line, h_line)
|
||||||
|
lines.highlight(PINK)
|
||||||
|
def lines_update(lines):
|
||||||
|
point = com_dot.get_center()
|
||||||
|
x, y = plane.point_to_coords(point)
|
||||||
|
h_line.put_start_and_end_on(
|
||||||
|
plane.coords_to_point(0, y), point
|
||||||
|
)
|
||||||
|
v_line.put_start_and_end_on(
|
||||||
|
plane.coords_to_point(x, 0), point
|
||||||
|
)
|
||||||
|
lines_update_anim = UpdateFromFunc(lines, lines_update)
|
||||||
|
lines_update_anim.update(0)
|
||||||
|
self.add(lines)
|
||||||
|
|
||||||
self.change_frequency(
|
self.change_frequency(
|
||||||
2.0, run_time = 15,
|
2.04,
|
||||||
|
added_anims = [
|
||||||
|
lines_update_anim,
|
||||||
|
self.center_of_mass_dot_anim,
|
||||||
|
],
|
||||||
|
run_time = 15,
|
||||||
rate_func = bezier([0, 0, 1, 1])
|
rate_func = bezier([0, 0, 1, 1])
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
|
self.dot_component_anim = lines_update_anim
|
||||||
|
|
||||||
def show_plane_as_complex_plane(self):
|
def show_plane_as_complex_plane(self):
|
||||||
pass
|
to_fade = VGroup(
|
||||||
|
self.time_axes_group, self.pol_graph, self.wps_label
|
||||||
|
)
|
||||||
|
plane = self.circle_plane
|
||||||
|
complex_plane_title = TextMobject("Complex plane")
|
||||||
|
complex_plane_title.add_background_rectangle()
|
||||||
|
complex_plane_title.to_edge(UP)
|
||||||
|
coordinate_labels = plane.get_coordinate_labels()
|
||||||
|
|
||||||
|
self.play(FadeOut(to_fade))
|
||||||
|
self.play(Write(complex_plane_title))
|
||||||
|
self.play(Write(coordinate_labels))
|
||||||
|
self.wait()
|
||||||
|
|
||||||
|
|
||||||
def show_eulers_formula(self):
|
def show_eulers_formula(self):
|
||||||
pass
|
pass
|
||||||
|
|
33
helpers.py
33
helpers.py
|
@ -252,14 +252,14 @@ def get_all_descendent_classes(Class):
|
||||||
result.append(Child)
|
result.append(Child)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def filtered_locals(local_args):
|
def filtered_locals(caller_locals):
|
||||||
result = local_args.copy()
|
result = caller_locals.copy()
|
||||||
ignored_local_args = ["self", "kwargs"]
|
ignored_local_args = ["self", "kwargs"]
|
||||||
for arg in ignored_local_args:
|
for arg in ignored_local_args:
|
||||||
result.pop(arg, local_args)
|
result.pop(arg, caller_locals)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def digest_config(obj, kwargs, local_args = {}):
|
def digest_config(obj, kwargs, caller_locals = {}):
|
||||||
"""
|
"""
|
||||||
Sets init args and CONFIG values as local variables
|
Sets init args and CONFIG values as local variables
|
||||||
|
|
||||||
|
@ -268,19 +268,25 @@ def digest_config(obj, kwargs, local_args = {}):
|
||||||
be easily passed into instantiation, and is attached
|
be easily passed into instantiation, and is attached
|
||||||
as an attribute of the object.
|
as an attribute of the object.
|
||||||
"""
|
"""
|
||||||
### Assemble list of CONFIGs from all super classes
|
|
||||||
|
# Assemble list of CONFIGs from all super classes
|
||||||
classes_in_hierarchy = [obj.__class__]
|
classes_in_hierarchy = [obj.__class__]
|
||||||
configs = []
|
static_configs = []
|
||||||
while len(classes_in_hierarchy) > 0:
|
while len(classes_in_hierarchy) > 0:
|
||||||
Class = classes_in_hierarchy.pop()
|
Class = classes_in_hierarchy.pop()
|
||||||
classes_in_hierarchy += Class.__bases__
|
classes_in_hierarchy += Class.__bases__
|
||||||
if hasattr(Class, "CONFIG"):
|
if hasattr(Class, "CONFIG"):
|
||||||
configs.append(Class.CONFIG)
|
static_configs.append(Class.CONFIG)
|
||||||
|
|
||||||
#Order matters a lot here, first dicts have higher priority
|
#Order matters a lot here, first dicts have higher priority
|
||||||
all_dicts = [kwargs, filtered_locals(local_args), obj.__dict__]
|
caller_locals = filtered_locals(caller_locals)
|
||||||
all_dicts += configs
|
all_dicts = [kwargs, caller_locals, obj.__dict__]
|
||||||
|
all_dicts += static_configs
|
||||||
|
all_new_dicts = [kwargs, caller_locals] + static_configs
|
||||||
obj.__dict__ = merge_config(all_dicts)
|
obj.__dict__ = merge_config(all_dicts)
|
||||||
|
#Keep track of the configuration of objects upon
|
||||||
|
#instantiation
|
||||||
|
obj.initial_config = merge_config(all_new_dicts)
|
||||||
|
|
||||||
def merge_config(all_dicts):
|
def merge_config(all_dicts):
|
||||||
all_config = reduce(op.add, [d.items() for d in all_dicts])
|
all_config = reduce(op.add, [d.items() for d in all_dicts])
|
||||||
|
@ -295,6 +301,15 @@ def merge_config(all_dicts):
|
||||||
config[key] = merge_config([config[key], value])
|
config[key] = merge_config([config[key], value])
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
def soft_dict_update(d1, d2):
|
||||||
|
"""
|
||||||
|
Adds key values pairs of d2 to d1 only when d1 doesn't
|
||||||
|
already have that key
|
||||||
|
"""
|
||||||
|
for key, value in d2.items():
|
||||||
|
if key not in d1:
|
||||||
|
d1[key] = value
|
||||||
|
|
||||||
def digest_locals(obj, keys = None):
|
def digest_locals(obj, keys = None):
|
||||||
caller_locals = filtered_locals(
|
caller_locals = filtered_locals(
|
||||||
inspect.currentframe().f_back.f_locals
|
inspect.currentframe().f_back.f_locals
|
||||||
|
|
|
@ -85,15 +85,17 @@ class VMobject(Mobject):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def match_style(self, vmobject):
|
def match_style(self, vmobject):
|
||||||
#TODO: Should this be smart about matching the
|
|
||||||
#style of the family members, if they happen to
|
|
||||||
#be different?
|
|
||||||
self.set_style_data(
|
self.set_style_data(
|
||||||
stroke_color = vmobject.get_stroke_color(),
|
stroke_color = vmobject.get_stroke_color(),
|
||||||
stroke_width = vmobject.get_stroke_width(),
|
stroke_width = vmobject.get_stroke_width(),
|
||||||
fill_color = vmobject.get_fill_color(),
|
fill_color = vmobject.get_fill_color(),
|
||||||
fill_opacity = vmobject.get_fill_opacity(),
|
fill_opacity = vmobject.get_fill_opacity(),
|
||||||
|
family = False
|
||||||
)
|
)
|
||||||
|
#TODO: This behaviro may not be optimal when submobject
|
||||||
|
#lists dont' have the same length
|
||||||
|
for sm1, sm2 in zip(self.submobjects, vmobject.submobjects):
|
||||||
|
sm1.match_style(sm2)
|
||||||
return
|
return
|
||||||
|
|
||||||
def fade(self, darkness = 0.5):
|
def fade(self, darkness = 0.5):
|
||||||
|
|
|
@ -11,7 +11,7 @@ class DecimalNumber(VMobject):
|
||||||
"num_decimal_points" : 2,
|
"num_decimal_points" : 2,
|
||||||
"digit_to_digit_buff" : 0.05,
|
"digit_to_digit_buff" : 0.05,
|
||||||
"show_ellipsis" : False,
|
"show_ellipsis" : False,
|
||||||
"unit" : None
|
"unit" : None,
|
||||||
}
|
}
|
||||||
def __init__(self, number, **kwargs):
|
def __init__(self, number, **kwargs):
|
||||||
digest_config(self, kwargs, locals())
|
digest_config(self, kwargs, locals())
|
||||||
|
@ -27,7 +27,9 @@ class DecimalNumber(VMobject):
|
||||||
if self.show_ellipsis:
|
if self.show_ellipsis:
|
||||||
self.add(TexMobject("\\dots"))
|
self.add(TexMobject("\\dots"))
|
||||||
|
|
||||||
|
if self.unit is not None:
|
||||||
|
self.add(TexMobject(self.unit))
|
||||||
|
|
||||||
self.arrange_submobjects(
|
self.arrange_submobjects(
|
||||||
buff = self.digit_to_digit_buff,
|
buff = self.digit_to_digit_buff,
|
||||||
aligned_edge = DOWN
|
aligned_edge = DOWN
|
||||||
|
@ -39,20 +41,8 @@ class DecimalNumber(VMobject):
|
||||||
self.submobjects[1], LEFT,
|
self.submobjects[1], LEFT,
|
||||||
buff = self.digit_to_digit_buff
|
buff = self.digit_to_digit_buff
|
||||||
)
|
)
|
||||||
|
if self.unit == "\\circ":
|
||||||
|
self[-1].align_to(self, UP)
|
||||||
if self.unit != None:
|
|
||||||
unit_sign = TexMobject(self.unit)
|
|
||||||
unit_sign.next_to(self.submobjects[-1],RIGHT,
|
|
||||||
buff = self.digit_to_digit_buff)
|
|
||||||
|
|
||||||
if self.unit == "^\\circ":
|
|
||||||
unit_sign.align_to(self,UP)
|
|
||||||
else:
|
|
||||||
unit_sign.align_to(self,DOWN)
|
|
||||||
self.add(unit_sign)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Integer(VGroup):
|
class Integer(VGroup):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
|
@ -72,20 +62,18 @@ class ChangingDecimal(Animation):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"num_decimal_points" : None,
|
"num_decimal_points" : None,
|
||||||
"show_ellipsis" : None,
|
"show_ellipsis" : None,
|
||||||
"spare_parts" : 2,
|
|
||||||
"position_update_func" : None,
|
"position_update_func" : None,
|
||||||
"tracked_mobject" : None
|
"tracked_mobject" : None
|
||||||
}
|
}
|
||||||
def __init__(self, decimal_number_mobject, number_update_func, **kwargs):
|
def __init__(self, decimal_number_mobject, number_update_func, **kwargs):
|
||||||
digest_config(self, kwargs, locals())
|
digest_config(self, kwargs, locals())
|
||||||
if self.num_decimal_points is None:
|
self.decimal_number_config = dict(
|
||||||
self.num_decimal_points = decimal_number_mobject.num_decimal_points
|
decimal_number_mobject.initial_config
|
||||||
if self.show_ellipsis is None:
|
|
||||||
self.show_ellipsis = decimal_number_mobject.show_ellipsis
|
|
||||||
decimal_number_mobject.add(*[
|
|
||||||
VectorizedPoint(decimal_number_mobject.get_corner(DOWN+LEFT))
|
|
||||||
for x in range(self.spare_parts)]
|
|
||||||
)
|
)
|
||||||
|
for attr in "num_decimal_points", "show_ellipsis":
|
||||||
|
value = getattr(self, attr)
|
||||||
|
if value is not None:
|
||||||
|
self.decimal_number_config[attr] = value
|
||||||
if self.tracked_mobject:
|
if self.tracked_mobject:
|
||||||
dmc = decimal_number_mobject.get_center()
|
dmc = decimal_number_mobject.get_center()
|
||||||
tmc = self.tracked_mobject.get_center()
|
tmc = self.tracked_mobject.get_center()
|
||||||
|
@ -100,13 +88,11 @@ class ChangingDecimal(Animation):
|
||||||
decimal = self.decimal_number_mobject
|
decimal = self.decimal_number_mobject
|
||||||
new_number = self.number_update_func(alpha)
|
new_number = self.number_update_func(alpha)
|
||||||
new_decimal = DecimalNumber(
|
new_decimal = DecimalNumber(
|
||||||
new_number,
|
new_number, **self.decimal_number_config
|
||||||
num_decimal_points = self.num_decimal_points,
|
|
||||||
show_ellipsis = self.show_ellipsis,
|
|
||||||
unit = self.decimal_number_mobject.unit
|
|
||||||
)
|
)
|
||||||
new_decimal.replace(decimal, dim_to_match = 1)
|
new_decimal.match_height(decimal)
|
||||||
new_decimal.highlight(decimal.get_color())
|
new_decimal.move_to(decimal)
|
||||||
|
new_decimal.match_style(decimal)
|
||||||
|
|
||||||
decimal.submobjects = new_decimal.submobjects
|
decimal.submobjects = new_decimal.submobjects
|
||||||
decimal.number = new_number
|
decimal.number = new_number
|
||||||
|
|
Loading…
Add table
Reference in a new issue